astro-sessionkit 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +35 -4
- package/security.md +18 -0
package/dist/server.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ declare function hasRole(role: string): boolean;
|
|
|
16
16
|
declare function hasPermission(permission: string): boolean;
|
|
17
17
|
declare function hasAllPermissions(...permissions: string[]): boolean;
|
|
18
18
|
declare function hasAnyPermission(...permissions: string[]): boolean;
|
|
19
|
+
declare function hasRolePermission(role: string, permission: string): boolean;
|
|
19
20
|
declare function setSession(context: APIContext, session: Session): void;
|
|
20
21
|
declare function clearSession(context: APIContext): void;
|
|
21
22
|
declare function updateSession(context: APIContext, updates: Partial<Session>): void;
|
|
22
23
|
|
|
23
|
-
export { clearSession, getSession, hasAllPermissions, hasAnyPermission, hasPermission, hasRole, isAuthenticated, requireSession, setSession, updateSession };
|
|
24
|
+
export { clearSession, getSession, hasAllPermissions, hasAnyPermission, hasPermission, hasRole, hasRolePermission, isAuthenticated, requireSession, setSession, updateSession };
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,OAAO,CAAC;AActC,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAG3C;AAcD,wBAAgB,cAAc,IAAI,OAAO,CAQxC;AAKD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAKD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS7C;AAKD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAKzD;AAKD,wBAAgB,iBAAiB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAMnE;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAMlE;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,OAAO,CAAC;AActC,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAG3C;AAcD,wBAAgB,cAAc,IAAI,OAAO,CAQxC;AAKD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAKD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS7C;AAKD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAKzD;AAKD,wBAAgB,iBAAiB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAMnE;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAMlE;AAsBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE3E;AAqCD,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAUtE;AAyBD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAEtD;AA6BD,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAkBlF"}
|
package/dist/server.js
CHANGED
|
@@ -43,6 +43,9 @@ function hasAnyPermission(...permissions) {
|
|
|
43
43
|
const userPermissions = session.permissions ?? [];
|
|
44
44
|
return permissions.some((p) => userPermissions.includes(p));
|
|
45
45
|
}
|
|
46
|
+
function hasRolePermission(role, permission) {
|
|
47
|
+
return hasRole(role) && hasPermission(permission);
|
|
48
|
+
}
|
|
46
49
|
function setSession(context, session) {
|
|
47
50
|
if (!isValidSessionStructure(session)) {
|
|
48
51
|
throw new Error('[SessionKit] Invalid session structure. Session must have a valid userId and follow the Session interface.');
|
|
@@ -64,5 +67,5 @@ function updateSession(context, updates) {
|
|
|
64
67
|
context.session?.set('__session__', updatedSession);
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
export { clearSession, getSession, hasAllPermissions, hasAnyPermission, hasPermission, hasRole, isAuthenticated, requireSession, setSession, updateSession };
|
|
70
|
+
export { clearSession, getSession, hasAllPermissions, hasAnyPermission, hasPermission, hasRole, hasRolePermission, isAuthenticated, requireSession, setSession, updateSession };
|
|
68
71
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../src/server.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAqBgB,UAAU,GAAA;AACtB,IAAA,MAAM,OAAO,GAAG,eAAe,EAAE;AACjC,IAAA,OAAO,OAAO,EAAE,OAAO,IAAI,IAAI;AACnC;SAcgB,cAAc,GAAA;AAC1B,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;IAE5B,IAAI,CAAC,OAAO,EAAE;QACV,MAAM,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAC,MAAM,EAAE,GAAG,EAAC,CAAC;IACrD;AAEA,IAAA,OAAO,OAAO;AAClB;SAKgB,eAAe,GAAA;AAC3B,IAAA,OAAO,UAAU,EAAE,KAAK,IAAI;AAChC;AAKM,SAAU,OAAO,CAAC,IAAY,EAAA;AAChC,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAG1B,IAAA,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;AAAE,QAAA,OAAO,IAAI;IAGtC,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK;AACjD;AAKM,SAAU,aAAa,CAAC,UAAkB,EAAA;AAC5C,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;IAE1B,OAAO,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK;AAC7D;AAKM,SAAU,iBAAiB,CAAC,GAAG,WAAqB,EAAA;AACtD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAE1B,IAAA,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE;AACjD,IAAA,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChE;AAKM,SAAU,gBAAgB,CAAC,GAAG,WAAqB,EAAA;AACrD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAE1B,IAAA,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE;AACjD,IAAA,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/D;
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../src/server.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAqBgB,UAAU,GAAA;AACtB,IAAA,MAAM,OAAO,GAAG,eAAe,EAAE;AACjC,IAAA,OAAO,OAAO,EAAE,OAAO,IAAI,IAAI;AACnC;SAcgB,cAAc,GAAA;AAC1B,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;IAE5B,IAAI,CAAC,OAAO,EAAE;QACV,MAAM,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAC,MAAM,EAAE,GAAG,EAAC,CAAC;IACrD;AAEA,IAAA,OAAO,OAAO;AAClB;SAKgB,eAAe,GAAA;AAC3B,IAAA,OAAO,UAAU,EAAE,KAAK,IAAI;AAChC;AAKM,SAAU,OAAO,CAAC,IAAY,EAAA;AAChC,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAG1B,IAAA,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;AAAE,QAAA,OAAO,IAAI;IAGtC,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK;AACjD;AAKM,SAAU,aAAa,CAAC,UAAkB,EAAA;AAC5C,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;IAE1B,OAAO,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK;AAC7D;AAKM,SAAU,iBAAiB,CAAC,GAAG,WAAqB,EAAA;AACtD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAE1B,IAAA,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE;AACjD,IAAA,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChE;AAKM,SAAU,gBAAgB,CAAC,GAAG,WAAqB,EAAA;AACrD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE;AAC5B,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,KAAK;AAE1B,IAAA,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE;AACjD,IAAA,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/D;AAsBM,SAAU,iBAAiB,CAAC,IAAY,EAAE,UAAkB,EAAA;IAC9D,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC;AACrD;AAqCM,SAAU,UAAU,CAAC,OAAmB,EAAE,OAAgB,EAAA;AAE5D,IAAA,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE;AACnC,QAAA,MAAM,IAAI,KAAK,CACX,4GAA4G,CAC/G;IACL;IAGA,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC;AAChD;AAyBM,SAAU,YAAY,CAAC,OAAmB,EAAA;AAC5C,IAAA,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,aAAa,CAAC;AAC1C;AA6BM,SAAU,aAAa,CAAC,OAAmB,EAAE,OAAyB,EAAA;IACxE,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,CAAU,aAAa,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE;AACjB,QAAA,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC;IAC5E;IAGA,MAAM,cAAc,GAAG,EAAC,GAAG,cAAc,EAAE,GAAG,OAAO,EAAC;AAGtD,IAAA,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,EAAE;AAC1C,QAAA,MAAM,IAAI,KAAK,CACX,mFAAmF,CACtF;IACL;IAEA,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,EAAE,cAAc,CAAC;AACvD;;;;"}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -301,6 +301,18 @@ if (hasAnyPermission('posts:delete', 'admin:panel')) {
|
|
|
301
301
|
}
|
|
302
302
|
```
|
|
303
303
|
|
|
304
|
+
#### `hasRolePermission(role: string, permission: string)`
|
|
305
|
+
|
|
306
|
+
Check if user has a specific role AND a specific permission.
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
import { hasRolePermission } from 'astro-sessionkit/server';
|
|
310
|
+
|
|
311
|
+
if (hasRolePermission('admin', 'delete users')) {
|
|
312
|
+
// User is admin AND has 'delete users' permission
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
304
316
|
## Route Protection
|
|
305
317
|
|
|
306
318
|
### Protection Rules
|
|
@@ -310,7 +322,7 @@ if (hasAnyPermission('posts:delete', 'admin:panel')) {
|
|
|
310
322
|
Require a specific role:
|
|
311
323
|
|
|
312
324
|
```ts
|
|
313
|
-
{ pattern: '/admin/**', role: 'admin' }
|
|
325
|
+
const rule = { pattern: '/admin/**', role: 'admin' };
|
|
314
326
|
```
|
|
315
327
|
|
|
316
328
|
#### By Multiple Roles
|
|
@@ -318,7 +330,7 @@ Require a specific role:
|
|
|
318
330
|
User must have ONE of these roles:
|
|
319
331
|
|
|
320
332
|
```ts
|
|
321
|
-
{ pattern: '/dashboard', roles: ['user', 'admin', 'moderator'] }
|
|
333
|
+
const rule = { pattern: '/dashboard', roles: ['user', 'admin', 'moderator'] };
|
|
322
334
|
```
|
|
323
335
|
|
|
324
336
|
#### By Permission
|
|
@@ -326,7 +338,7 @@ User must have ONE of these roles:
|
|
|
326
338
|
Require a specific permission:
|
|
327
339
|
|
|
328
340
|
```ts
|
|
329
|
-
{ pattern: '/settings', permission: 'settings:write' }
|
|
341
|
+
const rule = { pattern: '/settings', permission: 'settings:write' };
|
|
330
342
|
```
|
|
331
343
|
|
|
332
344
|
#### By Multiple Permissions
|
|
@@ -413,6 +425,25 @@ sessionkit({
|
|
|
413
425
|
})
|
|
414
426
|
```
|
|
415
427
|
|
|
428
|
+
### Custom Context Store
|
|
429
|
+
|
|
430
|
+
By default, SessionKit uses Node's `AsyncLocalStorage` to manage the session context. In some environments (like certain edge runtimes), you might need to provide your own context management.
|
|
431
|
+
|
|
432
|
+
```ts
|
|
433
|
+
sessionkit({
|
|
434
|
+
// Provide a custom way to run code within a context
|
|
435
|
+
runWithContext: (context, fn) => {
|
|
436
|
+
// Your custom context implementation
|
|
437
|
+
return myCustomStorage.run(context, fn);
|
|
438
|
+
},
|
|
439
|
+
|
|
440
|
+
// Provide a custom way to retrieve the current context
|
|
441
|
+
getContextStore: () => {
|
|
442
|
+
return myCustomStorage.getStore();
|
|
443
|
+
}
|
|
444
|
+
})
|
|
445
|
+
```
|
|
446
|
+
|
|
416
447
|
### Logout Flow
|
|
417
448
|
|
|
418
449
|
```ts
|
|
@@ -585,7 +616,7 @@ export const GET: APIRoute = async () => {
|
|
|
585
616
|
- Session expiration
|
|
586
617
|
- CSRF protection
|
|
587
618
|
|
|
588
|
-
These are your responsibility. See [SECURITY.md](./
|
|
619
|
+
These are your responsibility. See [SECURITY.md](./security.md) for a complete security guide.
|
|
589
620
|
|
|
590
621
|
### Quick Security Checklist
|
|
591
622
|
|
package/security.md
CHANGED
|
@@ -273,6 +273,24 @@ const session = getSession();
|
|
|
273
273
|
<div set:html={sanitizeHtml(session?.bio)}></div> <!-- ✅ Safe -->
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
+
### 7. 🛡️ User Role Validation
|
|
277
|
+
|
|
278
|
+
Always use the server-side helpers to validate user roles and permissions. Do not rely on client-side state or hidden inputs.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
import { hasRole, hasPermission, hasRolePermission } from 'astro-sessionkit/server';
|
|
282
|
+
|
|
283
|
+
// ✅ SAFE: Validation happens on the server using the trusted session
|
|
284
|
+
if (hasRole('admin')) {
|
|
285
|
+
// Perform admin action
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ✅ SAFE: Complex permission checks
|
|
289
|
+
if (hasRolePermission('editor', 'publish:posts')) {
|
|
290
|
+
// Perform action
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
276
294
|
---
|
|
277
295
|
|
|
278
296
|
## Security Checklist
|