mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-07 08:06:37 +08:00
refactor(architecture): eliminate internal package and complete cordis single-owner model and repository migration
- Physically purged all legacy internal/ packages, centralized pkg/model/ and pkg/repository/ - Migrated domain models and database repositories into self-contained owner plugins (user, auth, message_gateway, admin, upload, risk_control) - Decoupled cross-plugin interactions via pure core/contracts and typed EventBus - Ensured 100% test coverage pass, zero data races (-race clean), and 0 lint issues in make code-check
This commit is contained in:
@@ -1,20 +1,24 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package user provides user profiles, credentials, role management, and access token domain services.
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/core/contracts"
|
||||
"github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
"github.com/Rain-kl/Wavelet/internal/infra/persistence/idgen"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
db "github.com/Rain-kl/Wavelet/pkg/persistence"
|
||||
"github.com/Rain-kl/Wavelet/pkg/persistence/idgen"
|
||||
|
||||
pkgu "github.com/Rain-kl/Wavelet/pkg/util"
|
||||
)
|
||||
|
||||
func toUserDTO(u *model.User) *contracts.UserDTO {
|
||||
func toUserDTO(u *User) *contracts.UserDTO {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -44,23 +48,23 @@ func newUserService() contracts.UserService {
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) GetUserByID(ctx context.Context, id uint64) (*contracts.UserDTO, error) {
|
||||
u, err := repository.GetUserByID(ctx, id)
|
||||
u, err := GetUserByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toUserDTO(&u), nil
|
||||
return toUserDTO(u), nil
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) GetUserByUsername(ctx context.Context, username string) (*contracts.UserDTO, error) {
|
||||
u, err := repository.GetUserByUsername(ctx, username)
|
||||
u, err := GetUserByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toUserDTO(&u), nil
|
||||
return toUserDTO(u), nil
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) GetUserByEmail(ctx context.Context, email string) (*contracts.UserDTO, error) {
|
||||
var u model.User
|
||||
var u User
|
||||
if err := db.DB(ctx).Where("email = ?", email).First(&u).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -72,7 +76,7 @@ func (s *userServiceImpl) CreateUser(ctx context.Context, req contracts.CreateUs
|
||||
return nil, errors.New("user: username cannot be empty")
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
user := User{
|
||||
ID: idgen.NextUint64ID(),
|
||||
Username: req.Username,
|
||||
Nickname: req.Nickname,
|
||||
@@ -94,7 +98,7 @@ func (s *userServiceImpl) CreateUser(ctx context.Context, req contracts.CreateUs
|
||||
}
|
||||
}
|
||||
|
||||
if err := repository.CreateUser(ctx, &user); err != nil {
|
||||
if err := CreateUser(ctx, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -129,7 +133,7 @@ func (s *userServiceImpl) UpdateProfile(ctx context.Context, id uint64, req cont
|
||||
}
|
||||
updates["updated_at"] = time.Now()
|
||||
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||
if err := db.DB(ctx).Model(&User{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -137,7 +141,7 @@ func (s *userServiceImpl) UpdateProfile(ctx context.Context, id uint64, req cont
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) UpdatePassword(ctx context.Context, id uint64, oldPassword, newPassword string) error {
|
||||
var user model.User
|
||||
var user User
|
||||
if err := db.DB(ctx).Where("id = ?", id).First(&user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -150,7 +154,7 @@ func (s *userServiceImpl) UpdatePassword(ctx context.Context, id uint64, oldPass
|
||||
return err
|
||||
}
|
||||
|
||||
return db.DB(ctx).Model(&model.User{}).Where("id = ?", id).
|
||||
return db.DB(ctx).Model(&User{}).Where("id = ?", id).
|
||||
Updates(map[string]any{
|
||||
"password": user.Password,
|
||||
"updated_at": time.Now(),
|
||||
@@ -158,7 +162,7 @@ func (s *userServiceImpl) UpdatePassword(ctx context.Context, id uint64, oldPass
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) VerifyPassword(ctx context.Context, id uint64, password string) bool {
|
||||
var user model.User
|
||||
var user User
|
||||
if err := db.DB(ctx).Where("id = ?", id).First(&user).Error; err != nil {
|
||||
pkgu.DummyCheckPassword(password)
|
||||
return false
|
||||
@@ -167,7 +171,7 @@ func (s *userServiceImpl) VerifyPassword(ctx context.Context, id uint64, passwor
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) UpdateLastLogin(ctx context.Context, id uint64, _ string) error {
|
||||
return db.DB(ctx).Model(&model.User{}).Where("id = ?", id).
|
||||
return db.DB(ctx).Model(&User{}).Where("id = ?", id).
|
||||
Updates(map[string]any{
|
||||
"last_login_at": time.Now(),
|
||||
"updated_at": time.Now(),
|
||||
@@ -182,13 +186,13 @@ func (s *userServiceImpl) ListUsers(ctx context.Context, page, pageSize int, key
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
filter := repository.AdminUserListFilter{
|
||||
filter := AdminUserListFilter{
|
||||
Username: keyword,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
total, users, err := repository.ListAdminUsers(ctx, filter)
|
||||
total, users, err := ListAdminUsers(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -202,9 +206,77 @@ func (s *userServiceImpl) ListUsers(ctx context.Context, page, pageSize int, key
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) SetUserActive(ctx context.Context, id uint64, active bool) error {
|
||||
return repository.UpdateUserActive(ctx, id, active)
|
||||
return UpdateUserActive(ctx, id, active)
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) SetUserAdmin(ctx context.Context, id uint64, admin bool) error {
|
||||
return db.DB(ctx).Model(&model.User{}).Where("id = ?", id).Update("is_admin", admin).Error
|
||||
return db.DB(ctx).Model(&User{}).Where("id = ?", id).Update("is_admin", admin).Error
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) VerifyAccessToken(ctx context.Context, tokenHash string) (*contracts.UserDTO, bool, error) {
|
||||
tokenRecord, err := GetAccessTokenByHash(ctx, tokenHash)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
user, err := GetActiveUserByID(ctx, tokenRecord.UserID)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return toUserDTO(user), tokenRecord.IsAdmin, nil
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) DeleteUser(ctx context.Context, id uint64) error {
|
||||
return DeleteUserWithRelations(ctx, id)
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) CountUsers(ctx context.Context) (int64, error) {
|
||||
var count int64
|
||||
err := db.DB(ctx).Model(&User{}).Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) CountActiveUsers(ctx context.Context) (int64, error) {
|
||||
var count int64
|
||||
err := db.DB(ctx).Model(&User{}).Where("is_active = ?", true).Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) GetFirstAdminUser(ctx context.Context) (*contracts.UserDTO, error) {
|
||||
u, err := GetFirstAdminUser(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toUserDTO(u), nil
|
||||
}
|
||||
|
||||
func (s *userServiceImpl) UniqueUsername(ctx context.Context, base string) (string, error) {
|
||||
base = strings.TrimSpace(base)
|
||||
if base == "" {
|
||||
base = PluginName
|
||||
}
|
||||
|
||||
existingUsernames, err := ListUsernamesMatchingBase(ctx, base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
exists := make(map[string]bool, len(existingUsernames))
|
||||
for _, u := range existingUsernames {
|
||||
exists[strings.ToLower(u)] = true
|
||||
}
|
||||
|
||||
if !exists[strings.ToLower(base)] {
|
||||
return base, nil
|
||||
}
|
||||
|
||||
for i := 1; i <= 1000; i++ {
|
||||
candidate := fmt.Sprintf("%s-%d", base, i)
|
||||
if !exists[strings.ToLower(candidate)] {
|
||||
return candidate, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("failed to generate unique username")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user