235 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package user
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"time"
 | |
| 
 | |
| 	"management/internal/erpserver/model/dto"
 | |
| 	"management/internal/erpserver/model/system"
 | |
| 	"management/internal/erpserver/repository"
 | |
| 	"management/internal/pkg/crypto"
 | |
| 	"management/internal/pkg/rand"
 | |
| 	"management/internal/pkg/sqldb"
 | |
| 
 | |
| 	"github.com/drhin/logger"
 | |
| 	"github.com/google/uuid"
 | |
| )
 | |
| 
 | |
| type store struct {
 | |
| 	db  *repository.Store
 | |
| 	log *logger.Logger
 | |
| }
 | |
| 
 | |
| func NewStore(db *repository.Store, log *logger.Logger) system.UserRepository {
 | |
| 	return &store{
 | |
| 		db:  db,
 | |
| 		log: log,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *store) Initialize(ctx context.Context, departId, roleId int32) error {
 | |
| 	count, err := s.Count(ctx, dto.SearchDto{})
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if count == 0 {
 | |
| 		salt, err := rand.String(10)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		password := "secret"
 | |
| 		hashedPassword, err := crypto.BcryptHashPassword(password + salt)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		initTime, err := time.ParseInLocation(time.DateTime, "0001-01-01 00:00:00", time.Local)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		user := system.User{
 | |
| 			Uuid:             uuid.Must(uuid.NewV7()),
 | |
| 			Email:            "1185230223@qq.com",
 | |
| 			Username:         "kenneth",
 | |
| 			HashedPassword:   hashedPassword,
 | |
| 			Salt:             salt,
 | |
| 			Avatar:           "/assets/admin/images/avatar.jpg",
 | |
| 			Gender:           1,
 | |
| 			DepartmentID:     departId,
 | |
| 			RoleID:           roleId,
 | |
| 			Status:           0,
 | |
| 			ChangePasswordAt: initTime,
 | |
| 			CreatedAt:        time.Now(),
 | |
| 			UpdatedAt:        time.Now(),
 | |
| 		}
 | |
| 		return s.Create(ctx, &user)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (s *store) Create(ctx context.Context, obj *system.User) error {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	INSERT INTO sys_user (
 | |
| 		uuid, email, username, hashed_password, salt, avatar, gender, department_id, role_id, status
 | |
| 	) VALUES (
 | |
| 		:uuid, :email, :username, :hashed_password, :salt, :avatar, :gender, :department_id, :role_id, :status    
 | |
| 	);`
 | |
| 
 | |
| 	return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
 | |
| }
 | |
| 
 | |
| func (s *store) Update(ctx context.Context, obj *system.User) error {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	UPDATE sys_user
 | |
| 	SET email = :email,
 | |
| 		username = :username,
 | |
| 		hashed_password = :hashed_password,
 | |
| 		avatar = :avatar,
 | |
| 		gender = :gender,
 | |
| 		department_id = :department_id,
 | |
| 		role_id = :role_id,
 | |
| 		status = :status,
 | |
| 		change_password_at = :change_password_at,
 | |
| 		updated_at = :updated_at
 | |
| 	WHERE id = :id;`
 | |
| 
 | |
| 	return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
 | |
| }
 | |
| 
 | |
| func (s *store) Get(ctx context.Context, id int32) (*system.User, error) {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	SELECT
 | |
| 		id, uuid, email, username, hashed_password, salt, avatar, gender, department_id, 
 | |
|     	role_id, status, change_password_at, created_at, updated_at
 | |
| 	FROM 
 | |
| 		sys_user
 | |
| 	WHERE 
 | |
| 		id = :id;`
 | |
| 
 | |
| 	data := map[string]any{
 | |
| 		"id": id,
 | |
| 	}
 | |
| 
 | |
| 	var user system.User
 | |
| 	err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &user)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("select id user: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return &user, nil
 | |
| }
 | |
| 
 | |
| func (s *store) GetByEmail(ctx context.Context, email string) (*system.User, error) {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	SELECT
 | |
| 		id, uuid, email, username, hashed_password, salt, avatar, gender, department_id, 
 | |
|     	role_id, status, change_password_at, created_at, updated_at
 | |
| 	FROM 
 | |
| 		sys_user
 | |
| 	WHERE 
 | |
| 		email = :email;`
 | |
| 
 | |
| 	data := map[string]any{
 | |
| 		"email": email,
 | |
| 	}
 | |
| 
 | |
| 	var user system.User
 | |
| 	err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &user)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("select email user: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return &user, nil
 | |
| }
 | |
| 
 | |
| func (s *store) All(ctx context.Context) ([]*system.User, error) {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	SELECT
 | |
| 		id, uuid, email, username, hashed_password, salt, avatar, gender, department_id, 
 | |
|     	role_id, status, change_password_at, created_at, updated_at
 | |
| 	FROM 
 | |
| 		sys_user;`
 | |
| 
 | |
| 	data := map[string]any{}
 | |
| 
 | |
| 	var users []system.User
 | |
| 	err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &users)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("select all role: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return toPointer(users), nil
 | |
| }
 | |
| 
 | |
| func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	SELECT 
 | |
| 		COUNT(1)
 | |
| 	FROM 
 | |
| 		sys_user`
 | |
| 
 | |
| 	data := map[string]any{}
 | |
| 
 | |
| 	buf := bytes.NewBufferString(q)
 | |
| 	applyFilter(filter, data, buf)
 | |
| 
 | |
| 	var count struct {
 | |
| 		Count int64 `db:"count"`
 | |
| 	}
 | |
| 
 | |
| 	err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
 | |
| 	if err != nil {
 | |
| 		return 0, fmt.Errorf("select count user: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return count.Count, nil
 | |
| }
 | |
| 
 | |
| func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.User, error) {
 | |
| 	//goland:noinspection ALL
 | |
| 	const q = `
 | |
| 	SELECT
 | |
| 		id, uuid, email, username, hashed_password, salt, avatar, gender, department_id, 
 | |
|     	role_id, status, change_password_at, created_at, updated_at
 | |
| 	FROM 
 | |
| 		sys_user`
 | |
| 
 | |
| 	data := map[string]any{
 | |
| 		"offset":        (filter.Page - 1) * filter.Rows,
 | |
| 		"rows_per_page": filter.Rows,
 | |
| 	}
 | |
| 
 | |
| 	buf := bytes.NewBufferString(q)
 | |
| 	applyFilter(filter, data, buf)
 | |
| 
 | |
| 	buf.WriteString(" ORDER BY id DESC")
 | |
| 	buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
 | |
| 
 | |
| 	var users []system.User
 | |
| 	err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &users)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return toPointer(users), nil
 | |
| }
 | |
| 
 | |
| func toPointer(data []system.User) []*system.User {
 | |
| 	var res []*system.User
 | |
| 	for _, v := range data {
 | |
| 		res = append(res, &v)
 | |
| 	}
 | |
| 	return res
 | |
| }
 |