From 4fcbceb149d97a259a0bbb267844a2a8e09834a9 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Thu, 30 Nov 2023 18:37:59 +0800 Subject: [PATCH] Add permission control --- .../controller/permission/GroupController.kt | 25 ++++--- .../controller/permission/PowerController.kt | 2 + .../controller/permission/RoleController.kt | 27 +++++--- .../controller/permission/UserController.kt | 24 ++++--- .../api/controller/system/SysLogController.kt | 2 + .../fatweb/api/entity/permission/LoginUser.kt | 3 +- .../fatweb/api/handler/ExceptionHandler.kt | 6 ++ .../resources/db/migration/R__Basic_data.sql | 65 ++++++++++++++----- 8 files changed, 113 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/GroupController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/GroupController.kt index 14a2eac..1b6b212 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/GroupController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/GroupController.kt @@ -3,6 +3,7 @@ package top.fatweb.api.controller.permission import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.* import top.fatweb.api.entity.common.ResponseCode import top.fatweb.api.entity.common.ResponseResult @@ -24,24 +25,27 @@ import top.fatweb.api.vo.permission.GroupWithRoleVo class GroupController( val groupService: IGroupService ) { - @Operation(summary = "获取用户组") - @GetMapping - fun get(@Valid groupGetParam: GroupGetParam?): ResponseResult> { - return ResponseResult.databaseSuccess( - data = groupService.getPage(groupGetParam) - ) - } - @Operation(summary = "获取单个用户组") @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:group:query:one')") fun getOne(@PathVariable id: Long): ResponseResult { return ResponseResult.databaseSuccess( data = groupService.getOne(id) ) } + @Operation(summary = "获取用户组") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:group:query:all')") + fun get(@Valid groupGetParam: GroupGetParam?): ResponseResult> { + return ResponseResult.databaseSuccess( + data = groupService.getPage(groupGetParam) + ) + } + @Operation(summary = "获取用户组列表") @GetMapping("/list") + @PreAuthorize("hasAnyAuthority('system:group:query:list', 'system:user:add:one', 'system:user:modify:one')") fun list(): ResponseResult> { return ResponseResult.databaseSuccess( data = groupService.listAll() @@ -50,6 +54,7 @@ class GroupController( @Operation(summary = "添加用户组") @PostMapping + @PreAuthorize("hasAnyAuthority('system:group:add:one')") fun add(@Valid @RequestBody groupAddParam: GroupAddParam): ResponseResult { return groupService.add(groupAddParam)?.let { ResponseResult.databaseSuccess( @@ -60,6 +65,7 @@ class GroupController( @Operation(summary = "修改用户组") @PutMapping + @PreAuthorize("hasAnyAuthority('system:group:modify:one')") fun update(@Valid @RequestBody groupUpdateParam: GroupUpdateParam): ResponseResult { return groupService.update(groupUpdateParam)?.let { ResponseResult.databaseSuccess( @@ -70,6 +76,7 @@ class GroupController( @Operation(summary = "修改用户组状态") @PatchMapping + @PreAuthorize("hasAnyAuthority('system:group:modify:status')") fun changStatus(@Valid @RequestBody groupChangeStatusParam: GroupChangeStatusParam): ResponseResult { return if (groupService.changeStatus(groupChangeStatusParam)) { ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) @@ -80,6 +87,7 @@ class GroupController( @Operation(summary = "删除角色") @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:group:delete:one')") fun delete(@PathVariable id: Long): ResponseResult { groupService.deleteOne(id) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) @@ -87,6 +95,7 @@ class GroupController( @Operation(summary = "批量删除角色") @DeleteMapping + @PreAuthorize("hasAnyAuthority('system:group:delete:multiple')") fun deleteList(@Valid @RequestBody groupDeleteParam: GroupDeleteParam): ResponseResult { groupService.delete(groupDeleteParam) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/PowerController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/PowerController.kt index 22e16af..da57913 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/PowerController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/PowerController.kt @@ -2,6 +2,7 @@ package top.fatweb.api.controller.permission import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -22,5 +23,6 @@ class PowerController( ) { @Operation(summary = "获取权限列表") @GetMapping("/list") + @PreAuthorize("hasAnyAuthority('system:power:query:list', 'system:role:add:one', 'system:role:modify:one')") fun getList() = ResponseResult.databaseSuccess(data = powerService.getList()) } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/RoleController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/RoleController.kt index bab674b..d25c5b9 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/RoleController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/RoleController.kt @@ -3,14 +3,15 @@ package top.fatweb.api.controller.permission import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.* import top.fatweb.api.entity.common.ResponseCode import top.fatweb.api.entity.common.ResponseResult import top.fatweb.api.param.permission.role.* import top.fatweb.api.service.permission.IRoleService import top.fatweb.api.vo.PageVo -import top.fatweb.api.vo.permission.base.RoleVo import top.fatweb.api.vo.permission.RoleWithPowerVo +import top.fatweb.api.vo.permission.base.RoleVo /** * Role controller @@ -24,24 +25,27 @@ import top.fatweb.api.vo.permission.RoleWithPowerVo class RoleController( private val roleService: IRoleService ) { - @Operation(summary = "获取角色") - @GetMapping - fun get(roleGetParam: RoleGetParam?): ResponseResult> { - return ResponseResult.databaseSuccess( - data = roleService.getPage(roleGetParam) - ) - } - @Operation(summary = "获取单个角色") @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:role:query:one')") fun getOne(@PathVariable id: Long): ResponseResult { return ResponseResult.databaseSuccess( data = roleService.getOne(id) ) } + @Operation(summary = "获取角色") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:role:query:all')") + fun get(roleGetParam: RoleGetParam?): ResponseResult> { + return ResponseResult.databaseSuccess( + data = roleService.getPage(roleGetParam) + ) + } + @Operation(summary = "获取角色列表") @GetMapping("/list") + @PreAuthorize("hasAnyAuthority('system:role:query:list', 'system:group:add:one', 'system:group:modify:one', 'system:user:add:one', 'system:user:modify:one')") fun list(): ResponseResult> { return ResponseResult.databaseSuccess( data = roleService.listAll() @@ -50,6 +54,7 @@ class RoleController( @Operation(summary = "添加角色") @PostMapping + @PreAuthorize("hasAnyAuthority('system:role:add:one')") fun add(@Valid @RequestBody roleAddParam: RoleAddParam): ResponseResult { return roleService.add(roleAddParam)?.let { ResponseResult.databaseSuccess( @@ -60,6 +65,7 @@ class RoleController( @Operation(summary = "修改角色") @PutMapping + @PreAuthorize("hasAnyAuthority('system:role:modify:one')") fun update(@Valid @RequestBody roleUpdateParam: RoleUpdateParam): ResponseResult { return roleService.update(roleUpdateParam)?.let { ResponseResult.databaseSuccess( @@ -70,6 +76,7 @@ class RoleController( @Operation(summary = "修改角色状态") @PatchMapping + @PreAuthorize("hasAnyAuthority('system:role:modify:status')") fun changStatus(@Valid @RequestBody roleChangeStatusParam: RoleChangeStatusParam): ResponseResult { return if (roleService.changeStatus(roleChangeStatusParam)) { ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) @@ -80,6 +87,7 @@ class RoleController( @Operation(summary = "删除角色") @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:role:delete:one')") fun delete(@PathVariable id: Long): ResponseResult { roleService.deleteOne(id) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) @@ -87,6 +95,7 @@ class RoleController( @Operation(summary = "批量删除角色") @DeleteMapping + @PreAuthorize("hasAnyAuthority('system:role:delete:multiple')") fun deleteList(@Valid @RequestBody roleDeleteParam: RoleDeleteParam): ResponseResult { roleService.delete(roleDeleteParam) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt index 9d22f52..c412d7c 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt @@ -3,6 +3,7 @@ package top.fatweb.api.controller.permission import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.* import top.fatweb.api.entity.common.ResponseCode import top.fatweb.api.entity.common.ResponseResult @@ -34,16 +35,9 @@ class UserController( } ?: let { return ResponseResult.databaseFail() } } - @Operation(summary = "获取用户") - @GetMapping - fun get(@Valid userGetParam: UserGetParam?): ResponseResult> { - return ResponseResult.databaseSuccess( - data = userService.getPage(userGetParam) - ) - } - @Operation(summary = "获取单个用户") @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:user:query:one')") fun getOne(@PathVariable id: Long): ResponseResult { return userService.getOne(id)?.let { ResponseResult.databaseSuccess(data = it) @@ -52,8 +46,18 @@ class UserController( } } + @Operation(summary = "获取用户") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:user:query:all')") + fun get(@Valid userGetParam: UserGetParam?): ResponseResult> { + return ResponseResult.databaseSuccess( + data = userService.getPage(userGetParam) + ) + } + @Operation(summary = "添加用户") @PostMapping + @PreAuthorize("hasAnyAuthority('system:user:add:one')") fun add(@Valid @RequestBody userAddParam: UserAddParam): ResponseResult { return userService.add(userAddParam)?.let { ResponseResult.databaseSuccess( @@ -64,6 +68,7 @@ class UserController( @Operation(summary = "修改用户") @PutMapping + @PreAuthorize("hasAnyAuthority('system:user:modify:one')") fun update(@Valid @RequestBody userUpdateParam: UserUpdateParam): ResponseResult { return userService.update(userUpdateParam)?.let { ResponseResult.databaseSuccess( @@ -74,6 +79,7 @@ class UserController( @Operation(summary = "修改密码") @PatchMapping + @PreAuthorize("hasAnyAuthority('system:user:modify:password')") fun changePassword(@Valid @RequestBody userChangePasswordParam: UserChangePasswordParam): ResponseResult { userService.changePassword(userChangePasswordParam) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) @@ -81,6 +87,7 @@ class UserController( @Operation(summary = "删除用户") @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:user:delete:one')") fun delete(@PathVariable id: Long): ResponseResult { userService.deleteOne(id) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) @@ -88,6 +95,7 @@ class UserController( @Operation(summary = "批量删除用户") @DeleteMapping + @PreAuthorize("hasAnyAuthority('system:user:delete:multiple')") fun deleteList(@Valid @RequestBody userDeleteParam: UserDeleteParam): ResponseResult { userService.delete(userDeleteParam) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) diff --git a/src/main/kotlin/top/fatweb/api/controller/system/SysLogController.kt b/src/main/kotlin/top/fatweb/api/controller/system/SysLogController.kt index 665d385..5fa661f 100644 --- a/src/main/kotlin/top/fatweb/api/controller/system/SysLogController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/system/SysLogController.kt @@ -3,6 +3,7 @@ package top.fatweb.api.controller.system import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -28,6 +29,7 @@ class SysLogController( ) { @Operation(summary = "获取") @GetMapping + @PreAuthorize("hasAnyAuthority('system:log:query:all')") fun get(@Valid sysLogGetParam: SysLogGetParam?): ResponseResult> { return ResponseResult.success( ResponseCode.DATABASE_SELECT_SUCCESS, data = SysLogConverter.sysLogPageToSysLogPageVo( diff --git a/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt b/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt index c4850e4..8809c72 100644 --- a/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt +++ b/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt @@ -3,6 +3,7 @@ package top.fatweb.api.entity.permission import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonTypeInfo import org.springframework.security.core.GrantedAuthority +import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.core.userdetails.UserDetails import java.time.LocalDateTime import java.time.ZoneOffset @@ -27,7 +28,7 @@ class LoginUser() : UserDetails { @JsonIgnore override fun getAuthorities(): List { authorities?.let { return it } - authorities = emptyList() + authorities = user.operations?.map { SimpleGrantedAuthority(it.code) } ?: emptyList() return authorities as List } diff --git a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt index 4e0716b..5657310 100644 --- a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt +++ b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory import org.springframework.dao.DuplicateKeyException import org.springframework.http.converter.HttpMessageNotReadableException import org.springframework.jdbc.BadSqlGrammarException +import org.springframework.security.access.AccessDeniedException import org.springframework.security.authentication.* import org.springframework.web.HttpRequestMethodNotSupportedException import org.springframework.web.bind.MethodArgumentNotValidException @@ -106,6 +107,11 @@ class ExceptionHandler { ResponseResult.fail(ResponseCode.PERMISSION_TOKEN_HAS_EXPIRED, e.localizedMessage, null) } + is AccessDeniedException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.PERMISSION_ACCESS_DENIED, "Access Denied", null) + } + is BadSqlGrammarException -> { logger.debug(e.localizedMessage, e) ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, "Incorrect SQL syntax", null) diff --git a/src/main/resources/db/migration/R__Basic_data.sql b/src/main/resources/db/migration/R__Basic_data.sql index f6acb51..3549d08 100644 --- a/src/main/resources/db/migration/R__Basic_data.sql +++ b/src/main/resources/db/migration/R__Basic_data.sql @@ -11,9 +11,11 @@ insert into t_power (id, type_id) (1010000, 2), (1020000, 2), (1030000, 2), + (1040000, 2), (1010100, 3), (1010200, 3), (1010300, 3), + (1010400, 3), (1020100, 3), (1020200, 3), (1020300, 3), @@ -22,18 +24,32 @@ insert into t_power (id, type_id) (1030200, 3), (1030300, 3), (1030400, 3), + (1040100, 3), (1010101, 4), (1010102, 4), + (1010103, 4), (1010201, 4), (1010301, 4), + (1010302, 4), + (1010401, 4), + (1010402, 4), (1020101, 4), + (1020102, 4), + (1020103, 4), (1020201, 4), (1020301, 4), + (1020302, 4), (1020401, 4), + (1020402, 4), (1030101, 4), + (1030102, 4), + (1030103, 4), (1030201, 4), (1030301, 4), - (1030401, 4) + (1030302, 4), + (1030401, 4), + (1030402, 4), + (1040103, 4) as new_value on duplicate key update type_id = new_value.type_id; @@ -45,7 +61,9 @@ insert into t_menu (id, name, url, parent_id, module_id) values (1990000, '系统管理', '/system', null, 1000000), (1010000, '用户管理', '/system/user', 1990000, 1000000), (1020000, '角色管理', '/system/role', 1990000, 1000000), - (1030000, '用户组管理', '/system/group', 1990000, 1000000) as new_value + (1030000, '用户组管理', '/system/group', 1990000, 1000000), + (1040000, '权限管理', '/system/power', 1990000, 1000000), + (1510000, '日志管理', '/system/log', 1990000, 1000000) as new_value on duplicate key update name =new_value.name, url =new_value.url, parent_id =new_value.parent_id; @@ -54,6 +72,7 @@ insert into t_element(id, name, menu_id, parent_id) values (1010100, '查询', 1010000, null), (1010200, '增加', 1010000, null), (1010300, '修改', 1010000, null), + (1010400, '删除', 1010000, null), (1020100, '查询', 1020000, null), (1020200, '增加', 1020000, null), (1020300, '修改', 1020000, null), @@ -61,24 +80,40 @@ insert into t_element(id, name, menu_id, parent_id) (1030100, '查询', 1030000, null), (1030200, '增加', 1030000, null), (1030300, '修改', 1030000, null), - (1030400, '删除', 1030000, null) as new_value + (1030400, '删除', 1030000, null), + (1040100, '查询', 1040000, null), + (1510100, '查询', 1510000, null) as new_value on duplicate key update name = new_value.name, menu_id = new_value.menu_id, parent_id = new_value.parent_id; insert into t_operation(id, name, code, element_id) - values (1010101, '全部', 'system:user:query:all', 1010100), - (1010102, '单个', 'system:user:query:one', 1010100), - (1010201, '全部', 'system:user:add:all', 1010200), - (1010301, '全部', 'system:user:modify:all', 1010300), - (1020101, '全部', 'system:role:query:all', 1020100), - (1020201, '全部', 'system:role:add:all', 1020200), - (1020301, '全部', 'system:role:modify:all', 1020300), - (1020401, '全部', 'system:role:delete:all', 1020400), - (1030101, '全部', 'system:group:query:all', 1030100), - (1030201, '全部', 'system:group:add:all', 1030200), - (1030301, '全部', 'system:group:modify:all', 1030300), - (1030401, '全部', 'system:group:delete:all', 1030400) as new_value + values (1010101, '单个', 'system:user:query:one', 1010100), + (1010102, '全部', 'system:user:query:all', 1010100), + (1010103, '列表', 'system:user:query:list', 1010100), + (1010201, '单个', 'system:user:add:one', 1010200), + (1010301, '单个', 'system:user:modify:one', 1010300), + (1010302, '密码', 'system:user:modify:password', 1010300), + (1010401, '单个', 'system:user:delete:one', 1010400), + (1010402, '多个', 'system:user:delete:multiple', 1010400), + (1020101, '单个', 'system:role:query:one', 1020100), + (1020102, '全部', 'system:role:query:all', 1020100), + (1020103, '列表', 'system:role:query:list', 1020100), + (1020201, '单个', 'system:role:add:one', 1020200), + (1020301, '单个', 'system:role:modify:one', 1020300), + (1020302, '状态', 'system:role:modify:status', 1020300), + (1020401, '单个', 'system:role:delete:one', 1020400), + (1020402, '多个', 'system:role:delete:multiple', 1020400), + (1030101, '单个', 'system:group:query:one', 1030100), + (1030102, '全部', 'system:group:query:all', 1030100), + (1030103, '列表', 'system:group:query:list', 1030100), + (1030201, '单个', 'system:group:add:one', 1030200), + (1030301, '单个', 'system:group:modify:one', 1030300), + (1030302, '状态', 'system:group:modify:status', 1030300), + (1030401, '单个', 'system:group:delete:one', 1030400), + (1030402, '多个', 'system:group:delete:multiple', 1030400), + (1040103, '列表', 'system:power:query:list', 1040100), + (1510101, '列表', 'system:log:query:all', 1510100) as new_value on duplicate key update name=new_value.name, code=new_value.code, element_id=new_value.element_id; \ No newline at end of file