├── .github └── workflows │ ├── auto-check.yml │ ├── auto-docker-latest.yml │ ├── auto-jar-latest.yml │ ├── codeql.yml │ └── manual-release.yml ├── .gitignore ├── .gitmodules ├── Dockerfile ├── LICENSE ├── README.md ├── api.gradle ├── api ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── databasir │ │ ├── DatabasirApplication.java │ │ ├── api │ │ ├── AuditLogController.java │ │ ├── DatabaseTypeController.java │ │ ├── DocumentController.java │ │ ├── DocumentDescriptionController.java │ │ ├── DocumentDiscussionController.java │ │ ├── DocumentTemplateController.java │ │ ├── GroupController.java │ │ ├── IndexController.java │ │ ├── LoginAppController.java │ │ ├── LoginController.java │ │ ├── MockDataController.java │ │ ├── ProjectController.java │ │ ├── Routes.java │ │ ├── SearchController.java │ │ ├── SettingController.java │ │ ├── UserController.java │ │ ├── UserProjectController.java │ │ ├── advice │ │ │ ├── DatabasirExceptionAdvice.java │ │ │ └── OperationLogAspect.java │ │ ├── common │ │ │ └── LoginUserContext.java │ │ ├── config │ │ │ ├── SecurityConfig.java │ │ │ ├── WebConfig.java │ │ │ ├── i18n │ │ │ │ └── I18nConfig.java │ │ │ ├── oauth2 │ │ │ │ ├── DatabasirOAuth2Authentication.java │ │ │ │ ├── DatabasirOauth2LoginFilter.java │ │ │ │ └── OAuth2AuthenticationSuccessHandler.java │ │ │ └── security │ │ │ │ ├── DatabasirAuthenticationEntryPoint.java │ │ │ │ ├── DatabasirAuthenticationFailureHandler.java │ │ │ │ ├── DatabasirAuthenticationSuccessHandler.java │ │ │ │ ├── DatabasirJwtTokenFilter.java │ │ │ │ ├── DatabasirUserDetailService.java │ │ │ │ └── DatabasirUserDetails.java │ │ └── validator │ │ │ ├── CronExpressionValidator.java │ │ │ ├── DatabaseTypeValidator.java │ │ │ └── UserOperationValidator.java │ │ └── job │ │ ├── ProjectSyncJob.java │ │ ├── ProjectSyncJobScheduler.java │ │ ├── ProjectSyncTaskScheduler.java │ │ └── config │ │ └── ProjectSyncTaskThreadPoolConfig.java │ └── resources │ ├── application-local.properties │ ├── application.properties │ ├── i18n │ ├── messages_en.properties │ └── messages_zh_CN.properties │ └── static │ ├── css │ ├── 14.2e1c75a1.css │ ├── 227.90d5c1b0.css │ ├── 278.b8c2d37b.css │ ├── 282.f2905e33.css │ ├── 314.6b48a93a.css │ ├── 421.2e1c75a1.css │ ├── 718.67c86358.css │ ├── 770.80f6e2e0.css │ ├── 865.7df1e56e.css │ ├── app.7cd6f647.css │ └── chunk-vendors.113af7af.css │ ├── favicon.ico │ ├── img │ ├── MariaDB.6b8e15d1.svg │ ├── MySQL.c8f47618.svg │ ├── Oracle.c9ed26e0.svg │ ├── PostgreSQL.6e3d3a5e.svg │ ├── Sqlserver.deff7c4c.svg │ ├── default.acc0220f.svg │ ├── doc-table.e13752a1.svg │ ├── github.e45f4724.svg │ ├── gitlab.6b1155ee.svg │ ├── jar.a6df0ab2.svg │ ├── logo.1630e98e.png │ └── wework.aaf3f725.svg │ ├── index.html │ └── js │ ├── 109.e4093265.js │ ├── 109.e4093265.js.map │ ├── 14.1b552b49.js │ ├── 14.1b552b49.js.map │ ├── 227-legacy.7af18d8d.js │ ├── 227-legacy.7af18d8d.js.map │ ├── 227.7ef7b34b.js │ ├── 227.7ef7b34b.js.map │ ├── 278-legacy.df5f11d0.js │ ├── 278-legacy.df5f11d0.js.map │ ├── 278.15ed8ea3.js │ ├── 278.15ed8ea3.js.map │ ├── 282-legacy.9cf1cfb7.js │ ├── 282-legacy.9cf1cfb7.js.map │ ├── 282.a6bbdf00.js │ ├── 282.a6bbdf00.js.map │ ├── 314-legacy.c2e0f0f0.js │ ├── 314-legacy.c2e0f0f0.js.map │ ├── 314.779fe31f.js │ ├── 314.779fe31f.js.map │ ├── 351-legacy.189e8004.js │ ├── 351-legacy.189e8004.js.map │ ├── 351.6458e4cc.js │ ├── 351.6458e4cc.js.map │ ├── 421-legacy.fba50dcf.js │ ├── 421-legacy.fba50dcf.js.map │ ├── 465-legacy.8d5a9136.js │ ├── 465-legacy.8d5a9136.js.map │ ├── 469-legacy.aeed05a4.js │ ├── 469-legacy.aeed05a4.js.map │ ├── 469.99f1a7a9.js │ ├── 469.99f1a7a9.js.map │ ├── 718-legacy.64a09ee9.js │ ├── 718-legacy.64a09ee9.js.map │ ├── 718.a8630372.js │ ├── 718.a8630372.js.map │ ├── 745-legacy.7435dc44.js │ ├── 745-legacy.7435dc44.js.map │ ├── 745.4ce4ec11.js │ ├── 745.4ce4ec11.js.map │ ├── 770-legacy.506ec518.js │ ├── 770-legacy.506ec518.js.map │ ├── 770.3f7118df.js │ ├── 770.3f7118df.js.map │ ├── 842-legacy.3aa4e234.js │ ├── 842-legacy.3aa4e234.js.map │ ├── 842.eb6a2c3f.js │ ├── 842.eb6a2c3f.js.map │ ├── 865-legacy.07ab0cbc.js │ ├── 865-legacy.07ab0cbc.js.map │ ├── 865.1902074c.js │ ├── 865.1902074c.js.map │ ├── app-legacy.f88054d8.js │ ├── app-legacy.f88054d8.js.map │ ├── app.33790e0c.js │ ├── app.33790e0c.js.map │ ├── chunk-vendors-legacy.ed3287b0.js │ ├── chunk-vendors-legacy.ed3287b0.js.map │ ├── chunk-vendors.661f96f0.js │ └── chunk-vendors.661f96f0.js.map ├── build.gradle ├── common ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── databasir │ │ └── common │ │ ├── DatabasirErrors.java │ │ ├── DatabasirException.java │ │ ├── JsonData.java │ │ ├── SystemException.java │ │ ├── codec │ │ ├── Aes.java │ │ ├── Rsa.java │ │ └── Sha.java │ │ └── exception │ │ ├── Forbidden.java │ │ └── InvalidTokenException.java │ └── test │ └── java │ └── com │ └── databasir │ └── common │ └── codec │ └── CodecTest.java ├── config └── checkstyle │ └── checkstyle.xml ├── core ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── databasir │ │ │ └── core │ │ │ ├── config │ │ │ ├── AsyncConfig.java │ │ │ └── RestTemplateConfig.java │ │ │ ├── domain │ │ │ ├── DomainErrors.java │ │ │ ├── app │ │ │ │ ├── OpenAuthAppService.java │ │ │ │ ├── common │ │ │ │ │ ├── CommonProperties.java │ │ │ │ │ ├── GithubProperties.java │ │ │ │ │ ├── GitlabProperties.java │ │ │ │ │ └── WeWorkProperties.java │ │ │ │ ├── converter │ │ │ │ │ ├── OAuthAppResponseConverter.java │ │ │ │ │ └── OauthAppConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── OAuthAppCreateRequest.java │ │ │ │ │ ├── OAuthAppDetailResponse.java │ │ │ │ │ ├── OAuthAppPageCondition.java │ │ │ │ │ ├── OAuthAppPageResponse.java │ │ │ │ │ ├── OAuthAppPlatformResponse.java │ │ │ │ │ ├── OAuthAppResponse.java │ │ │ │ │ ├── OAuthAppUpdateRequest.java │ │ │ │ │ └── OauthAppPropertyData.java │ │ │ │ ├── exception │ │ │ │ │ └── DatabasirAuthenticationException.java │ │ │ │ ├── handler │ │ │ │ │ ├── GithubOpenAuthHandler.java │ │ │ │ │ ├── GitlabOpenAuthHandler.java │ │ │ │ │ ├── OAuthProcessContext.java │ │ │ │ │ ├── OAuthProcessResult.java │ │ │ │ │ ├── OpenAuthHandler.java │ │ │ │ │ ├── OpenAuthHandlers.java │ │ │ │ │ └── WeWorkOpenAuthHandler.java │ │ │ │ └── validator │ │ │ │ │ └── OauthPropertiesValidator.java │ │ │ ├── database │ │ │ │ ├── converter │ │ │ │ │ └── DatabaseTypeConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── DatabaseTypeCreateRequest.java │ │ │ │ │ ├── DatabaseTypeDetailResponse.java │ │ │ │ │ ├── DatabaseTypePageCondition.java │ │ │ │ │ ├── DatabaseTypePageResponse.java │ │ │ │ │ ├── DatabaseTypeSimpleResponse.java │ │ │ │ │ ├── DatabaseTypeUpdateRequest.java │ │ │ │ │ ├── DriverClassNameResolveRequest.java │ │ │ │ │ └── DriverDownloadRequest.java │ │ │ │ ├── service │ │ │ │ │ └── DatabaseTypeService.java │ │ │ │ └── validator │ │ │ │ │ └── DatabaseTypeUpdateValidator.java │ │ │ ├── description │ │ │ │ ├── converter │ │ │ │ │ └── DocumentDescriptionConverter.java │ │ │ │ ├── data │ │ │ │ │ └── DocumentDescriptionSaveRequest.java │ │ │ │ ├── event │ │ │ │ │ └── DescriptionUpdated.java │ │ │ │ └── service │ │ │ │ │ └── DocumentDescriptionService.java │ │ │ ├── discussion │ │ │ │ ├── converter │ │ │ │ │ └── DiscussionResponseConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── DiscussionCreateRequest.java │ │ │ │ │ ├── DiscussionListCondition.java │ │ │ │ │ └── DiscussionResponse.java │ │ │ │ ├── event │ │ │ │ │ ├── DiscussionCreated.java │ │ │ │ │ └── converter │ │ │ │ │ │ └── DiscussionEventConverter.java │ │ │ │ └── service │ │ │ │ │ └── DocumentDiscussionService.java │ │ │ ├── document │ │ │ │ ├── converter │ │ │ │ │ ├── DatabaseMetaConverter.java │ │ │ │ │ ├── DocumentDiffConverter.java │ │ │ │ │ ├── DocumentFullTextConverter.java │ │ │ │ │ ├── DocumentPojoConverter.java │ │ │ │ │ ├── DocumentResponseConverter.java │ │ │ │ │ ├── DocumentSimpleResponseConverter.java │ │ │ │ │ ├── DocumentTemplatePropertiesUpdateRequestConverter.java │ │ │ │ │ ├── DocumentTemplatePropertyResponseConverter.java │ │ │ │ │ └── TableResponseConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── DatabaseDocumentResponse.java │ │ │ │ │ ├── DatabaseDocumentSimpleResponse.java │ │ │ │ │ ├── DatabaseDocumentVersionResponse.java │ │ │ │ │ ├── DocumentFileTypeResponse.java │ │ │ │ │ ├── DocumentTemplatePropertiesResponse.java │ │ │ │ │ ├── DocumentTemplatePropertiesUpdateRequest.java │ │ │ │ │ ├── TableDocumentRequest.java │ │ │ │ │ ├── TableDocumentResponse.java │ │ │ │ │ ├── TableResponse.java │ │ │ │ │ └── diff │ │ │ │ │ │ ├── ColumnDocDiff.java │ │ │ │ │ │ ├── DatabaseDocDiff.java │ │ │ │ │ │ ├── DiffAble.java │ │ │ │ │ │ ├── ForeignKeyDocDiff.java │ │ │ │ │ │ ├── IndexDocDiff.java │ │ │ │ │ │ ├── TableDocDiff.java │ │ │ │ │ │ └── TriggerDocDiff.java │ │ │ │ ├── diff │ │ │ │ │ ├── BaseTypeFieldEqualFunction.java │ │ │ │ │ ├── DiffTypePredictor.java │ │ │ │ │ └── DocumentDiffChecker.java │ │ │ │ ├── event │ │ │ │ │ └── DocumentUpdated.java │ │ │ │ ├── generator │ │ │ │ │ ├── DocumentFileGenerator.java │ │ │ │ │ ├── DocumentFileType.java │ │ │ │ │ ├── markdown │ │ │ │ │ │ ├── MarkdownBuilder.java │ │ │ │ │ │ └── MarkdownDocumentFileGenerator.java │ │ │ │ │ └── plantuml │ │ │ │ │ │ ├── BasePlantUmlFileGenerator.java │ │ │ │ │ │ ├── PlantUmlErSvgFileGenerator.java │ │ │ │ │ │ └── PlantUmlPngFileGenerator.java │ │ │ │ └── service │ │ │ │ │ ├── DocumentService.java │ │ │ │ │ ├── DocumentSyncService.java │ │ │ │ │ └── DocumentTemplateService.java │ │ │ ├── group │ │ │ │ ├── converter │ │ │ │ │ ├── GroupConverter.java │ │ │ │ │ └── GroupResponseConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── GroupCreateRequest.java │ │ │ │ │ ├── GroupMemberCreateRequest.java │ │ │ │ │ ├── GroupMemberPageCondition.java │ │ │ │ │ ├── GroupMemberPageResponse.java │ │ │ │ │ ├── GroupMemberRoleUpdateRequest.java │ │ │ │ │ ├── GroupPageCondition.java │ │ │ │ │ ├── GroupPageResponse.java │ │ │ │ │ ├── GroupResponse.java │ │ │ │ │ └── GroupUpdateRequest.java │ │ │ │ ├── event │ │ │ │ │ ├── GroupCreated.java │ │ │ │ │ ├── GroupDeleted.java │ │ │ │ │ └── GroupUpdated.java │ │ │ │ └── service │ │ │ │ │ └── GroupService.java │ │ │ ├── log │ │ │ │ ├── annotation │ │ │ │ │ └── AuditLog.java │ │ │ │ ├── converter │ │ │ │ │ ├── OperationLogConverter.java │ │ │ │ │ └── OperationLogRequestConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── OperationLogPageCondition.java │ │ │ │ │ ├── OperationLogPageResponse.java │ │ │ │ │ └── OperationLogRequest.java │ │ │ │ └── service │ │ │ │ │ └── OperationLogService.java │ │ │ ├── login │ │ │ │ ├── data │ │ │ │ │ ├── AccessTokenRefreshRequest.java │ │ │ │ │ ├── AccessTokenRefreshResponse.java │ │ │ │ │ ├── LoginKeyResponse.java │ │ │ │ │ └── UserLoginResponse.java │ │ │ │ └── service │ │ │ │ │ └── LoginService.java │ │ │ ├── mock │ │ │ │ ├── MockDataService.java │ │ │ │ ├── converter │ │ │ │ │ ├── MockDataRuleConverter.java │ │ │ │ │ └── MockDataRuleResponseConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── ColumnMockRuleSaveRequest.java │ │ │ │ │ ├── MockDataGenerateCondition.java │ │ │ │ │ ├── MockDataRuleListCondition.java │ │ │ │ │ └── MockDataRuleResponse.java │ │ │ │ ├── factory │ │ │ │ │ ├── AutoMockDataFactory.java │ │ │ │ │ ├── FakerMockDataFactory.java │ │ │ │ │ ├── MockColumnRule.java │ │ │ │ │ ├── MockDataFactory.java │ │ │ │ │ └── ScriptMockDataFactory.java │ │ │ │ ├── generator │ │ │ │ │ ├── ColumnMockData.java │ │ │ │ │ ├── MockDataContext.java │ │ │ │ │ ├── MockDataGenerator.java │ │ │ │ │ └── TableMockData.java │ │ │ │ ├── script │ │ │ │ │ ├── MockScriptEvaluator.java │ │ │ │ │ └── SpelScriptEvaluator.java │ │ │ │ └── validator │ │ │ │ │ ├── MockDataSaveValidator.java │ │ │ │ │ └── MockDataValidator.java │ │ │ ├── project │ │ │ │ ├── converter │ │ │ │ │ ├── DataSourceConverter.java │ │ │ │ │ ├── ProjectConverter.java │ │ │ │ │ ├── ProjectResponseConverter.java │ │ │ │ │ └── ProjectSimpleTaskResponseConverter.java │ │ │ │ ├── data │ │ │ │ │ ├── DataSourcePropertyValue.java │ │ │ │ │ ├── ProjectCreateRequest.java │ │ │ │ │ ├── ProjectDetailResponse.java │ │ │ │ │ ├── ProjectListCondition.java │ │ │ │ │ ├── ProjectSimpleResponse.java │ │ │ │ │ ├── ProjectTestConnectionRequest.java │ │ │ │ │ ├── ProjectUpdateRequest.java │ │ │ │ │ └── task │ │ │ │ │ │ ├── ProjectSimpleTaskResponse.java │ │ │ │ │ │ └── ProjectTaskListCondition.java │ │ │ │ ├── event │ │ │ │ │ ├── ProjectDeleted.java │ │ │ │ │ └── ProjectSaved.java │ │ │ │ └── service │ │ │ │ │ └── ProjectService.java │ │ │ ├── search │ │ │ │ ├── SearchService.java │ │ │ │ ├── converter │ │ │ │ │ └── SearchResponseConverter.java │ │ │ │ └── data │ │ │ │ │ └── SearchResponse.java │ │ │ ├── system │ │ │ │ ├── data │ │ │ │ │ ├── SystemEmailResponse.java │ │ │ │ │ └── SystemEmailUpdateRequest.java │ │ │ │ └── service │ │ │ │ │ └── SystemService.java │ │ │ └── user │ │ │ │ ├── converter │ │ │ │ ├── FavoriteProjectPageResponseConverter.java │ │ │ │ ├── UserConverter.java │ │ │ │ └── UserResponseConverter.java │ │ │ │ ├── data │ │ │ │ ├── FavoriteProjectCreateRequest.java │ │ │ │ ├── FavoriteProjectPageCondition.java │ │ │ │ ├── FavoriteProjectPageResponse.java │ │ │ │ ├── UserCreateRequest.java │ │ │ │ ├── UserDetailResponse.java │ │ │ │ ├── UserNicknameUpdateRequest.java │ │ │ │ ├── UserPageCondition.java │ │ │ │ ├── UserPageResponse.java │ │ │ │ ├── UserPasswordUpdateRequest.java │ │ │ │ ├── UserRoleAssignRequest.java │ │ │ │ └── UserSource.java │ │ │ │ ├── event │ │ │ │ ├── UserCreated.java │ │ │ │ ├── UserPasswordRenewed.java │ │ │ │ └── converter │ │ │ │ │ └── UserEventConverter.java │ │ │ │ └── service │ │ │ │ ├── UserProjectService.java │ │ │ │ └── UserService.java │ │ │ └── infrastructure │ │ │ ├── connection │ │ │ ├── CustomDatabaseConnectionFactory.java │ │ │ ├── DatabaseConnectionFactory.java │ │ │ ├── DatabaseConnectionService.java │ │ │ ├── DatabaseTypes.java │ │ │ ├── MysqlDatabaseConnectionFactory.java │ │ │ └── PostgresqlDatabaseConnectionFactory.java │ │ │ ├── constant │ │ │ └── RoleConstants.java │ │ │ ├── converter │ │ │ └── JsonConverter.java │ │ │ ├── driver │ │ │ ├── DriverResources.java │ │ │ └── DriverResult.java │ │ │ ├── event │ │ │ ├── EventPublisher.java │ │ │ └── subscriber │ │ │ │ ├── DescriptionEventSubscriber.java │ │ │ │ ├── DiscussionEventSubscriber.java │ │ │ │ ├── DocumentEventSubscriber.java │ │ │ │ ├── GroupEventSubscriber.java │ │ │ │ ├── ProjectEventSubscriber.java │ │ │ │ ├── SystemStartedEventSubscriber.java │ │ │ │ └── UserEventSubscriber.java │ │ │ ├── jwt │ │ │ └── JwtTokens.java │ │ │ ├── mail │ │ │ ├── MailSender.java │ │ │ ├── MailTemplateConfig.java │ │ │ └── MailTemplateProcessor.java │ │ │ └── remote │ │ │ ├── ClientConfig.java │ │ │ ├── github │ │ │ ├── GithubApiClient.java │ │ │ ├── GithubOauthClient.java │ │ │ ├── GithubRemoteService.java │ │ │ └── TokenRequest.java │ │ │ ├── gitlab │ │ │ ├── GitlabApiClient.java │ │ │ └── GitlabRemoteService.java │ │ │ └── wework │ │ │ ├── WeWorkApiClient.java │ │ │ └── WeWorkRemoteService.java │ └── resources │ │ ├── ftl │ │ └── mail │ │ │ ├── DiscussCreated.ftl │ │ │ ├── DocumentUpdated.ftl │ │ │ ├── PasswordRenew.ftl │ │ │ └── UserCreated.ftl │ │ └── oauth │ │ └── platform-properties-schema.json │ └── test │ ├── java │ └── com │ │ └── databasir │ │ └── core │ │ ├── BaseTest.java │ │ ├── CoreTestApplication.java │ │ ├── domain │ │ ├── database │ │ │ └── service │ │ │ │ └── DatabaseTypeServiceTest.java │ │ ├── description │ │ │ └── service │ │ │ │ └── DocumentDescriptionServiceTest.java │ │ ├── discussion │ │ │ └── service │ │ │ │ └── DocumentDiscussionServiceTest.java │ │ ├── document │ │ │ └── diff │ │ │ │ ├── BaseTypeFieldEqualFunctionTest.java │ │ │ │ ├── ComplexObject.java │ │ │ │ └── SimpleObject.java │ │ ├── group │ │ │ └── service │ │ │ │ └── GroupServiceTest.java │ │ ├── log │ │ │ └── service │ │ │ │ └── OperationLogServiceTest.java │ │ ├── login │ │ │ └── service │ │ │ │ └── LoginServiceTest.java │ │ ├── project │ │ │ └── service │ │ │ │ └── ProjectServiceTest.java │ │ └── user │ │ │ └── service │ │ │ ├── UserProjectServiceTest.java │ │ │ └── UserServiceTest.java │ │ └── infrastructure │ │ └── event │ │ └── subscriber │ │ ├── DocumentEventSubscriberTest.java │ │ └── UserEventSubscriberTest.java │ └── resources │ ├── application-ut.properties │ └── sql │ ├── domain │ ├── database │ │ ├── CreateDuplicate.sql │ │ ├── DeleteById.sql │ │ └── Update.sql │ ├── discussion │ │ ├── Create.sql │ │ └── DeleteById.sql │ ├── group │ │ ├── GroupDelete.sql │ │ ├── GroupUpdate.sql │ │ ├── MemberAdd.sql │ │ ├── MemberRemove.sql │ │ └── MemberRoleChange.sql │ ├── login │ │ ├── Generate.sql │ │ ├── RefreshAccessTokens.sql │ │ ├── RefreshAccessTokensWhenUserDisabled.sql │ │ └── RefreshAccessTokensWhenUserNotExists.sql │ ├── project │ │ ├── Delete.sql │ │ └── Update.sql │ └── user │ │ ├── AddFavorites.sql │ │ ├── AddSysOwnerTo.sql │ │ ├── RemoveFavorites.sql │ │ ├── RemoveSysOwnerFrom.sql │ │ ├── RenewPassword.sql │ │ ├── SwitchEnableStatus.sql │ │ ├── UpdateNickname.sql │ │ └── UpdatePassword.sql │ ├── event │ └── subscriber │ │ ├── DocumentEventSubscriberTest.sql │ │ └── UserEventSubscriberTest.sql │ └── init.sql ├── dao ├── build.gradle ├── generated-src │ └── jooq │ │ └── main │ │ └── java │ │ └── com │ │ └── databasir │ │ └── dao │ │ ├── Databasir.java │ │ ├── DefaultCatalog.java │ │ ├── Indexes.java │ │ ├── Keys.java │ │ ├── Tables.java │ │ └── tables │ │ ├── DataSourcePropertyTable.java │ │ ├── DataSourceTable.java │ │ ├── DatabaseDocumentTable.java │ │ ├── DatabaseTypeTable.java │ │ ├── DocumentDescriptionTable.java │ │ ├── DocumentDiscussionTable.java │ │ ├── DocumentFullTextTable.java │ │ ├── DocumentTemplatePropertyTable.java │ │ ├── GroupTable.java │ │ ├── LoginTable.java │ │ ├── MockDataRuleTable.java │ │ ├── OauthAppPropertyTable.java │ │ ├── OauthAppTable.java │ │ ├── OperationLogTable.java │ │ ├── ProjectSyncRuleTable.java │ │ ├── ProjectSyncTaskTable.java │ │ ├── ProjectTable.java │ │ ├── SysKeyTable.java │ │ ├── SysMailTable.java │ │ ├── TableColumnDocumentTable.java │ │ ├── TableDocumentTable.java │ │ ├── TableForeignKeyDocumentTable.java │ │ ├── TableIndexDocumentTable.java │ │ ├── TableTriggerDocumentTable.java │ │ ├── UserFavoriteProjectTable.java │ │ ├── UserRoleTable.java │ │ ├── UserTable.java │ │ ├── pojos │ │ ├── DataSource.java │ │ ├── DataSourceProperty.java │ │ ├── DatabaseDocument.java │ │ ├── DatabaseType.java │ │ ├── DocumentDescription.java │ │ ├── DocumentDiscussion.java │ │ ├── DocumentFullText.java │ │ ├── DocumentTemplateProperty.java │ │ ├── Group.java │ │ ├── Login.java │ │ ├── MockDataRule.java │ │ ├── OauthApp.java │ │ ├── OauthAppProperty.java │ │ ├── OperationLog.java │ │ ├── Project.java │ │ ├── ProjectSyncRule.java │ │ ├── ProjectSyncTask.java │ │ ├── SysKey.java │ │ ├── SysMail.java │ │ ├── TableColumnDocument.java │ │ ├── TableDocument.java │ │ ├── TableForeignKeyDocument.java │ │ ├── TableIndexDocument.java │ │ ├── TableTriggerDocument.java │ │ ├── User.java │ │ ├── UserFavoriteProject.java │ │ └── UserRole.java │ │ └── records │ │ ├── DataSourcePropertyRecord.java │ │ ├── DataSourceRecord.java │ │ ├── DatabaseDocumentRecord.java │ │ ├── DatabaseTypeRecord.java │ │ ├── DocumentDescriptionRecord.java │ │ ├── DocumentDiscussionRecord.java │ │ ├── DocumentFullTextRecord.java │ │ ├── DocumentTemplatePropertyRecord.java │ │ ├── GroupRecord.java │ │ ├── LoginRecord.java │ │ ├── MockDataRuleRecord.java │ │ ├── OauthAppPropertyRecord.java │ │ ├── OauthAppRecord.java │ │ ├── OperationLogRecord.java │ │ ├── ProjectRecord.java │ │ ├── ProjectSyncRuleRecord.java │ │ ├── ProjectSyncTaskRecord.java │ │ ├── SysKeyRecord.java │ │ ├── SysMailRecord.java │ │ ├── TableColumnDocumentRecord.java │ │ ├── TableDocumentRecord.java │ │ ├── TableForeignKeyDocumentRecord.java │ │ ├── TableIndexDocumentRecord.java │ │ ├── TableTriggerDocumentRecord.java │ │ ├── UserFavoriteProjectRecord.java │ │ ├── UserRecord.java │ │ └── UserRoleRecord.java └── src │ └── main │ ├── java │ └── com │ │ └── databasir │ │ └── dao │ │ ├── converter │ │ ├── DocumentTemplatePropertyTypeConverter.java │ │ ├── MockDataTypeConverter.java │ │ ├── OAuthAppTypeConverter.java │ │ └── ProjectSyncTaskStatusConverter.java │ │ ├── enums │ │ ├── DocumentTemplatePropertyType.java │ │ ├── MockDataType.java │ │ ├── OAuthAppType.java │ │ └── ProjectSyncTaskStatus.java │ │ ├── exception │ │ └── DataNotExistsException.java │ │ ├── impl │ │ ├── BaseDao.java │ │ ├── DataSourceDao.java │ │ ├── DataSourcePropertyDao.java │ │ ├── DatabaseDocumentDao.java │ │ ├── DatabaseTypeDao.java │ │ ├── DocumentDescriptionDao.java │ │ ├── DocumentDiscussionDao.java │ │ ├── DocumentFullTextDao.java │ │ ├── DocumentTemplatePropertyDao.java │ │ ├── GroupDao.java │ │ ├── LoginDao.java │ │ ├── MockDataRuleDao.java │ │ ├── OauthAppDao.java │ │ ├── OauthAppPropertyDao.java │ │ ├── OperationLogDao.java │ │ ├── ProjectDao.java │ │ ├── ProjectSyncRuleDao.java │ │ ├── ProjectSyncTaskDao.java │ │ ├── SysKeyDao.java │ │ ├── SysMailDao.java │ │ ├── TableColumnDocumentDao.java │ │ ├── TableDocumentDao.java │ │ ├── TableForeignKeyDocumentDao.java │ │ ├── TableIndexDocumentDao.java │ │ ├── TableTriggerDocumentDao.java │ │ ├── UserDao.java │ │ ├── UserFavoriteProjectDao.java │ │ └── UserRoleDao.java │ │ ├── strategy │ │ └── DatabasirPojoNamingStrategy.java │ │ └── value │ │ ├── DatabaseDocumentVersionPojo.java │ │ ├── DocumentDiscussionCountPojo.java │ │ ├── FullTextProjectInfoUpdatePojo.java │ │ ├── GroupMemberDetailPojo.java │ │ ├── GroupMemberSimplePojo.java │ │ ├── GroupProjectCountPojo.java │ │ └── ProjectQueryPojo.java │ └── resources │ └── db │ ├── init │ ├── init.sql │ └── v1.0.5~v1.0.6 data migration.sql │ └── migration │ ├── V1.2__mock_data.sql │ ├── V1.3__sync_task.sql │ ├── V1.4.1__driver_file.sql │ ├── V1.4.2__document_comment_type.sql │ ├── V1.4.3__trigger_name.sql │ ├── V1.4.4__document_full_text.sql │ ├── V1.4.5__oauth_prop.sql │ ├── V1.4.6__oauth_prop_migraiton.sql │ ├── V1.4.7__sys_mail.sql │ ├── V1.4.8__sys_mail.sql │ ├── V1.4__project_uk.sql │ └── V1__init.sql ├── databasir-sample-k3s.yaml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.Dockerfile ├── meta ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── databasir │ │ └── core │ │ ├── Databasir.java │ │ ├── DatabasirConfig.java │ │ ├── diff │ │ ├── Diffs.java │ │ ├── data │ │ │ ├── Diff.java │ │ │ ├── DiffType.java │ │ │ ├── FieldDiff.java │ │ │ └── RootDiff.java │ │ └── processor │ │ │ ├── ColumnDiffProcessor.java │ │ │ ├── DatabaseDiffProcessor.java │ │ │ ├── DiffProcessor.java │ │ │ ├── ForeignKeyDiffProcessor.java │ │ │ ├── IndexDiffProcessor.java │ │ │ ├── TableDiffProcessor.java │ │ │ └── TriggerDiffProcessor.java │ │ └── meta │ │ ├── data │ │ ├── ColumnMeta.java │ │ ├── DatabaseMeta.java │ │ ├── ForeignKeyMeta.java │ │ ├── IndexMeta.java │ │ ├── TableMeta.java │ │ └── TriggerMeta.java │ │ └── provider │ │ ├── AbstractSqlTriggerMetaProvider.java │ │ ├── ColumnMetaProvider.java │ │ ├── DatabaseMetaProvider.java │ │ ├── ForeignKeyMetaProvider.java │ │ ├── IndexMetaProvider.java │ │ ├── MetaProviders.java │ │ ├── TableMetaProvider.java │ │ ├── TriggerMetaProvider.java │ │ ├── condition │ │ ├── Condition.java │ │ └── TableCondition.java │ │ ├── jdbc │ │ ├── JdbcColumnMetaProvider.java │ │ ├── JdbcDatabaseMetaProvider.java │ │ ├── JdbcForeignKeyMetaProvider.java │ │ ├── JdbcIndexMetaProvider.java │ │ ├── JdbcTableMetaProvider.java │ │ └── JdbcTriggerMetaProvider.java │ │ ├── maria │ │ └── MariaTriggerMetaProvider.java │ │ ├── mysql │ │ └── MysqlTableTriggerMetaProvider.java │ │ ├── oracle │ │ └── OracleTriggerMetaProvider.java │ │ ├── postgresql │ │ └── PostgresqlTriggerMetaProvider.java │ │ └── sqlserver │ │ ├── SqlServerColumnMetaProvider.java │ │ ├── SqlServerTableMetaProvider.java │ │ └── SqlServerTriggerMetaProvider.java │ └── test │ ├── java │ └── com │ │ └── databasir │ │ └── core │ │ └── diff │ │ └── service │ │ └── DiffsTest.java │ └── resources │ └── ut │ └── diffsTest │ ├── diffDatabaseAdded │ ├── current.json │ └── original.json │ ├── diffDatabaseModified │ ├── current.json │ └── original.json │ ├── diffDatabaseRemoved │ ├── current.json │ └── original.json │ ├── diffDatabaseSame │ ├── current.json │ └── original.json │ ├── diffTableAdded │ ├── current.json │ └── original.json │ ├── diffTableFieldsAdded │ ├── current.json │ └── original.json │ ├── diffTableFieldsModified │ ├── current.json │ └── original.json │ ├── diffTableFieldsRemoved │ ├── current.json │ └── original.json │ ├── diffTableModified │ ├── current.json │ └── original.json │ └── diffTableRemoved │ ├── current.json │ └── original.json └── settings.gradle /.github/workflows/auto-docker-latest.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java#publishing-using-gradle 3 | 4 | name: docker latest 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'master' 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up JDK 11 18 | uses: actions/setup-java@v1 19 | with: 20 | java-version: '11' 21 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 22 | settings-path: ${{ github.workspace }} # location for the settings.xml file 23 | 24 | - name: Gradle Permission Grant 25 | run: chmod +x ./gradlew 26 | 27 | - name: Gradle Build 28 | run: ./gradlew api:build -x checkstyleMain -x checkstyleTest 29 | 30 | - name: Login to Docker Hub 31 | uses: docker/login-action@v1 32 | with: 33 | username: ${{ secrets.DOCKER_HUB_USERNAME }} 34 | password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} 35 | 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v1 38 | 39 | - name: Docker Image Release 40 | uses: docker/build-push-action@v2 41 | with: 42 | context: . 43 | file: ./local.Dockerfile 44 | platforms: linux/amd64,linux/arm64 45 | push: true 46 | tags: ${{ secrets.DOCKER_HUB_USERNAME }}/databasir:latest -------------------------------------------------------------------------------- /.github/workflows/auto-jar-latest.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java#publishing-using-gradle 3 | 4 | name: jar latest 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'master' 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: '11' 23 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 24 | settings-path: ${{ github.workspace }} # location for the settings.xml file 25 | 26 | - name: Validate Gradle wrapper 27 | uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b 28 | - name: Gradle Permission Grant 29 | run: chmod +x ./gradlew 30 | - name: Publish package 31 | uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee 32 | with: 33 | arguments: api:publish 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/** 2 | **/build/** 3 | .idea/** 4 | **/.DS_Store 5 | drivers/** 6 | temp/** 7 | node_modules/ 8 | .cache/ 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "databasir-frontend"] 2 | path = databasir-frontend 3 | url = https://github.com/vran-dev/databasir-frontend 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gradle:7.3-jdk11 as build 2 | WORKDIR /app 3 | ADD . /app 4 | RUN gradle api:build 5 | 6 | FROM openjdk:11.0.13-jre 7 | WORKDIR /app 8 | COPY --from=build /app/api/build/libs/databasir.jar /app/databasir.jar 9 | EXPOSE 8080 10 | 11 | ENTRYPOINT ["sh", "-c","java -Ddatabasir.db.url=${DATABASIR_DB_URL} -Ddatabasir.db.username=${DATABASIR_DB_USERNAME} -Ddatabasir.db.password=${DATABASIR_DB_PASSWORD} -jar /app/databasir.jar ${PARAMS}"] -------------------------------------------------------------------------------- /api.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'api' 2 | include 'meta' 3 | include 'common' 4 | include 'dao' 5 | include 'core' -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/DatabasirApplication.java: -------------------------------------------------------------------------------- 1 | package com.databasir; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | @SpringBootApplication(exclude = {R2dbcAutoConfiguration.class}) 9 | @EnableScheduling 10 | public class DatabasirApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DatabasirApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api; 2 | 3 | import com.databasir.common.JsonData; 4 | import io.swagger.v3.oas.annotations.Operation; 5 | import io.swagger.v3.oas.annotations.tags.Tag; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.bind.annotation.ResponseStatus; 11 | 12 | @Controller 13 | @Tag(name = "IndexController", description = "测活 API") 14 | public class IndexController { 15 | 16 | @GetMapping("/live") 17 | @ResponseBody 18 | @Operation(summary = "测活") 19 | public JsonData live() { 20 | return JsonData.ok("ok"); 21 | } 22 | 23 | @GetMapping("/") 24 | public String index() { 25 | return "index.html"; 26 | } 27 | 28 | @ResponseStatus(HttpStatus.NOT_FOUND) 29 | @Operation(summary = "404 统一跳转") 30 | public String handleResourceNotFoundException() { 31 | return "/index.html"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/SearchController.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api; 2 | 3 | import com.databasir.common.JsonData; 4 | import com.databasir.core.domain.search.SearchService; 5 | import com.databasir.core.domain.search.data.SearchResponse; 6 | import io.swagger.v3.oas.annotations.Operation; 7 | import io.swagger.v3.oas.annotations.tags.Tag; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.data.web.PageableDefault; 11 | import org.springframework.validation.annotation.Validated; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | @RestController 17 | @RequiredArgsConstructor 18 | @Validated 19 | @Tag(name = "SearchController", description = "全局搜索 API") 20 | public class SearchController { 21 | 22 | private final SearchService searchService; 23 | 24 | @GetMapping(Routes.Search.SEARCH) 25 | @Operation(summary = "搜索") 26 | public JsonData search(@PageableDefault(size = 50) Pageable pageable, 27 | @RequestParam(name = "query") String keyword) { 28 | return JsonData.ok(searchService.search(pageable, keyword)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/common/LoginUserContext.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.common; 2 | 3 | import com.databasir.api.config.security.DatabasirUserDetails; 4 | import org.springframework.security.core.context.SecurityContextHolder; 5 | 6 | public class LoginUserContext { 7 | 8 | public static Integer getLoginUserId() { 9 | DatabasirUserDetails principal = (DatabasirUserDetails) SecurityContextHolder.getContext() 10 | .getAuthentication() 11 | .getPrincipal(); 12 | return principal.getUser().getId(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/config/i18n/I18nConfig.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.config.i18n; 2 | 3 | import org.springframework.context.MessageSource; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.support.ResourceBundleMessageSource; 7 | import org.springframework.web.servlet.LocaleResolver; 8 | import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; 9 | 10 | import java.util.Locale; 11 | 12 | @Configuration 13 | public class I18nConfig { 14 | 15 | @Bean 16 | public LocaleResolver localeResolver() { 17 | AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); 18 | localeResolver.setDefaultLocale(Locale.CHINA); 19 | return localeResolver; 20 | } 21 | 22 | @Bean 23 | public MessageSource messageSource() { 24 | ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); 25 | messageSource.setDefaultEncoding("UTF-8"); 26 | messageSource.addBasenames("i18n.messages"); 27 | return messageSource; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/config/oauth2/DatabasirOAuth2Authentication.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.config.oauth2; 2 | 3 | import org.springframework.security.authentication.AbstractAuthenticationToken; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | public class DatabasirOAuth2Authentication extends AbstractAuthenticationToken { 7 | 8 | private Object credentials; 9 | 10 | private Object principal; 11 | 12 | public DatabasirOAuth2Authentication(UserDetails principal) { 13 | super(principal.getAuthorities()); 14 | this.credentials = null; 15 | this.principal = principal; 16 | setAuthenticated(false); 17 | } 18 | 19 | @Override 20 | public Object getCredentials() { 21 | return this.credentials; 22 | } 23 | 24 | @Override 25 | public Object getPrincipal() { 26 | return this.principal; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/validator/CronExpressionValidator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.validator; 2 | 3 | import com.databasir.core.domain.DomainErrors; 4 | import com.databasir.core.domain.project.data.ProjectCreateRequest; 5 | import com.databasir.core.domain.project.data.ProjectUpdateRequest; 6 | import org.quartz.CronExpression; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.text.ParseException; 10 | 11 | @Component 12 | public class CronExpressionValidator { 13 | 14 | public void isValidCron(ProjectUpdateRequest request) { 15 | if (request.getProjectSyncRule().getIsAutoSync()) { 16 | isValidCron(request.getProjectSyncRule().getAutoSyncCron()); 17 | } 18 | } 19 | 20 | public void isValidCron(ProjectCreateRequest request) { 21 | if (request.getProjectSyncRule().getIsAutoSync()) { 22 | isValidCron(request.getProjectSyncRule().getAutoSyncCron()); 23 | } 24 | } 25 | 26 | public void isValidCron(String cron) { 27 | try { 28 | new CronExpression(cron); 29 | } catch (ParseException pe) { 30 | throw DomainErrors.INVALID_CRON_EXPRESSION.exception(pe); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/validator/DatabaseTypeValidator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.validator; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import static com.databasir.core.domain.DomainErrors.*; 6 | 7 | @Component 8 | public class DatabaseTypeValidator { 9 | 10 | public void isValidUrlPattern(String urlPattern) { 11 | if (urlPattern == null) { 12 | throw INVALID_DATABASE_TYPE_URL_PATTERN.exception(); 13 | } 14 | if (!urlPattern.contains("{{jdbc.protocol}}")) { 15 | throw MISS_JDBC_PROTOCOL.exception(); 16 | } 17 | if (!urlPattern.contains("{{db.url}}")) { 18 | throw MISS_DB_URL.exception(); 19 | } 20 | if (!urlPattern.contains("{{db.schema}}") && !urlPattern.contains("{{db.name}}")) { 21 | throw MISS_DB_SCHEMA.exception(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/api/validator/UserOperationValidator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.api.validator; 2 | 3 | import com.databasir.api.config.security.DatabasirUserDetails; 4 | import com.databasir.core.domain.DomainErrors; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class UserOperationValidator { 10 | 11 | public void forbiddenIfUpdateSelfRole(Integer userId) { 12 | DatabasirUserDetails principal = (DatabasirUserDetails) SecurityContextHolder.getContext() 13 | .getAuthentication() 14 | .getPrincipal(); 15 | if (principal.getUser().getId().equals(userId)) { 16 | throw DomainErrors.CANNOT_UPDATE_SELF_ROLE.exception(); 17 | } 18 | } 19 | 20 | public boolean isMyself(Integer userId) { 21 | DatabasirUserDetails principal = (DatabasirUserDetails) SecurityContextHolder.getContext() 22 | .getAuthentication() 23 | .getPrincipal(); 24 | return principal.getUser().getId().equals(userId); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/job/ProjectSyncJob.java: -------------------------------------------------------------------------------- 1 | package com.databasir.job; 2 | 3 | import com.databasir.common.DatabasirException; 4 | import com.databasir.core.domain.project.service.ProjectService; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.quartz.Job; 8 | import org.quartz.JobDataMap; 9 | import org.quartz.JobExecutionContext; 10 | import org.quartz.JobExecutionException; 11 | 12 | @RequiredArgsConstructor 13 | @Slf4j 14 | public class ProjectSyncJob implements Job { 15 | 16 | private final ProjectService projectService; 17 | 18 | @Override 19 | public void execute(JobExecutionContext context) throws JobExecutionException { 20 | JobDataMap dataMap = context.getMergedJobDataMap(); 21 | Integer projectId = dataMap.getInt("projectId"); 22 | try { 23 | projectService.createSyncTask(projectId, -1, true); 24 | } catch (DatabasirException e) { 25 | log.warn("Failed to create sync task for project {}, {}", projectId, e.getMessage()); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /api/src/main/java/com/databasir/job/config/ProjectSyncTaskThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.databasir.job.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 6 | 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | 9 | @Configuration 10 | public class ProjectSyncTaskThreadPoolConfig { 11 | 12 | @Bean 13 | public ThreadPoolTaskExecutor projectSyncTaskThreadPoolTaskExecutor() { 14 | final int maxCorePoolSize = 12; 15 | final int maxPoolSize = 32; 16 | 17 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 18 | int availableProcessorCount = Runtime.getRuntime().availableProcessors() + 2; 19 | int corePoolSize = Math.min(maxCorePoolSize, availableProcessorCount); 20 | executor.setCorePoolSize(corePoolSize); 21 | executor.setMaxPoolSize(maxPoolSize); 22 | executor.setAllowCoreThreadTimeOut(true); 23 | executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); 24 | return executor; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /api/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | logging.level.org.jooq=INFO 3 | logging.level.com.databasir.core.domain.document.generator=debug 4 | spring.jooq.sql-dialect=mysql 5 | springdoc.swagger-ui.path=/open-api.html 6 | # flyway 7 | spring.flyway.enabled=true 8 | spring.flyway.baseline-on-migrate=true 9 | spring.flyway.locations=classpath:db/migration 10 | # db 11 | databasir.db.url=localhost:3306 12 | databasir.db.username=root 13 | databasir.db.password=123456 14 | databasir.db.driver-directory=drivers 15 | databasir.jwt.secret=DatabasirJwtSecret -------------------------------------------------------------------------------- /api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | # datasource 3 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 4 | spring.datasource.username=${databasir.db.username} 5 | spring.datasource.password=${databasir.db.password} 6 | spring.datasource.url=jdbc:mysql://${databasir.db.url}/${databasir.db.name:databasir} 7 | spring.servlet.multipart.max-file-size=100MB 8 | spring.servlet.multipart.max-request-size=100MB 9 | # jooq 10 | spring.jooq.sql-dialect=mysql 11 | # flyway 12 | spring.flyway.enabled=true 13 | spring.flyway.baseline-on-migrate=true 14 | spring.flyway.locations=classpath:db/migration 15 | # driver directory 16 | databasir.db.driver-directory=drivers 17 | databasir.jwt.secret=${DATABASIR_JWT_SECRET:${random.uuid}} 18 | # api doc 19 | springdoc.api-docs.enabled=false 20 | spring.mvc.async.request-timeout=3600000 -------------------------------------------------------------------------------- /api/src/main/resources/static/css/227.90d5c1b0.css: -------------------------------------------------------------------------------- 1 | .el-row{margin-bottom:12px}.cell{border:none;outline:none;width:100%;padding:3px}.cell:focus{background-color:#f4f4f5} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/278.b8c2d37b.css: -------------------------------------------------------------------------------- 1 | .el-row{margin-top:18px}.param-item{margin-bottom:8px} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/282.f2905e33.css: -------------------------------------------------------------------------------- 1 | .el-col{margin-bottom:20px} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/314.6b48a93a.css: -------------------------------------------------------------------------------- 1 | .card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:22px}.el-row{margin-bottom:6px}.el-row:last-child{margin-bottom:0}.el-col{margin-bottom:20px}.box{border-radius:6px;border-width:1px} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/770.80f6e2e0.css: -------------------------------------------------------------------------------- 1 | .login-main{margin:0 auto;margin-top:200px}.login-input{border-width:0 0 1px 0;border-style:solid;border-color:#ddd;width:100%;min-height:33px}.login-input::-moz-placeholder{color:hsla(0,0%,71%,.808)}.login-input:-ms-input-placeholder{color:hsla(0,0%,71%,.808)}.login-input::placeholder{color:hsla(0,0%,71%,.808)}.login-input:focus{outline:none;border-color:#000}.login-card{max-width:600px;min-width:500px;border-color:#000}.app-icon{--el-avatar-bg-color:transparent} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/865.7df1e56e.css: -------------------------------------------------------------------------------- 1 | .login-main{margin:0 auto;margin-top:200px} -------------------------------------------------------------------------------- /api/src/main/resources/static/css/app.7cd6f647.css: -------------------------------------------------------------------------------- 1 | .left-menu:not(.el-menu--collapse){height:100vh}.search-item{padding:10px;width:95%;margin-bottom:12px;margin-right:12px;border-radius:8px;border-width:0 0 1px 0;border-color:#ddd;border-style:solid}.search-item:hover{background-color:#f0f2f5;border-color:transparent}.search-item .jump{margin-right:8px}.search-item .header{display:flex;justify-content:space-between}.search-item .content{padding:10px}.search-item .content .item{margin-right:8px}.search-container{max-height:420px;margin-top:12px;overflow-y:auto;overflow-x:hidden}.badge{margin-top:12px;margin-right:20px}.search-container .el-tabs__item{line-height:unset}.second-title{color:#909399;font-size:14px}.databasir-nav{left:0;bottom:0}.databasir-main-header,.databasir-nav{position:fixed;transform:scale(1);top:0}.databasir-main-header{display:flex;justify-content:space-between;align-items:center;right:0;left:50px;padding:30px;margin-left:33px;background:#fff;z-index:100;border-color:#eee;border-width:0 0 1px 0;border-style:solid}.databasir{display:block}.databasir-main{position:relative;margin-left:60px;margin-top:80px;--el-main-padding:0px 20px 20px 20px}.databasir-main-expand{margin-left:50px}.databasir-main-content{max-width:95%;--el-main-padding:0px 20px 20px 20px}.h2{font-size:24px;margin-top:13px;margin-bottom:13px}.h2,.h3{color:#303133;font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Arial,sans-serif}.h3{font-size:20px;margin-top:18px;margin-bottom:18px} -------------------------------------------------------------------------------- /api/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vran-dev/databasir/01fa3284b6155dd104965307c162cbdaf22c9a3a/api/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /api/src/main/resources/static/img/default.acc0220f.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/src/main/resources/static/img/doc-table.e13752a1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /api/src/main/resources/static/img/gitlab.6b1155ee.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/src/main/resources/static/img/logo.1630e98e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vran-dev/databasir/01fa3284b6155dd104965307c162cbdaf22c9a3a/api/src/main/resources/static/img/logo.1630e98e.png -------------------------------------------------------------------------------- /api/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | databasir
-------------------------------------------------------------------------------- /api/src/main/resources/static/js/865.1902074c.js: -------------------------------------------------------------------------------- 1 | "use strict";(self["webpackChunkdatabasir"]=self["webpackChunkdatabasir"]||[]).push([[865],{68865:function(t,e,i){i.r(e),i.d(e,{default:function(){return h}});var a=i(66252),r=i(49963);const n=(0,a.Uk)("立即跳转");function s(t,e,i,s,o,l){const u=(0,a.up)("el-button"),d=(0,a.up)("el-result"),c=(0,a.up)("el-main"),h=(0,a.up)("el-container"),g=(0,a.Q2)("loading");return(0,a.wg)(),(0,a.j4)(h,null,{default:(0,a.w5)((()=>[(0,a.wy)(((0,a.wg)(),(0,a.j4)(c,{class:"login-main"},{default:(0,a.w5)((()=>[(0,a.wy)((0,a.Wm)(d,{icon:o.icon,title:o.title,"sub-title":o.subTitle},{extra:(0,a.w5)((()=>[(0,a.Wm)(u,{type:"primary",onClick:e[0]||(e[0]=t=>l.toIndexPage())},{default:(0,a.w5)((()=>[n])),_:1})])),_:1},8,["icon","title","sub-title"]),[[r.F8,!o.loading]])])),_:1})),[[g,o.loading]])])),_:1})}var o=i(40152),l=i(51836),u={data(){return{registrationId:null,icon:"",title:"",subTitle:"",loading:!0}},created(){this.registrationId=this.$route.params.id,this.login()},methods:{login(){const t=window.location.href,e=this.$route.query;e.redirect_uri=t,(0,o.rd)(this.registrationId,e).then((t=>{t.errCode?(this.title=t.errMessage,this.icon="error"):(l.E.saveUserLoginData(t.data),this.$store.commit("userUpdate",{nickname:t.data.nickname,username:t.data.username,email:t.data.email,avatar:t.data.avatar}),this.icon="success",this.$router.push({path:"/groups"})),this.loading=!1})).catch((t=>{console.log("login failed: "+t),this.icon="error",this.title="登陆失败,请重试",this.loading=!1}))},toIndexPage(){this.$router.push({path:"/"})}}},d=i(83744);const c=(0,d.Z)(u,[["render",s]]);var h=c}}]); 2 | //# sourceMappingURL=865.1902074c.js.map -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | implementation 'org.apache.shiro:shiro-crypto-cipher:1.8.0' 3 | } 4 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/DatabasirErrors.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common; 2 | 3 | public interface DatabasirErrors { 4 | 5 | String getErrCode(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/JsonData.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Optional; 6 | 7 | @Data 8 | public class JsonData { 9 | 10 | /** 11 | * maybe null 12 | */ 13 | private T data; 14 | 15 | /** 16 | * only exists when error happened 17 | */ 18 | private String errCode; 19 | 20 | /** 21 | * only exists when error happened 22 | */ 23 | private String errMessage; 24 | 25 | public static JsonData ok() { 26 | return ok(Optional.empty()); 27 | } 28 | 29 | public static JsonData ok(T data) { 30 | JsonData jsonData = new JsonData<>(); 31 | jsonData.setData(data); 32 | return jsonData; 33 | } 34 | 35 | public static JsonData ok(Optional data) { 36 | JsonData jsonData = new JsonData<>(); 37 | jsonData.setData(data.orElse(null)); 38 | return jsonData; 39 | } 40 | 41 | public static JsonData error(String errorCode, String errMessage) { 42 | JsonData jsonData = new JsonData<>(); 43 | jsonData.setErrCode(errorCode); 44 | jsonData.setErrMessage(errMessage); 45 | return jsonData; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/SystemException.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common; 2 | 3 | public class SystemException extends RuntimeException { 4 | 5 | private static final String MSG_INTERNAL_SERVER_ERROR = "服务器开小差了,请稍后再试"; 6 | 7 | public static final SystemException INTERNAL_SERVER_ERROR = new SystemException(MSG_INTERNAL_SERVER_ERROR); 8 | 9 | /** 10 | * @param msg the detail message 11 | */ 12 | public SystemException(String msg) { 13 | super(msg); 14 | } 15 | 16 | /** 17 | * @param msg the detail message 18 | * @param cause the nested exception 19 | */ 20 | public SystemException(String msg, Throwable cause) { 21 | super(msg, cause); 22 | } 23 | 24 | public static SystemException internalServerErrorWithCause(Throwable cause) { 25 | return new SystemException(MSG_INTERNAL_SERVER_ERROR, cause); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/codec/Aes.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common.codec; 2 | 3 | import org.apache.shiro.crypto.AesCipherService; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.security.Key; 7 | import java.util.Base64; 8 | 9 | public class Aes { 10 | 11 | public static String encryptToBase64Data(String data, String key) { 12 | return new AesCipherService() 13 | .encrypt(toBytes(data), toBytes(key)) 14 | .toBase64(); 15 | } 16 | 17 | public static String decryptFromBase64Data(String encryptData, String key) { 18 | byte[] originEncrypted = Base64.getDecoder().decode(toBytes(encryptData)); 19 | byte[] originKey = toBytes(key); 20 | return toString(new AesCipherService().decrypt(originEncrypted, originKey).getBytes()); 21 | } 22 | 23 | public static String randomBase64Key() { 24 | Key key = new AesCipherService().generateNewKey(); 25 | return Base64.getEncoder().encodeToString(key.getEncoded()); 26 | } 27 | 28 | private static byte[] toBytes(String data) { 29 | return data.getBytes(StandardCharsets.UTF_8); 30 | } 31 | 32 | private static String toString(byte[] bytes) { 33 | return new String(bytes, StandardCharsets.UTF_8); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/codec/Sha.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common.codec; 2 | 3 | import lombok.SneakyThrows; 4 | import org.apache.shiro.codec.Hex; 5 | 6 | import java.security.MessageDigest; 7 | 8 | public class Sha { 9 | 10 | @SneakyThrows 11 | public static String sha256(String data) { 12 | MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); 13 | messageDigest.update(data.getBytes()); 14 | byte[] bytes = messageDigest.digest(); 15 | return Hex.encodeToString(bytes); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/exception/Forbidden.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common.exception; 2 | 3 | public class Forbidden extends RuntimeException{ 4 | } 5 | -------------------------------------------------------------------------------- /common/src/main/java/com/databasir/common/exception/InvalidTokenException.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common.exception; 2 | 3 | import com.databasir.common.DatabasirErrors; 4 | import com.databasir.common.DatabasirException; 5 | 6 | public class InvalidTokenException extends DatabasirException { 7 | 8 | public InvalidTokenException(DatabasirErrors errorCodeMessage) { 9 | super(errorCodeMessage); 10 | } 11 | 12 | @Override 13 | public String toString() { 14 | return "InvalidTokenException:" + getErrCode(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /common/src/test/java/com/databasir/common/codec/CodecTest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.common.codec; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class CodecTest { 7 | 8 | @Test 9 | public void testAes() { 10 | String key = Aes.randomBase64Key(); 11 | Assertions.assertNotNull(key); 12 | 13 | String data = "hello world!"; 14 | String encryptedData = Aes.encryptToBase64Data(data, key); 15 | Assertions.assertNotNull(encryptedData); 16 | 17 | String decryptedData = Aes.decryptFromBase64Data(encryptedData, key); 18 | Assertions.assertEquals(data, decryptedData); 19 | } 20 | 21 | @Test 22 | public void testRsa() { 23 | Rsa.RsaBase64Key key = Rsa.generateBase64Key(); 24 | Assertions.assertNotNull(key); 25 | Assertions.assertNotNull(key.getPrivateBase64Key()); 26 | Assertions.assertNotNull(key.getPublicBase64Key()); 27 | 28 | String data = "Hello world!"; 29 | String encrypted = Rsa.encryptToBase64DataByPublicKey(data, key.getPublicBase64Key()); 30 | Assertions.assertNotNull(encrypted); 31 | 32 | String decrypted = Rsa.decryptFromBase64DataByPrivateKey(encrypted, key.getPrivateBase64Key()); 33 | Assertions.assertEquals(data, decrypted); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.client.ClientHttpRequestFactory; 6 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 7 | import org.springframework.http.converter.StringHttpMessageConverter; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | import java.nio.charset.StandardCharsets; 11 | 12 | @Configuration 13 | public class RestTemplateConfig { 14 | 15 | @Bean 16 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) { 17 | RestTemplate restTemplate = new RestTemplate(factory); 18 | // 支持中文编码 19 | restTemplate.getMessageConverters().set(1, 20 | new StringHttpMessageConverter(StandardCharsets.UTF_8)); 21 | return restTemplate; 22 | } 23 | 24 | @Bean 25 | public ClientHttpRequestFactory simpleClientHttpRequestFactory() { 26 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 27 | //单位为ms 28 | factory.setReadTimeout(1000 * 30); 29 | //单位为ms 30 | factory.setConnectTimeout(1000 * 5); 31 | return factory; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/common/CommonProperties.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.common; 2 | 3 | import com.databasir.dao.tables.pojos.OauthAppProperty; 4 | 5 | import java.util.List; 6 | 7 | public interface CommonProperties { 8 | 9 | String AUTH_HOST = "auth_host"; 10 | 11 | String RESOURCE_HOST = "resource_host"; 12 | 13 | CommonProperties INSTANCE = new CommonProperties() { 14 | }; 15 | 16 | default String get(List properties, String key) { 17 | return properties.stream() 18 | .filter(p -> p.getName().equals(key)) 19 | .map(OauthAppProperty::getValue) 20 | .findFirst() 21 | .orElseThrow(); 22 | } 23 | 24 | default String getAuthHost(List properties) { 25 | return get(properties, AUTH_HOST); 26 | } 27 | 28 | default String getResourceHost(List properties) { 29 | return get(properties, RESOURCE_HOST); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/common/GithubProperties.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.common; 2 | 3 | public interface GithubProperties extends CommonProperties { 4 | 5 | String CLIENT_ID = "client_id"; 6 | 7 | String CLIENT_SECRET = "client_secret"; 8 | } 9 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/common/GitlabProperties.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.common; 2 | 3 | public interface GitlabProperties extends CommonProperties { 4 | 5 | String CLIENT_ID = "client_id"; 6 | 7 | String CLIENT_SECRET = "client_secret"; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/common/WeWorkProperties.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.common; 2 | 3 | public interface WeWorkProperties extends CommonProperties { 4 | 5 | String APP_ID = "appid"; 6 | 7 | String AGENT_ID = "agentid"; 8 | 9 | String SECRET = "secret"; 10 | 11 | String REDIRECT_URL = "redirect_uri"; 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.converter; 2 | 3 | import com.databasir.core.domain.app.data.OAuthAppResponse; 4 | import com.databasir.dao.tables.pojos.OauthApp; 5 | import org.mapstruct.Mapper; 6 | 7 | @Mapper(componentModel = "spring") 8 | public interface OAuthAppResponseConverter { 9 | 10 | OAuthAppResponse to(OauthApp pojo); 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.Data; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class OAuthAppCreateRequest { 13 | 14 | @NotNull 15 | private String registrationId; 16 | 17 | @NotBlank 18 | private String appName; 19 | 20 | @NotNull 21 | private OAuthAppType appType; 22 | 23 | private String appIcon; 24 | 25 | private List properties = new ArrayList<>(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppDetailResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | @Data 11 | public class OAuthAppDetailResponse { 12 | 13 | private Integer id; 14 | 15 | private String appName; 16 | 17 | private String appIcon; 18 | 19 | private OAuthAppType appType; 20 | 21 | private String registrationId; 22 | 23 | private List properties = new ArrayList<>(); 24 | 25 | private LocalDateTime updateAt; 26 | 27 | private LocalDateTime createAt; 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.Tables; 4 | import com.databasir.dao.enums.OAuthAppType; 5 | import lombok.Data; 6 | import org.jooq.Condition; 7 | import org.jooq.impl.DSL; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Data 13 | public class OAuthAppPageCondition { 14 | 15 | private String appNameContains; 16 | 17 | private OAuthAppType appType; 18 | 19 | public Condition toCondition() { 20 | List conditions = new ArrayList<>(); 21 | if (appNameContains != null && !appNameContains.trim().equals("")) { 22 | conditions.add(Tables.OAUTH_APP.APP_NAME.contains(appNameContains)); 23 | } 24 | if (appType != null) { 25 | conditions.add(Tables.OAUTH_APP.APP_TYPE.eq(appType)); 26 | } 27 | return conditions.stream() 28 | .reduce(Condition::and) 29 | .orElse(DSL.trueCondition()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class OAuthAppPageResponse { 10 | 11 | private Integer id; 12 | 13 | private String appName; 14 | 15 | private String appIcon; 16 | 17 | private OAuthAppType appType; 18 | 19 | private String registrationId; 20 | 21 | private LocalDateTime updateAt; 22 | 23 | private LocalDateTime createAt; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPlatformResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Builder 16 | public class OAuthAppPlatformResponse { 17 | 18 | private OAuthAppType authAppType; 19 | 20 | private String authAppName; 21 | 22 | @Builder.Default 23 | private List properties = new ArrayList<>(); 24 | 25 | @Data 26 | @Builder 27 | @NoArgsConstructor 28 | @AllArgsConstructor 29 | public static class OAuthAppPlatformProperty { 30 | 31 | private String name; 32 | 33 | private String label; 34 | 35 | private String description; 36 | 37 | private Boolean required; 38 | 39 | private String defaultValue; 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class OAuthAppResponse { 16 | 17 | private Integer id; 18 | 19 | private String appName; 20 | 21 | private String appIcon; 22 | 23 | private OAuthAppType appType; 24 | 25 | private String registrationId; 26 | 27 | private LocalDateTime createAt; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OAuthAppUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import lombok.Data; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class OAuthAppUpdateRequest { 13 | 14 | @NotNull 15 | private Integer id; 16 | 17 | @NotBlank 18 | private String registrationId; 19 | 20 | @NotBlank 21 | private String appName; 22 | 23 | @NotNull 24 | private OAuthAppType appType; 25 | 26 | private String appIcon; 27 | 28 | private List properties = new ArrayList<>(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/data/OauthAppPropertyData.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class OauthAppPropertyData { 13 | 14 | private String name; 15 | 16 | private String value; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/exception/DatabasirAuthenticationException.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.exception; 2 | 3 | import com.databasir.common.DatabasirException; 4 | import lombok.Getter; 5 | import org.springframework.security.core.AuthenticationException; 6 | 7 | @Getter 8 | public class DatabasirAuthenticationException extends AuthenticationException { 9 | 10 | private final DatabasirException databasirException; 11 | 12 | public DatabasirAuthenticationException(DatabasirException databasirException) { 13 | super(databasirException.getErrCode(), databasirException); 14 | this.databasirException = databasirException; 15 | } 16 | 17 | public String getErrCode() { 18 | return databasirException.getErrCode(); 19 | } 20 | 21 | public Object[] getArgs() { 22 | return databasirException.getArgs(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessContext.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.handler; 2 | 3 | import com.databasir.dao.tables.pojos.OauthApp; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Builder 16 | public class OAuthProcessContext { 17 | 18 | private String registrationId; 19 | 20 | private OauthApp app; 21 | 22 | @Builder.Default 23 | private Map parameters = new HashMap<>(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessResult.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.handler; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class OAuthProcessResult { 7 | 8 | private String email; 9 | 10 | private String username; 11 | 12 | private String nickname; 13 | 14 | private String avatar; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/app/handler/OpenAuthHandler.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.app.handler; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import com.databasir.dao.tables.pojos.OauthApp; 5 | import com.databasir.dao.tables.pojos.OauthAppProperty; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public interface OpenAuthHandler { 11 | 12 | boolean support(OAuthAppType oauthAppType); 13 | 14 | String authorizationUrl(OauthApp app, 15 | List properties, 16 | Map requestParams); 17 | 18 | OAuthProcessResult process(OauthApp app, 19 | List properties, 20 | Map requestParams); 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/converter/DatabaseTypeConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.converter; 2 | 3 | import com.databasir.core.domain.database.data.DatabaseTypeCreateRequest; 4 | import com.databasir.core.domain.database.data.DatabaseTypeDetailResponse; 5 | import com.databasir.core.domain.database.data.DatabaseTypePageResponse; 6 | import com.databasir.core.domain.database.data.DatabaseTypeUpdateRequest; 7 | import com.databasir.dao.tables.pojos.DatabaseType; 8 | import org.mapstruct.Mapper; 9 | import org.mapstruct.Mapping; 10 | 11 | @Mapper(componentModel = "spring") 12 | public interface DatabaseTypeConverter { 13 | 14 | @Mapping(target = "id", ignore = true) 15 | @Mapping(target = "updateAt", ignore = true) 16 | @Mapping(target = "createAt", ignore = true) 17 | @Mapping(target = "jdbcDriverFilePath", source = "jdbcDriverFilePath") 18 | DatabaseType of(DatabaseTypeCreateRequest request, String jdbcDriverFilePath); 19 | 20 | @Mapping(target = "jdbcDriverFilePath", source = "jdbcDriverFilePath") 21 | DatabaseType of(DatabaseTypeUpdateRequest request, String jdbcDriverFilePath); 22 | 23 | DatabaseType of(DatabaseTypeUpdateRequest request); 24 | 25 | DatabaseTypeDetailResponse toDetailResponse(DatabaseType data); 26 | 27 | DatabaseTypePageResponse toPageResponse(DatabaseType pojo, Integer projectCount); 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypeCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | @Data 8 | public class DatabaseTypeCreateRequest { 9 | 10 | @NotBlank 11 | private String databaseType; 12 | 13 | private String icon; 14 | 15 | @NotBlank 16 | private String description; 17 | 18 | private String jdbcDriverFileUrl; 19 | 20 | private String jdbcDriverFilePath; 21 | 22 | @NotBlank 23 | private String jdbcDriverClassName; 24 | 25 | @NotBlank 26 | private String jdbcProtocol; 27 | 28 | @NotBlank 29 | private String urlPattern; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypeDetailResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class DatabaseTypeDetailResponse { 9 | 10 | private Integer id; 11 | 12 | private String databaseType; 13 | 14 | private String icon; 15 | 16 | private String description; 17 | 18 | private String jdbcDriverFileUrl; 19 | 20 | private String jdbcDriverFilePath; 21 | 22 | private String jdbcDriverClassName; 23 | 24 | private String jdbcProtocol; 25 | 26 | private String urlPattern; 27 | 28 | private Boolean deleted; 29 | 30 | private Integer deletedToken; 31 | 32 | private LocalDateTime updateAt; 33 | 34 | private LocalDateTime createAt; 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypePageCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import com.databasir.dao.Tables; 4 | import lombok.Data; 5 | import org.jooq.Condition; 6 | import org.jooq.impl.DSL; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class DatabaseTypePageCondition { 13 | 14 | private String databaseTypeContains; 15 | 16 | public Condition toCondition() { 17 | List conditions = new ArrayList<>(); 18 | conditions.add(Tables.DATABASE_TYPE.DELETED.eq(false)); 19 | if (databaseTypeContains != null && !databaseTypeContains.trim().equals("")) { 20 | conditions.add(Tables.DATABASE_TYPE.DATABASE_TYPE_.containsIgnoreCase(databaseTypeContains)); 21 | } 22 | return conditions.stream() 23 | .reduce(Condition::and) 24 | .orElse(DSL.trueCondition()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypePageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class DatabaseTypePageResponse { 9 | 10 | private Integer id; 11 | 12 | private String databaseType; 13 | 14 | private String icon; 15 | 16 | private String description; 17 | 18 | private String jdbcDriverFileUrl; 19 | 20 | private String jdbcDriverFilePath; 21 | 22 | private String jdbcDriverClassName; 23 | 24 | private String jdbcProtocol; 25 | 26 | private Boolean deleted; 27 | 28 | private Integer deletedToken; 29 | 30 | private Integer projectCount; 31 | 32 | private String urlPattern; 33 | 34 | private LocalDateTime updateAt; 35 | 36 | private LocalDateTime createAt; 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypeSimpleResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DatabaseTypeSimpleResponse { 7 | 8 | private String databaseType; 9 | 10 | private String description; 11 | 12 | private String urlPattern; 13 | 14 | private String jdbcProtocol; 15 | 16 | private String icon; 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DatabaseTypeUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.NotNull; 7 | 8 | @Data 9 | public class DatabaseTypeUpdateRequest { 10 | 11 | @NotNull 12 | private Integer id; 13 | 14 | @NotBlank 15 | private String databaseType; 16 | 17 | private String icon; 18 | 19 | @NotBlank 20 | private String description; 21 | 22 | private String jdbcDriverFileUrl; 23 | 24 | private String jdbcDriverFilePath; 25 | 26 | @NotBlank 27 | private String jdbcDriverClassName; 28 | 29 | @NotBlank 30 | private String jdbcProtocol; 31 | 32 | @NotBlank 33 | private String urlPattern; 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DriverClassNameResolveRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DriverClassNameResolveRequest { 7 | 8 | private String databaseType; 9 | 10 | private String jdbcDriverFileUrl; 11 | 12 | private String jdbcDriverFilePath; 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/database/data/DriverDownloadRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.database.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | @Data 8 | public class DriverDownloadRequest { 9 | 10 | @NotBlank 11 | private String databaseType; 12 | 13 | @NotBlank 14 | private String jdbcDriverFileUrl; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/description/converter/DocumentDescriptionConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.description.converter; 2 | 3 | import com.databasir.core.domain.description.data.DocumentDescriptionSaveRequest; 4 | import com.databasir.dao.tables.pojos.DocumentDescription; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | 8 | @Mapper(componentModel = "spring") 9 | public interface DocumentDescriptionConverter { 10 | 11 | @Mapping(target = "id", ignore = true) 12 | @Mapping(target = "createAt", ignore = true) 13 | @Mapping(target = "updateAt", ignore = true) 14 | DocumentDescription of(Integer projectId, 15 | Integer updateBy, 16 | DocumentDescriptionSaveRequest request); 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/description/data/DocumentDescriptionSaveRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.description.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DocumentDescriptionSaveRequest { 7 | 8 | private String tableName; 9 | 10 | private String columnName; 11 | 12 | private String content; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/description/event/DescriptionUpdated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.description.event; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class DescriptionUpdated { 9 | 10 | private Integer groupId; 11 | 12 | private Integer projectId; 13 | 14 | private Integer userId; 15 | 16 | private String tableName; 17 | 18 | private String columnName; 19 | 20 | private String description; 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/converter/DiscussionResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.converter; 2 | 3 | import com.databasir.core.domain.discussion.data.DiscussionResponse; 4 | import com.databasir.dao.tables.pojos.DocumentDiscussion; 5 | import com.databasir.dao.tables.pojos.User; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.Mapping; 8 | 9 | @Mapper(componentModel = "spring") 10 | public interface DiscussionResponseConverter { 11 | 12 | @Mapping(target = "id", source = "discussion.id") 13 | @Mapping(target = "createAt", source = "discussion.createAt") 14 | @Mapping(target = "content", source = "discussion.content") 15 | DiscussionResponse of(DocumentDiscussion discussion, 16 | User discussBy); 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.NotNull; 7 | 8 | @Data 9 | public class DiscussionCreateRequest { 10 | 11 | @NotBlank 12 | private String content; 13 | 14 | @NotNull 15 | private String tableName; 16 | 17 | private String columnName; 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionListCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.data; 2 | 3 | import com.databasir.dao.Tables; 4 | import lombok.Data; 5 | import org.jooq.Condition; 6 | import org.jooq.impl.DSL; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Data 13 | public class DiscussionListCondition { 14 | 15 | @NotBlank 16 | private String tableName; 17 | 18 | public Condition toCondition(Integer projectId) { 19 | List conditions = new ArrayList<>(); 20 | Condition condition = Tables.DOCUMENT_DISCUSSION.TABLE_NAME.eq(tableName); 21 | conditions.add(condition); 22 | conditions.add(Tables.DOCUMENT_DISCUSSION.PROJECT_ID.eq(projectId)); 23 | return conditions.stream().reduce(Condition::and).orElse(DSL.trueCondition()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class DiscussionResponse { 9 | 10 | private Integer id; 11 | 12 | private Integer projectId; 13 | 14 | private String content; 15 | 16 | private DiscussByUser discussBy; 17 | 18 | private LocalDateTime createAt; 19 | 20 | @Data 21 | public static class DiscussByUser { 22 | 23 | private Integer userId; 24 | 25 | private String nickname; 26 | 27 | private String email; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/event/DiscussionCreated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.event; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.Optional; 7 | 8 | @Data 9 | public class DiscussionCreated { 10 | 11 | private Integer discussionId; 12 | 13 | private Integer createByUserId; 14 | 15 | private String content; 16 | 17 | private Integer projectId; 18 | 19 | private String tableName; 20 | 21 | private String columnName; 22 | 23 | private LocalDateTime createAt; 24 | 25 | public Optional getColumnName() { 26 | return Optional.of(columnName); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/discussion/event/converter/DiscussionEventConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.discussion.event.converter; 2 | 3 | import com.databasir.core.domain.discussion.event.DiscussionCreated; 4 | import com.databasir.dao.tables.pojos.DocumentDiscussion; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | 8 | @Mapper(componentModel = "spring") 9 | public interface DiscussionEventConverter { 10 | 11 | @Mapping(target = "createByUserId", source = "pojo.userId") 12 | DiscussionCreated of(DocumentDiscussion pojo, Integer discussionId); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/converter/DocumentTemplatePropertiesUpdateRequestConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.converter; 2 | 3 | import com.databasir.core.domain.document.data.DocumentTemplatePropertiesUpdateRequest; 4 | import com.databasir.dao.enums.DocumentTemplatePropertyType; 5 | import com.databasir.dao.tables.pojos.DocumentTemplateProperty; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.Mapping; 8 | 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | @Mapper(componentModel = "spring") 13 | public interface DocumentTemplatePropertiesUpdateRequestConverter { 14 | 15 | @Mapping(target = "defaultValue", constant = "") 16 | DocumentTemplateProperty toPojo(DocumentTemplatePropertiesUpdateRequest.PropertyRequest property, 17 | DocumentTemplatePropertyType type); 18 | 19 | default List toPojo(DocumentTemplatePropertiesUpdateRequest request) { 20 | return request.getProperties().stream() 21 | .map(prop -> toPojo(prop, request.getType())) 22 | .collect(Collectors.toList()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/converter/DocumentTemplatePropertyResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.converter; 2 | 3 | import com.databasir.core.domain.document.data.DocumentTemplatePropertiesResponse; 4 | import com.databasir.dao.tables.pojos.DocumentTemplateProperty; 5 | import org.mapstruct.Mapper; 6 | 7 | import java.util.List; 8 | 9 | @Mapper(componentModel = "spring") 10 | public interface DocumentTemplatePropertyResponseConverter { 11 | 12 | List of( 13 | List pojoList); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/converter/TableResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.converter; 2 | 3 | import com.databasir.core.domain.document.data.TableResponse; 4 | import com.databasir.dao.tables.pojos.TableColumnDocument; 5 | import com.databasir.dao.tables.pojos.TableDocument; 6 | import org.mapstruct.Mapper; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.stream.Collectors; 11 | 12 | @Mapper(componentModel = "spring") 13 | public interface TableResponseConverter { 14 | 15 | default List from(List tables, 16 | Map> columnMapByTableId) { 17 | return tables.stream() 18 | .map(table -> from(table, columnMapByTableId.get(table.getId()))) 19 | .collect(Collectors.toList()); 20 | } 21 | 22 | TableResponse from(TableDocument table, List columns); 23 | 24 | TableResponse.ColumnResponse from(TableColumnDocument column); 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DatabaseDocumentResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @Data 14 | @Builder 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class DatabaseDocumentResponse { 18 | 19 | private Integer id; 20 | 21 | private String databaseName; 22 | 23 | private String schemaName; 24 | 25 | private String productName; 26 | 27 | private String productVersion; 28 | 29 | private Integer documentVersion; 30 | 31 | @Builder.Default 32 | private List tables = new ArrayList<>(); 33 | 34 | private LocalDateTime createAt; 35 | 36 | private DiffType diffType; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DatabaseDocumentSimpleResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import com.databasir.core.domain.document.data.diff.DiffAble; 5 | import lombok.Data; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class DatabaseDocumentSimpleResponse { 13 | 14 | private Integer id; 15 | 16 | private String projectName; 17 | 18 | private String databaseName; 19 | 20 | private String schemaName; 21 | 22 | private String productName; 23 | 24 | private String productVersion; 25 | 26 | private Integer documentVersion; 27 | 28 | private List tables = new ArrayList<>(); 29 | 30 | private LocalDateTime createAt; 31 | 32 | private DiffType diffType; 33 | 34 | @Data 35 | public static class TableData implements DiffAble { 36 | 37 | private Integer id; 38 | 39 | private String name; 40 | 41 | private String type; 42 | 43 | private String comment; 44 | 45 | private Integer discussionCount; 46 | 47 | private String description; 48 | 49 | private DiffType diffType; 50 | 51 | private TableData original; 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DatabaseDocumentVersionResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Builder 14 | public class DatabaseDocumentVersionResponse { 15 | 16 | private Integer databaseDocumentId; 17 | 18 | private Long version; 19 | 20 | private LocalDateTime createAt; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DocumentFileTypeResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import com.databasir.core.domain.document.generator.DocumentFileType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class DocumentFileTypeResponse { 12 | 13 | private String name; 14 | 15 | private String fileExtension; 16 | 17 | private DocumentFileType type; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DocumentTemplatePropertiesResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import com.databasir.dao.enums.DocumentTemplatePropertyType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | @Data 14 | @Builder 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class DocumentTemplatePropertiesResponse { 18 | 19 | @Builder.Default 20 | private List tableFieldNameProperties = Collections.emptyList(); 21 | 22 | @Builder.Default 23 | private List columnFieldNameProperties = Collections.emptyList(); 24 | 25 | @Builder.Default 26 | private List indexFieldNameProperties = Collections.emptyList(); 27 | 28 | @Builder.Default 29 | private List triggerFieldNameProperties = Collections.emptyList(); 30 | 31 | @Builder.Default 32 | private List foreignKeyFieldNameProperties = Collections.emptyList(); 33 | 34 | @Data 35 | public static class DocumentTemplatePropertyResponse { 36 | 37 | private String key; 38 | 39 | private String value; 40 | 41 | private String defaultValue; 42 | 43 | private DocumentTemplatePropertyType type; 44 | 45 | private LocalDateTime createAt; 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/DocumentTemplatePropertiesUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import com.databasir.dao.enums.DocumentTemplatePropertyType; 4 | import lombok.Data; 5 | 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.NotNull; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | @Data 12 | public class DocumentTemplatePropertiesUpdateRequest { 13 | 14 | @NotNull 15 | private DocumentTemplatePropertyType type; 16 | 17 | @NotEmpty 18 | private List properties = Collections.emptyList(); 19 | 20 | @Data 21 | public static class PropertyRequest { 22 | 23 | private String key; 24 | 25 | private String value; 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/TableDocumentRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Collection; 6 | import java.util.Collections; 7 | 8 | @Data 9 | public class TableDocumentRequest { 10 | 11 | private Collection tableIds = Collections.emptyList(); 12 | 13 | private Long originalVersion; 14 | 15 | private Long currentVersion; 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/TableResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | @Data 9 | public class TableResponse { 10 | 11 | private Integer id; 12 | 13 | private String name; 14 | 15 | private List columns = Collections.emptyList(); 16 | 17 | @Data 18 | public static class ColumnResponse { 19 | 20 | private Integer id; 21 | 22 | private String name; 23 | 24 | private String type; 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/ColumnDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class ColumnDocDiff implements DiffAble { 10 | 11 | private Integer id; 12 | 13 | private Integer tableDocumentId; 14 | 15 | private Integer databaseDocumentId; 16 | 17 | private String name; 18 | 19 | private String type; 20 | 21 | private Integer dataType; 22 | 23 | private String comment; 24 | 25 | private String defaultValue; 26 | 27 | private Integer size; 28 | 29 | private Integer decimalDigits; 30 | 31 | private Boolean isPrimaryKey; 32 | 33 | private String nullable; 34 | 35 | private String autoIncrement; 36 | 37 | private LocalDateTime createAt; 38 | 39 | private DiffType diffType; 40 | 41 | private ColumnDocDiff original; 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/DatabaseDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | @Data 10 | public class DatabaseDocDiff { 11 | 12 | private Integer id; 13 | 14 | private Integer projectId; 15 | 16 | private String databaseName; 17 | 18 | private String schemaName; 19 | 20 | private String productName; 21 | 22 | private String productVersion; 23 | 24 | private Long version; 25 | 26 | private List tables = Collections.emptyList(); 27 | 28 | private LocalDateTime updateAt; 29 | 30 | private LocalDateTime createAt; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/DiffAble.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | 5 | public interface DiffAble { 6 | 7 | void setDiffType(DiffType diffType); 8 | 9 | void setOriginal(T t); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/ForeignKeyDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class ForeignKeyDocDiff implements DiffAble { 10 | 11 | private Integer id; 12 | 13 | private Integer tableDocumentId; 14 | 15 | private Integer databaseDocumentId; 16 | 17 | private Integer keySeq; 18 | 19 | private String fkName; 20 | 21 | private String fkTableName; 22 | 23 | private String fkColumnName; 24 | 25 | private String pkName; 26 | 27 | private String pkTableName; 28 | 29 | private String pkColumnName; 30 | 31 | private String updateRule; 32 | 33 | private String deleteRule; 34 | 35 | private LocalDateTime createAt; 36 | 37 | private DiffType diffType; 38 | 39 | private ForeignKeyDocDiff original; 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/IndexDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.Data; 5 | import org.jooq.JSON; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @Data 10 | public class IndexDocDiff implements DiffAble { 11 | 12 | private Integer id; 13 | 14 | private Integer tableDocumentId; 15 | 16 | private Integer databaseDocumentId; 17 | 18 | private String name; 19 | 20 | private Boolean isUnique; 21 | 22 | private JSON columnNameArray; 23 | 24 | private LocalDateTime createAt; 25 | 26 | private DiffType diffType; 27 | 28 | private IndexDocDiff original; 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/TableDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | @Data 12 | @Builder 13 | public class TableDocDiff implements DiffAble { 14 | 15 | private Integer id; 16 | 17 | private String name; 18 | 19 | private String type; 20 | 21 | private String comment; 22 | 23 | @Builder.Default 24 | private List columns = Collections.emptyList(); 25 | 26 | @Builder.Default 27 | private List indexes = Collections.emptyList(); 28 | 29 | @Builder.Default 30 | private List triggers = Collections.emptyList(); 31 | 32 | @Builder.Default 33 | private List foreignKeys = Collections.emptyList(); 34 | 35 | private LocalDateTime createAt; 36 | 37 | private DiffType diffType; 38 | 39 | private TableDocDiff original; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/data/diff/TriggerDocDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.data.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class TriggerDocDiff implements DiffAble { 10 | 11 | private Integer id; 12 | 13 | private String name; 14 | 15 | private Integer tableDocumentId; 16 | 17 | private Integer databaseDocumentId; 18 | 19 | private String timing; 20 | 21 | private String manipulation; 22 | 23 | private String statement; 24 | 25 | private String triggerCreateAt; 26 | 27 | private LocalDateTime createAt; 28 | 29 | private DiffType diffType; 30 | 31 | private TriggerDocDiff original; 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/diff/DiffTypePredictor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.diff; 2 | 3 | import com.databasir.core.diff.data.DiffType; 4 | import com.databasir.core.domain.document.data.DatabaseDocumentSimpleResponse; 5 | 6 | import java.util.List; 7 | 8 | public class DiffTypePredictor { 9 | 10 | public static DiffType predict(List result) { 11 | long changedItemSize = result.stream() 12 | .filter(item -> !item.getDiffType().isNone()) 13 | .count(); 14 | long addedItemSize = result.stream() 15 | .filter(item -> !item.getDiffType().isNone()) 16 | .filter(item -> item.getDiffType().isAdded()) 17 | .count(); 18 | long removedItemSize = result.stream() 19 | .filter(item -> !item.getDiffType().isNone()) 20 | .filter(item -> item.getDiffType().isRemoved()) 21 | .count(); 22 | if (changedItemSize > 0 && addedItemSize == changedItemSize) { 23 | return DiffType.ADDED; 24 | } else if (changedItemSize > 0 && removedItemSize == changedItemSize) { 25 | return DiffType.REMOVED; 26 | } else { 27 | return result.stream() 28 | .anyMatch(t -> t.getDiffType() != DiffType.NONE) ? DiffType.MODIFIED : DiffType.NONE; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/event/DocumentUpdated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.event; 2 | 3 | import com.databasir.core.diff.data.RootDiff; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Optional; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class DocumentUpdated { 14 | 15 | private RootDiff diff; 16 | 17 | private Long newVersion; 18 | 19 | private Long oldVersion; 20 | 21 | private Integer projectId; 22 | 23 | private Integer databaseDocumentId; 24 | 25 | public Optional getOldVersion() { 26 | return Optional.ofNullable(oldVersion); 27 | } 28 | 29 | public Optional getDiff() { 30 | return Optional.ofNullable(diff); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/generator/DocumentFileGenerator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.generator; 2 | 3 | import com.databasir.core.domain.document.data.DatabaseDocumentResponse; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.NonNull; 7 | 8 | import java.io.OutputStream; 9 | 10 | public interface DocumentFileGenerator { 11 | 12 | boolean support(DocumentFileType type); 13 | 14 | void generate(DocumentFileGenerateContext context, OutputStream outputStream); 15 | 16 | @Getter 17 | @Builder 18 | class DocumentFileGenerateContext { 19 | 20 | @NonNull 21 | private DocumentFileType documentFileType; 22 | 23 | @NonNull 24 | private DatabaseDocumentResponse databaseDocument; 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/generator/DocumentFileType.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.generator; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @AllArgsConstructor 7 | @Getter 8 | public enum DocumentFileType { 9 | 10 | MARKDOWN("md", "Markdown"), 11 | 12 | PLANT_UML_ER_SVG("svg", "UML SVG"), 13 | 14 | PLANT_UML_ER_PNG("png", "UML PNG"), 15 | ; 16 | 17 | private String fileExtension; 18 | 19 | private String name; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/generator/plantuml/PlantUmlErSvgFileGenerator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.generator.plantuml; 2 | 3 | import com.databasir.core.domain.document.generator.DocumentFileType; 4 | import lombok.extern.slf4j.Slf4j; 5 | import net.sourceforge.plantuml.FileFormat; 6 | import net.sourceforge.plantuml.FileFormatOption; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @Slf4j 11 | public class PlantUmlErSvgFileGenerator extends BasePlantUmlFileGenerator { 12 | 13 | @Override 14 | public boolean support(DocumentFileType type) { 15 | return type == DocumentFileType.PLANT_UML_ER_SVG; 16 | } 17 | 18 | @Override 19 | protected FileFormatOption fileFormatOption() { 20 | return new FileFormatOption(FileFormat.SVG); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/document/generator/plantuml/PlantUmlPngFileGenerator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.generator.plantuml; 2 | 3 | import com.databasir.core.domain.document.generator.DocumentFileType; 4 | import lombok.extern.slf4j.Slf4j; 5 | import net.sourceforge.plantuml.FileFormat; 6 | import net.sourceforge.plantuml.FileFormatOption; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @Slf4j 11 | public class PlantUmlPngFileGenerator extends BasePlantUmlFileGenerator { 12 | 13 | @Override 14 | public boolean support(DocumentFileType type) { 15 | return type == DocumentFileType.PLANT_UML_ER_PNG; 16 | } 17 | 18 | @Override 19 | protected FileFormatOption fileFormatOption() { 20 | return new FileFormatOption(FileFormat.PNG); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/converter/GroupConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.converter; 2 | 3 | import com.databasir.core.domain.group.data.GroupCreateRequest; 4 | import com.databasir.core.domain.group.data.GroupUpdateRequest; 5 | import com.databasir.dao.tables.pojos.Group; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.Mapping; 8 | 9 | @Mapper(componentModel = "spring") 10 | public interface GroupConverter { 11 | 12 | @Mapping(target = "id", ignore = true) 13 | @Mapping(target = "deleted", ignore = true) 14 | @Mapping(target = "createAt", ignore = true) 15 | @Mapping(target = "updateAt", ignore = true) 16 | Group of(GroupCreateRequest groupCreateRequest); 17 | 18 | @Mapping(target = "deleted", ignore = true) 19 | @Mapping(target = "createAt", ignore = true) 20 | @Mapping(target = "updateAt", ignore = true) 21 | Group of(GroupUpdateRequest groupUpdateRequest); 22 | 23 | default String nullToEmpty(String description) { 24 | return description == null ? "" : description; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.Size; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class GroupCreateRequest { 13 | 14 | @NotBlank 15 | private String name; 16 | 17 | private String description; 18 | 19 | @NotEmpty 20 | @Size(min = 1, max = 20, message = "一个分组的组长最多为 20 人,最少为 1 人") 21 | private List groupOwnerUserIds = new ArrayList<>(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupMemberCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GroupMemberCreateRequest { 7 | 8 | private Integer userId; 9 | 10 | private String role; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupMemberPageCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | import org.jooq.Condition; 5 | import org.jooq.impl.DSL; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import static com.databasir.dao.Tables.USER; 11 | import static com.databasir.dao.Tables.USER_ROLE; 12 | 13 | @Data 14 | public class GroupMemberPageCondition { 15 | 16 | private String role; 17 | 18 | private String nicknameOrUsernameOrEmailContains; 19 | 20 | public Condition toCondition() { 21 | List conditions = new ArrayList<>(); 22 | if (role != null) { 23 | conditions.add(USER_ROLE.ROLE.eq(role)); 24 | } 25 | if (nicknameOrUsernameOrEmailContains != null) { 26 | conditions.add(USER.USERNAME.contains(nicknameOrUsernameOrEmailContains) 27 | .or(USER.NICKNAME.contains(nicknameOrUsernameOrEmailContains)) 28 | .or(USER.EMAIL.contains(nicknameOrUsernameOrEmailContains))); 29 | } 30 | return conditions.stream().reduce(Condition::and).orElse(DSL.trueCondition()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupMemberPageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class GroupMemberPageResponse { 9 | 10 | private Integer userId; 11 | 12 | private String role; 13 | 14 | private String username; 15 | 16 | private String nickname; 17 | 18 | private String email; 19 | 20 | private LocalDateTime createAt; 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupMemberRoleUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | @Data 8 | public class GroupMemberRoleUpdateRequest { 9 | 10 | @NotBlank 11 | private String role; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupPageCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import com.databasir.dao.Tables; 4 | import lombok.Data; 5 | import org.jooq.Condition; 6 | import org.jooq.impl.DSL; 7 | 8 | @Data 9 | public class GroupPageCondition { 10 | 11 | private String groupNameContains; 12 | 13 | public Condition toCondition() { 14 | if (groupNameContains != null) { 15 | return Tables.GROUP.NAME.contains(groupNameContains); 16 | } 17 | return DSL.trueCondition(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupPageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class GroupPageResponse { 9 | 10 | private Integer id; 11 | 12 | private String name; 13 | 14 | private String description; 15 | 16 | private List groupOwnerNames; 17 | 18 | private Integer projectCount; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class GroupResponse { 11 | 12 | private Integer id; 13 | 14 | private String name; 15 | 16 | private String description; 17 | 18 | private List groupOwners = new ArrayList<>(); 19 | 20 | private LocalDateTime updateAt; 21 | 22 | private LocalDateTime createAt; 23 | 24 | @Data 25 | public static class GroupOwnerResponse { 26 | 27 | private Integer id; 28 | 29 | private String nickname; 30 | 31 | private String email; 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/data/GroupUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.NotNull; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class GroupUpdateRequest { 13 | 14 | @NotNull 15 | private Integer id; 16 | 17 | @NotBlank 18 | private String name; 19 | 20 | private String description; 21 | 22 | @NotEmpty 23 | private List groupOwnerUserIds = new ArrayList<>(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/event/GroupCreated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class GroupCreated { 11 | 12 | private Integer groupId; 13 | 14 | private String groupName; 15 | 16 | private String groupDescription; 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/event/GroupDeleted.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @Data 7 | @AllArgsConstructor 8 | public class GroupDeleted { 9 | 10 | private Integer groupId; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/group/event/GroupUpdated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.group.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class GroupUpdated { 11 | 12 | private Integer groupId; 13 | 14 | private String groupName; 15 | 16 | private String groupDescription; 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/log/annotation/AuditLog.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.log.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface AuditLog { 11 | 12 | String module(); 13 | 14 | String name() default "UNKNOWN"; 15 | 16 | /** 17 | * @return the Spring-EL expression 18 | */ 19 | String involvedProjectId() default "N/A"; 20 | 21 | /** 22 | * @return the Spring-EL expression 23 | */ 24 | String involvedGroupId() default "N/A"; 25 | 26 | /** 27 | * @return the Spring-EL expression 28 | */ 29 | String involvedUserId() default "N/A"; 30 | 31 | boolean retrieveInvolvedGroupId() default false; 32 | 33 | interface Modules { 34 | String UNKNOWN = "UNKNOWN"; 35 | String PROJECT = "project"; 36 | String USER = "user"; 37 | String GROUP = "group"; 38 | String LOGIN_APP = "login_app"; 39 | String SETTING = "setting"; 40 | String DATABASE_TYPE = "database_type"; 41 | String LOGIN = "login"; 42 | } 43 | 44 | interface Types { 45 | int SYSTEM_USER_ID = -1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/log/converter/OperationLogRequestConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.log.converter; 2 | 3 | import com.databasir.core.domain.log.data.OperationLogRequest; 4 | import com.databasir.core.infrastructure.converter.JsonConverter; 5 | import com.databasir.dao.tables.pojos.OperationLog; 6 | import org.mapstruct.Mapper; 7 | 8 | @Mapper(componentModel = "spring", uses = JsonConverter.class) 9 | public interface OperationLogRequestConverter { 10 | 11 | OperationLog toPojo(OperationLogRequest request); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/log/data/OperationLogRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.log.data; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class OperationLogRequest { 9 | 10 | private Integer operatorUserId; 11 | 12 | private String operatorUsername; 13 | 14 | private String operatorNickname; 15 | 16 | private String operationModule; 17 | 18 | private String operationCode; 19 | 20 | private String operationName; 21 | 22 | private Object operationResponse; 23 | 24 | private Boolean isSuccess; 25 | 26 | private Integer involvedProjectId; 27 | 28 | private Integer involvedGroupId; 29 | 30 | private Integer involvedUserId; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/login/data/AccessTokenRefreshRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.login.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | @Data 8 | public class AccessTokenRefreshRequest { 9 | 10 | @NotBlank 11 | private String refreshToken; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/login/data/AccessTokenRefreshResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.login.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class AccessTokenRefreshResponse { 11 | 12 | private String accessToken; 13 | 14 | private Long accessTokenExpireAt; 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/login/data/LoginKeyResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.login.data; 2 | 3 | import lombok.*; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | @Builder 11 | @EqualsAndHashCode 12 | public class LoginKeyResponse { 13 | 14 | private Integer userId; 15 | 16 | private String accessToken; 17 | 18 | private LocalDateTime accessTokenExpireAt; 19 | 20 | private String refreshToken; 21 | 22 | private LocalDateTime refreshTokenExpireAt; 23 | 24 | public boolean accessTokenIsExpired() { 25 | return accessTokenExpireAt.isBefore(LocalDateTime.now()); 26 | } 27 | 28 | public boolean refreshTokenIsExpired() { 29 | return refreshTokenExpireAt.isBefore(LocalDateTime.now()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/login/data/UserLoginResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.login.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class UserLoginResponse { 9 | 10 | private Integer id; 11 | 12 | private String nickname; 13 | 14 | private String email; 15 | 16 | private String username; 17 | 18 | private String avatar; 19 | 20 | private String accessToken; 21 | 22 | private long accessTokenExpireAt; 23 | 24 | private String refreshToken; 25 | 26 | private List roles; 27 | 28 | @Data 29 | public static class RoleResponse { 30 | 31 | private String role; 32 | 33 | private Integer groupId; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/converter/MockDataRuleConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.converter; 2 | 3 | import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest; 4 | import com.databasir.dao.tables.pojos.MockDataRule; 5 | import org.mapstruct.Mapper; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface MockDataRuleConverter { 12 | 13 | MockDataRule from(Integer projectId, ColumnMockRuleSaveRequest request); 14 | 15 | default List from(Integer projectId, List request) { 16 | return request.stream() 17 | .map(rule -> from(projectId, rule)) 18 | .collect(Collectors.toList()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/converter/MockDataRuleResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.converter; 2 | 3 | import com.databasir.core.domain.mock.data.MockDataRuleResponse; 4 | import com.databasir.dao.enums.MockDataType; 5 | import com.databasir.dao.tables.pojos.MockDataRule; 6 | import com.databasir.dao.tables.pojos.TableColumnDocument; 7 | import org.mapstruct.Mapper; 8 | import org.mapstruct.Mapping; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface MockDataRuleResponseConverter { 12 | 13 | @Mapping(target = "columnType", source = "column.type") 14 | MockDataRuleResponse from(MockDataRule pojo, TableColumnDocument column); 15 | 16 | @Mapping(target = "columnName", source = "pojo.name") 17 | @Mapping(target = "columnType", source = "pojo.type") 18 | MockDataRuleResponse from(String tableName, MockDataType mockDataType, TableColumnDocument pojo); 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/data/ColumnMockRuleSaveRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.data; 2 | 3 | import com.databasir.dao.enums.MockDataType; 4 | import lombok.Data; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | 9 | @Data 10 | public class ColumnMockRuleSaveRequest { 11 | 12 | @NotBlank 13 | private String tableName; 14 | 15 | @NotBlank 16 | private String columnName; 17 | 18 | private String dependentTableName; 19 | 20 | private String dependentColumnName; 21 | 22 | @NotNull 23 | private MockDataType mockDataType; 24 | 25 | private String mockDataScript; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/data/MockDataGenerateCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class MockDataGenerateCondition { 7 | 8 | private Long version; 9 | 10 | private Integer tableId; 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/data/MockDataRuleListCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class MockDataRuleListCondition { 7 | 8 | private Long version; 9 | 10 | private Integer tableId; 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/data/MockDataRuleResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.data; 2 | 3 | import com.databasir.dao.enums.MockDataType; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class MockDataRuleResponse { 8 | 9 | private String tableName; 10 | 11 | private String columnName; 12 | 13 | private String columnType; 14 | 15 | private String dependentTableName; 16 | 17 | private String dependentColumnName; 18 | 19 | private MockDataType mockDataType; 20 | 21 | private String mockDataScript; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/factory/MockColumnRule.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.factory; 2 | 3 | import com.databasir.dao.enums.MockDataType; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import java.util.Optional; 8 | 9 | @Getter 10 | @Builder 11 | public class MockColumnRule { 12 | 13 | private String tableName; 14 | 15 | private String columnName; 16 | 17 | private String columnType; 18 | 19 | private Integer dataType; 20 | 21 | private MockDataType mockDataType; 22 | 23 | private String mockDataScript; 24 | 25 | public static MockColumnRule auto(String tableName, String columnName) { 26 | return MockColumnRule.builder() 27 | .tableName(tableName) 28 | .columnName(columnName) 29 | .mockDataType(MockDataType.AUTO) 30 | .build(); 31 | } 32 | 33 | public Optional getMockDataScript() { 34 | return Optional.ofNullable(mockDataScript); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/factory/MockDataFactory.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.factory; 2 | 3 | public interface MockDataFactory { 4 | 5 | boolean accept(MockColumnRule rule); 6 | 7 | String create(MockColumnRule rule); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/factory/ScriptMockDataFactory.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.factory; 2 | 3 | import com.databasir.core.domain.mock.script.MockScriptEvaluator; 4 | import com.databasir.dao.enums.MockDataType; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.core.annotation.Order; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @Order(0) 11 | @RequiredArgsConstructor 12 | public class ScriptMockDataFactory implements MockDataFactory { 13 | 14 | private final MockScriptEvaluator mockScriptEvaluator; 15 | 16 | @Override 17 | public boolean accept(MockColumnRule rule) { 18 | return rule.getMockDataType() == MockDataType.SCRIPT; 19 | } 20 | 21 | @Override 22 | public String create(MockColumnRule rule) { 23 | return mockScriptEvaluator.evaluate(rule.getMockDataScript().get(), new MockScriptEvaluator.ScriptContext()); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/generator/ColumnMockData.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.generator; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @Builder 8 | public class ColumnMockData { 9 | 10 | private String columnName; 11 | 12 | private String columnType; 13 | 14 | private String mockData; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/generator/TableMockData.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.generator; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import java.util.List; 7 | import java.util.Objects; 8 | 9 | @Getter 10 | @AllArgsConstructor 11 | public class TableMockData { 12 | 13 | private String tableName; 14 | 15 | private List columnMockData; 16 | 17 | public static TableMockData of(String tableName, List columnMockData) { 18 | return new TableMockData(tableName, columnMockData); 19 | } 20 | 21 | public void addColumnIfNotExists(ColumnMockData data) { 22 | boolean present = columnMockData.stream() 23 | .anyMatch(col -> Objects.equals(col.getColumnName(), data.getColumnName())); 24 | if (present) { 25 | return; 26 | } 27 | this.columnMockData.add(data); 28 | } 29 | 30 | public boolean containsColumn(String columnName) { 31 | return columnMockData.stream() 32 | .anyMatch(col -> Objects.equals(col.getColumnName(), columnName)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/script/MockScriptEvaluator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.script; 2 | 3 | import lombok.Data; 4 | 5 | public interface MockScriptEvaluator { 6 | 7 | String evaluate(String script, ScriptContext context); 8 | 9 | @Data 10 | class ScriptContext { 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/mock/script/SpelScriptEvaluator.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.mock.script; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.expression.Expression; 5 | import org.springframework.expression.spel.standard.SpelExpressionParser; 6 | import org.springframework.expression.spel.support.SimpleEvaluationContext; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @RequiredArgsConstructor 11 | public class SpelScriptEvaluator implements MockScriptEvaluator { 12 | 13 | private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); 14 | 15 | @Override 16 | public String evaluate(String script, ScriptContext context) { 17 | Expression expression = spelExpressionParser.parseExpression(script); 18 | SimpleEvaluationContext spelContext = SimpleEvaluationContext.forReadOnlyDataBinding().build(); 19 | return expression.getValue(spelContext, String.class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/converter/ProjectSimpleTaskResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.converter; 2 | 3 | import com.databasir.core.domain.project.data.task.ProjectSimpleTaskResponse; 4 | import com.databasir.dao.tables.pojos.ProjectSyncTask; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | 8 | import java.util.List; 9 | 10 | @Mapper(componentModel = "spring") 11 | public interface ProjectSimpleTaskResponseConverter { 12 | 13 | List of(List pojos); 14 | 15 | @Mapping(target = "taskId", source = "id") 16 | ProjectSimpleTaskResponse of(ProjectSyncTask pojo); 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/DataSourcePropertyValue.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class DataSourcePropertyValue { 13 | 14 | @NotBlank 15 | private String key; 16 | 17 | @NotBlank 18 | private String value; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/ProjectDetailResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class ProjectDetailResponse { 11 | 12 | private Integer id; 13 | 14 | private String name; 15 | 16 | private String description; 17 | 18 | private Integer groupId; 19 | 20 | private DataSourceResponse dataSource; 21 | 22 | private ProjectSyncRuleResponse projectSyncRule; 23 | 24 | private LocalDateTime createAt; 25 | 26 | @Data 27 | public static class DataSourceResponse { 28 | 29 | private Integer id; 30 | 31 | private String username; 32 | 33 | private String url; 34 | 35 | private String databaseName; 36 | 37 | private String schemaName; 38 | 39 | private String databaseType; 40 | 41 | private List properties = new ArrayList<>(); 42 | 43 | private LocalDateTime updateAt; 44 | 45 | private LocalDateTime createAt; 46 | 47 | } 48 | 49 | @Data 50 | public static class ProjectSyncRuleResponse { 51 | 52 | private Integer id; 53 | 54 | private List ignoreTableNameRegexes = new ArrayList<>(); 55 | 56 | private List ignoreColumnNameRegexes = new ArrayList<>(); 57 | 58 | private Boolean isAutoSync; 59 | 60 | private String autoSyncCron; 61 | 62 | private LocalDateTime createAt; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/ProjectSimpleResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class ProjectSimpleResponse { 9 | 10 | private Integer id; 11 | 12 | private String name; 13 | 14 | private String description; 15 | 16 | private String databaseName; 17 | 18 | private String schemaName; 19 | 20 | private String databaseType; 21 | 22 | private Boolean isAutoSync; 23 | 24 | private Boolean isFavorite; 25 | 26 | private String autoSyncCron; 27 | 28 | private LocalDateTime createAt; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/ProjectTestConnectionRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class ProjectTestConnectionRequest { 11 | 12 | private Integer projectId; 13 | 14 | @NotBlank 15 | private String username; 16 | 17 | private String password; 18 | 19 | @NotBlank 20 | private String url; 21 | 22 | @NotBlank 23 | private String databaseName; 24 | 25 | @NotBlank 26 | private String schemaName; 27 | 28 | @NotBlank 29 | private String databaseType; 30 | 31 | private List properties = new ArrayList<>(); 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/task/ProjectSimpleTaskResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data.task; 2 | 3 | import com.databasir.dao.enums.ProjectSyncTaskStatus; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class ProjectSimpleTaskResponse { 10 | 11 | private Integer taskId; 12 | 13 | private ProjectSyncTaskStatus status; 14 | 15 | private String result; 16 | 17 | private LocalDateTime runAt; 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/data/task/ProjectTaskListCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.data.task; 2 | 3 | import com.databasir.dao.Tables; 4 | import com.databasir.dao.enums.ProjectSyncTaskStatus; 5 | import lombok.Data; 6 | import org.jooq.Condition; 7 | 8 | import java.util.Collection; 9 | import java.util.Collections; 10 | 11 | @Data 12 | public class ProjectTaskListCondition { 13 | 14 | private Collection taskIdIn = Collections.emptyList(); 15 | 16 | private Collection taskStatusIn = Collections.emptyList(); 17 | 18 | public Condition toCondition(Integer projectId) { 19 | Condition condition = Tables.PROJECT_SYNC_TASK.PROJECT_ID.eq(projectId); 20 | if (taskIdIn != null && !taskIdIn.isEmpty()) { 21 | condition = condition.and(Tables.PROJECT_SYNC_TASK.ID.in(taskIdIn)); 22 | } 23 | if (taskStatusIn != null && !taskStatusIn.isEmpty()) { 24 | condition = condition.and(Tables.PROJECT_SYNC_TASK.STATUS.in(taskStatusIn)); 25 | } 26 | // ignore system user task 27 | return condition.and(Tables.PROJECT_SYNC_TASK.USER_ID.ne(-1)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/event/ProjectDeleted.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.event; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @Data 7 | @AllArgsConstructor 8 | public class ProjectDeleted { 9 | 10 | private Integer projectId; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/project/event/ProjectSaved.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.project.event; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class ProjectSaved { 9 | 10 | private Integer groupId; 11 | 12 | private Integer projectId; 13 | 14 | private String projectName; 15 | 16 | private String projectDescription; 17 | 18 | private String databaseType; 19 | 20 | private String databaseName; 21 | 22 | private String schemaName; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/system/data/SystemEmailResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.system.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class SystemEmailResponse { 9 | 10 | private String username; 11 | 12 | private String mailFrom; 13 | 14 | private String smtpHost; 15 | 16 | private Integer smtpPort; 17 | 18 | private Boolean useSSL; 19 | 20 | private Boolean useTls; 21 | 22 | private LocalDateTime createAt; 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/system/data/SystemEmailUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.system.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.*; 6 | 7 | @Data 8 | public class SystemEmailUpdateRequest { 9 | 10 | @NotBlank 11 | private String username; 12 | 13 | private String password; 14 | 15 | @Email 16 | private String mailFrom; 17 | 18 | @NotBlank 19 | private String smtpHost; 20 | 21 | @NotNull 22 | @Min(0L) 23 | @Max(65535L) 24 | private Integer smtpPort; 25 | 26 | @NotNull 27 | private Boolean useSSL; 28 | 29 | @NotNull 30 | private Boolean useTls; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/converter/FavoriteProjectPageResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.converter; 2 | 3 | import com.databasir.core.domain.user.data.FavoriteProjectPageResponse; 4 | import com.databasir.dao.tables.pojos.*; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | 8 | @Mapper(componentModel = "spring") 9 | public interface FavoriteProjectPageResponseConverter { 10 | 11 | @Mapping(target = "projectId", source = "project.id") 12 | @Mapping(target = "projectName", source = "project.name") 13 | @Mapping(target = "projectDescription", source = "project.description") 14 | @Mapping(target = "groupId", source = "group.id") 15 | @Mapping(target = "groupName", source = "group.name") 16 | @Mapping(target = "createAt", source = "favoriteProject.createAt") 17 | FavoriteProjectPageResponse to(UserFavoriteProject favoriteProject, 18 | Project project, 19 | DataSource dataSource, 20 | ProjectSyncRule projectSyncRule, 21 | Group group); 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/converter/UserConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.converter; 2 | 3 | import com.databasir.core.domain.user.data.UserCreateRequest; 4 | import com.databasir.dao.tables.pojos.User; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | 8 | @Mapper(componentModel = "spring") 9 | public interface UserConverter { 10 | 11 | @Mapping(target = "password", source = "hashedPassword") 12 | User of(UserCreateRequest request, String hashedPassword); 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/converter/UserResponseConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.converter; 2 | 3 | import com.databasir.core.domain.user.data.UserDetailResponse; 4 | import com.databasir.core.domain.user.data.UserPageResponse; 5 | import com.databasir.dao.tables.pojos.User; 6 | import com.databasir.dao.tables.pojos.UserRole; 7 | import org.mapstruct.Mapper; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.stream.Collectors; 12 | 13 | @Mapper(componentModel = "spring") 14 | public interface UserResponseConverter { 15 | 16 | default UserDetailResponse detailResponse(User user, 17 | List userRoles, 18 | Map groupNameMapById) { 19 | List roles = userRoles.stream() 20 | .map(pojo -> userRoleDetailResponse(pojo, groupNameMapById.get(pojo.getGroupId()))) 21 | .collect(Collectors.toList()); 22 | return detailResponse(user, roles); 23 | } 24 | 25 | UserDetailResponse detailResponse(User pojo, List roles); 26 | 27 | UserDetailResponse.UserRoleDetailResponse userRoleDetailResponse(UserRole pojo, String groupName); 28 | 29 | UserPageResponse pageResponse(User pojo, Boolean isSysOwner, List inGroupIds); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/FavoriteProjectCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | public class FavoriteProjectCreateRequest { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/FavoriteProjectPageCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import com.databasir.dao.Tables; 4 | import lombok.Data; 5 | import org.jooq.Condition; 6 | import org.jooq.impl.DSL; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Data 12 | public class FavoriteProjectPageCondition { 13 | 14 | private String projectNameContains; 15 | 16 | public Condition toCondition(Integer userId) { 17 | List conditions = new ArrayList<>(); 18 | conditions.add(Tables.USER_FAVORITE_PROJECT.USER_ID.eq(userId)); 19 | if (projectNameContains != null && !projectNameContains.trim().equals("")) { 20 | conditions.add(Tables.PROJECT.NAME.contains(projectNameContains)); 21 | } 22 | return conditions.stream() 23 | .reduce(Condition::and) 24 | .orElse(DSL.trueCondition()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/FavoriteProjectPageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class FavoriteProjectPageResponse { 9 | 10 | private Integer projectId; 11 | 12 | private String projectName; 13 | 14 | private String projectDescription; 15 | 16 | private Boolean isAutoSync; 17 | 18 | private String autoSyncCron; 19 | 20 | private Integer groupId; 21 | 22 | private String groupName; 23 | 24 | private String databaseType; 25 | 26 | private String databaseName; 27 | 28 | private LocalDateTime createAt; 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.NotNull; 7 | 8 | @Data 9 | public class UserCreateRequest { 10 | 11 | private String avatar; 12 | 13 | @NotBlank 14 | private String username; 15 | 16 | @NotBlank 17 | private String nickname; 18 | 19 | @NotBlank 20 | private String email; 21 | 22 | @NotBlank 23 | private String password; 24 | 25 | @NotNull 26 | private Boolean enabled; 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserDetailResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class UserDetailResponse { 11 | 12 | private Integer id; 13 | 14 | private String username; 15 | 16 | private String nickname; 17 | 18 | private String avatar; 19 | 20 | private String email; 21 | 22 | private Boolean enabled; 23 | 24 | private List roles = new ArrayList<>(); 25 | 26 | private LocalDateTime createAt; 27 | 28 | @Data 29 | public static class UserRoleDetailResponse { 30 | 31 | private String role; 32 | 33 | private Integer groupId; 34 | 35 | private String groupName; 36 | 37 | private LocalDateTime createAt; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserNicknameUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.Size; 7 | 8 | @Data 9 | public class UserNicknameUpdateRequest { 10 | 11 | @NotBlank 12 | @Size(max = 32, min = 1) 13 | private String nickname; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserPageResponse.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class UserPageResponse { 11 | 12 | private Integer id; 13 | 14 | private String username; 15 | 16 | private String nickname; 17 | 18 | private String email; 19 | 20 | private Boolean enabled; 21 | 22 | private Boolean isSysOwner; 23 | 24 | private List inGroupIds = new ArrayList<>(); 25 | 26 | private LocalDateTime createAt; 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserPasswordUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.Size; 7 | 8 | @Data 9 | public class UserPasswordUpdateRequest { 10 | 11 | @NotBlank 12 | private String originPassword; 13 | 14 | @NotBlank 15 | @Size(min = 6, max = 32) 16 | private String newPassword; 17 | 18 | @NotBlank 19 | @Size(min = 6, max = 32) 20 | private String confirmNewPassword; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserRoleAssignRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class UserRoleAssignRequest { 7 | 8 | private Integer userId; 9 | 10 | private String role; 11 | 12 | private Integer groupId; 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/data/UserSource.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.data; 2 | 3 | import java.util.Objects; 4 | 5 | public interface UserSource { 6 | 7 | String MANUAL = "manual"; 8 | 9 | static boolean isManual(String source) { 10 | return Objects.equals(source, MANUAL); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/event/UserCreated.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.event; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | @Getter 8 | @Builder 9 | @ToString 10 | public class UserCreated { 11 | 12 | private Integer userId; 13 | 14 | private String nickname; 15 | 16 | private String email; 17 | 18 | private String username; 19 | 20 | private String rawPassword; 21 | 22 | private String source; 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/event/UserPasswordRenewed.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.event; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | @Getter 9 | @Builder 10 | public class UserPasswordRenewed { 11 | 12 | private Integer renewByUserId; 13 | 14 | private String nickname; 15 | 16 | private String email; 17 | 18 | private String newPassword; 19 | 20 | private LocalDateTime renewTime; 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/domain/user/event/converter/UserEventConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.user.event.converter; 2 | 3 | import com.databasir.core.domain.user.event.UserCreated; 4 | import com.databasir.core.domain.user.event.UserPasswordRenewed; 5 | import com.databasir.dao.tables.pojos.User; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.Mapping; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | @Mapper(componentModel = "spring") 12 | public interface UserEventConverter { 13 | 14 | UserPasswordRenewed userPasswordRenewed(User pojo, 15 | Integer renewByUserId, 16 | LocalDateTime renewTime, 17 | String newPassword); 18 | 19 | @Mapping(target = "userId", source = "userId") 20 | UserCreated userCreated(User pojo, String source, String rawPassword, Integer userId); 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/connection/DatabaseConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.connection; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.sql.Connection; 7 | import java.sql.SQLException; 8 | import java.util.Properties; 9 | 10 | public interface DatabaseConnectionFactory { 11 | 12 | boolean support(String databaseType); 13 | 14 | Connection getConnection(Context context) throws SQLException; 15 | 16 | @Builder 17 | @Data 18 | class Context { 19 | 20 | private String databaseType; 21 | 22 | private String username; 23 | 24 | private String password; 25 | 26 | private String url; 27 | 28 | private String databaseName; 29 | 30 | private String schemaName; 31 | 32 | private Properties properties; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/connection/DatabaseTypes.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.connection; 2 | 3 | import java.util.Objects; 4 | 5 | public interface DatabaseTypes { 6 | 7 | String MYSQL = "mysql"; 8 | 9 | String POSTGRESQL = "postgresql"; 10 | 11 | static boolean has(String name) { 12 | if (name == null) { 13 | return false; 14 | } 15 | return Objects.equals(MYSQL, name.toLowerCase()) 16 | || Objects.equals(POSTGRESQL, name.toLowerCase()); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/connection/MysqlDatabaseConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.connection; 2 | 3 | import org.springframework.core.annotation.Order; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.SQLException; 9 | import java.util.Properties; 10 | 11 | @Component 12 | @Order(1) 13 | public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory { 14 | 15 | @Override 16 | public boolean support(String databaseType) { 17 | return DatabaseTypes.MYSQL.equalsIgnoreCase(databaseType); 18 | } 19 | 20 | @Override 21 | public Connection getConnection(Context context) throws SQLException { 22 | try { 23 | Class.forName("com.mysql.cj.jdbc.Driver"); 24 | } catch (ClassNotFoundException e) { 25 | throw new IllegalStateException(e); 26 | } 27 | 28 | Properties info = new Properties(); 29 | info.put("user", context.getUsername()); 30 | info.put("password", context.getPassword()); 31 | info.putAll(context.getProperties()); 32 | String jdbcUrl = "jdbc:mysql://" + context.getUrl() + "/" + context.getDatabaseName(); 33 | return DriverManager.getConnection(jdbcUrl, info); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/connection/PostgresqlDatabaseConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.connection; 2 | 3 | import org.springframework.core.annotation.Order; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.SQLException; 9 | import java.util.Properties; 10 | 11 | @Component 12 | @Order(2) 13 | public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFactory { 14 | 15 | @Override 16 | public boolean support(String databaseType) { 17 | return DatabaseTypes.POSTGRESQL.equalsIgnoreCase(databaseType); 18 | } 19 | 20 | @Override 21 | public Connection getConnection(Context context) throws SQLException { 22 | try { 23 | Class.forName("org.postgresql.Driver"); 24 | } catch (ClassNotFoundException e) { 25 | throw new IllegalStateException(e); 26 | } 27 | 28 | Properties info = new Properties(); 29 | info.put("user", context.getUsername()); 30 | info.put("password", context.getPassword()); 31 | info.putAll(context.getProperties()); 32 | String jdbcUrl = "jdbc:postgresql://" + context.getUrl() + "/" + context.getDatabaseName(); 33 | return DriverManager.getConnection(jdbcUrl, info); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/constant/RoleConstants.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.constant; 2 | 3 | public interface RoleConstants { 4 | 5 | String SYS_OWNER = "SYS_OWNER"; 6 | 7 | String GROUP_OWNER = "GROUP_OWNER"; 8 | 9 | String GROUP_MEMBER = "GROUP_MEMBER"; 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/driver/DriverResult.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.driver; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.File; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class DriverResult { 13 | 14 | private String driverFilePath; 15 | 16 | private File driverFile; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/event/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.event; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.context.ApplicationEventPublisher; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | @RequiredArgsConstructor 9 | public class EventPublisher { 10 | 11 | private final ApplicationEventPublisher applicationEventPublisher; 12 | 13 | public void publish(Object event) { 14 | applicationEventPublisher.publishEvent(event); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DiscussionEventSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.event.subscriber; 2 | 3 | import com.databasir.core.domain.discussion.event.DiscussionCreated; 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.context.event.EventListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @RequiredArgsConstructor 11 | @Slf4j 12 | public class DiscussionEventSubscriber { 13 | 14 | @EventListener(classes = DiscussionCreated.class) 15 | public void onDiscussionCreated(DiscussionCreated created) { 16 | // TODO notification group member who subscribe this event 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/mail/MailTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.mail; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.TemplateExceptionHandler; 5 | import org.springframework.context.annotation.Bean; 6 | 7 | @org.springframework.context.annotation.Configuration 8 | public class MailTemplateConfig { 9 | 10 | @Bean 11 | public Configuration mailTemplateConfiguration() { 12 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_29); 13 | cfg.setClassForTemplateLoading(getClass(), "/"); 14 | cfg.setDefaultEncoding("UTF-8"); 15 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 16 | cfg.setLogTemplateExceptions(false); 17 | cfg.setWrapUncheckedExceptions(true); 18 | cfg.setFallbackOnNullLoopVariable(false); 19 | return cfg; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/mail/MailTemplateProcessor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.mail; 2 | 3 | import com.databasir.common.SystemException; 4 | import freemarker.template.Configuration; 5 | import freemarker.template.Template; 6 | import freemarker.template.TemplateException; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.io.IOException; 11 | import java.io.StringWriter; 12 | import java.util.Map; 13 | 14 | @Component 15 | @RequiredArgsConstructor 16 | public class MailTemplateProcessor { 17 | 18 | private final Configuration mailTemplateConfiguration; 19 | 20 | public String process(String templatePath, Map context) { 21 | try { 22 | Template template = mailTemplateConfiguration.getTemplate(templatePath); 23 | StringWriter writer = new StringWriter(); 24 | template.process(context, writer); 25 | return writer.toString(); 26 | } catch (IOException | TemplateException e) { 27 | throw new SystemException("build template content error", e); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/remote/github/GithubApiClient.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.remote.github; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import retrofit2.Call; 5 | import retrofit2.http.GET; 6 | import retrofit2.http.Header; 7 | import retrofit2.http.Headers; 8 | import retrofit2.http.Url; 9 | 10 | public interface GithubApiClient { 11 | 12 | @GET 13 | @Headers(value = { 14 | "Accept: application/json" 15 | }) 16 | Call getEmail(@Url String url, @Header("Authorization") String token); 17 | 18 | @GET 19 | @Headers(value = { 20 | "Accept: application/json" 21 | }) 22 | Call getProfile(@Url String url, @Header("Authorization") String token); 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/remote/github/GithubOauthClient.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.remote.github; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import retrofit2.Call; 5 | import retrofit2.http.Headers; 6 | import retrofit2.http.POST; 7 | import retrofit2.http.QueryMap; 8 | import retrofit2.http.Url; 9 | 10 | import java.util.Map; 11 | 12 | public interface GithubOauthClient { 13 | 14 | @Headers(value = { 15 | "Accept: application/json" 16 | }) 17 | @POST 18 | Call getAccessToken(@Url String url, @QueryMap Map request); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/remote/github/TokenRequest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.remote.github; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | @Data 10 | @SuppressWarnings("checkstyle:all") 11 | @Builder 12 | public class TokenRequest { 13 | 14 | private String client_id; 15 | 16 | private String client_secret; 17 | 18 | private String code; 19 | 20 | private String redirect_uri; 21 | 22 | public Map toMap() { 23 | HashMap map = new HashMap<>(); 24 | map.put("client_id", client_id); 25 | map.put("client_secret", client_secret); 26 | map.put("code", code); 27 | if (redirect_uri != null) { 28 | map.put("redirect_uri", redirect_uri); 29 | } 30 | return map; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/remote/gitlab/GitlabApiClient.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.remote.gitlab; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import retrofit2.Call; 5 | import retrofit2.http.*; 6 | 7 | public interface GitlabApiClient { 8 | @GET 9 | @Headers(value = { 10 | "Accept: application/json" 11 | }) 12 | Call getUser(@Url String url, @Header("Authorization") String token); 13 | 14 | @POST 15 | @Headers(value = { 16 | "Accept: application/json" 17 | }) 18 | Call getAccessToken(@Url String url); 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/com/databasir/core/infrastructure/remote/wework/WeWorkApiClient.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.infrastructure.remote.wework; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import retrofit2.Call; 5 | import retrofit2.http.GET; 6 | import retrofit2.http.Headers; 7 | import retrofit2.http.QueryMap; 8 | import retrofit2.http.Url; 9 | 10 | import java.util.Map; 11 | 12 | public interface WeWorkApiClient { 13 | 14 | @GET 15 | @Headers(value = { 16 | "Accept: application/json" 17 | }) 18 | Call getUserInfo(@Url String url, @QueryMap Map request); 19 | 20 | @GET 21 | @Headers(value = { 22 | "Accept: application/json" 23 | }) 24 | Call getAccessToken(@Url String url, @QueryMap Map request); 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/resources/ftl/mail/DiscussCreated.ftl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vran-dev/databasir/01fa3284b6155dd104965307c162cbdaf22c9a3a/core/src/main/resources/ftl/mail/DiscussCreated.ftl -------------------------------------------------------------------------------- /core/src/test/java/com/databasir/core/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core; 2 | 3 | import org.junit.jupiter.api.extension.ExtendWith; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.test.context.ActiveProfiles; 6 | import org.springframework.test.context.junit.jupiter.SpringExtension; 7 | 8 | @SpringBootTest(classes = CoreTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) 9 | @ActiveProfiles("ut") 10 | @ExtendWith(SpringExtension.class) 11 | public class BaseTest { 12 | } 13 | -------------------------------------------------------------------------------- /core/src/test/java/com/databasir/core/CoreTestApplication.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core; 2 | 3 | import com.databasir.core.config.AsyncConfig; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.FilterType; 9 | 10 | @SpringBootApplication(exclude = { 11 | R2dbcAutoConfiguration.class 12 | }) 13 | @ComponentScan( 14 | basePackages = "com.databasir", 15 | excludeFilters = { 16 | @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AsyncConfig.class) 17 | }) 18 | public class CoreTestApplication { 19 | public static void main(String[] args) { 20 | SpringApplication.run(CoreTestApplication.class, args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/test/java/com/databasir/core/domain/document/diff/ComplexObject.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.diff; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class ComplexObject { 10 | 11 | private Integer id; 12 | 13 | private String name; 14 | 15 | private List items = new ArrayList<>(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /core/src/test/java/com/databasir/core/domain/document/diff/SimpleObject.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.document.diff; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class SimpleObject { 9 | 10 | private Integer id; 11 | 12 | private Long height; 13 | 14 | private String name; 15 | 16 | } -------------------------------------------------------------------------------- /core/src/test/java/com/databasir/core/domain/log/service/OperationLogServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.domain.log.service; 2 | 3 | import com.databasir.common.JsonData; 4 | import com.databasir.core.BaseTest; 5 | import com.databasir.core.domain.log.data.OperationLogRequest; 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Transactional 12 | class OperationLogServiceTest extends BaseTest { 13 | 14 | @Autowired 15 | private OperationLogService operationLogService; 16 | 17 | @Test 18 | void save() { 19 | var request = OperationLogRequest.builder() 20 | .operatorUserId(-1000) 21 | .operatorUsername("ut") 22 | .operatorNickname("ut") 23 | .operationModule("system") 24 | .operationCode("updateEmail") 25 | .operationName("更新邮箱") 26 | .operationResponse(JsonData.ok()) 27 | .isSuccess(true) 28 | .involvedProjectId(null) 29 | .involvedGroupId(null) 30 | .involvedUserId(null) 31 | .build(); 32 | Long id = operationLogService.save(request); 33 | Assertions.assertNotNull(id); 34 | } 35 | } -------------------------------------------------------------------------------- /core/src/test/resources/application-ut.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.jooq=INFO 2 | server.port=8080 3 | # datasource 4 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 5 | spring.datasource.username=${databasir.db.username} 6 | spring.datasource.password=${databasir.db.password} 7 | spring.datasource.url=jdbc:mysql://${databasir.db.url}/${databasir.db.name:databasir}?serverTimezone=UTC&characterEncoding=utf-8 8 | # driver directory 9 | spring.jooq.sql-dialect=mysql 10 | # flyway 11 | spring.flyway.enabled=true 12 | spring.flyway.baseline-on-migrate=true 13 | spring.flyway.locations=classpath:db/migration 14 | # db 15 | databasir.db.url=localhost:3306 16 | databasir.db.username=root 17 | databasir.db.password=123456 18 | databasir.db.driver-directory=drivers 19 | databasir.jwt.secret=DatabasirJwtSecret -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/database/CreateDuplicate.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.database_type (id, database_type, icon, description, jdbc_driver_file_url, jdbc_driver_class_name, 2 | jdbc_protocol, url_pattern) 3 | VALUES (-1000, 'ut-mysql', '', 'system default mysql', 'N/A', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql', 4 | '{{jdbc.protocol}}://{{db.url}}/{{db.name}}'); 5 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/database/DeleteById.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.database_type (id, database_type, icon, description, jdbc_driver_file_url, jdbc_driver_class_name, 2 | jdbc_protocol, url_pattern) 3 | VALUES (-1000, 'ut-mysql', '', 'system default mysql', 'N/A', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql', 4 | '{{jdbc.protocol}}://{{db.url}}/{{db.name}}'); 5 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/database/Update.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.database_type (id, database_type, icon, description, jdbc_driver_file_url, jdbc_driver_class_name, 2 | jdbc_protocol, url_pattern) 3 | VALUES (-1000, 'ut-mysql', '', 'system default mysql', 'N/A', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql', 4 | '{{jdbc.protocol}}://{{db.url}}/{{db.name}}'); 5 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/discussion/Create.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.project (id, name, description, group_id, deleted, deleted_token, create_at) 5 | VALUES (-999, 'demo test', 'demo', -999, 0, 1, '2022-03-06 02:11:02'); 6 | 7 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/discussion/DeleteById.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.project (id, name, description, group_id, deleted, deleted_token, create_at) 5 | VALUES (-999, 'demo test', 'demo', -999, 0, 1, '2022-03-06 02:11:02'); 6 | 7 | INSERT INTO databasir.document_discussion(id, content, user_id, project_id, table_name, column_name) 8 | VALUES (-999, 'demo test', -1, -999, 'ut', 'ut'); 9 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/group/GroupDelete.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.user_role (user_id, role, group_id) 5 | VALUES (1000, 'GROUP_OWNER', -999), 6 | (1001, 'GROUP_OWNER', -999), 7 | (1002, 'GROUP_OWNER', -999), 8 | (1003, 'GROUP_OWNER', -999), 9 | (1004, 'GROUP_MEMBER', -999); 10 | 11 | INSERT INTO databasir.project (id, name, description, group_id, deleted, deleted_token, create_at) 12 | VALUES (-999, 'demo test', 'demo', -999, 0, 1, '2022-03-06 02:11:02'), 13 | (-1000, 'demo test3', 'no member', -999, 0, 1, '2022-03-25 09:00:16'), 14 | (-1001, 'demo test2', 'demo', -999, 0, 0, '2022-03-06 02:11:35'); 15 | 16 | 17 | INSERT INTO databasir.project_sync_rule (project_id, ignore_table_name_regex_array, ignore_column_name_regex_array, 18 | is_auto_sync, auto_sync_cron) 19 | VALUES (-999, '[]', '[]', 1, '0 0/20 * * * ? '), 20 | (-1000, '[]', '[]', 1, '0 0/20 * * * ? '), 21 | (-1001, '[]', '[]', 1, '0 0/20 * * * ? '); 22 | 23 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/group/GroupUpdate.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'), 3 | (-1000, '商品中心 ut', '商品中心', 0, '2022-03-06 02:11:53', '2022-03-06 02:11:53'); 4 | 5 | INSERT INTO databasir.user_role (user_id, role, group_id) 6 | VALUES (1000, 'GROUP_OWNER', -999), 7 | (1001, 'GROUP_OWNER', -999), 8 | (1002, 'GROUP_OWNER', -999), 9 | (1003, 'GROUP_OWNER', -999), 10 | (1004, 'GROUP_MEMBER', -999); 11 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/group/MemberAdd.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'), 3 | (-1000, '会员平台 ut2', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 4 | 5 | INSERT INTO databasir.user_role (user_id, role, group_id) 6 | VALUES (-2, 'GROUP_MEMBER', -999), 7 | (-2, 'GROUP_OWNER', -1000); 8 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/group/MemberRemove.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'), 3 | (-1000, '会员平台 ut2', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 4 | 5 | INSERT INTO databasir.user_role (user_id, role, group_id) 6 | VALUES (-1, 'SYS_OWNER', NULL), 7 | (-1, 'GROUP_OWNER', -999), 8 | (-2, 'GROUP_MEMBER', -999), 9 | (-2, 'GROUP_OWNER', -1000); 10 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/group/MemberRoleChange.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.user_role (user_id, role, group_id) 5 | VALUES (-1, 'GROUP_OWNER', -999); 6 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/login/Generate.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-1000, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 1); 3 | 4 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/login/RefreshAccessTokens.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-1000, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 1); 3 | 4 | INSERT INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, refresh_token_expire_at) 5 | VALUES (-1000, 6 | 'xxxx', 7 | '2a884c14ef654e14b069f8ca32ce0261', DATE_SUB(NOW(), INTERVAL 2 MINUTE), DATE_ADD(NOW(), INTERVAL 1 HOUR)); 8 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/login/RefreshAccessTokensWhenUserDisabled.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-1000, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 0); 3 | 4 | INSERT INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, refresh_token_expire_at) 5 | VALUES (-1000, 6 | 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJEYXRhYmFzaXIiLCJleHAiOjE2NDcwODc4NjgsInVzZXJuYW1lIjoidGVzdEBkYXRhYmFzaXIuY29tIn0.QXtY0R_2_nqpO2LueY0GFXHR1TCaFj1Y9yl1OoP2yYQ', 7 | '2a884c14ef654e14b069f8ca32ce0261', DATE_SUB(NOW(), INTERVAL 2 MINUTE), DATE_ADD(NOW(), INTERVAL 1 HOUR)); 8 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/login/RefreshAccessTokensWhenUserNotExists.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, refresh_token_expire_at) 2 | VALUES (-1000, 3 | 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJEYXRhYmFzaXIiLCJleHAiOjE2NDcwODc4NjgsInVzZXJuYW1lIjoidGVzdEBkYXRhYmFzaXIuY29tIn0.QXtY0R_2_nqpO2LueY0GFXHR1TCaFj1Y9yl1OoP2yYQ', 4 | '2a884c14ef654e14b069f8ca32ce0261', DATE_SUB(NOW(), INTERVAL 2 MINUTE), DATE_ADD(NOW(), INTERVAL 1 HOUR)); 5 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/project/Delete.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.project (id, name, description, group_id, deleted, deleted_token, create_at) 5 | VALUES (-1000, 'demo test2', 'demo', -999, 0, 0, '2022-03-06 02:11:35'); 6 | 7 | INSERT INTO databasir.project_sync_rule (project_id, ignore_table_name_regex_array, ignore_column_name_regex_array, 8 | is_auto_sync, auto_sync_cron) 9 | VALUES (-1000, '[]', '[]', 1, '0 0/20 * * * ? '); 10 | 11 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/project/Update.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.`group` (id, name, description, deleted, update_at, create_at) 2 | VALUES (-999, '会员平台 ut', '会员平台', 0, '2022-03-06 02:10:40', '2022-03-06 02:10:40'); 3 | 4 | INSERT INTO databasir.project (id, name, description, group_id, deleted, deleted_token, create_at) 5 | VALUES (-1000, 'demo test2', 'demo', -999, 0, 0, '2022-03-06 02:11:35'); 6 | 7 | INSERT INTO databasir.project_sync_rule (project_id, ignore_table_name_regex_array, ignore_column_name_regex_array, 8 | is_auto_sync, auto_sync_cron) 9 | VALUES (-1000, '[]', '[]', 0, '0 0/20 * * * ? '); 10 | 11 | INSERT INTO databasir.data_source(id, project_id, database_name, schema_name, database_type, url, username, password) 12 | VALUES (-1000, -1000, 'databasir', 'databasir', 'mysql', 'localhost:3306', 'root', '123456'); 13 | 14 | INSERT INTO databasir.data_source_property(data_source_id, `key`, value) 15 | VALUES (-1000, 'useSSL', 'true') -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/AddFavorites.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.project (id, NAME, DESCRIPTION, group_id, deleted, deleted_token, create_at) 2 | VALUES (999, 'addFavoritesTest', 'demo', 1, 0, 1, '2022-03-06 02:11:02'); 3 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/AddSysOwnerTo.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-998, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 1), 3 | (-999, 'notSysOwner@databasir.com', 'notSysOwner', '$2a$10$wXPDzPceU1PLXGKRAEW', 'b', NULL, 1); 4 | 5 | INSERT IGNORE INTO databasir.user_role (user_id, role, group_id, create_at) 6 | VALUES (-998, 'SYS_OWNER', NULL, '2022-03-06 02:05:30'); 7 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/RemoveFavorites.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user_favorite_project (user_id, project_id, create_at) 2 | VALUES (999, 999, '2022-03-06 10:25:47'), 3 | (999, 1000, '2022-03-10 09:13:30'); 4 | 5 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/RemoveSysOwnerFrom.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-998, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 1), 3 | (-999, 'notSysOwner@databasir.com', 'notSysOwner', '$2a$10$wXPDzPceU1PLXGKRAEW', 'b', NULL, 1); 4 | 5 | INSERT IGNORE INTO databasir.user_role (user_id, role, group_id, create_at) 6 | VALUES (-998, 'SYS_OWNER', NULL, '2022-03-06 02:05:30'); 7 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/RenewPassword.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-1, 'N/A', 'databasir', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1), 3 | (-2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1); -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/SwitchEnableStatus.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-999, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1); 3 | 4 | INSERT IGNORE INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, 5 | refresh_token_expire_at) 6 | VALUES (-999, 'eyJ0eXAiOiJKV1QM', '1a884c14ef6542ce0261', '2022-03-12 20:24:28', '2022-03-27 20:09:29'); 7 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/UpdateNickname.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, 2 | refresh_token_expire_at) 3 | VALUES (-999, 'eyJ0eXAiOiJKV1QM', '1a884c14ef6542ce0261', '2022-03-12 20:24:28', '2022-03-27 20:09:29'); 4 | 5 | INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 6 | VALUES (-999, 'demo2@databasir.com', 'demo2', '$2a$10$KTi5HBIBURn/5h9d7sp2DeIxK4T03vlh34dSwyJphjeNBRGWTzEDK', 'demo2', 7 | NULL, 1); 8 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/domain/user/UpdatePassword.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at, 2 | refresh_token_expire_at) 3 | VALUES (-999, 'eyJ0eXAiOiJKV1QM', '1a884c14ef6542ce0261', '2022-03-12 20:24:28', '2022-03-27 20:09:29'); 4 | 5 | INSERT INTO databasir.user (id, email, username, password, nickname, avatar, enabled, update_at, create_at) 6 | VALUES (-999, 'demo2@databasir.com', 'demo2', '$2a$10$KTi5HBIBURn/5h9d7sp2DeIxK4T03vlh34dSwyJphjeNBRGWTzEDK', 'demo2', 7 | NULL, 1, '2022-03-25 15:02:49', '2022-03-25 15:02:49'); 8 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/event/subscriber/DocumentEventSubscriberTest.sql: -------------------------------------------------------------------------------- 1 | REPLACE INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-1, 'jack@databasir.com', 'jack', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1), 3 | (-2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1), 4 | (-3, 'test@databasir.com', 'test', '$2a$10$XbnZlQB26cKKGB4WLlgZxxwbUr9tD1Amn/3Tf5H0i', 'test', NULL, 1), 5 | (-4, 'sample@databasir.com', 'sample', '$2a$10$Ua0zrJ7.HDb6ZIRNWb7fCJiG2OZRTN1.', 'sample', NULL, 1), 6 | (-5, 'demo@databasir.com', 'demo', '$2a$10$J4JT19JBO3LpWAvRARDxieFtm/pFQtna.dDq', 'demo', NULL, 0); 7 | 8 | REPLACE INTO databasir.project (id, name, description, group_id, deleted, deleted_token) 9 | VALUES (-1, 'demo', 'demo', 1, 0, 1), 10 | (-2, 'no member', 'no member', 1, 0, 1); 11 | 12 | REPLACE INTO databasir.`group` (id, name, description, deleted) 13 | VALUES (-1, '会员平台', '会员平台', 0), 14 | (-2, '成员为空', '会员平台', 0); 15 | 16 | REPLACE INTO databasir.user_role (user_id, role, group_id) 17 | VALUES (-1, 'SYS_OWNER', NULL), 18 | (-1, 'GROUP_OWNER', 1), 19 | (-2, 'GROUP_OWNER', 1), 20 | (-3, 'GROUP_MEMBER', 1), 21 | (-4, 'GROUP_OWNER', 1), 22 | (-5, 'GROUP_OWNER', 1); 23 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/event/subscriber/UserEventSubscriberTest.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO databasir.user (id, email, username, password, nickname, avatar, enabled) 2 | VALUES (-999, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1); 3 | 4 | -------------------------------------------------------------------------------- /core/src/test/resources/sql/init.sql: -------------------------------------------------------------------------------- 1 | REPLACE INTO databasir.sys_mail (id, username, password, smtp_host, smtp_port, use_ssl, update_at, create_at) 2 | VALUES (999, 'ut@databasir.com', '123456', 'smtp.exmail.databasir.com', 465, 1, '2022-03-25 03:14:27', 3 | '2022-03-21 14:20:56'); 4 | -------------------------------------------------------------------------------- /dao/generated-src/jooq/main/java/com/databasir/dao/DefaultCatalog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package com.databasir.dao; 5 | 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | import org.jooq.Schema; 11 | import org.jooq.impl.CatalogImpl; 12 | 13 | 14 | /** 15 | * This class is generated by jOOQ. 16 | */ 17 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 18 | public class DefaultCatalog extends CatalogImpl { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | /** 23 | * The reference instance of DEFAULT_CATALOG 24 | */ 25 | public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog(); 26 | 27 | /** 28 | * The schema databasir. 29 | */ 30 | public final Databasir DATABASIR = Databasir.DATABASIR; 31 | 32 | /** 33 | * No further instances allowed 34 | */ 35 | private DefaultCatalog() { 36 | super(""); 37 | } 38 | 39 | @Override 40 | public final List getSchemas() { 41 | return Arrays.asList( 42 | Databasir.DATABASIR 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/converter/DocumentTemplatePropertyTypeConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.converter; 2 | 3 | import com.databasir.dao.enums.DocumentTemplatePropertyType; 4 | import org.jooq.impl.EnumConverter; 5 | 6 | public class DocumentTemplatePropertyTypeConverter extends EnumConverter { 7 | 8 | public DocumentTemplatePropertyTypeConverter() { 9 | super(String.class, DocumentTemplatePropertyType.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/converter/MockDataTypeConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.converter; 2 | 3 | import com.databasir.dao.enums.MockDataType; 4 | import org.jooq.impl.EnumConverter; 5 | 6 | public class MockDataTypeConverter extends EnumConverter { 7 | 8 | public MockDataTypeConverter() { 9 | super(String.class, MockDataType.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/converter/OAuthAppTypeConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.converter; 2 | 3 | import com.databasir.dao.enums.OAuthAppType; 4 | import org.jooq.impl.EnumConverter; 5 | 6 | public class OAuthAppTypeConverter extends EnumConverter { 7 | 8 | public OAuthAppTypeConverter() { 9 | super(String.class, OAuthAppType.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/converter/ProjectSyncTaskStatusConverter.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.converter; 2 | 3 | import com.databasir.dao.enums.ProjectSyncTaskStatus; 4 | import org.jooq.impl.EnumConverter; 5 | 6 | public class ProjectSyncTaskStatusConverter extends EnumConverter { 7 | 8 | public ProjectSyncTaskStatusConverter() { 9 | super(String.class, ProjectSyncTaskStatus.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/enums/DocumentTemplatePropertyType.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.enums; 2 | 3 | public enum DocumentTemplatePropertyType { 4 | 5 | TABLE_FIELD_NAME, INDEX_FIELD_NAME, COLUMN_FIELD_NAME, TRIGGER_FIELD_NAME, FOREIGN_KEY_FIELD_NAME; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/enums/MockDataType.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.enums; 2 | 3 | import java.util.List; 4 | 5 | public enum MockDataType { 6 | 7 | // java faker supported type 8 | PHONE, 9 | EMAIL, 10 | FULL_NAME, 11 | FULL_ADDRESS, 12 | AVATAR_URL, 13 | UUID, 14 | 15 | // databasir custom type 16 | SCRIPT, 17 | CONSTANT, 18 | REF, 19 | AUTO, 20 | ; 21 | 22 | public static List fakerTypes() { 23 | return List.of(PHONE, EMAIL, FULL_NAME, FULL_ADDRESS, AVATAR_URL, UUID); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/enums/OAuthAppType.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @AllArgsConstructor 7 | public enum OAuthAppType { 8 | 9 | GITHUB("github"), GITLAB("gitlab"), WE_WORK("企业微信"); 10 | 11 | @Getter 12 | private String description; 13 | 14 | public boolean isSame(String type) { 15 | return this.name().equalsIgnoreCase(type); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/enums/ProjectSyncTaskStatus.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.enums; 2 | 3 | public enum ProjectSyncTaskStatus { 4 | NEW, 5 | RUNNING, 6 | FINISHED, 7 | FAILED, 8 | CANCELED 9 | } 10 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/exception/DataNotExistsException.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.exception; 2 | 3 | public class DataNotExistsException extends RuntimeException { 4 | 5 | public DataNotExistsException() { 6 | super(); 7 | } 8 | 9 | public DataNotExistsException(String message) { 10 | super(message); 11 | } 12 | 13 | public DataNotExistsException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | 17 | public DataNotExistsException(Throwable cause) { 18 | super(cause); 19 | } 20 | 21 | protected DataNotExistsException(String message, 22 | Throwable cause, 23 | boolean enableSuppression, 24 | boolean writableStackTrace) { 25 | super(message, cause, enableSuppression, writableStackTrace); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/DataSourcePropertyDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.tables.pojos.DataSourceProperty; 4 | import lombok.Getter; 5 | import org.jooq.DSLContext; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | import static com.databasir.dao.Tables.DATA_SOURCE_PROPERTY; 12 | 13 | @Repository 14 | public class DataSourcePropertyDao extends BaseDao { 15 | 16 | @Autowired 17 | @Getter 18 | private DSLContext dslContext; 19 | 20 | public DataSourcePropertyDao() { 21 | super(DATA_SOURCE_PROPERTY, DataSourceProperty.class); 22 | } 23 | 24 | public int deleteByDataSourceId(Integer dataSourceId) { 25 | return dslContext 26 | .deleteFrom(DATA_SOURCE_PROPERTY).where(DATA_SOURCE_PROPERTY.DATA_SOURCE_ID.eq(dataSourceId)) 27 | .execute(); 28 | } 29 | 30 | public List selectByDataSourceId(Integer id) { 31 | return dslContext 32 | .select(DATA_SOURCE_PROPERTY.fields()).from(DATA_SOURCE_PROPERTY) 33 | .where(DATA_SOURCE_PROPERTY.DATA_SOURCE_ID.eq(id)) 34 | .fetchInto(DataSourceProperty.class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/DocumentDiscussionDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.tables.pojos.DocumentDiscussion; 4 | import com.databasir.dao.value.DocumentDiscussionCountPojo; 5 | import lombok.Getter; 6 | import org.jooq.Condition; 7 | import org.jooq.DSLContext; 8 | import org.jooq.impl.DSL; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import java.util.List; 13 | 14 | import static com.databasir.dao.Tables.DOCUMENT_DISCUSSION; 15 | 16 | @Repository 17 | public class DocumentDiscussionDao extends BaseDao { 18 | 19 | @Autowired 20 | @Getter 21 | private DSLContext dslContext; 22 | 23 | public DocumentDiscussionDao() { 24 | super(DOCUMENT_DISCUSSION, DocumentDiscussion.class); 25 | } 26 | 27 | public List selectAllDiscussionCount(Integer projectId) { 28 | return this.selectDiscussionCount(DOCUMENT_DISCUSSION.PROJECT_ID.eq(projectId)); 29 | } 30 | 31 | public List selectDiscussionCount(Condition condition) { 32 | return this.getDslContext() 33 | .select(DSL.count(), DOCUMENT_DISCUSSION.TABLE_NAME) 34 | .from(DOCUMENT_DISCUSSION) 35 | .where(condition) 36 | .groupBy(DOCUMENT_DISCUSSION.TABLE_NAME) 37 | .fetchInto(DocumentDiscussionCountPojo.class); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/OauthAppDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.exception.DataNotExistsException; 4 | import com.databasir.dao.tables.pojos.OauthApp; 5 | import lombok.Getter; 6 | import org.jooq.DSLContext; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.Optional; 11 | 12 | import static com.databasir.dao.Tables.OAUTH_APP; 13 | 14 | @Repository 15 | public class OauthAppDao extends BaseDao { 16 | 17 | @Autowired 18 | @Getter 19 | private DSLContext dslContext; 20 | 21 | public OauthAppDao() { 22 | super(OAUTH_APP, OauthApp.class); 23 | } 24 | 25 | public Optional selectOptionByRegistrationId(String registrationId) { 26 | return this.getDslContext() 27 | .select(OAUTH_APP.fields()).from(OAUTH_APP).where(OAUTH_APP.REGISTRATION_ID.eq(registrationId)) 28 | .fetchOptionalInto(OauthApp.class); 29 | } 30 | 31 | public OauthApp selectByRegistrationId(String registrationId) { 32 | return this.selectOptionByRegistrationId(registrationId) 33 | .orElseThrow(() -> new DataNotExistsException("can not found oauth app by " + registrationId)); 34 | } 35 | } -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/OauthAppPropertyDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.tables.pojos.OauthAppProperty; 4 | import lombok.Getter; 5 | import org.jooq.DSLContext; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | import static com.databasir.dao.Tables.OAUTH_APP_PROPERTY; 12 | 13 | @Repository 14 | public class OauthAppPropertyDao extends BaseDao { 15 | 16 | @Autowired 17 | @Getter 18 | private DSLContext dslContext; 19 | 20 | public OauthAppPropertyDao() { 21 | super(OAUTH_APP_PROPERTY, OauthAppProperty.class); 22 | } 23 | 24 | public int deleteByOauthAppId(Integer oauthAppId) { 25 | return this.getDslContext() 26 | .deleteFrom(OAUTH_APP_PROPERTY) 27 | .where(OAUTH_APP_PROPERTY.OAUTH_APP_ID.eq(oauthAppId)) 28 | .execute(); 29 | } 30 | 31 | public List selectByOauthAppId(Integer oauthAppID) { 32 | return this.getDslContext() 33 | .select(OAUTH_APP_PROPERTY.fields()) 34 | .from(OAUTH_APP_PROPERTY).where(OAUTH_APP_PROPERTY.OAUTH_APP_ID.eq(oauthAppID)) 35 | .fetchInto(OauthAppProperty.class); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/OperationLogDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.tables.pojos.OperationLog; 4 | import lombok.Getter; 5 | import org.jooq.DSLContext; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.io.Serializable; 10 | 11 | import static com.databasir.dao.Tables.OPERATION_LOG; 12 | 13 | @Repository 14 | public class OperationLogDao extends BaseDao { 15 | 16 | @Autowired 17 | @Getter 18 | private DSLContext dslContext; 19 | 20 | public OperationLogDao() { 21 | super(OPERATION_LOG, OperationLog.class); 22 | } 23 | 24 | @Override 25 | protected Class identityType() { 26 | return (Class) Long.class; 27 | } 28 | } -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/SysKeyDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.exception.DataNotExistsException; 4 | import com.databasir.dao.tables.pojos.SysKey; 5 | import lombok.Getter; 6 | import org.jooq.DSLContext; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.Optional; 11 | 12 | import static com.databasir.dao.Tables.SYS_KEY; 13 | 14 | @Repository 15 | public class SysKeyDao extends BaseDao { 16 | 17 | @Autowired 18 | @Getter 19 | private DSLContext dslContext; 20 | 21 | public SysKeyDao() { 22 | super(SYS_KEY, SysKey.class); 23 | } 24 | 25 | public Optional selectOptionTopOne() { 26 | return dslContext.select(SYS_KEY.fields()).from(SYS_KEY) 27 | .limit(1) 28 | .fetchOptionalInto(SysKey.class); 29 | } 30 | 31 | public SysKey selectTopOne() { 32 | return selectOptionTopOne() 33 | .orElseThrow(() -> new DataNotExistsException("no syskey data find")); 34 | } 35 | } -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/impl/SysMailDao.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.impl; 2 | 3 | import com.databasir.dao.exception.DataNotExistsException; 4 | import com.databasir.dao.tables.pojos.SysMail; 5 | import com.databasir.dao.tables.records.SysMailRecord; 6 | import lombok.Getter; 7 | import org.jooq.DSLContext; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.Optional; 12 | 13 | import static com.databasir.dao.Tables.SYS_MAIL; 14 | 15 | @Repository 16 | public class SysMailDao extends BaseDao { 17 | 18 | @Autowired 19 | @Getter 20 | private DSLContext dslContext; 21 | 22 | public SysMailDao() { 23 | super(SYS_MAIL, SysMail.class); 24 | } 25 | 26 | public Optional selectOptionTopOne() { 27 | return dslContext.select(SYS_MAIL.fields()).from(SYS_MAIL) 28 | .limit(1) 29 | .fetchOptionalInto(SysMail.class); 30 | } 31 | 32 | public SysMail selectTopOne() { 33 | return selectOptionTopOne() 34 | .orElseThrow(() -> new DataNotExistsException("no sysmail data find")); 35 | } 36 | 37 | @Override 38 | public int updateById(SysMail pojo) { 39 | SysMailRecord record = getDslContext().newRecord(SYS_MAIL, pojo); 40 | record.changed(SYS_MAIL.ID, false); 41 | if (pojo.getPassword() == null) { 42 | record.changed(SYS_MAIL.PASSWORD, false); 43 | } 44 | return getDslContext().executeUpdate(record); 45 | } 46 | } -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/strategy/DatabasirPojoNamingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.strategy; 2 | 3 | import org.jooq.codegen.DefaultGeneratorStrategy; 4 | import org.jooq.meta.Definition; 5 | import org.jooq.meta.TableDefinition; 6 | 7 | public class DatabasirPojoNamingStrategy extends DefaultGeneratorStrategy { 8 | 9 | @Override 10 | public String getJavaClassName(Definition definition, Mode mode) { 11 | if (mode == Mode.DEFAULT && definition instanceof TableDefinition) { 12 | String javaClassName = super.getJavaClassName(definition, mode); 13 | if (javaClassName.endsWith("Table")) { 14 | return javaClassName; 15 | } else { 16 | return javaClassName + "Table"; 17 | } 18 | } 19 | 20 | return super.getJavaClassName(definition, mode); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/DatabaseDocumentVersionPojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class DatabaseDocumentVersionPojo { 9 | 10 | private Integer id; 11 | 12 | private Long version; 13 | 14 | private LocalDateTime createAt; 15 | } 16 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/DocumentDiscussionCountPojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DocumentDiscussionCountPojo { 7 | 8 | private Integer projectId; 9 | 10 | private String tableName; 11 | 12 | private Integer count; 13 | } 14 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/FullTextProjectInfoUpdatePojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class FullTextProjectInfoUpdatePojo { 9 | 10 | private Integer projectId; 11 | 12 | private String projectName; 13 | 14 | private String projectDescription; 15 | 16 | private String databaseType; 17 | 18 | private String databaseName; 19 | 20 | private String schemaName; 21 | } 22 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/GroupMemberDetailPojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @Data 8 | public class GroupMemberDetailPojo { 9 | 10 | private Integer userId; 11 | 12 | private String role; 13 | 14 | private Integer groupId; 15 | 16 | private String username; 17 | 18 | private String nickname; 19 | 20 | private String email; 21 | 22 | private LocalDateTime createAt; 23 | } 24 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/GroupMemberSimplePojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GroupMemberSimplePojo { 7 | 8 | private String nickname; 9 | 10 | private Integer groupId; 11 | 12 | private String role; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/GroupProjectCountPojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GroupProjectCountPojo { 7 | 8 | private Integer groupId; 9 | 10 | private Integer count; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /dao/src/main/java/com/databasir/dao/value/ProjectQueryPojo.java: -------------------------------------------------------------------------------- 1 | package com.databasir.dao.value; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class ProjectQueryPojo { 7 | 8 | private Integer projectId; 9 | 10 | private Integer groupId; 11 | 12 | private String groupName; 13 | 14 | private String projectName; 15 | 16 | private String projectDescription; 17 | 18 | private String databaseName; 19 | 20 | private String schemaName; 21 | } 22 | -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.2__mock_data.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS mock_data_rule 2 | ( 3 | `id` INT PRIMARY KEY AUTO_INCREMENT, 4 | `project_id` INT NOT NULL, 5 | `table_name` VARCHAR(255) NOT NULL, 6 | `column_name` VARCHAR(255) NOT NULL, 7 | `dependent_table_name` VARCHAR(255) DEFAULT NULL, 8 | `dependent_column_name` VARCHAR(255) DEFAULT NULL, 9 | `mock_data_type` VARCHAR(255) NOT NULL DEFAULT 'AUTO / REF / SCRIPT / PHONE / DATE / TIMESTAMP / ...', 10 | `mock_data_script` TEXT DEFAULT NULL, 11 | `update_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 12 | `create_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 13 | CONSTRAINT UNIQUE uk_project_id_table_name_column_name (project_id, table_name, column_name) 14 | ) CHARSET utf8mb4 15 | COLLATE utf8mb4_unicode_ci; 16 | 17 | ALTER TABLE databasir.table_column_document 18 | ADD COLUMN data_type INT NOT NULL DEFAULT 99999 AFTER type; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.3__sync_task.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS project_sync_task 2 | ( 3 | `id` INT PRIMARY KEY AUTO_INCREMENT, 4 | `project_id` INT NOT NULL, 5 | `user_id` INT NOT NULL, 6 | `status` VARCHAR(32) NOT NULL DEFAULT 'NEW' COMMENT 'NEW \ RUNNING \ FINISHED \ FAILED \ CANCELED', 7 | `result` VARCHAR(1024) NOT NULL DEFAULT '', 8 | `run_at` DATETIME DEFAULT NULL, 9 | `update_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 10 | `create_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 11 | INDEX idx_project_id (project_id), 12 | INDEX idx_user_id (user_id) 13 | ) CHARSET utf8mb4 14 | COLLATE utf8mb4_unicode_ci; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.1__driver_file.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE database_type 2 | ADD COLUMN jdbc_driver_file_path VARCHAR(512) DEFAULT NULL AFTER jdbc_driver_file_url; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.2__document_comment_type.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE databasir.table_document 2 | MODIFY COLUMN `comment` TEXT DEFAULT NULL; 3 | ALTER TABLE databasir.table_column_document 4 | MODIFY COLUMN `comment` TEXT DEFAULT NULL; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.3__trigger_name.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE table_trigger_document 2 | ADD COLUMN name VARCHAR(1024) DEFAULT '' NOT NULL AFTER id; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.5__oauth_prop.sql: -------------------------------------------------------------------------------- 1 | create table oauth_app_property 2 | ( 3 | `id` INT PRIMARY KEY AUTO_INCREMENT, 4 | `oauth_app_id` int not null comment 'oauth_app.id', 5 | `name` text not null, 6 | `value` text not null, 7 | `create_at` TIMESTAMP not null default CURRENT_TIMESTAMP, 8 | INDEX idx_oauth_app_id (oauth_app_id) 9 | ) CHARSET utf8mb4 10 | COLLATE utf8mb4_unicode_ci; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.6__oauth_prop_migraiton.sql: -------------------------------------------------------------------------------- 1 | insert into oauth_app_property (oauth_app_id, name, value) 2 | select id, 'auth_host', auth_url 3 | from oauth_app 4 | where auth_url is not null; 5 | 6 | insert into oauth_app_property (oauth_app_id, name, value) 7 | select id, 'resource_host', resource_url 8 | from oauth_app 9 | where resource_url is not null; 10 | 11 | insert into oauth_app_property (oauth_app_id, name, value) 12 | select id, 'client_id', client_id 13 | from oauth_app 14 | where client_id is not null; 15 | 16 | insert into oauth_app_property (oauth_app_id, name, value) 17 | select id, 'client_secret', client_secret 18 | from oauth_app 19 | where client_secret is not null; 20 | 21 | alter table oauth_app 22 | drop column auth_url; 23 | alter table oauth_app 24 | drop column resource_url; 25 | alter table oauth_app 26 | drop column client_id; 27 | alter table oauth_app 28 | drop column client_secret; 29 | alter table oauth_app 30 | drop column scope; 31 | -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.7__sys_mail.sql: -------------------------------------------------------------------------------- 1 | alter table sys_mail 2 | add column `mail_from` varchar(512) null; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4.8__sys_mail.sql: -------------------------------------------------------------------------------- 1 | alter table sys_mail 2 | add column `use_tls` BOOLEAN NOT NULL DEFAULT FALSE; -------------------------------------------------------------------------------- /dao/src/main/resources/db/migration/V1.4__project_uk.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE database_document 2 | ADD CONSTRAINT UNIQUE uk_project_id_version_is_archive (project_id, version, is_archive); 3 | ALTER TABLE database_document 4 | DROP INDEX idx_project_id; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vran-dev/databasir/01fa3284b6155dd104965307c162cbdaf22c9a3a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /local.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:11.0.13-jre 2 | WORKDIR /app 3 | ADD api/build/libs/databasir.jar /app/databasir.jar 4 | EXPOSE 8080 5 | 6 | ENTRYPOINT ["sh", "-c","java -XX:+PrintCommandLineFlags -Ddatabasir.db.url=${DATABASIR_DB_URL} -Ddatabasir.db.username=${DATABASIR_DB_USERNAME} -Ddatabasir.db.password=${DATABASIR_DB_PASSWORD} -jar /app/databasir.jar ${PARAMS}"] -------------------------------------------------------------------------------- /meta/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testImplementation 'mysql:mysql-connector-java:8.0.27' 3 | implementation 'org.commonmark:commonmark:0.18.1' 4 | implementation 'org.freemarker:freemarker:2.3.31' 5 | testImplementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" 6 | testImplementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" 7 | } 8 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/DatabasirConfig.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.Collection; 7 | import java.util.HashSet; 8 | 9 | @Getter 10 | @Setter 11 | public class DatabasirConfig { 12 | 13 | private Collection ignoreTableNameRegex = new HashSet<>(); 14 | 15 | private Collection ignoreTableColumnNameRegex = new HashSet<>(); 16 | 17 | public DatabasirConfig ignoreTable(String tableNameRegex) { 18 | ignoreTableNameRegex.add(tableNameRegex); 19 | return this; 20 | } 21 | 22 | public DatabasirConfig ignoreColumn(String columnNameRegex) { 23 | ignoreTableColumnNameRegex.add(columnNameRegex); 24 | return this; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/Diffs.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff; 2 | 3 | import com.databasir.core.diff.data.RootDiff; 4 | import com.databasir.core.diff.processor.DatabaseDiffProcessor; 5 | import com.databasir.core.meta.data.DatabaseMeta; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | @Slf4j 9 | public class Diffs { 10 | 11 | private static final DatabaseDiffProcessor databaseDiffProcessor = new DatabaseDiffProcessor(); 12 | 13 | public static RootDiff diff(DatabaseMeta original, DatabaseMeta current) { 14 | return databaseDiffProcessor.process(original, current); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/data/Diff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.data; 2 | 3 | public interface Diff { 4 | 5 | DiffType getDiffType(); 6 | 7 | Object getOriginal(); 8 | 9 | Object getCurrent(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/data/DiffType.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.data; 2 | 3 | public enum DiffType { 4 | NONE, ADDED, REMOVED, MODIFIED; 5 | 6 | public static boolean isModified(DiffType type) { 7 | return type != null && type != NONE; 8 | } 9 | 10 | public boolean isAdded() { 11 | return this == ADDED; 12 | } 13 | 14 | public boolean isRemoved() { 15 | return this == REMOVED; 16 | } 17 | 18 | public boolean isNone() { 19 | return this == NONE; 20 | } 21 | } -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/data/FieldDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.data; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | @Builder 11 | public class FieldDiff implements Diff { 12 | 13 | private String fieldName; 14 | 15 | private DiffType diffType; 16 | 17 | private Object original; 18 | 19 | private Object current; 20 | 21 | @Builder.Default 22 | private List fields = new ArrayList<>(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/data/RootDiff.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.data; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class RootDiff { 10 | 11 | private DiffType diffType; 12 | 13 | private List fields = new ArrayList<>(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/processor/ColumnDiffProcessor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.processor; 2 | 3 | import com.databasir.core.diff.data.FieldDiff; 4 | import com.databasir.core.meta.data.ColumnMeta; 5 | 6 | import java.util.List; 7 | 8 | public class ColumnDiffProcessor implements DiffProcessor { 9 | 10 | @Override 11 | public FieldDiff process(String fieldName, List original, List current) { 12 | return diffTableField(original, current, fieldName, ColumnMeta::getName); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/processor/ForeignKeyDiffProcessor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.processor; 2 | 3 | import com.databasir.core.diff.data.FieldDiff; 4 | import com.databasir.core.meta.data.ForeignKeyMeta; 5 | 6 | import java.util.List; 7 | 8 | public class ForeignKeyDiffProcessor implements DiffProcessor { 9 | 10 | @Override 11 | public FieldDiff process(String fieldName, List original, List current) { 12 | return diffTableField( 13 | original, 14 | current, 15 | "foreignKeys", 16 | fk -> fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/processor/IndexDiffProcessor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.processor; 2 | 3 | import com.databasir.core.diff.data.FieldDiff; 4 | import com.databasir.core.meta.data.IndexMeta; 5 | 6 | import java.util.List; 7 | 8 | public class IndexDiffProcessor implements DiffProcessor { 9 | 10 | @Override 11 | public FieldDiff process(String fieldName, List original, List current) { 12 | return diffTableField(original, current, fieldName, IndexMeta::getName); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/diff/processor/TriggerDiffProcessor.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.diff.processor; 2 | 3 | import com.databasir.core.diff.data.FieldDiff; 4 | import com.databasir.core.meta.data.TriggerMeta; 5 | 6 | import java.util.List; 7 | 8 | public class TriggerDiffProcessor implements DiffProcessor { 9 | 10 | @Override 11 | public FieldDiff process(String fieldName, List original, List current) { 12 | return diffTableField(original, current, fieldName, TriggerMeta::getName); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/ColumnMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Builder 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ColumnMeta { 13 | 14 | private String name; 15 | 16 | private String comment; 17 | 18 | private String type; 19 | 20 | private Integer dataType; 21 | 22 | /** 23 | * if default value is empty string, will be converted to ''. 24 | */ 25 | private String defaultValue; 26 | 27 | private Integer size; 28 | 29 | private Integer decimalDigits; 30 | 31 | private String nullable; 32 | 33 | private String autoIncrement; 34 | 35 | private Boolean isPrimaryKey; 36 | } -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/DatabaseMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Builder 15 | public class DatabaseMeta { 16 | 17 | /** 18 | * product_name 19 | */ 20 | private String productName; 21 | 22 | /** 23 | * product_version 24 | */ 25 | private String productVersion; 26 | 27 | /** 28 | * driver_name 29 | */ 30 | private String driverName; 31 | 32 | /** 33 | * driver_version 34 | */ 35 | private String driverVersion; 36 | 37 | /** 38 | * database_name 39 | */ 40 | private String databaseName; 41 | 42 | /** 43 | * schema_name 44 | */ 45 | private String schemaName; 46 | 47 | @Builder.Default 48 | private List tables = Collections.emptyList(); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Builder 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ForeignKeyMeta { 13 | 14 | private Integer keySeq; 15 | 16 | /** 17 | * may null 18 | */ 19 | private String pkName; 20 | 21 | private String pkTableName; 22 | 23 | private String pkColumnName; 24 | 25 | /** 26 | * may null 27 | */ 28 | private String fkName; 29 | 30 | private String fkTableName; 31 | 32 | private String fkColumnName; 33 | 34 | /** 35 | * NO_ACTION \ CASCADE \ SET_NULL \ SET_DEFAULT 36 | */ 37 | private String updateRule; 38 | 39 | /** 40 | * NO_ACTION \ CASCADE \ SET_NULL \ SET_DEFAULT 41 | */ 42 | private String deleteRule; 43 | } 44 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/IndexMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | @Builder 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class IndexMeta { 16 | 17 | private String name; 18 | 19 | @Builder.Default 20 | private List columnNames = Collections.emptyList(); 21 | 22 | private Boolean isUniqueKey; 23 | } 24 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/TableMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | @Builder 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class TableMeta { 16 | 17 | private String name; 18 | 19 | private String type; 20 | 21 | private String comment; 22 | 23 | @Builder.Default 24 | private List columns = Collections.emptyList(); 25 | 26 | @Builder.Default 27 | private List triggers = Collections.emptyList(); 28 | 29 | @Builder.Default 30 | private List indexes = Collections.emptyList(); 31 | 32 | @Builder.Default 33 | private List foreignKeys = Collections.emptyList(); 34 | } 35 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/data/TriggerMeta.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * now: only support mysql, postgresql. 10 | */ 11 | @Builder 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class TriggerMeta { 16 | 17 | private String name; 18 | 19 | /** 20 | * example: BEFORE, AFTER 21 | */ 22 | private String timing; 23 | 24 | /** 25 | * example: INSERT, UPDATE 26 | */ 27 | private String manipulation; 28 | 29 | private String statement; 30 | 31 | private String createAt; 32 | } 33 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/ColumnMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.ColumnMeta; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | 9 | public interface ColumnMetaProvider { 10 | 11 | List selectColumns(Connection connection, TableCondition condition); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/DatabaseMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.DatabaseMeta; 4 | import com.databasir.core.meta.provider.condition.Condition; 5 | 6 | import java.sql.Connection; 7 | import java.util.Optional; 8 | 9 | public interface DatabaseMetaProvider { 10 | 11 | Optional select(Connection connection, Condition condition); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/ForeignKeyMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.ForeignKeyMeta; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | 9 | public interface ForeignKeyMetaProvider { 10 | 11 | List selectForeignKeys(Connection connection, TableCondition condition); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/IndexMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.IndexMeta; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | 9 | public interface IndexMetaProvider { 10 | 11 | List selectIndexes(Connection connection, TableCondition condition); 12 | } 13 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/TableMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.TableMeta; 4 | import com.databasir.core.meta.provider.condition.Condition; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | 9 | public interface TableMetaProvider { 10 | 11 | List selectTables(Connection connection, Condition condition); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/TriggerMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider; 2 | 3 | import com.databasir.core.meta.data.TriggerMeta; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | 9 | public interface TriggerMetaProvider { 10 | 11 | List selectTriggers(Connection connection, TableCondition condition); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/condition/Condition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider.condition; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.NonNull; 6 | import lombok.experimental.SuperBuilder; 7 | 8 | import java.util.Collection; 9 | import java.util.Collections; 10 | import java.util.regex.Pattern; 11 | 12 | @SuperBuilder 13 | @Getter 14 | public class Condition { 15 | 16 | @NonNull 17 | private String databaseName; 18 | 19 | private String schemaName; 20 | 21 | @Builder.Default 22 | @Builder.ObtainVia(method = "ignoreTableNameRegexes") 23 | private Collection ignoreTableNamePatterns = Collections.emptyList(); 24 | 25 | @Builder.Default 26 | @Builder.ObtainVia(method = "ignoreTableColumnNameRegexes") 27 | private Collection ignoreTableColumnNamePatterns = Collections.emptyList(); 28 | 29 | public boolean tableIsIgnored(String tableName) { 30 | return ignoreTableNamePatterns.stream().anyMatch(regex -> regex.matcher(tableName).matches()); 31 | } 32 | 33 | public boolean columnIsIgnored(String column) { 34 | return ignoreTableColumnNamePatterns.stream().anyMatch(regex -> regex.matcher(column).matches()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/condition/TableCondition.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider.condition; 2 | 3 | import lombok.Getter; 4 | import lombok.NonNull; 5 | import lombok.experimental.SuperBuilder; 6 | 7 | @SuperBuilder 8 | @Getter 9 | public class TableCondition extends Condition { 10 | 11 | @NonNull 12 | private String tableName; 13 | 14 | public static TableCondition of(Condition condition, String tableName) { 15 | return TableCondition.builder() 16 | .databaseName(condition.getDatabaseName()) 17 | .tableName(tableName) 18 | .schemaName(condition.getSchemaName()) 19 | .ignoreTableNamePatterns(condition.getIgnoreTableNamePatterns()) 20 | .ignoreTableColumnNamePatterns(condition.getIgnoreTableColumnNamePatterns()) 21 | .build(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/jdbc/JdbcTriggerMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider.jdbc; 2 | 3 | import com.databasir.core.meta.data.TriggerMeta; 4 | import com.databasir.core.meta.provider.TriggerMetaProvider; 5 | import com.databasir.core.meta.provider.condition.TableCondition; 6 | 7 | import java.sql.Connection; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class JdbcTriggerMetaProvider implements TriggerMetaProvider { 12 | 13 | @Override 14 | public List selectTriggers(Connection connection, TableCondition condition) { 15 | // note: jdbc not support get triggers 16 | return Collections.emptyList(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/maria/MariaTriggerMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider.maria; 2 | 3 | import com.databasir.core.meta.provider.AbstractSqlTriggerMetaProvider; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | @Slf4j 8 | public class MariaTriggerMetaProvider extends AbstractSqlTriggerMetaProvider { 9 | @Override 10 | protected String sql(TableCondition condition) { 11 | String sql = "SELECT \n" 12 | + " TRIGGER_NAME,\n" 13 | + " TRIGGER_SCHEMA,\n" 14 | + " TRIGGER_CATALOG,\n" 15 | + " EVENT_OBJECT_CATALOG,\n" 16 | + " EVENT_OBJECT_SCHEMA,\n" 17 | + " EVENT_OBJECT_TABLE,\n" 18 | + " ACTION_STATEMENT,\n" 19 | + " ACTION_TIMING,\n" 20 | + " EVENT_MANIPULATION,\n" 21 | + " CREATED\n" 22 | + "FROM information_schema.triggers " 23 | + "WHERE TRIGGER_SCHEMA = '%s' AND EVENT_OBJECT_TABLE = '%s'"; 24 | return String.format(sql, condition.getDatabaseName(), condition.getTableName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /meta/src/main/java/com/databasir/core/meta/provider/postgresql/PostgresqlTriggerMetaProvider.java: -------------------------------------------------------------------------------- 1 | package com.databasir.core.meta.provider.postgresql; 2 | 3 | import com.databasir.core.meta.provider.AbstractSqlTriggerMetaProvider; 4 | import com.databasir.core.meta.provider.condition.TableCondition; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | @Slf4j 8 | public class PostgresqlTriggerMetaProvider extends AbstractSqlTriggerMetaProvider { 9 | @Override 10 | protected String sql(TableCondition condition) { 11 | String sql = "SELECT trigger_name AS TRIGGER_NAME,\n" 12 | + " action_timing AS ACTION_TIMING,\n" 13 | + " event_manipulation AS EVENT_MANIPULATION,\n" 14 | + " action_statement AS ACTION_STATEMENT,\n" 15 | + " created AS CREATED,\n" 16 | + " trigger_catalog AS trigger_catalog,\n" 17 | + " TRIGGER_SCHEMA AS trigger_schema,\n" 18 | + " event_object_catalog AS target_catalog,\n" 19 | + " event_object_schema AS target_schema,\n" 20 | + " event_object_table AS target_table_name\n" 21 | + "FROM information_schema.triggers " 22 | + "WHERE trigger_catalog = '%s' AND trigger_schema = '%s' AND event_object_table = '%s';"; 23 | return String.format(sql, condition.getDatabaseName(), condition.getSchemaName(), condition.getTableName()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /meta/src/test/resources/ut/diffsTest/diffDatabaseAdded/original.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /meta/src/test/resources/ut/diffsTest/diffDatabaseRemoved/current.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'databasir' 2 | include 'meta' 3 | include 'api' 4 | include 'common' 5 | include 'dao' 6 | include 'core' 7 | --------------------------------------------------------------------------------