diff --git a/api/api.go b/api/api.go index 888a2e6..1c4c7e5 100644 --- a/api/api.go +++ b/api/api.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "github.com/veypi/OneAuth/api/app" + "github.com/veypi/OneAuth/api/auth" "github.com/veypi/OneAuth/api/resource" "github.com/veypi/OneAuth/api/role" "github.com/veypi/OneAuth/api/token" @@ -41,6 +42,7 @@ func Router(r OneBD.Router) { app.Router(r.SubRouter("app")) appRouter := r.SubRouter("/app/:uuid") role.Router(appRouter.SubRouter("role")) + auth.Router(appRouter.SubRouter("auth")) resource.Router(appRouter.SubRouter("resource")) token.Router(appRouter.SubRouter("token")) diff --git a/api/app/app.go b/api/app/app.go index 47cf429..4f2a3ce 100644 --- a/api/app/app.go +++ b/api/app/app.go @@ -5,13 +5,12 @@ import ( "github.com/veypi/OneAuth/libs/auth" "github.com/veypi/OneAuth/libs/base" "github.com/veypi/OneAuth/libs/oerr" + "github.com/veypi/OneAuth/libs/tools" "github.com/veypi/OneAuth/models" "github.com/veypi/OneBD" "github.com/veypi/OneBD/rfc" "github.com/veypi/utils" - "github.com/veypi/utils/log" "gorm.io/gorm" - "reflect" ) var appHandlerP = OneBD.NewHandlerPool(func() OneBD.Handler { @@ -120,22 +119,6 @@ func (h *appHandler) Post() (interface{}, error) { return a, nil } -func Struct2Map(obj interface{}) (data map[string]interface{}) { - data = make(map[string]interface{}) - objT := reflect.TypeOf(obj) - objV := reflect.ValueOf(obj) - var item reflect.Value - var k reflect.StructField - for i := 0; i < objT.NumField(); i++ { - k = objT.Field(i) - item = objV.Field(i) - if !item.IsNil() { - data[k.Name] = item.Interface() - } - } - return -} - func (h *appHandler) Patch() (interface{}, error) { uid := h.Meta().Params("uuid") if uid == "" || !h.Payload.GetAuth(auth.APP, uid).CanUpdate() { @@ -152,8 +135,7 @@ func (h *appHandler) Patch() (interface{}, error) { if err := h.Meta().ReadJson(&opts); err != nil { return nil, err } - query := Struct2Map(opts) - log.Warn().Msgf("%#v", query) + query := tools.Struct2Map(opts) if len(query) == 0 { return nil, nil } diff --git a/api/auth/auth.go b/api/auth/auth.go new file mode 100644 index 0000000..eeb9433 --- /dev/null +++ b/api/auth/auth.go @@ -0,0 +1,140 @@ +package auth + +import ( + "github.com/veypi/OneAuth/cfg" + "github.com/veypi/OneAuth/libs/auth" + "github.com/veypi/OneAuth/libs/base" + "github.com/veypi/OneAuth/libs/oerr" + "github.com/veypi/OneAuth/models" + "github.com/veypi/OneAuth/oalib" + "github.com/veypi/OneBD" + "github.com/veypi/OneBD/core" + "strconv" +) + +var authP = OneBD.NewHandlerPool(func() core.Handler { + return &authHandler{} +}) + +type authHandler struct { + base.AppHandler +} + +func (h *authHandler) Get() (interface{}, error) { + if !h.GetAuth(auth.Auth, h.UUID).CanRead() { + return nil, oerr.NoAuth + } + var err error + id, _ := strconv.Atoi(h.Meta().Query("rid")) + rid := uint(id) + id, _ = strconv.Atoi(h.Meta().Query("uid")) + uid := uint(id) + if rid == 0 && uid == 0 { + return nil, err + } + query := &models.Auth{ + AppUUID: h.UUID, + } + if rid != 0 { + query.RoleID = &rid + } else if uid != 0 { + query.UserID = &uid + } + l := make([]*models.Auth, 0, 10) + err = cfg.DB().Where(query).Find(&l).Error + return l, err +} + +func (h *authHandler) Post() (interface{}, error) { + if !h.GetAuth(auth.Auth, h.UUID).CanCreate() { + return nil, oerr.NoAuth + } + query := &models.Auth{} + err := h.Meta().ReadJson(query) + if err != nil { + return nil, err + } + if query.ResourceID == 0 { + return nil, oerr.ApiArgsError + } + query.AppUUID = h.UUID + res := &models.Resource{} + res.ID = query.ResourceID + err = cfg.DB().First(res).Error + if err != nil { + return nil, err + } + query.RID = res.Name + err = cfg.DB().Create(query).Error + return query, err +} + +func (h *authHandler) Patch() (interface{}, error) { + if !h.GetAuth(auth.Auth, h.UUID).CanUpdate() { + return nil, oerr.NoAuth + } + id := h.Meta().ParamsInt("id") + if id <= 0 { + return nil, oerr.ApiArgsError + } + a := &models.Auth{} + a.ID = uint(id) + err := cfg.DB().First(a).Error + if err != nil { + return nil, err + } + opts := struct { + ResourceID *uint `gorm:"not null"` + RUID *string + Level *oalib.AuthLevel + }{} + err = h.Meta().ReadJson(&opts) + if err != nil { + return nil, err + } + if a.AppUUID != h.UUID { + return nil, oerr.ApiArgsError + } + query := map[string]interface{}{} + if opts.ResourceID != nil && a.ResourceID != *opts.ResourceID { + query["ResourceID"] = *opts.ResourceID + res := &models.Resource{} + res.ID = *opts.ResourceID + err = cfg.DB().First(res).Error + if err != nil { + return nil, err + } + query["RID"] = res.Name + a.ResourceID = *opts.ResourceID + } + if opts.RUID != nil { + query["RUID"] = *opts.RUID + a.RUID = *opts.RUID + } + if opts.Level != nil { + query["Level"] = *opts.Level + a.Level = *opts.Level + } + err = cfg.DB().Model(a).Where("id = ?", id).Updates(query).Error + return a, err +} + +func (h *authHandler) Delete() (interface{}, error) { + if !h.GetAuth(auth.Auth, h.UUID).CanDelete() { + return nil, oerr.NoAuth + } + id := h.Meta().ParamsInt("id") + if id <= 0 { + return nil, oerr.ApiArgsError + } + a := &models.Auth{} + a.ID = uint(id) + err := cfg.DB().First(a).Error + if err != nil { + return nil, err + } + if a.AppUUID != h.UUID { + return nil, oerr.ApiArgsError + } + return nil, cfg.DB().Delete(a).Error +} diff --git a/api/auth/router.go b/api/auth/router.go new file mode 100644 index 0000000..0d2aae7 --- /dev/null +++ b/api/auth/router.go @@ -0,0 +1,11 @@ +package auth + +import ( + "github.com/veypi/OneBD" + "github.com/veypi/OneBD/rfc" +) + +func Router(r OneBD.Router) { + r.Set("/", authP, rfc.MethodGet, rfc.MethodPost) + r.Set("/:id", authP, rfc.MethodPatch, rfc.MethodDelete) +} diff --git a/api/resource/resource.go b/api/resource/resource.go index 0f536a2..f6035c0 100644 --- a/api/resource/resource.go +++ b/api/resource/resource.go @@ -6,6 +6,7 @@ import ( "github.com/veypi/OneAuth/libs/auth" "github.com/veypi/OneAuth/libs/base" "github.com/veypi/OneAuth/libs/oerr" + "github.com/veypi/OneAuth/libs/tools" "github.com/veypi/OneAuth/models" "github.com/veypi/OneBD" ) @@ -55,6 +56,29 @@ func (h *resourceHandler) Post() (interface{}, error) { return res, err } +func (h *resourceHandler) Patch() (interface{}, error) { + if !h.GetAuth(auth.Res, h.UUID).CanUpdate() { + return nil, oerr.NoAuth + } + props := struct { + Des *string + }{} + err := h.Meta().ReadJson(&props) + if err != nil { + return nil, err + } + + query := tools.Struct2Map(props) + id := h.Meta().ParamsInt("id") + if len(query) == 0 || id <= 0 { + return nil, oerr.ApiArgsMissing + } + if err := cfg.DB().Table("Resources").Where("id = ?", id).Updates(query).Error; err != nil { + return nil, err + } + return nil, nil +} + func (h *resourceHandler) Delete() (interface{}, error) { if !h.GetAuth(auth.Res, h.UUID).CanDelete() { return nil, oerr.NoAuth diff --git a/api/resource/router.go b/api/resource/router.go index 5a5c1ca..2133d2c 100644 --- a/api/resource/router.go +++ b/api/resource/router.go @@ -13,5 +13,5 @@ import ( func Router(r OneBD.Router) { r.Set("/", resP, rfc.MethodGet, rfc.MethodPost) - r.Set("/:id", resP, rfc.MethodDelete) + r.Set("/:id", resP, rfc.MethodDelete, rfc.MethodPatch) } diff --git a/api/role/auth.go b/api/role/auth.go deleted file mode 100644 index fb758c4..0000000 --- a/api/role/auth.go +++ /dev/null @@ -1,60 +0,0 @@ -package role - -import ( - "github.com/veypi/OneAuth/cfg" - "github.com/veypi/OneAuth/libs/auth" - "github.com/veypi/OneAuth/libs/base" - "github.com/veypi/OneAuth/libs/oerr" - "github.com/veypi/OneAuth/models" - "github.com/veypi/OneAuth/oalib" - "github.com/veypi/OneBD" - "github.com/veypi/OneBD/core" - "strconv" -) - -var authP = OneBD.NewHandlerPool(func() core.Handler { - return &authHandler{} -}) - -type authHandler struct { - base.ApiHandler -} - -func (h *authHandler) Get() (interface{}, error) { - if !h.GetAuth(auth.Auth).CanRead() { - return nil, oerr.NoAuth - } - aid := h.Meta().ParamsInt("id") - query := &models.Auth{} - var err error - if aid > 0 { - err = cfg.DB().Where("ID = ?", aid).First(query).Error - return query, err - } - id, _ := strconv.Atoi(h.Meta().Query("id")) - uuid := h.Meta().Query("uuid") - if id == 0 || uuid == "" { - return nil, oerr.ApiArgsMissing - } - target := &models.App{} - err = cfg.DB().Where("UUID = ?", uuid).First(target).Error - if err != nil { - return nil, err - } - u := &models.User{} - err = cfg.DB().Preload("Roles.Auths").Preload("Auths").Where("ID = ?", id).First(u).Error - if err != nil { - return nil, err - } - l := make([]*oalib.SimpleAuth, 0, 10) - for _, as := range u.GetAuths() { - if as.AppUUID == uuid { - l = append(l, &oalib.SimpleAuth{ - RID: as.RID, - RUID: as.RUID, - Level: as.Level, - }) - } - } - return l, nil -} diff --git a/api/role/role.go b/api/role/role.go index 2993ac0..f9a302e 100644 --- a/api/role/role.go +++ b/api/role/role.go @@ -42,7 +42,9 @@ func (h *roleHandler) Post() (interface{}, error) { if !h.GetAuth(auth.Role).CanCreate() { return nil, oerr.NoAuth } - role := &models.Role{} + role := &models.Role{ + AppUUID: h.UUID, + } err := h.Meta().ReadJson(role) if err != nil { return nil, err diff --git a/api/role/roleAuth.go b/api/role/roleAuth.go deleted file mode 100644 index c9d3dfc..0000000 --- a/api/role/roleAuth.go +++ /dev/null @@ -1,42 +0,0 @@ -package role - -import ( - "github.com/veypi/OneAuth/libs/auth" - "github.com/veypi/OneAuth/libs/base" - "github.com/veypi/OneAuth/libs/oerr" - "github.com/veypi/OneBD" -) - -/** -* @name: roleAuth -* @author: veypi -* @date: 2021-11-17 15:20 -* @description:roleAuth -* @update: 2021-11-17 15:20 - */ - -var rap = OneBD.NewHandlerPool(func() OneBD.Handler { - return &roleAuthHandler{} -}) - -type roleAuthHandler struct { - base.AppHandler - id uint - aid uint -} - -func (h *roleAuthHandler) Init(m OneBD.Meta) error { - id := uint(m.ParamsInt("id")) - aid := uint(m.ParamsInt("aid")) - if id == 0 || aid == 0 { - return oerr.ApiArgsError - } - return h.ApiHandler.Init(m) -} - -func (h *roleAuthHandler) Post() (interface{}, error) { - if !h.Payload.GetAuth(auth.Auth, h.UUID).CanCreate() { - return nil, oerr.NoAuth - } - return nil, nil -} diff --git a/api/role/router.go b/api/role/router.go index ab42b8f..f07a454 100644 --- a/api/role/router.go +++ b/api/role/router.go @@ -9,6 +9,4 @@ func Router(r OneBD.Router) { r.Set("/", roleP, rfc.MethodGet, rfc.MethodPost) r.Set("/:id", roleP, rfc.MethodGet, rfc.MethodDelete, rfc.MethodPatch) r.Set("/:id/auth/:aid", roleP, rfc.MethodGet) - r.Set("/auth/", authP, rfc.MethodGet) - r.Set("/auth/:id", authP, rfc.MethodGet) } diff --git a/libs/tools/tools.go b/libs/tools/tools.go index 146dd9c..38275b2 100644 --- a/libs/tools/tools.go +++ b/libs/tools/tools.go @@ -5,6 +5,7 @@ import ( "github.com/veypi/OneBD" "net/http" "net/url" + "reflect" ) type Initer interface { @@ -42,3 +43,19 @@ func Query(addr string, query map[string]string, res interface{}) error { } return json.NewDecoder(resp.Body).Decode(res) } + +func Struct2Map(obj interface{}) (data map[string]interface{}) { + data = make(map[string]interface{}) + objT := reflect.TypeOf(obj) + objV := reflect.ValueOf(obj) + var item reflect.Value + var k reflect.StructField + for i := 0; i < objT.NumField(); i++ { + k = objT.Field(i) + item = objV.Field(i) + if !item.IsNil() { + data[k.Name] = item.Interface() + } + } + return +} diff --git a/models/app.go b/models/app.go index 298e5e2..c58fa99 100644 --- a/models/app.go +++ b/models/app.go @@ -1,12 +1,14 @@ package models +import "gorm.io/gorm" + var AppKeys = map[string]string{} type App struct { UUID string `gorm:"primaryKey;size:32"` CreatedAt JSONTime UpdatedAt JSONTime - DeletedAt *JSONTime `sql:"index"` + DeletedAt gorm.DeletedAt `gorm:"index"` Name string Icon string Des string diff --git a/models/init.go b/models/init.go index 3ebfd49..0ff9dc4 100644 --- a/models/init.go +++ b/models/init.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/veypi/OneAuth/cfg" + "gorm.io/gorm" "time" ) @@ -95,8 +96,8 @@ func (jt *JSONTime) SetTime(t time.Time) { } type BaseModel struct { - ID uint `gorm:"primaryKey"` - CreatedAt JSONTime `` - UpdatedAt JSONTime `` - DeletedAt *JSONTime `sql:"index"` + ID uint `gorm:"primaryKey"` + CreatedAt JSONTime `` + UpdatedAt JSONTime `` + DeletedAt gorm.DeletedAt `gorm:"index"` } diff --git a/models/role.go b/models/role.go index 26e05c4..95cca97 100644 --- a/models/role.go +++ b/models/role.go @@ -1,6 +1,8 @@ package models -import "github.com/veypi/OneAuth/oalib" +import ( + "github.com/veypi/OneAuth/oalib" +) type UserRole struct { BaseModel @@ -28,7 +30,7 @@ type Auth struct { AppUUID string `gorm:"size:32"` App *App `gorm:"association_foreignkey:UUID"` // 权限绑定只能绑定一个 - RoleID *uint `gorm:""` + RoleID *uint Role *Role UserID *uint User *User diff --git a/oaf/src/api/auth.ts b/oaf/src/api/auth.ts index 4d657b1..6b65318 100644 --- a/oaf/src/api/auth.ts +++ b/oaf/src/api/auth.ts @@ -8,8 +8,30 @@ export default (uuid: string) => { get(id: number) { return new Interface(ajax.get, this.local + id) }, - list(appUUID: string, user_id: number) { - return new Interface(ajax.get, this.local, {uuid: appUUID, id: user_id}) + del(id: number) { + return new Interface(ajax.delete, this.local + id) + }, + update(id: number, ResourceID: number, RUID: string, Level: number) { + return new Interface(ajax.patch, this.local + id, { + ResourceID, + RUID, + Level, + }) + }, + create(ResourceID: number, UserID: number | null, RoleID: number | null, RUID: string, Level: number) { + return new Interface(ajax.post, this.local, { + ResourceID, + UserID, + RoleID, + RUID, + Level, + }) + }, + listOfUser(user_id: number) { + return new Interface(ajax.get, this.local, {uid: user_id}) + }, + listOfRole(id: number) { + return new Interface(ajax.get, this.local, {rid: id}) }, } } diff --git a/oaf/src/api/resource.ts b/oaf/src/api/resource.ts index 9718b44..878553d 100644 --- a/oaf/src/api/resource.ts +++ b/oaf/src/api/resource.ts @@ -15,6 +15,9 @@ export default (uuid: string) => { list() { return new Interface(ajax.get, this.local) }, + update(id: number, props: {}) { + return new Interface(ajax.patch, this.local + id, props) + }, create(Name: string, Des: string) { return new Interface(ajax.post, this.local, {Name, Des}) }, diff --git a/oaf/src/api/role.ts b/oaf/src/api/role.ts index 13e6830..9aba9d2 100644 --- a/oaf/src/api/role.ts +++ b/oaf/src/api/role.ts @@ -4,17 +4,19 @@ import ajax from './ajax' export default (uuid: string) => { return { - local: BaseUrl +'app/' + uuid + '/role/', + local: BaseUrl + 'app/' + uuid + '/role/', get(id: number) { return new Interface(ajax.get, this.local + id) }, list() { return new Interface(ajax.get, this.local) }, - create(uuid: string, name: string) { + update(id: number, props) { + return new Interface(ajax.patch, this.local + id, props) + }, + create(Name: string, Tag: string) { return new Interface(ajax.post, this.local, { - uuid: uuid, - name: name, + Name,Tag }) }, bind(id: number, aid: number) { diff --git a/oaf/src/components/connectors/roleauths.vue b/oaf/src/components/connectors/roleauths.vue new file mode 100644 index 0000000..fba4405 --- /dev/null +++ b/oaf/src/components/connectors/roleauths.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/oaf/src/components/connectors/roleusers.vue b/oaf/src/components/connectors/roleusers.vue new file mode 100644 index 0000000..cbc8f2b --- /dev/null +++ b/oaf/src/components/connectors/roleusers.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/oaf/src/components/editor/resource.vue b/oaf/src/components/editor/resource.vue new file mode 100644 index 0000000..980685a --- /dev/null +++ b/oaf/src/components/editor/resource.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/oaf/src/components/editor/role.vue b/oaf/src/components/editor/role.vue new file mode 100644 index 0000000..066e885 --- /dev/null +++ b/oaf/src/components/editor/role.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/oaf/src/models/index.ts b/oaf/src/models/index.ts index fa365b6..839e619 100644 --- a/oaf/src/models/index.ts +++ b/oaf/src/models/index.ts @@ -66,6 +66,24 @@ export interface modelsSimpleAuth { RUID: string } +export interface modelsAuth { + App?: modelsApp + AppUUID: string + CreatedAt: string + DeletedAt: null + ID: number + Level: number + RID: string + RUID: string + Resource?: modelsResource + ResourceID: number + Role?: modelsRole + RoleID: number + UpdatedAt: string + User?: modelsUser + UserID?: number +} + export interface modelsRole { App?: modelsApp AppUUID: string diff --git a/oaf/src/views/app/roles.vue b/oaf/src/views/app/roles.vue index 0607a4b..fbc4da3 100644 --- a/oaf/src/views/app/roles.vue +++ b/oaf/src/views/app/roles.vue @@ -1,6 +1,14 @@ @@ -46,6 +34,9 @@ import {NButton, useMessage} from 'naive-ui' import {modelsBread, modelsResource, modelsRole} from '@/models' import {useStore} from '@/store' import {useRoute} from 'vue-router' +import EditorRes from '@/components/editor/resource.vue' +import EditorRole from '@/components/editor/role.vue' +import RoleAuths from '@/components/connectors/roleauths.vue' let store = useStore() let route = useRoute() @@ -66,15 +57,18 @@ const columns = [ h(NButton, { class: 'mr-1', size: 'small', - onClick: () => console.log(row), + onClick: () => { + raFlag.value = true + tmp.value = row + }, }, - {default: () => '查看权限'}), + {default: () => '权限'}), h(NButton, { class: 'mr-1', size: 'small', onClick: () => console.log(row), }, - {default: () => '查看用户'}, + {default: () => '用户'}, ), ] }, @@ -104,40 +98,37 @@ const resCols = [ { title: '操作', key: '', - width: 100, + width: 200, fixed: 'right', render(row, i) { - return h(NButton, { + return [h(NButton, { class: 'mr-1', size: 'small', onClick: () => { - api.resource(uuid.value).delete(row.ID).Start(e => { - resources.value.splice(i, 1) - msg.success('删除成功') - }) + trFlag.value = true + tmp.value = row }, - }, {default: () => '删除'}, - ) + }, {default: () => '编辑'}, + ), h(NButton, { + class: 'mr-1', + size: 'small', + onClick: () => { + api.resource(uuid.value).delete(row.ID).Start(e => { + resources.value.splice(i, 1) + msg.success('删除成功') + }) + }, + }, {default: () => '删除'}), + ] }, }, ] -let tmp_res = ref({ - index: -1, - Name: '', - Des: '', -}) -let tr_flag = ref(false) +let tmp = ref({}) +let trFlag = ref(false) +let roleFlag = ref(false) +let raFlag = ref(false) -function add_res() { - if (tmp_res.value.index >= 0) { - return - } - api.resource(uuid.value).create(tmp_res.value.Name, tmp_res.value.Des).Start(e => { - resources.value.push(e) - tr_flag.value = false - }) -}