diff --git a/scripts/sql/fill.sql b/scripts/sql/fill.sql index 64019c6..edef7f2 100644 --- a/scripts/sql/fill.sql +++ b/scripts/sql/fill.sql @@ -2,115 +2,20 @@ -- region 填充数据 -- ==================== -insert into client - (client_id, client_secret, redirect_uri, spec, name, type) +insert into client (type, spec, name, client_id, client_secret, redirect_uri) values (1, 3, 'web', 'web', '$2a$10$Ss12mXQgpYyo1CKIZ3URouDm.Lc2KcYJzsvEK2PTIXlv6fHQht45a', ''); +insert into client (type, spec, name, client_id, client_secret, redirect_uri) values (1, 3, 'admin', 'admin', '$2a$10$dlfvX5Uf3iVsUWgwlb0Wt.oYsw/OEXgS.Aior3yoT63Ju7ZSsJr/2', ''); + +insert into product (code, name, description) values ('dynamic-short', '短效动态', '短效动态'); +insert into product (code, name, description) values ('dynamic-long', '长效动态', '长效动态'); +insert into product (code, name, description) values ('static', '长效静态', '长效静态'); + +delete from permission where true; +insert into permission + (name, description) values - ('web', '$2a$10$Ss12mXQgpYyo1CKIZ3URouDm.Lc2KcYJzsvEK2PTIXlv6fHQht45a', '', 3, 'web', 1); - -with pid as ( - insert into app.public.product - (code, name, description) - values - ('dynamic-short', '短效动态', '短效动态') - returning id -) -insert into app.public.product_sku - (product_id, code, name, price, discount) -select pid.id, 'mode=quota,live=3,expire=0', '短效动态包量 3 分钟', 50, 1 from pid -union all select pid.id, 'mode=quota,live=5,expire=0', '短效动态包量 5 分钟', 100, 1 from pid -union all select pid.id, 'mode=quota,live=10,expire=0', '短效动态包量 10 分钟', 200, 1 from pid -union all select pid.id, 'mode=quota,live=20,expire=0', '短效动态包量 20 分钟', 300, 1 from pid -union all select pid.id, 'mode=quota,live=30,expire=0', '短效动态包量 30 分钟', 600, 1 from pid - -union all select pid.id, 'mode=time,live=3,expire=7', '短效动态包时 7 天 3 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=3,expire=15', '短效动态包时 15 天 3 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=3,expire=30', '短效动态包时 30 天 3 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=3,expire=90', '短效动态包时 90 天 3 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=3,expire=180', '短效动态包时 180 天 3 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=3,expire=365', '短效动态包时 365 天 3 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=5,expire=7', '短效动态包时 7 天 5 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=5,expire=15', '短效动态包时 15 天 5 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=5,expire=30', '短效动态包时 30 天 5 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=5,expire=90', '短效动态包时 90 天 5 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=5,expire=180', '短效动态包时 180 天 5 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=5,expire=365', '短效动态包时 365 天 5 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=10,expire=7', '短效动态包时 7 天 10 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=10,expire=15', '短效动态包时 15 天 10 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=10,expire=30', '短效动态包时 30 天 10 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=10,expire=90', '短效动态包时 90 天 10 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=10,expire=180', '短效动态包时 180 天 10 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=10,expire=365', '短效动态包时 365 天 10 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=20,expire=7', '短效动态包时 7 天 20 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=20,expire=15', '短效动态包时 15 天 20 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=20,expire=30', '短效动态包时 30 天 20 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=20,expire=90', '短效动态包时 90 天 20 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=20,expire=180', '短效动态包时 180 天 20 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=20,expire=365', '短效动态包时 365 天 20 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=30,expire=7', '短效动态包时 7 天 30 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=30,expire=15', '短效动态包时 15 天 30 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=30,expire=30', '短效动态包时 30 天 30 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=30,expire=90', '短效动态包时 90 天 30 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=30,expire=180', '短效动态包时 180 天 30 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=30,expire=365', '短效动态包时 365 天 30 分钟', 1642.5, 1 from pid + ('permission:read', '读取权限列表'), + ('permission:write', '写入权限'), + ('admin-role:read', '读取管理员角色列表'), + ('admin-role:write', '写入管理员角色') ; - -with pid as ( - insert into app.public.product - (code, name, description) - values - ('dynamic-long', '长效动态', '长效动态') - returning id -) -insert into app.public.product_sku - (product_id, code, name, price, discount) -select pid.id, 'mode=quota,live=60,expire=0', '长效动态包量 60 分钟', 50, 1 from pid -union all select pid.id, 'mode=quota,live=240,expire=0', '长效动态包量 240 分钟', 100, 1 from pid -union all select pid.id, 'mode=quota,live=480,expire=0', '长效动态包量 480 分钟', 200, 1 from pid -union all select pid.id, 'mode=quota,live=720,expire=0', '长效动态包量 720 分钟', 300, 1 from pid -union all select pid.id, 'mode=quota,live=1440,expire=0', '长效动态包量 1440 分钟', 600, 1 from pid - -union all select pid.id, 'mode=time,live=60,expire=7', '长效动态包时 7 天 60 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=60,expire=15', '长效动态包时 15 天 60 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=60,expire=30', '长效动态包时 30 天 60 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=60,expire=90', '长效动态包时 90 天 60 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=60,expire=180', '长效动态包时 180 天 60 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=60,expire=365', '长效动态包时 365 天 60 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=240,expire=7', '长效动态包时 7 天 240 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=240,expire=15', '长效动态包时 15 天 240 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=240,expire=30', '长效动态包时 30 天 240 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=240,expire=90', '长效动态包时 90 天 240 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=240,expire=180', '长效动态包时 180 天 240 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=240,expire=365', '长效动态包时 365 天 240 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=480,expire=7', '长效动态包时 7 天 480 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=480,expire=15', '长效动态包时 15 天 480 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=480,expire=30', '长效动态包时 30 天 480 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=480,expire=90', '长效动态包时 90 天 480 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=480,expire=180', '长效动态包时 180 天 480 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=480,expire=365', '长效动态包时 365 天 480 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=720,expire=7', '长效动态包时 7 天 720 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=720,expire=15', '长效动态包时 15 天 720 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=720,expire=30', '长效动态包时 30 天 720 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=720,expire=90', '长效动态包时 90 天 720 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=720,expire=180', '长效动态包时 180 天 720 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=720,expire=365', '长效动态包时 365 天 720 分钟', 1642.5, 1 from pid - -union all select pid.id, 'mode=time,live=1440,expire=7', '长效动态包时 7 天 1440 分钟', 56, 1 from pid -union all select pid.id, 'mode=time,live=1440,expire=15', '长效动态包时 15 天 1440 分钟', 90, 1 from pid -union all select pid.id, 'mode=time,live=1440,expire=30', '长效动态包时 30 天 1440 分钟', 180, 1 from pid -union all select pid.id, 'mode=time,live=1440,expire=90', '长效动态包时 90 天 1440 分钟', 450, 1 from pid -union all select pid.id, 'mode=time,live=1440,expire=180', '长效动态包时 180 天 1440 分钟', 900, 1 from pid -union all select pid.id, 'mode=time,live=1440,expire=365', '长效动态包时 365 天 1440 分钟', 1642.5, 1 from pid -; - -insert into app.public.product - (code, name, description) -values - ('static', '长效静态', '长效静态'); -- endregion diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index c0ed2c5..15b8bd5 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -227,8 +227,8 @@ create table admin_role ( id int generated by default as identity primary key, name text not null, description text, - active bool default true, - sort int default 0, + active bool not null default true, + sort int not null default 0, created_at timestamptz default current_timestamp, updated_at timestamptz default current_timestamp, deleted_at timestamptz @@ -451,63 +451,63 @@ drop table if exists link_user_role cascade; create table link_user_role ( id int generated by default as identity primary key, user_id int not null, - role_id int not null + user_role_id int not null ); create index idx_link_user_role_user_id on link_user_role (user_id); -create index idx_link_user_role_role_id on link_user_role (role_id); +create index idx_link_user_role_role_id on link_user_role (user_role_id); -- link_user_role表字段注释 comment on table link_user_role is '用户角色关联表'; comment on column link_user_role.id is '关联ID'; comment on column link_user_role.user_id is '用户ID'; -comment on column link_user_role.role_id is '角色ID'; +comment on column link_user_role.user_role_id is '角色ID'; -- link_admin_role drop table if exists link_admin_role cascade; create table link_admin_role ( id int generated by default as identity primary key, admin_id int not null, - role_id int not null + admin_role_id int not null ); create index idx_link_admin_role_admin_id on link_admin_role (admin_id); -create index idx_link_admin_role_role_id on link_admin_role (role_id); +create index idx_link_admin_role_role_id on link_admin_role (admin_role_id); -- link_admin_role表字段注释 comment on table link_admin_role is '管理员角色关联表'; comment on column link_admin_role.id is '关联ID'; comment on column link_admin_role.admin_id is '管理员ID'; -comment on column link_admin_role.role_id is '角色ID'; +comment on column link_admin_role.admin_role_id is '角色ID'; -- link_user_role_permission drop table if exists link_user_role_permission cascade; create table link_user_role_permission ( id int generated by default as identity primary key, - role_id int not null, + user_role_id int not null, permission_id int not null ); -create index idx_link_user_role_permission_role_id on link_user_role_permission (role_id); +create index idx_link_user_role_permission_role_id on link_user_role_permission (user_role_id); create index idx_link_user_role_permission_permission_id on link_user_role_permission (permission_id); -- link_user_role_permission表字段注释 comment on table link_user_role_permission is '用户角色权限关联表'; comment on column link_user_role_permission.id is '关联ID'; -comment on column link_user_role_permission.role_id is '角色ID'; +comment on column link_user_role_permission.user_role_id is '角色ID'; comment on column link_user_role_permission.permission_id is '权限ID'; -- link_admin_role_permission drop table if exists link_admin_role_permission cascade; create table link_admin_role_permission ( id int generated by default as identity primary key, - role_id int not null, + admin_role_id int not null, permission_id int not null ); -create index idx_link_admin_role_permission_role_id on link_admin_role_permission (role_id); +create index idx_link_admin_role_permission_role_id on link_admin_role_permission (admin_role_id); create index idx_link_admin_role_permission_permission_id on link_admin_role_permission (permission_id); -- link_admin_role_permission表字段注释 comment on table link_admin_role_permission is '管理员角色权限关联表'; comment on column link_admin_role_permission.id is '关联ID'; -comment on column link_admin_role_permission.role_id is '角色ID'; +comment on column link_admin_role_permission.admin_role_id is '角色ID'; comment on column link_admin_role_permission.permission_id is '权限ID'; -- link_client_permission @@ -1034,23 +1034,23 @@ alter table permission alter table link_user_role add constraint fk_link_user_role_user_id foreign key (user_id) references "user" (id) on delete cascade; alter table link_user_role - add constraint fk_link_user_role_role_id foreign key (role_id) references user_role (id) on delete cascade; + add constraint fk_link_user_role_role_id foreign key (user_role_id) references user_role (id) on delete cascade; -- link_admin_role表外键 alter table link_admin_role add constraint fk_link_admin_role_admin_id foreign key (admin_id) references admin (id) on delete cascade; alter table link_admin_role - add constraint fk_link_admin_role_role_id foreign key (role_id) references admin_role (id) on delete cascade; + add constraint fk_link_admin_role_role_id foreign key (admin_role_id) references admin_role (id) on delete cascade; -- link_user_role_permission表外键 alter table link_user_role_permission - add constraint fk_link_user_role_permission_role_id foreign key (role_id) references user_role (id) on delete cascade; + add constraint fk_link_user_role_permission_role_id foreign key (user_role_id) references user_role (id) on delete cascade; alter table link_user_role_permission add constraint fk_link_user_role_permission_permission_id foreign key (permission_id) references permission (id) on delete cascade; -- link_admin_role_permission表外键 alter table link_admin_role_permission - add constraint fk_link_admin_role_permission_role_id foreign key (role_id) references admin_role (id) on delete cascade; + add constraint fk_link_admin_role_permission_role_id foreign key (admin_role_id) references admin_role (id) on delete cascade; alter table link_admin_role_permission add constraint fk_link_admin_role_permission_permission_id foreign key (permission_id) references permission (id) on delete cascade; diff --git a/web/auth/account.go b/web/auth/account.go index 9b193df..4781ea0 100644 --- a/web/auth/account.go +++ b/web/auth/account.go @@ -17,6 +17,7 @@ func authClient(clientId string, clientSecrets ...string) (*m.Client, error) { // 获取客户端信息 client, err := q.Client. + Preload(q.Client.Permissions). Where( q.Client.ClientID.Eq(clientId), q.Client.Status.Eq(1)). @@ -36,8 +37,6 @@ func authClient(clientId string, clientSecrets ...string) (*m.Client, error) { } } - // todo 查询客户端关联权限 - // 组织授权信息(一次性请求) return client, nil } @@ -154,3 +153,33 @@ func authAdminByPassword(tx *q.Query, username, password string) (*m.Admin, erro return admin, nil } + +func adminScopes(admin *m.Admin) ([]string, error) { + count, err := q.Admin. + LeftJoin(q.LinkAdminRole, q.LinkAdminRole.AdminID.EqCol(q.Admin.ID)). + LeftJoin(q.LinkAdminRolePermission, q.LinkAdminRolePermission.RoleID.EqCol(q.LinkAdminRole.RoleID)). + LeftJoin(q.Permission, q.Permission.ID.EqCol(q.LinkAdminRolePermission.PermissionID)). + Where(q.Admin.ID.Eq(admin.ID)). + Select(q.Permission.Name). + Count() + if err != nil { + return nil, err + } + if count == 0 { + return nil, nil + } + + scopes := make([]string, 0, count) + err = q.Admin. + LeftJoin(q.LinkAdminRole, q.LinkAdminRole.AdminID.EqCol(q.Admin.ID)). + LeftJoin(q.LinkAdminRolePermission, q.LinkAdminRolePermission.RoleID.EqCol(q.LinkAdminRole.RoleID)). + LeftJoin(q.Permission, q.Permission.ID.EqCol(q.LinkAdminRolePermission.PermissionID)). + Where(q.Admin.ID.Eq(admin.ID)). + Select(q.Permission.Name). + Scan(&scopes) + if err != nil { + return nil, err + } + + return scopes, nil +} diff --git a/web/auth/check.go b/web/auth/check.go index 4b292dd..946af86 100644 --- a/web/auth/check.go +++ b/web/auth/check.go @@ -69,7 +69,8 @@ func (a *AuthCtx) checkScopes(scopes ...string) bool { return true } if len(a.smap) == 0 && len(a.Scopes) > 0 { - for _, scope := range scopes { + a.smap = make(map[string]struct{}, len(a.Scopes)) + for _, scope := range a.Scopes { a.smap[scope] = struct{}{} } } diff --git a/web/auth/endpoints.go b/web/auth/endpoints.go index 9b11f4e..25a25d0 100644 --- a/web/auth/endpoints.go +++ b/web/auth/endpoints.go @@ -288,6 +288,7 @@ func authAuthorizationCode(c *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time. func authClientCredential(c *fiber.Ctx, auth *AuthCtx, _ *TokenReq, now time.Time) (*m.Session, error) { // todo 检查 scope + scopes := strings.Join(auth.Scopes, " ") // 生成会话 ip, _ := orm.ParseInet(c.IP()) // 可空字段,忽略异常 @@ -298,6 +299,7 @@ func authClientCredential(c *fiber.Ctx, auth *AuthCtx, _ *TokenReq, now time.Tim ClientID: &auth.Client.ID, AccessToken: uuid.NewString(), AccessTokenExpires: now.Add(time.Duration(env.SessionAccessExpire) * time.Second), + Scopes: &scopes, } // 保存会话 @@ -318,6 +320,8 @@ func authPassword(c *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (*m var user *m.User var admin *m.Admin + var scopes []string + pool := req.LoginPool if pool == "" { pool = PwdLoginAsUser @@ -348,6 +352,10 @@ func authPassword(c *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (*m if err != nil { return nil, err } + scopes, err = adminScopes(admin) + if err != nil { + return nil, err + } // 更新管理员登录时间 admin.LastLogin = u.P(time.Now()) @@ -363,7 +371,7 @@ func authPassword(c *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (*m IP: ip, UA: ua, ClientID: &auth.Client.ID, - Scopes: u.X(req.Scope), + Scopes: u.X(strings.Join(scopes, " ")), AccessToken: uuid.NewString(), AccessTokenExpires: now.Add(time.Duration(env.SessionAccessExpire) * time.Second), } diff --git a/web/auth/middleware.go b/web/auth/middleware.go index 1e6cb2e..88c6ed1 100644 --- a/web/auth/middleware.go +++ b/web/auth/middleware.go @@ -113,8 +113,14 @@ func authBasic(_ context.Context, token string) (*AuthCtx, error) { return nil, fmt.Errorf("客户端认证失败:%w", err) } + scopes := []string{} + if client.Permissions != nil { + for _, p := range client.Permissions { + scopes = append(scopes, p.Name) + } + } return &AuthCtx{ Client: client, - Scopes: []string{}, + Scopes: scopes, }, nil } diff --git a/web/core/http.go b/web/core/http.go index a2acdf2..604fb7c 100644 --- a/web/core/http.go +++ b/web/core/http.go @@ -130,3 +130,8 @@ func Query(in any) url.Values { return out } + +// 数据请求 +type IdReq struct { + Id int32 `json:"id"` +} diff --git a/web/core/model.go b/web/core/model.go index 646501a..7e68b5e 100644 --- a/web/core/model.go +++ b/web/core/model.go @@ -15,7 +15,7 @@ type Model struct { ID int32 `json:"id" gorm:"column:id;primaryKey"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` - DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at"` + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at"` } func (m *Model) GetID() int32 { diff --git a/web/core/scopes.go b/web/core/scopes.go new file mode 100644 index 0000000..3386948 --- /dev/null +++ b/web/core/scopes.go @@ -0,0 +1,10 @@ +package core + +const ( + ScopePermissionRead = string("permission:read") + ScopePermissionWrite = string("permission:write") + ScopeAdminRoleRead = string("admin_role:read") + ScopeAdminRoleWrite = string("admin_role:write") + ScopeAdminRead = string("admin:read") + ScopeAdminWrite = string("admin:write") +) diff --git a/web/handlers/admin.go b/web/handlers/admin.go new file mode 100644 index 0000000..7ce516f --- /dev/null +++ b/web/handlers/admin.go @@ -0,0 +1,92 @@ +package handlers + +import ( + "platform/web/auth" + "platform/web/core" + g "platform/web/globals" + s "platform/web/services" + + "github.com/gofiber/fiber/v2" +) + +func PageAdminsByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRead) + if err != nil { + return err + } + + var req PageAdminsReq + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + list, total, err := s.Admin.PageAdmins(req.PageReq) + if err != nil { + return err + } + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + +type PageAdminsReq struct { + core.PageReq +} + +func CreateAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminWrite) + if err != nil { + return err + } + + var req s.CreateAdmin + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.Admin.CreateAdmin(&req); err != nil { + return err + } + + return c.JSON(nil) +} + +func UpdateAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminWrite) + if err != nil { + return err + } + + var req s.UpdateAdmin + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.Admin.UpdateAdmin(&req); err != nil { + return err + } + + return c.JSON(nil) +} + +func RemoveAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminWrite) + if err != nil { + return err + } + + var req core.IdReq + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.Admin.RemoveAdmin(req.Id); err != nil { + return err + } + + return c.JSON(nil) +} diff --git a/web/handlers/admin_role.go b/web/handlers/admin_role.go new file mode 100644 index 0000000..b631ce2 --- /dev/null +++ b/web/handlers/admin_role.go @@ -0,0 +1,103 @@ +package handlers + +import ( + "platform/web/auth" + "platform/web/core" + g "platform/web/globals" + s "platform/web/services" + + "github.com/gofiber/fiber/v2" +) + +func ListAdminRolesByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRoleRead) + if err != nil { + return err + } + + list, err := s.AdminRole.ListRoles() + if err != nil { + return err + } + + return c.JSON(list) +} + +func PageAdminRolesByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRoleRead) + if err != nil { + return err + } + + var req PageAdminRolesReq + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + list, total, err := s.AdminRole.PageRoles(req.PageReq) + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + +type PageAdminRolesReq struct { + core.PageReq +} + +func CreateAdminRole(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRoleWrite) + if err != nil { + return err + } + + var req s.CreateAdminRole + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.AdminRole.CreateAdminRole(&req); err != nil { + return err + } + + return c.JSON(nil) +} + +func UpdateAdminRole(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRoleWrite) + if err != nil { + return err + } + + var req s.UpdateAdminRole + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.AdminRole.UpdateAdminRole(&req); err != nil { + return err + } + + return c.JSON(nil) +} + +func RemoveAdminRole(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeAdminRoleWrite) + if err != nil { + return err + } + + var req core.IdReq + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + if err := s.AdminRole.RemoveAdminRole(req.Id); err != nil { + return err + } + + return c.JSON(nil) +} diff --git a/web/handlers/iden.go b/web/handlers/iden.go index 8bdf1db..e5a96a6 100644 --- a/web/handlers/iden.go +++ b/web/handlers/iden.go @@ -142,7 +142,7 @@ func IdentifyCallbackNew(c *fiber.Ctx) error { } // 更新用户实名认证状态 - _, err = q.User.Debug(). + _, err = q.User. Where(q.User.ID.Eq(info.Uid)). UpdateSimple( q.User.IDType.Value(info.Type), diff --git a/web/handlers/permission.go b/web/handlers/permission.go new file mode 100644 index 0000000..346a752 --- /dev/null +++ b/web/handlers/permission.go @@ -0,0 +1,53 @@ +package handlers + +import ( + "platform/web/auth" + "platform/web/core" + g "platform/web/globals" + s "platform/web/services" + + "github.com/gofiber/fiber/v2" +) + +func ListPermissionsByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopePermissionRead) + if err != nil { + return err + } + + list, err := s.Permission.ListPermissions() + if err != nil { + return err + } + + return c.JSON(list) +} + +func PagePermissionByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopePermissionRead) + if err != nil { + return err + } + + var req PagePermissionByAdminReq + if err := g.Validator.ParseBody(c, &req); err != nil { + return err + } + + // 获取权限列表 + list, total, err := s.Permission.PagePermissions(req.PageReq) + if err != nil { + return core.NewServErr("获取权限列表失败") + } + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + +type PagePermissionByAdminReq struct { + core.PageReq +} diff --git a/web/models/admin.go b/web/models/admin.go index f726fc3..5662d5a 100644 --- a/web/models/admin.go +++ b/web/models/admin.go @@ -20,6 +20,8 @@ type Admin struct { LastLogin *time.Time `json:"last_login,omitempty" gorm:"column:last_login"` // 最后登录时间 LastLoginIP *orm.Inet `json:"last_login_ip,omitempty" gorm:"column:last_login_ip"` // 最后登录地址 LastLoginUA *string `json:"last_login_ua,omitempty" gorm:"column:last_login_ua"` // 最后登录代理 + + Roles []*AdminRole `json:"roles" gorm:"many2many:link_admin_role"` } // AdminStatus 管理员状态枚举 diff --git a/web/models/admin_role.go b/web/models/admin_role.go index aaac7db..9a5de6d 100644 --- a/web/models/admin_role.go +++ b/web/models/admin_role.go @@ -11,4 +11,6 @@ type AdminRole struct { Description *string `json:"description,omitempty" gorm:"column:description"` // 角色描述 Active bool `json:"active" gorm:"column:active"` // 是否激活 Sort int32 `json:"sort" gorm:"column:sort"` // 排序 + + Permissions []*Permission `json:"permissions" gorm:"many2many:link_admin_role_permission"` } diff --git a/web/models/client.go b/web/models/client.go index a8c9e75..2e7e7fa 100644 --- a/web/models/client.go +++ b/web/models/client.go @@ -15,6 +15,8 @@ type Client struct { Icon *string `json:"icon,omitempty" gorm:"column:icon"` // 图标URL Status ClientStatus `json:"status" gorm:"column:status"` // 状态:0-禁用,1-正常 Type ClientType `json:"type" gorm:"column:type"` // 类型:0-普通,1-官方 + + Permissions []*Permission `json:"permissions" gorm:"many2many:link_client_permission"` } // ClientSpec 客户端安全规范枚举 diff --git a/web/models/link_admin_role.go b/web/models/link_admin_role.go index 5b5ffa7..a6602c4 100644 --- a/web/models/link_admin_role.go +++ b/web/models/link_admin_role.go @@ -2,7 +2,7 @@ package models // LinkAdminRole 管理员角色关联表 type LinkAdminRole struct { - ID int32 `json:"id" gorm:"column:id"` // 关联ID - AdminID int32 `json:"admin_id" gorm:"column:admin_id"` // 管理员ID - RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID + ID int32 `json:"id" gorm:"column:id"` // 关联ID + AdminID int32 `json:"admin_id" gorm:"column:admin_id"` // 管理员ID + RoleID int32 `json:"role_id" gorm:"column:admin_role_id"` // 角色ID } diff --git a/web/models/link_admin_role_permission.go b/web/models/link_admin_role_permission.go index 6ddbeb4..9241b55 100644 --- a/web/models/link_admin_role_permission.go +++ b/web/models/link_admin_role_permission.go @@ -3,6 +3,6 @@ package models // LinkAdminRolePermission 管理员角色权限关联表 type LinkAdminRolePermission struct { ID int32 `json:"id" gorm:"column:id"` // 关联ID - RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID + RoleID int32 `json:"role_id" gorm:"column:admin_role_id"` // 角色ID PermissionID int32 `json:"permission_id" gorm:"column:permission_id"` // 权限ID } diff --git a/web/models/link_user_role.go b/web/models/link_user_role.go index 8141918..317d3d2 100644 --- a/web/models/link_user_role.go +++ b/web/models/link_user_role.go @@ -2,7 +2,7 @@ package models // LinkUserRole 用户角色关联表 type LinkUserRole struct { - ID int32 `json:"id" gorm:"column:id"` // 关联ID - UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID - RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID + ID int32 `json:"id" gorm:"column:id"` // 关联ID + UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID + RoleID int32 `json:"role_id" gorm:"column:user_role_id"` // 角色ID } diff --git a/web/models/link_user_role_permission.go b/web/models/link_user_role_permission.go index 994c7c7..bb8206c 100644 --- a/web/models/link_user_role_permission.go +++ b/web/models/link_user_role_permission.go @@ -3,6 +3,6 @@ package models // LinkUserRolePermission 用户角色权限关联表 type LinkUserRolePermission struct { ID int32 `json:"id" gorm:"column:id"` // 关联ID - RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID + RoleID int32 `json:"role_id" gorm:"column:user_role_id"` // 角色ID PermissionID int32 `json:"permission_id" gorm:"column:permission_id"` // 权限ID } diff --git a/web/models/user.go b/web/models/user.go index 24be5a5..d3291f8 100644 --- a/web/models/user.go +++ b/web/models/user.go @@ -29,7 +29,8 @@ type User struct { LastLoginIP *orm.Inet `json:"last_login_ip,omitempty" gorm:"column:last_login_ip"` // 最后登录地址 LastLoginUA *string `json:"last_login_ua,omitempty" gorm:"column:last_login_ua"` // 最后登录代理 - Admin *Admin `json:"admin,omitempty" gorm:"foreignKey:AdminID"` + Admin *Admin `json:"admin,omitempty" gorm:"foreignKey:AdminID"` + Roles []*UserRole `json:"roles" gorm:"many2many:link_user_role"` } // UserStatus 用户状态枚举 diff --git a/web/models/user_role.go b/web/models/user_role.go index 034ab0f..3c9618d 100644 --- a/web/models/user_role.go +++ b/web/models/user_role.go @@ -11,4 +11,6 @@ type UserRole struct { Description *string `json:"description,omitempty" gorm:"column:description"` // 角色描述 Active bool `json:"active" gorm:"column:active"` // 是否激活 Sort int32 `json:"sort" gorm:"column:sort"` // 排序 + + Permissions []*Permission `json:"permissions" gorm:"many2many:link_user_role_permission"` } diff --git a/web/queries/admin.gen.go b/web/queries/admin.gen.go index bc68f0b..21a1be2 100644 --- a/web/queries/admin.gen.go +++ b/web/queries/admin.gen.go @@ -41,6 +41,32 @@ func newAdmin(db *gorm.DB, opts ...gen.DOOption) admin { _admin.LastLogin = field.NewTime(tableName, "last_login") _admin.LastLoginIP = field.NewField(tableName, "last_login_ip") _admin.LastLoginUA = field.NewString(tableName, "last_login_ua") + _admin.Roles = adminManyToManyRoles{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Roles.Permissions.Children", "models.Permission"), + }, + }, + } _admin.fillFieldMap() @@ -65,6 +91,7 @@ type admin struct { LastLogin field.Time LastLoginIP field.Field LastLoginUA field.String + Roles adminManyToManyRoles fieldMap map[string]field.Expr } @@ -111,7 +138,7 @@ func (a *admin) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (a *admin) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 14) + a.fieldMap = make(map[string]field.Expr, 15) a.fieldMap["id"] = a.ID a.fieldMap["created_at"] = a.CreatedAt a.fieldMap["updated_at"] = a.UpdatedAt @@ -126,18 +153,113 @@ func (a *admin) fillFieldMap() { a.fieldMap["last_login"] = a.LastLogin a.fieldMap["last_login_ip"] = a.LastLoginIP a.fieldMap["last_login_ua"] = a.LastLoginUA + } func (a admin) clone(db *gorm.DB) admin { a.adminDo.ReplaceConnPool(db.Statement.ConnPool) + a.Roles.db = db.Session(&gorm.Session{Initialized: true}) + a.Roles.db.Statement.ConnPool = db.Statement.ConnPool return a } func (a admin) replaceDB(db *gorm.DB) admin { a.adminDo.ReplaceDB(db) + a.Roles.db = db.Session(&gorm.Session{}) return a } +type adminManyToManyRoles struct { + db *gorm.DB + + field.RelationField + + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } +} + +func (a adminManyToManyRoles) Where(conds ...field.Expr) *adminManyToManyRoles { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a adminManyToManyRoles) WithContext(ctx context.Context) *adminManyToManyRoles { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a adminManyToManyRoles) Session(session *gorm.Session) *adminManyToManyRoles { + a.db = a.db.Session(session) + return &a +} + +func (a adminManyToManyRoles) Model(m *models.Admin) *adminManyToManyRolesTx { + return &adminManyToManyRolesTx{a.db.Model(m).Association(a.Name())} +} + +func (a adminManyToManyRoles) Unscoped() *adminManyToManyRoles { + a.db = a.db.Unscoped() + return &a +} + +type adminManyToManyRolesTx struct{ tx *gorm.Association } + +func (a adminManyToManyRolesTx) Find() (result []*models.AdminRole, err error) { + return result, a.tx.Find(&result) +} + +func (a adminManyToManyRolesTx) Append(values ...*models.AdminRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a adminManyToManyRolesTx) Replace(values ...*models.AdminRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a adminManyToManyRolesTx) Delete(values ...*models.AdminRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a adminManyToManyRolesTx) Clear() error { + return a.tx.Clear() +} + +func (a adminManyToManyRolesTx) Count() int64 { + return a.tx.Count() +} + +func (a adminManyToManyRolesTx) Unscoped() *adminManyToManyRolesTx { + a.tx = a.tx.Unscoped() + return &a +} + type adminDo struct{ gen.DO } func (a adminDo) Debug() *adminDo { diff --git a/web/queries/admin_role.gen.go b/web/queries/admin_role.gen.go index 8855796..3d527f5 100644 --- a/web/queries/admin_role.gen.go +++ b/web/queries/admin_role.gen.go @@ -35,6 +35,21 @@ func newAdminRole(db *gorm.DB, opts ...gen.DOOption) adminRole { _adminRole.Description = field.NewString(tableName, "description") _adminRole.Active = field.NewBool(tableName, "active") _adminRole.Sort = field.NewInt32(tableName, "sort") + _adminRole.Permissions = adminRoleManyToManyPermissions{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Children", "models.Permission"), + }, + } _adminRole.fillFieldMap() @@ -53,6 +68,7 @@ type adminRole struct { Description field.String Active field.Bool Sort field.Int32 + Permissions adminRoleManyToManyPermissions fieldMap map[string]field.Expr } @@ -93,7 +109,7 @@ func (a *adminRole) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (a *adminRole) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 8) + a.fieldMap = make(map[string]field.Expr, 9) a.fieldMap["id"] = a.ID a.fieldMap["created_at"] = a.CreatedAt a.fieldMap["updated_at"] = a.UpdatedAt @@ -102,18 +118,110 @@ func (a *adminRole) fillFieldMap() { a.fieldMap["description"] = a.Description a.fieldMap["active"] = a.Active a.fieldMap["sort"] = a.Sort + } func (a adminRole) clone(db *gorm.DB) adminRole { a.adminRoleDo.ReplaceConnPool(db.Statement.ConnPool) + a.Permissions.db = db.Session(&gorm.Session{Initialized: true}) + a.Permissions.db.Statement.ConnPool = db.Statement.ConnPool return a } func (a adminRole) replaceDB(db *gorm.DB) adminRole { a.adminRoleDo.ReplaceDB(db) + a.Permissions.db = db.Session(&gorm.Session{}) return a } +type adminRoleManyToManyPermissions struct { + db *gorm.DB + + field.RelationField + + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } +} + +func (a adminRoleManyToManyPermissions) Where(conds ...field.Expr) *adminRoleManyToManyPermissions { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a adminRoleManyToManyPermissions) WithContext(ctx context.Context) *adminRoleManyToManyPermissions { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a adminRoleManyToManyPermissions) Session(session *gorm.Session) *adminRoleManyToManyPermissions { + a.db = a.db.Session(session) + return &a +} + +func (a adminRoleManyToManyPermissions) Model(m *models.AdminRole) *adminRoleManyToManyPermissionsTx { + return &adminRoleManyToManyPermissionsTx{a.db.Model(m).Association(a.Name())} +} + +func (a adminRoleManyToManyPermissions) Unscoped() *adminRoleManyToManyPermissions { + a.db = a.db.Unscoped() + return &a +} + +type adminRoleManyToManyPermissionsTx struct{ tx *gorm.Association } + +func (a adminRoleManyToManyPermissionsTx) Find() (result []*models.Permission, err error) { + return result, a.tx.Find(&result) +} + +func (a adminRoleManyToManyPermissionsTx) Append(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a adminRoleManyToManyPermissionsTx) Replace(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a adminRoleManyToManyPermissionsTx) Delete(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a adminRoleManyToManyPermissionsTx) Clear() error { + return a.tx.Clear() +} + +func (a adminRoleManyToManyPermissionsTx) Count() int64 { + return a.tx.Count() +} + +func (a adminRoleManyToManyPermissionsTx) Unscoped() *adminRoleManyToManyPermissionsTx { + a.tx = a.tx.Unscoped() + return &a +} + type adminRoleDo struct{ gen.DO } func (a adminRoleDo) Debug() *adminRoleDo { diff --git a/web/queries/bill.gen.go b/web/queries/bill.gen.go index 1949dfc..40e9d5f 100644 --- a/web/queries/bill.gen.go +++ b/web/queries/bill.gen.go @@ -45,8 +45,68 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -200,6 +260,24 @@ type billBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/channel.gen.go b/web/queries/channel.gen.go index 9ef0390..4c7b909 100644 --- a/web/queries/channel.gen.go +++ b/web/queries/channel.gen.go @@ -53,8 +53,68 @@ func newChannel(db *gorm.DB, opts ...gen.DOOption) channel { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -269,6 +329,24 @@ type channelBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/client.gen.go b/web/queries/client.gen.go index 79874f7..3470c6b 100644 --- a/web/queries/client.gen.go +++ b/web/queries/client.gen.go @@ -39,6 +39,21 @@ func newClient(db *gorm.DB, opts ...gen.DOOption) client { _client.Icon = field.NewString(tableName, "icon") _client.Status = field.NewInt(tableName, "status") _client.Type = field.NewInt(tableName, "type") + _client.Permissions = clientManyToManyPermissions{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Children", "models.Permission"), + }, + } _client.fillFieldMap() @@ -61,6 +76,7 @@ type client struct { Icon field.String Status field.Int Type field.Int + Permissions clientManyToManyPermissions fieldMap map[string]field.Expr } @@ -105,7 +121,7 @@ func (c *client) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (c *client) fillFieldMap() { - c.fieldMap = make(map[string]field.Expr, 12) + c.fieldMap = make(map[string]field.Expr, 13) c.fieldMap["id"] = c.ID c.fieldMap["created_at"] = c.CreatedAt c.fieldMap["updated_at"] = c.UpdatedAt @@ -118,18 +134,110 @@ func (c *client) fillFieldMap() { c.fieldMap["icon"] = c.Icon c.fieldMap["status"] = c.Status c.fieldMap["type"] = c.Type + } func (c client) clone(db *gorm.DB) client { c.clientDo.ReplaceConnPool(db.Statement.ConnPool) + c.Permissions.db = db.Session(&gorm.Session{Initialized: true}) + c.Permissions.db.Statement.ConnPool = db.Statement.ConnPool return c } func (c client) replaceDB(db *gorm.DB) client { c.clientDo.ReplaceDB(db) + c.Permissions.db = db.Session(&gorm.Session{}) return c } +type clientManyToManyPermissions struct { + db *gorm.DB + + field.RelationField + + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } +} + +func (a clientManyToManyPermissions) Where(conds ...field.Expr) *clientManyToManyPermissions { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a clientManyToManyPermissions) WithContext(ctx context.Context) *clientManyToManyPermissions { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a clientManyToManyPermissions) Session(session *gorm.Session) *clientManyToManyPermissions { + a.db = a.db.Session(session) + return &a +} + +func (a clientManyToManyPermissions) Model(m *models.Client) *clientManyToManyPermissionsTx { + return &clientManyToManyPermissionsTx{a.db.Model(m).Association(a.Name())} +} + +func (a clientManyToManyPermissions) Unscoped() *clientManyToManyPermissions { + a.db = a.db.Unscoped() + return &a +} + +type clientManyToManyPermissionsTx struct{ tx *gorm.Association } + +func (a clientManyToManyPermissionsTx) Find() (result []*models.Permission, err error) { + return result, a.tx.Find(&result) +} + +func (a clientManyToManyPermissionsTx) Append(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a clientManyToManyPermissionsTx) Replace(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a clientManyToManyPermissionsTx) Delete(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a clientManyToManyPermissionsTx) Clear() error { + return a.tx.Clear() +} + +func (a clientManyToManyPermissionsTx) Count() int64 { + return a.tx.Count() +} + +func (a clientManyToManyPermissionsTx) Unscoped() *clientManyToManyPermissionsTx { + a.tx = a.tx.Unscoped() + return &a +} + type clientDo struct{ gen.DO } func (c clientDo) Debug() *clientDo { diff --git a/web/queries/link_admin_role.gen.go b/web/queries/link_admin_role.gen.go index 86a5de9..f6eb10b 100644 --- a/web/queries/link_admin_role.gen.go +++ b/web/queries/link_admin_role.gen.go @@ -29,7 +29,7 @@ func newLinkAdminRole(db *gorm.DB, opts ...gen.DOOption) linkAdminRole { _linkAdminRole.ALL = field.NewAsterisk(tableName) _linkAdminRole.ID = field.NewInt32(tableName, "id") _linkAdminRole.AdminID = field.NewInt32(tableName, "admin_id") - _linkAdminRole.RoleID = field.NewInt32(tableName, "role_id") + _linkAdminRole.RoleID = field.NewInt32(tableName, "admin_role_id") _linkAdminRole.fillFieldMap() @@ -61,7 +61,7 @@ func (l *linkAdminRole) updateTableName(table string) *linkAdminRole { l.ALL = field.NewAsterisk(table) l.ID = field.NewInt32(table, "id") l.AdminID = field.NewInt32(table, "admin_id") - l.RoleID = field.NewInt32(table, "role_id") + l.RoleID = field.NewInt32(table, "admin_role_id") l.fillFieldMap() @@ -81,7 +81,7 @@ func (l *linkAdminRole) fillFieldMap() { l.fieldMap = make(map[string]field.Expr, 3) l.fieldMap["id"] = l.ID l.fieldMap["admin_id"] = l.AdminID - l.fieldMap["role_id"] = l.RoleID + l.fieldMap["admin_role_id"] = l.RoleID } func (l linkAdminRole) clone(db *gorm.DB) linkAdminRole { diff --git a/web/queries/link_admin_role_permission.gen.go b/web/queries/link_admin_role_permission.gen.go index 5e137e9..28a0d1e 100644 --- a/web/queries/link_admin_role_permission.gen.go +++ b/web/queries/link_admin_role_permission.gen.go @@ -28,7 +28,7 @@ func newLinkAdminRolePermission(db *gorm.DB, opts ...gen.DOOption) linkAdminRole tableName := _linkAdminRolePermission.linkAdminRolePermissionDo.TableName() _linkAdminRolePermission.ALL = field.NewAsterisk(tableName) _linkAdminRolePermission.ID = field.NewInt32(tableName, "id") - _linkAdminRolePermission.RoleID = field.NewInt32(tableName, "role_id") + _linkAdminRolePermission.RoleID = field.NewInt32(tableName, "admin_role_id") _linkAdminRolePermission.PermissionID = field.NewInt32(tableName, "permission_id") _linkAdminRolePermission.fillFieldMap() @@ -60,7 +60,7 @@ func (l linkAdminRolePermission) As(alias string) *linkAdminRolePermission { func (l *linkAdminRolePermission) updateTableName(table string) *linkAdminRolePermission { l.ALL = field.NewAsterisk(table) l.ID = field.NewInt32(table, "id") - l.RoleID = field.NewInt32(table, "role_id") + l.RoleID = field.NewInt32(table, "admin_role_id") l.PermissionID = field.NewInt32(table, "permission_id") l.fillFieldMap() @@ -80,7 +80,7 @@ func (l *linkAdminRolePermission) GetFieldByName(fieldName string) (field.OrderE func (l *linkAdminRolePermission) fillFieldMap() { l.fieldMap = make(map[string]field.Expr, 3) l.fieldMap["id"] = l.ID - l.fieldMap["role_id"] = l.RoleID + l.fieldMap["admin_role_id"] = l.RoleID l.fieldMap["permission_id"] = l.PermissionID } diff --git a/web/queries/link_user_role.gen.go b/web/queries/link_user_role.gen.go index 8dafde4..429b249 100644 --- a/web/queries/link_user_role.gen.go +++ b/web/queries/link_user_role.gen.go @@ -29,7 +29,7 @@ func newLinkUserRole(db *gorm.DB, opts ...gen.DOOption) linkUserRole { _linkUserRole.ALL = field.NewAsterisk(tableName) _linkUserRole.ID = field.NewInt32(tableName, "id") _linkUserRole.UserID = field.NewInt32(tableName, "user_id") - _linkUserRole.RoleID = field.NewInt32(tableName, "role_id") + _linkUserRole.RoleID = field.NewInt32(tableName, "user_role_id") _linkUserRole.fillFieldMap() @@ -61,7 +61,7 @@ func (l *linkUserRole) updateTableName(table string) *linkUserRole { l.ALL = field.NewAsterisk(table) l.ID = field.NewInt32(table, "id") l.UserID = field.NewInt32(table, "user_id") - l.RoleID = field.NewInt32(table, "role_id") + l.RoleID = field.NewInt32(table, "user_role_id") l.fillFieldMap() @@ -81,7 +81,7 @@ func (l *linkUserRole) fillFieldMap() { l.fieldMap = make(map[string]field.Expr, 3) l.fieldMap["id"] = l.ID l.fieldMap["user_id"] = l.UserID - l.fieldMap["role_id"] = l.RoleID + l.fieldMap["user_role_id"] = l.RoleID } func (l linkUserRole) clone(db *gorm.DB) linkUserRole { diff --git a/web/queries/link_user_role_permission.gen.go b/web/queries/link_user_role_permission.gen.go index 457b28c..2be8fc7 100644 --- a/web/queries/link_user_role_permission.gen.go +++ b/web/queries/link_user_role_permission.gen.go @@ -28,7 +28,7 @@ func newLinkUserRolePermission(db *gorm.DB, opts ...gen.DOOption) linkUserRolePe tableName := _linkUserRolePermission.linkUserRolePermissionDo.TableName() _linkUserRolePermission.ALL = field.NewAsterisk(tableName) _linkUserRolePermission.ID = field.NewInt32(tableName, "id") - _linkUserRolePermission.RoleID = field.NewInt32(tableName, "role_id") + _linkUserRolePermission.RoleID = field.NewInt32(tableName, "user_role_id") _linkUserRolePermission.PermissionID = field.NewInt32(tableName, "permission_id") _linkUserRolePermission.fillFieldMap() @@ -60,7 +60,7 @@ func (l linkUserRolePermission) As(alias string) *linkUserRolePermission { func (l *linkUserRolePermission) updateTableName(table string) *linkUserRolePermission { l.ALL = field.NewAsterisk(table) l.ID = field.NewInt32(table, "id") - l.RoleID = field.NewInt32(table, "role_id") + l.RoleID = field.NewInt32(table, "user_role_id") l.PermissionID = field.NewInt32(table, "permission_id") l.fillFieldMap() @@ -80,7 +80,7 @@ func (l *linkUserRolePermission) GetFieldByName(fieldName string) (field.OrderEx func (l *linkUserRolePermission) fillFieldMap() { l.fieldMap = make(map[string]field.Expr, 3) l.fieldMap["id"] = l.ID - l.fieldMap["role_id"] = l.RoleID + l.fieldMap["user_role_id"] = l.RoleID l.fieldMap["permission_id"] = l.PermissionID } diff --git a/web/queries/logs_login.gen.go b/web/queries/logs_login.gen.go index 0cf8fb3..1df7645 100644 --- a/web/queries/logs_login.gen.go +++ b/web/queries/logs_login.gen.go @@ -41,8 +41,68 @@ func newLogsLogin(db *gorm.DB, opts ...gen.DOOption) logsLogin { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -136,6 +196,24 @@ type logsLoginBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/logs_request.gen.go b/web/queries/logs_request.gen.go index 0d2660e..9fb6566 100644 --- a/web/queries/logs_request.gen.go +++ b/web/queries/logs_request.gen.go @@ -42,6 +42,27 @@ func newLogsRequest(db *gorm.DB, opts ...gen.DOOption) logsRequest { db: db.Session(&gorm.Session{}), RelationField: field.NewRelation("Client", "models.Client"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("Client.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Client.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Client.Permissions.Children", "models.Permission"), + }, + }, } _logsRequest.User = logsRequestBelongsToUser{ @@ -50,8 +71,40 @@ func newLogsRequest(db *gorm.DB, opts ...gen.DOOption) logsRequest { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -156,6 +209,16 @@ type logsRequestHasOneClient struct { db *gorm.DB field.RelationField + + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } } func (a logsRequestHasOneClient) Where(conds ...field.Expr) *logsRequestHasOneClient { @@ -240,6 +303,18 @@ type logsRequestBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/product_sku_user.gen.go b/web/queries/product_sku_user.gen.go index f3b177e..2734b88 100644 --- a/web/queries/product_sku_user.gen.go +++ b/web/queries/product_sku_user.gen.go @@ -40,8 +40,68 @@ func newProductSkuUser(db *gorm.DB, opts ...gen.DOOption) productSkuUser { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -148,6 +208,24 @@ type productSkuUserBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/proxy.gen.go b/web/queries/proxy.gen.go index bb61cfc..d5de9ea 100644 --- a/web/queries/proxy.gen.go +++ b/web/queries/proxy.gen.go @@ -47,13 +47,91 @@ func newProxy(db *gorm.DB, opts ...gen.DOOption) proxy { field.RelationField Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } }{ RelationField: field.NewRelation("Channels.User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("Channels.User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("Channels.User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("Channels.User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Channels.User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Channels.User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("Channels.User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Channels.User.Roles.Permissions", "models.Permission"), + }, }, }, Resource: struct { @@ -209,6 +287,24 @@ type proxyHasManyChannels struct { field.RelationField Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } Resource struct { diff --git a/web/queries/resource.gen.go b/web/queries/resource.gen.go index 7885336..c4ae5c9 100644 --- a/web/queries/resource.gen.go +++ b/web/queries/resource.gen.go @@ -53,8 +53,68 @@ func newResource(db *gorm.DB, opts ...gen.DOOption) resource { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -320,6 +380,24 @@ type resourceBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } diff --git a/web/queries/session.gen.go b/web/queries/session.gen.go index 502d535..2d30bb8 100644 --- a/web/queries/session.gen.go +++ b/web/queries/session.gen.go @@ -47,8 +47,68 @@ func newSession(db *gorm.DB, opts ...gen.DOOption) session { RelationField: field.NewRelation("User", "models.User"), Admin: struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } }{ RelationField: field.NewRelation("User.Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + }, + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("User.Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"), + }, }, } @@ -62,6 +122,11 @@ func newSession(db *gorm.DB, opts ...gen.DOOption) session { db: db.Session(&gorm.Session{}), RelationField: field.NewRelation("Client", "models.Client"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Client.Permissions", "models.Permission"), + }, } _session.fillFieldMap() @@ -182,6 +247,24 @@ type sessionBelongsToUser struct { Admin struct { field.RelationField + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } + } + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + } } } @@ -345,6 +428,10 @@ type sessionBelongsToClient struct { db *gorm.DB field.RelationField + + Permissions struct { + field.RelationField + } } func (a sessionBelongsToClient) Where(conds ...field.Expr) *sessionBelongsToClient { diff --git a/web/queries/user.gen.go b/web/queries/user.gen.go index 90c50e0..72cf349 100644 --- a/web/queries/user.gen.go +++ b/web/queries/user.gen.go @@ -52,6 +52,52 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user { db: db.Session(&gorm.Session{}), RelationField: field.NewRelation("Admin", "models.Admin"), + Roles: struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("Admin.Roles", "models.AdminRole"), + Permissions: struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("Admin.Roles.Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Admin.Roles.Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Admin.Roles.Permissions.Children", "models.Permission"), + }, + }, + }, + } + + _user.Roles = userManyToManyRoles{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Roles", "models.UserRole"), + Permissions: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Roles.Permissions", "models.Permission"), + }, } _user.fillFieldMap() @@ -86,6 +132,8 @@ type user struct { LastLoginUA field.String Admin userBelongsToAdmin + Roles userManyToManyRoles + fieldMap map[string]field.Expr } @@ -138,7 +186,7 @@ func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (u *user) fillFieldMap() { - u.fieldMap = make(map[string]field.Expr, 22) + u.fieldMap = make(map[string]field.Expr, 23) u.fieldMap["id"] = u.ID u.fieldMap["created_at"] = u.CreatedAt u.fieldMap["updated_at"] = u.UpdatedAt @@ -167,12 +215,15 @@ func (u user) clone(db *gorm.DB) user { u.userDo.ReplaceConnPool(db.Statement.ConnPool) u.Admin.db = db.Session(&gorm.Session{Initialized: true}) u.Admin.db.Statement.ConnPool = db.Statement.ConnPool + u.Roles.db = db.Session(&gorm.Session{Initialized: true}) + u.Roles.db.Statement.ConnPool = db.Statement.ConnPool return u } func (u user) replaceDB(db *gorm.DB) user { u.userDo.ReplaceDB(db) u.Admin.db = db.Session(&gorm.Session{}) + u.Roles.db = db.Session(&gorm.Session{}) return u } @@ -180,6 +231,19 @@ type userBelongsToAdmin struct { db *gorm.DB field.RelationField + + Roles struct { + field.RelationField + Permissions struct { + field.RelationField + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } + } + } } func (a userBelongsToAdmin) Where(conds ...field.Expr) *userBelongsToAdmin { @@ -257,6 +321,91 @@ func (a userBelongsToAdminTx) Unscoped() *userBelongsToAdminTx { return &a } +type userManyToManyRoles struct { + db *gorm.DB + + field.RelationField + + Permissions struct { + field.RelationField + } +} + +func (a userManyToManyRoles) Where(conds ...field.Expr) *userManyToManyRoles { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a userManyToManyRoles) WithContext(ctx context.Context) *userManyToManyRoles { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a userManyToManyRoles) Session(session *gorm.Session) *userManyToManyRoles { + a.db = a.db.Session(session) + return &a +} + +func (a userManyToManyRoles) Model(m *models.User) *userManyToManyRolesTx { + return &userManyToManyRolesTx{a.db.Model(m).Association(a.Name())} +} + +func (a userManyToManyRoles) Unscoped() *userManyToManyRoles { + a.db = a.db.Unscoped() + return &a +} + +type userManyToManyRolesTx struct{ tx *gorm.Association } + +func (a userManyToManyRolesTx) Find() (result []*models.UserRole, err error) { + return result, a.tx.Find(&result) +} + +func (a userManyToManyRolesTx) Append(values ...*models.UserRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a userManyToManyRolesTx) Replace(values ...*models.UserRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a userManyToManyRolesTx) Delete(values ...*models.UserRole) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a userManyToManyRolesTx) Clear() error { + return a.tx.Clear() +} + +func (a userManyToManyRolesTx) Count() int64 { + return a.tx.Count() +} + +func (a userManyToManyRolesTx) Unscoped() *userManyToManyRolesTx { + a.tx = a.tx.Unscoped() + return &a +} + type userDo struct{ gen.DO } func (u userDo) Debug() *userDo { diff --git a/web/queries/user_role.gen.go b/web/queries/user_role.gen.go index cbeaeec..47d5149 100644 --- a/web/queries/user_role.gen.go +++ b/web/queries/user_role.gen.go @@ -35,6 +35,21 @@ func newUserRole(db *gorm.DB, opts ...gen.DOOption) userRole { _userRole.Description = field.NewString(tableName, "description") _userRole.Active = field.NewBool(tableName, "active") _userRole.Sort = field.NewInt32(tableName, "sort") + _userRole.Permissions = userRoleManyToManyPermissions{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Permissions", "models.Permission"), + Parent: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Parent", "models.Permission"), + }, + Children: struct { + field.RelationField + }{ + RelationField: field.NewRelation("Permissions.Children", "models.Permission"), + }, + } _userRole.fillFieldMap() @@ -53,6 +68,7 @@ type userRole struct { Description field.String Active field.Bool Sort field.Int32 + Permissions userRoleManyToManyPermissions fieldMap map[string]field.Expr } @@ -93,7 +109,7 @@ func (u *userRole) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (u *userRole) fillFieldMap() { - u.fieldMap = make(map[string]field.Expr, 8) + u.fieldMap = make(map[string]field.Expr, 9) u.fieldMap["id"] = u.ID u.fieldMap["created_at"] = u.CreatedAt u.fieldMap["updated_at"] = u.UpdatedAt @@ -102,18 +118,110 @@ func (u *userRole) fillFieldMap() { u.fieldMap["description"] = u.Description u.fieldMap["active"] = u.Active u.fieldMap["sort"] = u.Sort + } func (u userRole) clone(db *gorm.DB) userRole { u.userRoleDo.ReplaceConnPool(db.Statement.ConnPool) + u.Permissions.db = db.Session(&gorm.Session{Initialized: true}) + u.Permissions.db.Statement.ConnPool = db.Statement.ConnPool return u } func (u userRole) replaceDB(db *gorm.DB) userRole { u.userRoleDo.ReplaceDB(db) + u.Permissions.db = db.Session(&gorm.Session{}) return u } +type userRoleManyToManyPermissions struct { + db *gorm.DB + + field.RelationField + + Parent struct { + field.RelationField + } + Children struct { + field.RelationField + } +} + +func (a userRoleManyToManyPermissions) Where(conds ...field.Expr) *userRoleManyToManyPermissions { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a userRoleManyToManyPermissions) WithContext(ctx context.Context) *userRoleManyToManyPermissions { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a userRoleManyToManyPermissions) Session(session *gorm.Session) *userRoleManyToManyPermissions { + a.db = a.db.Session(session) + return &a +} + +func (a userRoleManyToManyPermissions) Model(m *models.UserRole) *userRoleManyToManyPermissionsTx { + return &userRoleManyToManyPermissionsTx{a.db.Model(m).Association(a.Name())} +} + +func (a userRoleManyToManyPermissions) Unscoped() *userRoleManyToManyPermissions { + a.db = a.db.Unscoped() + return &a +} + +type userRoleManyToManyPermissionsTx struct{ tx *gorm.Association } + +func (a userRoleManyToManyPermissionsTx) Find() (result []*models.Permission, err error) { + return result, a.tx.Find(&result) +} + +func (a userRoleManyToManyPermissionsTx) Append(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a userRoleManyToManyPermissionsTx) Replace(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a userRoleManyToManyPermissionsTx) Delete(values ...*models.Permission) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a userRoleManyToManyPermissionsTx) Clear() error { + return a.tx.Clear() +} + +func (a userRoleManyToManyPermissionsTx) Count() int64 { + return a.tx.Count() +} + +func (a userRoleManyToManyPermissionsTx) Unscoped() *userRoleManyToManyPermissionsTx { + a.tx = a.tx.Unscoped() + return &a +} + type userRoleDo struct{ gen.DO } func (u userRoleDo) Debug() *userRoleDo { diff --git a/web/routes.go b/web/routes.go index 85f8bd4..a869637 100644 --- a/web/routes.go +++ b/web/routes.go @@ -107,6 +107,26 @@ func userRouter(api fiber.Router) { func adminRouter(api fiber.Router) { api = api.Group("/admin") + // permission 权限 + var permission = api.Group("/permission") + permission.Post("/list", handlers.ListPermissionsByAdmin) + permission.Post("/page", handlers.PagePermissionByAdmin) + + // admin-role 管理员角色 + var adminRole = api.Group("/admin-role") + adminRole.Post("/list", handlers.ListAdminRolesByAdmin) + adminRole.Post("/page", handlers.PageAdminRolesByAdmin) + adminRole.Post("/create", handlers.CreateAdminRole) + adminRole.Post("/update", handlers.UpdateAdminRole) + adminRole.Post("/remove", handlers.RemoveAdminRole) + + // admins 管理员账户 + var admins = api.Group("/admin") + admins.Post("/page", handlers.PageAdminsByAdmin) + admins.Post("/create", handlers.CreateAdmin) + admins.Post("/update", handlers.UpdateAdmin) + admins.Post("/remove", handlers.RemoveAdmin) + // user 用户 var user = api.Group("/user") user.Post("/page", handlers.PageUserByAdmin) diff --git a/web/services/admin.go b/web/services/admin.go new file mode 100644 index 0000000..07e93ad --- /dev/null +++ b/web/services/admin.go @@ -0,0 +1,151 @@ +package services + +import ( + "platform/pkg/u" + "platform/web/core" + m "platform/web/models" + q "platform/web/queries" + + "golang.org/x/crypto/bcrypt" + "gorm.io/gen/field" +) + +var Admin = &adminService{} + +type adminService struct{} + +func (s *adminService) PageAdmins(req core.PageReq) (result []*m.Admin, count int64, err error) { + return q.Admin. + Preload(q.Admin.Roles). + Omit(q.Admin.Password). + Order(q.Admin.CreatedAt.Desc()). + FindByPage(req.GetOffset(), req.GetLimit()) +} + +type CreateAdmin struct { + Username string `json:"username" validate:"required,min=3,max=50"` + Password string `json:"password" validate:"required,min=6,max=50"` + Name *string `json:"name"` + Avatar *string `json:"avatar"` + Phone *string `json:"phone"` + Email *string `json:"email"` + Status *m.AdminStatus `json:"status"` + Roles []int32 `json:"roles"` +} + +func (s *adminService) CreateAdmin(create *CreateAdmin) error { + // 哈希密码 + hash, err := bcrypt.GenerateFromPassword([]byte(create.Password), bcrypt.DefaultCost) + if err != nil { + return core.NewServErr("密码加密失败", err) + } + + return q.Q.Transaction(func(tx *q.Query) error { + // 创建管理员 + admin := &m.Admin{ + Username: create.Username, + Password: string(hash), + Name: create.Name, + Avatar: create.Avatar, + Phone: create.Phone, + Email: create.Email, + Status: u.Else(create.Status, m.AdminStatusEnabled), + } + if err := tx.Admin.Create(admin); err != nil { + return err + } + + // 关联角色 + if len(create.Roles) > 0 { + links := make([]*m.LinkAdminRole, len(create.Roles)) + for i, roleID := range create.Roles { + links[i] = &m.LinkAdminRole{ + AdminID: admin.ID, + RoleID: roleID, + } + } + if err := tx.LinkAdminRole.CreateInBatches(links, 1000); err != nil { + return err + } + } + + return nil + }) +} + +type UpdateAdmin struct { + Id int32 `json:"id" validate:"required"` + Password *string `json:"password"` + Name *string `json:"name"` + Avatar *string `json:"avatar"` + Phone *string `json:"phone"` + Email *string `json:"email"` + Status *m.AdminStatus `json:"status"` + Roles *[]int32 `json:"roles"` +} + +func (s *adminService) UpdateAdmin(update *UpdateAdmin) error { + simples := make([]field.AssignExpr, 0) + + if update.Password != nil { + hash, err := bcrypt.GenerateFromPassword([]byte(*update.Password), bcrypt.DefaultCost) + if err != nil { + return core.NewServErr("密码加密失败", err) + } + simples = append(simples, q.Admin.Password.Value(string(hash))) + } + if update.Name != nil { + simples = append(simples, q.Admin.Name.Value(*update.Name)) + } + if update.Avatar != nil { + simples = append(simples, q.Admin.Avatar.Value(*update.Avatar)) + } + if update.Phone != nil { + simples = append(simples, q.Admin.Phone.Value(*update.Phone)) + } + if update.Email != nil { + simples = append(simples, q.Admin.Email.Value(*update.Email)) + } + if update.Status != nil { + simples = append(simples, q.Admin.Status.Value(int(*update.Status))) + } + + return q.Q.Transaction(func(tx *q.Query) error { + // 更新管理员基本信息 + if len(simples) > 0 { + _, err := tx.Admin. + Where(tx.Admin.ID.Eq(update.Id)). + UpdateSimple(simples...) + if err != nil { + return err + } + } + + // 更新角色关联 + if update.Roles != nil { + roles := *update.Roles + if _, err := tx.LinkAdminRole.Where(tx.LinkAdminRole.AdminID.Eq(update.Id)).Delete(); err != nil { + return err + } + if len(roles) > 0 { + links := make([]*m.LinkAdminRole, len(roles)) + for i, roleID := range roles { + links[i] = &m.LinkAdminRole{ + AdminID: update.Id, + RoleID: roleID, + } + } + if err := tx.LinkAdminRole.CreateInBatches(links, 1000); err != nil { + return err + } + } + } + + return nil + }) +} + +func (s *adminService) RemoveAdmin(id int32) error { + _, err := q.Admin.Where(q.Admin.ID.Eq(id)).Delete() + return err +} diff --git a/web/services/admin_role.go b/web/services/admin_role.go new file mode 100644 index 0000000..77e4bfd --- /dev/null +++ b/web/services/admin_role.go @@ -0,0 +1,143 @@ +package services + +import ( + "platform/pkg/u" + "platform/web/core" + g "platform/web/globals" + "platform/web/models" + m "platform/web/models" + q "platform/web/queries" + + "gorm.io/gen/field" +) + +var AdminRole = &adminRoleService{} + +type adminRoleService struct{} + +func (r *adminRoleService) ListRoles() (result []*m.AdminRole, err error) { + return q.AdminRole. + Order(q.AdminRole.Sort.Asc(), q.AdminRole.CreatedAt.Desc()). + Find() +} + +func (r *adminRoleService) PageRoles(req core.PageReq) (result []*m.AdminRole, count int64, err error) { + return q.AdminRole. + Preload(q.AdminRole.Permissions). + Order(q.AdminRole.Sort.Asc(), q.AdminRole.CreatedAt.Desc()). + FindByPage(req.GetOffset(), req.GetLimit()) +} + +func (r *adminRoleService) CreateAdminRole(create *CreateAdminRole) error { + return q.Q.Transaction(func(q *q.Query) error { + + // 创建角色 + role := &m.AdminRole{ + Name: create.Name, + Description: create.Description, + Active: u.Else(create.Active, true), + Sort: u.Else(create.Sort, 0), + } + if err := q.AdminRole.Create(role); err != nil { + return err + } + + // 替换权限 + permissions := make([]*models.LinkAdminRolePermission, 0, len(create.Permissions)) + for _, permissionID := range create.Permissions { + permissions = append(permissions, &models.LinkAdminRolePermission{ + RoleID: role.ID, + PermissionID: permissionID, + }) + } + if len(permissions) > 0 { + err := g.Redsync.WithLock(AdminRoleModifyLock, func() error { + return q.LinkAdminRolePermission.CreateInBatches(permissions, 1000) + }) + if err != nil { + return err + } + } + + return nil + }) +} + +type CreateAdminRole struct { + Name string `json:"name"` + Description *string `json:"description"` + Active *bool `json:"active"` + Sort *int32 `json:"sort"` + Permissions []int32 `json:"permissions"` +} + +func (r *adminRoleService) UpdateAdminRole(update *UpdateAdminRole) error { + + var simples = make([]field.AssignExpr, 0) + if update.Name != nil { + simples = append(simples, q.AdminRole.Name.Value(*update.Name)) + } + if update.Description != nil { + simples = append(simples, q.AdminRole.Description.Value(*update.Description)) + } + if update.Active != nil { + simples = append(simples, q.AdminRole.Active.Value(*update.Active)) + } + if update.Sort != nil { + simples = append(simples, q.AdminRole.Sort.Value(*update.Sort)) + } + + err := q.Q.Transaction(func(q *q.Query) error { + + // 修改角色 + _, err := q.AdminRole. + Where(q.AdminRole.ID.Eq(update.Id)). + UpdateSimple(simples...) + if err != nil { + return err + } + + // 修改角色关联权限 + if update.Permissions != nil { + updatePermissions := *update.Permissions + permissions := make([]*models.LinkAdminRolePermission, len(updatePermissions)) + for i, permissionID := range updatePermissions { + permissions[i] = &models.LinkAdminRolePermission{ + RoleID: update.Id, + PermissionID: permissionID, + } + } + err = g.Redsync.WithLock(AdminRoleModifyLock, func() error { + if _, err := q.LinkAdminRolePermission.Where(q.LinkAdminRolePermission.RoleID.Eq(update.Id)).Delete(); err != nil { + return err + } + if err = q.LinkAdminRolePermission.CreateInBatches(permissions, 1000); err != nil { + return err + } + return nil + }) + if err != nil { + return err + } + } + + return nil + }) + return err +} + +type UpdateAdminRole struct { + Id int32 `json:"id"` + Name *string `json:"name"` + Description *string `json:"description"` + Active *bool `json:"active"` + Sort *int32 `json:"sort"` + Permissions *[]int32 `json:"permissions"` +} + +func (r *adminRoleService) RemoveAdminRole(id int32) error { + _, err := q.AdminRole.Where(q.AdminRole.ID.Eq(id)).Delete() + return err +} + +var AdminRoleModifyLock = "platform:admin_role_permissions:modify" diff --git a/web/services/channel_baiyin.go b/web/services/channel_baiyin.go index d812268..36f04be 100644 --- a/web/services/channel_baiyin.go +++ b/web/services/channel_baiyin.go @@ -174,7 +174,7 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int ) case isLongType: - rs, err = q.ResourceLong.Debug(). + rs, err = q.ResourceLong. Where( q.ResourceLong.ID.Eq(*resource.LongId), q.ResourceLong.Used.Eq(resource.Used), diff --git a/web/services/permission.go b/web/services/permission.go new file mode 100644 index 0000000..83c6ec0 --- /dev/null +++ b/web/services/permission.go @@ -0,0 +1,19 @@ +package services + +import ( + "platform/web/core" + m "platform/web/models" + q "platform/web/queries" +) + +var Permission = &permissionService{} + +type permissionService struct{} + +func (r *permissionService) ListPermissions() (result []*m.Permission, err error) { + return q.Permission.Find() +} + +func (p *permissionService) PagePermissions(req core.PageReq) (result []*m.Permission, count int64, err error) { + return q.Permission.FindByPage(req.GetOffset(), req.GetLimit()) +}