mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
refactor: replace raw SQL with repository interfaces in entranceserver and API server
Extract all direct database calls from entranceserver (2 calls) and API server (17 calls) into typed repository interfaces with PostgreSQL implementations, matching the pattern established in signserver and channelserver. Entranceserver: EntranceServerRepo, EntranceSessionRepo API server: APIUserRepo, APICharacterRepo, APISessionRepo Also fix the 3 remaining fmt.Sprintf calls inside logger invocations in handlers_commands.go and handlers_stage.go, replacing them with structured zap fields. Unskip 5 TestNewAuthData* tests that previously required a real database — they now run with mock repos.
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"erupe-ce/common/token"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -11,41 +12,25 @@ import (
|
||||
)
|
||||
|
||||
func (s *APIServer) createNewUser(ctx context.Context, username string, password string) (uint32, uint32, error) {
|
||||
// Create salted hash of user password
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
var (
|
||||
id uint32
|
||||
rights uint32
|
||||
)
|
||||
err = s.db.QueryRowContext(
|
||||
ctx, `
|
||||
INSERT INTO users (username, password, return_expires)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, rights
|
||||
`,
|
||||
username, string(passwordHash), time.Now().Add(time.Hour*24*30),
|
||||
).Scan(&id, &rights)
|
||||
return id, rights, err
|
||||
return s.userRepo.Register(ctx, username, string(passwordHash), time.Now().Add(time.Hour*24*30))
|
||||
}
|
||||
|
||||
func (s *APIServer) createLoginToken(ctx context.Context, uid uint32) (uint32, string, error) {
|
||||
loginToken := token.Generate(16)
|
||||
var tid uint32
|
||||
err := s.db.QueryRowContext(ctx, "INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id", uid, loginToken).Scan(&tid)
|
||||
tid, err := s.sessionRepo.CreateToken(ctx, uid, loginToken)
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
return tid, loginToken, nil
|
||||
}
|
||||
|
||||
func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32, error) {
|
||||
var userID uint32
|
||||
err := s.db.QueryRowContext(ctx, "SELECT user_id FROM sign_sessions WHERE token = $1", token).Scan(&userID)
|
||||
if err == sql.ErrNoRows {
|
||||
func (s *APIServer) userIDFromToken(ctx context.Context, tkn string) (uint32, error) {
|
||||
userID, err := s.sessionRepo.GetUserIDByToken(ctx, tkn)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, fmt.Errorf("invalid login token")
|
||||
} else if err != nil {
|
||||
return 0, err
|
||||
@@ -54,82 +39,50 @@ func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32,
|
||||
}
|
||||
|
||||
func (s *APIServer) createCharacter(ctx context.Context, userID uint32) (Character, error) {
|
||||
var character Character
|
||||
err := s.db.GetContext(ctx, &character,
|
||||
"SELECT id, name, is_female, weapon_type, hr, gr, last_login FROM characters WHERE is_new_character = true AND user_id = $1 LIMIT 1",
|
||||
userID,
|
||||
)
|
||||
if err == sql.ErrNoRows {
|
||||
var count int
|
||||
_ = s.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM characters WHERE user_id = $1", userID).Scan(&count)
|
||||
character, err := s.charRepo.GetNewCharacter(ctx, userID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
count, _ := s.charRepo.CountForUser(ctx, userID)
|
||||
if count >= 16 {
|
||||
return character, fmt.Errorf("cannot have more than 16 characters")
|
||||
}
|
||||
err = s.db.GetContext(ctx, &character, `
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hr, gr, weapon_type, last_login
|
||||
)
|
||||
VALUES ($1, false, true, '', '', 0, 0, 0, $2)
|
||||
RETURNING id, name, is_female, weapon_type, hr, gr, last_login`,
|
||||
userID, uint32(time.Now().Unix()),
|
||||
)
|
||||
character, err = s.charRepo.Create(ctx, userID, uint32(time.Now().Unix()))
|
||||
}
|
||||
return character, err
|
||||
}
|
||||
|
||||
func (s *APIServer) deleteCharacter(ctx context.Context, userID uint32, charID uint32) error {
|
||||
var isNew bool
|
||||
err := s.db.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", charID).Scan(&isNew)
|
||||
func (s *APIServer) deleteCharacter(_ context.Context, _ uint32, charID uint32) error {
|
||||
isNew, err := s.charRepo.IsNew(charID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isNew {
|
||||
_, err = s.db.Exec("DELETE FROM characters WHERE id = $1", charID)
|
||||
} else {
|
||||
_, err = s.db.Exec("UPDATE characters SET deleted = true WHERE id = $1", charID)
|
||||
return s.charRepo.HardDelete(charID)
|
||||
}
|
||||
return err
|
||||
return s.charRepo.SoftDelete(charID)
|
||||
}
|
||||
|
||||
func (s *APIServer) getCharactersForUser(ctx context.Context, uid uint32) ([]Character, error) {
|
||||
var characters []Character
|
||||
err := s.db.SelectContext(
|
||||
ctx, &characters, `
|
||||
SELECT id, name, is_female, weapon_type, hr, gr, last_login
|
||||
FROM characters
|
||||
WHERE user_id = $1 AND deleted = false AND is_new_character = false ORDER BY id ASC`,
|
||||
uid,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return characters, nil
|
||||
return s.charRepo.GetForUser(ctx, uid)
|
||||
}
|
||||
|
||||
func (s *APIServer) getReturnExpiry(uid uint32) time.Time {
|
||||
var returnExpiry, lastLogin time.Time
|
||||
_ = s.db.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid)
|
||||
lastLogin, _ := s.userRepo.GetLastLogin(uid)
|
||||
var returnExpiry time.Time
|
||||
if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) {
|
||||
returnExpiry = time.Now().Add(time.Hour * 24 * 30)
|
||||
_, _ = s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
_ = s.userRepo.UpdateReturnExpiry(uid, returnExpiry)
|
||||
} else {
|
||||
err := s.db.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid)
|
||||
var err error
|
||||
returnExpiry, err = s.userRepo.GetReturnExpiry(uid)
|
||||
if err != nil {
|
||||
returnExpiry = time.Now()
|
||||
_, _ = s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
_ = s.userRepo.UpdateReturnExpiry(uid, returnExpiry)
|
||||
}
|
||||
}
|
||||
_, _ = s.db.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid)
|
||||
_ = s.userRepo.UpdateLastLogin(uid, time.Now())
|
||||
return returnExpiry
|
||||
}
|
||||
|
||||
func (s *APIServer) exportSave(ctx context.Context, uid uint32, cid uint32) (map[string]interface{}, error) {
|
||||
row := s.db.QueryRowxContext(ctx, "SELECT * FROM characters WHERE id=$1 AND user_id=$2", cid, uid)
|
||||
result := make(map[string]interface{})
|
||||
err := row.MapScan(result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
return s.charRepo.ExportSave(ctx, uid, cid)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user