109 lines
2 KiB
Go
109 lines
2 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"crypto/subtle"
|
|
"database/sql"
|
|
"errors"
|
|
"strings"
|
|
|
|
"go-backend/internal/auth"
|
|
"go-backend/internal/database/sqlc"
|
|
)
|
|
|
|
type AuthService struct {
|
|
db *sql.DB
|
|
queries *sqlc.Queries
|
|
}
|
|
|
|
func NewAuthService(db *sql.DB, queries *sqlc.Queries) *AuthService {
|
|
return &AuthService{
|
|
db: db,
|
|
queries: queries,
|
|
}
|
|
}
|
|
|
|
type SessionWithToken struct {
|
|
Session sqlc.UserSession
|
|
Token string
|
|
}
|
|
|
|
func (s *AuthService) CreateSession(ctx context.Context, userID string) (*SessionWithToken, error) {
|
|
id, err := auth.GenerateSecureRandomString()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
secret, err := auth.GenerateSecureRandomString()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
secretHash := auth.HashSecret(secret)
|
|
token := id + "." + secret
|
|
|
|
session, err := s.queries.InsertSession(ctx, sqlc.InsertSessionParams{
|
|
ID: id,
|
|
SecretHash: secretHash,
|
|
UserID: userID,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &SessionWithToken{
|
|
Session: session,
|
|
Token: token,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func (s *AuthService) ValidateSessionToken(ctx context.Context, token string) (*sqlc.UserSession, error) {
|
|
tokenParts := strings.Split(token, ".")
|
|
if len(tokenParts) != 2 {
|
|
return nil, nil
|
|
}
|
|
|
|
sessionID := tokenParts[0]
|
|
sessionSecret := tokenParts[1]
|
|
|
|
session, err := s.queries.SelectSessionById(ctx, sessionID)
|
|
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, nil
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
if auth.CheckExpiration(session.CreatedAt) {
|
|
err = s.queries.DeleteSessionById(ctx, sessionID)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
tokenSecretHash := auth.HashSecret(sessionSecret)
|
|
if subtle.ConstantTimeCompare(tokenSecretHash, session.SecretHash) != 1 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &session, nil
|
|
}
|
|
|
|
func (s *AuthService) DeleteSession(ctx context.Context, token string) error {
|
|
tokenParts := strings.Split(token, ".")
|
|
if len(tokenParts) != 2 {
|
|
return nil
|
|
}
|
|
|
|
sessionID := tokenParts[0]
|
|
|
|
err := s.queries.DeleteSessionById(ctx, sessionID)
|
|
|
|
return err
|
|
}
|