// Code scaffolded by goctl. Safe to edit. // goctl 1.9.2 package svc import ( "context" "crypto/md5" "fmt" "log" "github.com/casbin/casbin/v2" casbinmodel "github.com/casbin/casbin/v2/model" gormadapter "github.com/casbin/gorm-adapter/v3" "github.com/youruser/base/internal/config" "github.com/youruser/base/internal/middleware" "github.com/youruser/base/model" "gorm.io/driver/mysql" "gorm.io/gorm" "github.com/zeromicro/go-zero/rest" ) const casbinModelText = ` [request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && r.act == p.act ` type ServiceContext struct { Config config.Config Cors rest.Middleware Log rest.Middleware Auth rest.Middleware Authz rest.Middleware // 数据库连接 DB *gorm.DB // Casbin enforcer Enforcer *casbin.Enforcer } func NewServiceContext(c config.Config) *ServiceContext { // 创建数据库连接 dsn := c.MySQL.DSN db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("Failed to connect database: " + err.Error()) } // 自动迁移表 err = db.AutoMigrate(&model.User{}, &model.Profile{}) if err != nil { panic("Failed to migrate database: " + err.Error()) } // 初始化 Casbin enforcer := initCasbin(db) // 种子超级管理员 seedSuperAdmin(db) // 种子 Casbin 策略 seedCasbinPolicies(enforcer) return &ServiceContext{ Config: c, Cors: middleware.NewCorsMiddleware().Handle, Log: middleware.NewLogMiddleware().Handle, Auth: middleware.NewAuthMiddleware().Handle, Authz: middleware.NewAuthzMiddleware(enforcer).Handle, DB: db, Enforcer: enforcer, } } // Close 关闭资源 func (s *ServiceContext) Close() error { if s.DB != nil { sqlDB, err := s.DB.DB() if err != nil { return err } return sqlDB.Close() } return nil } // initCasbin 初始化 Casbin enforcer func initCasbin(db *gorm.DB) *casbin.Enforcer { // 使用 GORM adapter(自动创建 casbin_rule 表) adapter, err := gormadapter.NewAdapterByDB(db) if err != nil { panic("Failed to create Casbin adapter: " + err.Error()) } // 从字符串加载 model m, err := casbinmodel.NewModelFromString(casbinModelText) if err != nil { panic("Failed to create Casbin model: " + err.Error()) } enforcer, err := casbin.NewEnforcer(m, adapter) if err != nil { panic("Failed to create Casbin enforcer: " + err.Error()) } // 加载策略 if err := enforcer.LoadPolicy(); err != nil { panic("Failed to load Casbin policy: " + err.Error()) } log.Println("[Casbin] Enforcer initialized successfully") return enforcer } // seedSuperAdmin 首次启动创建超级管理员 func seedSuperAdmin(db *gorm.DB) { ctx := context.Background() existing, err := model.FindOneByUsername(ctx, db, "admin") if err == nil { if existing.Role != model.RoleSuperAdmin { existing.Role = model.RoleSuperAdmin existing.Source = model.SourceSystem model.Update(ctx, db, existing) log.Println("[Seed] Updated admin to super_admin role") } return } password := fmt.Sprintf("%x", md5.Sum([]byte("admin123"))) admin := &model.User{ Username: "admin", Phone: "13800000000", Email: "", Password: password, Role: model.RoleSuperAdmin, Source: model.SourceSystem, Remark: "系统自动创建的超级管理员", Status: 1, } _, err = model.Insert(ctx, db, admin) if err != nil { log.Printf("[Seed] Failed to create super admin: %v", err) return } log.Println("[Seed] Super admin created: admin / admin123") } // seedCasbinPolicies 种子 Casbin 策略(幂等) func seedCasbinPolicies(enforcer *casbin.Enforcer) { // 角色层级: super_admin > admin > user > guest roleHierarchy := [][]string{ {"super_admin", "admin"}, {"admin", "user"}, {"user", "guest"}, } for _, g := range roleHierarchy { if has, _ := enforcer.HasGroupingPolicy(g[0], g[1]); !has { enforcer.AddGroupingPolicy(g[0], g[1]) } } // 默认策略 policies := [][]string{ // guest: 仪表盘只读 {"guest", "/api/v1/dashboard/*", "GET"}, // user: 个人中心 {"user", "/api/v1/profile/*", "GET"}, {"user", "/api/v1/profile/*", "PUT"}, {"user", "/api/v1/profile/*", "POST"}, // admin: 用户管理(增查改) {"admin", "/api/v1/users", "GET"}, {"admin", "/api/v1/user", "POST"}, {"admin", "/api/v1/user/:id", "GET"}, {"admin", "/api/v1/user/:id", "PUT"}, // super_admin: 用户删除 {"super_admin", "/api/v1/user/:id", "DELETE"}, } for _, p := range policies { if has, _ := enforcer.HasPolicy(p[0], p[1], p[2]); !has { enforcer.AddPolicy(p[0], p[1], p[2]) } } enforcer.SavePolicy() log.Println("[Casbin] Policies seeded successfully") }