diff --git a/api/src/main/java/com/databasir/api/DocumentDiscussionController.java b/api/src/main/java/com/databasir/api/DocumentDiscussionController.java index dcd323f..50f76bb 100644 --- a/api/src/main/java/com/databasir/api/DocumentDiscussionController.java +++ b/api/src/main/java/com/databasir/api/DocumentDiscussionController.java @@ -3,10 +3,10 @@ package com.databasir.api; import com.databasir.api.config.security.DatabasirUserDetails; import com.databasir.common.JsonData; import com.databasir.core.domain.log.annotation.Operation; -import com.databasir.core.domain.remark.data.DiscussionCreateRequest; -import com.databasir.core.domain.remark.data.DiscussionListCondition; -import com.databasir.core.domain.remark.data.DiscussionResponse; -import com.databasir.core.domain.remark.service.DocumentDiscussionService; +import com.databasir.core.domain.discussion.data.DiscussionCreateRequest; +import com.databasir.core.domain.discussion.data.DiscussionListCondition; +import com.databasir.core.domain.discussion.data.DiscussionResponse; +import com.databasir.core.domain.discussion.service.DocumentDiscussionService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/api/src/main/java/com/databasir/api/UserController.java b/api/src/main/java/com/databasir/api/UserController.java index 9203894..f464781 100644 --- a/api/src/main/java/com/databasir/api/UserController.java +++ b/api/src/main/java/com/databasir/api/UserController.java @@ -1,5 +1,6 @@ package com.databasir.api; +import com.databasir.api.common.LoginUserContext; import com.databasir.api.validator.UserOperationValidator; import com.databasir.common.JsonData; import com.databasir.common.exception.Forbidden; @@ -7,6 +8,7 @@ import com.databasir.core.domain.DomainErrors; import com.databasir.core.domain.log.annotation.Operation; import com.databasir.core.domain.user.data.*; import com.databasir.core.domain.user.service.UserService; +import com.databasir.core.infrastructure.event.EventPublisher; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -27,6 +29,8 @@ public class UserController { private final UserOperationValidator userOperationValidator; + private final EventPublisher eventPublisher; + @GetMapping(Routes.User.LIST) public JsonData> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable, @@ -60,7 +64,7 @@ public class UserController { @PreAuthorize("hasAnyAuthority('SYS_OWNER')") @Operation(module = Operation.Modules.USER, name = "创建用户") public JsonData create(@RequestBody @Valid UserCreateRequest request) { - userService.create(request); + userService.create(request, UserSource.MANUAL); return JsonData.ok(); } @@ -73,7 +77,8 @@ public class UserController { @PreAuthorize("hasAnyAuthority('SYS_OWNER')") @Operation(module = Operation.Modules.USER, name = "重置用户密码", involvedUserId = "#userId") public JsonData renewPassword(@PathVariable Integer userId) { - userService.renewPassword(userId); + Integer operatorUserId = LoginUserContext.getLoginUserId(); + userService.renewPassword(operatorUserId, userId); return JsonData.ok(); } diff --git a/api/src/main/java/com/databasir/api/common/LoginUserContext.java b/api/src/main/java/com/databasir/api/common/LoginUserContext.java new file mode 100644 index 0000000..28a010c --- /dev/null +++ b/api/src/main/java/com/databasir/api/common/LoginUserContext.java @@ -0,0 +1,14 @@ +package com.databasir.api.common; + +import com.databasir.api.config.security.DatabasirUserDetails; +import org.springframework.security.core.context.SecurityContextHolder; + +public class LoginUserContext { + + public static Integer getLoginUserId() { + DatabasirUserDetails principal = (DatabasirUserDetails) SecurityContextHolder.getContext() + .getAuthentication() + .getPrincipal(); + return principal.getUserPojo().getId(); + } +} diff --git a/core/src/main/java/com/databasir/core/domain/app/OpenAuthAppService.java b/core/src/main/java/com/databasir/core/domain/app/OpenAuthAppService.java index c2b4c17..d34b834 100644 --- a/core/src/main/java/com/databasir/core/domain/app/OpenAuthAppService.java +++ b/core/src/main/java/com/databasir/core/domain/app/OpenAuthAppService.java @@ -51,7 +51,7 @@ public class OpenAuthAppService { user.setAvatar(result.getAvatar()); user.setEnabled(true); user.setPassword(UUID.randomUUID().toString().substring(0, 6)); - Integer id = userService.create(user); + Integer id = userService.create(user, registrationId); return userService.get(id); }); } diff --git a/core/src/main/java/com/databasir/core/domain/remark/converter/DiscussionResponseConverter.java b/core/src/main/java/com/databasir/core/domain/discussion/converter/DiscussionResponseConverter.java similarity index 81% rename from core/src/main/java/com/databasir/core/domain/remark/converter/DiscussionResponseConverter.java rename to core/src/main/java/com/databasir/core/domain/discussion/converter/DiscussionResponseConverter.java index 1aafc2a..4532b83 100644 --- a/core/src/main/java/com/databasir/core/domain/remark/converter/DiscussionResponseConverter.java +++ b/core/src/main/java/com/databasir/core/domain/discussion/converter/DiscussionResponseConverter.java @@ -1,6 +1,6 @@ -package com.databasir.core.domain.remark.converter; +package com.databasir.core.domain.discussion.converter; -import com.databasir.core.domain.remark.data.DiscussionResponse; +import com.databasir.core.domain.discussion.data.DiscussionResponse; import com.databasir.dao.tables.pojos.DocumentDiscussionPojo; import com.databasir.dao.tables.pojos.UserPojo; import org.mapstruct.Mapper; diff --git a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionCreateRequest.java b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionCreateRequest.java similarity index 84% rename from core/src/main/java/com/databasir/core/domain/remark/data/DiscussionCreateRequest.java rename to core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionCreateRequest.java index 90ccb6d..6df0e0a 100644 --- a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionCreateRequest.java +++ b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionCreateRequest.java @@ -1,4 +1,4 @@ -package com.databasir.core.domain.remark.data; +package com.databasir.core.domain.discussion.data; import lombok.Data; diff --git a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionListCondition.java b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionListCondition.java similarity index 95% rename from core/src/main/java/com/databasir/core/domain/remark/data/DiscussionListCondition.java rename to core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionListCondition.java index 5748201..b912e39 100644 --- a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionListCondition.java +++ b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionListCondition.java @@ -1,4 +1,4 @@ -package com.databasir.core.domain.remark.data; +package com.databasir.core.domain.discussion.data; import com.databasir.dao.Tables; import lombok.Data; diff --git a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionResponse.java b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionResponse.java similarity index 89% rename from core/src/main/java/com/databasir/core/domain/remark/data/DiscussionResponse.java rename to core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionResponse.java index 4703b23..4ed5d16 100644 --- a/core/src/main/java/com/databasir/core/domain/remark/data/DiscussionResponse.java +++ b/core/src/main/java/com/databasir/core/domain/discussion/data/DiscussionResponse.java @@ -1,4 +1,4 @@ -package com.databasir.core.domain.remark.data; +package com.databasir.core.domain.discussion.data; import lombok.Data; diff --git a/core/src/main/java/com/databasir/core/domain/discussion/event/DiscussionCreated.java b/core/src/main/java/com/databasir/core/domain/discussion/event/DiscussionCreated.java new file mode 100644 index 0000000..695c595 --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/discussion/event/DiscussionCreated.java @@ -0,0 +1,28 @@ +package com.databasir.core.domain.discussion.event; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Optional; + +@Data +public class DiscussionCreated { + + private Integer discussionId; + + private Integer createByUserId; + + private String content; + + private Integer projectId; + + private String tableName; + + private String columnName; + + private LocalDateTime createAt; + + public Optional getColumnName() { + return Optional.of(columnName); + } +} diff --git a/core/src/main/java/com/databasir/core/domain/discussion/event/converter/DiscussionEventConverter.java b/core/src/main/java/com/databasir/core/domain/discussion/event/converter/DiscussionEventConverter.java new file mode 100644 index 0000000..120e7c5 --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/discussion/event/converter/DiscussionEventConverter.java @@ -0,0 +1,14 @@ +package com.databasir.core.domain.discussion.event.converter; + +import com.databasir.core.domain.discussion.event.DiscussionCreated; +import com.databasir.dao.tables.pojos.DocumentDiscussionPojo; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper(componentModel = "spring") +public interface DiscussionEventConverter { + + @Mapping(target = "createByUserId", source = "pojo.userId") + DiscussionCreated of(DocumentDiscussionPojo pojo, Integer discussionId); + +} diff --git a/core/src/main/java/com/databasir/core/domain/remark/service/DocumentDiscussionService.java b/core/src/main/java/com/databasir/core/domain/discussion/service/DocumentDiscussionService.java similarity index 72% rename from core/src/main/java/com/databasir/core/domain/remark/service/DocumentDiscussionService.java rename to core/src/main/java/com/databasir/core/domain/discussion/service/DocumentDiscussionService.java index 49edae4..89e5c9b 100644 --- a/core/src/main/java/com/databasir/core/domain/remark/service/DocumentDiscussionService.java +++ b/core/src/main/java/com/databasir/core/domain/discussion/service/DocumentDiscussionService.java @@ -1,10 +1,13 @@ -package com.databasir.core.domain.remark.service; +package com.databasir.core.domain.discussion.service; import com.databasir.common.exception.Forbidden; -import com.databasir.core.domain.remark.converter.DiscussionResponseConverter; -import com.databasir.core.domain.remark.data.DiscussionCreateRequest; -import com.databasir.core.domain.remark.data.DiscussionListCondition; -import com.databasir.core.domain.remark.data.DiscussionResponse; +import com.databasir.core.domain.discussion.converter.DiscussionResponseConverter; +import com.databasir.core.domain.discussion.data.DiscussionCreateRequest; +import com.databasir.core.domain.discussion.data.DiscussionListCondition; +import com.databasir.core.domain.discussion.data.DiscussionResponse; +import com.databasir.core.domain.discussion.event.DiscussionCreated; +import com.databasir.core.domain.discussion.event.converter.DiscussionEventConverter; +import com.databasir.core.infrastructure.event.EventPublisher; import com.databasir.dao.impl.DocumentDiscussionDao; import com.databasir.dao.impl.ProjectDao; import com.databasir.dao.impl.UserDao; @@ -32,6 +35,10 @@ public class DocumentDiscussionService { private final DiscussionResponseConverter discussionResponseConverter; + private final DiscussionEventConverter discussionEventConverter; + + private final EventPublisher eventPublisher; + public void deleteById(Integer groupId, Integer projectId, Integer discussionId) { @@ -57,9 +64,9 @@ public class DocumentDiscussionService { .stream() .collect(Collectors.toMap(UserPojo::getId, Function.identity())); return data - .map(dicussionPojo -> { - UserPojo userPojo = userMapById.get(dicussionPojo.getUserId()); - return discussionResponseConverter.of(dicussionPojo, userPojo); + .map(discussionPojo -> { + UserPojo userPojo = userMapById.get(discussionPojo.getUserId()); + return discussionResponseConverter.of(discussionPojo, userPojo); }); } else { throw new Forbidden(); @@ -74,7 +81,9 @@ public class DocumentDiscussionService { pojo.setContent(request.getContent()); pojo.setTableName(request.getTableName()); pojo.setColumnName(request.getColumnName()); - documentDiscussionDao.insertAndReturnId(pojo); + Integer discussionId = documentDiscussionDao.insertAndReturnId(pojo); + DiscussionCreated event = discussionEventConverter.of(pojo, discussionId); + eventPublisher.publish(event); } else { throw new Forbidden(); } diff --git a/core/src/main/java/com/databasir/core/domain/document/event/DocumentUpdated.java b/core/src/main/java/com/databasir/core/domain/document/event/DocumentUpdated.java new file mode 100644 index 0000000..637685f --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/document/event/DocumentUpdated.java @@ -0,0 +1,30 @@ +package com.databasir.core.domain.document.event; + +import com.databasir.core.diff.data.RootDiff; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Optional; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DocumentUpdated { + + private RootDiff diff; + + private Long newVersion; + + private Long oldVersion; + + private Integer projectId; + + public Optional getOldVersion() { + return Optional.ofNullable(oldVersion); + } + + public Optional getDiff() { + return Optional.ofNullable(diff); + } +} diff --git a/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java b/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java index 571259b..ed7ad48 100644 --- a/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java +++ b/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java @@ -14,10 +14,12 @@ import com.databasir.core.domain.document.data.DatabaseDocumentResponse; import com.databasir.core.domain.document.data.DatabaseDocumentSimpleResponse; import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse; import com.databasir.core.domain.document.data.TableDocumentResponse; +import com.databasir.core.domain.document.event.DocumentUpdated; import com.databasir.core.domain.document.generator.DocumentFileGenerator; import com.databasir.core.domain.document.generator.DocumentFileType; import com.databasir.core.infrastructure.connection.DatabaseConnectionService; import com.databasir.core.infrastructure.converter.JsonConverter; +import com.databasir.core.infrastructure.event.EventPublisher; import com.databasir.core.meta.data.DatabaseMeta; import com.databasir.dao.impl.*; import com.databasir.dao.tables.pojos.*; @@ -84,6 +86,8 @@ public class DocumentService { private final List documentFileGenerators; + private final EventPublisher eventPublisher; + @Transactional public void syncByProjectId(Integer projectId) { projectDao.selectOptionalById(projectId) @@ -103,9 +107,12 @@ public class DocumentService { Integer previousDocumentId = original.getId(); // archive old version databaseDocumentDao.updateIsArchiveById(previousDocumentId, true); - saveNewDocument(current, original.getVersion() + 1, original.getProjectId()); + Long version = original.getVersion(); + saveNewDocument(current, version + 1, original.getProjectId()); + eventPublisher.publish(new DocumentUpdated(diff, version + 1, version, projectId)); } else { saveNewDocument(current, 1L, projectId); + eventPublisher.publish(new DocumentUpdated(null, 1L, null, projectId)); } } diff --git a/core/src/main/java/com/databasir/core/domain/user/data/UserCreateRequest.java b/core/src/main/java/com/databasir/core/domain/user/data/UserCreateRequest.java index ae68290..8e74f5b 100644 --- a/core/src/main/java/com/databasir/core/domain/user/data/UserCreateRequest.java +++ b/core/src/main/java/com/databasir/core/domain/user/data/UserCreateRequest.java @@ -25,4 +25,5 @@ public class UserCreateRequest { @NotNull private Boolean enabled; + } diff --git a/core/src/main/java/com/databasir/core/domain/user/data/UserSource.java b/core/src/main/java/com/databasir/core/domain/user/data/UserSource.java new file mode 100644 index 0000000..1b2ea7f --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/user/data/UserSource.java @@ -0,0 +1,12 @@ +package com.databasir.core.domain.user.data; + +import java.util.Objects; + +public interface UserSource { + + String MANUAL = "manual"; + + static boolean isManual(String source) { + return Objects.equals(source, MANUAL); + } +} diff --git a/core/src/main/java/com/databasir/core/domain/user/event/UserCreated.java b/core/src/main/java/com/databasir/core/domain/user/event/UserCreated.java new file mode 100644 index 0000000..cdd1f2c --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/user/event/UserCreated.java @@ -0,0 +1,23 @@ +package com.databasir.core.domain.user.event; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +@Getter +@Builder +@ToString +public class UserCreated { + + private Integer userId; + + private String nickname; + + private String email; + + private String username; + + private String rawPassword; + + private String source; +} diff --git a/core/src/main/java/com/databasir/core/domain/user/event/UserPasswordRenewed.java b/core/src/main/java/com/databasir/core/domain/user/event/UserPasswordRenewed.java new file mode 100644 index 0000000..ca9a6f3 --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/user/event/UserPasswordRenewed.java @@ -0,0 +1,21 @@ +package com.databasir.core.domain.user.event; + +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@Builder +public class UserPasswordRenewed { + + private Integer renewByUserId; + + private String nickname; + + private String email; + + private String newPassword; + + private LocalDateTime renewTime; +} diff --git a/core/src/main/java/com/databasir/core/domain/user/event/converter/UserEventConverter.java b/core/src/main/java/com/databasir/core/domain/user/event/converter/UserEventConverter.java new file mode 100644 index 0000000..be92577 --- /dev/null +++ b/core/src/main/java/com/databasir/core/domain/user/event/converter/UserEventConverter.java @@ -0,0 +1,21 @@ +package com.databasir.core.domain.user.event.converter; + +import com.databasir.core.domain.user.event.UserCreated; +import com.databasir.core.domain.user.event.UserPasswordRenewed; +import com.databasir.dao.tables.pojos.UserPojo; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +import java.time.LocalDateTime; + +@Mapper(componentModel = "spring") +public interface UserEventConverter { + + UserPasswordRenewed userPasswordRenewed(UserPojo pojo, + Integer renewByUserId, + LocalDateTime renewTime, + String newPassword); + + @Mapping(target = "userId", source = "userId") + UserCreated userCreated(UserPojo pojo, String source, String rawPassword, Integer userId); +} diff --git a/core/src/main/java/com/databasir/core/domain/user/service/UserService.java b/core/src/main/java/com/databasir/core/domain/user/service/UserService.java index fc2639a..a4f05e6 100644 --- a/core/src/main/java/com/databasir/core/domain/user/service/UserService.java +++ b/core/src/main/java/com/databasir/core/domain/user/service/UserService.java @@ -4,8 +4,14 @@ import com.databasir.core.domain.DomainErrors; import com.databasir.core.domain.user.converter.UserPojoConverter; import com.databasir.core.domain.user.converter.UserResponseConverter; import com.databasir.core.domain.user.data.*; -import com.databasir.core.infrastructure.mail.MailSender; -import com.databasir.dao.impl.*; +import com.databasir.core.domain.user.event.UserCreated; +import com.databasir.core.domain.user.event.UserPasswordRenewed; +import com.databasir.core.domain.user.event.converter.UserEventConverter; +import com.databasir.core.infrastructure.event.EventPublisher; +import com.databasir.dao.impl.GroupDao; +import com.databasir.dao.impl.LoginDao; +import com.databasir.dao.impl.UserDao; +import com.databasir.dao.impl.UserRoleDao; import com.databasir.dao.tables.pojos.GroupPojo; import com.databasir.dao.tables.pojos.UserPojo; import com.databasir.dao.tables.pojos.UserRolePojo; @@ -17,6 +23,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.*; import static java.util.stream.Collectors.*; @@ -31,15 +38,15 @@ public class UserService { private final GroupDao groupDao; - private final SysMailDao sysMailDao; - private final LoginDao loginDao; private final UserPojoConverter userPojoConverter; private final UserResponseConverter userResponseConverter; - private final MailSender mailSender; + private final UserEventConverter userEventConverter; + + private final EventPublisher eventPublisher; @SuppressWarnings("checkstyle:all") private BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); @@ -64,14 +71,18 @@ public class UserService { } @Transactional - public Integer create(UserCreateRequest userCreateRequest) { + public Integer create(UserCreateRequest userCreateRequest, String source) { userDao.selectByEmailOrUsername(userCreateRequest.getUsername()).ifPresent(data -> { throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception(); }); String hashedPassword = bCryptPasswordEncoder.encode(userCreateRequest.getPassword()); UserPojo pojo = userPojoConverter.of(userCreateRequest, hashedPassword); try { - return userDao.insertAndReturnId(pojo); + Integer id = userDao.insertAndReturnId(pojo); + // publish event + UserCreated event = userEventConverter.userCreated(pojo, source, userCreateRequest.getPassword(), id); + eventPublisher.publish(event); + return id; } catch (DuplicateKeyException e) { throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception(); } @@ -106,19 +117,20 @@ public class UserService { } @Transactional - public String renewPassword(Integer userId) { - UserPojo userPojo = userDao.selectById(userId); + public String renewPassword(Integer renewByUserId, Integer userId) { + UserPojo pojo = userDao.selectById(userId); String randomPassword = UUID.randomUUID().toString() .replace("-", "") .substring(0, 8); String hashedPassword = bCryptPasswordEncoder.encode(randomPassword); userDao.updatePassword(userId, hashedPassword); - sysMailDao.selectOptionTopOne() - .ifPresent(mailPojo -> { - String subject = "Databasir 密码重置提醒"; - String message = "您的密码已被重置,新密码为:" + randomPassword; - mailSender.send(mailPojo, userPojo.getEmail(), subject, message); - }); + + // publish event + UserPasswordRenewed event = userEventConverter.userPasswordRenewed(pojo, + renewByUserId, + LocalDateTime.now(), + randomPassword); + eventPublisher.publish(event); return randomPassword; } diff --git a/core/src/main/java/com/databasir/core/infrastructure/event/EventPublisher.java b/core/src/main/java/com/databasir/core/infrastructure/event/EventPublisher.java new file mode 100644 index 0000000..4bc06b6 --- /dev/null +++ b/core/src/main/java/com/databasir/core/infrastructure/event/EventPublisher.java @@ -0,0 +1,16 @@ +package com.databasir.core.infrastructure.event; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class EventPublisher { + + private final ApplicationEventPublisher applicationEventPublisher; + + public void publish(Object event) { + applicationEventPublisher.publishEvent(event); + } +} diff --git a/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DiscussionEventSubscriber.java b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DiscussionEventSubscriber.java new file mode 100644 index 0000000..0651433 --- /dev/null +++ b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DiscussionEventSubscriber.java @@ -0,0 +1,18 @@ +package com.databasir.core.infrastructure.event.subscriber; + +import com.databasir.core.domain.discussion.event.DiscussionCreated; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Slf4j +public class DiscussionEventSubscriber { + + @EventListener(classes = DiscussionCreated.class) + public void onDiscussionCreated(DiscussionCreated created) { + // TODO notification group member who subscribe this event + } +} diff --git a/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java new file mode 100644 index 0000000..87a5d4a --- /dev/null +++ b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java @@ -0,0 +1,84 @@ +package com.databasir.core.infrastructure.event.subscriber; + +import com.databasir.core.diff.data.DiffType; +import com.databasir.core.diff.data.RootDiff; +import com.databasir.core.domain.document.event.DocumentUpdated; +import com.databasir.core.infrastructure.mail.MailSender; +import com.databasir.dao.impl.ProjectDao; +import com.databasir.dao.impl.SysMailDao; +import com.databasir.dao.impl.UserDao; +import com.databasir.dao.impl.UserRoleDao; +import com.databasir.dao.tables.pojos.ProjectPojo; +import com.databasir.dao.tables.pojos.UserPojo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +@Slf4j +public class DocumentEventSubscriber { + + private final ProjectDao projectDao; + + private final MailSender mailSender; + + private final UserRoleDao userRoleDao; + + private final UserDao userDao; + + private final SysMailDao sysMailDao; + + @EventListener(classes = DocumentUpdated.class) + public void onDocumentUpdated(DocumentUpdated created) { + ProjectPojo project = projectDao.selectById(created.getProjectId()); + List to = userDao.selectEnabledGroupMembers(project.getGroupId()) + .stream() + .map(UserPojo::getEmail) + .filter(mail -> mail.contains("@")) + .collect(Collectors.toList()); + sysMailDao.selectOptionTopOne().ifPresent(mail -> { + String subject = project.getName() + " 文档有新的版本"; + String message = created.getDiff() + .map(diff -> build(diff)) + .orElseGet(() -> "首次文档同步常规"); + mailSender.batchSend(mail, to, subject, message); + }); + } + + private String build(RootDiff diff) { + if (diff.getDiffType() == DiffType.NONE) { + return ""; + } else { + return diff.getFields() + .stream() + .filter(field -> field.getFieldName().equals("tables")) + .flatMap(f -> f.getFields().stream()) + .map(table -> { + String tableName = table.getFieldName(); + String change = toDescription(table.getDiffType()); + return tableName + " " + change; + }) + .collect(Collectors.joining("\n")); + } + } + + private String toDescription(DiffType diffType) { + switch (diffType) { + case NONE: + return "无变化"; + case ADDED: + return "新增"; + case REMOVED: + return "删除"; + case MODIFIED: + return "修改"; + default: + return diffType.name(); + } + } +} diff --git a/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriber.java b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriber.java new file mode 100644 index 0000000..adc01b9 --- /dev/null +++ b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriber.java @@ -0,0 +1,61 @@ +package com.databasir.core.infrastructure.event.subscriber; + +import com.databasir.core.domain.user.data.UserSource; +import com.databasir.core.domain.user.event.UserCreated; +import com.databasir.core.domain.user.event.UserPasswordRenewed; +import com.databasir.core.infrastructure.mail.MailSender; +import com.databasir.dao.impl.SysMailDao; +import com.databasir.dao.impl.UserDao; +import com.databasir.dao.tables.pojos.UserPojo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * TODO use html template instead of simple message + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class UserEventSubscriber { + + private final MailSender mailSender; + + private final SysMailDao sysMailDao; + + private final UserDao userDao; + + @EventListener(classes = UserPasswordRenewed.class) + public void onPasswordRenewed(UserPasswordRenewed event) { + UserPojo operator = userDao.selectById(event.getRenewByUserId()); + sysMailDao.selectOptionTopOne() + .ifPresent(mailPojo -> { + String renewBy = operator.getNickname(); + String subject = "Databasir 密码重置提醒"; + String message = String.format("Hi %s,\r\n 您的密码已被 %s 重置,新密码为 %s", + event.getNickname(), + renewBy, + event.getNewPassword()); + mailSender.send(mailPojo, event.getEmail(), subject, message); + }); + } + + @EventListener(classes = UserCreated.class) + public void onUserCreated(UserCreated event) { + String subject = "Databasir 账户创建成功"; + String message; + if (UserSource.isManual(event.getSource())) { + message = String.format("Hi %s\r\n您的 Databasir 账户已创建成功,用户名:%s,密码:%s", + event.getNickname(), event.getUsername(), event.getRawPassword()); + } else { + message = String.format("Hi %s\r\n您的 Databasir 账户已创建成功,用户名:%s", + event.getNickname(), event.getUsername()); + } + sysMailDao.selectOptionTopOne() + .ifPresent(mailPojo -> { + mailSender.send(mailPojo, event.getEmail(), subject, message); + }); + } + +} diff --git a/core/src/main/java/com/databasir/core/infrastructure/mail/MailSender.java b/core/src/main/java/com/databasir/core/infrastructure/mail/MailSender.java index a3d835b..bc53664 100644 --- a/core/src/main/java/com/databasir/core/infrastructure/mail/MailSender.java +++ b/core/src/main/java/com/databasir/core/infrastructure/mail/MailSender.java @@ -7,21 +7,26 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; @Component public class MailSender { - public void send(SysMailPojo mail, String to, String subject, String content) { + public void batchSend(SysMailPojo mail, Collection to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(mail.getUsername()); - message.setTo(to); + message.setTo(to.toArray(new String[0])); message.setSubject(subject); message.setText(content); - JavaMailSender sender = initJavaMailSender(mail); sender.send(message); } + public void send(SysMailPojo mail, String to, String subject, String content) { + this.batchSend(mail, Collections.singleton(to), subject, content); + } + private JavaMailSender initJavaMailSender(SysMailPojo properties) { JavaMailSenderImpl sender = new JavaMailSenderImpl(); sender.setHost(properties.getSmtpHost()); diff --git a/dao/src/main/java/com/databasir/dao/impl/UserDao.java b/dao/src/main/java/com/databasir/dao/impl/UserDao.java index 6463630..cd8426b 100644 --- a/dao/src/main/java/com/databasir/dao/impl/UserDao.java +++ b/dao/src/main/java/com/databasir/dao/impl/UserDao.java @@ -78,6 +78,13 @@ public class UserDao extends BaseDao { .fetchOptionalInto(UserPojo.class); } + public List selectEnabledGroupMembers(Integer groupId) { + return dslContext.select(USER.fields()).from(USER) + .innerJoin(USER_ROLE).on(USER.ID.eq(USER_ROLE.USER_ID)) + .where(USER_ROLE.GROUP_ID.eq(groupId).and(USER.ENABLED.eq(true))) + .fetchInto(UserPojo.class); + } + public Page selectGroupMembers(Integer groupId, Pageable request, Condition condition) { // total Integer count = dslContext