@inai-dev/astro 0.1.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 +61 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +127 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.d.ts +9 -0
- package/dist/middleware.js +55 -0
- package/dist/middleware.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +52 -0
- package/dist/server.js.map +1 -0
- package/package.json +56 -0
- package/src/components/signed-in.astro +6 -0
- package/src/components/signed-out.astro +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @inai-dev/astro
|
|
2
|
+
|
|
3
|
+
Astro integration for InAI Auth. Provides middleware, server-side helpers, and Astro components for authentication.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @inai-dev/astro
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
### 1. Add Integration
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// astro.config.mjs
|
|
17
|
+
import { defineConfig } from "astro/config";
|
|
18
|
+
import inaiAuth from "@inai-dev/astro";
|
|
19
|
+
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
integrations: [
|
|
22
|
+
inaiAuth({
|
|
23
|
+
publishableKey: import.meta.env.INAI_PUBLISHABLE_KEY,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Use in Pages
|
|
30
|
+
|
|
31
|
+
```astro
|
|
32
|
+
---
|
|
33
|
+
// src/pages/dashboard.astro
|
|
34
|
+
const auth = Astro.locals.auth;
|
|
35
|
+
if (!auth?.userId) return Astro.redirect("/sign-in");
|
|
36
|
+
---
|
|
37
|
+
<p>Welcome {auth.user.email}</p>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 3. API Endpoints
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// src/pages/api/auth/[...path].ts
|
|
44
|
+
import { handleAuthRoutes } from "@inai-dev/astro/server";
|
|
45
|
+
export const ALL = handleAuthRoutes();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Exports
|
|
49
|
+
|
|
50
|
+
- `@inai-dev/astro` — Astro integration function
|
|
51
|
+
- `@inai-dev/astro/middleware` — Auth middleware
|
|
52
|
+
- `@inai-dev/astro/server` — Server-side helpers and API route handlers
|
|
53
|
+
|
|
54
|
+
## Documentation
|
|
55
|
+
|
|
56
|
+
- [Astro Integration](https://github.com/inai-dev/sdk/blob/main/docs/astro-integration.md)
|
|
57
|
+
- [API Reference](https://github.com/inai-dev/sdk/blob/main/docs/api-reference.md)
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
[MIT](../../LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AstroIntegration } from 'astro';
|
|
2
|
+
export { InAIAstroMiddlewareConfig, inaiAstroMiddleware } from './middleware.js';
|
|
3
|
+
export { auth, currentUser } from './server.js';
|
|
4
|
+
export { AuthObject, OrganizationResource, UserResource } from '@inai-dev/types';
|
|
5
|
+
|
|
6
|
+
interface InAIAstroConfig {
|
|
7
|
+
apiUrl: string;
|
|
8
|
+
publishableKey?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function inaiAuth(config: InAIAstroConfig): AstroIntegration;
|
|
11
|
+
|
|
12
|
+
export { type InAIAstroConfig, inaiAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// src/integration.ts
|
|
2
|
+
function inaiAuth(config) {
|
|
3
|
+
return {
|
|
4
|
+
name: "@inai-dev/astro",
|
|
5
|
+
hooks: {
|
|
6
|
+
"astro:config:setup": ({ updateConfig }) => {
|
|
7
|
+
updateConfig({
|
|
8
|
+
vite: {
|
|
9
|
+
define: {
|
|
10
|
+
"import.meta.env.INAI_API_URL": JSON.stringify(config.apiUrl),
|
|
11
|
+
"import.meta.env.INAI_PUBLISHABLE_KEY": JSON.stringify(
|
|
12
|
+
config.publishableKey ?? ""
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/middleware.ts
|
|
23
|
+
import {
|
|
24
|
+
COOKIE_AUTH_TOKEN,
|
|
25
|
+
getClaimsFromToken,
|
|
26
|
+
isTokenExpired
|
|
27
|
+
} from "@inai-dev/shared";
|
|
28
|
+
function inaiAstroMiddleware(config = {}) {
|
|
29
|
+
const { publicRoutes = [], signInUrl = "/login" } = config;
|
|
30
|
+
return async (context, next) => {
|
|
31
|
+
const { pathname } = context.url;
|
|
32
|
+
const isPublic = publicRoutes.some((route) => {
|
|
33
|
+
if (route.endsWith("*")) {
|
|
34
|
+
return pathname.startsWith(route.slice(0, -1));
|
|
35
|
+
}
|
|
36
|
+
return pathname === route;
|
|
37
|
+
}) || pathname === signInUrl || pathname.startsWith("/_") || pathname.startsWith("/api/");
|
|
38
|
+
if (isPublic) {
|
|
39
|
+
return next();
|
|
40
|
+
}
|
|
41
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;
|
|
42
|
+
if (!token || isTokenExpired(token)) {
|
|
43
|
+
return context.redirect(
|
|
44
|
+
`${signInUrl}?returnTo=${encodeURIComponent(pathname)}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const claims = getClaimsFromToken(token);
|
|
48
|
+
if (!claims) {
|
|
49
|
+
return context.redirect(signInUrl);
|
|
50
|
+
}
|
|
51
|
+
const roles = claims.roles ?? [];
|
|
52
|
+
const permissions = claims.permissions ?? [];
|
|
53
|
+
const authObject = {
|
|
54
|
+
userId: claims.sub,
|
|
55
|
+
tenantId: claims.tenant_id,
|
|
56
|
+
appId: claims.app_id ?? null,
|
|
57
|
+
envId: claims.env_id ?? null,
|
|
58
|
+
orgId: claims.org_id ?? null,
|
|
59
|
+
orgRole: claims.org_role ?? null,
|
|
60
|
+
sessionId: null,
|
|
61
|
+
getToken: async () => token,
|
|
62
|
+
has: (params) => {
|
|
63
|
+
if (params.role && roles.includes(params.role)) return true;
|
|
64
|
+
if (params.permission && permissions.includes(params.permission))
|
|
65
|
+
return true;
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
context.locals.auth = authObject;
|
|
70
|
+
return next();
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/server.ts
|
|
75
|
+
import { InAIAuthClient } from "@inai-dev/backend";
|
|
76
|
+
import {
|
|
77
|
+
COOKIE_AUTH_TOKEN as COOKIE_AUTH_TOKEN2,
|
|
78
|
+
getClaimsFromToken as getClaimsFromToken2,
|
|
79
|
+
isTokenExpired as isTokenExpired2
|
|
80
|
+
} from "@inai-dev/shared";
|
|
81
|
+
function auth(context) {
|
|
82
|
+
const existing = context.locals.auth;
|
|
83
|
+
if (existing) return existing;
|
|
84
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN2)?.value;
|
|
85
|
+
if (!token || isTokenExpired2(token)) return null;
|
|
86
|
+
const claims = getClaimsFromToken2(token);
|
|
87
|
+
if (!claims) return null;
|
|
88
|
+
const roles = claims.roles ?? [];
|
|
89
|
+
const permissions = claims.permissions ?? [];
|
|
90
|
+
return {
|
|
91
|
+
userId: claims.sub,
|
|
92
|
+
tenantId: claims.tenant_id,
|
|
93
|
+
appId: claims.app_id ?? null,
|
|
94
|
+
envId: claims.env_id ?? null,
|
|
95
|
+
orgId: claims.org_id ?? null,
|
|
96
|
+
orgRole: claims.org_role ?? null,
|
|
97
|
+
sessionId: null,
|
|
98
|
+
getToken: async () => token,
|
|
99
|
+
has: (params) => {
|
|
100
|
+
if (params.role && roles.includes(params.role)) return true;
|
|
101
|
+
if (params.permission && permissions.includes(params.permission))
|
|
102
|
+
return true;
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async function currentUser(context, config) {
|
|
108
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN2)?.value;
|
|
109
|
+
if (!token || isTokenExpired2(token)) return null;
|
|
110
|
+
const client = new InAIAuthClient({
|
|
111
|
+
apiUrl: config.apiUrl,
|
|
112
|
+
publishableKey: config.publishableKey
|
|
113
|
+
});
|
|
114
|
+
try {
|
|
115
|
+
const { data } = await client.getMe(token);
|
|
116
|
+
return data;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export {
|
|
122
|
+
auth,
|
|
123
|
+
currentUser,
|
|
124
|
+
inaiAstroMiddleware,
|
|
125
|
+
inaiAuth
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/integration.ts","../src/middleware.ts","../src/server.ts"],"sourcesContent":["import type { AstroIntegration } from \"astro\";\n\nexport interface InAIAstroConfig {\n apiUrl: string;\n publishableKey?: string;\n}\n\nexport function inaiAuth(config: InAIAstroConfig): AstroIntegration {\n return {\n name: \"@inai-dev/astro\",\n hooks: {\n \"astro:config:setup\": ({ updateConfig }) => {\n updateConfig({\n vite: {\n define: {\n \"import.meta.env.INAI_API_URL\": JSON.stringify(config.apiUrl),\n \"import.meta.env.INAI_PUBLISHABLE_KEY\": JSON.stringify(\n config.publishableKey ?? \"\",\n ),\n },\n },\n });\n },\n },\n };\n}\n","import type { MiddlewareHandler } from \"astro\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIAstroMiddlewareConfig {\n publicRoutes?: string[];\n signInUrl?: string;\n}\n\nexport function inaiAstroMiddleware(\n config: InAIAstroMiddlewareConfig = {},\n): MiddlewareHandler {\n const { publicRoutes = [], signInUrl = \"/login\" } = config;\n\n return async (context, next) => {\n const { pathname } = context.url;\n\n const isPublic =\n publicRoutes.some((route) => {\n if (route.endsWith(\"*\")) {\n return pathname.startsWith(route.slice(0, -1));\n }\n return pathname === route;\n }) ||\n pathname === signInUrl ||\n pathname.startsWith(\"/_\") ||\n pathname.startsWith(\"/api/\");\n\n if (isPublic) {\n return next();\n }\n\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n return context.redirect(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n );\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return context.redirect(signInUrl);\n }\n\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n\n const authObject: AuthObject = {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n\n (context.locals as Record<string, unknown>).auth = authObject;\n\n return next();\n };\n}\n","import type { AuthObject, UserResource } from \"@inai-dev/types\";\nimport { InAIAuthClient } from \"@inai-dev/backend\";\nimport {\n COOKIE_AUTH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\ninterface AstroContext {\n cookies: {\n get(name: string): { value: string } | undefined;\n };\n locals: Record<string, unknown>;\n}\n\nexport function auth(context: AstroContext): AuthObject | null {\n const existing = (context.locals as Record<string, unknown>).auth as AuthObject | undefined;\n if (existing) return existing;\n\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n if (!token || isTokenExpired(token)) return null;\n\n const claims = getClaimsFromToken(token);\n if (!claims) return null;\n\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nexport async function currentUser(\n context: AstroContext,\n config: { apiUrl: string; publishableKey?: string },\n): Promise<UserResource | null> {\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n if (!token || isTokenExpired(token)) return null;\n\n const client = new InAIAuthClient({\n apiUrl: config.apiUrl,\n publishableKey: config.publishableKey,\n });\n\n try {\n const { data } = await client.getMe(token);\n return data;\n } catch {\n return null;\n }\n}\n"],"mappings":";AAOO,SAAS,SAAS,QAA2C;AAClE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,sBAAsB,CAAC,EAAE,aAAa,MAAM;AAC1C,qBAAa;AAAA,UACX,MAAM;AAAA,YACJ,QAAQ;AAAA,cACN,gCAAgC,KAAK,UAAU,OAAO,MAAM;AAAA,cAC5D,wCAAwC,KAAK;AAAA,gBAC3C,OAAO,kBAAkB;AAAA,cAC3B;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACvBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOA,SAAS,oBACd,SAAoC,CAAC,GAClB;AACnB,QAAM,EAAE,eAAe,CAAC,GAAG,YAAY,SAAS,IAAI;AAEpD,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,EAAE,SAAS,IAAI,QAAQ;AAE7B,UAAM,WACJ,aAAa,KAAK,CAAC,UAAU;AAC3B,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AACA,aAAO,aAAa;AAAA,IACtB,CAAC,KACD,aAAa,aACb,SAAS,WAAW,IAAI,KACxB,SAAS,WAAW,OAAO;AAE7B,QAAI,UAAU;AACZ,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AAEtD,QAAI,CAAC,SAAS,eAAe,KAAK,GAAG;AACnC,aAAO,QAAQ;AAAA,QACb,GAAG,SAAS,aAAa,mBAAmB,QAAQ,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,SAAS,mBAAmB,KAAK;AACvC,QAAI,CAAC,QAAQ;AACX,aAAO,QAAQ,SAAS,SAAS;AAAA,IACnC;AAEA,UAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,UAAM,cAAc,OAAO,eAAe,CAAC;AAE3C,UAAM,aAAyB;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,MACxB,SAAS,OAAO,YAAY;AAAA,MAC5B,WAAW;AAAA,MACX,UAAU,YAAY;AAAA,MACtB,KAAK,CAAC,WAAmD;AACvD,YAAI,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI,EAAG,QAAO;AACvD,YAAI,OAAO,cAAc,YAAY,SAAS,OAAO,UAAU;AAC7D,iBAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAEA,IAAC,QAAQ,OAAmC,OAAO;AAEnD,WAAO,KAAK;AAAA,EACd;AACF;;;ACxEA,SAAS,sBAAsB;AAC/B;AAAA,EACE,qBAAAA;AAAA,EACA,sBAAAC;AAAA,EACA,kBAAAC;AAAA,OACK;AASA,SAAS,KAAK,SAA0C;AAC7D,QAAM,WAAY,QAAQ,OAAmC;AAC7D,MAAI,SAAU,QAAO;AAErB,QAAM,QAAQ,QAAQ,QAAQ,IAAIF,kBAAiB,GAAG;AACtD,MAAI,CAAC,SAASE,gBAAe,KAAK,EAAG,QAAO;AAE5C,QAAM,SAASD,oBAAmB,KAAK;AACvC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,QAAM,cAAc,OAAO,eAAe,CAAC;AAE3C,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO,UAAU;AAAA,IACxB,OAAO,OAAO,UAAU;AAAA,IACxB,OAAO,OAAO,UAAU;AAAA,IACxB,SAAS,OAAO,YAAY;AAAA,IAC5B,WAAW;AAAA,IACX,UAAU,YAAY;AAAA,IACtB,KAAK,CAAC,WAAmD;AACvD,UAAI,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI,EAAG,QAAO;AACvD,UAAI,OAAO,cAAc,YAAY,SAAS,OAAO,UAAU;AAC7D,eAAO;AACT,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,YACpB,SACA,QAC8B;AAC9B,QAAM,QAAQ,QAAQ,QAAQ,IAAID,kBAAiB,GAAG;AACtD,MAAI,CAAC,SAASE,gBAAe,KAAK,EAAG,QAAO;AAE5C,QAAM,SAAS,IAAI,eAAe;AAAA,IAChC,QAAQ,OAAO;AAAA,IACf,gBAAgB,OAAO;AAAA,EACzB,CAAC;AAED,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,MAAM,KAAK;AACzC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":["COOKIE_AUTH_TOKEN","getClaimsFromToken","isTokenExpired"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MiddlewareHandler } from 'astro';
|
|
2
|
+
|
|
3
|
+
interface InAIAstroMiddlewareConfig {
|
|
4
|
+
publicRoutes?: string[];
|
|
5
|
+
signInUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function inaiAstroMiddleware(config?: InAIAstroMiddlewareConfig): MiddlewareHandler;
|
|
8
|
+
|
|
9
|
+
export { type InAIAstroMiddlewareConfig, inaiAstroMiddleware };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/middleware.ts
|
|
2
|
+
import {
|
|
3
|
+
COOKIE_AUTH_TOKEN,
|
|
4
|
+
getClaimsFromToken,
|
|
5
|
+
isTokenExpired
|
|
6
|
+
} from "@inai-dev/shared";
|
|
7
|
+
function inaiAstroMiddleware(config = {}) {
|
|
8
|
+
const { publicRoutes = [], signInUrl = "/login" } = config;
|
|
9
|
+
return async (context, next) => {
|
|
10
|
+
const { pathname } = context.url;
|
|
11
|
+
const isPublic = publicRoutes.some((route) => {
|
|
12
|
+
if (route.endsWith("*")) {
|
|
13
|
+
return pathname.startsWith(route.slice(0, -1));
|
|
14
|
+
}
|
|
15
|
+
return pathname === route;
|
|
16
|
+
}) || pathname === signInUrl || pathname.startsWith("/_") || pathname.startsWith("/api/");
|
|
17
|
+
if (isPublic) {
|
|
18
|
+
return next();
|
|
19
|
+
}
|
|
20
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;
|
|
21
|
+
if (!token || isTokenExpired(token)) {
|
|
22
|
+
return context.redirect(
|
|
23
|
+
`${signInUrl}?returnTo=${encodeURIComponent(pathname)}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
const claims = getClaimsFromToken(token);
|
|
27
|
+
if (!claims) {
|
|
28
|
+
return context.redirect(signInUrl);
|
|
29
|
+
}
|
|
30
|
+
const roles = claims.roles ?? [];
|
|
31
|
+
const permissions = claims.permissions ?? [];
|
|
32
|
+
const authObject = {
|
|
33
|
+
userId: claims.sub,
|
|
34
|
+
tenantId: claims.tenant_id,
|
|
35
|
+
appId: claims.app_id ?? null,
|
|
36
|
+
envId: claims.env_id ?? null,
|
|
37
|
+
orgId: claims.org_id ?? null,
|
|
38
|
+
orgRole: claims.org_role ?? null,
|
|
39
|
+
sessionId: null,
|
|
40
|
+
getToken: async () => token,
|
|
41
|
+
has: (params) => {
|
|
42
|
+
if (params.role && roles.includes(params.role)) return true;
|
|
43
|
+
if (params.permission && permissions.includes(params.permission))
|
|
44
|
+
return true;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
context.locals.auth = authObject;
|
|
49
|
+
return next();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
inaiAstroMiddleware
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import type { MiddlewareHandler } from \"astro\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIAstroMiddlewareConfig {\n publicRoutes?: string[];\n signInUrl?: string;\n}\n\nexport function inaiAstroMiddleware(\n config: InAIAstroMiddlewareConfig = {},\n): MiddlewareHandler {\n const { publicRoutes = [], signInUrl = \"/login\" } = config;\n\n return async (context, next) => {\n const { pathname } = context.url;\n\n const isPublic =\n publicRoutes.some((route) => {\n if (route.endsWith(\"*\")) {\n return pathname.startsWith(route.slice(0, -1));\n }\n return pathname === route;\n }) ||\n pathname === signInUrl ||\n pathname.startsWith(\"/_\") ||\n pathname.startsWith(\"/api/\");\n\n if (isPublic) {\n return next();\n }\n\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n return context.redirect(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n );\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return context.redirect(signInUrl);\n }\n\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n\n const authObject: AuthObject = {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n\n (context.locals as Record<string, unknown>).auth = authObject;\n\n return next();\n };\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOA,SAAS,oBACd,SAAoC,CAAC,GAClB;AACnB,QAAM,EAAE,eAAe,CAAC,GAAG,YAAY,SAAS,IAAI;AAEpD,SAAO,OAAO,SAAS,SAAS;AAC9B,UAAM,EAAE,SAAS,IAAI,QAAQ;AAE7B,UAAM,WACJ,aAAa,KAAK,CAAC,UAAU;AAC3B,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AACA,aAAO,aAAa;AAAA,IACtB,CAAC,KACD,aAAa,aACb,SAAS,WAAW,IAAI,KACxB,SAAS,WAAW,OAAO;AAE7B,QAAI,UAAU;AACZ,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AAEtD,QAAI,CAAC,SAAS,eAAe,KAAK,GAAG;AACnC,aAAO,QAAQ;AAAA,QACb,GAAG,SAAS,aAAa,mBAAmB,QAAQ,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,SAAS,mBAAmB,KAAK;AACvC,QAAI,CAAC,QAAQ;AACX,aAAO,QAAQ,SAAS,SAAS;AAAA,IACnC;AAEA,UAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,UAAM,cAAc,OAAO,eAAe,CAAC;AAE3C,UAAM,aAAyB;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,MACxB,SAAS,OAAO,YAAY;AAAA,MAC5B,WAAW;AAAA,MACX,UAAU,YAAY;AAAA,MACtB,KAAK,CAAC,WAAmD;AACvD,YAAI,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI,EAAG,QAAO;AACvD,YAAI,OAAO,cAAc,YAAY,SAAS,OAAO,UAAU;AAC7D,iBAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAEA,IAAC,QAAQ,OAAmC,OAAO;AAEnD,WAAO,KAAK;AAAA,EACd;AACF;","names":[]}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AuthObject, UserResource } from '@inai-dev/types';
|
|
2
|
+
|
|
3
|
+
interface AstroContext {
|
|
4
|
+
cookies: {
|
|
5
|
+
get(name: string): {
|
|
6
|
+
value: string;
|
|
7
|
+
} | undefined;
|
|
8
|
+
};
|
|
9
|
+
locals: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
declare function auth(context: AstroContext): AuthObject | null;
|
|
12
|
+
declare function currentUser(context: AstroContext, config: {
|
|
13
|
+
apiUrl: string;
|
|
14
|
+
publishableKey?: string;
|
|
15
|
+
}): Promise<UserResource | null>;
|
|
16
|
+
|
|
17
|
+
export { auth, currentUser };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import { InAIAuthClient } from "@inai-dev/backend";
|
|
3
|
+
import {
|
|
4
|
+
COOKIE_AUTH_TOKEN,
|
|
5
|
+
getClaimsFromToken,
|
|
6
|
+
isTokenExpired
|
|
7
|
+
} from "@inai-dev/shared";
|
|
8
|
+
function auth(context) {
|
|
9
|
+
const existing = context.locals.auth;
|
|
10
|
+
if (existing) return existing;
|
|
11
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;
|
|
12
|
+
if (!token || isTokenExpired(token)) return null;
|
|
13
|
+
const claims = getClaimsFromToken(token);
|
|
14
|
+
if (!claims) return null;
|
|
15
|
+
const roles = claims.roles ?? [];
|
|
16
|
+
const permissions = claims.permissions ?? [];
|
|
17
|
+
return {
|
|
18
|
+
userId: claims.sub,
|
|
19
|
+
tenantId: claims.tenant_id,
|
|
20
|
+
appId: claims.app_id ?? null,
|
|
21
|
+
envId: claims.env_id ?? null,
|
|
22
|
+
orgId: claims.org_id ?? null,
|
|
23
|
+
orgRole: claims.org_role ?? null,
|
|
24
|
+
sessionId: null,
|
|
25
|
+
getToken: async () => token,
|
|
26
|
+
has: (params) => {
|
|
27
|
+
if (params.role && roles.includes(params.role)) return true;
|
|
28
|
+
if (params.permission && permissions.includes(params.permission))
|
|
29
|
+
return true;
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function currentUser(context, config) {
|
|
35
|
+
const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;
|
|
36
|
+
if (!token || isTokenExpired(token)) return null;
|
|
37
|
+
const client = new InAIAuthClient({
|
|
38
|
+
apiUrl: config.apiUrl,
|
|
39
|
+
publishableKey: config.publishableKey
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
const { data } = await client.getMe(token);
|
|
43
|
+
return data;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
auth,
|
|
50
|
+
currentUser
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import type { AuthObject, UserResource } from \"@inai-dev/types\";\nimport { InAIAuthClient } from \"@inai-dev/backend\";\nimport {\n COOKIE_AUTH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\ninterface AstroContext {\n cookies: {\n get(name: string): { value: string } | undefined;\n };\n locals: Record<string, unknown>;\n}\n\nexport function auth(context: AstroContext): AuthObject | null {\n const existing = (context.locals as Record<string, unknown>).auth as AuthObject | undefined;\n if (existing) return existing;\n\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n if (!token || isTokenExpired(token)) return null;\n\n const claims = getClaimsFromToken(token);\n if (!claims) return null;\n\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nexport async function currentUser(\n context: AstroContext,\n config: { apiUrl: string; publishableKey?: string },\n): Promise<UserResource | null> {\n const token = context.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n if (!token || isTokenExpired(token)) return null;\n\n const client = new InAIAuthClient({\n apiUrl: config.apiUrl,\n publishableKey: config.publishableKey,\n });\n\n try {\n const { data } = await client.getMe(token);\n return data;\n } catch {\n return null;\n }\n}\n"],"mappings":";AACA,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASA,SAAS,KAAK,SAA0C;AAC7D,QAAM,WAAY,QAAQ,OAAmC;AAC7D,MAAI,SAAU,QAAO;AAErB,QAAM,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AACtD,MAAI,CAAC,SAAS,eAAe,KAAK,EAAG,QAAO;AAE5C,QAAM,SAAS,mBAAmB,KAAK;AACvC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,QAAM,cAAc,OAAO,eAAe,CAAC;AAE3C,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO,UAAU;AAAA,IACxB,OAAO,OAAO,UAAU;AAAA,IACxB,OAAO,OAAO,UAAU;AAAA,IACxB,SAAS,OAAO,YAAY;AAAA,IAC5B,WAAW;AAAA,IACX,UAAU,YAAY;AAAA,IACtB,KAAK,CAAC,WAAmD;AACvD,UAAI,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI,EAAG,QAAO;AACvD,UAAI,OAAO,cAAc,YAAY,SAAS,OAAO,UAAU;AAC7D,eAAO;AACT,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,YACpB,SACA,QAC8B;AAC9B,QAAM,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AACtD,MAAI,CAAC,SAAS,eAAe,KAAK,EAAG,QAAO;AAE5C,QAAM,SAAS,IAAI,eAAe;AAAA,IAChC,QAAQ,OAAO;AAAA,IACf,gBAAgB,OAAO;AAAA,EACzB,CAAC;AAED,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,MAAM,KAAK;AACzC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inai-dev/astro",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Astro integration for InAI Auth SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./middleware": {
|
|
14
|
+
"types": "./dist/middleware.d.ts",
|
|
15
|
+
"import": "./dist/middleware.js"
|
|
16
|
+
},
|
|
17
|
+
"./server": {
|
|
18
|
+
"types": "./dist/server.d.ts",
|
|
19
|
+
"import": "./dist/server.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": ["dist", "src/components"],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"dev": "tsup --watch",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@inai-dev/types": "^0.1.0",
|
|
32
|
+
"@inai-dev/shared": "^0.1.0",
|
|
33
|
+
"@inai-dev/backend": "^0.1.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"astro": ">=4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"astro": {
|
|
40
|
+
"optional": false
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"author": "InAI <contact@inai.dev>",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/InAI-Team/inai-auth-sdk.git",
|
|
51
|
+
"directory": "packages/astro"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://inai.dev/",
|
|
54
|
+
"bugs": "https://github.com/InAI-Team/inai-auth-sdk/issues",
|
|
55
|
+
"keywords": ["inai", "auth", "astro", "middleware", "multi-tenant", "ssg"]
|
|
56
|
+
}
|