@thecodeorigin/auth 0.0.1
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 +84 -0
- package/dist/contract/index.d.mts +117 -0
- package/dist/contract/index.d.ts +117 -0
- package/dist/contract/index.mjs +52 -0
- package/dist/module.d.mts +23 -0
- package/dist/module.d.ts +23 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +51 -0
- package/dist/runtime/app/composables/useAuth.d.ts +106 -0
- package/dist/runtime/app/composables/useAuth.js +60 -0
- package/dist/runtime/app/composables/useCasl.d.ts +8 -0
- package/dist/runtime/app/composables/useCasl.js +9 -0
- package/dist/runtime/app/middleware/auth.global.d.ts +2 -0
- package/dist/runtime/app/middleware/auth.global.js +11 -0
- package/dist/runtime/app/middleware/casl.global.d.ts +2 -0
- package/dist/runtime/app/middleware/casl.global.js +17 -0
- package/dist/runtime/app/plugins/0.session.d.ts +2 -0
- package/dist/runtime/app/plugins/0.session.js +11 -0
- package/dist/runtime/app/plugins/ability.d.ts +7 -0
- package/dist/runtime/app/plugins/ability.js +23 -0
- package/dist/runtime/server/api/_auth/impersonatable-users.get.d.ts +2 -0
- package/dist/runtime/server/api/_auth/impersonatable-users.get.js +9 -0
- package/dist/runtime/server/api/_auth/impersonate.post.d.ts +36 -0
- package/dist/runtime/server/api/_auth/impersonate.post.js +36 -0
- package/dist/runtime/server/api/_auth/organizations/switch.post.d.ts +36 -0
- package/dist/runtime/server/api/_auth/organizations/switch.post.js +16 -0
- package/dist/runtime/server/api/_auth/organizations.get.d.ts +8 -0
- package/dist/runtime/server/api/_auth/organizations.get.js +8 -0
- package/dist/runtime/server/api/_auth/session.get.d.ts +36 -0
- package/dist/runtime/server/api/_auth/session.get.js +6 -0
- package/dist/runtime/server/api/_auth/stop-impersonating.post.d.ts +36 -0
- package/dist/runtime/server/api/_auth/stop-impersonating.post.js +21 -0
- package/dist/runtime/server/index.d.ts +2 -0
- package/dist/runtime/server/index.js +1 -0
- package/dist/runtime/server/routes/callback.get.d.ts +2 -0
- package/dist/runtime/server/routes/callback.get.js +61 -0
- package/dist/runtime/server/routes/sign-in.get.d.ts +2 -0
- package/dist/runtime/server/routes/sign-in.get.js +24 -0
- package/dist/runtime/server/routes/sign-out.get.d.ts +2 -0
- package/dist/runtime/server/routes/sign-out.get.js +19 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/server/utils/idp.d.ts +11 -0
- package/dist/runtime/server/utils/idp.js +58 -0
- package/dist/runtime/server/utils/oidc.d.ts +29 -0
- package/dist/runtime/server/utils/oidc.js +62 -0
- package/dist/runtime/server/utils/session.d.ts +74 -0
- package/dist/runtime/server/utils/session.js +79 -0
- package/dist/runtime/types.d.ts +17 -0
- package/dist/types.d.mts +3 -0
- package/package.json +77 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Get your module up and running quickly.
|
|
3
|
+
|
|
4
|
+
Find and replace all on all files (CMD+SHIFT+F):
|
|
5
|
+
- Name: My Module
|
|
6
|
+
- Package name: my-module
|
|
7
|
+
- Description: My new Nuxt module
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# My Module
|
|
11
|
+
|
|
12
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
13
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
14
|
+
[![License][license-src]][license-href]
|
|
15
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
16
|
+
|
|
17
|
+
My new Nuxt module for doing amazing things.
|
|
18
|
+
|
|
19
|
+
- [✨ Release Notes](/CHANGELOG.md)
|
|
20
|
+
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/my-module?file=playground%2Fapp.vue) -->
|
|
21
|
+
<!-- - [📖 Documentation](https://example.com) -->
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
<!-- Highlight some of the features your module provide here -->
|
|
26
|
+
- ⛰ Foo
|
|
27
|
+
- 🚠 Bar
|
|
28
|
+
- 🌲 Baz
|
|
29
|
+
|
|
30
|
+
## Quick Setup
|
|
31
|
+
|
|
32
|
+
Install the module to your Nuxt application with one command:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx nuxt module add my-module
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
That's it! You can now use My Module in your Nuxt app ✨
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Contribution
|
|
42
|
+
|
|
43
|
+
<details>
|
|
44
|
+
<summary>Local development</summary>
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Install dependencies
|
|
48
|
+
npm install
|
|
49
|
+
|
|
50
|
+
# Generate type stubs
|
|
51
|
+
npm run dev:prepare
|
|
52
|
+
|
|
53
|
+
# Develop with the playground
|
|
54
|
+
npm run dev
|
|
55
|
+
|
|
56
|
+
# Build the playground
|
|
57
|
+
npm run dev:build
|
|
58
|
+
|
|
59
|
+
# Run ESLint
|
|
60
|
+
npm run lint
|
|
61
|
+
|
|
62
|
+
# Run Vitest
|
|
63
|
+
npm run test
|
|
64
|
+
npm run test:watch
|
|
65
|
+
|
|
66
|
+
# Release new version
|
|
67
|
+
npm run release
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
</details>
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
<!-- Badges -->
|
|
74
|
+
[npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=020420&colorB=00DC82
|
|
75
|
+
[npm-version-href]: https://npmjs.com/package/my-module
|
|
76
|
+
|
|
77
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/my-module.svg?style=flat&colorA=020420&colorB=00DC82
|
|
78
|
+
[npm-downloads-href]: https://npm.chart.dev/my-module
|
|
79
|
+
|
|
80
|
+
[license-src]: https://img.shields.io/npm/l/my-module.svg?style=flat&colorA=020420&colorB=00DC82
|
|
81
|
+
[license-href]: https://npmjs.com/package/my-module
|
|
82
|
+
|
|
83
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt
|
|
84
|
+
[nuxt-href]: https://nuxt.com
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const RpOrganizationSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
slug: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
role: z.ZodString;
|
|
8
|
+
personal: z.ZodBoolean;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type RpOrganization = z.infer<typeof RpOrganizationSchema>;
|
|
11
|
+
/** CASL ability rule emitted into /oauth2/userinfo by the IdP. */
|
|
12
|
+
declare const AbilityRuleSchema: z.ZodObject<{
|
|
13
|
+
action: z.ZodString;
|
|
14
|
+
subject: z.ZodString;
|
|
15
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
type AbilityRule = z.infer<typeof AbilityRuleSchema>;
|
|
18
|
+
declare const UserinfoClaimsSchema: z.ZodObject<{
|
|
19
|
+
org: z.ZodNullable<z.ZodString>;
|
|
20
|
+
roles: z.ZodNullable<z.ZodString>;
|
|
21
|
+
personal: z.ZodBoolean;
|
|
22
|
+
entitlement: z.ZodNullable<z.ZodObject<{
|
|
23
|
+
product: z.ZodString;
|
|
24
|
+
plan: z.ZodString;
|
|
25
|
+
status: z.ZodString;
|
|
26
|
+
active: z.ZodBoolean;
|
|
27
|
+
currentPeriodEnd: z.ZodNullable<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
organizations: z.ZodArray<z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
slug: z.ZodString;
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
role: z.ZodString;
|
|
34
|
+
personal: z.ZodBoolean;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
abilities: z.ZodArray<z.ZodObject<{
|
|
37
|
+
action: z.ZodString;
|
|
38
|
+
subject: z.ZodString;
|
|
39
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
role: z.ZodNullable<z.ZodString>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
type UserinfoClaims = z.infer<typeof UserinfoClaimsSchema>;
|
|
44
|
+
declare const PublicUserSchema: z.ZodObject<{
|
|
45
|
+
sub: z.ZodString;
|
|
46
|
+
email: z.ZodString;
|
|
47
|
+
name: z.ZodNullable<z.ZodString>;
|
|
48
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
type PublicUser = z.infer<typeof PublicUserSchema>;
|
|
51
|
+
declare const ImpersonationCandidateSchema: z.ZodObject<{
|
|
52
|
+
id: z.ZodString;
|
|
53
|
+
email: z.ZodString;
|
|
54
|
+
name: z.ZodNullable<z.ZodString>;
|
|
55
|
+
image: z.ZodNullable<z.ZodString>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
type ImpersonationCandidate = z.infer<typeof ImpersonationCandidateSchema>;
|
|
58
|
+
/** Server-safe session projection — no tokens, no KV internals. */
|
|
59
|
+
interface ServerAuthSession {
|
|
60
|
+
sub: string;
|
|
61
|
+
email: string;
|
|
62
|
+
name: string | null;
|
|
63
|
+
picture: string | null;
|
|
64
|
+
systemRole: string | null;
|
|
65
|
+
abilities: AbilityRule[];
|
|
66
|
+
organizations: RpOrganization[];
|
|
67
|
+
activeOrg: string | null;
|
|
68
|
+
entitlement: {
|
|
69
|
+
product: string;
|
|
70
|
+
plan: string;
|
|
71
|
+
status: string;
|
|
72
|
+
active: boolean;
|
|
73
|
+
currentPeriodEnd: number | null;
|
|
74
|
+
} | null;
|
|
75
|
+
isImpersonation: boolean;
|
|
76
|
+
impersonator: PublicUser | null;
|
|
77
|
+
}
|
|
78
|
+
/** Browser-visible session — NO tokens. */
|
|
79
|
+
declare const PublicSessionSchema: z.ZodObject<{
|
|
80
|
+
user: z.ZodObject<{
|
|
81
|
+
sub: z.ZodString;
|
|
82
|
+
email: z.ZodString;
|
|
83
|
+
name: z.ZodNullable<z.ZodString>;
|
|
84
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
abilities: z.ZodArray<z.ZodObject<{
|
|
87
|
+
action: z.ZodString;
|
|
88
|
+
subject: z.ZodString;
|
|
89
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
90
|
+
}, z.core.$strip>>;
|
|
91
|
+
systemRole: z.ZodNullable<z.ZodString>;
|
|
92
|
+
organizations: z.ZodArray<z.ZodObject<{
|
|
93
|
+
id: z.ZodString;
|
|
94
|
+
slug: z.ZodString;
|
|
95
|
+
name: z.ZodString;
|
|
96
|
+
role: z.ZodString;
|
|
97
|
+
personal: z.ZodBoolean;
|
|
98
|
+
}, z.core.$strip>>;
|
|
99
|
+
activeOrg: z.ZodNullable<z.ZodString>;
|
|
100
|
+
entitlement: z.ZodNullable<z.ZodObject<{
|
|
101
|
+
product: z.ZodString;
|
|
102
|
+
plan: z.ZodString;
|
|
103
|
+
status: z.ZodString;
|
|
104
|
+
active: z.ZodBoolean;
|
|
105
|
+
currentPeriodEnd: z.ZodNullable<z.ZodNumber>;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
impersonator: z.ZodNullable<z.ZodObject<{
|
|
108
|
+
sub: z.ZodString;
|
|
109
|
+
email: z.ZodString;
|
|
110
|
+
name: z.ZodNullable<z.ZodString>;
|
|
111
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
112
|
+
}, z.core.$strip>>;
|
|
113
|
+
}, z.core.$strip>;
|
|
114
|
+
type PublicSession = z.infer<typeof PublicSessionSchema>;
|
|
115
|
+
|
|
116
|
+
export { AbilityRuleSchema, ImpersonationCandidateSchema, PublicSessionSchema, PublicUserSchema, RpOrganizationSchema, UserinfoClaimsSchema };
|
|
117
|
+
export type { AbilityRule, ImpersonationCandidate, PublicSession, PublicUser, RpOrganization, ServerAuthSession, UserinfoClaims };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const RpOrganizationSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
slug: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
role: z.ZodString;
|
|
8
|
+
personal: z.ZodBoolean;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type RpOrganization = z.infer<typeof RpOrganizationSchema>;
|
|
11
|
+
/** CASL ability rule emitted into /oauth2/userinfo by the IdP. */
|
|
12
|
+
declare const AbilityRuleSchema: z.ZodObject<{
|
|
13
|
+
action: z.ZodString;
|
|
14
|
+
subject: z.ZodString;
|
|
15
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
type AbilityRule = z.infer<typeof AbilityRuleSchema>;
|
|
18
|
+
declare const UserinfoClaimsSchema: z.ZodObject<{
|
|
19
|
+
org: z.ZodNullable<z.ZodString>;
|
|
20
|
+
roles: z.ZodNullable<z.ZodString>;
|
|
21
|
+
personal: z.ZodBoolean;
|
|
22
|
+
entitlement: z.ZodNullable<z.ZodObject<{
|
|
23
|
+
product: z.ZodString;
|
|
24
|
+
plan: z.ZodString;
|
|
25
|
+
status: z.ZodString;
|
|
26
|
+
active: z.ZodBoolean;
|
|
27
|
+
currentPeriodEnd: z.ZodNullable<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
organizations: z.ZodArray<z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
slug: z.ZodString;
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
role: z.ZodString;
|
|
34
|
+
personal: z.ZodBoolean;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
abilities: z.ZodArray<z.ZodObject<{
|
|
37
|
+
action: z.ZodString;
|
|
38
|
+
subject: z.ZodString;
|
|
39
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
role: z.ZodNullable<z.ZodString>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
type UserinfoClaims = z.infer<typeof UserinfoClaimsSchema>;
|
|
44
|
+
declare const PublicUserSchema: z.ZodObject<{
|
|
45
|
+
sub: z.ZodString;
|
|
46
|
+
email: z.ZodString;
|
|
47
|
+
name: z.ZodNullable<z.ZodString>;
|
|
48
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
type PublicUser = z.infer<typeof PublicUserSchema>;
|
|
51
|
+
declare const ImpersonationCandidateSchema: z.ZodObject<{
|
|
52
|
+
id: z.ZodString;
|
|
53
|
+
email: z.ZodString;
|
|
54
|
+
name: z.ZodNullable<z.ZodString>;
|
|
55
|
+
image: z.ZodNullable<z.ZodString>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
type ImpersonationCandidate = z.infer<typeof ImpersonationCandidateSchema>;
|
|
58
|
+
/** Server-safe session projection — no tokens, no KV internals. */
|
|
59
|
+
interface ServerAuthSession {
|
|
60
|
+
sub: string;
|
|
61
|
+
email: string;
|
|
62
|
+
name: string | null;
|
|
63
|
+
picture: string | null;
|
|
64
|
+
systemRole: string | null;
|
|
65
|
+
abilities: AbilityRule[];
|
|
66
|
+
organizations: RpOrganization[];
|
|
67
|
+
activeOrg: string | null;
|
|
68
|
+
entitlement: {
|
|
69
|
+
product: string;
|
|
70
|
+
plan: string;
|
|
71
|
+
status: string;
|
|
72
|
+
active: boolean;
|
|
73
|
+
currentPeriodEnd: number | null;
|
|
74
|
+
} | null;
|
|
75
|
+
isImpersonation: boolean;
|
|
76
|
+
impersonator: PublicUser | null;
|
|
77
|
+
}
|
|
78
|
+
/** Browser-visible session — NO tokens. */
|
|
79
|
+
declare const PublicSessionSchema: z.ZodObject<{
|
|
80
|
+
user: z.ZodObject<{
|
|
81
|
+
sub: z.ZodString;
|
|
82
|
+
email: z.ZodString;
|
|
83
|
+
name: z.ZodNullable<z.ZodString>;
|
|
84
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
abilities: z.ZodArray<z.ZodObject<{
|
|
87
|
+
action: z.ZodString;
|
|
88
|
+
subject: z.ZodString;
|
|
89
|
+
conditions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
90
|
+
}, z.core.$strip>>;
|
|
91
|
+
systemRole: z.ZodNullable<z.ZodString>;
|
|
92
|
+
organizations: z.ZodArray<z.ZodObject<{
|
|
93
|
+
id: z.ZodString;
|
|
94
|
+
slug: z.ZodString;
|
|
95
|
+
name: z.ZodString;
|
|
96
|
+
role: z.ZodString;
|
|
97
|
+
personal: z.ZodBoolean;
|
|
98
|
+
}, z.core.$strip>>;
|
|
99
|
+
activeOrg: z.ZodNullable<z.ZodString>;
|
|
100
|
+
entitlement: z.ZodNullable<z.ZodObject<{
|
|
101
|
+
product: z.ZodString;
|
|
102
|
+
plan: z.ZodString;
|
|
103
|
+
status: z.ZodString;
|
|
104
|
+
active: z.ZodBoolean;
|
|
105
|
+
currentPeriodEnd: z.ZodNullable<z.ZodNumber>;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
impersonator: z.ZodNullable<z.ZodObject<{
|
|
108
|
+
sub: z.ZodString;
|
|
109
|
+
email: z.ZodString;
|
|
110
|
+
name: z.ZodNullable<z.ZodString>;
|
|
111
|
+
picture: z.ZodNullable<z.ZodString>;
|
|
112
|
+
}, z.core.$strip>>;
|
|
113
|
+
}, z.core.$strip>;
|
|
114
|
+
type PublicSession = z.infer<typeof PublicSessionSchema>;
|
|
115
|
+
|
|
116
|
+
export { AbilityRuleSchema, ImpersonationCandidateSchema, PublicSessionSchema, PublicUserSchema, RpOrganizationSchema, UserinfoClaimsSchema };
|
|
117
|
+
export type { AbilityRule, ImpersonationCandidate, PublicSession, PublicUser, RpOrganization, ServerAuthSession, UserinfoClaims };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
const RpOrganizationSchema = z.object({
|
|
4
|
+
id: z.string(),
|
|
5
|
+
slug: z.string(),
|
|
6
|
+
name: z.string(),
|
|
7
|
+
role: z.string(),
|
|
8
|
+
personal: z.boolean()
|
|
9
|
+
});
|
|
10
|
+
const AbilityRuleSchema = z.object({
|
|
11
|
+
action: z.string(),
|
|
12
|
+
subject: z.string(),
|
|
13
|
+
conditions: z.record(z.string(), z.string()).optional()
|
|
14
|
+
});
|
|
15
|
+
const UserinfoClaimsSchema = z.object({
|
|
16
|
+
org: z.string().nullable(),
|
|
17
|
+
roles: z.string().nullable(),
|
|
18
|
+
personal: z.boolean(),
|
|
19
|
+
entitlement: z.object({
|
|
20
|
+
product: z.string(),
|
|
21
|
+
plan: z.string(),
|
|
22
|
+
status: z.string(),
|
|
23
|
+
active: z.boolean(),
|
|
24
|
+
currentPeriodEnd: z.number().nullable()
|
|
25
|
+
}).nullable(),
|
|
26
|
+
organizations: z.array(RpOrganizationSchema),
|
|
27
|
+
abilities: z.array(AbilityRuleSchema),
|
|
28
|
+
role: z.string().nullable()
|
|
29
|
+
});
|
|
30
|
+
const PublicUserSchema = z.object({
|
|
31
|
+
sub: z.string(),
|
|
32
|
+
email: z.string(),
|
|
33
|
+
name: z.string().nullable(),
|
|
34
|
+
picture: z.string().nullable()
|
|
35
|
+
});
|
|
36
|
+
const ImpersonationCandidateSchema = z.object({
|
|
37
|
+
id: z.string(),
|
|
38
|
+
email: z.string(),
|
|
39
|
+
name: z.string().nullable(),
|
|
40
|
+
image: z.string().nullable()
|
|
41
|
+
});
|
|
42
|
+
const PublicSessionSchema = z.object({
|
|
43
|
+
user: PublicUserSchema,
|
|
44
|
+
abilities: z.array(AbilityRuleSchema),
|
|
45
|
+
systemRole: z.string().nullable(),
|
|
46
|
+
organizations: z.array(RpOrganizationSchema),
|
|
47
|
+
activeOrg: z.string().nullable(),
|
|
48
|
+
entitlement: UserinfoClaimsSchema.shape.entitlement,
|
|
49
|
+
impersonator: PublicUserSchema.nullable()
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export { AbilityRuleSchema, ImpersonationCandidateSchema, PublicSessionSchema, PublicUserSchema, RpOrganizationSchema, UserinfoClaimsSchema };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface AuthRoutes {
|
|
4
|
+
signIn: string;
|
|
5
|
+
callback: string;
|
|
6
|
+
signOut: string;
|
|
7
|
+
home: string;
|
|
8
|
+
error: string;
|
|
9
|
+
}
|
|
10
|
+
interface ModuleOptions {
|
|
11
|
+
domain: string;
|
|
12
|
+
clientId: string;
|
|
13
|
+
clientSecret: string;
|
|
14
|
+
issuer?: string;
|
|
15
|
+
scopes?: string[];
|
|
16
|
+
sessionStorageBase?: string;
|
|
17
|
+
sessionCookieName?: string;
|
|
18
|
+
routes?: Partial<AuthRoutes>;
|
|
19
|
+
}
|
|
20
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
21
|
+
|
|
22
|
+
export { _default as default };
|
|
23
|
+
export type { AuthRoutes, ModuleOptions };
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface AuthRoutes {
|
|
4
|
+
signIn: string;
|
|
5
|
+
callback: string;
|
|
6
|
+
signOut: string;
|
|
7
|
+
home: string;
|
|
8
|
+
error: string;
|
|
9
|
+
}
|
|
10
|
+
interface ModuleOptions {
|
|
11
|
+
domain: string;
|
|
12
|
+
clientId: string;
|
|
13
|
+
clientSecret: string;
|
|
14
|
+
issuer?: string;
|
|
15
|
+
scopes?: string[];
|
|
16
|
+
sessionStorageBase?: string;
|
|
17
|
+
sessionCookieName?: string;
|
|
18
|
+
routes?: Partial<AuthRoutes>;
|
|
19
|
+
}
|
|
20
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
21
|
+
|
|
22
|
+
export { _default as default };
|
|
23
|
+
export type { AuthRoutes, ModuleOptions };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addServerHandler, addServerImportsDir, addImportsDir, addRouteMiddleware, addPlugin } from '@nuxt/kit';
|
|
2
|
+
import { defu } from 'defu';
|
|
3
|
+
|
|
4
|
+
const module$1 = defineNuxtModule({
|
|
5
|
+
meta: { name: "@thecodeorigin/auth", configKey: "auth" },
|
|
6
|
+
defaults: {
|
|
7
|
+
domain: "",
|
|
8
|
+
clientId: "",
|
|
9
|
+
clientSecret: "",
|
|
10
|
+
scopes: ["openid", "profile", "email"],
|
|
11
|
+
sessionStorageBase: "auth",
|
|
12
|
+
sessionCookieName: "tco_auth",
|
|
13
|
+
routes: { signIn: "/auth/sign-in", callback: "/auth/callback", signOut: "/auth/sign-out", home: "/", error: "/auth/sign-in" }
|
|
14
|
+
},
|
|
15
|
+
setup(options, nuxt) {
|
|
16
|
+
const resolver = createResolver(import.meta.url);
|
|
17
|
+
const routes = options.routes;
|
|
18
|
+
const issuer = options.issuer || (options.domain ? `https://${options.domain}/api/auth` : "");
|
|
19
|
+
nuxt.options.runtimeConfig.auth = defu(
|
|
20
|
+
nuxt.options.runtimeConfig.auth,
|
|
21
|
+
{ clientSecret: options.clientSecret, sessionStorageBase: options.sessionStorageBase, sessionCookieName: options.sessionCookieName }
|
|
22
|
+
);
|
|
23
|
+
nuxt.options.runtimeConfig.public.auth = defu(
|
|
24
|
+
nuxt.options.runtimeConfig.public.auth,
|
|
25
|
+
{ domain: options.domain, clientId: options.clientId, issuer, scopes: options.scopes, routes }
|
|
26
|
+
);
|
|
27
|
+
addServerHandler({ route: routes.signIn, handler: resolver.resolve("./runtime/server/routes/sign-in.get") });
|
|
28
|
+
addServerHandler({ route: routes.callback, handler: resolver.resolve("./runtime/server/routes/callback.get") });
|
|
29
|
+
addServerHandler({ route: routes.signOut, handler: resolver.resolve("./runtime/server/routes/sign-out.get") });
|
|
30
|
+
for (const [route, file] of [
|
|
31
|
+
["/api/_auth/session", "session.get"],
|
|
32
|
+
["/api/_auth/organizations", "organizations.get"],
|
|
33
|
+
["/api/_auth/organizations/switch", "organizations/switch.post"],
|
|
34
|
+
["/api/_auth/impersonatable-users", "impersonatable-users.get"],
|
|
35
|
+
["/api/_auth/impersonate", "impersonate.post"],
|
|
36
|
+
["/api/_auth/stop-impersonating", "stop-impersonating.post"]
|
|
37
|
+
])
|
|
38
|
+
addServerHandler({ route, handler: resolver.resolve(`./runtime/server/api/_auth/${file}`) });
|
|
39
|
+
addServerImportsDir(resolver.resolve("./runtime/server/utils"));
|
|
40
|
+
addImportsDir(resolver.resolve("./runtime/app/composables"));
|
|
41
|
+
addRouteMiddleware({ name: "auth", path: resolver.resolve("./runtime/app/middleware/auth.global"), global: true });
|
|
42
|
+
addRouteMiddleware({ name: "casl", path: resolver.resolve("./runtime/app/middleware/casl.global"), global: true });
|
|
43
|
+
addPlugin(resolver.resolve("./runtime/app/plugins/0.session"));
|
|
44
|
+
addPlugin(resolver.resolve("./runtime/app/plugins/ability"));
|
|
45
|
+
nuxt.hook("prepare:types", ({ references }) => {
|
|
46
|
+
references.push({ path: resolver.resolve("./runtime/types.d.ts") });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export { module$1 as default };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { ImpersonationCandidate, RpOrganization } from '../../../contract/index.js';
|
|
2
|
+
export declare function useAuth(): {
|
|
3
|
+
session: import("vue").Ref<{
|
|
4
|
+
user: {
|
|
5
|
+
sub: string;
|
|
6
|
+
email: string;
|
|
7
|
+
name: string | null;
|
|
8
|
+
picture: string | null;
|
|
9
|
+
};
|
|
10
|
+
abilities: {
|
|
11
|
+
action: string;
|
|
12
|
+
subject: string;
|
|
13
|
+
conditions?: Record<string, string> | undefined;
|
|
14
|
+
}[];
|
|
15
|
+
systemRole: string | null;
|
|
16
|
+
organizations: {
|
|
17
|
+
id: string;
|
|
18
|
+
slug: string;
|
|
19
|
+
name: string;
|
|
20
|
+
role: string;
|
|
21
|
+
personal: boolean;
|
|
22
|
+
}[];
|
|
23
|
+
activeOrg: string | null;
|
|
24
|
+
entitlement: {
|
|
25
|
+
product: string;
|
|
26
|
+
plan: string;
|
|
27
|
+
status: string;
|
|
28
|
+
active: boolean;
|
|
29
|
+
currentPeriodEnd: number | null;
|
|
30
|
+
} | null;
|
|
31
|
+
impersonator: {
|
|
32
|
+
sub: string;
|
|
33
|
+
email: string;
|
|
34
|
+
name: string | null;
|
|
35
|
+
picture: string | null;
|
|
36
|
+
} | null;
|
|
37
|
+
} | null, {
|
|
38
|
+
user: {
|
|
39
|
+
sub: string;
|
|
40
|
+
email: string;
|
|
41
|
+
name: string | null;
|
|
42
|
+
picture: string | null;
|
|
43
|
+
};
|
|
44
|
+
abilities: {
|
|
45
|
+
action: string;
|
|
46
|
+
subject: string;
|
|
47
|
+
conditions?: Record<string, string> | undefined;
|
|
48
|
+
}[];
|
|
49
|
+
systemRole: string | null;
|
|
50
|
+
organizations: {
|
|
51
|
+
id: string;
|
|
52
|
+
slug: string;
|
|
53
|
+
name: string;
|
|
54
|
+
role: string;
|
|
55
|
+
personal: boolean;
|
|
56
|
+
}[];
|
|
57
|
+
activeOrg: string | null;
|
|
58
|
+
entitlement: {
|
|
59
|
+
product: string;
|
|
60
|
+
plan: string;
|
|
61
|
+
status: string;
|
|
62
|
+
active: boolean;
|
|
63
|
+
currentPeriodEnd: number | null;
|
|
64
|
+
} | null;
|
|
65
|
+
impersonator: {
|
|
66
|
+
sub: string;
|
|
67
|
+
email: string;
|
|
68
|
+
name: string | null;
|
|
69
|
+
picture: string | null;
|
|
70
|
+
} | null;
|
|
71
|
+
} | null>;
|
|
72
|
+
user: import("vue").ComputedRef<{
|
|
73
|
+
sub: string;
|
|
74
|
+
email: string;
|
|
75
|
+
name: string | null;
|
|
76
|
+
picture: string | null;
|
|
77
|
+
} | null>;
|
|
78
|
+
loggedIn: import("vue").ComputedRef<boolean>;
|
|
79
|
+
abilities: import("vue").ComputedRef<{
|
|
80
|
+
action: string;
|
|
81
|
+
subject: string;
|
|
82
|
+
conditions?: Record<string, string> | undefined;
|
|
83
|
+
}[]>;
|
|
84
|
+
impersonator: import("vue").ComputedRef<{
|
|
85
|
+
sub: string;
|
|
86
|
+
email: string;
|
|
87
|
+
name: string | null;
|
|
88
|
+
picture: string | null;
|
|
89
|
+
} | null>;
|
|
90
|
+
isImpersonating: import("vue").ComputedRef<boolean>;
|
|
91
|
+
getOrganizations: () => RpOrganization[];
|
|
92
|
+
switchOrganization: (orgId: string) => Promise<void>;
|
|
93
|
+
getImpersonatableUsers: (query?: {
|
|
94
|
+
q?: string;
|
|
95
|
+
limit?: number;
|
|
96
|
+
offset?: number;
|
|
97
|
+
}) => Promise<{
|
|
98
|
+
items: ImpersonationCandidate[];
|
|
99
|
+
hasMore: boolean;
|
|
100
|
+
}>;
|
|
101
|
+
impersonate: (userId: string) => Promise<void>;
|
|
102
|
+
stopImpersonating: () => Promise<void>;
|
|
103
|
+
signIn: (redirect?: string) => string | false | void | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric | Promise<false | void | import("vue-router").NavigationFailure>;
|
|
104
|
+
signOut: () => string | false | void | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric | Promise<false | void | import("vue-router").NavigationFailure>;
|
|
105
|
+
refresh: () => Promise<void>;
|
|
106
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { computed } from "vue";
|
|
2
|
+
import { navigateTo, useRuntimeConfig, useState } from "#app";
|
|
3
|
+
export function useAuth() {
|
|
4
|
+
const session = useState("tco-auth-session", () => null);
|
|
5
|
+
const routes = useRuntimeConfig().public.auth?.routes ?? {};
|
|
6
|
+
const user = computed(() => session.value?.user ?? null);
|
|
7
|
+
const loggedIn = computed(() => !!session.value);
|
|
8
|
+
const abilities = computed(() => session.value?.abilities ?? []);
|
|
9
|
+
const impersonator = computed(() => session.value?.impersonator ?? null);
|
|
10
|
+
const isImpersonating = computed(() => !!session.value?.impersonator);
|
|
11
|
+
async function refresh() {
|
|
12
|
+
session.value = await $fetch("/api/_auth/session");
|
|
13
|
+
}
|
|
14
|
+
function getOrganizations() {
|
|
15
|
+
return session.value?.organizations ?? [];
|
|
16
|
+
}
|
|
17
|
+
async function switchOrganization(orgId) {
|
|
18
|
+
session.value = await $fetch("/api/_auth/organizations/switch", {
|
|
19
|
+
method: "POST",
|
|
20
|
+
body: { organizationId: orgId }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function getImpersonatableUsers(query) {
|
|
24
|
+
return $fetch("/api/_auth/impersonatable-users", { query });
|
|
25
|
+
}
|
|
26
|
+
async function impersonate(userId) {
|
|
27
|
+
session.value = await $fetch("/api/_auth/impersonate", {
|
|
28
|
+
method: "POST",
|
|
29
|
+
body: { userId }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function stopImpersonating() {
|
|
33
|
+
session.value = await $fetch("/api/_auth/stop-impersonating", { method: "POST" });
|
|
34
|
+
}
|
|
35
|
+
function signIn(redirect) {
|
|
36
|
+
return navigateTo(
|
|
37
|
+
redirect ? `${routes.signIn}?redirect=${encodeURIComponent(redirect)}` : routes.signIn,
|
|
38
|
+
{ external: true }
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function signOut() {
|
|
42
|
+
return navigateTo(routes.signOut, { external: true });
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
session,
|
|
46
|
+
user,
|
|
47
|
+
loggedIn,
|
|
48
|
+
abilities,
|
|
49
|
+
impersonator,
|
|
50
|
+
isImpersonating,
|
|
51
|
+
getOrganizations,
|
|
52
|
+
switchOrganization,
|
|
53
|
+
getImpersonatableUsers,
|
|
54
|
+
impersonate,
|
|
55
|
+
stopImpersonating,
|
|
56
|
+
signIn,
|
|
57
|
+
signOut,
|
|
58
|
+
refresh
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function useCasl(): {
|
|
2
|
+
ability: {
|
|
3
|
+
can: (action: string, subject: string, field?: string) => boolean;
|
|
4
|
+
cannot: (action: string, subject: string, field?: string) => boolean;
|
|
5
|
+
};
|
|
6
|
+
can: (action: string, subject: string, field?: string) => boolean;
|
|
7
|
+
cannot: (action: string, subject: string, field?: string) => boolean;
|
|
8
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
2
|
+
export function useCasl() {
|
|
3
|
+
const { $ability } = useNuxtApp();
|
|
4
|
+
return {
|
|
5
|
+
ability: $ability,
|
|
6
|
+
can: (action, subject, field) => $ability.can(action, subject, field),
|
|
7
|
+
cannot: (action, subject, field) => $ability.cannot(action, subject, field)
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineNuxtRouteMiddleware, navigateTo, useRuntimeConfig, useState } from "#app";
|
|
2
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
3
|
+
const session = useState("tco-auth-session", () => null);
|
|
4
|
+
const routes = useRuntimeConfig().public.auth?.routes ?? {};
|
|
5
|
+
const authed = !!session.value;
|
|
6
|
+
const isPublic = to.meta.public === true || to.meta.unauthenticatedOnly === true;
|
|
7
|
+
if (authed && to.meta.unauthenticatedOnly)
|
|
8
|
+
return navigateTo(routes.home);
|
|
9
|
+
if (!authed && !isPublic)
|
|
10
|
+
return navigateTo(`${routes.signIn}?redirect=${encodeURIComponent(to.fullPath)}`, { external: true });
|
|
11
|
+
});
|