import type { Context } from "sealious"; import { App, Collections, FieldTypes, Policies } from "sealious"; import assert from "assert"; import TheApp from "../app.js"; import ADMIN_CREDENTIALS from "../default-admin-credentials.js"; import { Roles } from "../policy-types/roles.js"; export default class Users extends Collections.users { fields = { ...App.BaseCollections.users.fields, email: new FieldTypes.Email().setRequired(true), roles: new FieldTypes.ReverseSingleReference({ referencing_collection: "user-roles", referencing_field: "user", }), }; defaultPolicy = new Policies.Or([new Policies.Themselves(), new Roles(["admin"])]); policies = { create: new Roles(["admin"]), show: new Policies.Or([new Policies.Themselves(), new Roles(["admin"])]), }; async init(app: App, name: string) { assert(app instanceof TheApp); await super.init(app, name); app.on("started", async () => { const username = ADMIN_CREDENTIALS.username; const all_users = await app.collections.users.suList().fetch(); if (all_users.empty) { app.Logger.warn( "ADMIN", `Creating an admin account for ${app.manifest.admin_email}` ); const { id } = await app.collections.users.suCreate({ username, password: ADMIN_CREDENTIALS.password, email: ADMIN_CREDENTIALS.email, roles: [], }); await app.collections["user-roles"].suCreate({ user: id, role: "admin" }); } }); } public static async getRoles(ctx: Context) { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions const rolesEntries = await (ctx.app as TheApp).collections["user-roles"] .list(ctx) .filter({ user: ctx.user_id || "" }) .fetch(); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions return rolesEntries.items.map((item) => item.get("role")); } }