package interceptor import ( "net/http" "net/http/httptest" "os" "testing" "time" "bindbox-game/internal/pkg/core" "bindbox-game/internal/pkg/jwtoken" "bindbox-game/internal/pkg/logger" "bindbox-game/internal/proposal" "bindbox-game/internal/repository/mysql" "bindbox-game/internal/repository/mysql/model" ) func setupDB(t *testing.T) mysql.Repo { repo, err := mysql.NewSQLiteRepoForTest() if err != nil { t.Fatal(err) } if err := repo.GetDbR().AutoMigrate(&model.Admin{}, &model.RoleUsers{}, &model.RoleActions{}, &model.MenuActions{}); err != nil { t.Fatal(err) } return repo } func newLogger(t *testing.T) logger.CustomLogger { l, err := logger.NewCustomLogger(nil, logger.WithOutputInConsole()) if err != nil { t.Fatal(err) } return l } func signToken(secret string, info proposal.SessionUserInfo) string { token, _ := jwtoken.New(secret).Sign(info, time.Hour) return token } func TestRequireAdminRole_NoToken(t *testing.T) { repo := setupDB(t) l := newLogger(t) intc := New(l, repo) m, err := core.New(l) if err != nil { t.Fatal(err) } g := m.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) g.GET("/ping", intc.RequireAdminRole(), func(ctx core.Context) { ctx.Payload(map[string]string{"message": "ok"}) }) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/api/admin/ping", nil) m.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expect 401 got %d", w.Code) } } func TestRequireAdminRole_NoRole(t *testing.T) { repo := setupDB(t) l := newLogger(t) intc := New(l, repo) secret := "testsecret" os.Setenv("ADMIN_JWT_SECRET", secret) info := proposal.SessionUserInfo{Id: 1, UserName: "u", IsSuper: 0} token := signToken(secret, info) h := token if err := repo.GetDbR().Create(&model.Admin{ID: 1, Username: "u", Nickname: "n", Avatar: "a", Mobile: "m", Password: "p", IsSuper: 0, LoginStatus: 1, LastLoginTime: time.Now(), LastLoginIP: "0.0.0.0", LastLoginHash: h, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } m, err := core.New(l) if err != nil { t.Fatal(err) } g := m.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) g.GET("/ping", intc.RequireAdminRole(), func(ctx core.Context) { ctx.Payload(map[string]string{"message": "ok"}) }) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/api/admin/ping", nil) req.Header.Set("Authorization", token) m.ServeHTTP(w, req) if w.Code != http.StatusForbidden { t.Fatalf("expect 403 got %d", w.Code) } } func TestRequireAdminAction_AllowedByRole(t *testing.T) { repo := setupDB(t) l := newLogger(t) intc := New(l, repo) secret := "testsecret" os.Setenv("ADMIN_JWT_SECRET", secret) info := proposal.SessionUserInfo{Id: 2, UserName: "u2", IsSuper: 0} token := signToken(secret, info) h := token if err := repo.GetDbR().Create(&model.Admin{ID: 2, Username: "u2", Nickname: "n", Avatar: "a", Mobile: "m", Password: "p", IsSuper: 0, LoginStatus: 1, LastLoginTime: time.Now(), LastLoginIP: "0.0.0.0", LastLoginHash: h, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } if err := repo.GetDbR().Create(&model.RoleUsers{RoleID: 10, AdminID: 2, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } if err := repo.GetDbR().Create(&model.MenuActions{ID: 100, MenuID: 1, ActionMark: "guild:create", ActionName: "create", Status: true, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } if err := repo.GetDbR().Create(&model.RoleActions{RoleID: 10, ActionID: 100, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } m, err := core.New(l) if err != nil { t.Fatal(err) } g := m.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) g.POST("/guilds", intc.RequireAdminRole(), intc.RequireAdminAction("guild:create"), func(ctx core.Context) { ctx.Payload(map[string]string{"message": "ok"}) }) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/admin/guilds", nil) req.Header.Set("Authorization", token) m.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("expect 200 got %d", w.Code) } } func TestRequireAdminAction_Forbidden(t *testing.T) { repo := setupDB(t) l := newLogger(t) intc := New(l, repo) secret := "testsecret" os.Setenv("ADMIN_JWT_SECRET", secret) info := proposal.SessionUserInfo{Id: 3, UserName: "u3", IsSuper: 0} token := signToken(secret, info) h := token if err := repo.GetDbR().Create(&model.Admin{ID: 3, Username: "u3", Nickname: "n", Avatar: "a", Mobile: "m", Password: "p", IsSuper: 0, LoginStatus: 1, LastLoginTime: time.Now(), LastLoginIP: "0.0.0.0", LastLoginHash: h, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } if err := repo.GetDbR().Create(&model.RoleUsers{RoleID: 11, AdminID: 3, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } if err := repo.GetDbR().Create(&model.MenuActions{ID: 101, MenuID: 1, ActionMark: "guild:delete", ActionName: "delete", Status: true, CreatedUser: "t", UpdatedUser: "t"}).Error; err != nil { t.Fatal(err) } m, err := core.New(l) if err != nil { t.Fatal(err) } g := m.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) g.DELETE("/guilds/1", intc.RequireAdminRole(), intc.RequireAdminAction("guild:delete"), func(ctx core.Context) { ctx.Payload(map[string]string{"message": "ok"}) }) w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", "/api/admin/guilds/1", nil) req.Header.Set("Authorization", token) m.ServeHTTP(w, req) if w.Code != http.StatusForbidden { t.Fatalf("expect 403 got %d", w.Code) } }