feat: complete production readiness improvements
- Fix DIP violations in service layer (device, stats, auth middleware) - Add ReplaceUserRoles interface method for transaction safety - Implement Magic Bytes validation for avatar uploads - Standardize OAuth error handling with ErrOAuthProviderNotSupported - Use crypto/rand for JWT secret generation instead of weak fixed key - Apply code formatting with gofumpt and goimports - Fix staticcheck issues (S1024, S1008, ST1005) - Add comprehensive quality and functional test reports - Achieve 36.3% test coverage (up from 16.3%) - All E2E, integration, and business logic tests passing
This commit is contained in:
@@ -171,7 +171,7 @@ func (r *DeviceRepository) GetActiveDevices(ctx context.Context, userID int64) (
|
||||
// TrustDevice 设置设备为信任状态
|
||||
func (r *DeviceRepository) TrustDevice(ctx context.Context, deviceID int64, expiresAt *time.Time) error {
|
||||
updates := map[string]interface{}{
|
||||
"is_trusted": true,
|
||||
"is_trusted": true,
|
||||
"trust_expires_at": expiresAt,
|
||||
}
|
||||
return r.db.WithContext(ctx).Model(&domain.Device{}).Where("id = ?", deviceID).Updates(updates).Error
|
||||
@@ -180,7 +180,7 @@ func (r *DeviceRepository) TrustDevice(ctx context.Context, deviceID int64, expi
|
||||
// UntrustDevice 取消设备信任状态
|
||||
func (r *DeviceRepository) UntrustDevice(ctx context.Context, deviceID int64) error {
|
||||
updates := map[string]interface{}{
|
||||
"is_trusted": false,
|
||||
"is_trusted": false,
|
||||
"trust_expires_at": nil,
|
||||
}
|
||||
return r.db.WithContext(ctx).Model(&domain.Device{}).Where("id = ?", deviceID).Updates(updates).Error
|
||||
|
||||
@@ -136,7 +136,6 @@ func (r *PermissionRepository) GetByRoleIDs(ctx context.Context, roleIDs []int64
|
||||
Where("role_permissions.role_id IN ?", roleIDs).
|
||||
Where("permissions.status = ?", domain.PermissionStatusEnabled).
|
||||
Find(&permissions).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -86,11 +86,11 @@ func (r *UserRoleRepository) GetRoleIDsByUserID(ctx context.Context, userID int6
|
||||
// GetUserRolesAndPermissions 获取用户角色和权限(PERF-01 优化:合并为单次 JOIN 查询)
|
||||
func (r *UserRoleRepository) GetUserRolesAndPermissions(ctx context.Context, userID int64) ([]*domain.Role, []*domain.Permission, error) {
|
||||
var results []struct {
|
||||
RoleID int64
|
||||
RoleName string
|
||||
RoleCode string
|
||||
RoleStatus int
|
||||
PermissionID int64
|
||||
RoleID int64
|
||||
RoleName string
|
||||
RoleCode string
|
||||
RoleStatus int
|
||||
PermissionID int64
|
||||
PermissionCode string
|
||||
PermissionName string
|
||||
}
|
||||
@@ -118,9 +118,9 @@ func (r *UserRoleRepository) GetUserRolesAndPermissions(ctx context.Context, use
|
||||
for _, row := range results {
|
||||
if _, ok := roleMap[row.RoleID]; !ok {
|
||||
roleMap[row.RoleID] = &domain.Role{
|
||||
ID: row.RoleID,
|
||||
Name: row.RoleName,
|
||||
Code: row.RoleCode,
|
||||
ID: row.RoleID,
|
||||
Name: row.RoleName,
|
||||
Code: row.RoleCode,
|
||||
Status: domain.RoleStatus(row.RoleStatus),
|
||||
}
|
||||
}
|
||||
@@ -180,11 +180,38 @@ func (r *UserRoleRepository) BatchDelete(ctx context.Context, userRoles []*domai
|
||||
if len(userRoles) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
var ids []int64
|
||||
for _, ur := range userRoles {
|
||||
ids = append(ids, ur.ID)
|
||||
}
|
||||
|
||||
|
||||
return r.db.WithContext(ctx).Delete(&domain.UserRole{}, ids).Error
|
||||
}
|
||||
|
||||
// ReplaceUserRoles replaces all roles for a user in a single transaction
|
||||
// This encapsulates the delete-then-create pattern to ensure atomicity
|
||||
func (r *UserRoleRepository) ReplaceUserRoles(ctx context.Context, userID int64, roleIDs []int64) error {
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// Delete all existing roles for the user
|
||||
if err := tx.Where("user_id = ?", userID).Delete(&domain.UserRole{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create new role associations if any
|
||||
if len(roleIDs) > 0 {
|
||||
userRoles := make([]*domain.UserRole, len(roleIDs))
|
||||
for i, roleID := range roleIDs {
|
||||
userRoles[i] = &domain.UserRole{
|
||||
UserID: userID,
|
||||
RoleID: roleID,
|
||||
}
|
||||
}
|
||||
if err := tx.Create(&userRoles).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user