add user role
This commit is contained in:
@@ -26,7 +26,7 @@ type cacheEntry struct {
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func NewCachedUserProcessor(userRepo *repository.UserRepositoryImpl, profileRepo *repository.UserProfileRepository) *CachedUserProcessor {
|
||||
func NewCachedUserProcessor(userRepo *repository.UserRepositoryImpl, profileRepo *repository.UserProfileRepository, userRoleProc UserRoleProcessor) *CachedUserProcessor {
|
||||
return &CachedUserProcessor{
|
||||
userRepo: userRepo,
|
||||
profileRepo: profileRepo,
|
||||
|
||||
@@ -2,6 +2,8 @@ package processor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"eslogad-be/internal/appcontext"
|
||||
"time"
|
||||
|
||||
"eslogad-be/internal/entities"
|
||||
"eslogad-be/internal/repository"
|
||||
@@ -50,40 +52,52 @@ func (p *RecipientProcessorImpl) CreateDefaultRecipients(ctx context.Context, le
|
||||
}
|
||||
|
||||
func (p *RecipientProcessorImpl) CreateRecipients(ctx context.Context, letterID uuid.UUID, departmentIDs []uuid.UUID) ([]entities.LetterIncomingRecipient, error) {
|
||||
if len(departmentIDs) == 0 {
|
||||
return []entities.LetterIncomingRecipient{}, nil
|
||||
}
|
||||
userCreatorDepartment := appcontext.FromGinContext(ctx).DepartmentID
|
||||
departmentIDs = append(departmentIDs, userCreatorDepartment)
|
||||
|
||||
userMemberships, err := p.userDeptRepo.ListActiveByDepartmentIDs(ctx, departmentIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recipients := p.buildUniqueRecipients(letterID, userMemberships)
|
||||
recipients := p.buildUniqueRecipients(letterID, userMemberships, userCreatorDepartment)
|
||||
|
||||
if len(recipients) > 0 {
|
||||
if err := p.recipientRepo.CreateBulk(ctx, recipients); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.recipientRepo.CreateBulk(ctx, recipients); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return recipients, nil
|
||||
}
|
||||
|
||||
func (p *RecipientProcessorImpl) buildUniqueRecipients(letterID uuid.UUID, userMemberships []repository.UserDepartmentRow) []entities.LetterIncomingRecipient {
|
||||
func (p *RecipientProcessorImpl) buildUniqueRecipients(letterID uuid.UUID, userMemberships []repository.UserDepartmentRow, userCreatorDepartment uuid.UUID) []entities.LetterIncomingRecipient {
|
||||
var recipients []entities.LetterIncomingRecipient
|
||||
userMap := make(map[string]bool)
|
||||
now := time.Now()
|
||||
|
||||
for _, membership := range userMemberships {
|
||||
userIDStr := membership.UserID.String()
|
||||
|
||||
if !userMap[userIDStr] {
|
||||
recipients = append(recipients, entities.LetterIncomingRecipient{
|
||||
LetterID: letterID,
|
||||
RecipientUserID: &membership.UserID,
|
||||
RecipientDepartmentID: &membership.DepartmentID,
|
||||
Status: entities.RecipientStatusNew,
|
||||
})
|
||||
userID := membership.UserID
|
||||
departmentID := membership.DepartmentID
|
||||
|
||||
if userCreatorDepartment == membership.DepartmentID {
|
||||
recipients = append(recipients, entities.LetterIncomingRecipient{
|
||||
LetterID: letterID,
|
||||
RecipientUserID: &userID,
|
||||
RecipientDepartmentID: &departmentID,
|
||||
Status: entities.RecipientStatusCompleted,
|
||||
ReadAt: &now,
|
||||
CompletedAt: &now,
|
||||
})
|
||||
} else {
|
||||
recipients = append(recipients, entities.LetterIncomingRecipient{
|
||||
LetterID: letterID,
|
||||
RecipientUserID: &userID,
|
||||
RecipientDepartmentID: &departmentID,
|
||||
Status: entities.RecipientStatusNew,
|
||||
})
|
||||
}
|
||||
userMap[userIDStr] = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ type UserProcessorImpl struct {
|
||||
userRepo UserRepository
|
||||
profileRepo UserProfileRepository
|
||||
novuProcessor NovuProcessor
|
||||
userRoleProc UserRoleProcessor
|
||||
}
|
||||
|
||||
type UserProfileRepository interface {
|
||||
@@ -29,10 +30,12 @@ type UserProfileRepository interface {
|
||||
func NewUserProcessor(
|
||||
userRepo UserRepository,
|
||||
profileRepo UserProfileRepository,
|
||||
userRoleProc UserRoleProcessor,
|
||||
) *UserProcessorImpl {
|
||||
return &UserProcessorImpl{
|
||||
userRepo: userRepo,
|
||||
profileRepo: profileRepo,
|
||||
userRepo: userRepo,
|
||||
profileRepo: profileRepo,
|
||||
userRoleProc: userRoleProc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +61,6 @@ func (p *UserProcessorImpl) CreateUser(ctx context.Context, req *contract.Create
|
||||
return nil, fmt.Errorf("failed to create user: %w", err)
|
||||
}
|
||||
|
||||
// create default user profile
|
||||
defaultFullName := userEntity.Name
|
||||
profile := &entities.UserProfile{
|
||||
UserID: userEntity.ID,
|
||||
@@ -70,11 +72,14 @@ func (p *UserProcessorImpl) CreateUser(ctx context.Context, req *contract.Create
|
||||
}
|
||||
_ = p.profileRepo.Create(ctx, profile)
|
||||
|
||||
// Create Novu subscriber
|
||||
if req.RoleID != nil {
|
||||
if err := p.userRoleProc.AssignRoleToUser(ctx, userEntity.ID, *req.RoleID); err != nil {
|
||||
return nil, fmt.Errorf("failed to assign role to user: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if p.novuProcessor != nil {
|
||||
if err := p.novuProcessor.CreateSubscriber(ctx, userEntity); err != nil {
|
||||
// Log error but don't fail user creation
|
||||
// You might want to add proper logging here
|
||||
_ = err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package processor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"eslogad-be/internal/entities"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserRoleProcessor interface {
|
||||
AssignRoleToUser(ctx context.Context, userID, roleID uuid.UUID) error
|
||||
RemoveRoleFromUser(ctx context.Context, userID, roleID uuid.UUID) error
|
||||
GetUserRoles(ctx context.Context, userID uuid.UUID) ([]entities.Role, error)
|
||||
HasRole(ctx context.Context, userID uuid.UUID, roleCode string) (bool, error)
|
||||
}
|
||||
|
||||
type UserRoleProcessorImpl struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserRoleProcessor(db *gorm.DB) *UserRoleProcessorImpl {
|
||||
return &UserRoleProcessorImpl{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
type UserRoleEntry struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()"`
|
||||
UserID uuid.UUID `gorm:"type:uuid;not null"`
|
||||
RoleID uuid.UUID `gorm:"type:uuid;not null"`
|
||||
AssignedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
|
||||
RemovedAt *time.Time
|
||||
}
|
||||
|
||||
func (UserRoleEntry) TableName() string {
|
||||
return "user_role"
|
||||
}
|
||||
|
||||
func (p *UserRoleProcessorImpl) AssignRoleToUser(ctx context.Context, userID, roleID uuid.UUID) error {
|
||||
var existingEntry UserRoleEntry
|
||||
err := p.db.WithContext(ctx).
|
||||
Where("user_id = ? AND role_id = ? AND removed_at IS NULL", userID, roleID).
|
||||
First(&existingEntry).Error
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
|
||||
newEntry := UserRoleEntry{
|
||||
UserID: userID,
|
||||
RoleID: roleID,
|
||||
AssignedAt: time.Now(),
|
||||
}
|
||||
|
||||
return p.db.WithContext(ctx).Create(&newEntry).Error
|
||||
}
|
||||
|
||||
func (p *UserRoleProcessorImpl) RemoveRoleFromUser(ctx context.Context, userID, roleID uuid.UUID) error {
|
||||
now := time.Now()
|
||||
return p.db.WithContext(ctx).
|
||||
Model(&UserRoleEntry{}).
|
||||
Where("user_id = ? AND role_id = ? AND removed_at IS NULL", userID, roleID).
|
||||
Update("removed_at", now).Error
|
||||
}
|
||||
|
||||
func (p *UserRoleProcessorImpl) GetUserRoles(ctx context.Context, userID uuid.UUID) ([]entities.Role, error) {
|
||||
var roles []entities.Role
|
||||
err := p.db.WithContext(ctx).
|
||||
Table("roles as r").
|
||||
Select("r.*").
|
||||
Joins("JOIN user_role ur ON ur.role_id = r.id AND ur.removed_at IS NULL").
|
||||
Where("ur.user_id = ?", userID).
|
||||
Find(&roles).Error
|
||||
return roles, err
|
||||
}
|
||||
|
||||
func (p *UserRoleProcessorImpl) HasRole(ctx context.Context, userID uuid.UUID, roleCode string) (bool, error) {
|
||||
var count int64
|
||||
err := p.db.WithContext(ctx).
|
||||
Table("user_role as ur").
|
||||
Joins("JOIN roles r ON r.id = ur.role_id").
|
||||
Where("ur.user_id = ? AND r.code = ? AND ur.removed_at IS NULL", userID, roleCode).
|
||||
Count(&count).Error
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
Reference in New Issue
Block a user