@stacksjs/auth 0.75.461 → 0.75.464

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.
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The configured addresses, normalized. Throws on a malformed or repeated
3
+ * address so a typo fails the deploy rather than granting nothing.
4
+ */
5
+ export declare function adminEmails(list?: unknown): string[];
6
+ /** "ada.lovelace@…" → "Ada Lovelace": a name until the person (or their identity provider) sets one. */
7
+ export declare function nameFromEmail(email: string): string;
8
+ /** Make every configured address an administrator. Idempotent: a second run reports each one `unchanged`. */
9
+ export declare function provisionAdmins(options?: ProvisionAdminsOptions): Promise<ProvisionedAdmin[]>;
10
+ export declare const databaseAdminAccounts: AdminAccountStore;
11
+ export declare interface AdminRole { name: string, guard?: string }
12
+ /** The accounts side, swappable for tests and for applications whose users carry more than a row. */
13
+ export declare interface AdminAccountStore {
14
+ findUserId: (email: string) => Promise<number | null>
15
+ createUser: (account: { email: string, name: string }) => Promise<number>
16
+ }
17
+ export declare interface ProvisionAdminsOptions {
18
+ emails?: readonly string[]
19
+ role?: AdminRole | false
20
+ accounts?: Partial<AdminAccountStore>
21
+ afterEach?: (admin: { userId: number, email: string, created: boolean }) => Promise<boolean | void>
22
+ }
23
+ export declare interface ProvisionedAdmin {
24
+ email: string
25
+ userId: number
26
+ outcome: 'created' | 'granted' | 'unchanged'
27
+ }
package/dist/admins.js ADDED
@@ -0,0 +1 @@
1
+ import{randomBytes}from"node:crypto";import{config}from"@stacksjs/config";import{db,sqlDateTime}from"@stacksjs/database/runtime";import{makeHash}from"@stacksjs/security";import{findAuthUserRowByEmail,normalizeAuthEmail}from"./credential-user";import{assignRole,createRole,findRole,hasFreshRole}from"./rbac";const EMAIL=/^[^\s@]{1,64}@[^\s@]{1,190}\.[^\s@]{2,63}$/;export function adminEmails(list=config.auth?.admins){if(list===void 0||list===null)return[];if(!Array.isArray(list))throw TypeError("auth.admins must be a list of email addresses");const emails=list.map((value)=>normalizeAuthEmail(String(value??""))),invalid=emails.find((email)=>email.length>254||!EMAIL.test(email));if(invalid!==void 0)throw TypeError(`auth.admins lists an invalid email address: "${invalid}"`);const repeated=emails.find((email,index)=>emails.indexOf(email)!==index);if(repeated)throw TypeError(`auth.admins lists ${repeated} twice`);return emails}export function nameFromEmail(email){const words=email.split("@")[0].replace(/\+.*$/,"").split(/[._-]+/).filter(Boolean);return words.length?words.map((word)=>word[0].toUpperCase()+word.slice(1)).join(" "):email}export const databaseAdminAccounts={async findUserId(email){const row=await findAuthUserRowByEmail(email);return row?Number(row.id):null},async createUser({email,name}){const now=sqlDateTime();await db.insertInto("users").values({email,name,email_verified_at:now,created_at:now,updated_at:now,password:await makeHash(randomBytes(32).toString("hex"),{algorithm:"bcrypt"})}).execute();const row=await findAuthUserRowByEmail(email);if(!row)throw Error(`Could not read back the account created for ${email}`);return Number(row.id)}};export async function provisionAdmins(options={}){const emails=adminEmails(options.emails??config.auth?.admins),configured=options.role??config.auth?.adminRole??{name:"admin",guard:"web"},role=configured===!1?null:{name:configured.name,guard:configured.guard??"web"},accounts={...databaseAdminAccounts,...options.accounts};if(role&&emails.length&&!await findRole(role.name,role.guard))await createRole(role.name,role.guard,"Administrators named in config.auth.admins");const results=[];for(const email of emails){const existing=await accounts.findUserId(email),userId=existing??await accounts.createUser({email,name:nameFromEmail(email)});let changed=!1;if(role&&!await hasFreshRole(userId,role.name,role.guard)){await assignRole(userId,role.name,role.guard);changed=!0}if(options.afterEach&&await options.afterEach({userId,email,created:existing===null})===!0)changed=!0;results.push({email,userId,outcome:existing===null?"created":changed?"granted":"unchanged"})}return results}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type { AdminAccountStore, AdminRole, ProvisionAdminsOptions, ProvisionedAdmin } from './admins';
1
2
  export type { SeedDefaultRolesResult } from './rbac-seed';
2
3
  export * from './authentication';
3
4
  export * from './impersonation';
@@ -47,6 +48,7 @@ export * from './permissions';
47
48
  export * from './rbac';
48
49
  export { createBqbRbacStore } from './rbac-store-bqb';
49
50
  export { DEFAULT_ROLE_PACKS, seedDefaultRoles } from './rbac-seed';
51
+ export { adminEmails, databaseAdminAccounts, nameFromEmail, provisionAdmins } from './admins';
50
52
  // Email Verification
51
53
  export * from './email-verification';
52
54
  // Session-based Authentication (SPA Cookie Auth)
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./authentication";export*from"./impersonation";export{requestImpersonation}from"./impersonation-auth";export*from"./impersonation-store";export*from"./authenticator";export*from"./client";export*from"./credential-user";export*from"./middleware";export*from"./oauth-authorization";export*from"./oauth-authorization-endpoint";export*from"./oauth-authorization-requests";export*from"./oauth-authorization-response";export*from"./oauth-authorization-codes";export*from"./oauth-browser-session";export*from"./oauth-client-registration";export*from"./oauth-consent";export*from"./oauth-delegated-access";export*from"./oauth-grants";export*from"./oauth-introspection";export*from"./oauth-metadata";export*from"./oauth-provider";export*from"./oauth-pruning";export*from"./oauth-pkce";export*from"./oauth-revocation";export*from"./oauth-token-exchange";export*from"./oauth-token-endpoint";export*from"./oauth-token-request";export*from"./oauth-token-response";export*from"./rate-limiter";export*from"./magic-link";export*from"./passkey";export*from"./passkeys";export*from"./password/reset";export*from"./password/reset-token";export*from"./register";export*from"./user";export*from"./tokens";export*from"./gate";export*from"./policy";export*from"./authorizable";export*from"./permissions";export*from"./rbac";export{createBqbRbacStore}from"./rbac-store-bqb";export{DEFAULT_ROLE_PACKS,seedDefaultRoles}from"./rbac-seed";export*from"./email-verification";export*from"./session-auth";export*from"./cookie-auth";export*from"./browser-session";export*from"./request-token";export*from"./page-gate";export*from"./socials";export*from"./session-handoff";export{generateTOTP,verifyTOTP,generateTOTPSecret,totpKeyUri}from"@stacksjs/ts-auth";export*from"./two-factor";export*from"./team";export*from"./referrals";export*from"./oauth-dynamic-registration";export*from"./oauth-protected-resource";export*from"./oauth-userinfo";export*from"./oauth-server";
1
+ export*from"./authentication";export*from"./impersonation";export{requestImpersonation}from"./impersonation-auth";export*from"./impersonation-store";export*from"./authenticator";export*from"./client";export*from"./credential-user";export*from"./middleware";export*from"./oauth-authorization";export*from"./oauth-authorization-endpoint";export*from"./oauth-authorization-requests";export*from"./oauth-authorization-response";export*from"./oauth-authorization-codes";export*from"./oauth-browser-session";export*from"./oauth-client-registration";export*from"./oauth-consent";export*from"./oauth-delegated-access";export*from"./oauth-grants";export*from"./oauth-introspection";export*from"./oauth-metadata";export*from"./oauth-provider";export*from"./oauth-pruning";export*from"./oauth-pkce";export*from"./oauth-revocation";export*from"./oauth-token-exchange";export*from"./oauth-token-endpoint";export*from"./oauth-token-request";export*from"./oauth-token-response";export*from"./rate-limiter";export*from"./magic-link";export*from"./passkey";export*from"./passkeys";export*from"./password/reset";export*from"./password/reset-token";export*from"./register";export*from"./user";export*from"./tokens";export*from"./gate";export*from"./policy";export*from"./authorizable";export*from"./permissions";export*from"./rbac";export{createBqbRbacStore}from"./rbac-store-bqb";export{DEFAULT_ROLE_PACKS,seedDefaultRoles}from"./rbac-seed";export{adminEmails,databaseAdminAccounts,nameFromEmail,provisionAdmins}from"./admins";export*from"./email-verification";export*from"./session-auth";export*from"./cookie-auth";export*from"./browser-session";export*from"./request-token";export*from"./page-gate";export*from"./socials";export*from"./session-handoff";export{generateTOTP,verifyTOTP,generateTOTPSecret,totpKeyUri}from"@stacksjs/ts-auth";export*from"./two-factor";export*from"./team";export*from"./referrals";export*from"./oauth-dynamic-registration";export*from"./oauth-protected-resource";export*from"./oauth-userinfo";export*from"./oauth-server";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/auth",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.461",
5
+ "version": "0.75.464",
6
6
  "description": "A more simplistic way to authenticate.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -59,19 +59,19 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@stacksjs/bun-router": "^0.1.24",
62
- "@stacksjs/cache": "0.75.461",
63
- "@stacksjs/config": "0.75.461",
64
- "@stacksjs/database": "0.75.461",
65
- "@stacksjs/email": "0.75.461",
66
- "@stacksjs/env": "0.75.461",
67
- "@stacksjs/error-handling": "0.75.461",
68
- "@stacksjs/logging": "0.75.461",
69
- "@stacksjs/orm": "0.75.461",
70
- "@stacksjs/path": "0.75.461",
71
- "@stacksjs/router": "0.75.461",
72
- "@stacksjs/security": "0.75.461",
73
- "@stacksjs/socials": "0.75.461",
74
- "@stacksjs/storage": "0.75.461",
62
+ "@stacksjs/cache": "0.75.464",
63
+ "@stacksjs/config": "0.75.464",
64
+ "@stacksjs/database": "0.75.464",
65
+ "@stacksjs/email": "0.75.464",
66
+ "@stacksjs/env": "0.75.464",
67
+ "@stacksjs/error-handling": "0.75.464",
68
+ "@stacksjs/logging": "0.75.464",
69
+ "@stacksjs/orm": "0.75.464",
70
+ "@stacksjs/path": "0.75.464",
71
+ "@stacksjs/router": "0.75.464",
72
+ "@stacksjs/security": "0.75.464",
73
+ "@stacksjs/socials": "0.75.464",
74
+ "@stacksjs/storage": "0.75.464",
75
75
  "@stacksjs/ts-auth": "^0.4.7",
76
76
  "ts-qr-codes": "^0.1.8"
77
77
  },