hazo_auth 5.3.1 → 6.0.0
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/README.md +97 -17
- package/SETUP_CHECKLIST.md +7 -7
- package/cli-src/cli/generate.ts +10 -1
- package/cli-src/lib/auth/auth_types.ts +21 -12
- package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +25 -24
- package/cli-src/lib/auth/index.ts +2 -2
- package/cli-src/lib/auth/with_auth.server.ts +15 -15
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +10 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.d.ts +13 -12
- package/dist/lib/auth/auth_types.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.js +8 -0
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts +8 -7
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_tenant_auth.server.js +23 -22
- package/dist/lib/auth/index.d.ts +2 -2
- package/dist/lib/auth/index.d.ts.map +1 -1
- package/dist/lib/auth/with_auth.server.d.ts +13 -13
- package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/with_auth.server.js +2 -2
- package/dist/server_pages/forgot_password.d.ts +1 -1
- package/dist/server_pages/forgot_password.d.ts.map +1 -1
- package/dist/server_pages/forgot_password.js +2 -1
- package/dist/server_pages/login.d.ts +1 -1
- package/dist/server_pages/login.d.ts.map +1 -1
- package/dist/server_pages/login.js +2 -1
- package/dist/server_pages/my_settings.d.ts +1 -1
- package/dist/server_pages/my_settings.d.ts.map +1 -1
- package/dist/server_pages/my_settings.js +2 -1
- package/dist/server_pages/register.d.ts +1 -1
- package/dist/server_pages/register.d.ts.map +1 -1
- package/dist/server_pages/register.js +2 -1
- package/dist/server_pages/reset_password.d.ts +1 -1
- package/dist/server_pages/reset_password.d.ts.map +1 -1
- package/dist/server_pages/reset_password.js +2 -1
- package/dist/server_pages/verify_email.d.ts +1 -1
- package/dist/server_pages/verify_email.d.ts.map +1 -1
- package/dist/server_pages/verify_email.js +2 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,6 +2,84 @@
|
|
|
2
2
|
|
|
3
3
|
A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
|
|
4
4
|
|
|
5
|
+
### What's New in v6.0.0 🚨 BREAKING CHANGE
|
|
6
|
+
|
|
7
|
+
**`TenantAuthResult.organization` / `.organization_id` renamed to `.selected_scope` / `.selected_scope_id`.**
|
|
8
|
+
|
|
9
|
+
The multi-tenancy model has been scope-based for several releases — `auth.user_scopes`, `auth.scope_access_via`, `auth.scope_ok`, the `hazo_auth_scope_id` cookie, the `X-Hazo-Scope-Id` header. The only holdouts using the legacy "organization" name were two fields on `TenantAuthResult` that were always just *"the currently selected scope"* under the hood. This release eliminates the inconsistency.
|
|
10
|
+
|
|
11
|
+
> 📖 **Full migration guide:** [MIGRATION.md → v5.x → v6.0](./MIGRATION.md#v5x--v60-organization--selected_scope)
|
|
12
|
+
|
|
13
|
+
**No behavioral change.** `selected_scope_id` is derived from the same scope-selection cookie/header that `organization_id` was. Wire-format auth responses change field names, but the underlying scope lookup is identical.
|
|
14
|
+
|
|
15
|
+
**No deprecation shim.** A clean find-replace is the upgrade path. If you absolutely need a transitional period, pin to `hazo_auth@^5.3` until you can do the rename in one shot.
|
|
16
|
+
|
|
17
|
+
**What to replace (find ↔ replace, all in your app code):**
|
|
18
|
+
|
|
19
|
+
| Find | Replace with |
|
|
20
|
+
| ------------------------------------------------- | -------------------------------------------------- |
|
|
21
|
+
| `auth.organization` | `auth.selected_scope` |
|
|
22
|
+
| `auth.organization_id` | `auth.selected_scope_id` |
|
|
23
|
+
| `import type { TenantOrganization }` | `import type { SelectedScope }` |
|
|
24
|
+
| `: TenantOrganization` | `: SelectedScope` |
|
|
25
|
+
| `AuthenticatedTenantAuthWithOrg` | `AuthenticatedTenantAuthWithSelectedScope` |
|
|
26
|
+
|
|
27
|
+
**Before / after example:**
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// BEFORE (v5.x)
|
|
31
|
+
import { hazo_get_tenant_auth } from "hazo_auth/server-lib";
|
|
32
|
+
import type { TenantOrganization } from "hazo_auth";
|
|
33
|
+
|
|
34
|
+
export async function GET(request: NextRequest) {
|
|
35
|
+
const auth = await hazo_get_tenant_auth(request);
|
|
36
|
+
if (!auth.authenticated || !auth.organization) {
|
|
37
|
+
return NextResponse.json({ error: "no tenant" }, { status: 403 });
|
|
38
|
+
}
|
|
39
|
+
const data = await getData(auth.organization_id); // or auth.organization.id
|
|
40
|
+
return NextResponse.json({ org: auth.organization, data });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// AFTER (v6.0)
|
|
44
|
+
import { hazo_get_tenant_auth } from "hazo_auth/server-lib";
|
|
45
|
+
import type { SelectedScope } from "hazo_auth";
|
|
46
|
+
|
|
47
|
+
export async function GET(request: NextRequest) {
|
|
48
|
+
const auth = await hazo_get_tenant_auth(request);
|
|
49
|
+
if (!auth.authenticated || !auth.selected_scope) {
|
|
50
|
+
return NextResponse.json({ error: "no tenant scope" }, { status: 403 });
|
|
51
|
+
}
|
|
52
|
+
const data = await getData(auth.selected_scope_id); // or auth.selected_scope.id
|
|
53
|
+
return NextResponse.json({ selected_scope: auth.selected_scope, data });
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**What did NOT change** (same names, same behavior, same wire format):
|
|
58
|
+
- `auth.user_scopes` — array of all scopes the user has access to
|
|
59
|
+
- `auth.scope_ok`, `auth.scope_access_via` — scope-access fields
|
|
60
|
+
- `hazo_auth_scope_id` cookie name and `X-Hazo-Scope-Id` request header
|
|
61
|
+
- All `Tenant*` type and class names: `TenantAuthResult`, `TenantAuthOptions`, `RequiredTenantAuthResult`, `TenantRequiredError`, `TenantAccessDeniedError`, `hazo_get_tenant_auth`, `require_tenant_auth`, `withAuth`'s `require_tenant` option
|
|
62
|
+
- The error response `{ code: "TENANT_REQUIRED" }` shape — only the human-readable `error` string was rephrased ("Organization context required" → "Tenant scope context required")
|
|
63
|
+
|
|
64
|
+
**One-liner upgrade for typical consumers:**
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Run from your app repo (NOT inside hazo_auth itself).
|
|
68
|
+
# Update the path glob to match your code layout.
|
|
69
|
+
git grep -l "organization\b\|TenantOrganization\|AuthenticatedTenantAuthWithOrg" -- 'src/**' 'app/**' 'lib/**' \
|
|
70
|
+
| xargs sed -i.bak '
|
|
71
|
+
s/auth\.organization_id\b/auth.selected_scope_id/g;
|
|
72
|
+
s/auth\.organization\b/auth.selected_scope/g;
|
|
73
|
+
s/\bTenantOrganization\b/SelectedScope/g;
|
|
74
|
+
s/\bAuthenticatedTenantAuthWithOrg\b/AuthenticatedTenantAuthWithSelectedScope/g;
|
|
75
|
+
'
|
|
76
|
+
# Then: review the diff carefully — sed is blunt. Remove .bak files when satisfied.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> ⚠️ The sed line is a starting point, not a blanket "trust me." It only catches `auth.organization*` and the type names. If you destructure (`const { organization } = auth`), aliased imports (`TenantOrganization as Org`), or reference `organization` for unrelated reasons (HTML autocomplete attribute, your own variables), the script either misses or wrongly rewrites them. **Always diff before committing.**
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
5
83
|
### What's New in v5.3.1 🔧
|
|
6
84
|
|
|
7
85
|
**`get_client_ip(request)` exported from `hazo_auth/server-lib`** — extracts the client IP from `x-forwarded-for` (first element), falling back to `x-real-ip`, then `"unknown"`. Previously private to `hazo_get_auth.server.ts`. Useful for consumers that need consistent IP extraction across handlers (e.g., `hazo_feedback` audit logging).
|
|
@@ -1644,7 +1722,7 @@ export async function proxy(request: NextRequest) {
|
|
|
1644
1722
|
|
|
1645
1723
|
#### `hazo_get_tenant_auth` (Recommended for Multi-Tenant Apps)
|
|
1646
1724
|
|
|
1647
|
-
**New:** Tenant-aware authentication function that extracts scope context from request headers or cookies and returns enriched result
|
|
1725
|
+
**New:** Tenant-aware authentication function that extracts scope context from request headers or cookies and returns enriched result including the currently selected scope.
|
|
1648
1726
|
|
|
1649
1727
|
**Location:** `src/lib/auth/hazo_get_tenant_auth.server.ts`
|
|
1650
1728
|
|
|
@@ -1678,8 +1756,9 @@ type TenantAuthResult =
|
|
|
1678
1756
|
permissions: string[];
|
|
1679
1757
|
permission_ok: boolean;
|
|
1680
1758
|
missing_permissions?: string[];
|
|
1681
|
-
|
|
1682
|
-
|
|
1759
|
+
selected_scope: SelectedScope | null; // Currently selected tenant/scope
|
|
1760
|
+
selected_scope_id: string | null; // Shorthand for selected_scope?.id
|
|
1761
|
+
user_scopes: ScopeDetails[]; // All user's scopes for switching
|
|
1683
1762
|
scope_ok: boolean;
|
|
1684
1763
|
}
|
|
1685
1764
|
| {
|
|
@@ -1687,12 +1766,13 @@ type TenantAuthResult =
|
|
|
1687
1766
|
user: null;
|
|
1688
1767
|
permissions: [];
|
|
1689
1768
|
permission_ok: false;
|
|
1690
|
-
|
|
1769
|
+
selected_scope: null;
|
|
1770
|
+
selected_scope_id: null;
|
|
1691
1771
|
user_scopes: [];
|
|
1692
1772
|
scope_ok: false;
|
|
1693
1773
|
};
|
|
1694
1774
|
|
|
1695
|
-
type
|
|
1775
|
+
type SelectedScope = {
|
|
1696
1776
|
id: string;
|
|
1697
1777
|
name: string;
|
|
1698
1778
|
slug: string | null; // URL-friendly identifier
|
|
@@ -1734,10 +1814,10 @@ export async function GET(request: NextRequest) {
|
|
|
1734
1814
|
return NextResponse.json({ error: "Authentication required" }, { status: 401 });
|
|
1735
1815
|
}
|
|
1736
1816
|
|
|
1737
|
-
if (!auth.
|
|
1817
|
+
if (!auth.selected_scope) {
|
|
1738
1818
|
return NextResponse.json(
|
|
1739
1819
|
{
|
|
1740
|
-
error: "No
|
|
1820
|
+
error: "No tenant scope context",
|
|
1741
1821
|
available_scopes: auth.user_scopes.map(s => ({ id: s.id, name: s.name }))
|
|
1742
1822
|
},
|
|
1743
1823
|
{ status: 403 }
|
|
@@ -1745,10 +1825,10 @@ export async function GET(request: NextRequest) {
|
|
|
1745
1825
|
}
|
|
1746
1826
|
|
|
1747
1827
|
// Access tenant-specific data
|
|
1748
|
-
const data = await getTenantData(auth.
|
|
1828
|
+
const data = await getTenantData(auth.selected_scope.id);
|
|
1749
1829
|
|
|
1750
1830
|
return NextResponse.json({
|
|
1751
|
-
|
|
1831
|
+
selected_scope: auth.selected_scope,
|
|
1752
1832
|
data,
|
|
1753
1833
|
// Include available scopes for UI scope switcher
|
|
1754
1834
|
available_scopes: auth.user_scopes,
|
|
@@ -1766,8 +1846,8 @@ export async function GET(request: NextRequest) {
|
|
|
1766
1846
|
required_permissions: ["view_reports"],
|
|
1767
1847
|
});
|
|
1768
1848
|
|
|
1769
|
-
// auth.
|
|
1770
|
-
const reports = await getReports(auth.
|
|
1849
|
+
// auth.selected_scope is guaranteed non-null here
|
|
1850
|
+
const reports = await getReports(auth.selected_scope.id);
|
|
1771
1851
|
return NextResponse.json({ reports });
|
|
1772
1852
|
} catch (error) {
|
|
1773
1853
|
if (error instanceof HazoAuthError) {
|
|
@@ -1817,16 +1897,16 @@ Helper function that wraps `hazo_get_tenant_auth` and throws typed errors for co
|
|
|
1817
1897
|
- `TenantRequiredError` (403) - No tenant context in request
|
|
1818
1898
|
- `TenantAccessDeniedError` (403) - User lacks access to requested tenant
|
|
1819
1899
|
|
|
1820
|
-
**Returns:** `RequiredTenantAuthResult` with guaranteed non-null `
|
|
1900
|
+
**Returns:** `RequiredTenantAuthResult` with guaranteed non-null `selected_scope`
|
|
1821
1901
|
|
|
1822
1902
|
**Example:**
|
|
1823
1903
|
```typescript
|
|
1824
1904
|
export async function GET(request: NextRequest) {
|
|
1825
1905
|
try {
|
|
1826
|
-
//
|
|
1827
|
-
const {
|
|
1906
|
+
// selected_scope is guaranteed to exist
|
|
1907
|
+
const { selected_scope, user, permissions } = await require_tenant_auth(request);
|
|
1828
1908
|
|
|
1829
|
-
const data = await getData(
|
|
1909
|
+
const data = await getData(selected_scope.id);
|
|
1830
1910
|
return NextResponse.json(data);
|
|
1831
1911
|
} catch (error) {
|
|
1832
1912
|
if (error instanceof HazoAuthError) {
|
|
@@ -1879,10 +1959,10 @@ export const DELETE = withAuth<{ id: string }>(
|
|
|
1879
1959
|
{ required_permissions: ["admin_system"] }
|
|
1880
1960
|
);
|
|
1881
1961
|
|
|
1882
|
-
// With tenant requirement (auth.
|
|
1962
|
+
// With tenant requirement (auth.selected_scope guaranteed non-null)
|
|
1883
1963
|
export const GET = withAuth<{ id: string }>(
|
|
1884
1964
|
async (request, auth, { id }) => {
|
|
1885
|
-
const data = await getData(auth.
|
|
1965
|
+
const data = await getData(auth.selected_scope.id, id);
|
|
1886
1966
|
return NextResponse.json(data);
|
|
1887
1967
|
},
|
|
1888
1968
|
{ require_tenant: true }
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -1924,10 +1924,10 @@ import { hazo_get_tenant_auth } from "hazo_auth/server-lib";
|
|
|
1924
1924
|
export async function GET(request: NextRequest) {
|
|
1925
1925
|
const auth = await hazo_get_tenant_auth(request);
|
|
1926
1926
|
|
|
1927
|
-
if (auth.authenticated && auth.
|
|
1928
|
-
// auth.
|
|
1927
|
+
if (auth.authenticated && auth.selected_scope) {
|
|
1928
|
+
// auth.selected_scope contains the currently selected tenant/scope
|
|
1929
1929
|
// auth.user_scopes contains all scopes user can access (for UI switcher)
|
|
1930
|
-
const data = await getTenantData(auth.
|
|
1930
|
+
const data = await getTenantData(auth.selected_scope.id);
|
|
1931
1931
|
}
|
|
1932
1932
|
}
|
|
1933
1933
|
```
|
|
@@ -1939,8 +1939,8 @@ import { require_tenant_auth, HazoAuthError } from "hazo_auth/server-lib";
|
|
|
1939
1939
|
export async function GET(request: NextRequest) {
|
|
1940
1940
|
try {
|
|
1941
1941
|
const auth = await require_tenant_auth(request);
|
|
1942
|
-
// auth.
|
|
1943
|
-
return NextResponse.json(await getData(auth.
|
|
1942
|
+
// auth.selected_scope is guaranteed non-null
|
|
1943
|
+
return NextResponse.json(await getData(auth.selected_scope.id));
|
|
1944
1944
|
} catch (error) {
|
|
1945
1945
|
if (error instanceof HazoAuthError) {
|
|
1946
1946
|
return NextResponse.json(
|
|
@@ -1960,7 +1960,7 @@ import { withAuth } from "hazo_auth/server-lib";
|
|
|
1960
1960
|
// Auth + params + error handling all automatic
|
|
1961
1961
|
export const GET = withAuth<{ id: string }>(
|
|
1962
1962
|
async (request, auth, { id }) => {
|
|
1963
|
-
const data = await getData(auth.
|
|
1963
|
+
const data = await getData(auth.selected_scope.id, id);
|
|
1964
1964
|
return NextResponse.json(data);
|
|
1965
1965
|
},
|
|
1966
1966
|
{ require_tenant: true }
|
|
@@ -2009,7 +2009,7 @@ const auth = await hazo_get_tenant_auth(request);
|
|
|
2009
2009
|
|
|
2010
2010
|
// Return available scopes to frontend
|
|
2011
2011
|
return NextResponse.json({
|
|
2012
|
-
current_scope: auth.
|
|
2012
|
+
current_scope: auth.selected_scope,
|
|
2013
2013
|
available_scopes: auth.user_scopes.map(s => ({
|
|
2014
2014
|
id: s.id,
|
|
2015
2015
|
name: s.name,
|
package/cli-src/cli/generate.ts
CHANGED
|
@@ -127,11 +127,20 @@ ${exports}
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function generate_page_content(page: PageDefinition): string {
|
|
130
|
+
// Next 16 requires page default exports to satisfy `PageProps` (i.e. accept
|
|
131
|
+
// `{ params?, searchParams? }` and nothing else). Re-exporting the named
|
|
132
|
+
// component directly fails that check because the component carries custom
|
|
133
|
+
// props (image_src, layout, …). The wrapper below is a parameter-less
|
|
134
|
+
// function that returns the component — Next sees a `() => JSX` signature
|
|
135
|
+
// which trivially satisfies PageProps. Direct JSX consumers still use the
|
|
136
|
+
// named export from `hazo_auth/pages` and get the full custom-prop API.
|
|
130
137
|
return `// Generated by hazo_auth - do not edit manually
|
|
131
138
|
// Page: /${page.path}
|
|
132
139
|
import { ${page.component_name} } from "hazo_auth/pages";
|
|
133
140
|
|
|
134
|
-
export default
|
|
141
|
+
export default function Page() {
|
|
142
|
+
return <${page.component_name} />;
|
|
143
|
+
}
|
|
135
144
|
`;
|
|
136
145
|
}
|
|
137
146
|
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// file_description: Type definitions and error classes for hazo_get_auth utility
|
|
2
|
+
//
|
|
3
|
+
// Naming note (v6.0.0): the field previously called `organization` (and
|
|
4
|
+
// `organization_id`) on `TenantAuthResult` was renamed to `selected_scope`
|
|
5
|
+
// (and `selected_scope_id`), and the type `TenantOrganization` was renamed
|
|
6
|
+
// to `SelectedScope`. The multi-tenancy model is scopes throughout; the
|
|
7
|
+
// old name was a legacy synonym for "the currently selected scope" derived
|
|
8
|
+
// from the scope-selection cookie/header. No deprecation shim is provided.
|
|
9
|
+
//
|
|
2
10
|
// section: types
|
|
3
11
|
|
|
4
12
|
/**
|
|
@@ -123,10 +131,11 @@ export type ScopeDetails = {
|
|
|
123
131
|
};
|
|
124
132
|
|
|
125
133
|
/**
|
|
126
|
-
*
|
|
127
|
-
* Simplified view of scope
|
|
134
|
+
* Currently selected scope information returned in tenant auth results.
|
|
135
|
+
* Simplified view of the scope chosen via the scope-selection cookie or
|
|
136
|
+
* `X-Hazo-Scope-Id` header.
|
|
128
137
|
*/
|
|
129
|
-
export type
|
|
138
|
+
export type SelectedScope = {
|
|
130
139
|
id: string;
|
|
131
140
|
name: string;
|
|
132
141
|
slug: string | null;
|
|
@@ -167,9 +176,9 @@ export type TenantAuthResult =
|
|
|
167
176
|
permissions: string[];
|
|
168
177
|
permission_ok: boolean;
|
|
169
178
|
missing_permissions?: string[];
|
|
170
|
-
|
|
171
|
-
/** Shorthand for
|
|
172
|
-
|
|
179
|
+
selected_scope: SelectedScope | null;
|
|
180
|
+
/** Shorthand for selected_scope?.id - commonly used for DB query filters. */
|
|
181
|
+
selected_scope_id: string | null;
|
|
173
182
|
user_scopes: ScopeDetails[];
|
|
174
183
|
scope_ok?: boolean;
|
|
175
184
|
scope_access_via?: ScopeAccessInfo;
|
|
@@ -179,20 +188,20 @@ export type TenantAuthResult =
|
|
|
179
188
|
user: null;
|
|
180
189
|
permissions: [];
|
|
181
190
|
permission_ok: false;
|
|
182
|
-
|
|
183
|
-
/** Shorthand for
|
|
184
|
-
|
|
191
|
+
selected_scope: null;
|
|
192
|
+
/** Shorthand for selected_scope?.id - commonly used for DB query filters. */
|
|
193
|
+
selected_scope_id: null;
|
|
185
194
|
user_scopes: [];
|
|
186
195
|
scope_ok?: false;
|
|
187
196
|
};
|
|
188
197
|
|
|
189
198
|
/**
|
|
190
|
-
* Guaranteed authenticated result with non-null
|
|
191
|
-
* Returned by require_tenant_auth when validation passes
|
|
199
|
+
* Guaranteed authenticated result with non-null selected_scope.
|
|
200
|
+
* Returned by require_tenant_auth when validation passes.
|
|
192
201
|
*/
|
|
193
202
|
export type RequiredTenantAuthResult = TenantAuthResult & {
|
|
194
203
|
authenticated: true;
|
|
195
|
-
|
|
204
|
+
selected_scope: SelectedScope;
|
|
196
205
|
};
|
|
197
206
|
|
|
198
207
|
// section: tenant_error_classes
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
TenantAuthOptions,
|
|
15
15
|
TenantAuthResult,
|
|
16
16
|
RequiredTenantAuthResult,
|
|
17
|
-
|
|
17
|
+
SelectedScope,
|
|
18
18
|
ScopeDetails,
|
|
19
19
|
} from "./auth_types";
|
|
20
20
|
import {
|
|
@@ -62,15 +62,15 @@ export function extract_scope_id_from_request(
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
* Builds
|
|
65
|
+
* Builds SelectedScope from scope details and access info.
|
|
66
66
|
* @param scope_details - Full scope details from cache
|
|
67
67
|
* @param is_super_admin - Whether user is accessing as super admin
|
|
68
|
-
* @returns
|
|
68
|
+
* @returns SelectedScope object
|
|
69
69
|
*/
|
|
70
|
-
function
|
|
70
|
+
function build_selected_scope(
|
|
71
71
|
scope_details: ScopeDetails,
|
|
72
72
|
is_super_admin: boolean,
|
|
73
|
-
):
|
|
73
|
+
): SelectedScope {
|
|
74
74
|
return {
|
|
75
75
|
id: scope_details.id,
|
|
76
76
|
name: scope_details.name,
|
|
@@ -96,20 +96,21 @@ function build_tenant_organization(
|
|
|
96
96
|
* Tenant-aware authentication function
|
|
97
97
|
*
|
|
98
98
|
* Extracts tenant/scope context from request headers or cookies,
|
|
99
|
-
* validates access, and returns enriched result
|
|
99
|
+
* validates access, and returns enriched result including the currently
|
|
100
|
+
* selected scope.
|
|
100
101
|
*
|
|
101
102
|
* Header priority: X-Hazo-Scope-Id > Cookie
|
|
102
103
|
*
|
|
103
104
|
* @param request - NextRequest object
|
|
104
105
|
* @param options - TenantAuthOptions for customization
|
|
105
|
-
* @returns TenantAuthResult with user, permissions,
|
|
106
|
+
* @returns TenantAuthResult with user, permissions, selected_scope, and user_scopes
|
|
106
107
|
*
|
|
107
108
|
* @example
|
|
108
109
|
* ```typescript
|
|
109
110
|
* const auth = await hazo_get_tenant_auth(request);
|
|
110
|
-
* if (auth.authenticated && auth.
|
|
111
|
+
* if (auth.authenticated && auth.selected_scope) {
|
|
111
112
|
* // Access tenant-specific data
|
|
112
|
-
* const data = await getData(auth.
|
|
113
|
+
* const data = await getData(auth.selected_scope.id);
|
|
113
114
|
* }
|
|
114
115
|
* ```
|
|
115
116
|
*/
|
|
@@ -136,8 +137,8 @@ export async function hazo_get_tenant_auth(
|
|
|
136
137
|
user: null,
|
|
137
138
|
permissions: [],
|
|
138
139
|
permission_ok: false,
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
selected_scope: null,
|
|
141
|
+
selected_scope_id: null,
|
|
141
142
|
user_scopes: [],
|
|
142
143
|
scope_ok: false,
|
|
143
144
|
};
|
|
@@ -155,8 +156,8 @@ export async function hazo_get_tenant_auth(
|
|
|
155
156
|
// User scopes from cache or empty array
|
|
156
157
|
const user_scopes: ScopeDetails[] = cached?.scopes || [];
|
|
157
158
|
|
|
158
|
-
// Build
|
|
159
|
-
let
|
|
159
|
+
// Build selected_scope info if scope access was successful
|
|
160
|
+
let selected_scope: SelectedScope | null = null;
|
|
160
161
|
|
|
161
162
|
if (scope_id && auth_result.scope_ok && auth_result.scope_access_via) {
|
|
162
163
|
// Find the scope in user's scopes that matches the access_via scope
|
|
@@ -165,7 +166,7 @@ export async function hazo_get_tenant_auth(
|
|
|
165
166
|
);
|
|
166
167
|
|
|
167
168
|
if (access_scope) {
|
|
168
|
-
|
|
169
|
+
selected_scope = build_selected_scope(
|
|
169
170
|
access_scope,
|
|
170
171
|
auth_result.scope_access_via.is_super_admin || false,
|
|
171
172
|
);
|
|
@@ -174,7 +175,7 @@ export async function hazo_get_tenant_auth(
|
|
|
174
175
|
const hazoConnect = get_hazo_connect_instance();
|
|
175
176
|
const scope_result = await get_scope_by_id(hazoConnect, scope_id);
|
|
176
177
|
if (scope_result.success && scope_result.scope) {
|
|
177
|
-
|
|
178
|
+
selected_scope = {
|
|
178
179
|
id: scope_result.scope.id,
|
|
179
180
|
name: scope_result.scope.name,
|
|
180
181
|
slug: null, // Could fetch from scope if slug column exists
|
|
@@ -200,8 +201,8 @@ export async function hazo_get_tenant_auth(
|
|
|
200
201
|
permissions: auth_result.permissions,
|
|
201
202
|
permission_ok: auth_result.permission_ok,
|
|
202
203
|
missing_permissions: auth_result.missing_permissions,
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
selected_scope,
|
|
205
|
+
selected_scope_id: selected_scope?.id || null,
|
|
205
206
|
user_scopes,
|
|
206
207
|
scope_ok: auth_result.scope_ok,
|
|
207
208
|
scope_access_via: auth_result.scope_access_via,
|
|
@@ -218,15 +219,15 @@ export async function hazo_get_tenant_auth(
|
|
|
218
219
|
*
|
|
219
220
|
* @param request - NextRequest object
|
|
220
221
|
* @param options - TenantAuthOptions for customization
|
|
221
|
-
* @returns RequiredTenantAuthResult with guaranteed non-null
|
|
222
|
+
* @returns RequiredTenantAuthResult with guaranteed non-null selected_scope
|
|
222
223
|
* @throws AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError
|
|
223
224
|
*
|
|
224
225
|
* @example
|
|
225
226
|
* ```typescript
|
|
226
227
|
* try {
|
|
227
228
|
* const auth = await require_tenant_auth(request);
|
|
228
|
-
* // auth.
|
|
229
|
-
* const data = await getData(auth.
|
|
229
|
+
* // auth.selected_scope is guaranteed non-null here
|
|
230
|
+
* const data = await getData(auth.selected_scope.id);
|
|
230
231
|
* } catch (error) {
|
|
231
232
|
* if (error instanceof HazoAuthError) {
|
|
232
233
|
* return NextResponse.json(
|
|
@@ -257,14 +258,14 @@ export async function require_tenant_auth(
|
|
|
257
258
|
throw new TenantAccessDeniedError(scope_id, result.user_scopes);
|
|
258
259
|
}
|
|
259
260
|
|
|
260
|
-
// Check if
|
|
261
|
-
if (!result.
|
|
261
|
+
// Check if scope context is required but missing
|
|
262
|
+
if (!result.selected_scope) {
|
|
262
263
|
throw new TenantRequiredError(
|
|
263
|
-
"No
|
|
264
|
+
"No tenant scope context provided. Include X-Hazo-Scope-Id header or scope cookie.",
|
|
264
265
|
result.user_scopes,
|
|
265
266
|
);
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
// Type assertion: at this point we know
|
|
269
|
+
// Type assertion: at this point we know selected_scope is non-null
|
|
269
270
|
return result as RequiredTenantAuthResult;
|
|
270
271
|
}
|
|
@@ -22,7 +22,7 @@ export {
|
|
|
22
22
|
} from "./hazo_get_tenant_auth.server.js";
|
|
23
23
|
export type {
|
|
24
24
|
ScopeDetails,
|
|
25
|
-
|
|
25
|
+
SelectedScope,
|
|
26
26
|
TenantAuthOptions,
|
|
27
27
|
TenantAuthResult,
|
|
28
28
|
RequiredTenantAuthResult,
|
|
@@ -50,7 +50,7 @@ export {
|
|
|
50
50
|
} from "./with_auth.server.js";
|
|
51
51
|
export type {
|
|
52
52
|
AuthenticatedTenantAuth,
|
|
53
|
-
|
|
53
|
+
AuthenticatedTenantAuthWithSelectedScope,
|
|
54
54
|
WithAuthOptions,
|
|
55
55
|
} from "./with_auth.server";
|
|
56
56
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
PermissionError,
|
|
11
11
|
type TenantAuthOptions,
|
|
12
12
|
type TenantAuthResult,
|
|
13
|
-
type
|
|
13
|
+
type SelectedScope,
|
|
14
14
|
type HazoAuthUser,
|
|
15
15
|
type ScopeDetails,
|
|
16
16
|
type ScopeAccessInfo,
|
|
@@ -27,19 +27,19 @@ export type AuthenticatedTenantAuth = {
|
|
|
27
27
|
permissions: string[];
|
|
28
28
|
permission_ok: boolean;
|
|
29
29
|
missing_permissions?: string[];
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
selected_scope: SelectedScope | null;
|
|
31
|
+
selected_scope_id: string | null;
|
|
32
32
|
user_scopes: ScopeDetails[];
|
|
33
33
|
scope_ok?: boolean;
|
|
34
34
|
scope_access_via?: ScopeAccessInfo;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Authenticated branch with guaranteed non-null
|
|
38
|
+
* Authenticated branch with guaranteed non-null selected_scope
|
|
39
39
|
*/
|
|
40
|
-
export type
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
export type AuthenticatedTenantAuthWithSelectedScope = AuthenticatedTenantAuth & {
|
|
41
|
+
selected_scope: SelectedScope;
|
|
42
|
+
selected_scope_id: string;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -48,8 +48,8 @@ export type AuthenticatedTenantAuthWithOrg = AuthenticatedTenantAuth & {
|
|
|
48
48
|
*/
|
|
49
49
|
export type WithAuthOptions = TenantAuthOptions & {
|
|
50
50
|
/**
|
|
51
|
-
* If true, requires
|
|
52
|
-
* Narrows auth type to
|
|
51
|
+
* If true, requires tenant/scope context (403 if missing)
|
|
52
|
+
* Narrows auth type to AuthenticatedTenantAuthWithSelectedScope
|
|
53
53
|
*/
|
|
54
54
|
require_tenant?: boolean;
|
|
55
55
|
};
|
|
@@ -75,7 +75,7 @@ type AuthenticatedHandler<TParams> = (
|
|
|
75
75
|
*/
|
|
76
76
|
type AuthenticatedTenantHandler<TParams> = (
|
|
77
77
|
request: NextRequest,
|
|
78
|
-
auth:
|
|
78
|
+
auth: AuthenticatedTenantAuthWithSelectedScope,
|
|
79
79
|
params: TParams,
|
|
80
80
|
) => Promise<NextResponse> | NextResponse;
|
|
81
81
|
|
|
@@ -138,7 +138,7 @@ async function resolve_params<TParams>(
|
|
|
138
138
|
*
|
|
139
139
|
* - Calls `hazo_get_tenant_auth` and returns 401 if not authenticated
|
|
140
140
|
* - Returns 403 if `required_permissions` are specified and not satisfied
|
|
141
|
-
* - Returns 403 if `require_tenant: true` and no
|
|
141
|
+
* - Returns 403 if `require_tenant: true` and no tenant/scope context
|
|
142
142
|
* - Resolves `await context.params` (Next.js 15 pattern)
|
|
143
143
|
* - Catches HazoAuthError, PermissionError, and unexpected errors
|
|
144
144
|
*
|
|
@@ -161,8 +161,8 @@ async function resolve_params<TParams>(
|
|
|
161
161
|
* // With tenant requirement
|
|
162
162
|
* export const GET = withAuth<{ id: string }>(
|
|
163
163
|
* async (request, auth, { id }) => {
|
|
164
|
-
* // auth.
|
|
165
|
-
* const data = await getData(auth.
|
|
164
|
+
* // auth.selected_scope is guaranteed non-null
|
|
165
|
+
* const data = await getData(auth.selected_scope.id, id);
|
|
166
166
|
* return NextResponse.json(data);
|
|
167
167
|
* },
|
|
168
168
|
* { require_tenant: true }
|
|
@@ -227,10 +227,10 @@ export function withAuth<TParams = Record<string, never>>(
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
// Check tenant requirement
|
|
230
|
-
if (options.require_tenant && !auth.
|
|
230
|
+
if (options.require_tenant && !auth.selected_scope) {
|
|
231
231
|
return NextResponse.json(
|
|
232
232
|
{
|
|
233
|
-
error: "
|
|
233
|
+
error: "Tenant scope context required",
|
|
234
234
|
code: "TENANT_REQUIRED",
|
|
235
235
|
},
|
|
236
236
|
{ status: 403 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AA0MF,wBAAgB,eAAe,CAAC,OAAO,GAAE,eAAoB,GAAG,IAAI,CA8DnE"}
|
package/dist/cli/generate.js
CHANGED
|
@@ -93,11 +93,20 @@ ${exports}
|
|
|
93
93
|
`;
|
|
94
94
|
}
|
|
95
95
|
function generate_page_content(page) {
|
|
96
|
+
// Next 16 requires page default exports to satisfy `PageProps` (i.e. accept
|
|
97
|
+
// `{ params?, searchParams? }` and nothing else). Re-exporting the named
|
|
98
|
+
// component directly fails that check because the component carries custom
|
|
99
|
+
// props (image_src, layout, …). The wrapper below is a parameter-less
|
|
100
|
+
// function that returns the component — Next sees a `() => JSX` signature
|
|
101
|
+
// which trivially satisfies PageProps. Direct JSX consumers still use the
|
|
102
|
+
// named export from `hazo_auth/pages` and get the full custom-prop API.
|
|
96
103
|
return `// Generated by hazo_auth - do not edit manually
|
|
97
104
|
// Page: /${page.path}
|
|
98
105
|
import { ${page.component_name} } from "hazo_auth/pages";
|
|
99
106
|
|
|
100
|
-
export default
|
|
107
|
+
export default function Page() {
|
|
108
|
+
return <${page.component_name} />;
|
|
109
|
+
}
|
|
101
110
|
`;
|
|
102
111
|
}
|
|
103
112
|
// section: api_route_generation
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./contexts/hazo_auth_provider.js";
|
|
2
2
|
export * from "./contexts/hazo_auth_config.js";
|
|
3
3
|
export * from "./components/index.js";
|
|
4
|
-
export type { HazoAuthUser, HazoAuthResult, HazoAuthError, HazoAuthOptions, ScopeDetails,
|
|
4
|
+
export type { HazoAuthUser, HazoAuthResult, HazoAuthError, HazoAuthOptions, ScopeDetails, SelectedScope, TenantAuthOptions, TenantAuthResult, RequiredTenantAuthResult, } from "./lib/auth/auth_types";
|
|
5
5
|
export { AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError, } from "./lib/auth/auth_types.js";
|
|
6
6
|
export { cn, merge_class_names } from "./lib/utils.js";
|
|
7
7
|
export { HAZO_AUTH_PERMISSIONS, ALL_ADMIN_PERMISSIONS } from "./lib/constants.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -103,10 +103,11 @@ export type ScopeDetails = {
|
|
|
103
103
|
tagline: string | null;
|
|
104
104
|
};
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
107
|
-
* Simplified view of scope
|
|
106
|
+
* Currently selected scope information returned in tenant auth results.
|
|
107
|
+
* Simplified view of the scope chosen via the scope-selection cookie or
|
|
108
|
+
* `X-Hazo-Scope-Id` header.
|
|
108
109
|
*/
|
|
109
|
-
export type
|
|
110
|
+
export type SelectedScope = {
|
|
110
111
|
id: string;
|
|
111
112
|
name: string;
|
|
112
113
|
slug: string | null;
|
|
@@ -144,9 +145,9 @@ export type TenantAuthResult = {
|
|
|
144
145
|
permissions: string[];
|
|
145
146
|
permission_ok: boolean;
|
|
146
147
|
missing_permissions?: string[];
|
|
147
|
-
|
|
148
|
-
/** Shorthand for
|
|
149
|
-
|
|
148
|
+
selected_scope: SelectedScope | null;
|
|
149
|
+
/** Shorthand for selected_scope?.id - commonly used for DB query filters. */
|
|
150
|
+
selected_scope_id: string | null;
|
|
150
151
|
user_scopes: ScopeDetails[];
|
|
151
152
|
scope_ok?: boolean;
|
|
152
153
|
scope_access_via?: ScopeAccessInfo;
|
|
@@ -155,19 +156,19 @@ export type TenantAuthResult = {
|
|
|
155
156
|
user: null;
|
|
156
157
|
permissions: [];
|
|
157
158
|
permission_ok: false;
|
|
158
|
-
|
|
159
|
-
/** Shorthand for
|
|
160
|
-
|
|
159
|
+
selected_scope: null;
|
|
160
|
+
/** Shorthand for selected_scope?.id - commonly used for DB query filters. */
|
|
161
|
+
selected_scope_id: null;
|
|
161
162
|
user_scopes: [];
|
|
162
163
|
scope_ok?: false;
|
|
163
164
|
};
|
|
164
165
|
/**
|
|
165
|
-
* Guaranteed authenticated result with non-null
|
|
166
|
-
* Returned by require_tenant_auth when validation passes
|
|
166
|
+
* Guaranteed authenticated result with non-null selected_scope.
|
|
167
|
+
* Returned by require_tenant_auth when validation passes.
|
|
167
168
|
*/
|
|
168
169
|
export type RequiredTenantAuthResult = TenantAuthResult & {
|
|
169
170
|
authenticated: true;
|
|
170
|
-
|
|
171
|
+
selected_scope: SelectedScope;
|
|
171
172
|
};
|
|
172
173
|
/**
|
|
173
174
|
* Base error class for all hazo_auth errors
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth_types.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth_types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth_types.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth_types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// file_description: Type definitions and error classes for hazo_get_auth utility
|
|
2
|
+
//
|
|
3
|
+
// Naming note (v6.0.0): the field previously called `organization` (and
|
|
4
|
+
// `organization_id`) on `TenantAuthResult` was renamed to `selected_scope`
|
|
5
|
+
// (and `selected_scope_id`), and the type `TenantOrganization` was renamed
|
|
6
|
+
// to `SelectedScope`. The multi-tenancy model is scopes throughout; the
|
|
7
|
+
// old name was a legacy synonym for "the currently selected scope" derived
|
|
8
|
+
// from the scope-selection cookie/header. No deprecation shim is provided.
|
|
9
|
+
//
|
|
2
10
|
// section: types
|
|
3
11
|
/**
|
|
4
12
|
* Custom error class for permission denials
|
|
@@ -13,20 +13,21 @@ export declare function extract_scope_id_from_request(request: NextRequest, opti
|
|
|
13
13
|
* Tenant-aware authentication function
|
|
14
14
|
*
|
|
15
15
|
* Extracts tenant/scope context from request headers or cookies,
|
|
16
|
-
* validates access, and returns enriched result
|
|
16
|
+
* validates access, and returns enriched result including the currently
|
|
17
|
+
* selected scope.
|
|
17
18
|
*
|
|
18
19
|
* Header priority: X-Hazo-Scope-Id > Cookie
|
|
19
20
|
*
|
|
20
21
|
* @param request - NextRequest object
|
|
21
22
|
* @param options - TenantAuthOptions for customization
|
|
22
|
-
* @returns TenantAuthResult with user, permissions,
|
|
23
|
+
* @returns TenantAuthResult with user, permissions, selected_scope, and user_scopes
|
|
23
24
|
*
|
|
24
25
|
* @example
|
|
25
26
|
* ```typescript
|
|
26
27
|
* const auth = await hazo_get_tenant_auth(request);
|
|
27
|
-
* if (auth.authenticated && auth.
|
|
28
|
+
* if (auth.authenticated && auth.selected_scope) {
|
|
28
29
|
* // Access tenant-specific data
|
|
29
|
-
* const data = await getData(auth.
|
|
30
|
+
* const data = await getData(auth.selected_scope.id);
|
|
30
31
|
* }
|
|
31
32
|
* ```
|
|
32
33
|
*/
|
|
@@ -41,15 +42,15 @@ export declare function hazo_get_tenant_auth(request: NextRequest, options?: Ten
|
|
|
41
42
|
*
|
|
42
43
|
* @param request - NextRequest object
|
|
43
44
|
* @param options - TenantAuthOptions for customization
|
|
44
|
-
* @returns RequiredTenantAuthResult with guaranteed non-null
|
|
45
|
+
* @returns RequiredTenantAuthResult with guaranteed non-null selected_scope
|
|
45
46
|
* @throws AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError
|
|
46
47
|
*
|
|
47
48
|
* @example
|
|
48
49
|
* ```typescript
|
|
49
50
|
* try {
|
|
50
51
|
* const auth = await require_tenant_auth(request);
|
|
51
|
-
* // auth.
|
|
52
|
-
* const data = await getData(auth.
|
|
52
|
+
* // auth.selected_scope is guaranteed non-null here
|
|
53
|
+
* const data = await getData(auth.selected_scope.id);
|
|
53
54
|
* } catch (error) {
|
|
54
55
|
* if (error instanceof HazoAuthError) {
|
|
55
56
|
* return NextResponse.json(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_get_tenant_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/hazo_get_tenant_auth.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EAGzB,MAAM,cAAc,CAAC;AAqBtB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,iBAAiB,GACzB,MAAM,GAAG,SAAS,CAYpB;AAiCD
|
|
1
|
+
{"version":3,"file":"hazo_get_tenant_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/hazo_get_tenant_auth.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EAGzB,MAAM,cAAc,CAAC;AAqBtB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,iBAAiB,GACzB,MAAM,GAAG,SAAS,CAYpB;AAiCD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CA0F3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,wBAAwB,CAAC,CA0BnC"}
|
|
@@ -39,12 +39,12 @@ export function extract_scope_id_from_request(request, options) {
|
|
|
39
39
|
return cookie_value;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Builds
|
|
42
|
+
* Builds SelectedScope from scope details and access info.
|
|
43
43
|
* @param scope_details - Full scope details from cache
|
|
44
44
|
* @param is_super_admin - Whether user is accessing as super admin
|
|
45
|
-
* @returns
|
|
45
|
+
* @returns SelectedScope object
|
|
46
46
|
*/
|
|
47
|
-
function
|
|
47
|
+
function build_selected_scope(scope_details, is_super_admin) {
|
|
48
48
|
return {
|
|
49
49
|
id: scope_details.id,
|
|
50
50
|
name: scope_details.name,
|
|
@@ -67,20 +67,21 @@ function build_tenant_organization(scope_details, is_super_admin) {
|
|
|
67
67
|
* Tenant-aware authentication function
|
|
68
68
|
*
|
|
69
69
|
* Extracts tenant/scope context from request headers or cookies,
|
|
70
|
-
* validates access, and returns enriched result
|
|
70
|
+
* validates access, and returns enriched result including the currently
|
|
71
|
+
* selected scope.
|
|
71
72
|
*
|
|
72
73
|
* Header priority: X-Hazo-Scope-Id > Cookie
|
|
73
74
|
*
|
|
74
75
|
* @param request - NextRequest object
|
|
75
76
|
* @param options - TenantAuthOptions for customization
|
|
76
|
-
* @returns TenantAuthResult with user, permissions,
|
|
77
|
+
* @returns TenantAuthResult with user, permissions, selected_scope, and user_scopes
|
|
77
78
|
*
|
|
78
79
|
* @example
|
|
79
80
|
* ```typescript
|
|
80
81
|
* const auth = await hazo_get_tenant_auth(request);
|
|
81
|
-
* if (auth.authenticated && auth.
|
|
82
|
+
* if (auth.authenticated && auth.selected_scope) {
|
|
82
83
|
* // Access tenant-specific data
|
|
83
|
-
* const data = await getData(auth.
|
|
84
|
+
* const data = await getData(auth.selected_scope.id);
|
|
84
85
|
* }
|
|
85
86
|
* ```
|
|
86
87
|
*/
|
|
@@ -98,8 +99,8 @@ export async function hazo_get_tenant_auth(request, options = {}) {
|
|
|
98
99
|
user: null,
|
|
99
100
|
permissions: [],
|
|
100
101
|
permission_ok: false,
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
selected_scope: null,
|
|
103
|
+
selected_scope_id: null,
|
|
103
104
|
user_scopes: [],
|
|
104
105
|
scope_ok: false,
|
|
105
106
|
};
|
|
@@ -110,20 +111,20 @@ export async function hazo_get_tenant_auth(request, options = {}) {
|
|
|
110
111
|
const cached = cache.get(auth_result.user.id);
|
|
111
112
|
// User scopes from cache or empty array
|
|
112
113
|
const user_scopes = (cached === null || cached === void 0 ? void 0 : cached.scopes) || [];
|
|
113
|
-
// Build
|
|
114
|
-
let
|
|
114
|
+
// Build selected_scope info if scope access was successful
|
|
115
|
+
let selected_scope = null;
|
|
115
116
|
if (scope_id && auth_result.scope_ok && auth_result.scope_access_via) {
|
|
116
117
|
// Find the scope in user's scopes that matches the access_via scope
|
|
117
118
|
const access_scope = user_scopes.find((s) => { var _a; return s.id === ((_a = auth_result.scope_access_via) === null || _a === void 0 ? void 0 : _a.scope_id); });
|
|
118
119
|
if (access_scope) {
|
|
119
|
-
|
|
120
|
+
selected_scope = build_selected_scope(access_scope, auth_result.scope_access_via.is_super_admin || false);
|
|
120
121
|
}
|
|
121
122
|
else if (auth_result.scope_access_via.is_super_admin) {
|
|
122
123
|
// Super admin accessing scope they're not assigned to - fetch scope details
|
|
123
124
|
const hazoConnect = get_hazo_connect_instance();
|
|
124
125
|
const scope_result = await get_scope_by_id(hazoConnect, scope_id);
|
|
125
126
|
if (scope_result.success && scope_result.scope) {
|
|
126
|
-
|
|
127
|
+
selected_scope = {
|
|
127
128
|
id: scope_result.scope.id,
|
|
128
129
|
name: scope_result.scope.name,
|
|
129
130
|
slug: null, // Could fetch from scope if slug column exists
|
|
@@ -148,8 +149,8 @@ export async function hazo_get_tenant_auth(request, options = {}) {
|
|
|
148
149
|
permissions: auth_result.permissions,
|
|
149
150
|
permission_ok: auth_result.permission_ok,
|
|
150
151
|
missing_permissions: auth_result.missing_permissions,
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
selected_scope,
|
|
153
|
+
selected_scope_id: (selected_scope === null || selected_scope === void 0 ? void 0 : selected_scope.id) || null,
|
|
153
154
|
user_scopes,
|
|
154
155
|
scope_ok: auth_result.scope_ok,
|
|
155
156
|
scope_access_via: auth_result.scope_access_via,
|
|
@@ -165,15 +166,15 @@ export async function hazo_get_tenant_auth(request, options = {}) {
|
|
|
165
166
|
*
|
|
166
167
|
* @param request - NextRequest object
|
|
167
168
|
* @param options - TenantAuthOptions for customization
|
|
168
|
-
* @returns RequiredTenantAuthResult with guaranteed non-null
|
|
169
|
+
* @returns RequiredTenantAuthResult with guaranteed non-null selected_scope
|
|
169
170
|
* @throws AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError
|
|
170
171
|
*
|
|
171
172
|
* @example
|
|
172
173
|
* ```typescript
|
|
173
174
|
* try {
|
|
174
175
|
* const auth = await require_tenant_auth(request);
|
|
175
|
-
* // auth.
|
|
176
|
-
* const data = await getData(auth.
|
|
176
|
+
* // auth.selected_scope is guaranteed non-null here
|
|
177
|
+
* const data = await getData(auth.selected_scope.id);
|
|
177
178
|
* } catch (error) {
|
|
178
179
|
* if (error instanceof HazoAuthError) {
|
|
179
180
|
* return NextResponse.json(
|
|
@@ -197,10 +198,10 @@ export async function require_tenant_auth(request, options = {}) {
|
|
|
197
198
|
if (scope_id && !result.scope_ok) {
|
|
198
199
|
throw new TenantAccessDeniedError(scope_id, result.user_scopes);
|
|
199
200
|
}
|
|
200
|
-
// Check if
|
|
201
|
-
if (!result.
|
|
202
|
-
throw new TenantRequiredError("No
|
|
201
|
+
// Check if scope context is required but missing
|
|
202
|
+
if (!result.selected_scope) {
|
|
203
|
+
throw new TenantRequiredError("No tenant scope context provided. Include X-Hazo-Scope-Id header or scope cookie.", result.user_scopes);
|
|
203
204
|
}
|
|
204
|
-
// Type assertion: at this point we know
|
|
205
|
+
// Type assertion: at this point we know selected_scope is non-null
|
|
205
206
|
return result;
|
|
206
207
|
}
|
package/dist/lib/auth/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export { get_authenticated_user, require_auth, is_authenticated, } from "./auth_
|
|
|
4
4
|
export type { AuthResult, AuthUser } from "./auth_utils.server";
|
|
5
5
|
export { ensure_anon_id } from "./ensure_anon_id.server.js";
|
|
6
6
|
export { hazo_get_tenant_auth, require_tenant_auth, extract_scope_id_from_request, } from "./hazo_get_tenant_auth.server.js";
|
|
7
|
-
export type { ScopeDetails,
|
|
7
|
+
export type { ScopeDetails, SelectedScope, TenantAuthOptions, TenantAuthResult, RequiredTenantAuthResult, } from "./auth_types";
|
|
8
8
|
export { HazoAuthError, AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError, } from "./auth_types.js";
|
|
9
9
|
export { get_server_auth_user } from "./server_auth.js";
|
|
10
10
|
export type { ServerAuthResult } from "./server_auth";
|
|
11
11
|
export { withAuth, withOptionalAuth, hasPermission, hasAllPermissions, hasAnyPermission, requirePermission, requireAllPermissions, } from "./with_auth.server.js";
|
|
12
|
-
export type { AuthenticatedTenantAuth,
|
|
12
|
+
export type { AuthenticatedTenantAuth, AuthenticatedTenantAuthWithSelectedScope, WithAuthOptions, } from "./with_auth.server";
|
|
13
13
|
export { get_auth_cache, reset_auth_cache } from "./auth_cache.js";
|
|
14
14
|
export { get_rate_limiter, reset_rate_limiter } from "./auth_rate_limiter.js";
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,YAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,wCAAwC,EACxC,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "server-only";
|
|
2
2
|
import { NextRequest, NextResponse } from "next/server";
|
|
3
|
-
import { type TenantAuthOptions, type TenantAuthResult, type
|
|
3
|
+
import { type TenantAuthOptions, type TenantAuthResult, type SelectedScope, type HazoAuthUser, type ScopeDetails, type ScopeAccessInfo } from "./auth_types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Authenticated branch of TenantAuthResult - guaranteed authenticated: true
|
|
6
6
|
*/
|
|
@@ -10,18 +10,18 @@ export type AuthenticatedTenantAuth = {
|
|
|
10
10
|
permissions: string[];
|
|
11
11
|
permission_ok: boolean;
|
|
12
12
|
missing_permissions?: string[];
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
selected_scope: SelectedScope | null;
|
|
14
|
+
selected_scope_id: string | null;
|
|
15
15
|
user_scopes: ScopeDetails[];
|
|
16
16
|
scope_ok?: boolean;
|
|
17
17
|
scope_access_via?: ScopeAccessInfo;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
* Authenticated branch with guaranteed non-null
|
|
20
|
+
* Authenticated branch with guaranteed non-null selected_scope
|
|
21
21
|
*/
|
|
22
|
-
export type
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
export type AuthenticatedTenantAuthWithSelectedScope = AuthenticatedTenantAuth & {
|
|
23
|
+
selected_scope: SelectedScope;
|
|
24
|
+
selected_scope_id: string;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
27
|
* Options for withAuth/withOptionalAuth wrappers
|
|
@@ -29,8 +29,8 @@ export type AuthenticatedTenantAuthWithOrg = AuthenticatedTenantAuth & {
|
|
|
29
29
|
*/
|
|
30
30
|
export type WithAuthOptions = TenantAuthOptions & {
|
|
31
31
|
/**
|
|
32
|
-
* If true, requires
|
|
33
|
-
* Narrows auth type to
|
|
32
|
+
* If true, requires tenant/scope context (403 if missing)
|
|
33
|
+
* Narrows auth type to AuthenticatedTenantAuthWithSelectedScope
|
|
34
34
|
*/
|
|
35
35
|
require_tenant?: boolean;
|
|
36
36
|
};
|
|
@@ -47,7 +47,7 @@ type AuthenticatedHandler<TParams> = (request: NextRequest, auth: AuthenticatedT
|
|
|
47
47
|
/**
|
|
48
48
|
* Handler function signature for withAuth with require_tenant
|
|
49
49
|
*/
|
|
50
|
-
type AuthenticatedTenantHandler<TParams> = (request: NextRequest, auth:
|
|
50
|
+
type AuthenticatedTenantHandler<TParams> = (request: NextRequest, auth: AuthenticatedTenantAuthWithSelectedScope, params: TParams) => Promise<NextResponse> | NextResponse;
|
|
51
51
|
/**
|
|
52
52
|
* Handler function signature for withOptionalAuth
|
|
53
53
|
*/
|
|
@@ -57,7 +57,7 @@ type OptionalAuthHandler<TParams> = (request: NextRequest, auth: TenantAuthResul
|
|
|
57
57
|
*
|
|
58
58
|
* - Calls `hazo_get_tenant_auth` and returns 401 if not authenticated
|
|
59
59
|
* - Returns 403 if `required_permissions` are specified and not satisfied
|
|
60
|
-
* - Returns 403 if `require_tenant: true` and no
|
|
60
|
+
* - Returns 403 if `require_tenant: true` and no tenant/scope context
|
|
61
61
|
* - Resolves `await context.params` (Next.js 15 pattern)
|
|
62
62
|
* - Catches HazoAuthError, PermissionError, and unexpected errors
|
|
63
63
|
*
|
|
@@ -80,8 +80,8 @@ type OptionalAuthHandler<TParams> = (request: NextRequest, auth: TenantAuthResul
|
|
|
80
80
|
* // With tenant requirement
|
|
81
81
|
* export const GET = withAuth<{ id: string }>(
|
|
82
82
|
* async (request, auth, { id }) => {
|
|
83
|
-
* // auth.
|
|
84
|
-
* const data = await getData(auth.
|
|
83
|
+
* // auth.selected_scope is guaranteed non-null
|
|
84
|
+
* const data = await getData(auth.selected_scope.id, id);
|
|
85
85
|
* return NextResponse.json(data);
|
|
86
86
|
* },
|
|
87
87
|
* { require_tenant: true }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"with_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/with_auth.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,
|
|
1
|
+
{"version":3,"file":"with_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/with_auth.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,9 +50,9 @@ export function withAuth(handler, options = {}) {
|
|
|
50
50
|
})), { status: 403 });
|
|
51
51
|
}
|
|
52
52
|
// Check tenant requirement
|
|
53
|
-
if (options.require_tenant && !auth.
|
|
53
|
+
if (options.require_tenant && !auth.selected_scope) {
|
|
54
54
|
return NextResponse.json({
|
|
55
|
-
error: "
|
|
55
|
+
error: "Tenant scope context required",
|
|
56
56
|
code: "TENANT_REQUIRED",
|
|
57
57
|
}, { status: 403 });
|
|
58
58
|
}
|
|
@@ -50,6 +50,6 @@ export type ForgotPasswordPageProps = {
|
|
|
50
50
|
* @param props - Optional visual and navigation customization props
|
|
51
51
|
* @returns Server-rendered forgot password page
|
|
52
52
|
*/
|
|
53
|
-
export default function ForgotPasswordPage(
|
|
53
|
+
export default function ForgotPasswordPage(props: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
54
54
|
export { ForgotPasswordPage };
|
|
55
55
|
//# sourceMappingURL=forgot_password.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forgot_password.d.ts","sourceRoot":"","sources":["../../src/server_pages/forgot_password.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"forgot_password.d.ts","sourceRoot":"","sources":["../../src/server_pages/forgot_password.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,2CAiCxE;AAGD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -31,7 +31,8 @@ import { DEFAULT_FORGOT_PASSWORD } from "../lib/config/default_config.js";
|
|
|
31
31
|
* @param props - Optional visual and navigation customization props
|
|
32
32
|
* @returns Server-rendered forgot password page
|
|
33
33
|
*/
|
|
34
|
-
export default function ForgotPasswordPage(
|
|
34
|
+
export default function ForgotPasswordPage(props) {
|
|
35
|
+
const { image_src, image_alt, image_background_color, sign_in_path = DEFAULT_FORGOT_PASSWORD.loginPath, sign_in_label = DEFAULT_FORGOT_PASSWORD.loginLabel, } = props !== null && props !== void 0 ? props : {};
|
|
35
36
|
// Load configuration from INI file (with defaults including asset images)
|
|
36
37
|
const config = get_forgot_password_config();
|
|
37
38
|
// Use props if provided, otherwise fall back to config (which includes default asset image)
|
|
@@ -52,6 +52,6 @@ export type LoginPageProps = {
|
|
|
52
52
|
* @param props - Optional visual customization props
|
|
53
53
|
* @returns Server-rendered login page
|
|
54
54
|
*/
|
|
55
|
-
export default function LoginPage(
|
|
55
|
+
export default function LoginPage(props: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
56
56
|
export { LoginPage };
|
|
57
57
|
//# sourceMappingURL=login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/server_pages/login.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACrC,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/server_pages/login.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACrC,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,KAAK,EAAE,cAAc,2CAiEtD;AAGD,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -32,7 +32,8 @@ import { FloatingHomeLink } from "../components/layouts/shared/components/floati
|
|
|
32
32
|
* @param props - Optional visual customization props
|
|
33
33
|
* @returns Server-rendered login page
|
|
34
34
|
*/
|
|
35
|
-
export default function LoginPage(
|
|
35
|
+
export default function LoginPage(props) {
|
|
36
|
+
const { image_src, image_alt, image_background_color, layout = "two_column", } = props !== null && props !== void 0 ? props : {};
|
|
36
37
|
// Load configuration from INI file (with defaults including asset images)
|
|
37
38
|
const config = get_login_config();
|
|
38
39
|
// Use props if provided, otherwise fall back to config (which includes default asset image)
|
|
@@ -50,6 +50,6 @@ export type MySettingsPageProps = {
|
|
|
50
50
|
* @param props - Optional className for custom styling
|
|
51
51
|
* @returns Server-rendered my settings component
|
|
52
52
|
*/
|
|
53
|
-
export default function MySettingsPage(
|
|
53
|
+
export default function MySettingsPage(props: MySettingsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
54
54
|
export { MySettingsPage };
|
|
55
55
|
//# sourceMappingURL=my_settings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"my_settings.d.ts","sourceRoot":"","sources":["../../src/server_pages/my_settings.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"my_settings.d.ts","sourceRoot":"","sources":["../../src/server_pages/my_settings.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAiChE;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -52,7 +52,8 @@ import { AuthPageShell } from "../components/layouts/shared/components/auth_page
|
|
|
52
52
|
* @param props - Optional className for custom styling
|
|
53
53
|
* @returns Server-rendered my settings component
|
|
54
54
|
*/
|
|
55
|
-
export default function MySettingsPage(
|
|
55
|
+
export default function MySettingsPage(props) {
|
|
56
|
+
const { className } = props !== null && props !== void 0 ? props : {};
|
|
56
57
|
// Load configuration from INI file (with defaults)
|
|
57
58
|
const config = get_my_settings_config();
|
|
58
59
|
// Render layout with all server-initialized configuration, wrapped in AuthPageShell for navbar support
|
|
@@ -48,6 +48,6 @@ export type RegisterPageProps = {
|
|
|
48
48
|
* @param props - Optional visual customization props
|
|
49
49
|
* @returns Server-rendered register page
|
|
50
50
|
*/
|
|
51
|
-
export default function RegisterPage(
|
|
51
|
+
export default function RegisterPage(props: RegisterPageProps): import("react/jsx-runtime").JSX.Element;
|
|
52
52
|
export { RegisterPage };
|
|
53
53
|
//# sourceMappingURL=register.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/server_pages/register.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACrC,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/server_pages/register.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACrC,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,iBAAiB,2CAuD5D;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -34,7 +34,8 @@ import { FloatingHomeLink } from "../components/layouts/shared/components/floati
|
|
|
34
34
|
* @param props - Optional visual customization props
|
|
35
35
|
* @returns Server-rendered register page
|
|
36
36
|
*/
|
|
37
|
-
export default function RegisterPage(
|
|
37
|
+
export default function RegisterPage(props) {
|
|
38
|
+
const { image_src, image_alt, image_background_color, layout = "two_column", } = props !== null && props !== void 0 ? props : {};
|
|
38
39
|
// Load configuration from INI file (with defaults including asset images)
|
|
39
40
|
const config = get_register_config();
|
|
40
41
|
// Use props if provided, otherwise fall back to config (which includes default asset image)
|
|
@@ -41,6 +41,6 @@ export type ResetPasswordPageProps = {
|
|
|
41
41
|
* @param props - Optional visual customization props
|
|
42
42
|
* @returns Server-rendered reset password page
|
|
43
43
|
*/
|
|
44
|
-
export default function ResetPasswordPage(
|
|
44
|
+
export default function ResetPasswordPage(props: ResetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
45
45
|
export { ResetPasswordPage };
|
|
46
46
|
//# sourceMappingURL=reset_password.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset_password.d.ts","sourceRoot":"","sources":["../../src/server_pages/reset_password.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"reset_password.d.ts","sourceRoot":"","sources":["../../src/server_pages/reset_password.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,2CAkCtE;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -31,7 +31,8 @@ import { AuthPageShell } from "../components/layouts/shared/components/auth_page
|
|
|
31
31
|
* @param props - Optional visual customization props
|
|
32
32
|
* @returns Server-rendered reset password page
|
|
33
33
|
*/
|
|
34
|
-
export default function ResetPasswordPage(
|
|
34
|
+
export default function ResetPasswordPage(props) {
|
|
35
|
+
const { image_src, image_alt, image_background_color, } = props !== null && props !== void 0 ? props : {};
|
|
35
36
|
// Load configuration from INI file (with defaults including asset images)
|
|
36
37
|
const config = get_reset_password_config();
|
|
37
38
|
// Use props if provided, otherwise fall back to config (which includes default asset image)
|
|
@@ -50,6 +50,6 @@ export type VerifyEmailPageProps = {
|
|
|
50
50
|
* @param props - Optional visual and behavior customization props
|
|
51
51
|
* @returns Server-rendered email verification page
|
|
52
52
|
*/
|
|
53
|
-
export default function VerifyEmailPage(
|
|
53
|
+
export default function VerifyEmailPage(props: VerifyEmailPageProps): import("react/jsx-runtime").JSX.Element;
|
|
54
54
|
export { VerifyEmailPage };
|
|
55
55
|
//# sourceMappingURL=verify_email.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify_email.d.ts","sourceRoot":"","sources":["../../src/server_pages/verify_email.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"verify_email.d.ts","sourceRoot":"","sources":["../../src/server_pages/verify_email.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAErC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CAiClE;AAGD,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -31,7 +31,8 @@ import { DEFAULT_EMAIL_VERIFICATION } from "../lib/config/default_config.js";
|
|
|
31
31
|
* @param props - Optional visual and behavior customization props
|
|
32
32
|
* @returns Server-rendered email verification page
|
|
33
33
|
*/
|
|
34
|
-
export default function VerifyEmailPage(
|
|
34
|
+
export default function VerifyEmailPage(props) {
|
|
35
|
+
const { image_src, image_alt, image_background_color, redirect_delay = DEFAULT_EMAIL_VERIFICATION.redirectDelay, login_path = DEFAULT_EMAIL_VERIFICATION.loginPath, } = props !== null && props !== void 0 ? props : {};
|
|
35
36
|
// Load configuration from INI file (with defaults including asset images)
|
|
36
37
|
const config = get_email_verification_config();
|
|
37
38
|
// Use props if provided, otherwise fall back to config (which includes default asset image)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authentication",
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
"@radix-ui/react-tabs": "^1.1.0",
|
|
251
251
|
"@radix-ui/react-tooltip": "^1.2.0",
|
|
252
252
|
"hazo_config": "^2.1.0",
|
|
253
|
-
"hazo_connect": "^2.
|
|
253
|
+
"hazo_connect": "^2.6.0",
|
|
254
254
|
"hazo_logs": "^1.0.13",
|
|
255
255
|
"hazo_notify": "^3.0.0",
|
|
256
256
|
"hazo_ui": "^2.7.0",
|
|
@@ -374,7 +374,7 @@
|
|
|
374
374
|
"eslint-plugin-storybook": "^10.0.6",
|
|
375
375
|
"@tailwindcss/postcss": "^4.2.4",
|
|
376
376
|
"hazo_config": "^2.1.0",
|
|
377
|
-
"hazo_connect": "^2.
|
|
377
|
+
"hazo_connect": "^2.6.0",
|
|
378
378
|
"hazo_logs": "^1.0.13",
|
|
379
379
|
"hazo_notify": "^3.0.0",
|
|
380
380
|
"hazo_ui": "^2.7.0",
|