Add video
This commit is contained in:
parent
589de0c5ac
commit
7c36cbfdd4
18 changed files with 2292 additions and 333 deletions
121
video/src/pb-admin.ts
Normal file
121
video/src/pb-admin.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
interface SuperuserAuthResponse {
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface UserRecord {
|
||||
id: string;
|
||||
email: string;
|
||||
is_admin?: boolean;
|
||||
subscription?: string;
|
||||
}
|
||||
|
||||
function requireEnv(name: string): string {
|
||||
const value = process.env[name];
|
||||
if (!value) throw new Error(`${name} is required`);
|
||||
return value;
|
||||
}
|
||||
|
||||
async function pbJson<T>(
|
||||
url: string,
|
||||
init: RequestInit,
|
||||
label: string
|
||||
): Promise<T> {
|
||||
const res = await fetch(url, init);
|
||||
if (!res.ok) {
|
||||
throw new Error(`${label} ${res.status}: ${await res.text()}`);
|
||||
}
|
||||
return (await res.json()) as T;
|
||||
}
|
||||
|
||||
async function superuserToken(pbUrl: string, email: string, password: string): Promise<string> {
|
||||
const data = await pbJson<SuperuserAuthResponse>(
|
||||
`${pbUrl}/api/collections/_superusers/auth-with-password`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ identity: email, password }),
|
||||
},
|
||||
'PocketBase superuser auth'
|
||||
);
|
||||
return data.token;
|
||||
}
|
||||
|
||||
async function findUser(pbUrl: string, token: string, email: string): Promise<UserRecord | null> {
|
||||
const filter = `email="${email.replaceAll('"', '\\"')}"`;
|
||||
const data = await pbJson<{ items: UserRecord[] }>(
|
||||
`${pbUrl}/api/collections/users/records?filter=${encodeURIComponent(filter)}&perPage=1`,
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
'PocketBase user lookup'
|
||||
);
|
||||
return data.items[0] ?? null;
|
||||
}
|
||||
|
||||
function recorderUserBody(email: string, password: string): Record<string, unknown> {
|
||||
return {
|
||||
email,
|
||||
emailVisibility: true,
|
||||
verified: true,
|
||||
password,
|
||||
passwordConfirm: password,
|
||||
is_admin: true,
|
||||
subscription: 'licensed',
|
||||
};
|
||||
}
|
||||
|
||||
export async function ensureRecorderAdminUser(): Promise<void> {
|
||||
const pbUrl = requireEnv('PB_URL').replace(/\/$/, '');
|
||||
const email = requireEnv('PB_EMAIL');
|
||||
const password = requireEnv('PB_PASSWORD');
|
||||
const adminEmail = process.env.PB_ADMIN_EMAIL ?? process.env.POCKETBASE_ADMIN_EMAIL;
|
||||
const adminPassword = process.env.PB_ADMIN_PASSWORD ?? process.env.POCKETBASE_ADMIN_PASSWORD;
|
||||
|
||||
if (!adminEmail || !adminPassword) {
|
||||
throw new Error('PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD are required to bootstrap the recorder user');
|
||||
}
|
||||
|
||||
const token = await superuserToken(pbUrl, adminEmail, adminPassword);
|
||||
const existing = await findUser(pbUrl, token, email);
|
||||
const body = recorderUserBody(email, password);
|
||||
|
||||
if (existing) {
|
||||
await pbJson<UserRecord>(
|
||||
`${pbUrl}/api/collections/users/records/${existing.id}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
},
|
||||
'PocketBase recorder user update'
|
||||
);
|
||||
console.log(`Updated recorder admin user ${email}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
await pbJson<UserRecord>(
|
||||
`${pbUrl}/api/collections/users/records`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
},
|
||||
'PocketBase recorder user create'
|
||||
);
|
||||
console.log(`Created recorder admin user ${email}.`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await ensureRecorderAdminUser();
|
||||
}
|
||||
|
||||
if (process.argv[1]?.endsWith('pb-admin.js')) {
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue