@lunora/auth 1.0.0-alpha.27 → 1.0.0-alpha.29

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/index.d.mts CHANGED
@@ -575,4 +575,4 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
575
575
  * with the same 60s cookie cache as `rolling`.
576
576
  */
577
577
  declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
578
- export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthInvitation, type AuthMember, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTimestamp, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
578
+ export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthConfigInfo, type AuthInvitation, type AuthMember, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
package/dist/index.d.ts CHANGED
@@ -575,4 +575,4 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
575
575
  * with the same 60s cookie cache as `rolling`.
576
576
  */
577
577
  declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
578
- export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthInvitation, type AuthMember, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTimestamp, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
578
+ export { type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthCapabilities, type AuthConfigInfo, type AuthInvitation, type AuthMember, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, type LunoraAuthOptions, type SessionPolicy, compileMigrationsSql, createAuthAdmin, ensureMigrated, handleAuthRequest, sessionPresets, validateSessionPolicy };
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  export { lunoraAuthAdapter, lunoraD1Adapter } from './adapter.mjs';
2
- export { LunoraAuthAdminError, createAuthAdmin } from './packem_shared/LunoraAuthAdminError-D4L7n6gN.mjs';
3
- export { createAuth, resolveAuthOptions } from './packem_shared/createAuth-BVMMllTm.mjs';
2
+ export { LunoraAuthAdminError, createAuthAdmin } from './packem_shared/LunoraAuthAdminError-CReJPMkx.mjs';
3
+ export { createAuth, resolveAuthOptions } from './packem_shared/createAuth-s4i7WhAh.mjs';
4
4
  export { DEFAULT_AUTH_BASE_PATH, handleAuthRequest } from './packem_shared/DEFAULT_AUTH_BASE_PATH-DjcUWEQl.mjs';
5
5
  export { LunoraAuthHeadersError, withAuthPlugins } from './middleware.mjs';
6
- export { compileMigrationsSql, ensureMigrated } from './packem_shared/compileMigrationsSql-B9bj-mJv.mjs';
6
+ export { compileMigrationsSql, ensureMigrated } from './packem_shared/compileMigrationsSql-Dl5N8z5q.mjs';
7
7
  export { default as authTables } from './schema.mjs';
8
8
  export { sessionPresets, validateSessionPolicy } from './packem_shared/sessionPresets-Dwwd74_J.mjs';
9
9
  export { createSqlAuthStore, d1Executor } from './sql-store.mjs';
