feat(admin): manual account blocking (suspensions)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 12s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m10s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 12s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m10s
Operator-driven hard block, the counterpart to the soft high-rate flag: permanent or until a date, with an optional reason chosen from an editable en+ru picklist (snapshotted onto the block). A block forfeits the player's active games (opponent wins, as a resignation) and cancels their open matchmaking games. A backend gate refuses a blocked account on every /api/v1/user/* route except the block-status probe with 403 account_blocked, which threads through the gateway as the Execute result_code; the UI surfaces it as a terminal blocked screen and stops all push/poll. Temporary blocks self-expire; the operator can unblock at any time (lost games stay lost). Sessions are not revoked, so the blocked client can still reach the exempt block-status endpoint. Backend: migration 00003 (account_suspensions + suspension_reasons) + jet regen; account suspension store; game.ForfeitAllForAccount; requireNotSuspended gate + block-status endpoint; admin console block/unblock + Reasons CRUD. Wire: fbs BlockStatus + account.block_status gateway op. UI: blocked screen, app state, transport/codec, i18n. Docs: ARCHITECTURE, FUNCTIONAL(+ru), PRERELEASE (AB).
This commit is contained in:
@@ -135,6 +135,29 @@ type UserDetailView struct {
|
||||
// MoveChart is the pre-rendered inline SVG of the account's per-move-number think
|
||||
// time (min/mean/max), empty when the account has no timed move.
|
||||
MoveChart template.HTML
|
||||
// Suspension is the account's current manual-block state, shown with the block/unblock
|
||||
// form; Reasons is the operator-editable reason picklist offered in the block form.
|
||||
Suspension SuspensionView
|
||||
Reasons []ReasonOption
|
||||
}
|
||||
|
||||
// SuspensionView is an account's current manual-block state shown on the user card: whether it
|
||||
// is blocked, whether the block is permanent, the pre-formatted expiry (empty when permanent),
|
||||
// when it was applied, and the reason snapshot in both languages (empty when none was cited).
|
||||
type SuspensionView struct {
|
||||
Blocked bool
|
||||
Permanent bool
|
||||
Until string
|
||||
BlockedAt string
|
||||
ReasonEn string
|
||||
ReasonRu string
|
||||
}
|
||||
|
||||
// ReasonOption is one suspension-reason picklist entry offered in the block form's dropdown.
|
||||
type ReasonOption struct {
|
||||
ID string
|
||||
TextEn string
|
||||
TextRu string
|
||||
}
|
||||
|
||||
// StatsRow is an account's lifetime statistics.
|
||||
@@ -317,6 +340,19 @@ type FlaggedAccountRow struct {
|
||||
FlaggedAt string
|
||||
}
|
||||
|
||||
// ReasonsView is the suspension-reason picklist management page: every editable reason entry.
|
||||
type ReasonsView struct {
|
||||
Items []ReasonRow
|
||||
}
|
||||
|
||||
// ReasonRow is one editable suspension-reason entry, with its English and Russian text.
|
||||
type ReasonRow struct {
|
||||
ID string
|
||||
TextEn string
|
||||
TextRu string
|
||||
CreatedAt string
|
||||
}
|
||||
|
||||
// MessageView is the result page shown after a POST action.
|
||||
type MessageView struct {
|
||||
Heading string
|
||||
|
||||
Reference in New Issue
Block a user