feat: add user/document/discussion event (#59)
This commit is contained in:
parent
890414deb1
commit
4deebab2cb
|
@ -3,10 +3,10 @@ package com.databasir.api;
|
||||||
import com.databasir.api.config.security.DatabasirUserDetails;
|
import com.databasir.api.config.security.DatabasirUserDetails;
|
||||||
import com.databasir.common.JsonData;
|
import com.databasir.common.JsonData;
|
||||||
import com.databasir.core.domain.log.annotation.Operation;
|
import com.databasir.core.domain.log.annotation.Operation;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionCreateRequest;
|
import com.databasir.core.domain.discussion.data.DiscussionCreateRequest;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionListCondition;
|
import com.databasir.core.domain.discussion.data.DiscussionListCondition;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionResponse;
|
import com.databasir.core.domain.discussion.data.DiscussionResponse;
|
||||||
import com.databasir.core.domain.remark.service.DocumentDiscussionService;
|
import com.databasir.core.domain.discussion.service.DocumentDiscussionService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.databasir.api;
|
package com.databasir.api;
|
||||||
|
|
||||||
|
import com.databasir.api.common.LoginUserContext;
|
||||||
import com.databasir.api.validator.UserOperationValidator;
|
import com.databasir.api.validator.UserOperationValidator;
|
||||||
import com.databasir.common.JsonData;
|
import com.databasir.common.JsonData;
|
||||||
import com.databasir.common.exception.Forbidden;
|
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.log.annotation.Operation;
|
||||||
import com.databasir.core.domain.user.data.*;
|
import com.databasir.core.domain.user.data.*;
|
||||||
import com.databasir.core.domain.user.service.UserService;
|
import com.databasir.core.domain.user.service.UserService;
|
||||||
|
import com.databasir.core.infrastructure.event.EventPublisher;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
@ -27,6 +29,8 @@ public class UserController {
|
||||||
|
|
||||||
private final UserOperationValidator userOperationValidator;
|
private final UserOperationValidator userOperationValidator;
|
||||||
|
|
||||||
|
private final EventPublisher eventPublisher;
|
||||||
|
|
||||||
@GetMapping(Routes.User.LIST)
|
@GetMapping(Routes.User.LIST)
|
||||||
public JsonData<Page<UserPageResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC)
|
public JsonData<Page<UserPageResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC)
|
||||||
Pageable pageable,
|
Pageable pageable,
|
||||||
|
@ -60,7 +64,7 @@ public class UserController {
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER')")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER')")
|
||||||
@Operation(module = Operation.Modules.USER, name = "创建用户")
|
@Operation(module = Operation.Modules.USER, name = "创建用户")
|
||||||
public JsonData<Void> create(@RequestBody @Valid UserCreateRequest request) {
|
public JsonData<Void> create(@RequestBody @Valid UserCreateRequest request) {
|
||||||
userService.create(request);
|
userService.create(request, UserSource.MANUAL);
|
||||||
return JsonData.ok();
|
return JsonData.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +77,8 @@ public class UserController {
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER')")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER')")
|
||||||
@Operation(module = Operation.Modules.USER, name = "重置用户密码", involvedUserId = "#userId")
|
@Operation(module = Operation.Modules.USER, name = "重置用户密码", involvedUserId = "#userId")
|
||||||
public JsonData<Void> renewPassword(@PathVariable Integer userId) {
|
public JsonData<Void> renewPassword(@PathVariable Integer userId) {
|
||||||
userService.renewPassword(userId);
|
Integer operatorUserId = LoginUserContext.getLoginUserId();
|
||||||
|
userService.renewPassword(operatorUserId, userId);
|
||||||
return JsonData.ok();
|
return JsonData.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ public class OpenAuthAppService {
|
||||||
user.setAvatar(result.getAvatar());
|
user.setAvatar(result.getAvatar());
|
||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
user.setPassword(UUID.randomUUID().toString().substring(0, 6));
|
user.setPassword(UUID.randomUUID().toString().substring(0, 6));
|
||||||
Integer id = userService.create(user);
|
Integer id = userService.create(user, registrationId);
|
||||||
return userService.get(id);
|
return userService.get(id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.DocumentDiscussionPojo;
|
||||||
import com.databasir.dao.tables.pojos.UserPojo;
|
import com.databasir.dao.tables.pojos.UserPojo;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.databasir.core.domain.remark.data;
|
package com.databasir.core.domain.discussion.data;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.databasir.core.domain.remark.data;
|
package com.databasir.core.domain.discussion.data;
|
||||||
|
|
||||||
import com.databasir.dao.Tables;
|
import com.databasir.dao.Tables;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.databasir.core.domain.remark.data;
|
package com.databasir.core.domain.discussion.data;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -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<String> getColumnName() {
|
||||||
|
return Optional.of(columnName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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.common.exception.Forbidden;
|
||||||
import com.databasir.core.domain.remark.converter.DiscussionResponseConverter;
|
import com.databasir.core.domain.discussion.converter.DiscussionResponseConverter;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionCreateRequest;
|
import com.databasir.core.domain.discussion.data.DiscussionCreateRequest;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionListCondition;
|
import com.databasir.core.domain.discussion.data.DiscussionListCondition;
|
||||||
import com.databasir.core.domain.remark.data.DiscussionResponse;
|
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.DocumentDiscussionDao;
|
||||||
import com.databasir.dao.impl.ProjectDao;
|
import com.databasir.dao.impl.ProjectDao;
|
||||||
import com.databasir.dao.impl.UserDao;
|
import com.databasir.dao.impl.UserDao;
|
||||||
|
@ -32,6 +35,10 @@ public class DocumentDiscussionService {
|
||||||
|
|
||||||
private final DiscussionResponseConverter discussionResponseConverter;
|
private final DiscussionResponseConverter discussionResponseConverter;
|
||||||
|
|
||||||
|
private final DiscussionEventConverter discussionEventConverter;
|
||||||
|
|
||||||
|
private final EventPublisher eventPublisher;
|
||||||
|
|
||||||
public void deleteById(Integer groupId,
|
public void deleteById(Integer groupId,
|
||||||
Integer projectId,
|
Integer projectId,
|
||||||
Integer discussionId) {
|
Integer discussionId) {
|
||||||
|
@ -57,9 +64,9 @@ public class DocumentDiscussionService {
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(UserPojo::getId, Function.identity()));
|
.collect(Collectors.toMap(UserPojo::getId, Function.identity()));
|
||||||
return data
|
return data
|
||||||
.map(dicussionPojo -> {
|
.map(discussionPojo -> {
|
||||||
UserPojo userPojo = userMapById.get(dicussionPojo.getUserId());
|
UserPojo userPojo = userMapById.get(discussionPojo.getUserId());
|
||||||
return discussionResponseConverter.of(dicussionPojo, userPojo);
|
return discussionResponseConverter.of(discussionPojo, userPojo);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Forbidden();
|
throw new Forbidden();
|
||||||
|
@ -74,7 +81,9 @@ public class DocumentDiscussionService {
|
||||||
pojo.setContent(request.getContent());
|
pojo.setContent(request.getContent());
|
||||||
pojo.setTableName(request.getTableName());
|
pojo.setTableName(request.getTableName());
|
||||||
pojo.setColumnName(request.getColumnName());
|
pojo.setColumnName(request.getColumnName());
|
||||||
documentDiscussionDao.insertAndReturnId(pojo);
|
Integer discussionId = documentDiscussionDao.insertAndReturnId(pojo);
|
||||||
|
DiscussionCreated event = discussionEventConverter.of(pojo, discussionId);
|
||||||
|
eventPublisher.publish(event);
|
||||||
} else {
|
} else {
|
||||||
throw new Forbidden();
|
throw new Forbidden();
|
||||||
}
|
}
|
|
@ -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<Long> getOldVersion() {
|
||||||
|
return Optional.ofNullable(oldVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<RootDiff> getDiff() {
|
||||||
|
return Optional.ofNullable(diff);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.DatabaseDocumentSimpleResponse;
|
||||||
import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
|
import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
|
||||||
import com.databasir.core.domain.document.data.TableDocumentResponse;
|
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.DocumentFileGenerator;
|
||||||
import com.databasir.core.domain.document.generator.DocumentFileType;
|
import com.databasir.core.domain.document.generator.DocumentFileType;
|
||||||
import com.databasir.core.infrastructure.connection.DatabaseConnectionService;
|
import com.databasir.core.infrastructure.connection.DatabaseConnectionService;
|
||||||
import com.databasir.core.infrastructure.converter.JsonConverter;
|
import com.databasir.core.infrastructure.converter.JsonConverter;
|
||||||
|
import com.databasir.core.infrastructure.event.EventPublisher;
|
||||||
import com.databasir.core.meta.data.DatabaseMeta;
|
import com.databasir.core.meta.data.DatabaseMeta;
|
||||||
import com.databasir.dao.impl.*;
|
import com.databasir.dao.impl.*;
|
||||||
import com.databasir.dao.tables.pojos.*;
|
import com.databasir.dao.tables.pojos.*;
|
||||||
|
@ -84,6 +86,8 @@ public class DocumentService {
|
||||||
|
|
||||||
private final List<DocumentFileGenerator> documentFileGenerators;
|
private final List<DocumentFileGenerator> documentFileGenerators;
|
||||||
|
|
||||||
|
private final EventPublisher eventPublisher;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void syncByProjectId(Integer projectId) {
|
public void syncByProjectId(Integer projectId) {
|
||||||
projectDao.selectOptionalById(projectId)
|
projectDao.selectOptionalById(projectId)
|
||||||
|
@ -103,9 +107,12 @@ public class DocumentService {
|
||||||
Integer previousDocumentId = original.getId();
|
Integer previousDocumentId = original.getId();
|
||||||
// archive old version
|
// archive old version
|
||||||
databaseDocumentDao.updateIsArchiveById(previousDocumentId, true);
|
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 {
|
} else {
|
||||||
saveNewDocument(current, 1L, projectId);
|
saveNewDocument(current, 1L, projectId);
|
||||||
|
eventPublisher.publish(new DocumentUpdated(null, 1L, null, projectId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,5 @@ public class UserCreateRequest {
|
||||||
@NotNull
|
@NotNull
|
||||||
private Boolean enabled;
|
private Boolean enabled;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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.UserPojoConverter;
|
||||||
import com.databasir.core.domain.user.converter.UserResponseConverter;
|
import com.databasir.core.domain.user.converter.UserResponseConverter;
|
||||||
import com.databasir.core.domain.user.data.*;
|
import com.databasir.core.domain.user.data.*;
|
||||||
import com.databasir.core.infrastructure.mail.MailSender;
|
import com.databasir.core.domain.user.event.UserCreated;
|
||||||
import com.databasir.dao.impl.*;
|
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.GroupPojo;
|
||||||
import com.databasir.dao.tables.pojos.UserPojo;
|
import com.databasir.dao.tables.pojos.UserPojo;
|
||||||
import com.databasir.dao.tables.pojos.UserRolePojo;
|
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.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.*;
|
import static java.util.stream.Collectors.*;
|
||||||
|
@ -31,15 +38,15 @@ public class UserService {
|
||||||
|
|
||||||
private final GroupDao groupDao;
|
private final GroupDao groupDao;
|
||||||
|
|
||||||
private final SysMailDao sysMailDao;
|
|
||||||
|
|
||||||
private final LoginDao loginDao;
|
private final LoginDao loginDao;
|
||||||
|
|
||||||
private final UserPojoConverter userPojoConverter;
|
private final UserPojoConverter userPojoConverter;
|
||||||
|
|
||||||
private final UserResponseConverter userResponseConverter;
|
private final UserResponseConverter userResponseConverter;
|
||||||
|
|
||||||
private final MailSender mailSender;
|
private final UserEventConverter userEventConverter;
|
||||||
|
|
||||||
|
private final EventPublisher eventPublisher;
|
||||||
|
|
||||||
@SuppressWarnings("checkstyle:all")
|
@SuppressWarnings("checkstyle:all")
|
||||||
private BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
|
private BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
|
||||||
|
@ -64,14 +71,18 @@ public class UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public Integer create(UserCreateRequest userCreateRequest) {
|
public Integer create(UserCreateRequest userCreateRequest, String source) {
|
||||||
userDao.selectByEmailOrUsername(userCreateRequest.getUsername()).ifPresent(data -> {
|
userDao.selectByEmailOrUsername(userCreateRequest.getUsername()).ifPresent(data -> {
|
||||||
throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception();
|
throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception();
|
||||||
});
|
});
|
||||||
String hashedPassword = bCryptPasswordEncoder.encode(userCreateRequest.getPassword());
|
String hashedPassword = bCryptPasswordEncoder.encode(userCreateRequest.getPassword());
|
||||||
UserPojo pojo = userPojoConverter.of(userCreateRequest, hashedPassword);
|
UserPojo pojo = userPojoConverter.of(userCreateRequest, hashedPassword);
|
||||||
try {
|
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) {
|
} catch (DuplicateKeyException e) {
|
||||||
throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception();
|
throw DomainErrors.USERNAME_OR_EMAIL_DUPLICATE.exception();
|
||||||
}
|
}
|
||||||
|
@ -106,19 +117,20 @@ public class UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public String renewPassword(Integer userId) {
|
public String renewPassword(Integer renewByUserId, Integer userId) {
|
||||||
UserPojo userPojo = userDao.selectById(userId);
|
UserPojo pojo = userDao.selectById(userId);
|
||||||
String randomPassword = UUID.randomUUID().toString()
|
String randomPassword = UUID.randomUUID().toString()
|
||||||
.replace("-", "")
|
.replace("-", "")
|
||||||
.substring(0, 8);
|
.substring(0, 8);
|
||||||
String hashedPassword = bCryptPasswordEncoder.encode(randomPassword);
|
String hashedPassword = bCryptPasswordEncoder.encode(randomPassword);
|
||||||
userDao.updatePassword(userId, hashedPassword);
|
userDao.updatePassword(userId, hashedPassword);
|
||||||
sysMailDao.selectOptionTopOne()
|
|
||||||
.ifPresent(mailPojo -> {
|
// publish event
|
||||||
String subject = "Databasir 密码重置提醒";
|
UserPasswordRenewed event = userEventConverter.userPasswordRenewed(pojo,
|
||||||
String message = "您的密码已被重置,新密码为:" + randomPassword;
|
renewByUserId,
|
||||||
mailSender.send(mailPojo, userPojo.getEmail(), subject, message);
|
LocalDateTime.now(),
|
||||||
});
|
randomPassword);
|
||||||
|
eventPublisher.publish(event);
|
||||||
return randomPassword;
|
return randomPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,21 +7,26 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MailSender {
|
public class MailSender {
|
||||||
|
|
||||||
public void send(SysMailPojo mail, String to, String subject, String content) {
|
public void batchSend(SysMailPojo mail, Collection<String> to, String subject, String content) {
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
message.setFrom(mail.getUsername());
|
message.setFrom(mail.getUsername());
|
||||||
message.setTo(to);
|
message.setTo(to.toArray(new String[0]));
|
||||||
message.setSubject(subject);
|
message.setSubject(subject);
|
||||||
message.setText(content);
|
message.setText(content);
|
||||||
|
|
||||||
JavaMailSender sender = initJavaMailSender(mail);
|
JavaMailSender sender = initJavaMailSender(mail);
|
||||||
sender.send(message);
|
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) {
|
private JavaMailSender initJavaMailSender(SysMailPojo properties) {
|
||||||
JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
||||||
sender.setHost(properties.getSmtpHost());
|
sender.setHost(properties.getSmtpHost());
|
||||||
|
|
|
@ -78,6 +78,13 @@ public class UserDao extends BaseDao<UserPojo> {
|
||||||
.fetchOptionalInto(UserPojo.class);
|
.fetchOptionalInto(UserPojo.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<UserPojo> 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<GroupMemberDetailPojo> selectGroupMembers(Integer groupId, Pageable request, Condition condition) {
|
public Page<GroupMemberDetailPojo> selectGroupMembers(Integer groupId, Pageable request, Condition condition) {
|
||||||
// total
|
// total
|
||||||
Integer count = dslContext
|
Integer count = dslContext
|
||||||
|
|
Loading…
Reference in New Issue