A plain blocklist for names like @support - separate from the collectible
system, so a reservation has no owner, no price and no "bought on Fragment"
badge.
- reserved_usernames table + migration.
- Enforced in replacePeerUsernameTx (the single editable-username write point:
account.updateUsername, channels.updateUsername, @BotFather /setusername) and
in the collectible mint path; a reserved name returns USERNAME_OCCUPIED.
- admin.Service: ReserveUsername / UnreserveUsername (journalled commands) and
the ReservedUsernames listing.
- adminapi: /v1/reserved-usernames{,/reserve,/unreserve}.
- telesrv-admin panel + a "Reserved Usernames" page in the web UI (dist rebuilt).
- Postgres and in-memory store implementations; the memory registry gains an
optional reserved-name check so tests exercise the same rule.
22 lines
971 B
Go
22 lines
971 B
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
// ReservedUsernameStore owns the operator username blocklist. IsReserved is the
|
|
// hot path consulted on every editable-username write; the rest are the admin
|
|
// lifecycle.
|
|
type ReservedUsernameStore interface {
|
|
// IsReserved reports whether usernameLower (already lowercased) is blocked.
|
|
IsReserved(ctx context.Context, usernameLower string) (bool, error)
|
|
// ReserveUsername adds an entry. Returns created=false if it already existed
|
|
// (the existing reason/actor are kept).
|
|
ReserveUsername(ctx context.Context, username, reason, actor string) (created bool, err error)
|
|
// UnreserveUsername removes an entry. Returns removed=false if absent.
|
|
UnreserveUsername(ctx context.Context, username string) (removed bool, err error)
|
|
// ReservedUsernames pages the blocklist, newest first.
|
|
ReservedUsernames(ctx context.Context, filter domain.ReservedUsernameFilter) ([]domain.ReservedUsername, error)
|
|
}
|