diff --git a/app/api/admin/api/auth.go b/app/api/admin/api/auth.go index a0b8757..0a8f4d9 100644 --- a/app/api/admin/api/auth.go +++ b/app/api/admin/api/auth.go @@ -10,7 +10,42 @@ import ( type Auth struct{} +type authForm struct { + ParentID string `json:"parent_id" form:"parent_id"` + Kind int `json:"kind" form:"kind" binding:"required"` + Name string `json:"name" form:"name" binding:"required"` + Auth string `json:"auth" form:"auth" binding:"required"` + Sort int `json:"sort" form:"sort"` + Remark string `json:"remark" form:"remark"` +} + func (*Auth) Index(c *gin.Context) { data, err := auth.NewInstance()(api.GetSession()(c).(*session.Admin)).Index() api.APIResponse(err, data)(c) } + +func (*Auth) Add(c *gin.Context) { + form := &struct { + RoleID string `json:"role_id" form:"role_id" binding:"required"` + AuthIDs []string `json:"auth_ids" form:"auth_ids" binding:"required"` + }{} + if err := api.Bind(form)(c); err != nil { + api.APIFailure(err.(error))(c) + return + } +} + +func (*Auth) Edit(c *gin.Context) { + form := &struct { + RoleID string `json:"role_id" form:"role_id" binding:"required"` + AuthIDs []string `json:"auth_ids" form:"auth_ids" binding:"required"` + }{} + if err := api.Bind(form)(c); err != nil { + api.APIFailure(err.(error))(c) + return + } +} + +func (*Auth) Delete(c *gin.Context) { + +} diff --git a/app/api/admin/api/department.go b/app/api/admin/api/department.go index 71eb183..54f9665 100644 --- a/app/api/admin/api/department.go +++ b/app/api/admin/api/department.go @@ -4,7 +4,6 @@ import ( "SciencesServer/app/api/admin/controller/department" "SciencesServer/app/basic/api" "SciencesServer/app/session" - "github.com/gin-gonic/gin" ) @@ -13,14 +12,21 @@ type Department struct{} type departmentForm struct { ParentID string `json:"parent_id" form:"parent_id"` Name string `json:"name" form:"name" binding:"required"` - Contact string `json:"contact" form:"contact_title"` + Contact string `json:"contact" form:"contact"` ContactMobile string `json:"contact_mobile" form:"contact_mobile"` Status int `json:"status" form:"status" binding:"required"` Remark string `json:"remark" form:"remark"` } func (a *Department) Index(c *gin.Context) { - data, err := department.NewInstance()(api.GetSession()(c).(*session.Admin)).Index() + form := &struct { + FilterID string `json:"filter_id" form:"filter_id"` + }{} + if err := api.Bind(form)(c); err != nil { + api.APIFailure(err.(error))(c) + return + } + data, err := department.NewInstance()(api.GetSession()(c).(*session.Admin)).Index((&api.IDStringForm{ID: form.FilterID}).Convert()) api.APIResponse(err, data)(c) } diff --git a/app/api/admin/api/menu.go b/app/api/admin/api/menu.go index ef9d465..b87cda6 100644 --- a/app/api/admin/api/menu.go +++ b/app/api/admin/api/menu.go @@ -19,7 +19,7 @@ type ( Link string `json:"path" form:"path"` Component string `json:"component" form:"component"` Icon string `json:"icon" form:"icon"` - Auth int `json:"auth" form:"auth"` + Auth string `json:"auth" form:"auth"` Sort int `json:"sort" form:"sort"` IsCache int `json:"is_cache" form:"is_cache"` Hidden int `json:"hidden" form:"hidden"` diff --git a/app/api/admin/api/tenant.go b/app/api/admin/api/tenant.go index ad9c05e..b802ab4 100644 --- a/app/api/admin/api/tenant.go +++ b/app/api/admin/api/tenant.go @@ -107,38 +107,48 @@ func (a *Tenant) MemberBind(c *gin.Context) { func (a *Tenant) Menu(c *gin.Context) { form := &struct { - TenantID uint64 `json:"tenant_id" form:"tenant_id" binding:"required"` + TenantID string `json:"tenant_id" form:"tenant_id" binding:"required"` }{} if err := api.Bind(form)(c); err != nil { api.APIFailure(err.(error))(c) return } - data, err := tenant.NewMenu()(api.GetSession()(c).(*session.Admin)).List(form.TenantID) + data, err := tenant.NewMenu()(api.GetSession()(c).(*session.Admin)).List((&api.IDStringForm{ID: form.TenantID}).Convert()) api.APIResponse(err, data)(c) } func (a *Tenant) MenuBind(c *gin.Context) { form := &struct { - TenantID uint64 `json:"tenant_id" form:"tenant_id" binding:"required"` - MenuIDs []uint64 `json:"menu_ids" form:"menu_ids" binding:"required"` + TenantID string `json:"tenant_id" form:"tenant_id" binding:"required"` + MenuIDs []string `json:"menu_ids" form:"menu_ids" binding:"required"` }{} if err := api.Bind(form)(c); err != nil { api.APIFailure(err.(error))(c) return } - err := tenant.NewMenu()(api.GetSession()(c).(*session.Admin)).Bind(form.TenantID, form.MenuIDs) + menuIDs := make([]uint64, 0) + + for _, v := range form.MenuIDs { + menuIDs = append(menuIDs, (&api.IDStringForm{ID: v}).Convert()) + } + err := tenant.NewMenu()(api.GetSession()(c).(*session.Admin)).Bind((&api.IDStringForm{ID: form.TenantID}).Convert(), menuIDs) api.APIResponse(err)(c) } func (a *Tenant) AuthBind(c *gin.Context) { form := &struct { - TenantID uint64 `json:"tenant_id" form:"tenant_id" binding:"required"` - AuthIDs []uint64 `json:"auth_ids" form:"auth_ids" binding:"required"` + TenantID string `json:"tenant_id" form:"tenant_id" binding:"required"` + AuthIDs []string `json:"auth_ids" form:"auth_ids" binding:"required"` }{} if err := api.Bind(form)(c); err != nil { api.APIFailure(err.(error))(c) return } - err := tenant.NewAuth()(api.GetSession()(c).(*session.Admin)).Bind(form.TenantID, form.AuthIDs) + authIDs := make([]uint64, 0) + + for _, v := range form.AuthIDs { + authIDs = append(authIDs, (&api.IDStringForm{ID: v}).Convert()) + } + err := tenant.NewAuth()(api.GetSession()(c).(*session.Admin)).Bind((&api.IDStringForm{ID: form.TenantID}).Convert(), authIDs) api.APIResponse(err)(c) } diff --git a/app/api/admin/api/user.go b/app/api/admin/api/user.go index d24c138..8ad8163 100644 --- a/app/api/admin/api/user.go +++ b/app/api/admin/api/user.go @@ -11,12 +11,14 @@ import ( type User struct{} type userForm struct { - Account string `json:"account" form:"account" binding:"required"` + Account string `json:"account" form:"account"` Name string `json:"name" form:"name" binding:"required"` Mobile string `json:"mobile" form:"mobile" binding:"required"` Gender int `json:"gender" form:"gender" binding:"required"` + Status int `json:"status" form:"status" binding:"required"` DepartmentID string `json:"department_id" form:"department_id"` RoleIDs []string `json:"role_ids" form:"role_ids"` + Email string `json:"email" form:"email"` Remark string `json:"remark" form:"remark"` } @@ -81,8 +83,8 @@ func (a *User) Add(c *gin.Context) { return } err := user.NewInstance()(api.GetSession()(c).(*session.Admin)).Add(&user.InstanceForm{ - Account: form.Account, Name: form.Name, Mobile: form.Mobile, Password: form.Password, - Remark: form.Remark, Gender: form.Gender, DepartmentID: form.departmentInfo(), RoleIDs: form.RoleInfo(), + Account: form.Account, Name: form.Name, Mobile: form.Mobile, Password: form.Password, Status: form.Status, + Email: form.Email, Remark: form.Remark, Gender: form.Gender, DepartmentID: form.departmentInfo(), RoleIDs: form.RoleInfo(), }) api.APIResponse(err)(c) } @@ -97,8 +99,8 @@ func (a *User) Edit(c *gin.Context) { return } err := user.NewInstance()(api.GetSession()(c).(*session.Admin)).Edit(&user.InstanceForm{ - ID: form.Convert(), Account: form.Account, Name: form.Name, Mobile: form.Mobile, - Remark: form.Remark, Gender: form.Gender, DepartmentID: form.departmentInfo(), RoleIDs: form.RoleInfo(), + ID: form.Convert(), Account: form.Account, Name: form.Name, Mobile: form.Mobile, Status: form.Status, + Email: form.Email, Remark: form.Remark, Gender: form.Gender, DepartmentID: form.departmentInfo(), RoleIDs: form.RoleInfo(), }) api.APIResponse(err)(c) } @@ -107,7 +109,7 @@ func (a *User) Password(c *gin.Context) { form := &struct { api.IDStringForm Password string `json:"password" form:"password" binding:"required"` - RepeatPwd string `json:"repeat_pwd" form:"repeat_pwd" binding:"required"` + RepeatPwd string `json:"repeat_pwd" form:"repeat_pwd"` }{} if err := api.Bind(form)(c); err != nil { api.APIFailure(err.(error))(c) diff --git a/app/api/admin/controller/auth/instance.go b/app/api/admin/controller/auth/instance.go index 9950f1a..25d53c3 100644 --- a/app/api/admin/controller/auth/instance.go +++ b/app/api/admin/controller/auth/instance.go @@ -4,19 +4,26 @@ import ( "SciencesServer/app/api/admin/model" model2 "SciencesServer/app/common/model" "SciencesServer/app/session" + "errors" ) type Instance struct{ *session.Admin } type InstanceHandle func(session *session.Admin) *Instance +type InstanceParams struct { + ID, ParentID uint64 + Kind, Sort int + Name, Auth, Remark string +} + // Index 列表信息 func (c *Instance) Index() ([]*Tree, error) { mSysAuth := model.NewSysAuth() where := []*model2.ModelWhereOrder{ + &model2.ModelWhereOrder{Order: model2.NewOrder("sort", model2.OrderModeToAsc)}, &model2.ModelWhereOrder{Order: model2.NewOrder("parent_id", model2.OrderModeToAsc)}, - &model2.ModelWhereOrder{Order: model2.NewOrder("sort", model2.OrderModeToDesc)}, } out := make([]*model2.SysAuth, 0) @@ -26,6 +33,44 @@ func (c *Instance) Index() ([]*Tree, error) { return tree(out, 0), nil } +// Form 数据操作 +func (c *Instance) Form(params *InstanceParams) error { + mSysAuth := model.NewSysAuth() + + if params.ID > 0 { + mSysAuth.ID = params.ID + + if isExist, err := model2.First(mSysAuth.SysAuth); err != nil { + return err + } else if !isExist { + return errors.New("操作错误,权限信息不存在") + } + } + mSysAuth.ParentID = params.ParentID + mSysAuth.Kind = model2.SysAuthKind(params.Kind) + mSysAuth.Name = params.Name + mSysAuth.Auth = params.Auth + mSysAuth.Sort = params.Sort + mSysAuth.Remark = params.Remark + + if mSysAuth.ID > 0 { + return model2.Updates(mSysAuth.SysAuth, mSysAuth.SysAuth) + } + return model2.Create(mSysAuth.SysAuth) +} + +func (c *Instance) Delete(id uint64) error { + mSysAuth := model.NewSysAuth() + mSysAuth.ID = id + + err := model2.Delete(mSysAuth.SysAuth) + + if err != nil { + return err + } + return nil +} + func NewInstance() InstanceHandle { return func(session *session.Admin) *Instance { return &Instance{Admin: session} diff --git a/app/api/admin/controller/department/instance.go b/app/api/admin/controller/department/instance.go index 7db6e53..9ded5f7 100644 --- a/app/api/admin/controller/department/instance.go +++ b/app/api/admin/controller/department/instance.go @@ -49,18 +49,26 @@ func (c *Instance) tree(src []*model2.SysDepartment, parentID uint64) []*Instanc return out } -func (c *Instance) Index() ([]*InstanceTreeInfo, error) { +func (c *Instance) Index(filterID uint64) ([]*InstanceTreeInfo, error) { mSysDepartment := model.NewSysDepartment() out := make([]*model2.SysDepartment, 0) - if err := model2.Scan(mSysDepartment.SysDepartment, &out, &model2.ModelWhereOrder{ - Where: model2.NewWhere("tenant_id", c.TenantID), - Order: model2.NewOrder("parent_id", model2.OrderModeToAsc)}, + where := []*model2.ModelWhereOrder{ &model2.ModelWhereOrder{ - Order: model2.NewOrder("id", model2.OrderModeToDesc)}); err != nil { + Where: model2.NewWhere("tenant_id", c.TenantID), + Order: model2.NewOrder("parent_id", model2.OrderModeToAsc)}, + &model2.ModelWhereOrder{ + Order: model2.NewOrder("id", model2.OrderModeToAsc)}, + } + if filterID > 0 { + where = append(where, &model2.ModelWhereOrder{Where: model2.NewWhereCondition("id", "!=", filterID)}, + &model2.ModelWhereOrder{Where: model2.NewWhereCondition("parent_id", "!=", filterID)}) + } + if err := model2.Scan(mSysDepartment.SysDepartment, &out, where...); err != nil { return nil, err } + return c.tree(out, 0), nil } @@ -73,7 +81,7 @@ func (c *Instance) Select() ([]*InstanceTreeInfo, error) { Where: model2.NewWhere("tenant_id", c.TenantID), Order: model2.NewOrder("parent_id", model2.OrderModeToAsc)}, &model2.ModelWhereOrder{ Where: model2.NewWhere("status", 1), - Order: model2.NewOrder("id", model2.OrderModeToDesc)}); err != nil { + Order: model2.NewOrder("id", model2.OrderModeToAsc)}); err != nil { return nil, err } return c.tree(out, 0), nil diff --git a/app/api/admin/controller/menu/menu.go b/app/api/admin/controller/menu/menu.go index ad2e1ea..ab600dc 100644 --- a/app/api/admin/controller/menu/menu.go +++ b/app/api/admin/controller/menu/menu.go @@ -16,11 +16,11 @@ type InstanceHandle func(session *session.Admin) *Instance type ( // InstanceParams 菜单参数 InstanceParams struct { - ID, ParentID uint64 - Kind, Auth int - Name, Link, Component, Icon string - Sort, IsCache, IsHidden, Status int - Remark string + ID, ParentID uint64 + Kind int + Name, Link, Auth, Component, Icon string + Sort, IsCache, IsHidden, Status int + Remark string } ) @@ -50,7 +50,7 @@ func (c *Instance) Form(params *InstanceParams) error { IsHidden: model2.SysMenuHiddenStatus(params.IsHidden), Icon: params.Icon, }, - Auth: model2.SysMenuAuth(params.Auth), + Auth: params.Auth, Sort: params.Sort, Status: model2.SysMenuStatus(params.Status), Remark: params.Remark, @@ -72,7 +72,7 @@ func (c *Instance) Form(params *InstanceParams) error { out.Link = params.Link out.Component = params.Component out.Icon = params.Icon - out.Auth = model2.SysMenuAuth(params.Auth) + out.Auth = params.Auth out.IsCache = model2.SysMenuCacheStatus(params.IsCache) out.IsHidden = model2.SysMenuHiddenStatus(params.IsHidden) out.Sort = params.Sort diff --git a/app/api/admin/controller/role/instance.go b/app/api/admin/controller/role/instance.go index 2f44d1a..2baedcb 100644 --- a/app/api/admin/controller/role/instance.go +++ b/app/api/admin/controller/role/instance.go @@ -25,7 +25,7 @@ type ( } // InstanceBasicInfo 角色基本信息 InstanceBasicInfo struct { - ID uint64 `json:"id"` + ID string `json:"id"` Name string `json:"name"` } ) @@ -77,12 +77,20 @@ func (c *Instance) Select() ([]*InstanceBasicInfo, error) { Order: model2.NewOrder("id", model2.OrderModeToDesc), }, } - out := make([]*InstanceBasicInfo, 0) + out := make([]*model2.SysRole, 0) if err := model2.Scan(mSysRole.SysRole, &out, where...); err != nil { return nil, err } - return out, nil + list := make([]*InstanceBasicInfo, 0) + + for _, v := range out { + list = append(list, &InstanceBasicInfo{ + ID: v.GetEncodeID(), + Name: v.Name, + }) + } + return list, nil } // Form 数据操作 @@ -152,11 +160,10 @@ func (c *Instance) Delete(id uint64) error { return err } go utils.TryCatch(func() { - permission := service.NewPermission( + if _, err = service.NewPermission( service.WithAuthTenant(fmt.Sprintf("%d", mSysRole.TenantID)), service.WithAuthRoles([]string{fmt.Sprintf("%d", id)}), - ) - if _, err = permission.RemoveRolePolicy(); err != nil { + ).RemoveSingleRolePolicy(); err != nil { logger.ErrorF("Casbin 删除租户【%d】下角色【%d】权限信息错误:%v", mSysRole.TenantID, id, err) return } diff --git a/app/api/admin/controller/role/menu.go b/app/api/admin/controller/role/menu.go index 9835dc3..1e42fbd 100644 --- a/app/api/admin/controller/role/menu.go +++ b/app/api/admin/controller/role/menu.go @@ -6,8 +6,6 @@ import ( model2 "SciencesServer/app/common/model" "SciencesServer/app/session" "SciencesServer/serve/orm" - "errors" - "gorm.io/gorm" ) @@ -24,16 +22,7 @@ func (c *Menu) Index(roleID uint64) ([]*menu2.TreeChecked, error) { // Bind 绑定菜单 func (c *Menu) Bind(roleID uint64, menuIDs []uint64) error { if len(menuIDs) > 0 { - var count int64 - mSysMenu := model.NewSysMenu() - - if err := model2.Count(mSysMenu.SysMenu, &count, model2.NewWhereIn("id", menuIDs), - model2.NewWhere("auth", model2.SysMenuAuthForSystem)); err != nil { - return err - } else if count > 0 { - return errors.New("不可设置超管菜单") - } } mSysRoleMenu := model.NewSysRoleMenu() @@ -54,9 +43,7 @@ func (c *Menu) Bind(roleID uint64, menuIDs []uint64) error { if _, has := mark[v]; has { continue } - menus = append(menus, &model2.SysRoleMenu{ - ModelTenant: model2.ModelTenant{TenantID: c.TenantID}, RoleID: roleID, MenuID: v, - }) + menus = append(menus, &model2.SysRoleMenu{RoleID: roleID, MenuID: v}) mark[v] = v } if err = model2.Creates(mSysRoleMenu.SysRoleMenu, menus, tx); err != nil { diff --git a/app/api/admin/controller/tenant/menu.go b/app/api/admin/controller/tenant/menu.go index 9632546..05377b1 100644 --- a/app/api/admin/controller/tenant/menu.go +++ b/app/api/admin/controller/tenant/menu.go @@ -3,12 +3,11 @@ package tenant import ( "SciencesServer/app/api/admin/controller/menu" "SciencesServer/app/api/admin/model" - model3 "SciencesServer/app/api/enterprise/model" model2 "SciencesServer/app/common/model" + "SciencesServer/app/service" "SciencesServer/app/session" "SciencesServer/serve/orm" - "errors" - + "fmt" "gorm.io/gorm" ) @@ -16,6 +15,16 @@ type Menu struct{ *session.Admin } type MenuHandle func(session *session.Admin) *Menu +func (c *Menu) auth(tenantID string, roleIDs []string, request []*service.AuthRequest) error { + permission := service.NewPermission( + service.WithAuthTenant(tenantID), + service.WithAuthRoles(roleIDs), + service.WithAuthRequest(request), + ) + _, err := permission.RemoveRolePolicies() + return err +} + // List 菜单列表 func (c *Menu) List(tenantID uint64) ([]*menu.TreeChecked, error) { mSysMenu := model.NewSysMenu() @@ -24,60 +33,112 @@ func (c *Menu) List(tenantID uint64) ([]*menu.TreeChecked, error) { // Bind 绑定菜单 func (c *Menu) Bind(tenantID uint64, menuIDs []uint64) error { - if len(menuIDs) > 0 { - var count int64 - - mSysMenu := model3.NewSysMenu() - - if err := model2.Count(mSysMenu.SysMenu, &count, model2.NewWhereIn("id", menuIDs), - model2.NewWhere("auth", model2.SysMenuAuthForSystem)); err != nil { - return err - } else if count > 0 { - return errors.New("不可设置超管菜单") - } - } + // 查询菜单信息 mSysTenantMenu := model.NewSysTenantMenu() + // 当前租户的信息 + out := make([]*model2.SysTenantMenu, 0) + err := model2.ScanFields(mSysTenantMenu.SysTenantMenu, &out, []string{"id", "menu_id"}) + + if err != nil { + return err + } + _menus := make(map[uint64]uint64, 0) + // 应保存的菜单 + insertMenus := make([]*model2.SysTenantMenu, 0) + // 应删除的菜单 + deleteMenuIDs := make([]uint64, 0) + + for _, v := range menuIDs { + _menus[v] = v + } return orm.GetDB().Transaction(func(tx *gorm.DB) error { - // TODO:先全部删除,后期考虑局部删除 - err := model2.DeleteWhere(mSysTenantMenu.SysTenantMenu, []*model2.ModelWhere{model2.NewWhere("tenant_id", tenantID)}, tx) + // 无菜单信息 + if len(_menus) <= 0 { + for _, v := range out { + deleteMenuIDs = append(deleteMenuIDs, v.MenuID) + } + goto NEXT + } + // 租户原本含有菜单信息 + for _, v := range out { + _, has := _menus[v.MenuID] - if err != nil { + if !has { + deleteMenuIDs = append(deleteMenuIDs, v.MenuID) + continue + } + delete(_menus, v.MenuID) + } + for k := range _menus { + insertMenus = append(insertMenus, &model2.SysTenantMenu{ + ModelTenant: model2.ModelTenant{TenantID: tenantID}, + MenuID: k, + }) + } + if len(insertMenus) > 0 { + if err = model2.Creates(mSysTenantMenu.SysTenantMenu, insertMenus); err != nil { + return err + } + } + NEXT: + // 删除操作 + if len(deleteMenuIDs) <= 0 { + return nil + } + // 删除租户的菜单信息 + if err = model2.DeleteWhere(mSysTenantMenu.SysTenantMenu, []*model2.ModelWhere{model2.NewWhere("tenant_id", tenantID), + model2.NewWhereIn("menu_id", deleteMenuIDs)}, tx); err != nil { return err } - // 租户角色的菜单 + // 查询租户下所有角色信息 + mSysRole := model.NewSysRole() + + roleIDs := make([]uint64, 0) + + if err = model2.Pluck(mSysRole.SysRole, "id", &roleIDs, model2.NewWhere("tenant_id", tenantID)); err != nil { + return err + } + // 删除租户下角色的菜单 mSysRoleMenu := model.NewSysRoleMenu() if len(menuIDs) <= 0 { - if err = model2.DeleteWhere(mSysRoleMenu.SysRoleMenu, []*model2.ModelWhere{model2.NewWhere("tenant_id", tenantID)}, tx); err != nil { + if err = model2.DeleteWhere(mSysRoleMenu.SysRoleMenu, []*model2.ModelWhere{ + model2.NewWhereIn("role_id", roleIDs), model2.NewWhereIn("menu_id", deleteMenuIDs), + }, tx); err != nil { return err } return nil } - menus := make([]*model2.SysTenantMenu, 0) + // 查询菜单信息,关闭角色的权限信息 + mSysMenu := model.NewSysMenu() - mark := make(map[uint64]uint64, 0) + menus := make([]*model2.SysMenu, 0) - for _, v := range menuIDs { - if _, has := mark[v]; has { + if err = model2.ScanFields(mSysMenu.SysMenu, &menus, []string{"kind", "auth"}, + &model2.ModelWhereOrder{Where: model2.NewWhereIn("id", deleteMenuIDs)}); err != nil { + return err + } + // 同步权限 + _roleIDs := make([]string, 0) + + for _, v := range roleIDs { + _roleIDs = append(_roleIDs, fmt.Sprintf("%d", v)) + } + request := make([]*service.AuthRequest, 0) + + for _, v := range menus { + if v.Kind == model2.SysMenuKindForCatalogue || v.Auth == "" { continue } - menus = append(menus, &model2.SysTenantMenu{ - ModelTenant: model2.ModelTenant{TenantID: tenantID}, MenuID: v, + mSysMenu.Auth = v.Auth + + request = append(request, &service.AuthRequest{ + Url: mSysMenu.FilterAuth(), + Method: "*", }) - mark[v] = v } - if err = model2.Creates(mSysTenantMenu.SysTenantMenu, menus, tx); err != nil { - return err - } - // 删除租户下角色不存在的菜单 - if err = model2.DeleteWhere(mSysRoleMenu.SysRoleMenu, []*model2.ModelWhere{ - model2.NewWhere("tenant_id", tenantID), - model2.NewWhereNotIn("menu_id", menuIDs), - }); err != nil { - return err - } - return nil + return c.auth(fmt.Sprintf("%d", tenantID), _roleIDs, request) }) } diff --git a/app/api/admin/controller/user/instance.go b/app/api/admin/controller/user/instance.go index 2a174b8..56c04f8 100644 --- a/app/api/admin/controller/user/instance.go +++ b/app/api/admin/controller/user/instance.go @@ -26,12 +26,15 @@ type ( InstanceInfo struct { ID string `json:"id"` InstanceUserInfo + Account string `json:"account"` Gender model2.GenderKind `json:"gender"` IsAdmin model2.SysUserAdministrator `json:"is_admin"` Status model2.SysUserStatus `json:"status"` Department *InstanceDepartmentInfo `json:"department"` - Role *InstanceRoleInfo `json:"role"` - CreatedAt time.Time `json:"created_at"` + //Role *InstanceRoleInfo `json:"role"` + RoleIDs []string `json:"role_ids"` + Remark string `json:"remark"` + CreatedAt time.Time `json:"created_at"` } // InstanceUserInfo 用户信息 InstanceUserInfo struct { @@ -55,11 +58,11 @@ type ( // InstanceForm 表单信息 type InstanceForm struct { - ID uint64 - Account, Name, Mobile, Password, Remark string - Gender int - DepartmentID uint64 - RoleIDs []uint64 + ID uint64 + Account, Name, Mobile, Password, Email, Remark string + Gender, Status int + DepartmentID uint64 + RoleIDs []uint64 } func (c *InstanceForm) sync(tx *gorm.DB, first bool, uid, tenantID uint64) error { @@ -171,7 +174,10 @@ func (c *Instance) Index(name, mobile string, departmentIDs []uint64, status, pa InstanceUserInfo: InstanceUserInfo{ UID: v.UUIDString(), Avatar: v.Avatar, Name: v.Name, Email: v.Email, Mobile: v.Mobile, }, - Gender: v.Gender.Gender, IsAdmin: v.IsAdmin, Status: v.Status, CreatedAt: v.CreatedAt, + Account: v.Account, Gender: v.Gender.Gender, IsAdmin: v.IsAdmin, Status: v.Status, CreatedAt: v.CreatedAt, + //Role: make([]*InstanceRoleInfo, 0), + RoleIDs: make([]string, 0), + Remark: v.Remark, } if v.DepartmentID > 0 { @@ -188,11 +194,11 @@ func (c *Instance) Index(name, mobile string, departmentIDs []uint64, status, pa obj.ID = utils.StringToUnit64(v) roleIDs = append(roleIDs, obj.GetEncodeID()) } - roles := &InstanceRoleInfo{ - IDs: roleIDs, - Names: strings.Split(v.RoleNames, "&&"), - } - data.Role = roles + //roles := &InstanceRoleInfo{ + // IDs: roleIDs, + //Names: strings.Split(v.RoleNames, "&&"), + //} + data.RoleIDs = roleIDs } list = append(list, data) } @@ -201,7 +207,7 @@ func (c *Instance) Index(name, mobile string, departmentIDs []uint64, status, pa // Add 添加用户 func (c *Instance) Add(params *InstanceForm) error { - if utils.ValidateMobile(params.Mobile) { + if !utils.ValidateMobile(params.Mobile) { return errors.New("操作错误,手机号码格式错误") } mSysUser := model.NewSysUser() @@ -213,15 +219,18 @@ func (c *Instance) Add(params *InstanceForm) error { if err != nil { return err + } else if count > 0 { + return errors.New("操作错误,当前手机号码已注册") } - return orm.GetDB().Transaction(func(tx *gorm.DB) error { mSysUser.TenantID = c.TenantID mSysUser.Account = params.Account mSysUser.Name = params.Name mSysUser.Mobile = params.Mobile + mSysUser.Email = params.Email mSysUser.Gender.Gender = model2.GenderKind(params.Gender) mSysUser.Password = params.Password + mSysUser.Status = model2.SysUserStatus(params.Status) mSysUser.Remark = params.Remark if err = model2.Create(mSysUser.SysUser, tx); err != nil { @@ -250,7 +259,7 @@ func (c *Instance) Edit(params *InstanceForm) error { return errors.New("操作错误,无权限操作") } if mSysUser.Mobile != params.Mobile { - if utils.ValidateMobile(params.Mobile) { + if !utils.ValidateMobile(params.Mobile) { return errors.New("操作错误,手机号码格式错误") } var count int64 @@ -263,8 +272,8 @@ func (c *Instance) Edit(params *InstanceForm) error { } mSysUser.Mobile = params.Mobile } - mSysUser.Account = params.Account mSysUser.Name = params.Name + mSysUser.Email = params.Email mSysUser.Gender.Gender = model2.GenderKind(params.Gender) mSysUser.Remark = params.Remark @@ -280,10 +289,11 @@ func (c *Instance) Edit(params *InstanceForm) error { } func (c *Instance) Password(id uint64, password, repeatPwd string) error { - if password != repeatPwd { - return errors.New("操作错误,两次密码输入不一致") - } + //if password != repeatPwd { + // return errors.New("操作错误,两次密码输入不一致") + //} mSysUser := model.NewSysUser() + mSysUser.ID = id isExist, err := model2.FirstField(mSysUser.SysUser, []string{"id", "uuid", "is_admin"}) diff --git a/app/api/admin/model/sys_menu.go b/app/api/admin/model/sys_menu.go index 00f21e5..8bb2c23 100644 --- a/app/api/admin/model/sys_menu.go +++ b/app/api/admin/model/sys_menu.go @@ -4,6 +4,7 @@ import ( "SciencesServer/app/common/model" "SciencesServer/serve/orm" "fmt" + "strings" ) type SysMenu struct { @@ -16,6 +17,10 @@ type SysMenuScene struct { SceneID uint64 `json:"scene_id"` // 场景(租户,角色) } +func (m *SysMenu) FilterAuth() string { + return "/" + strings.ReplaceAll(m.Auth, ":", "/") +} + // Recursion 递归查询子菜单 func (m *SysMenu) Recursion(id uint64) { //SELECT diff --git a/app/api/admin/model/sys_user.go b/app/api/admin/model/sys_user.go index 9f3990d..eeb69ea 100644 --- a/app/api/admin/model/sys_user.go +++ b/app/api/admin/model/sys_user.go @@ -38,7 +38,8 @@ func (m *SysUser) GetByAccountOrMobile(account string, tenantID uint64) (bool, e db := orm.GetDB().Table(m.TableName()). Select("id", "uuid", "tenant_id", "name", "mobile", "password", "salt", "is_admin", "status"). Where("tenant_id = ?", tenantID). - Where("(account = ? OR mobile = ?)", account, account). + //Where("(email = ? OR mobile = ?)", account, account). + Where("mobile = ?", account). Where("is_deleted = ?", model.DeleteStatusForNot) if err := db.First(m.SysUser).Error; err != nil { @@ -50,6 +51,23 @@ func (m *SysUser) GetByAccountOrMobile(account string, tenantID uint64) (bool, e return true, nil } +func (m *SysUser) CheckByAccountOrMobile(account string, tenantID uint64) (bool, error) { + db := orm.GetDB().Table(m.TableName()). + Where("tenant_id = ?", tenantID). + Where("(account = ? OR mobile = ?)", account, account). + Where("is_deleted = ?", model.DeleteStatusForNot) + + var count int64 + + if err := db.Count(&count).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return false, nil + } + return false, err + } + return true, nil +} + // Users 用户信息 func (m *SysUser) Users(page, pageSize int, count *int64, where ...*model.ModelWhere) ([]*SysUserInfo, error) { db := orm.GetDB().Table(m.TableName()+" AS u"). diff --git a/app/common/model/model_test.go b/app/common/model/model_test.go index beb8642..5615edb 100644 --- a/app/common/model/model_test.go +++ b/app/common/model/model_test.go @@ -48,8 +48,8 @@ func mysql() *gorm.DB { orm.WithMaxOpenConns(2000), orm.WithMaxLifetime(1000), orm.WithMysqlOption(&logic.Mysql{ - User: "appuser", Password: "ABCabc01!", Host: "192.168.0.188", Port: 3306, - DBName: "sciences", Parameters: "charset=utf8mb4,utf8&parseTime=True&loc=Local", + Username: "appuser", Password: "ABCabc01!", Host: "192.168.0.188", Port: 3306, + Database: "sciences", Parameters: "charset=utf8mb4,utf8&parseTime=True&loc=Local", }), ).Init() return instance.Engine diff --git a/app/common/model/sys_department.go b/app/common/model/sys_department.go index 871351b..e70f4cd 100644 --- a/app/common/model/sys_department.go +++ b/app/common/model/sys_department.go @@ -6,7 +6,7 @@ type SysDepartment struct { ModelTenant ParentID uint64 `gorm:"column:parent_id;type:int;default:0;comment:父级ID" json:"-"` Name string `gorm:"column:name;type:varchar(20);default:'';comment:部门名称" json:"name"` - Contact string `gorm:"column:contact_name;type:varchar(20);default:'';comment:联系人" json:"contact_name"` + Contact string `gorm:"column:contact;type:varchar(20);default:'';comment:联系人" json:"contact"` ContactMobile string `gorm:"column:contact_mobile;type:varchar(15);default:'';comment:联系方式" json:"contact_mobile"` Status int `gorm:"column:status;type:tinyint(1);default:1;comment:状态(1:正常,2:禁用)" json:"status"` Remark string `gorm:"column:remark;type:varchar(255);default:'';comment:备注信息" json:"remark"` diff --git a/app/common/model/sys_menu.go b/app/common/model/sys_menu.go index c1d9eac..27ca70d 100644 --- a/app/common/model/sys_menu.go +++ b/app/common/model/sys_menu.go @@ -3,7 +3,7 @@ package model type SysMenu struct { Model SysMenuBasic - Auth SysMenuAuth `gorm:"column:auth;type:tinyint(1);default:0;comment:查看权限(0:通用,1:超管)" json:"-"` + Auth string `gorm:"column:auth;type:varchar(100);default:'';comment:权限/路由" json:"auth"` Sort int `gorm:"column:sort;type:tinyint(3);default:0;comment:排序,数值越大,优先排序" json:"sort"` Remark string `gorm:"column:remark;type:varchar(255);default:'';comment:菜单备注" json:"remark"` Status SysMenuStatus `gorm:"column:status;type:tinyint(1);default:1;comment:状态" json:"status"` @@ -34,16 +34,6 @@ const ( SysMenuKindForEvent ) -// SysMenuAuth 菜单权限 -type SysMenuAuth int - -const ( - // SysMenuAuthForOrdinary 普通权限 - SysMenuAuthForOrdinary SysMenuAuth = iota - // SysMenuAuthForSystem 系统权限 - SysMenuAuthForSystem -) - // SysMenuStatus 菜单状态 type SysMenuStatus int diff --git a/app/common/model/sys_role_menu.go b/app/common/model/sys_role_menu.go index 4ed6104..b946dad 100644 --- a/app/common/model/sys_role_menu.go +++ b/app/common/model/sys_role_menu.go @@ -2,7 +2,6 @@ package model type SysRoleMenu struct { Model - ModelTenant RoleID uint64 `gorm:"column:role_id;type:int;default:0;comment:角色ID" json:"-"` MenuID uint64 `gorm:"column:menu_id;type:int;default:0;comment:菜单ID" json:"-"` ModelDeleted diff --git a/app/service/auth.go b/app/service/auth.go index 3d9dad3..b577c0e 100644 --- a/app/service/auth.go +++ b/app/service/auth.go @@ -168,8 +168,28 @@ func (this *Permission) AddPolicies() (bool, error) { return auth.enforcer.AddPolicies(rules) } -// RemoveRolePolicy 删除角色的所有规则 -func (this *Permission) RemoveRolePolicy() (bool, error) { +// RemoveRolePolicies 删除角色指定规则 +func (this *Permission) RemoveRolePolicies() (bool, error) { + if len(this.roles) <= 0 { + return false, errors.New("not role") + } + rules := make([][]string, 0) + + tenantFormat := this.tenantFormat() + + for _, v := range this.roleFormat() { + + for _, request := range this.request { + rules = append(rules, []string{ + v, tenantFormat, request.Url, request.Method, + }) + } + } + return auth.enforcer.RemovePolicies(rules) +} + +// RemoveSingleRolePolicy 删除角色的所有规则 +func (this *Permission) RemoveSingleRolePolicy() (bool, error) { if len(this.roles) <= 0 { return false, errors.New("not role") } diff --git a/app/service/auth_test.go b/app/service/auth_test.go new file mode 100644 index 0000000..3fc47d1 --- /dev/null +++ b/app/service/auth_test.go @@ -0,0 +1,47 @@ +package service + +import ( + "SciencesServer/app/common/model" + "SciencesServer/serve/orm" + "SciencesServer/serve/orm/logic" + "gorm.io/gorm" + "testing" +) + +func mysql() *gorm.DB { + instance := orm.NewInstance( + orm.WithDebug(false), + orm.WithDBMode("mysql"), + orm.WithTablePrefix(""), + orm.WithSingularTable(false), + orm.WithMaxIdleConns(3600), + orm.WithMaxOpenConns(2000), + orm.WithMaxLifetime(1000), + orm.WithMysqlOption(&logic.Mysql{ + Username: "appuser", Password: "ABCabc01", Host: "192.168.0.188", Port: 3306, + Database: "sciences", Parameters: "charset=utf8mb4,utf8&parseTime=True&loc=Local", + }), + ).Init() + return instance.Engine +} + +func TestNewPermission(t *testing.T) { + mysql := mysql() + NewAuth().Register()("mysql", mysql, model.NewSysAuthRule().TableName()) + + permission := NewPermission( + WithAuthTenant("0"), + WithAuthUser("123"), + WithAuthRoles([]string{"1", "2"}), + WithAuthRequest([]*AuthRequest{&AuthRequest{ + Url: "/admin/123", + Method: "*", + }}), + ) + //status, err := permission.AddPolicies() + //status, err := permission.AddRoleForUser() + //status, err := permission.RemoveRolePolicies() + status, err := permission.Enforce() + t.Log(status) + t.Log(err) +} diff --git a/utils/encrypt_test.go b/utils/encrypt_test.go index 5aade2e..6d87913 100644 --- a/utils/encrypt_test.go +++ b/utils/encrypt_test.go @@ -4,6 +4,6 @@ import "testing" func TestSha256String(t *testing.T) { //t.Log(Md5String("9f735e0df9a1ddc702bf0a1a7b83033f9f7153a00c29de82cedadc9957289b05")) - t.Log(HASHIDEncode(123)) + t.Log(HASHIDEncode(2)) t.Log(HASHIDDecode("lV5OBJ")) }