mirror of
				https://github.com/vran-dev/databasir.git
				synced 2025-10-31 12:39:20 +08:00 
			
		
		
		
	feature: add spring doc api annotation (#173)
* feat: rename @Operation to @AuditLog * feat: add swagger annotation to api
This commit is contained in:
		| @@ -32,6 +32,11 @@ dependencies { | ||||
|     implementation 'org.springframework.boot:spring-boot-starter-quartz' | ||||
|     implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' | ||||
|  | ||||
|     // open api | ||||
|     implementation 'org.springdoc:springdoc-openapi-ui:1.6.8' | ||||
|     implementation 'io.swagger.core.v3:swagger-core:2.2.0' | ||||
|     implementation 'io.swagger.core.v3:swagger-annotations:2.2.0' | ||||
|  | ||||
|     implementation 'org.flywaydb:flyway-core' | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.data.OperationLogPageCondition; | ||||
| import com.databasir.core.domain.log.data.OperationLogPageResponse; | ||||
| import com.databasir.core.domain.log.service.OperationLogService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -17,12 +19,14 @@ import org.springframework.web.bind.annotation.RestController; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| public class OperationLogController { | ||||
| @Tag(name = "AuditLogController", description = "操作日志 API") | ||||
| public class AuditLogController { | ||||
| 
 | ||||
|     private final OperationLogService operationLogService; | ||||
| 
 | ||||
|     @GetMapping(Routes.OperationLog.LIST) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "查询操作日志") | ||||
|     public JsonData<Page<OperationLogPageResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC) | ||||
|                                                          Pageable page, | ||||
|                                                          OperationLogPageCondition condition) { | ||||
| @@ -4,7 +4,9 @@ import com.databasir.api.validator.DatabaseTypeValidator; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.database.data.*; | ||||
| import com.databasir.core.domain.database.service.DatabaseTypeService; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -23,6 +25,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC; | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @RestController | ||||
| @Tag(name = "DatabaseTypeController", description = "数据库类型 API") | ||||
| public class DatabaseTypeController { | ||||
|  | ||||
|     private final DatabaseTypeService databaseTypeService; | ||||
| @@ -30,11 +33,13 @@ public class DatabaseTypeController { | ||||
|     private final DatabaseTypeValidator databaseTypeValidator; | ||||
|  | ||||
|     @GetMapping(Routes.DatabaseType.LIST_SIMPLE) | ||||
|     @Operation(summary = "获取所有数据库类型") | ||||
|     public JsonData<List<DatabaseTypeSimpleResponse>> listSimpleDatabaseTypes() { | ||||
|         return JsonData.ok(databaseTypeService.listSimpleDatabaseTypes()); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.DatabaseType.LIST_PAGE) | ||||
|     @Operation(summary = "分页获取数据库类型") | ||||
|     public JsonData<Page<DatabaseTypePageResponse>> listPage(@PageableDefault(sort = "id", direction = DESC) | ||||
|                                                              Pageable page, | ||||
|                                                              DatabaseTypePageCondition condition) { | ||||
| @@ -43,8 +48,9 @@ public class DatabaseTypeController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.DatabaseType.CREATE) | ||||
|     @Operation(module = Operation.Modules.DATABASE_TYPE, name = "创建数据库类型") | ||||
|     @AuditLog(module = AuditLog.Modules.DATABASE_TYPE, name = "创建数据库类型") | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "创建数据库类型") | ||||
|     public JsonData<Integer> create(@RequestBody @Valid DatabaseTypeCreateRequest request) { | ||||
|         databaseTypeValidator.isValidUrlPattern(request.getUrlPattern()); | ||||
|         Integer id = databaseTypeService.create(request); | ||||
| @@ -52,8 +58,9 @@ public class DatabaseTypeController { | ||||
|     } | ||||
|  | ||||
|     @PatchMapping(Routes.DatabaseType.UPDATE) | ||||
|     @Operation(module = Operation.Modules.DATABASE_TYPE, name = "更新数据库类型") | ||||
|     @AuditLog(module = AuditLog.Modules.DATABASE_TYPE, name = "更新数据库类型") | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "更新数据库类型") | ||||
|     public JsonData<Void> update(@RequestBody @Valid DatabaseTypeUpdateRequest request) { | ||||
|         databaseTypeValidator.isValidUrlPattern(request.getUrlPattern()); | ||||
|         databaseTypeService.update(request); | ||||
| @@ -61,14 +68,16 @@ public class DatabaseTypeController { | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping(Routes.DatabaseType.DELETE_ONE) | ||||
|     @Operation(module = Operation.Modules.DATABASE_TYPE, name = "删除数据库类型") | ||||
|     @AuditLog(module = AuditLog.Modules.DATABASE_TYPE, name = "删除数据库类型") | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "删除数据库类型") | ||||
|     public JsonData<Void> delete(@PathVariable Integer id) { | ||||
|         databaseTypeService.deleteById(id); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.DatabaseType.GET_ONE) | ||||
|     @Operation(summary = "获取数据库类型") | ||||
|     public JsonData<DatabaseTypeDetailResponse> getOne(@PathVariable Integer id) { | ||||
|         Optional<DatabaseTypeDetailResponse> data = databaseTypeService.selectOne(id); | ||||
|         return JsonData.ok(data); | ||||
| @@ -76,6 +85,7 @@ public class DatabaseTypeController { | ||||
|  | ||||
|     @PostMapping(Routes.DatabaseType.RESOLVE_DRIVER_CLASS_NAME) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "解析数据库驱动类名") | ||||
|     public JsonData<String> resolveDriverClassName(@RequestBody @Valid DriverClassNameResolveRequest request) { | ||||
|         String driverClassName = databaseTypeService.resolveDriverClassName(request); | ||||
|         return JsonData.ok(driverClassName); | ||||
| @@ -83,6 +93,7 @@ public class DatabaseTypeController { | ||||
|  | ||||
|     @PostMapping(Routes.DatabaseType.UPLOAD_DRIVER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "上传数据库驱动") | ||||
|     public JsonData<String> uploadDriver(@RequestPart MultipartFile file) { | ||||
|         String driverPath = databaseTypeService.uploadDriver(file); | ||||
|         return JsonData.ok(driverPath); | ||||
|   | ||||
| @@ -5,8 +5,10 @@ import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.document.data.*; | ||||
| import com.databasir.core.domain.document.generator.DocumentFileType; | ||||
| import com.databasir.core.domain.document.service.DocumentService; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.project.service.ProjectService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -29,6 +31,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC; | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @RestController | ||||
| @Tag(name = "DocumentController", description = "数据库文档 API") | ||||
| public class DocumentController { | ||||
|  | ||||
|     private final DocumentService documentService; | ||||
| @@ -36,7 +39,8 @@ public class DocumentController { | ||||
|     private final ProjectService projectService; | ||||
|  | ||||
|     @PostMapping(Routes.Document.SYNC_ONE) | ||||
|     @Operation(module = Operation.Modules.PROJECT, name = "文档同步", involvedProjectId = "#projectId") | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, name = "文档同步", involvedProjectId = "#projectId") | ||||
|     @Operation(summary = "同步文档") | ||||
|     public JsonData<Integer> sync(@PathVariable Integer projectId) { | ||||
|         Integer userId = LoginUserContext.getLoginUserId(); | ||||
|         Optional<Integer> taskIdOpt = projectService.createSyncTask(projectId, userId, false); | ||||
| @@ -44,6 +48,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Document.GET_ONE) | ||||
|     @Operation(summary = "获取文档") | ||||
|     public JsonData<DatabaseDocumentResponse> getByProjectId(@PathVariable Integer projectId, | ||||
|                                                              @RequestParam(required = false) Long version) { | ||||
|         return documentService.getOneByProjectId(projectId, version) | ||||
| @@ -52,6 +57,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Document.LIST_VERSIONS) | ||||
|     @Operation(summary = "获取文档版本列表") | ||||
|     public JsonData<Page<DatabaseDocumentVersionResponse>> getVersionsByProjectId(@PathVariable Integer projectId, | ||||
|                                                                                   @PageableDefault(sort = "id", | ||||
|                                                                                           direction = DESC) | ||||
| @@ -60,6 +66,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Document.EXPORT) | ||||
|     @Operation(summary = "导出文档") | ||||
|     public ResponseEntity<StreamingResponseBody> getDocumentFiles(@PathVariable Integer projectId, | ||||
|                                                                   @RequestParam(required = false) | ||||
|                                                                   Long version, | ||||
| @@ -76,6 +83,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Document.GET_SIMPLE_ONE) | ||||
|     @Operation(summary = "获取文档(无详情信息)") | ||||
|     public JsonData<DatabaseDocumentSimpleResponse> getSimpleByProjectId(@PathVariable Integer projectId, | ||||
|                                                                          @RequestParam(required = false) | ||||
|                                                                          Long version, | ||||
| @@ -85,6 +93,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.Document.GET_TABLE_DETAIL) | ||||
|     @Operation(summary = "获取表详情") | ||||
|     public JsonData<List<TableDocumentResponse>> getTableDocument(@PathVariable Integer projectId, | ||||
|                                                                   @PathVariable Integer documentId, | ||||
|                                                                   @RequestBody @Valid TableDocumentRequest request) { | ||||
| @@ -92,6 +101,7 @@ public class DocumentController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Document.LIST_TABLES) | ||||
|     @Operation(summary = "获取表列表") | ||||
|     public JsonData<List<TableResponse>> listTables(@PathVariable Integer projectId, | ||||
|                                                     @RequestParam(required = false) Long version) { | ||||
|         return JsonData.ok(documentService.getTableAndColumns(projectId, version)); | ||||
|   | ||||
| @@ -4,7 +4,9 @@ import com.databasir.api.config.security.DatabasirUserDetails; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.description.data.DocumentDescriptionSaveRequest; | ||||
| import com.databasir.core.domain.description.service.DocumentDescriptionService; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| @@ -19,15 +21,17 @@ import javax.validation.Valid; | ||||
| @RestController | ||||
| @Validated | ||||
| @RequiredArgsConstructor | ||||
| @Tag(name = "DocumentDescriptionController", description = "文档描述 API") | ||||
| public class DocumentDescriptionController { | ||||
|  | ||||
|     private final DocumentDescriptionService documentDescriptionService; | ||||
|  | ||||
|     @PostMapping(Routes.DocumentDescription.SAVE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "更新描述", | ||||
|             involvedProjectId = "#projectId") | ||||
|     @Operation(summary = "更新描述") | ||||
|     public JsonData<Void> save(@PathVariable Integer groupId, | ||||
|                                @PathVariable Integer projectId, | ||||
|                                @RequestBody @Valid DocumentDescriptionSaveRequest request) { | ||||
|   | ||||
| @@ -2,11 +2,13 @@ package com.databasir.api; | ||||
|  | ||||
| import com.databasir.api.config.security.DatabasirUserDetails; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.discussion.data.DiscussionCreateRequest; | ||||
| import com.databasir.core.domain.discussion.data.DiscussionListCondition; | ||||
| import com.databasir.core.domain.discussion.data.DiscussionResponse; | ||||
| import com.databasir.core.domain.discussion.service.DocumentDiscussionService; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -22,11 +24,13 @@ import javax.validation.Valid; | ||||
| @RestController | ||||
| @Validated | ||||
| @RequiredArgsConstructor | ||||
| @Tag(name = "DocumentDiscussionController", description = "文档讨论 API") | ||||
| public class DocumentDiscussionController { | ||||
|  | ||||
|     private final DocumentDiscussionService documentDiscussionService; | ||||
|  | ||||
|     @GetMapping(Routes.DocumentDiscussion.LIST) | ||||
|     @Operation(summary = "获取文档评论列表") | ||||
|     public JsonData<Page<DiscussionResponse>> listByProjectId(@PathVariable Integer groupId, | ||||
|                                                               @PathVariable Integer projectId, | ||||
|                                                               @PageableDefault(sort = "id", | ||||
| @@ -39,9 +43,10 @@ public class DocumentDiscussionController { | ||||
|  | ||||
|     @DeleteMapping(Routes.DocumentDiscussion.DELETE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "删除评论", | ||||
|             involvedProjectId = "#projectId") | ||||
|     @Operation(summary = "删除评论") | ||||
|     public JsonData<Void> delete(@PathVariable Integer groupId, | ||||
|                                  @PathVariable Integer projectId, | ||||
|                                  @PathVariable Integer discussionId) { | ||||
| @@ -51,9 +56,10 @@ public class DocumentDiscussionController { | ||||
|  | ||||
|     @PostMapping(Routes.DocumentDiscussion.CREATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "新增评论", | ||||
|             involvedProjectId = "#projectId") | ||||
|     @Operation(summary = "新增评论") | ||||
|     public JsonData<Void> create(@PathVariable Integer groupId, | ||||
|                                  @PathVariable Integer projectId, | ||||
|                                  @RequestBody @Valid DiscussionCreateRequest request) { | ||||
|   | ||||
| @@ -4,7 +4,9 @@ import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.document.data.DocumentTemplatePropertiesResponse; | ||||
| import com.databasir.core.domain.document.data.DocumentTemplatePropertiesUpdateRequest; | ||||
| import com.databasir.core.domain.document.service.DocumentTemplateService; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -18,18 +20,21 @@ import javax.validation.Valid; | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @RestController | ||||
| @Tag(name = "DocumentTemplateController", description = "文档模板 API") | ||||
| public class DocumentTemplateController { | ||||
|  | ||||
|     private final DocumentTemplateService documentTemplateService; | ||||
|  | ||||
|     @GetMapping(Routes.DocumentTemplateProperty.API) | ||||
|     @Operation(summary = "获取模板属性") | ||||
|     public JsonData<DocumentTemplatePropertiesResponse> getAllProperties() { | ||||
|         return JsonData.ok(documentTemplateService.getAllProperties()); | ||||
|     } | ||||
|  | ||||
|     @PatchMapping(Routes.DocumentTemplateProperty.API) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.SETTING, name = "更新模板") | ||||
|     @AuditLog(module = AuditLog.Modules.SETTING, name = "更新模板") | ||||
|     @Operation(summary = "更新模板属性") | ||||
|     public JsonData<Void> updateByType(@RequestBody @Valid DocumentTemplatePropertiesUpdateRequest request) { | ||||
|         documentTemplateService.updateByType(request); | ||||
|         return JsonData.ok(); | ||||
|   | ||||
| @@ -4,7 +4,9 @@ import com.databasir.api.validator.UserOperationValidator; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.group.data.*; | ||||
| import com.databasir.core.domain.group.service.GroupService; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -24,6 +26,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "GroupController", description = "分组 API") | ||||
| public class GroupController { | ||||
|  | ||||
|     private final GroupService groupService; | ||||
| @@ -32,7 +35,8 @@ public class GroupController { | ||||
|  | ||||
|     @PostMapping(Routes.Group.CREATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.GROUP, name = "创建分组") | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, name = "创建分组") | ||||
|     @Operation(summary = "创建分组") | ||||
|     public JsonData<Void> create(@RequestBody @Valid GroupCreateRequest request) { | ||||
|         groupService.create(request); | ||||
|         return JsonData.ok(); | ||||
| @@ -40,15 +44,17 @@ public class GroupController { | ||||
|  | ||||
|     @PatchMapping(Routes.Group.UPDATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER'.concat('?groupId='.concat(#request.id)))") | ||||
|     @Operation(module = Operation.Modules.GROUP, | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, | ||||
|             name = "更新分组", | ||||
|             involvedGroupId = "#request.id") | ||||
|     @Operation(summary = "更新分组") | ||||
|     public JsonData<Void> update(@RequestBody @Valid GroupUpdateRequest request) { | ||||
|         groupService.update(request); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Group.LIST) | ||||
|     @Operation(summary = "分页查询分组") | ||||
|     public JsonData<Page<GroupPageResponse>> list(@PageableDefault(sort = "id", direction = DESC) | ||||
|                                                           Pageable page, | ||||
|                                                   GroupPageCondition condition) { | ||||
| @@ -57,20 +63,23 @@ public class GroupController { | ||||
|  | ||||
|     @DeleteMapping(Routes.Group.DELETE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER'.concat('?groupId='.concat(#groupId)))") | ||||
|     @Operation(module = Operation.Modules.GROUP, | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, | ||||
|             name = "删除分组", | ||||
|             involvedGroupId = "#groupId") | ||||
|     @Operation(summary = "删除分组") | ||||
|     public JsonData<Void> deleteById(@PathVariable Integer groupId) { | ||||
|         groupService.delete(groupId); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Group.GET_ONE) | ||||
|     @Operation(summary = "查询分组") | ||||
|     public JsonData<GroupResponse> getOne(@PathVariable Integer groupId) { | ||||
|         return JsonData.ok(groupService.get(groupId)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Group.MEMBERS) | ||||
|     @Operation(summary = "查询分组成员") | ||||
|     public JsonData<Page<GroupMemberPageResponse>> listGroupMembers(@PathVariable Integer groupId, | ||||
|                                                                     @PageableDefault(sort = "user_role.create_at", | ||||
|                                                                             direction = DESC) | ||||
| @@ -81,10 +90,11 @@ public class GroupController { | ||||
|  | ||||
|     @PostMapping(Routes.Group.ADD_MEMBER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER'.concat('?groupId='.concat(#groupId)))") | ||||
|     @Operation(module = Operation.Modules.GROUP, | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, | ||||
|             name = "添加组员", | ||||
|             involvedGroupId = "#groupId", | ||||
|             involvedUserId = "#request.userId") | ||||
|     @Operation(summary = "添加组员") | ||||
|     public JsonData<Void> addGroupMember(@PathVariable Integer groupId, | ||||
|                                          @RequestBody @Valid GroupMemberCreateRequest request) { | ||||
|         userOperationValidator.forbiddenIfUpdateSelfRole(request.getUserId()); | ||||
| @@ -98,10 +108,11 @@ public class GroupController { | ||||
|  | ||||
|     @DeleteMapping(Routes.Group.DELETE_MEMBER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER'.concat('?groupId='.concat(#groupId)))") | ||||
|     @Operation(module = Operation.Modules.GROUP, | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, | ||||
|             name = "移除组员", | ||||
|             involvedGroupId = "#groupId", | ||||
|             involvedUserId = "#userId") | ||||
|     @Operation(summary = "移除组员") | ||||
|     public JsonData<Void> removeGroupMember(@PathVariable Integer groupId, | ||||
|                                             @PathVariable Integer userId) { | ||||
|         userOperationValidator.forbiddenIfUpdateSelfRole(userId); | ||||
| @@ -111,10 +122,11 @@ public class GroupController { | ||||
|  | ||||
|     @PatchMapping(Routes.Group.UPDATE_MEMBER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER'.concat('?groupId='.concat(#groupId)))") | ||||
|     @Operation(module = Operation.Modules.GROUP, | ||||
|     @AuditLog(module = AuditLog.Modules.GROUP, | ||||
|             name = "更新组员角色", | ||||
|             involvedGroupId = "#groupId", | ||||
|             involvedUserId = "#userId") | ||||
|     @Operation(summary = "更新组员角色") | ||||
|     public JsonData<Void> updateGroupMemberRole(@PathVariable Integer groupId, | ||||
|                                                 @PathVariable Integer userId, | ||||
|                                                 @RequestBody GroupMemberRoleUpdateRequest request) { | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| package com.databasir.api; | ||||
|  | ||||
| import com.databasir.common.JsonData; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| @@ -8,10 +10,12 @@ import org.springframework.web.bind.annotation.ResponseBody; | ||||
| import org.springframework.web.bind.annotation.ResponseStatus; | ||||
|  | ||||
| @Controller | ||||
| @Tag(name = "IndexController", description = "测活 API") | ||||
| public class IndexController { | ||||
|  | ||||
|     @GetMapping("/live") | ||||
|     @ResponseBody | ||||
|     @Operation(summary = "测活") | ||||
|     public JsonData<String> live() { | ||||
|         return JsonData.ok("ok"); | ||||
|     } | ||||
| @@ -22,6 +26,7 @@ public class IndexController { | ||||
|     } | ||||
|  | ||||
|     @ResponseStatus(HttpStatus.NOT_FOUND) | ||||
|     @Operation(summary = "404 统一跳转") | ||||
|     public String handleResourceNotFoundException() { | ||||
|         return "/index.html"; | ||||
|     } | ||||
|   | ||||
| @@ -4,13 +4,16 @@ import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.app.OpenAuthAppService; | ||||
| import com.databasir.core.domain.app.data.*; | ||||
| import com.databasir.core.domain.app.handler.OpenAuthHandlers; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| import org.springframework.data.web.PageableDefault; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| @@ -22,6 +25,8 @@ import static org.springframework.data.domain.Sort.Direction.DESC; | ||||
|  | ||||
| @Controller | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "LoginAppController", description = "OAuth2 应用 API") | ||||
| public class LoginAppController { | ||||
|  | ||||
|     private final OpenAuthAppService openAuthAppService; | ||||
| @@ -33,6 +38,7 @@ public class LoginAppController { | ||||
|      */ | ||||
|     @GetMapping("/oauth2/apps") | ||||
|     @ResponseBody | ||||
|     @Operation(summary = "获取登录应用") | ||||
|     public JsonData<List<OAuthAppResponse>> listApps() { | ||||
|         return JsonData.ok(openAuthAppService.listAll()); | ||||
|     } | ||||
| @@ -42,6 +48,7 @@ public class LoginAppController { | ||||
|      */ | ||||
|     @GetMapping("/oauth2/authorization/{registrationId}") | ||||
|     @ResponseBody | ||||
|     @Operation(summary = "OAuth2 授权回调") | ||||
|     public JsonData<String> authorization(@PathVariable String registrationId, | ||||
|                                           HttpServletRequest request) { | ||||
|         Map<String, String[]> parameters = request.getParameterMap(); | ||||
| @@ -52,6 +59,7 @@ public class LoginAppController { | ||||
|     @GetMapping(Routes.OAuth2App.LIST_PAGE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @ResponseBody | ||||
|     @Operation(summary = "分页查询登录应用") | ||||
|     public JsonData<Page<OAuthAppPageResponse>> listPage(@PageableDefault(sort = "id", direction = DESC) | ||||
|                                                          Pageable page, | ||||
|                                                          OAuthAppPageCondition condition) { | ||||
| @@ -61,6 +69,7 @@ public class LoginAppController { | ||||
|     @GetMapping(Routes.OAuth2App.GET_ONE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @ResponseBody | ||||
|     @Operation(summary = "查询登录应用详情") | ||||
|     public JsonData<OAuthAppDetailResponse> getOne(@PathVariable Integer id) { | ||||
|         return JsonData.ok(openAuthAppService.getOne(id)); | ||||
|  | ||||
| @@ -69,7 +78,8 @@ public class LoginAppController { | ||||
|     @PostMapping(Routes.OAuth2App.CREATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @ResponseBody | ||||
|     @Operation(module = Operation.Modules.LOGIN_APP, name = "创建登录应用") | ||||
|     @AuditLog(module = AuditLog.Modules.LOGIN_APP, name = "创建登录应用") | ||||
|     @Operation(summary = "创建登录应用") | ||||
|     public JsonData<Integer> create(@RequestBody @Valid OAuthAppCreateRequest request) { | ||||
|         Integer id = openAuthAppService.create(request); | ||||
|         return JsonData.ok(id); | ||||
| @@ -78,7 +88,8 @@ public class LoginAppController { | ||||
|     @PatchMapping(Routes.OAuth2App.UPDATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @ResponseBody | ||||
|     @Operation(module = Operation.Modules.LOGIN_APP, name = "更新登录应用") | ||||
|     @AuditLog(module = AuditLog.Modules.LOGIN_APP, name = "更新登录应用") | ||||
|     @Operation(summary = "更新登录应用") | ||||
|     public JsonData<Void> updateById(@RequestBody @Valid OAuthAppUpdateRequest request) { | ||||
|         openAuthAppService.updateById(request); | ||||
|         return JsonData.ok(); | ||||
| @@ -87,7 +98,8 @@ public class LoginAppController { | ||||
|     @DeleteMapping(Routes.OAuth2App.DELETE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @ResponseBody | ||||
|     @Operation(module = Operation.Modules.LOGIN_APP, name = "删除登录应用") | ||||
|     @AuditLog(module = AuditLog.Modules.LOGIN_APP, name = "删除登录应用") | ||||
|     @Operation(summary = "删除登录应用") | ||||
|     public JsonData<Void> deleteById(@PathVariable Integer id) { | ||||
|         openAuthAppService.deleteById(id); | ||||
|         return JsonData.ok(); | ||||
|   | ||||
| @@ -5,11 +5,13 @@ import com.databasir.common.DatabasirException; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.common.exception.InvalidTokenException; | ||||
| import com.databasir.core.domain.DomainErrors; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.login.data.AccessTokenRefreshRequest; | ||||
| import com.databasir.core.domain.login.data.AccessTokenRefreshResponse; | ||||
| import com.databasir.core.domain.login.data.UserLoginResponse; | ||||
| import com.databasir.core.domain.login.service.LoginService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| @@ -26,18 +28,21 @@ import java.util.Objects; | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Slf4j | ||||
| @Tag(name = "LoginController", description = "登录 API") | ||||
| public class LoginController { | ||||
|  | ||||
|     private final LoginService loginService; | ||||
|  | ||||
|     @GetMapping(Routes.Login.LOGOUT) | ||||
|     @Operation(module = Operation.Modules.USER, name = "注销登录") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "注销登录") | ||||
|     @Operation(summary = "注销登录") | ||||
|     public JsonData<Void> logout() { | ||||
|         SecurityContextHolder.clearContext(); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.Login.REFRESH_ACCESS_TOKEN) | ||||
|     @Operation(summary = "刷新 Access Token") | ||||
|     public JsonData<AccessTokenRefreshResponse> refreshAccessTokens(@RequestBody | ||||
|                                                                     @Valid AccessTokenRefreshRequest request) { | ||||
|         try { | ||||
| @@ -54,6 +59,7 @@ public class LoginController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.Login.LOGIN_INFO) | ||||
|     @Operation(summary = "获取登录信息") | ||||
|     public JsonData<UserLoginResponse> getUserLoginData() { | ||||
|         DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext() | ||||
|                 .getAuthentication() | ||||
|   | ||||
| @@ -6,6 +6,8 @@ import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest; | ||||
| import com.databasir.core.domain.mock.data.MockDataGenerateCondition; | ||||
| import com.databasir.core.domain.mock.data.MockDataRuleListCondition; | ||||
| import com.databasir.core.domain.mock.data.MockDataRuleResponse; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -17,11 +19,13 @@ import java.util.List; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "MockDataController", description = "MOCK SQL API") | ||||
| public class MockDataController { | ||||
|  | ||||
|     private final MockDataService mockDataService; | ||||
|  | ||||
|     @GetMapping(Routes.MockData.GET_SQL_MOCK_DATA) | ||||
|     @Operation(summary = "获取 Mock Insert SQL") | ||||
|     public JsonData<String> getMockSql(@PathVariable("groupId") Integer groupId, | ||||
|                                        @PathVariable("projectId") Integer projectId, | ||||
|                                        @Valid MockDataGenerateCondition condition) { | ||||
| @@ -30,6 +34,7 @@ public class MockDataController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.MockData.GET_MOCK_RULE) | ||||
|     @Operation(summary = "获取 Mock Rule") | ||||
|     public JsonData<List<MockDataRuleResponse>> getMockRules(@PathVariable("groupId") Integer groupId, | ||||
|                                                              @PathVariable("projectId") Integer projectId, | ||||
|                                                              @Valid MockDataRuleListCondition condition) { | ||||
| @@ -39,6 +44,7 @@ public class MockDataController { | ||||
|  | ||||
|     @PostMapping(Routes.MockData.SAVE_MOCK_RULE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)") | ||||
|     @Operation(summary = "保存 Mock Rule") | ||||
|     public JsonData<Void> saveMockRules(@PathVariable Integer groupId, | ||||
|                                         @PathVariable Integer projectId, | ||||
|                                         @PathVariable Integer tableId, | ||||
|   | ||||
| @@ -3,11 +3,13 @@ package com.databasir.api; | ||||
| import com.databasir.api.config.security.DatabasirUserDetails; | ||||
| import com.databasir.api.validator.CronExpressionValidator; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.project.data.*; | ||||
| import com.databasir.core.domain.project.data.task.ProjectSimpleTaskResponse; | ||||
| import com.databasir.core.domain.project.data.task.ProjectTaskListCondition; | ||||
| import com.databasir.core.domain.project.service.ProjectService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -24,6 +26,7 @@ import java.util.List; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "ProjectController", description = "项目 API") | ||||
| public class ProjectController { | ||||
|  | ||||
|     private final ProjectService projectService; | ||||
| @@ -33,9 +36,10 @@ public class ProjectController { | ||||
|     @PostMapping(Routes.GroupProject.CREATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#request.groupId, " | ||||
|             + "'GROUP_MEMBER?groupId='+#request.groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "创建项目", | ||||
|             involvedGroupId = "#request.groupId") | ||||
|     @Operation(summary = "创建项目") | ||||
|     public JsonData<Void> create(@RequestBody @Valid ProjectCreateRequest request) { | ||||
|         cronExpressionValidator.isValidCron(request); | ||||
|         projectService.create(request); | ||||
| @@ -44,10 +48,11 @@ public class ProjectController { | ||||
|  | ||||
|     @PatchMapping(Routes.GroupProject.UPDATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "更新项目", | ||||
|             involvedGroupId = "#groupId", | ||||
|             involvedProjectId = "#request.id") | ||||
|     @Operation(summary = "更新项目") | ||||
|     public JsonData<Void> update(@RequestBody @Valid ProjectUpdateRequest request, | ||||
|                                  @PathVariable Integer groupId) { | ||||
|         cronExpressionValidator.isValidCron(request); | ||||
| @@ -57,10 +62,11 @@ public class ProjectController { | ||||
|  | ||||
|     @DeleteMapping(Routes.GroupProject.DELETE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)") | ||||
|     @Operation(module = Operation.Modules.PROJECT, | ||||
|     @AuditLog(module = AuditLog.Modules.PROJECT, | ||||
|             name = "删除项目", | ||||
|             involvedGroupId = "#groupId", | ||||
|             involvedProjectId = "#projectId") | ||||
|     @Operation(summary = "删除项目") | ||||
|     public JsonData<Void> delete(@PathVariable Integer groupId, | ||||
|                                  @PathVariable Integer projectId) { | ||||
|         projectService.delete(projectId); | ||||
| @@ -68,11 +74,13 @@ public class ProjectController { | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.GroupProject.GET_ONE) | ||||
|     @Operation(summary = "获取项目详情") | ||||
|     public JsonData<ProjectDetailResponse> getOne(@PathVariable Integer projectId) { | ||||
|         return JsonData.ok(projectService.getOne(projectId)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.GroupProject.LIST) | ||||
|     @Operation(summary = "获取项目列表") | ||||
|     public JsonData<Page<ProjectSimpleResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC) | ||||
|                                                       Pageable page, | ||||
|                                                       ProjectListCondition condition) { | ||||
| @@ -84,18 +92,21 @@ public class ProjectController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.GroupProject.TEST_CONNECTION) | ||||
|     @Operation(summary = "测试连接") | ||||
|     public JsonData<Void> testConnection(@RequestBody @Valid ProjectTestConnectionRequest request) { | ||||
|         projectService.testConnection(request); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.GroupProject.LIST_MANUAL_TASKS) | ||||
|     @Operation(summary = "获取同步任务列表") | ||||
|     public JsonData<List<ProjectSimpleTaskResponse>> listManualTasks(@PathVariable Integer projectId, | ||||
|                                                                      @RequestBody ProjectTaskListCondition condition) { | ||||
|         return JsonData.ok(projectService.listManualTasks(projectId, condition)); | ||||
|     } | ||||
|  | ||||
|     @PatchMapping(Routes.GroupProject.CANCEL_MANUAL_TASK) | ||||
|     @Operation(summary = "取消同步任务") | ||||
|     public JsonData<Void> cancelTask(@PathVariable Integer projectId, | ||||
|                                      @PathVariable Integer taskId) { | ||||
|         projectService.cancelTask(projectId, taskId); | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| package com.databasir.api; | ||||
|  | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.system.data.SystemEmailResponse; | ||||
| import com.databasir.core.domain.system.data.SystemEmailUpdateRequest; | ||||
| import com.databasir.core.domain.system.service.SystemService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -16,11 +18,13 @@ import javax.validation.Valid; | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
| @Tag(name = "SettingController", description = "系统设置 API") | ||||
| public class SettingController { | ||||
|  | ||||
|     private final SystemService systemService; | ||||
|  | ||||
|     @GetMapping(Routes.Setting.GET_SYS_EMAIL) | ||||
|     @Operation(summary = "获取系统邮箱配置") | ||||
|     public JsonData<SystemEmailResponse> getSystemEmailSetting() { | ||||
|         return systemService.getEmailSetting() | ||||
|                 .map(JsonData::ok) | ||||
| @@ -28,14 +32,16 @@ public class SettingController { | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping(Routes.Setting.DELETE_SYS_EMAIL) | ||||
|     @Operation(module = Operation.Modules.SETTING, name = "重置系统邮箱") | ||||
|     @AuditLog(module = AuditLog.Modules.SETTING, name = "重置系统邮箱") | ||||
|     @Operation(summary = "重置系统邮箱") | ||||
|     public JsonData<Void> deleteSysEmail() { | ||||
|         systemService.deleteSystemEmail(); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.Setting.UPDATE_SYS_EMAIL) | ||||
|     @Operation(module = Operation.Modules.SETTING, name = "更新邮件配置") | ||||
|     @AuditLog(module = AuditLog.Modules.SETTING, name = "更新邮件配置") | ||||
|     @Operation(summary = "更新邮件配置") | ||||
|     public JsonData<Void> updateSystemEmailSetting(@RequestBody @Valid SystemEmailUpdateRequest request) { | ||||
|         systemService.updateEmailSetting(request); | ||||
|         return JsonData.ok(); | ||||
|   | ||||
| @@ -5,9 +5,11 @@ import com.databasir.api.validator.UserOperationValidator; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.common.exception.Forbidden; | ||||
| import com.databasir.core.domain.DomainErrors; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.user.data.*; | ||||
| import com.databasir.core.domain.user.service.UserService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -22,6 +24,7 @@ import javax.validation.Valid; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "UserController", description = "用户 API") | ||||
| public class UserController { | ||||
|  | ||||
|     private final UserService userService; | ||||
| @@ -29,6 +32,7 @@ public class UserController { | ||||
|     private final UserOperationValidator userOperationValidator; | ||||
|  | ||||
|     @GetMapping(Routes.User.LIST) | ||||
|     @Operation(summary = "分页查询用户") | ||||
|     public JsonData<Page<UserPageResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC) | ||||
|                                                  Pageable pageable, | ||||
|                                                  UserPageCondition condition) { | ||||
| @@ -37,7 +41,8 @@ public class UserController { | ||||
|  | ||||
|     @PostMapping(Routes.User.DISABLE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "禁用用户", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "禁用用户", involvedUserId = "#userId") | ||||
|     @Operation(summary = "禁用用户") | ||||
|     public JsonData<Void> disableUser(@PathVariable Integer userId) { | ||||
|         if (userOperationValidator.isMyself(userId)) { | ||||
|             throw DomainErrors.CANNOT_UPDATE_SELF_ENABLED_STATUS.exception(); | ||||
| @@ -48,7 +53,8 @@ public class UserController { | ||||
|  | ||||
|     @PostMapping(Routes.User.ENABLE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "启用用户", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "启用用户", involvedUserId = "#userId") | ||||
|     @Operation(summary = "启用用户") | ||||
|     public JsonData<Void> enableUser(@PathVariable Integer userId) { | ||||
|         if (userOperationValidator.isMyself(userId)) { | ||||
|             throw DomainErrors.CANNOT_UPDATE_SELF_ENABLED_STATUS.exception(); | ||||
| @@ -59,19 +65,22 @@ public class UserController { | ||||
|  | ||||
|     @PostMapping(Routes.User.CREATE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "创建用户") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "创建用户") | ||||
|     @Operation(summary = "创建用户") | ||||
|     public JsonData<Void> create(@RequestBody @Valid UserCreateRequest request) { | ||||
|         userService.create(request, UserSource.MANUAL); | ||||
|         return JsonData.ok(); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(Routes.User.GET_ONE) | ||||
|     @Operation(summary = "根据 ID 查询用户") | ||||
|     public JsonData<UserDetailResponse> getOne(@PathVariable Integer userId) { | ||||
|         return JsonData.ok(userService.get(userId)); | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping(Routes.User.DELETE_ONE) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(summary = "根据 ID 删除用户") | ||||
|     public JsonData<Void> deleteOne(@PathVariable Integer userId) { | ||||
|         if (userOperationValidator.isMyself(userId)) { | ||||
|             throw DomainErrors.CANNOT_DELETE_SELF.exception(); | ||||
| @@ -82,7 +91,8 @@ public class UserController { | ||||
|  | ||||
|     @PostMapping(Routes.User.RENEW_PASSWORD) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "重置用户密码", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "重置用户密码", involvedUserId = "#userId") | ||||
|     @Operation(summary = "重置用户密码") | ||||
|     public JsonData<Void> renewPassword(@PathVariable Integer userId) { | ||||
|         Integer operatorUserId = LoginUserContext.getLoginUserId(); | ||||
|         userService.renewPassword(operatorUserId, userId); | ||||
| @@ -91,7 +101,8 @@ public class UserController { | ||||
|  | ||||
|     @PostMapping(Routes.User.ADD_OR_REMOVE_SYS_OWNER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "添加系统管理员", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "添加系统管理员", involvedUserId = "#userId") | ||||
|     @Operation(summary = "添加系统管理员") | ||||
|     public JsonData<Void> addSysOwner(@PathVariable Integer userId) { | ||||
|         userOperationValidator.forbiddenIfUpdateSelfRole(userId); | ||||
|         userService.addSysOwnerTo(userId); | ||||
| @@ -100,7 +111,8 @@ public class UserController { | ||||
|  | ||||
|     @DeleteMapping(Routes.User.ADD_OR_REMOVE_SYS_OWNER) | ||||
|     @PreAuthorize("hasAnyAuthority('SYS_OWNER')") | ||||
|     @Operation(module = Operation.Modules.USER, name = "移除系统管理员", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "移除系统管理员", involvedUserId = "#userId") | ||||
|     @Operation(summary = "移除系统管理员") | ||||
|     public JsonData<Void> removeSysOwner(@PathVariable Integer userId) { | ||||
|         userOperationValidator.forbiddenIfUpdateSelfRole(userId); | ||||
|         userService.removeSysOwnerFrom(userId); | ||||
| @@ -108,7 +120,8 @@ public class UserController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.User.UPDATE_PASSWORD) | ||||
|     @Operation(module = Operation.Modules.USER, name = "更新密码", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "更新密码", involvedUserId = "#userId") | ||||
|     @Operation(summary = "更新密码") | ||||
|     public JsonData<Void> updatePassword(@PathVariable Integer userId, | ||||
|                                          @RequestBody @Valid UserPasswordUpdateRequest request) { | ||||
|         if (userOperationValidator.isMyself(userId)) { | ||||
| @@ -120,7 +133,8 @@ public class UserController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.User.UPDATE_NICKNAME) | ||||
|     @Operation(module = Operation.Modules.USER, name = "更新昵称", involvedUserId = "#userId") | ||||
|     @AuditLog(module = AuditLog.Modules.USER, name = "更新昵称", involvedUserId = "#userId") | ||||
|     @Operation(summary = "更新昵称") | ||||
|     public JsonData<Void> updateNickname(@PathVariable Integer userId, | ||||
|                                          @RequestBody @Valid UserNicknameUpdateRequest request) { | ||||
|         if (userOperationValidator.isMyself(userId)) { | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.user.data.FavoriteProjectPageCondition; | ||||
| import com.databasir.core.domain.user.data.FavoriteProjectPageResponse; | ||||
| import com.databasir.core.domain.user.service.UserProjectService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.Pageable; | ||||
| @@ -18,11 +20,13 @@ import static org.springframework.data.domain.Sort.Direction.DESC; | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @Validated | ||||
| @Tag(name = "UserProjectController", description = "用户关注项目 API") | ||||
| public class UserProjectController { | ||||
|  | ||||
|     private final UserProjectService userProjectService; | ||||
|  | ||||
|     @GetMapping(Routes.UserProject.LIST) | ||||
|     @Operation(summary = "获取用户关注项目列表") | ||||
|     public JsonData<Page<FavoriteProjectPageResponse>> listFavorites( | ||||
|             @PageableDefault(sort = "id", direction = DESC) Pageable pageable, | ||||
|             FavoriteProjectPageCondition condition) { | ||||
| @@ -34,6 +38,7 @@ public class UserProjectController { | ||||
|     } | ||||
|  | ||||
|     @PostMapping(Routes.UserProject.ADD) | ||||
|     @Operation(summary = "添加用户关注项目") | ||||
|     public JsonData<Void> addFavorite(@PathVariable Integer projectId) { | ||||
|         DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext() | ||||
|                 .getAuthentication() | ||||
| @@ -44,6 +49,7 @@ public class UserProjectController { | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping(Routes.UserProject.REMOVE) | ||||
|     @Operation(summary = "删除用户关注项目") | ||||
|     public JsonData<Void> removeFavorite(@PathVariable Integer projectId) { | ||||
|         DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext() | ||||
|                 .getAuthentication() | ||||
|   | ||||
| @@ -2,7 +2,7 @@ package com.databasir.api.advice; | ||||
|  | ||||
| import com.databasir.api.config.security.DatabasirUserDetails; | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.log.data.OperationLogRequest; | ||||
| import com.databasir.core.domain.log.service.OperationLogService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| @@ -38,17 +38,17 @@ public class OperationLogAspect { | ||||
|     private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); | ||||
|  | ||||
|     @AfterReturning(value = "@annotation(operation)", returning = "returnValue") | ||||
|     public void log(JoinPoint joinPoint, Object returnValue, Operation operation) { | ||||
|     public void log(JoinPoint joinPoint, Object returnValue, AuditLog operation) { | ||||
|         saveLog(operation, joinPoint, (JsonData<Object>) returnValue); | ||||
|     } | ||||
|  | ||||
|     @AfterThrowing(value = "@annotation(operation)", throwing = "ex") | ||||
|     public void log(JoinPoint joinPoint, RuntimeException ex, Operation operation) { | ||||
|     public void log(JoinPoint joinPoint, RuntimeException ex, AuditLog operation) { | ||||
|         saveLog(operation, joinPoint, JsonData.error("-1", ex.getMessage())); | ||||
|         throw ex; | ||||
|     } | ||||
|  | ||||
|     private void saveLog(Operation operation, JoinPoint joinPoint, JsonData<Object> result) { | ||||
|     private void saveLog(AuditLog operation, JoinPoint joinPoint, JsonData<Object> result) { | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|         Method method = signature.getMethod(); | ||||
|         Object[] arguments = joinPoint.getArgs(); | ||||
| @@ -65,7 +65,7 @@ public class OperationLogAspect { | ||||
|         int userId = userId(); | ||||
|         String username = principal.getUserPojo().getUsername(); | ||||
|         String nickname = principal.getUserPojo().getNickname(); | ||||
|         if (userId == Operation.Types.SYSTEM_USER_ID) { | ||||
|         if (userId == AuditLog.Types.SYSTEM_USER_ID) { | ||||
|             username = "system"; | ||||
|             nickname = "system"; | ||||
|         } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| server.port=8080 | ||||
| logging.level.org.jooq=INFO | ||||
| spring.jooq.sql-dialect=mysql | ||||
| springdoc.swagger-ui.path=/open-api.html | ||||
| # flyway | ||||
| spring.flyway.enabled=true | ||||
| spring.flyway.baseline-on-migrate=true | ||||
|   | ||||
| @@ -15,3 +15,5 @@ spring.flyway.locations=classpath:db/migration | ||||
| # driver directory | ||||
| databasir.db.driver-directory=drivers | ||||
| databasir.jwt.secret=${DATABASIR_JWT_SECRET:${random.uuid}} | ||||
| # api doc | ||||
| springdoc.api-docs.enabled=false | ||||
| @@ -39,6 +39,7 @@ subprojects { | ||||
|         freemarkerVersion = '2.3.31' | ||||
|         retrofitVersion = '2.9.0' | ||||
|         commonsIoVersion = '2.11.0' | ||||
|         springDocVersion = '1.6.8' | ||||
|     } | ||||
|  | ||||
|     dependencies { | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import java.lang.annotation.Target; | ||||
| 
 | ||||
| @Target(ElementType.METHOD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| public @interface Operation { | ||||
| public @interface AuditLog { | ||||
| 
 | ||||
|     String module(); | ||||
| 
 | ||||
| @@ -1,7 +1,7 @@ | ||||
| package com.databasir.core.domain.log.service; | ||||
|  | ||||
| import com.databasir.common.JsonData; | ||||
| import com.databasir.core.domain.log.annotation.Operation; | ||||
| import com.databasir.core.domain.log.annotation.AuditLog; | ||||
| import com.databasir.core.domain.log.converter.OperationLogPojoConverter; | ||||
| import com.databasir.core.domain.log.converter.OperationLogRequestConverter; | ||||
| import com.databasir.core.domain.log.data.OperationLogPageCondition; | ||||
| @@ -55,7 +55,7 @@ public class OperationLogService { | ||||
|             OperationLogRequest log = OperationLogRequest.builder() | ||||
|                     .isSuccess(false) | ||||
|                     .operationCode("login") | ||||
|                     .operationModule(Operation.Modules.LOGIN) | ||||
|                     .operationModule(AuditLog.Modules.LOGIN) | ||||
|                     .operationName("登录") | ||||
|                     .operatorNickname(username) | ||||
|                     .operatorUsername(username) | ||||
| @@ -81,7 +81,7 @@ public class OperationLogService { | ||||
|                     .isSuccess(success) | ||||
|                     .involvedUserId(user.getId()) | ||||
|                     .operationCode("login") | ||||
|                     .operationModule(Operation.Modules.LOGIN) | ||||
|                     .operationModule(AuditLog.Modules.LOGIN) | ||||
|                     .operationName("登录") | ||||
|                     .operatorNickname(user.getNickname()) | ||||
|                     .operatorUsername(user.getUsername()) | ||||
|   | ||||
 Submodule databasir-frontend updated: db483af6ed...2de726a650
									
								
							
		Reference in New Issue
	
	Block a user