chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
94
internal/store/postgres/peer_username.go
Normal file
94
internal/store/postgres/peer_username.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgerrcode"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store/postgres/sqlcgen"
|
||||
)
|
||||
|
||||
const (
|
||||
peerUsernameTypeUser = "user"
|
||||
peerUsernameTypeChannel = "channel"
|
||||
)
|
||||
|
||||
type peerUsernameOwner struct {
|
||||
peerType string
|
||||
peerID int64
|
||||
}
|
||||
|
||||
func (o peerUsernameOwner) matches(peerType string, peerID int64) bool {
|
||||
return o.peerType == peerType && o.peerID == peerID
|
||||
}
|
||||
|
||||
func getPeerUsernameOwner(ctx context.Context, db sqlcgen.DBTX, usernameLower string, forUpdate bool) (peerUsernameOwner, bool, error) {
|
||||
if usernameLower == "" {
|
||||
return peerUsernameOwner{}, false, nil
|
||||
}
|
||||
query := `SELECT peer_type, peer_id FROM peer_usernames WHERE username_lower = $1`
|
||||
if forUpdate {
|
||||
query += ` FOR UPDATE`
|
||||
}
|
||||
var owner peerUsernameOwner
|
||||
err := db.QueryRow(ctx, query, usernameLower).Scan(&owner.peerType, &owner.peerID)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return peerUsernameOwner{}, false, nil
|
||||
}
|
||||
return peerUsernameOwner{}, false, fmt.Errorf("get peer username owner: %w", err)
|
||||
}
|
||||
return owner, true, nil
|
||||
}
|
||||
|
||||
func peerUsernameAvailable(ctx context.Context, db sqlcgen.DBTX, usernameLower, peerType string, peerID int64) (bool, error) {
|
||||
owner, found, err := getPeerUsernameOwner(ctx, db, usernameLower, false)
|
||||
if err != nil || !found {
|
||||
return !found, err
|
||||
}
|
||||
return owner.matches(peerType, peerID), nil
|
||||
}
|
||||
|
||||
func replacePeerUsernameTx(ctx context.Context, tx pgx.Tx, peerType string, peerID int64, usernameLower string) error {
|
||||
if usernameLower != "" {
|
||||
owner, found, err := getPeerUsernameOwner(ctx, tx, usernameLower, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found && !owner.matches(peerType, peerID) {
|
||||
return domain.ErrUsernameOccupied
|
||||
}
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `DELETE FROM peer_usernames WHERE peer_type = $1 AND peer_id = $2`, peerType, peerID); err != nil {
|
||||
return fmt.Errorf("delete peer username: %w", err)
|
||||
}
|
||||
if usernameLower == "" {
|
||||
return nil
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO peer_usernames (username_lower, peer_type, peer_id)
|
||||
VALUES ($1, $2, $3)`, usernameLower, peerType, peerID); err != nil {
|
||||
if isUniqueViolation(err) {
|
||||
return domain.ErrUsernameOccupied
|
||||
}
|
||||
return fmt.Errorf("insert peer username: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deletePeerUsernameTx(ctx context.Context, tx pgx.Tx, peerType string, peerID int64) error {
|
||||
if _, err := tx.Exec(ctx, `DELETE FROM peer_usernames WHERE peer_type = $1 AND peer_id = $2`, peerType, peerID); err != nil {
|
||||
return fmt.Errorf("delete peer username: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isUniqueConstraint(err error, constraintName string) bool {
|
||||
var pgErr *pgconn.PgError
|
||||
return errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UniqueViolation && pgErr.ConstraintName == constraintName
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue