package user import ( "github.com/veypi/vbase/cfg" "github.com/veypi/vbase/models" "github.com/veypi/vigo" "gorm.io/gorm" ) type GetRolesReq struct { UserID string `src:"path@user_id" desc:"User ID"` Scope *string `json:"scope" src:"query" desc:"Scope"` } func getRoles(x *vigo.X, req *GetRolesReq) ([]models.Role, error) { var userRoles []models.UserRole query := cfg.DB().Preload("Role").Where("user_id = ?", req.UserID) if req.Scope != nil { query = query.Joins("JOIN roles ON roles.id = user_roles.role_id").Where("roles.scope = ?", *req.Scope) } if err := query.Find(&userRoles).Error; err != nil { return nil, vigo.ErrDatabase.WithError(err) } roles := make([]models.Role, 0, len(userRoles)) for _, ur := range userRoles { roles = append(roles, ur.Role) } return roles, nil } type UpdateRolesReq struct { UserID string `src:"path@user_id" desc:"User ID"` RoleIDs []string `json:"role_ids" src:"json" desc:"Role IDs"` Scope string `json:"scope" src:"json" default:"default" desc:"Scope"` } func updateRoles(x *vigo.X, req *UpdateRolesReq) error { var user models.User if err := cfg.DB().First(&user, "id = ?", req.UserID).Error; err != nil { return vigo.ErrNotFound } return cfg.DB().Transaction(func(tx *gorm.DB) error { // Find all roles in the target scope to identify which UserRoles to delete var scopeRoleIDs []string if err := tx.Model(&models.Role{}).Where("scope = ?", req.Scope).Pluck("id", &scopeRoleIDs).Error; err != nil { return err } // If there are roles in this scope, delete the user's association with them if len(scopeRoleIDs) > 0 { if err := tx.Where("user_id = ? AND role_id IN ?", req.UserID, scopeRoleIDs).Delete(&models.UserRole{}).Error; err != nil { return err } } if len(req.RoleIDs) > 0 { // Verify that all provided RoleIDs belong to the requested scope var count int64 if err := tx.Model(&models.Role{}).Where("id IN ? AND scope = ?", req.RoleIDs, req.Scope).Count(&count).Error; err != nil { return err } if count != int64(len(req.RoleIDs)) { return vigo.ErrInvalidArg.WithString("One or more roles do not belong to the specified scope") } userRoles := make([]models.UserRole, 0, len(req.RoleIDs)) for _, rid := range req.RoleIDs { userRoles = append(userRoles, models.UserRole{ UserID: req.UserID, RoleID: rid, }) } if err := tx.Create(&userRoles).Error; err != nil { return err } } return nil }) }