@stacksjs/database 0.70.351 → 0.70.352
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-tables.d.ts +20 -0
- package/dist/auth-tables.js +7 -2
- package/package.json +10 -10
package/dist/auth-tables.d.ts
CHANGED
|
@@ -42,6 +42,26 @@ export declare function usersTwoFactorColumnsSql(sql: SqlHelpers): string[];
|
|
|
42
42
|
* stacksjs/status#1 Phase 9).
|
|
43
43
|
*/
|
|
44
44
|
export declare function usersStripeIdSql(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Defensive ALTERs guaranteeing the device columns on
|
|
47
|
+
* `oauth_access_tokens` - `user_agent` and `ip_address`.
|
|
48
|
+
*
|
|
49
|
+
* They exist for one feature and it cannot be built without them: **a list of
|
|
50
|
+
* your own sessions that you can revoke.** Without something to recognise a row
|
|
51
|
+
* by, that page is a column of identical timestamps and "revoke" is guesswork,
|
|
52
|
+
* so the page nobody can act on is the page nobody builds - which is why
|
|
53
|
+
* "somebody is signed in as me on a laptop I sold" has no answer in most
|
|
54
|
+
* self-hosted software.
|
|
55
|
+
*
|
|
56
|
+
* Nullable, and populated only by callers that have a request to read them
|
|
57
|
+
* from. A token minted by a script has no user agent and no meaningful address,
|
|
58
|
+
* and inventing one would make the list less trustworthy rather than more.
|
|
59
|
+
*
|
|
60
|
+
* Same pure-builder + try/catch-swallow pattern as the `users` guarantees
|
|
61
|
+
* above, for the same reason: no generated migration creates this table, so
|
|
62
|
+
* both schema paths have to be able to add to it idempotently.
|
|
63
|
+
*/
|
|
64
|
+
export declare function oauthAccessTokenDeviceColumnsSql(): string[];
|
|
45
65
|
/**
|
|
46
66
|
* Runs every `users` guarantee-column ALTER (email_verified_at,
|
|
47
67
|
* password_changed_at, two_factor_secret, two_factor_enabled,
|
package/dist/auth-tables.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import process from"node:process";import{randomBytes}from"node:crypto";import{log}from"@stacksjs/logging";import{env as envVars}from"@stacksjs/env";import{db}from"./utils";import{sqlHelpers}from"./sql-helpers";import{indexSqlForDialect}from"./dialect";function getDbDriver(){return envVars.DB_CONNECTION||"sqlite"}export function usersEmailVerifiedAtSql(sql){return`ALTER TABLE users ADD COLUMN email_verified_at ${sql.nullableTimestamp}`}export function usersPasswordChangedAtSql(sql){return`ALTER TABLE users ADD COLUMN password_changed_at ${sql.nullableTimestamp}`}export function usersTwoFactorColumnsSql(sql){return["ALTER TABLE users ADD COLUMN two_factor_secret VARCHAR(255)",`ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN NOT NULL DEFAULT ${sql.boolFalse}`,"ALTER TABLE users ADD COLUMN two_factor_last_used_step BIGINT"]}export function usersStripeIdSql(){return"ALTER TABLE users ADD COLUMN stripe_id VARCHAR(255)"}export async function ensureUsersAuthColumns(sql,options={}){const alters=[usersEmailVerifiedAtSql(sql),usersPasswordChangedAtSql(sql),...usersTwoFactorColumnsSql(sql),usersStripeIdSql()];for(const alterSql of alters)try{await db.unsafe(alterSql).execute()}catch{if(options.verbose)log.debug(`[auth-tables] Skipped (already applied or users missing): ${alterSql}`)}try{await db.unsafe(indexSqlForDialect("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_stripe_id ON users(stripe_id)",getDbDriver())).execute()}catch{if(options.verbose)log.debug("[auth-tables] Skipped users.stripe_id unique index (already applied or users missing)")}}export async function migrateAuthTables(options={}){const dbDriver=getDbDriver(),sql=sqlHelpers(dbDriver),{isPostgres,boolTrue,now,pkColumn,nullableTimestamp,datetime}=sql;if(options.verbose)log.info(`Creating auth tables for ${dbDriver}...`);try{if(options.verbose)log.info("Creating oauth_clients table...");await db.unsafe(`
|
|
1
|
+
import process from"node:process";import{randomBytes}from"node:crypto";import{log}from"@stacksjs/logging";import{env as envVars}from"@stacksjs/env";import{db}from"./utils";import{sqlHelpers}from"./sql-helpers";import{indexSqlForDialect}from"./dialect";function getDbDriver(){return envVars.DB_CONNECTION||"sqlite"}export function usersEmailVerifiedAtSql(sql){return`ALTER TABLE users ADD COLUMN email_verified_at ${sql.nullableTimestamp}`}export function usersPasswordChangedAtSql(sql){return`ALTER TABLE users ADD COLUMN password_changed_at ${sql.nullableTimestamp}`}export function usersTwoFactorColumnsSql(sql){return["ALTER TABLE users ADD COLUMN two_factor_secret VARCHAR(255)",`ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN NOT NULL DEFAULT ${sql.boolFalse}`,"ALTER TABLE users ADD COLUMN two_factor_last_used_step BIGINT"]}export function usersStripeIdSql(){return"ALTER TABLE users ADD COLUMN stripe_id VARCHAR(255)"}export function oauthAccessTokenDeviceColumnsSql(){return["ALTER TABLE oauth_access_tokens ADD COLUMN user_agent VARCHAR(255)","ALTER TABLE oauth_access_tokens ADD COLUMN ip_address VARCHAR(45)"]}export async function ensureUsersAuthColumns(sql,options={}){const alters=[usersEmailVerifiedAtSql(sql),usersPasswordChangedAtSql(sql),...usersTwoFactorColumnsSql(sql),usersStripeIdSql()];for(const alterSql of alters)try{await db.unsafe(alterSql).execute()}catch{if(options.verbose)log.debug(`[auth-tables] Skipped (already applied or users missing): ${alterSql}`)}try{await db.unsafe(indexSqlForDialect("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_stripe_id ON users(stripe_id)",getDbDriver())).execute()}catch{if(options.verbose)log.debug("[auth-tables] Skipped users.stripe_id unique index (already applied or users missing)")}}export async function migrateAuthTables(options={}){const dbDriver=getDbDriver(),sql=sqlHelpers(dbDriver),{isPostgres,boolTrue,now,pkColumn,nullableTimestamp,datetime}=sql;if(options.verbose)log.info(`Creating auth tables for ${dbDriver}...`);try{if(options.verbose)log.info("Creating oauth_clients table...");await db.unsafe(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS oauth_clients (
|
|
3
3
|
${pkColumn},
|
|
4
4
|
name VARCHAR(255) NOT NULL,
|
|
@@ -21,10 +21,15 @@ import process from"node:process";import{randomBytes}from"node:crypto";import{lo
|
|
|
21
21
|
scopes TEXT,
|
|
22
22
|
revoked BOOLEAN NOT NULL DEFAULT ${sql.boolFalse},
|
|
23
23
|
expires_at ${nullableTimestamp},
|
|
24
|
+
-- What the browser called itself and where it came from, so a person
|
|
25
|
+
-- can recognise their own sessions well enough to revoke one. Null for
|
|
26
|
+
-- a token minted by a script, which has neither.
|
|
27
|
+
user_agent VARCHAR(255),
|
|
28
|
+
ip_address VARCHAR(45),
|
|
24
29
|
created_at ${datetime} DEFAULT CURRENT_TIMESTAMP,
|
|
25
30
|
updated_at ${nullableTimestamp}
|
|
26
31
|
)
|
|
27
|
-
`).execute();await createTokenIndex("idx_oauth_access_tokens_token","oauth_access_tokens","token");if(options.verbose)log.info("Creating oauth_refresh_tokens table...");await db.unsafe(`
|
|
32
|
+
`).execute();await createTokenIndex("idx_oauth_access_tokens_token","oauth_access_tokens","token");for(const alterSql of oauthAccessTokenDeviceColumnsSql())try{await db.unsafe(alterSql).execute()}catch{if(options.verbose)log.debug(`[auth-tables] Skipped (already applied): ${alterSql}`)}if(options.verbose)log.info("Creating oauth_refresh_tokens table...");await db.unsafe(`
|
|
28
33
|
CREATE TABLE IF NOT EXISTS oauth_refresh_tokens (
|
|
29
34
|
${pkColumn},
|
|
30
35
|
access_token_id INTEGER NOT NULL,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/database",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.352",
|
|
6
6
|
"description": "The Stacks database integration.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"dynamodb-tooling": "^0.3.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@stacksjs/cli": "0.70.
|
|
69
|
-
"@stacksjs/config": "0.70.
|
|
70
|
-
"@stacksjs/logging": "0.70.
|
|
71
|
-
"@stacksjs/router": "0.70.
|
|
68
|
+
"@stacksjs/cli": "0.70.352",
|
|
69
|
+
"@stacksjs/config": "0.70.352",
|
|
70
|
+
"@stacksjs/logging": "0.70.352",
|
|
71
|
+
"@stacksjs/router": "0.70.352",
|
|
72
72
|
"better-dx": "^0.2.17",
|
|
73
|
-
"@stacksjs/path": "0.70.
|
|
74
|
-
"@stacksjs/query-builder": "0.70.
|
|
75
|
-
"@stacksjs/storage": "0.70.
|
|
76
|
-
"@stacksjs/strings": "0.70.
|
|
77
|
-
"@stacksjs/utils": "0.70.
|
|
73
|
+
"@stacksjs/path": "0.70.352",
|
|
74
|
+
"@stacksjs/query-builder": "0.70.352",
|
|
75
|
+
"@stacksjs/storage": "0.70.352",
|
|
76
|
+
"@stacksjs/strings": "0.70.352",
|
|
77
|
+
"@stacksjs/utils": "0.70.352"
|
|
78
78
|
}
|
|
79
79
|
}
|