@rebasepro/server-postgres 0.9.1-canary.c0d4c07 → 0.9.1-canary.d906fb7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/services.d.ts +0 -16
- package/dist/connection.d.ts +0 -21
- package/dist/index.es.js +29 -148
- package/dist/index.es.js.map +1 -1
- package/dist/schema/doctor.d.ts +1 -1
- package/dist/security/policy-drift.d.ts +0 -30
- package/package.json +6 -7
- package/src/auth/ensure-tables.ts +11 -73
- package/src/auth/services.ts +19 -49
- package/src/cli.ts +0 -60
- package/src/connection.ts +1 -61
- package/src/databasePoolManager.ts +0 -2
- package/src/schema/doctor.ts +20 -45
- package/src/security/policy-drift.test.ts +1 -106
- package/src/security/policy-drift.ts +0 -56
- package/src/services/row-pipeline.ts +3 -27
package/dist/auth/services.d.ts
CHANGED
|
@@ -19,22 +19,6 @@ export declare class UserService implements UserRepository {
|
|
|
19
19
|
private userIdentitiesTable;
|
|
20
20
|
constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
|
|
21
21
|
private getQualifiedUsersTableName;
|
|
22
|
-
/**
|
|
23
|
-
* Run a privileged auth write with an explicitly cleared RLS context.
|
|
24
|
-
*
|
|
25
|
-
* The auth services run on the base/owner connection, which by design
|
|
26
|
-
* carries a NULL `app.user_id` so the `auth.uid() IS NULL` server-escape
|
|
27
|
-
* in the default policies applies. That NULL is normally guaranteed by
|
|
28
|
-
* `set_config(..., is_local = true)` resetting at transaction end — but a
|
|
29
|
-
* GUC that survives on a pooled connection (or a connection role that
|
|
30
|
-
* doesn't bypass RLS: FORCE ROW LEVEL SECURITY, or a non-owner role)
|
|
31
|
-
* turns the trusted write into an RLS-scoped one and denies it with
|
|
32
|
-
* SQLSTATE 42501. Clearing the GUCs here, transaction-locally at the
|
|
33
|
-
* single chokepoint, makes the server context deterministic instead of
|
|
34
|
-
* trusting whatever state the pool hands us. `auth.uid()` reads '' as
|
|
35
|
-
* NULL via NULLIF, so '' is the server context.
|
|
36
|
-
*/
|
|
37
|
-
private withServerContext;
|
|
38
22
|
private mapRowToUser;
|
|
39
23
|
private mapPayload;
|
|
40
24
|
createUser(data: CreateUserData): Promise<UserData>;
|
package/dist/connection.d.ts
CHANGED
|
@@ -19,27 +19,6 @@ export interface PostgresPoolConfig {
|
|
|
19
19
|
/** Enable TCP keep-alive (default: true) */
|
|
20
20
|
keepAlive?: boolean;
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Destroy pool clients that are released while still inside a transaction.
|
|
24
|
-
*
|
|
25
|
-
* pg-pool returns a client to the idle list whenever `release()` is called
|
|
26
|
-
* without an error — even if the connection is still mid-transaction (status
|
|
27
|
-
* `T`/`E`). That happens in practice: drizzle's pool transaction releases in
|
|
28
|
-
* a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
|
|
29
|
-
* (e.g. it was queued behind a statement that hit the client-side
|
|
30
|
-
* query_timeout), the client goes back dirty. The next checkout then runs
|
|
31
|
-
* its statements inside the zombie transaction — with the previous request's
|
|
32
|
-
* `app.*` RLS GUCs still applied, which turns unrelated queries into
|
|
33
|
-
* RLS-scoped ones (observed in production as registration failing with
|
|
34
|
-
* SQLSTATE 42501 under a leaked anonymous context).
|
|
35
|
-
*
|
|
36
|
-
* pg-pool emits `release` before it consults its private `_expired` set, so
|
|
37
|
-
* marking the client expired here makes `_release()` destroy it instead of
|
|
38
|
-
* pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
|
|
39
|
-
* private APIs — feature-detect and fall back to loud logging so an upstream
|
|
40
|
-
* change degrades to observability, never to silent corruption.
|
|
41
|
-
*/
|
|
42
|
-
export declare function guardPoolAgainstDirtyRelease(pool: Pool, label: string): void;
|
|
43
22
|
/**
|
|
44
23
|
* Create a Drizzle-backed Postgres connection with a production-grade
|
|
45
24
|
* connection pool.
|
package/dist/index.es.js
CHANGED
|
@@ -71,51 +71,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
71
71
|
var connection_exports = /* @__PURE__ */ __exportAll({
|
|
72
72
|
createDirectDatabaseConnection: () => createDirectDatabaseConnection,
|
|
73
73
|
createPostgresDatabaseConnection: () => createPostgresDatabaseConnection,
|
|
74
|
-
createReadReplicaConnection: () => createReadReplicaConnection
|
|
75
|
-
guardPoolAgainstDirtyRelease: () => guardPoolAgainstDirtyRelease
|
|
74
|
+
createReadReplicaConnection: () => createReadReplicaConnection
|
|
76
75
|
});
|
|
77
76
|
var DEFAULT_POOL = {
|
|
78
77
|
max: 20,
|
|
79
78
|
idleTimeoutMillis: 3e4,
|
|
80
79
|
connectionTimeoutMillis: 1e4,
|
|
81
|
-
queryTimeout:
|
|
80
|
+
queryTimeout: 3e4,
|
|
82
81
|
statementTimeout: 3e4,
|
|
83
82
|
keepAlive: true
|
|
84
83
|
};
|
|
85
|
-
/** ReadyForQuery status byte: `I` idle, `T` in transaction, `E` failed transaction. */
|
|
86
|
-
var TX_IDLE = "I";
|
|
87
|
-
/**
|
|
88
|
-
* Destroy pool clients that are released while still inside a transaction.
|
|
89
|
-
*
|
|
90
|
-
* pg-pool returns a client to the idle list whenever `release()` is called
|
|
91
|
-
* without an error — even if the connection is still mid-transaction (status
|
|
92
|
-
* `T`/`E`). That happens in practice: drizzle's pool transaction releases in
|
|
93
|
-
* a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
|
|
94
|
-
* (e.g. it was queued behind a statement that hit the client-side
|
|
95
|
-
* query_timeout), the client goes back dirty. The next checkout then runs
|
|
96
|
-
* its statements inside the zombie transaction — with the previous request's
|
|
97
|
-
* `app.*` RLS GUCs still applied, which turns unrelated queries into
|
|
98
|
-
* RLS-scoped ones (observed in production as registration failing with
|
|
99
|
-
* SQLSTATE 42501 under a leaked anonymous context).
|
|
100
|
-
*
|
|
101
|
-
* pg-pool emits `release` before it consults its private `_expired` set, so
|
|
102
|
-
* marking the client expired here makes `_release()` destroy it instead of
|
|
103
|
-
* pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
|
|
104
|
-
* private APIs — feature-detect and fall back to loud logging so an upstream
|
|
105
|
-
* change degrades to observability, never to silent corruption.
|
|
106
|
-
*/
|
|
107
|
-
function guardPoolAgainstDirtyRelease(pool, label) {
|
|
108
|
-
pool.on("release", (err, client) => {
|
|
109
|
-
if (err) return;
|
|
110
|
-
const txStatus = client?._txStatus;
|
|
111
|
-
if (typeof txStatus !== "string" || txStatus === TX_IDLE) return;
|
|
112
|
-
const expired = pool._expired;
|
|
113
|
-
if (expired && typeof expired.add === "function" && typeof expired.has === "function" && client && typeof client === "object") {
|
|
114
|
-
expired.add(client);
|
|
115
|
-
logger.error(`[${label}] Client released back to the pool while still in a transaction (status '${txStatus}') — destroying it so the open transaction and its session state (RLS GUCs) cannot leak into the next request.`);
|
|
116
|
-
} else logger.error(`[${label}] Client released mid-transaction (status '${txStatus}') but the pool's internal expiry set is unavailable (pg-pool internals changed?). The connection may leak its open transaction into subsequent requests.`);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
84
|
/**
|
|
120
85
|
* Create a Drizzle-backed Postgres connection with a production-grade
|
|
121
86
|
* connection pool.
|
|
@@ -147,7 +112,6 @@ function createPostgresDatabaseConnection(connectionString, schema, poolConfig)
|
|
|
147
112
|
logger.error("[pg-pool] Unexpected pool error", { detail: err.message });
|
|
148
113
|
if (err.message.includes("ETIMEDOUT")) logger.warn("[pg-pool] Connection timeout detected — pool will auto-retry");
|
|
149
114
|
});
|
|
150
|
-
guardPoolAgainstDirtyRelease(pool, "pg-pool");
|
|
151
115
|
return {
|
|
152
116
|
db: schema ? drizzle(pool, { schema }) : drizzle(pool),
|
|
153
117
|
pool,
|
|
@@ -180,7 +144,6 @@ function createDirectDatabaseConnection(connectionString, schema, poolConfig) {
|
|
|
180
144
|
pool.on("error", (err) => {
|
|
181
145
|
logger.error("[pg-direct-pool] Unexpected pool error", { detail: err.message });
|
|
182
146
|
});
|
|
183
|
-
guardPoolAgainstDirtyRelease(pool, "pg-direct-pool");
|
|
184
147
|
return {
|
|
185
148
|
db: schema ? drizzle(pool, { schema }) : drizzle(pool),
|
|
186
149
|
pool,
|
|
@@ -210,7 +173,6 @@ function createReadReplicaConnection(connectionString, schema, poolConfig) {
|
|
|
210
173
|
pool.on("error", (err) => {
|
|
211
174
|
logger.error("[pg-replica-pool] Unexpected pool error", { detail: err.message });
|
|
212
175
|
});
|
|
213
|
-
guardPoolAgainstDirtyRelease(pool, "pg-replica-pool");
|
|
214
176
|
return {
|
|
215
177
|
db: schema ? drizzle(pool, { schema }) : drizzle(pool),
|
|
216
178
|
pool,
|
|
@@ -6524,27 +6486,8 @@ function coerceDeclaredNumbers(row, collection) {
|
|
|
6524
6486
|
return out;
|
|
6525
6487
|
}
|
|
6526
6488
|
/** Render one target row in the requested style. */
|
|
6527
|
-
/**
|
|
6528
|
-
* Drop every column the collection marked `excludeFromApi`.
|
|
6529
|
-
*
|
|
6530
|
-
* Password hashes and verification tokens have to be readable server-side but
|
|
6531
|
-
* must never reach a client — and "never" has to mean every exit from this
|
|
6532
|
-
* pipeline, including relation targets, or a secret leaks through whichever
|
|
6533
|
-
* path was overlooked. Keyed by both the property name and its column name,
|
|
6534
|
-
* since a row can arrive keyed either way depending on the caller.
|
|
6535
|
-
*/
|
|
6536
|
-
function stripExcluded(row, collection) {
|
|
6537
|
-
const properties = collection.properties;
|
|
6538
|
-
if (!properties) return row;
|
|
6539
|
-
for (const [key, property] of Object.entries(properties)) {
|
|
6540
|
-
if (!property?.excludeFromApi) continue;
|
|
6541
|
-
delete row[key];
|
|
6542
|
-
if (property.columnName) delete row[property.columnName];
|
|
6543
|
-
}
|
|
6544
|
-
return row;
|
|
6545
|
-
}
|
|
6546
6489
|
function renderTarget(targetRow, targetCollection, style, registry) {
|
|
6547
|
-
if (style === "inline") return
|
|
6490
|
+
if (style === "inline") return coerceDeclaredNumbers({ ...targetRow }, targetCollection);
|
|
6548
6491
|
const address = relationTargetAddress(targetRow, targetCollection, registry);
|
|
6549
6492
|
const path = targetCollection.slug;
|
|
6550
6493
|
return createRelationRefWithData(address, path, {
|
|
@@ -6586,7 +6529,7 @@ function toCmsRow(row, collection, registry) {
|
|
|
6586
6529
|
normalized[key] = relData.map((item) => renderTarget(isJunctionRelation(relation) ? unwrapJunctionRow(item) : item, targetCollection, "ref", registry));
|
|
6587
6530
|
} else if (relation.cardinality === "one" && typeof relData === "object" && !Array.isArray(relData)) normalized[key] = renderTarget(relData, relation.target(), "ref", registry);
|
|
6588
6531
|
}
|
|
6589
|
-
return
|
|
6532
|
+
return normalized;
|
|
6590
6533
|
}
|
|
6591
6534
|
/**
|
|
6592
6535
|
* The row REST serves: every column under its own name, with the value Postgres
|
|
@@ -6611,7 +6554,7 @@ function toRestRow(row, collection, registry) {
|
|
|
6611
6554
|
else if (relation && typeof value === "object" && value !== null) flat[key] = renderTarget(value, relation.target(), "inline", registry);
|
|
6612
6555
|
else flat[key] = coerceDeclaredNumber(value, collection.properties?.[key]);
|
|
6613
6556
|
}
|
|
6614
|
-
return
|
|
6557
|
+
return flat;
|
|
6615
6558
|
}
|
|
6616
6559
|
//#endregion
|
|
6617
6560
|
//#region src/services/FetchService.ts
|
|
@@ -9253,7 +9196,6 @@ var DatabasePoolManager = class {
|
|
|
9253
9196
|
pool.on("error", (err) => {
|
|
9254
9197
|
logger.error(`[DatabasePoolManager] Unexpected error on idle client for db ${databaseName}`, { error: err });
|
|
9255
9198
|
});
|
|
9256
|
-
guardPoolAgainstDirtyRelease(pool, `pg-pool:${databaseName}`);
|
|
9257
9199
|
this.pools.set(databaseName, pool);
|
|
9258
9200
|
return pool;
|
|
9259
9201
|
}
|
|
@@ -20814,22 +20756,14 @@ async function ensureAuthTablesExist(db, collection) {
|
|
|
20814
20756
|
$$ LANGUAGE sql STABLE
|
|
20815
20757
|
`);
|
|
20816
20758
|
});
|
|
20817
|
-
|
|
20818
|
-
|
|
20819
|
-
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
|
|
20825
|
-
"is_anonymous BOOLEAN DEFAULT FALSE NOT NULL",
|
|
20826
|
-
"metadata JSONB DEFAULT '{}' NOT NULL",
|
|
20827
|
-
"created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL",
|
|
20828
|
-
"updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL"
|
|
20829
|
-
]) await db.execute(sql`
|
|
20830
|
-
ALTER TABLE ${sql.raw(usersTableName)}
|
|
20831
|
-
ADD COLUMN IF NOT EXISTS ${sql.raw(columnDef)}
|
|
20832
|
-
`);
|
|
20759
|
+
await db.execute(sql`
|
|
20760
|
+
ALTER TABLE ${sql.raw(usersTableName)}
|
|
20761
|
+
ADD COLUMN IF NOT EXISTS is_anonymous BOOLEAN DEFAULT FALSE
|
|
20762
|
+
`);
|
|
20763
|
+
await db.execute(sql`
|
|
20764
|
+
ALTER TABLE ${sql.raw(usersTableName)}
|
|
20765
|
+
ADD COLUMN IF NOT EXISTS roles TEXT[] DEFAULT '{}' NOT NULL
|
|
20766
|
+
`);
|
|
20833
20767
|
try {
|
|
20834
20768
|
if ((await db.execute(sql`
|
|
20835
20769
|
SELECT EXISTS (
|
|
@@ -20900,34 +20834,6 @@ async function ensureAuthTablesExist(db, collection) {
|
|
|
20900
20834
|
CREATE INDEX IF NOT EXISTS idx_recovery_codes_user
|
|
20901
20835
|
ON ${sql.raw(recoveryCodesTableName)}(user_id)
|
|
20902
20836
|
`);
|
|
20903
|
-
try {
|
|
20904
|
-
const authTablePairs = [
|
|
20905
|
-
[usersSchema, resolvedTable],
|
|
20906
|
-
[authSchema, "user_identities"],
|
|
20907
|
-
[authSchema, "refresh_tokens"],
|
|
20908
|
-
[authSchema, "password_reset_tokens"],
|
|
20909
|
-
[authSchema, "app_config"],
|
|
20910
|
-
[authSchema, "mfa_factors"],
|
|
20911
|
-
[authSchema, "mfa_challenges"],
|
|
20912
|
-
[authSchema, "recovery_codes"]
|
|
20913
|
-
];
|
|
20914
|
-
for (const [schemaName, tableName] of authTablePairs) if ((await db.execute(sql`
|
|
20915
|
-
SELECT 1
|
|
20916
|
-
FROM pg_class c
|
|
20917
|
-
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
20918
|
-
WHERE n.nspname = ${schemaName}
|
|
20919
|
-
AND c.relname = ${tableName}
|
|
20920
|
-
AND c.relforcerowsecurity
|
|
20921
|
-
`)).rows.length > 0) {
|
|
20922
|
-
await db.execute(sql`
|
|
20923
|
-
ALTER TABLE ${sql.raw(`"${schemaName}"."${tableName}"`)}
|
|
20924
|
-
NO FORCE ROW LEVEL SECURITY
|
|
20925
|
-
`);
|
|
20926
|
-
logger.warn(`🔧 Cleared stale FORCE ROW LEVEL SECURITY on "${schemaName}"."${tableName}" (legacy RLS model — it binds the owner connection and breaks privileged auth writes)`);
|
|
20927
|
-
}
|
|
20928
|
-
} catch (rlsReconcileError) {
|
|
20929
|
-
logger.warn(`⚠️ Could not reconcile FORCE ROW LEVEL SECURITY on auth tables: ${rlsReconcileError instanceof Error ? rlsReconcileError.message : String(rlsReconcileError)}`);
|
|
20930
|
-
}
|
|
20931
20837
|
logger.info("✅ Auth tables ready");
|
|
20932
20838
|
} catch (error) {
|
|
20933
20839
|
logger.error("❌ Failed to create auth tables", { error });
|
|
@@ -20975,31 +20881,6 @@ var UserService = class {
|
|
|
20975
20881
|
const name = getTableName(this.usersTable);
|
|
20976
20882
|
return `"${getTableConfig(this.usersTable).schema || "public"}"."${name}"`;
|
|
20977
20883
|
}
|
|
20978
|
-
/**
|
|
20979
|
-
* Run a privileged auth write with an explicitly cleared RLS context.
|
|
20980
|
-
*
|
|
20981
|
-
* The auth services run on the base/owner connection, which by design
|
|
20982
|
-
* carries a NULL `app.user_id` so the `auth.uid() IS NULL` server-escape
|
|
20983
|
-
* in the default policies applies. That NULL is normally guaranteed by
|
|
20984
|
-
* `set_config(..., is_local = true)` resetting at transaction end — but a
|
|
20985
|
-
* GUC that survives on a pooled connection (or a connection role that
|
|
20986
|
-
* doesn't bypass RLS: FORCE ROW LEVEL SECURITY, or a non-owner role)
|
|
20987
|
-
* turns the trusted write into an RLS-scoped one and denies it with
|
|
20988
|
-
* SQLSTATE 42501. Clearing the GUCs here, transaction-locally at the
|
|
20989
|
-
* single chokepoint, makes the server context deterministic instead of
|
|
20990
|
-
* trusting whatever state the pool hands us. `auth.uid()` reads '' as
|
|
20991
|
-
* NULL via NULLIF, so '' is the server context.
|
|
20992
|
-
*/
|
|
20993
|
-
async withServerContext(fn) {
|
|
20994
|
-
return await this.db.transaction(async (tx) => {
|
|
20995
|
-
await tx.execute(sql`
|
|
20996
|
-
SELECT set_config('app.user_id', '', true),
|
|
20997
|
-
set_config('app.user_roles', '', true),
|
|
20998
|
-
set_config('app.jwt', '', true)
|
|
20999
|
-
`);
|
|
21000
|
-
return await fn(tx);
|
|
21001
|
-
});
|
|
21002
|
-
}
|
|
21003
20884
|
mapRowToUser(row) {
|
|
21004
20885
|
if (!row) return row;
|
|
21005
20886
|
const id = row.id ?? row.uid;
|
|
@@ -21097,7 +20978,7 @@ var UserService = class {
|
|
|
21097
20978
|
}
|
|
21098
20979
|
async createUser(data) {
|
|
21099
20980
|
const payload = this.mapPayload(data);
|
|
21100
|
-
const [row] = await this.
|
|
20981
|
+
const [row] = await this.db.insert(this.usersTable).values(payload).returning();
|
|
21101
20982
|
return this.mapRowToUser(row);
|
|
21102
20983
|
}
|
|
21103
20984
|
async getUserById(id) {
|
|
@@ -21136,12 +21017,12 @@ var UserService = class {
|
|
|
21136
21017
|
}));
|
|
21137
21018
|
}
|
|
21138
21019
|
async linkUserIdentity(userId, provider, providerId, profileData) {
|
|
21139
|
-
await this.
|
|
21020
|
+
await this.db.insert(this.userIdentitiesTable).values({
|
|
21140
21021
|
userId,
|
|
21141
21022
|
provider,
|
|
21142
21023
|
providerId,
|
|
21143
21024
|
profileData: profileData || null
|
|
21144
|
-
}).onConflictDoNothing({ target: [this.userIdentitiesTable.provider, this.userIdentitiesTable.providerId] })
|
|
21025
|
+
}).onConflictDoNothing({ target: [this.userIdentitiesTable.provider, this.userIdentitiesTable.providerId] });
|
|
21145
21026
|
}
|
|
21146
21027
|
async updateUser(id, data) {
|
|
21147
21028
|
const idCol = getColumn(this.usersTable, "id");
|
|
@@ -21149,13 +21030,13 @@ var UserService = class {
|
|
|
21149
21030
|
const payload = this.mapPayload(data);
|
|
21150
21031
|
const updatedAtKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
21151
21032
|
payload[updatedAtKey] = /* @__PURE__ */ new Date();
|
|
21152
|
-
const [row] = await this.
|
|
21033
|
+
const [row] = await this.db.update(this.usersTable).set(payload).where(eq(idCol, id)).returning();
|
|
21153
21034
|
return row ? this.mapRowToUser(row) : null;
|
|
21154
21035
|
}
|
|
21155
21036
|
async deleteUser(id) {
|
|
21156
21037
|
const idCol = getColumn(this.usersTable, "id");
|
|
21157
21038
|
if (!idCol) return;
|
|
21158
|
-
await this.
|
|
21039
|
+
await this.db.delete(this.usersTable).where(eq(idCol, id));
|
|
21159
21040
|
}
|
|
21160
21041
|
async listUsers() {
|
|
21161
21042
|
return (await this.db.select().from(this.usersTable)).map((row) => this.mapRowToUser(row));
|
|
@@ -21209,10 +21090,10 @@ var UserService = class {
|
|
|
21209
21090
|
if (!idCol) return;
|
|
21210
21091
|
const passwordHashColKey = getColumnKey(this.usersTable, "passwordHash", "password_hash") || "passwordHash";
|
|
21211
21092
|
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
21212
|
-
await this.
|
|
21093
|
+
await this.db.update(this.usersTable).set({
|
|
21213
21094
|
[passwordHashColKey]: passwordHash,
|
|
21214
21095
|
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
21215
|
-
}).where(eq(idCol, id))
|
|
21096
|
+
}).where(eq(idCol, id));
|
|
21216
21097
|
}
|
|
21217
21098
|
/**
|
|
21218
21099
|
* Set email verification status
|
|
@@ -21223,11 +21104,11 @@ var UserService = class {
|
|
|
21223
21104
|
const emailVerifiedColKey = getColumnKey(this.usersTable, "emailVerified", "email_verified") || "emailVerified";
|
|
21224
21105
|
const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
|
|
21225
21106
|
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
21226
|
-
await this.
|
|
21107
|
+
await this.db.update(this.usersTable).set({
|
|
21227
21108
|
[emailVerifiedColKey]: verified,
|
|
21228
21109
|
[emailVerificationTokenColKey]: null,
|
|
21229
21110
|
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
21230
|
-
}).where(eq(idCol, id))
|
|
21111
|
+
}).where(eq(idCol, id));
|
|
21231
21112
|
}
|
|
21232
21113
|
/**
|
|
21233
21114
|
* Set email verification token
|
|
@@ -21238,11 +21119,11 @@ var UserService = class {
|
|
|
21238
21119
|
const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
|
|
21239
21120
|
const emailVerificationSentAtColKey = getColumnKey(this.usersTable, "emailVerificationSentAt", "email_verification_sent_at") || "emailVerificationSentAt";
|
|
21240
21121
|
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
21241
|
-
await this.
|
|
21122
|
+
await this.db.update(this.usersTable).set({
|
|
21242
21123
|
[emailVerificationTokenColKey]: token,
|
|
21243
21124
|
[emailVerificationSentAtColKey]: token ? /* @__PURE__ */ new Date() : null,
|
|
21244
21125
|
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
21245
|
-
}).where(eq(idCol, id))
|
|
21126
|
+
}).where(eq(idCol, id));
|
|
21246
21127
|
}
|
|
21247
21128
|
/**
|
|
21248
21129
|
* Find user by email verification token
|
|
@@ -21287,22 +21168,22 @@ var UserService = class {
|
|
|
21287
21168
|
async setUserRoles(userId, roleIds) {
|
|
21288
21169
|
const usersTableName = this.getQualifiedUsersTableName();
|
|
21289
21170
|
const rolesArray = `{${roleIds.join(",")}}`;
|
|
21290
|
-
await this.
|
|
21171
|
+
await this.db.execute(sql`
|
|
21291
21172
|
UPDATE ${sql.raw(usersTableName)}
|
|
21292
21173
|
SET roles = ${rolesArray}::text[], updated_at = NOW()
|
|
21293
21174
|
WHERE id = ${userId}
|
|
21294
|
-
`)
|
|
21175
|
+
`);
|
|
21295
21176
|
}
|
|
21296
21177
|
/**
|
|
21297
21178
|
* Assign a specific role to new user (appends if not present)
|
|
21298
21179
|
*/
|
|
21299
21180
|
async assignDefaultRole(userId, roleId) {
|
|
21300
21181
|
const usersTableName = this.getQualifiedUsersTableName();
|
|
21301
|
-
await this.
|
|
21182
|
+
await this.db.execute(sql`
|
|
21302
21183
|
UPDATE ${sql.raw(usersTableName)}
|
|
21303
21184
|
SET roles = array_append(roles, ${roleId}), updated_at = NOW()
|
|
21304
21185
|
WHERE id = ${userId} AND NOT (${roleId} = ANY(roles))
|
|
21305
|
-
`)
|
|
21186
|
+
`);
|
|
21306
21187
|
}
|
|
21307
21188
|
/**
|
|
21308
21189
|
* Get user with their roles
|
|
@@ -22952,6 +22833,6 @@ function createPostgresAdapter(pgConfig) {
|
|
|
22952
22833
|
};
|
|
22953
22834
|
}
|
|
22954
22835
|
//#endregion
|
|
22955
|
-
export { AuthenticatedPostgresBackendDriver, BackupToolError, BranchService, DatabasePoolManager, DrizzleConditionBuilder, PostgresBackendDriver, PostgresCollectionRegistry, PostgresConditionBuilder, PostgresRealtimeProvider, RealtimeService, appConfig, backupCronConfigFromEnv, buildBackupFilename, buildPgDumpArgs, buildPgRestoreArgs, checkToolServerCompatibility, createAuthSchema, createBackupCron, createDirectDatabaseConnection, createDump, createPostgresAdapter, createPostgresBootstrapper, createPostgresDatabaseConnection, createPostgresWebSocket, createReadReplicaConnection, detectToolMajor, ensureDatabaseExists, generateSchema, getServerVersionMajor,
|
|
22836
|
+
export { AuthenticatedPostgresBackendDriver, BackupToolError, BranchService, DatabasePoolManager, DrizzleConditionBuilder, PostgresBackendDriver, PostgresCollectionRegistry, PostgresConditionBuilder, PostgresRealtimeProvider, RealtimeService, appConfig, backupCronConfigFromEnv, buildBackupFilename, buildPgDumpArgs, buildPgRestoreArgs, checkToolServerCompatibility, createAuthSchema, createBackupCron, createDirectDatabaseConnection, createDump, createPostgresAdapter, createPostgresBootstrapper, createPostgresDatabaseConnection, createPostgresWebSocket, createReadReplicaConnection, detectToolMajor, ensureDatabaseExists, generateSchema, getServerVersionMajor, joinStorageKey, listBackups, magicLinkTokens, magicLinkTokensRelations, mfaChallenges, mfaChallengesRelations, mfaFactors, mfaFactorsRelations, parseBackupDestination, parseBackupTimestamp, parseDbNameFromUrl, parsePgToolMajor, passwordResetTokens, passwordResetTokensRelations, preflight, pruneBackups, recoveryCodes, recoveryCodesRelations, refreshTokens, refreshTokensRelations, resolveConnectionString, resolvePgBinary, restoreDump, selectBackupsToPrune, serverVersionNumToMajor, uploadBackup, userIdentities, userIdentitiesRelations, users, usersRelations, usersSchema, withDatabaseName };
|
|
22956
22837
|
|
|
22957
22838
|
//# sourceMappingURL=index.es.js.map
|