@@ -74,6 +74,17 @@ const asAdminError = (error) => {
74
74
  const createAuthAdmin = (auth, options = {}) => {
75
75
  const context = auth.$context;
76
76
  const features = options.features ?? {};
77
+ const deriveCapabilities = (authOptions) => {
78
+ const ids = new Set((authOptions.plugins ?? []).map((plugin) => plugin.id));
79
+ const has = (id) => ids.has(id);
80
+ return {
81
+ accounts: features.accounts ?? true,
82
+ admin: features.admin ?? has("admin"),
83
+ organization: features.organization ?? has("organization"),
84
+ passkey: features.passkey ?? has("passkey"),
85
+ twoFactor: features.twoFactor ?? has("two-factor")
86
+ };
87
+ };
77
88
  const withContext = async (function_) => {
78
89
  try {
79
90
  return await function_(await context);
@@ -98,9 +109,18 @@ const createAuthAdmin = (auth, options = {}) => {
98
109
  };
99
110
  return {
100
111
  banUser: ({ expiresInSeconds, reason, userId }) => withContext(async (context_) => {
101
- const seconds = typeof expiresInSeconds === "number" && Number.isFinite(expiresInSeconds) ? Math.min(Math.trunc(expiresInSeconds), MAX_BAN_SECONDS) : 0;
102
- const banExpires = seconds > 0 ? new Date(Date.now() + seconds * 1e3) : void 0;
112
+ let banExpires = null;
113
+ if (expiresInSeconds !== void 0) {
114
+ if (!Number.isInteger(expiresInSeconds) || expiresInSeconds <= 0) {
115
+ throw new LunoraAuthAdminError("expiresInSeconds must be a positive finite integer", "INVALID_BAN_SECONDS");
116
+ }
117
+ const seconds = Math.min(expiresInSeconds, MAX_BAN_SECONDS);
118
+ banExpires = new Date(Date.now() + seconds * 1e3);
119
+ }
103
120
  const user = await context_.internalAdapter.updateUser(userId, {
121
+ // `null` (not `undefined`) for a permanent ban so the adapter clears any prior
122
+ // `banExpires` rather than skipping it — otherwise a temp-ban-then-permanent-ban
123
+ // escalation leaves the old expiry and the "permanent" ban silently lapses.
104
124
  banExpires,
105
125
  banned: true,
106
126
  banReason: reason ?? "No reason"
@@ -111,17 +131,7 @@ const createAuthAdmin = (auth, options = {}) => {
111
131
  cancelInvitation: ({ invitationId }) => withContext(async (context_) => {
112
132
  await context_.adapter.delete({ model: "invitation", where: [{ field: "id", value: invitationId }] });
113
133
  }),
114
- capabilities: () => withContext((context_) => {
115
- const ids = new Set((context_.options.plugins ?? []).map((plugin) => plugin.id));
116
- const has = (id) => ids.has(id);
117
- return Promise.resolve({
118
- accounts: features.accounts ?? true,
119
- admin: features.admin ?? has("admin"),
120
- organization: features.organization ?? has("organization"),
121
- passkey: features.passkey ?? has("passkey"),
122
- twoFactor: features.twoFactor ?? has("two-factor")
123
- });
124
- }),
134
+ capabilities: () => withContext((context_) => Promise.resolve(deriveCapabilities(context_.options))),
125
135
  // ── Directly add an existing user to an org (no invitation/acceptance). ──
126
136
  addMember: ({ organizationId, role, userId }) => withContext(async (context_) => {
127
137
  const member = await context_.adapter.create({
@@ -141,15 +151,8 @@ const createAuthAdmin = (auth, options = {}) => {
141
151
  // only from the resolved better-auth options (no DB, no secrets).
142
152
  config: () => withContext((context_) => {
143
153
  const authOptions = context_.options;
154
+ const capabilities = deriveCapabilities(authOptions);
144
155
  const ids = new Set((authOptions.plugins ?? []).map((plugin) => plugin.id));
145
- const has = (id) => ids.has(id);
146
- const capabilities = {
147
- accounts: features.accounts ?? true,
148
- admin: features.admin ?? has("admin"),
149
- organization: features.organization ?? has("organization"),
150
- passkey: features.passkey ?? has("passkey"),
151
- twoFactor: features.twoFactor ?? has("two-factor")
152
- };
153
156
  const tables = getAuthTables(authOptions);
154
157
  const session = authOptions.session ?? {};
155
158
  const rateLimit = authOptions.rateLimit ?? {};
@@ -1,5 +1,5 @@
1
1
  import { getMigrations } from 'better-auth/db/migration';
2
- import { resolveAuthOptions } from './createAuth-BVMMllTm.mjs';
2
+ import { resolveAuthOptions } from './createAuth-s4i7WhAh.mjs';
3
3
 
4
4
  const migrating = /* @__PURE__ */ new WeakMap();
5
5
  const ensureMigrated = async (auth) => {
@@ -7,21 +7,6 @@ const isWeakSecret = (secret) => {
7
7
  const trimmedLength = typeof secret === "string" ? secret.trim().length : 0;
8
8
  return trimmedLength > 0 && trimmedLength < MIN_SECRET_LENGTH;
9
9
  };
10
- const isHttpsBaseUrl = (baseURL) => {
11
- if (typeof baseURL === "string") {
12
- return baseURL.startsWith("https://");
13
- }
14
- if (baseURL && typeof baseURL === "object") {
15
- if (baseURL.protocol === "https") {
16
- return true;
17
- }
18
- if (baseURL.protocol === "http") {
19
- return false;
20
- }
21
- return typeof baseURL.fallback === "string" && baseURL.fallback.startsWith("https://");
22
- }
23
- return false;
24
- };
25
10
  const isExplicitHttpBaseUrl = (baseURL) => {
26
11
  if (typeof baseURL === "string") {
27
12
  return baseURL.toLowerCase().startsWith("http://");
@@ -40,7 +25,7 @@ const isExplicitHttpBaseUrl = (baseURL) => {
40
25
  const hardenAuthOptions = (options) => {
41
26
  if (isWeakSecret(options.secret)) {
42
27
  const message = `@lunora/auth: AUTH_SECRET is only ${String(options.secret?.trim().length)} characters. Use at least ${String(MIN_SECRET_LENGTH)} for a brute-force-resistant secret — generate one with \`openssl rand -hex 32\`.`;
43
- if (isHttpsBaseUrl(options.baseURL)) {
28
+ if (!isExplicitHttpBaseUrl(options.baseURL)) {
44
29
  throw new LunoraError("INTERNAL", message);
45
30
  }
46
31
  console.warn(message);
@@ -28,7 +28,12 @@ const verifyTurnstile = async ({
28
28
  if (!response.ok) {
29
29
  throw new LunoraError("SERVICE_UNAVAILABLE", `turnstile siteverify returned ${String(response.status)}`, { status: 503 });
30
30
  }
31
- const raw = await response.json();
31
+ let raw;
32
+ try {
33
+ raw = await response.json();
34
+ } catch (error) {
35
+ throw new LunoraError("SERVICE_UNAVAILABLE", "turnstile siteverify returned a non-JSON body", { cause: error, status: 503 });
36
+ }
32
37
  const action = asString(raw.action);
33
38
  const hostname = asString(raw.hostname);
34
39
  const errorCodes = asStringArray(raw["error-codes"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/auth",
3
- "version": "1.0.0-alpha.27",
3
+ "version": "1.0.0-alpha.29",
4
4
  "description": "Auth for Lunora — a thin better-auth wrapper: email/password, OAuth, plugins, D1-backed",
5
5
  "keywords": [
6
6
  "auth",
@@ -83,9 +83,9 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@better-auth/passkey": "^1.6.23",
86
- "@lunora/errors": "1.0.0-alpha.3",
87
- "@lunora/server": "1.0.0-alpha.21",
88
- "@lunora/values": "1.0.0-alpha.6",
86
+ "@lunora/errors": "1.0.0-alpha.4",
87
+ "@lunora/server": "1.0.0-alpha.23",
88
+ "@lunora/values": "1.0.0-alpha.7",
89
89
  "better-auth": "^1.6.23"
90
90
  },
91
91
  "engines": {