package cmd import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gcfg" "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/genv" adminctl "service.xpcool.com/internal/controller/admin" housectl "service.xpcool.com/internal/controller/house" openctl "service.xpcool.com/internal/controller/open" userctl "service.xpcool.com/internal/controller/user" "service.xpcool.com/internal/library/jwt" "service.xpcool.com/internal/middleware" admin "service.xpcool.com/internal/service/admin/admin/admin" adminauth "service.xpcool.com/internal/service/admin/admin/login" log "service.xpcool.com/internal/service/admin/base/log" adminaudit "service.xpcool.com/internal/service/admin/system/log" adminloginlog "service.xpcool.com/internal/service/admin/system/login_log" adminmenu "service.xpcool.com/internal/service/admin/system/menu" menu_manage "service.xpcool.com/internal/service/admin/system/menu_manage" role "service.xpcool.com/internal/service/admin/system/role" userauth "service.xpcool.com/internal/service/user/auth" housecommunity "service.xpcool.com/internal/service/house/community" housedashboard "service.xpcool.com/internal/service/house/dashboard" houselisting "service.xpcool.com/internal/service/house/listing" ) // injectEnv 手动把关键环境变量写入配置系统。 // 注意:gf v2.10.2 起配置不再自动替换 ${ENV} 占位符,需在此显式注入, // 否则 config.dev.yaml 中的 ${DB_DSN}/${JWT_SECRET} 会原样传给数据库与 JWT。 func injectEnv(ctx context.Context) { adapter, ok := g.Cfg().GetAdapter().(*gcfg.AdapterFile) if !ok { return } if v := genv.Get("DB_DSN"); !v.IsEmpty() { _ = adapter.Set("database.default.link", v.String()) } if v := genv.Get("JWT_SECRET"); !v.IsEmpty() { _ = adapter.Set("jwt.secret", v.String()) } } var ( Main = gcmd.Command{ Name: "main", Usage: "main", Brief: "start http server", Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { injectEnv(ctx) s := g.Server() tokens := jwt.New(ctx) userauth.RegisterUserAuth(userauth.NewUserAuth(tokens, nil, nil)) adminauth.RegisterAdminAuth(adminauth.NewAdminAuth(tokens)) adminmenu.RegisterAdminMenu(adminmenu.NewAdminMenu()) admin.RegisterAdminManage(admin.NewAdminManage()) role.RegisterRoleManage(role.NewRoleManage()) menu_manage.RegisterMenuManage(menu_manage.NewMenuManage()) log.RegisterLogManage(log.NewLogManage()) adminaudit.RegisterAdminAudit(adminaudit.NewAdminAudit()) adminloginlog.RegisterAdminLoginLog(adminloginlog.NewAdminLoginLog()) housecommunity.RegisterCommunity(housecommunity.NewCommunity()) houselisting.RegisterListing(houselisting.NewListing()) housedashboard.RegisterDashboard(housedashboard.NewDashboard()) s.Group("/api/service/open", func(group *ghttp.RouterGroup) { group.Middleware(middleware.Recover, middleware.CORS, ghttp.MiddlewareHandlerResponse) group.Bind(openctl.New()) // Open tools API for frontends, no auth required. }) s.Group("/api/service/user", func(group *ghttp.RouterGroup) { group.Middleware(middleware.Recover, middleware.CORS, ghttp.MiddlewareHandlerResponse) group.Bind(userctl.New()) // Login and refresh routes are public. group.Group("/", func(protected *ghttp.RouterGroup) { protected.Middleware(middleware.UserAuth(tokens)) }) }) s.Group("/api/service/admin", func(group *ghttp.RouterGroup) { group.Middleware(middleware.Recover, middleware.CORS, ghttp.MiddlewareHandlerResponse) group.Bind(adminctl.NewAuth()) // Public: login only. group.Group("/", func(profile *ghttp.RouterGroup) { // 仅登录端点:个人资料 / 权限码 / 菜单路由。 profile.Middleware(middleware.AdminAuthOnly(tokens)) profile.Bind(adminctl.NewProfile()) }) group.Group("/", func(protected *ghttp.RouterGroup) { // 受权限保护端点:RBAC 管理、日志等。 // 权限由后端按「方法+路径」自动匹配,无需前端传 X-Permission。 protected.Middleware(middleware.AdminAuth(tokens, adminauth.AdminAuth().PermissionForPath, adminauth.AdminAuth().HasPermission, func(ctx context.Context, id uint64, permission, method, path, ip, param string, duration, status int) { adminaudit.AdminAudit().Record(ctx, adminaudit.AuditEvent{AdminID: id, Permission: permission, Method: method, Path: path, IP: ip, Param: param, DurationMS: duration, StatusCode: status}) })) protected.Bind(adminctl.New()) protected.Bind(housectl.New()) }) }) s.Run() return nil }, } )