[www] Manage Avatar Studio and screen-sharing access (#144)

This commit is contained in:
dukedotdev
2026-10-26 20:05:27 -04:00
committed by GitHub
parent 44704fec51
commit f6214fb824
8 changed files with 356 additions and 67 deletions
+18 -2
View File
@@ -11,6 +11,7 @@
* it from `@repo/domain` (each uses the subset it needs).
*/
import { AVATAR_STUDIO_ACCESS } from './avatar-studio'
import { bindPlaceholders, chunkForBinds } from './d1-binds'
/**
@@ -206,6 +207,8 @@ export interface Account {
* open keeps its old access until it signs in again or refreshes.
*/
hasStudio?: boolean
/** Staff override for screen sharing. Absent means screen sharing is disabled. */
hasScreenshare?: boolean
}
interface AccountRow {
@@ -500,10 +503,23 @@ export async function listInfluencerIds(db: D1Database): Promise<number[]> {
* Every account flagged `hasStudio`, lowest id first — the website's staff list. A JSON
* scan rather than a generated column: the list is short and only staff read it.
*/
export async function listStudioAccounts(db: D1Database): Promise<Account[]> {
export async function listStudioAccounts(
db: D1Database,
kind: 'studio' | 'avatar' | 'screenshare' | keyof typeof AVATAR_STUDIO_ACCESS = 'studio'
): Promise<Account[]> {
const mask =
kind === 'avatar'
? 7
: Object.hasOwn(AVATAR_STUDIO_ACCESS, kind)
? AVATAR_STUDIO_ACCESS[kind as keyof typeof AVATAR_STUDIO_ACCESS]
: 0
const { results } = await db
.prepare(
`SELECT data FROM account WHERE json_extract(data, '$.hasStudio') = 1 ORDER BY account_id`
mask !== 0
? `SELECT data FROM account WHERE account_id IN (SELECT account_id FROM avatar_studio_access WHERE (flags & ${mask}) != 0) ORDER BY account_id`
: kind === 'screenshare'
? `SELECT data FROM account WHERE json_extract(data, '$.hasScreenshare') = 1 ORDER BY account_id`
: `SELECT data FROM account WHERE json_extract(data, '$.hasStudio') = 1 ORDER BY account_id`
)
.all<AccountRow>()
return parseAll(results)
+8
View File
@@ -28,6 +28,14 @@ export interface AvatarStudioSave {
update_current: number
created_at: string
}
/** Independent authoring permissions reported by Studio's access override. */
export const AVATAR_STUDIO_ACCESS = {
'avatar-items': 1,
'avatar-costumes': 2,
'avatar-badges': 4,
'avatar-consumables': 8,
} as const
export async function avatarStudioFlags(db: D1Database, accountId: number): Promise<number> {
const row = await db
.prepare('SELECT flags FROM avatar_studio_access WHERE account_id=?')