feat/fix: adding auth.default_role_register and disallow giving role on registration payload

This commit is contained in:
dswbx
2025-12-05 14:02:42 +01:00
parent e21b5e5b55
commit ed41887d74
6 changed files with 145 additions and 8 deletions

View File

@@ -46,6 +46,22 @@ export class AppAuth extends Module<AppAuthSchema> {
to.strategies!.password!.enabled = true;
}
if (to.default_role_register && to.default_role_register?.length > 0) {
const valid_to_role = Object.keys(to.roles ?? {}).includes(to.default_role_register);
if (!valid_to_role) {
const msg = `Default role for registration not found: ${to.default_role_register}`;
// if changing to a new value
if (from.default_role_register !== to.default_role_register) {
throw new Error(msg);
}
// resetting gracefully, since role doesn't exist anymore
$console.warn(`${msg}, resetting to undefined`);
to.default_role_register = undefined;
}
}
return to;
}
@@ -82,6 +98,7 @@ export class AppAuth extends Module<AppAuthSchema> {
this._authenticator = new Authenticator(strategies, new AppUserPool(this), {
jwt: this.config.jwt,
cookie: this.config.cookie,
default_role_register: this.config.default_role_register,
});
this.registerEntities();
@@ -171,10 +188,20 @@ export class AppAuth extends Module<AppAuthSchema> {
} catch (e) {}
}
async createUser({ email, password, ...additional }: CreateUserPayload): Promise<DB["users"]> {
async createUser({
email,
password,
role,
...additional
}: CreateUserPayload): Promise<DB["users"]> {
if (!this.enabled) {
throw new Error("Cannot create user, auth not enabled");
}
if (role) {
if (!Object.keys(this.config.roles ?? {}).includes(role)) {
throw new Error(`Role "${role}" not found`);
}
}
const strategy = "password" as const;
const pw = this.authenticator.strategy(strategy) as PasswordStrategy;
@@ -183,6 +210,7 @@ export class AppAuth extends Module<AppAuthSchema> {
mutator.__unstable_toggleSystemEntityCreation(false);
const { data: created } = await mutator.insertOne({
...(additional as any),
role: role || this.config.default_role_register || undefined,
email,
strategy,
strategy_value,

View File

@@ -51,6 +51,7 @@ export const authConfigSchema = $object(
basepath: s.string({ default: "/api/auth" }),
entity_name: s.string({ default: "users" }),
allow_register: s.boolean({ default: true }).optional(),
default_role_register: s.string().optional(),
jwt: jwtConfig,
cookie: cookieConfig,
strategies: $record(

View File

@@ -74,6 +74,7 @@ export const jwtConfig = s.strictObject(
export const authenticatorConfig = s.object({
jwt: jwtConfig,
cookie: cookieConfig,
default_role_register: s.string().optional(),
});
type AuthConfig = s.Static<typeof authenticatorConfig>;
@@ -164,9 +165,13 @@ export class Authenticator<
if (!("strategy_value" in profile)) {
throw new InvalidConditionsException("Profile must have a strategy value");
}
if ("role" in profile) {
throw new InvalidConditionsException("Role cannot be provided during registration");
}
const user = await this.userPool.create(strategy.getName(), {
...profile,
role: this.config.default_role_register,
strategy_value: profile.strategy_value,
});