feat(auth): support schema-qualified SQL stores

This commit is contained in:
Clintchiz committed 2026-08-26 14:11:13 +05:30
1 parent a85cbf240d
commit 681679483a
5 files changed
+48 -4

No files matched your search

+1
View File
@@ -8,6 +8,7 @@ export {
export type { AuthStore } from "./store.ts";
export { MemoryAuthStore } from "./stores/memory.ts";
export { SqlAuthStore } from "./stores/sql.ts";
export type { SqlAuthStoreOptions } from "./stores/sql.ts";
export {
authSession,
requireAuth,
+23 -2
View File
@@ -34,10 +34,31 @@ function placeholders(sql: string, dialect: string): string {
return sql.replace(/\?/g, () => `$${++index}`);
}
export interface SqlAuthStoreOptions {
/** PostgreSQL schema owning authentication tables. */
schema?: string;
/** Defaults to wrn_auth_; use an empty prefix for e.g. sso.users. */
tablePrefix?: string;
}
export class SqlAuthStore implements AuthStore {
constructor(private readonly db: Db) {}
constructor(
private readonly db: Db,
private readonly options: SqlAuthStoreOptions = {},
) {
if (options.schema && !/^[a-z_][a-z0-9_]*$/i.test(options.schema))
throw new Error("Invalid auth schema identifier");
if (options.tablePrefix && !/^[a-z_][a-z0-9_]*$/i.test(options.tablePrefix))
throw new Error("Invalid auth table prefix");
if (options.schema && db.driver.dialect !== "postgres")
throw new Error("Auth schema requires PostgreSQL");
}
private sql(value: string): string {
return placeholders(value, this.db.driver.dialect);
const qualified = value.replace(/\bwrn_auth_([a-z_]+)\b/g, (_match, table: string) => {
const name = (this.options.tablePrefix ?? "wrn_auth_") + table;
return this.options.schema ? '"' + this.options.schema + '"."' + name + '"' : name;
});
return placeholders(qualified, this.db.driver.dialect);
}
private async one(sql: string, params: unknown[] = []): Promise<Row | undefined> {
return (await this.db.one(this.sql(sql), params)) ?? undefined;