Files
2026-08-29 17:02:42 +03:00

65 lines
3.1 KiB
Go

package postgres
import (
"context"
"fmt"
"git.cin.su/m/Assistant/contracts/identity"
"github.com/jackc/pgx/v5/pgxpool"
)
type IdentityRepository struct{ pool *pgxpool.Pool }
func OpenIdentity(ctx context.Context, config ContinuityConfig) (*IdentityRepository, error) {
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
return &IdentityRepository{pool: pool}, nil
}
func (r *IdentityRepository) Close() { r.pool.Close() }
func (r *IdentityRepository) LoadBinding(ctx context.Context, actor identity.ActorID, principal identity.PrincipalID) (identity.PrincipalBinding, error) {
var binding identity.PrincipalBinding
err := r.pool.QueryRow(ctx, `SELECT actor_id, principal_id, active FROM identity.principal_bindings WHERE actor_id=$1 AND principal_id=$2`, actor, principal).Scan(&binding.ActorID, &binding.PrincipalID, &binding.Active)
if err != nil {
return identity.PrincipalBinding{}, fmt.Errorf("load identity binding: %w", err)
}
return binding, nil
}
func (r *IdentityRepository) LoadCreatorAccount(ctx context.Context, username string) (identity.CreatorAccount, error) {
var account identity.CreatorAccount
err := r.pool.QueryRow(ctx, `SELECT username, actor_id, principal_id, password_hash, revision FROM identity.creator_accounts WHERE username=$1`, username).
Scan(&account.Username, &account.ActorID, &account.PrincipalID, &account.PasswordHash, &account.Revision)
if err != nil {
return identity.CreatorAccount{}, fmt.Errorf("load creator account: %w", err)
}
return account, nil
}
func (r *IdentityRepository) LoadCreatorAccountByBinding(ctx context.Context, actor identity.ActorID, principal identity.PrincipalID) (identity.CreatorAccount, error) {
var account identity.CreatorAccount
err := r.pool.QueryRow(ctx, `SELECT username, actor_id, principal_id, password_hash, revision FROM identity.creator_accounts WHERE actor_id=$1 AND principal_id=$2`, actor, principal).
Scan(&account.Username, &account.ActorID, &account.PrincipalID, &account.PasswordHash, &account.Revision)
if err != nil {
return identity.CreatorAccount{}, fmt.Errorf("load creator account by binding: %w", err)
}
return account, nil
}
func (r *IdentityRepository) CreateCreatorAccount(ctx context.Context, account identity.CreatorAccount) error {
_, err := r.pool.Exec(ctx, `INSERT INTO identity.creator_accounts (username, actor_id, principal_id, password_hash) VALUES ($1,$2,$3,$4) ON CONFLICT (username) DO NOTHING`, account.Username, account.ActorID, account.PrincipalID, account.PasswordHash)
return err
}
func (r *IdentityRepository) UpdateCreatorPassword(ctx context.Context, actor identity.ActorID, principal identity.PrincipalID, revision int64, passwordHash string) error {
result, err := r.pool.Exec(ctx, `UPDATE identity.creator_accounts SET password_hash=$1, revision=revision+1, password_changed_at=CURRENT_TIMESTAMP WHERE actor_id=$2 AND principal_id=$3 AND revision=$4`, passwordHash, actor, principal, revision)
if err != nil {
return fmt.Errorf("update creator password: %w", err)
}
if result.RowsAffected() != 1 {
return fmt.Errorf("update creator password: revision conflict")
}
return nil
}