refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion. - Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects. - Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management. - Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering. - Improve database initialization by moving it from `internal/model` to `internal/database`. - Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool. - Enhance error handling and security by implementing fail-fast checks for encryption key length during startup. - Clean up unused code, including the `avatar` package and several unused DTOs.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"with_you/internal/dto"
|
||||
apperrors "with_you/internal/errors"
|
||||
"with_you/internal/model"
|
||||
"with_you/internal/repository"
|
||||
)
|
||||
@@ -291,48 +292,36 @@ func (s *adminGroupServiceImpl) RemoveMember(ctx context.Context, groupID string
|
||||
}
|
||||
|
||||
// TransferOwner 转让群主
|
||||
// 委托 groupRepo.TransferOwner 在单个数据库事务内原子完成:
|
||||
// - 更新 group.owner_id 为新群主
|
||||
// - 原群主角色降级为普通成员
|
||||
// - 新群主角色升级为 owner
|
||||
//
|
||||
// 任何一步失败都会整体回滚,避免出现「两个群主」或「零群主」的数据不一致。
|
||||
func (s *adminGroupServiceImpl) TransferOwner(ctx context.Context, groupID string, newOwnerID string) (*dto.AdminGroupDetailResponse, error) {
|
||||
// 先检查群组是否存在
|
||||
// 校验群组存在
|
||||
group, err := s.groupRepo.GetByID(groupID)
|
||||
if err != nil {
|
||||
return nil, errors.New("群组不存在")
|
||||
return nil, apperrors.ErrGroupNotFound
|
||||
}
|
||||
|
||||
// 检查新群主是否是群成员
|
||||
// 校验新群主是群成员
|
||||
newOwnerMember, err := s.groupRepo.GetMember(groupID, newOwnerID)
|
||||
if err != nil {
|
||||
return nil, errors.New("新群主不是群组成员")
|
||||
return nil, apperrors.ErrNotGroupMember
|
||||
}
|
||||
// 新群主已是群主则无需转让
|
||||
if newOwnerMember.Role == model.GroupRoleOwner {
|
||||
return nil, apperrors.ErrInvalidOperation
|
||||
}
|
||||
|
||||
// 获取当前群主信息
|
||||
currentOwnerMember, err := s.groupRepo.GetMember(groupID, group.OwnerID)
|
||||
if err != nil {
|
||||
return nil, errors.New("当前群主信息不存在")
|
||||
// 校验当前群主信息存在
|
||||
if _, err := s.groupRepo.GetMember(groupID, group.OwnerID); err != nil {
|
||||
return nil, apperrors.ErrGroupNotFound
|
||||
}
|
||||
|
||||
oldOwnerID := group.OwnerID
|
||||
|
||||
// 更新当前群主为普通成员
|
||||
err = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 更新新群主角色
|
||||
err = s.groupRepo.SetMemberRole(groupID, newOwnerID, model.GroupRoleOwner)
|
||||
if err != nil {
|
||||
// 回滚
|
||||
_ = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleOwner)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 更新群组的OwnerID
|
||||
group.OwnerID = newOwnerID
|
||||
err = s.groupRepo.Update(group)
|
||||
if err != nil {
|
||||
// 回滚
|
||||
_ = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleOwner)
|
||||
_ = s.groupRepo.SetMemberRole(groupID, newOwnerID, newOwnerMember.Role)
|
||||
// 原子转让:所有写入在 groupRepo.TransferOwner 的单个事务内完成
|
||||
if err := s.groupRepo.TransferOwner(groupID, group.OwnerID, newOwnerID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -373,7 +362,5 @@ func (s *adminGroupServiceImpl) TransferOwner(ctx context.Context, groupID strin
|
||||
}
|
||||
}
|
||||
|
||||
_ = currentOwnerMember // 避免 unused variable 警告
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user