diff --git a/api/permission_api/dto/request_dto.go b/api/permission_api/dto/request_dto.go index 4a2397b..a499d73 100644 --- a/api/permission_api/dto/request_dto.go +++ b/api/permission_api/dto/request_dto.go @@ -1,11 +1,17 @@ package dto -import "schisandra-cloud-album/model" +import ( + "schisandra-cloud-album/model" +) +// AddPermissionRequestDto 添加权限请求dto type AddPermissionRequestDto struct { - Permissions []model.ScaAuthPermission `json:"permissions"` + Permissions []model.ScaAuthPermission `form:"permissions[]" json:"permissions"` } + +// AddPermissionToRoleRequestDto 添加权限到角色请求dto type AddPermissionToRoleRequestDto struct { - RoleKey string `json:"role_key"` - Permissions []model.ScaAuthPermission `json:"permissions"` + RoleKey string `json:"role_key"` + Permission string `json:"permission"` + Method string `json:"method"` } diff --git a/api/permission_api/permission_api.go b/api/permission_api/permission_api.go index 78a8fba..714422f 100644 --- a/api/permission_api/permission_api.go +++ b/api/permission_api/permission_api.go @@ -21,8 +21,9 @@ var permissionService = service.Service.PermissionService // @Router /api/auth/permission/add [post] func (PermissionAPI) AddPermissions(c *gin.Context) { addPermissionRequestDto := dto.AddPermissionRequestDto{} - err := c.ShouldBindJSON(&addPermissionRequestDto) + err := c.ShouldBind(&addPermissionRequestDto.Permissions) if err != nil { + global.LOG.Error(err) return } err = permissionService.CreatePermissions(addPermissionRequestDto.Permissions) @@ -34,3 +35,36 @@ func (PermissionAPI) AddPermissions(c *gin.Context) { result.OkWithMessage(ginI18n.MustGetMessage(c, "CreatedSuccess"), c) return } + +// AssignPermissionsToRole 给指定角色分配权限 +// @Summary 给指定角色分配权限 +// @Description 给指定角色分配权限 +// @Tags 权限管理 +// @Accept json +// @Produce json +// @Param permissions body dto.AddPermissionToRoleRequestDto true "权限列表" +// @Router /api/auth/permission/assign [post] +func (PermissionAPI) AssignPermissionsToRole(c *gin.Context) { + permissionToRoleRequestDto := dto.AddPermissionToRoleRequestDto{} + + err := c.ShouldBind(&permissionToRoleRequestDto) + + if err != nil { + global.LOG.Error(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "AssignFailed"), c) + return + } + + policy, err := global.Casbin.AddPolicy(permissionToRoleRequestDto.RoleKey, permissionToRoleRequestDto.Permission, permissionToRoleRequestDto.Method) + if err != nil { + global.LOG.Error(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "AssignFailed"), c) + return + } + if policy == false { + result.FailWithMessage(ginI18n.MustGetMessage(c, "AssignFailed"), c) + return + } + result.OkWithMessage(ginI18n.MustGetMessage(c, "AssignSuccess"), c) + return +} diff --git a/api/user_api/user_api.go b/api/user_api/user_api.go index 0265bb4..c3ae0b2 100644 --- a/api/user_api/user_api.go +++ b/api/user_api/user_api.go @@ -429,6 +429,12 @@ func (UserAPI) ResetPassword(c *gin.Context) { // getUserLoginDevice 获取用户登录设备 func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { + + // 检查user.UID是否为空 + if user.UID == nil { + global.LOG.Errorln("user.UID is nil") + return false + } userAgent := c.GetHeader("User-Agent") if userAgent == "" { global.LOG.Errorln("user-agent is empty") @@ -438,11 +444,12 @@ func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { ip := utils.GetClientIP(c) location, err := global.IP2Location.SearchByStr(ip) - location = utils.RemoveZeroAndAdjust(location) if err != nil { global.LOG.Errorln(err) return false } + location = utils.RemoveZeroAndAdjust(location) + isBot := ua.Bot() browser, browserVersion := ua.Browser() os := ua.OS() @@ -451,6 +458,7 @@ func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { m := ua.Model() platform := ua.Platform() engine, engineVersion := ua.Engine() + device := model.ScaAuthUserDevice{ UserID: user.UID, IP: &ip, @@ -467,8 +475,10 @@ func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { EngineName: &engine, EngineVersion: &engineVersion, } + mu.Lock() defer mu.Unlock() + userDevice, err := userDeviceService.GetUserDeviceByUIDIPAgent(*user.UID, ip, userAgent) if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { err = userDeviceService.AddUserDevice(&device) @@ -476,12 +486,16 @@ func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { global.LOG.Errorln(err) return false } - return true + } else if err != nil { + global.LOG.Errorln(err) + return false } else { err := userDeviceService.UpdateUserDevice(userDevice.ID, &device) if err != nil { + global.LOG.Errorln(err) return false } - return true } + + return true } diff --git a/docs/docs.go b/docs/docs.go index 3541296..f7c6b54 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,6 +15,33 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/auth/permission/add": { + "post": { + "description": "批量添加权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限管理" + ], + "summary": "批量添加权限", + "parameters": [ + { + "description": "权限列表", + "name": "permissions", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddPermissionRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/role/add_role_to_user": { "post": { "description": "给指定用户添加角色", @@ -645,33 +672,6 @@ const docTemplate = `{ } } }, - "/api/user/add": { - "post": { - "tags": [ - "用户模块" - ], - "summary": "添加用户", - "parameters": [ - { - "description": "用户信息", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/api/user/login": { "post": { "tags": [ @@ -789,6 +789,17 @@ const docTemplate = `{ } } }, + "dto.AddPermissionRequestDto": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ScaAuthPermission" + } + } + } + }, "dto.AddRoleToUserRequestDto": { "type": "object", "properties": { @@ -800,20 +811,6 @@ const docTemplate = `{ } } }, - "dto.AddUserRequest": { - "type": "object", - "properties": { - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, "dto.PhoneLoginRequest": { "type": "object", "properties": { @@ -855,6 +852,75 @@ const docTemplate = `{ "type": "string" } } + }, + "model.ScaAuthPermission": { + "type": "object", + "properties": { + "created_by": { + "description": "创建人", + "type": "string" + }, + "created_time": { + "description": "创建时间", + "type": "string" + }, + "deleted": { + "description": "是否删除", + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "method": { + "description": "请求方式", + "type": "string" + }, + "order": { + "description": "排序", + "type": "integer" + }, + "parent_id": { + "description": "父ID", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "permission_key": { + "description": "权限关键字", + "type": "string" + }, + "permission_name": { + "description": "权限名称", + "type": "string" + }, + "remark": { + "description": "备注 描述", + "type": "string" + }, + "status": { + "description": "状态 0 启用 1 停用", + "type": "integer" + }, + "type": { + "description": "类型 0 菜单 1 目录 2 按钮 -1其他", + "type": "integer" + }, + "update_by": { + "description": "更新人", + "type": "string" + }, + "update_time": { + "description": "更新时间", + "type": "string" + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index 86545e6..3bdf03e 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4,6 +4,33 @@ "contact": {} }, "paths": { + "/api/auth/permission/add": { + "post": { + "description": "批量添加权限", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "权限管理" + ], + "summary": "批量添加权限", + "parameters": [ + { + "description": "权限列表", + "name": "permissions", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddPermissionRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/role/add_role_to_user": { "post": { "description": "给指定用户添加角色", @@ -634,33 +661,6 @@ } } }, - "/api/user/add": { - "post": { - "tags": [ - "用户模块" - ], - "summary": "添加用户", - "parameters": [ - { - "description": "用户信息", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/api/user/login": { "post": { "tags": [ @@ -778,6 +778,17 @@ } } }, + "dto.AddPermissionRequestDto": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ScaAuthPermission" + } + } + } + }, "dto.AddRoleToUserRequestDto": { "type": "object", "properties": { @@ -789,20 +800,6 @@ } } }, - "dto.AddUserRequest": { - "type": "object", - "properties": { - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, "dto.PhoneLoginRequest": { "type": "object", "properties": { @@ -844,6 +841,75 @@ "type": "string" } } + }, + "model.ScaAuthPermission": { + "type": "object", + "properties": { + "created_by": { + "description": "创建人", + "type": "string" + }, + "created_time": { + "description": "创建时间", + "type": "string" + }, + "deleted": { + "description": "是否删除", + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "method": { + "description": "请求方式", + "type": "string" + }, + "order": { + "description": "排序", + "type": "integer" + }, + "parent_id": { + "description": "父ID", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "permission_key": { + "description": "权限关键字", + "type": "string" + }, + "permission_name": { + "description": "权限名称", + "type": "string" + }, + "remark": { + "description": "备注 描述", + "type": "string" + }, + "status": { + "description": "状态 0 启用 1 停用", + "type": "integer" + }, + "type": { + "description": "类型 0 菜单 1 目录 2 按钮 -1其他", + "type": "integer" + }, + "update_by": { + "description": "更新人", + "type": "string" + }, + "update_time": { + "description": "更新时间", + "type": "string" + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 73ba8c5..e390756 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -8,6 +8,13 @@ definitions: password: type: string type: object + dto.AddPermissionRequestDto: + properties: + permissions: + items: + $ref: '#/definitions/model.ScaAuthPermission' + type: array + type: object dto.AddRoleToUserRequestDto: properties: role_key: @@ -15,15 +22,6 @@ definitions: uid: type: string type: object - dto.AddUserRequest: - properties: - password: - type: string - phone: - type: string - username: - type: string - type: object dto.PhoneLoginRequest: properties: auto_login: @@ -51,9 +49,78 @@ definitions: role_name: type: string type: object + model.ScaAuthPermission: + properties: + created_by: + description: 创建人 + type: string + created_time: + description: 创建时间 + type: string + deleted: + description: 是否删除 + type: integer + icon: + description: 图标 + type: string + id: + description: 主键ID + type: integer + method: + description: 请求方式 + type: string + order: + description: 排序 + type: integer + parent_id: + description: 父ID + type: integer + path: + description: 路径 + type: string + permission_key: + description: 权限关键字 + type: string + permission_name: + description: 权限名称 + type: string + remark: + description: 备注 描述 + type: string + status: + description: 状态 0 启用 1 停用 + type: integer + type: + description: 类型 0 菜单 1 目录 2 按钮 -1其他 + type: integer + update_by: + description: 更新人 + type: string + update_time: + description: 更新时间 + type: string + type: object info: contact: {} paths: + /api/auth/permission/add: + post: + consumes: + - application/json + description: 批量添加权限 + parameters: + - description: 权限列表 + in: body + name: permissions + required: true + schema: + $ref: '#/definitions/dto.AddPermissionRequestDto' + produces: + - application/json + responses: {} + summary: 批量添加权限 + tags: + - 权限管理 /api/auth/role/add_role_to_user: post: consumes: @@ -470,23 +537,6 @@ paths: summary: 刷新token tags: - 用户模块 - /api/user/add: - post: - parameters: - - description: 用户信息 - in: body - name: user - required: true - schema: - $ref: '#/definitions/dto.AddUserRequest' - responses: - "200": - description: OK - schema: - type: string - summary: 添加用户 - tags: - - 用户模块 /api/user/login: post: parameters: diff --git a/go.mod b/go.mod index ce2efc3..c8d1d3e 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,9 @@ require ( github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/gorilla/websocket v1.5.3 github.com/juju/ratelimit v1.0.2 + github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 github.com/lxzan/gws v1.8.5 + github.com/mssola/useragent v1.0.0 github.com/pkg6/go-sms v0.1.2 github.com/redis/go-redis/v9 v9.6.1 github.com/satori/go.uuid v1.2.0 @@ -76,14 +78,11 @@ require ( github.com/klauspost/compress v1.17.5 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/microsoft/go-mssqldb v1.6.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mssola/useragent v1.0.0 // indirect github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect diff --git a/go.sum b/go.sum index a8e012d..bcfddd6 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,6 @@ github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwp github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/i18n/language/en.toml b/i18n/language/en.toml index dd9ec8d..d288a16 100644 --- a/i18n/language/en.toml +++ b/i18n/language/en.toml @@ -54,3 +54,5 @@ QRCodeGetSuccess = "qr code get successfully!" QRCodeExpired = "qr code expired!" InternalError = "internal error!" RequestError = "request error!" +AssignFailed = "assign failed!" +AssignSuccess = "assign successfully!" diff --git a/i18n/language/zh.toml b/i18n/language/zh.toml index 435adab..d9c7fd7 100644 --- a/i18n/language/zh.toml +++ b/i18n/language/zh.toml @@ -54,4 +54,6 @@ QRCodeGetSuccess = "获取二维码成功!" QRCodeExpired = "二维码已过期!" InternalError = "内部错误!" RequestError = "请求错误!" +AssignFailed = "分配失败!" +AssignSuccess = "分配成功!" diff --git a/router/modules/permission_router.go b/router/modules/permission_router.go new file mode 100644 index 0000000..1f84ad1 --- /dev/null +++ b/router/modules/permission_router.go @@ -0,0 +1,14 @@ +package modules + +import ( + "github.com/gin-gonic/gin" + "schisandra-cloud-album/api" +) + +var permissionApi = api.Api.PermissionApi + +func PermissionRouter(router *gin.RouterGroup) { + group := router.Group("/auth/permission") + //group.Use(middleware.JWTAuthMiddleware()) + group.POST("/add", permissionApi.AddPermissions) +} diff --git a/router/modules/swagger_router.go b/router/modules/swagger_router.go index 0e88dd7..c121b7a 100644 --- a/router/modules/swagger_router.go +++ b/router/modules/swagger_router.go @@ -11,9 +11,9 @@ import ( func SwaggerRouter(router *gin.Engine) { docs.SwaggerInfo.BasePath = "" docs.SwaggerInfo.Description = global.CONFIG.Swagger.Description - router.GET("/api/doc/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, func(config *ginSwagger.Config) { - config.Title = global.CONFIG.Swagger.Title - }), gin.BasicAuth(gin.Accounts{ + router.GET("/api/doc/*any", gin.BasicAuth(gin.Accounts{ global.CONFIG.Swagger.User: global.CONFIG.Swagger.Password, + }), ginSwagger.WrapHandler(swaggerFiles.Handler, func(config *ginSwagger.Config) { + config.Title = global.CONFIG.Swagger.Title })) } diff --git a/router/router.go b/router/router.go index 7535445..48eaa9c 100644 --- a/router/router.go +++ b/router/router.go @@ -30,12 +30,13 @@ func InitRouter() *gin.Engine { // 国际化设置 publicGroup.Use(middleware.I18n()) - modules.SwaggerRouter(router) // 注册swagger路由 - modules.UserRouter(publicGroup) // 注册鉴权路由 - modules.CaptchaRouter(publicGroup) // 注册验证码路由 - modules.SmsRouter(publicGroup) // 注册短信验证码路由 - modules.OauthRouter(publicGroup) // 注册oauth路由 - modules.WebsocketRouter(publicGroup) // 注册websocket路由 - modules.RoleRouter(publicGroup) // 注册角色路由 + modules.SwaggerRouter(router) // 注册swagger路由 + modules.UserRouter(publicGroup) // 注册鉴权路由 + modules.CaptchaRouter(publicGroup) // 注册验证码路由 + modules.SmsRouter(publicGroup) // 注册短信验证码路由 + modules.OauthRouter(publicGroup) // 注册oauth路由 + modules.WebsocketRouter(publicGroup) // 注册websocket路由 + modules.RoleRouter(publicGroup) // 注册角色路由 + modules.PermissionRouter(publicGroup) // 注册权限路由 return router }