@mesob/auth-hono 0.5.0 → 0.5.2

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.
@@ -1,7 +1,7 @@
1
1
  import * as hono from 'hono';
2
2
  import { OpenAPIHono } from '@hono/zod-openapi';
3
3
  import { PermissionTree } from '@mesob/common';
4
- import { D as Database } from './index-D8OE85f8.js';
4
+ import { D as Database } from './index-Dhe5obDc.js';
5
5
 
6
6
  type Tenant = {
7
7
  id: string;
@@ -89,6 +89,12 @@ type PhoneConfig = VerificationConfig & {
89
89
  phoneRegex?: RegExp | string;
90
90
  };
91
91
  type EmailConfig = VerificationConfig;
92
+ type SignUpConfig = {
93
+ enabled: boolean;
94
+ emailEnabled: boolean;
95
+ phoneEnabled: boolean;
96
+ allowedEmailDomains?: readonly string[];
97
+ };
92
98
  type SessionConfig = {
93
99
  /** Default session duration (e.g., '7d', '30d'). Default: '7d' */
94
100
  expiresIn: string;
@@ -147,6 +153,7 @@ type AuthConfig = {
147
153
  session: SessionConfig;
148
154
  email: EmailConfig;
149
155
  phone: PhoneConfig;
156
+ signUp?: SignUpConfig;
150
157
  security?: SecurityConfig;
151
158
  };
152
159
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { A as AuthConfig, M as MesobAuth } from './index-DwIwuvVj.js';
2
- export { a as SendInvitationParams, b as SendVerificationOTPParams, c as Session, S as SessionStatus, T as Tenant, U as User } from './index-DwIwuvVj.js';
3
- import { D as Database } from './index-D8OE85f8.js';
4
- export { c as createDatabase } from './index-D8OE85f8.js';
1
+ import { A as AuthConfig, M as MesobAuth } from './index-CDgzxZzO.js';
2
+ export { a as SendInvitationParams, b as SendVerificationOTPParams, c as Session, S as SessionStatus, T as Tenant, U as User } from './index-CDgzxZzO.js';
3
+ import { D as Database } from './index-Dhe5obDc.js';
4
+ export { c as createDatabase } from './index-Dhe5obDc.js';
5
5
  export { cleanupExpiredData, cleanupExpiredSessions, cleanupExpiredVerifications } from './lib/cleanup.js';
6
6
  export { hasPermission, hasPermissionThrow } from './lib/has-role-permission.js';
7
7
  import * as hono from 'hono';
package/dist/index.js CHANGED
@@ -1283,6 +1283,19 @@ var checkAccountHandler = async (c) => {
1283
1283
  const resolvedTenantId = ensureTenantId(config, tenantId);
1284
1284
  const { username } = body;
1285
1285
  const isEmail = username.includes("@");
1286
+ const disabledChannelResponse = {
1287
+ exists: false,
1288
+ verified: false,
1289
+ hasPassword: false,
1290
+ requiresPasswordSetup: false,
1291
+ account: null
1292
+ };
1293
+ if (isEmail && !config.email.enabled) {
1294
+ return c.json(disabledChannelResponse, 200);
1295
+ }
1296
+ if (!(isEmail || config.phone.enabled)) {
1297
+ return c.json(disabledChannelResponse, 200);
1298
+ }
1286
1299
  const userTypeFilter = sql4`${usersInIam.userType} @> ARRAY[${config.userType}]::text[]`;
1287
1300
  const whereClause = isEmail ? and6(
1288
1301
  eq6(usersInIam.tenantId, resolvedTenantId),
@@ -1846,6 +1859,20 @@ var SignUpError = class extends Error {
1846
1859
  this.status = status;
1847
1860
  }
1848
1861
  };
1862
+ var normalizeSignupDomain = (value) => {
1863
+ return value.trim().toLowerCase().replace(/^@/, "");
1864
+ };
1865
+ var isAllowedSignupEmail = (email, allowedDomains) => {
1866
+ const domain = email.split("@")[1]?.toLowerCase();
1867
+ if (!domain) {
1868
+ return false;
1869
+ }
1870
+ const normalizedDomains = allowedDomains.map(normalizeSignupDomain).filter(Boolean);
1871
+ if (normalizedDomains.length === 0) {
1872
+ return true;
1873
+ }
1874
+ return normalizedDomains.includes(domain);
1875
+ };
1849
1876
  var signUpHandler = async (c) => {
1850
1877
  const body = c.req.valid("json");
1851
1878
  const config = c.get("config");
@@ -1857,7 +1884,19 @@ var signUpHandler = async (c) => {
1857
1884
  if (!identifier) {
1858
1885
  return c.json({ error: "Either email or phone is required" }, 409);
1859
1886
  }
1887
+ if (config.signUp && !config.signUp.enabled) {
1888
+ return c.json({ error: "Sign up is disabled" }, 403);
1889
+ }
1860
1890
  const isEmail = identifier.includes("@");
1891
+ if (isEmail && config.signUp && !config.signUp.emailEnabled) {
1892
+ return c.json({ error: "Email sign up is disabled" }, 403);
1893
+ }
1894
+ if (!isEmail && config.signUp && !config.signUp.phoneEnabled) {
1895
+ return c.json({ error: "Phone sign up is disabled" }, 403);
1896
+ }
1897
+ if (isEmail && config.signUp?.allowedEmailDomains && !isAllowedSignupEmail(identifier, config.signUp.allowedEmailDomains)) {
1898
+ return c.json({ error: "Email domain is not allowed for sign up" }, 403);
1899
+ }
1861
1900
  if (phone) {
1862
1901
  const phoneValidator = createPhoneField(config);
1863
1902
  if (!phoneValidator.validate(phone)) {
@@ -3987,6 +4026,14 @@ var phoneVerificationRequestHandler = async (c) => {
3987
4026
  return c.json({ error: "Phone authentication is disabled" }, 400);
3988
4027
  }
3989
4028
  const { phone, context } = body;
4029
+ if (context === "sign-up" && config.signUp) {
4030
+ if (!config.signUp.enabled) {
4031
+ return c.json({ error: "Sign up is disabled" }, 400);
4032
+ }
4033
+ if (!config.signUp.phoneEnabled) {
4034
+ return c.json({ error: "Phone sign up is disabled" }, 400);
4035
+ }
4036
+ }
3990
4037
  if (!phone) {
3991
4038
  return c.json({ error: "Phone required" }, 400);
3992
4039
  }
@@ -8566,6 +8613,12 @@ var defaultAuthConfig = {
8566
8613
  ...defaultConfig,
8567
8614
  phoneRegex: defaultPhoneRegex
8568
8615
  },
8616
+ signUp: {
8617
+ enabled: true,
8618
+ emailEnabled: true,
8619
+ phoneEnabled: true,
8620
+ allowedEmailDomains: []
8621
+ },
8569
8622
  security: {
8570
8623
  maxLoginAttempts: 5,
8571
8624
  lockoutDuration: "15m"