una-nuxt-module 3.0.36 → 3.0.38
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/module.json +1 -1
- package/dist/module.mjs +179 -9
- package/dist/runtime/auth/middleware/authentication.d.ts +3 -3
- package/dist/runtime/auth/middleware/authentication.js +22 -27
- package/dist/runtime/auth/middleware/authorization.js +7 -1
- package/dist/runtime/auth/pages/login.d.vue.ts +1 -11
- package/dist/runtime/auth/pages/login.vue +2 -10
- package/dist/runtime/auth/pages/login.vue.d.ts +1 -11
- package/dist/runtime/auth/pages/logout.d.vue.ts +1 -11
- package/dist/runtime/auth/pages/logout.vue +4 -6
- package/dist/runtime/auth/pages/logout.vue.d.ts +1 -11
- package/dist/runtime/auth/plugins/auth.js +43 -26
- package/dist/runtime/auth/stores/auth.d.ts +38 -29
- package/dist/runtime/auth/stores/auth.js +20 -3
- package/dist/runtime/auth/utils/isAuthCallback.d.ts +3 -0
- package/dist/runtime/auth/utils/isAuthCallback.js +9 -0
- package/dist/runtime/auth/utils/parseCedulaFromSub.d.ts +1 -0
- package/dist/runtime/auth/utils/parseCedulaFromSub.js +4 -0
- package/dist/runtime/auth/utils/parseUserInfo.d.ts +6 -0
- package/dist/runtime/auth/utils/parseUserInfo.js +55 -0
- package/dist/runtime/auth/utils/postLoginRedirect.d.ts +3 -0
- package/dist/runtime/auth/utils/postLoginRedirect.js +36 -0
- package/dist/runtime/composables/useFonts.d.ts +3 -0
- package/dist/runtime/composables/useFonts.js +10 -0
- package/dist/runtime/repository-pattern/plugins/api-fetch.d.ts +2 -0
- package/dist/runtime/repository-pattern/plugins/api-fetch.js +5 -1
- package/dist/runtime/types/index.d.ts +9 -8
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -167,12 +167,165 @@ function addTemplates() {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
const name = "una-nuxt-module";
|
|
170
|
-
const version = "3.0.
|
|
170
|
+
const version = "3.0.38";
|
|
171
|
+
const description = "Módulo Nuxt para desarrollo CGI";
|
|
172
|
+
const repository = {
|
|
173
|
+
type: "git",
|
|
174
|
+
url: ""
|
|
175
|
+
};
|
|
176
|
+
const license = "MIT";
|
|
177
|
+
const type = "module";
|
|
178
|
+
const exports$1 = {
|
|
179
|
+
".": {
|
|
180
|
+
types: "./dist/types.d.mts",
|
|
181
|
+
style: "./dist/runtime/styles/main.css",
|
|
182
|
+
"import": "./dist/module.mjs",
|
|
183
|
+
require: "./dist/module.mjs"
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const main = "./dist/module.mjs";
|
|
187
|
+
const typesVersions = {
|
|
188
|
+
"*": {
|
|
189
|
+
".": [
|
|
190
|
+
"./dist/types.d.mts"
|
|
191
|
+
],
|
|
192
|
+
"runtime/*": [
|
|
193
|
+
"./dist/runtime/*"
|
|
194
|
+
],
|
|
195
|
+
"components/*": [
|
|
196
|
+
"./dist/runtime/components/*"
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const imports = {
|
|
201
|
+
"#build/templates/*": "./.nuxt/templates/*.ts",
|
|
202
|
+
"#build/templates.css": "./.nuxt/templates.css"
|
|
203
|
+
};
|
|
204
|
+
const style = "./dist/runtime/styles/main.css";
|
|
205
|
+
const files = [
|
|
206
|
+
"README.md",
|
|
207
|
+
"LICENSE",
|
|
208
|
+
".nuxt/templates",
|
|
209
|
+
".nuxt/templates.css",
|
|
210
|
+
"dist"
|
|
211
|
+
];
|
|
212
|
+
const scripts = {
|
|
213
|
+
prepack: "nuxt-module-build build",
|
|
214
|
+
dev: "pnpm run dev:prepare && nuxi dev playground",
|
|
215
|
+
"dev:https": "pnpm run dev:prepare && cd playground && pnpm run dev:https",
|
|
216
|
+
"dev:build": "nuxi build playground",
|
|
217
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
218
|
+
"release:prepare:major": "pnpm run test && pnpm run prepack && changelogen --release --major",
|
|
219
|
+
"release:prepare:minor": "pnpm run test && pnpm run prepack && changelogen --release --minor",
|
|
220
|
+
"release:prepare:patch": "pnpm run test && pnpm run prepack && changelogen --release --patch",
|
|
221
|
+
release: "pnpm publish && git push --follow-tags",
|
|
222
|
+
prepare: "husky",
|
|
223
|
+
format: "prettier --write .",
|
|
224
|
+
lint: "eslint .",
|
|
225
|
+
"lint:fix": "eslint . --fix",
|
|
226
|
+
test: "vitest run",
|
|
227
|
+
"test:watch": "vitest watch",
|
|
228
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
229
|
+
};
|
|
230
|
+
const dependencies = {
|
|
231
|
+
"@asgardeo/auth-spa": "3.5.2",
|
|
232
|
+
"@nuxt/a11y": "1.0.0-alpha.1",
|
|
233
|
+
"@nuxt/fonts": "0.14.0",
|
|
234
|
+
"@nuxt/hints": "1.1.2",
|
|
235
|
+
"@nuxt/icon": "2.2.3",
|
|
236
|
+
"@nuxt/image": "2.0.0",
|
|
237
|
+
"@nuxt/kit": "4.4.7",
|
|
238
|
+
"@nuxtjs/i18n": "10.4.0",
|
|
239
|
+
"@pinia/nuxt": "0.5.5",
|
|
240
|
+
"@tailwindcss/vite": "4.3.0",
|
|
241
|
+
"@tanstack/vue-table": "8.21.3",
|
|
242
|
+
"@unovis/ts": "1.6.5",
|
|
243
|
+
"@unovis/vue": "1.6.5",
|
|
244
|
+
"@vee-validate/zod": "4.15.1",
|
|
245
|
+
"@vueuse/core": "14.3.0",
|
|
246
|
+
"class-variance-authority": "0.7.1",
|
|
247
|
+
clsx: "2.1.1",
|
|
248
|
+
colorette: "2.0.20",
|
|
249
|
+
defu: "6.1.7",
|
|
250
|
+
"embla-carousel-vue": "8.6.0",
|
|
251
|
+
"lucide-vue-next": "1.0.0",
|
|
252
|
+
"nuxt-security": "2.6.0",
|
|
253
|
+
pinia: "2.2.8",
|
|
254
|
+
"reka-ui": "2.9.9",
|
|
255
|
+
scule: "1.3.0",
|
|
256
|
+
"tailwind-merge": "3.6.0",
|
|
257
|
+
tailwindcss: "4.3.0",
|
|
258
|
+
"tw-animate-css": "1.4.0",
|
|
259
|
+
"vaul-vue": "0.4.1",
|
|
260
|
+
"vee-validate": "4.15.1",
|
|
261
|
+
"vue-input-otp": "0.3.2",
|
|
262
|
+
"vue-sonner": "2.0.9",
|
|
263
|
+
zod: "3.25.76"
|
|
264
|
+
};
|
|
265
|
+
const devDependencies = {
|
|
266
|
+
"@nuxt/devtools": "3.2.4",
|
|
267
|
+
"@nuxt/eslint-config": "1.15.2",
|
|
268
|
+
"@nuxt/module-builder": "1.0.2",
|
|
269
|
+
"@nuxt/schema": "4.4.7",
|
|
270
|
+
"@nuxt/test-utils": "4.0.3",
|
|
271
|
+
"@nuxtjs/color-mode": "4.0.0",
|
|
272
|
+
"@types/node": "24.3.1",
|
|
273
|
+
"@typescript-eslint/parser": "8.60.1",
|
|
274
|
+
changelogen: "0.6.2",
|
|
275
|
+
eslint: "9.39.1",
|
|
276
|
+
"eslint-plugin-security": "3.0.1",
|
|
277
|
+
husky: "9.1.7",
|
|
278
|
+
"lint-staged": "17.0.7",
|
|
279
|
+
nuxt: "4.4.7",
|
|
280
|
+
prettier: "3.8.3",
|
|
281
|
+
"prettier-plugin-tailwindcss": "0.8.0",
|
|
282
|
+
"shadcn-nuxt": "2.7.4",
|
|
283
|
+
typescript: "~5.9.2",
|
|
284
|
+
"unaxt-eslint-config": "0.0.3",
|
|
285
|
+
vitest: "4.1.8",
|
|
286
|
+
"vue-eslint-parser": "10.4.1",
|
|
287
|
+
"vue-tsc": "3.3.3"
|
|
288
|
+
};
|
|
289
|
+
const directories = {
|
|
290
|
+
test: "test"
|
|
291
|
+
};
|
|
292
|
+
const author = "Universidad Nacional - Centro de Gestion Informatica";
|
|
293
|
+
const bugs = {
|
|
294
|
+
url: "https://github.com/una-cgi/una-nuxt-module/issues"
|
|
295
|
+
};
|
|
296
|
+
const homepage = "https://github.com/una-cgi/una-nuxt-module#readme";
|
|
297
|
+
const pkg = {
|
|
298
|
+
name: name,
|
|
299
|
+
version: version,
|
|
300
|
+
description: description,
|
|
301
|
+
repository: repository,
|
|
302
|
+
license: license,
|
|
303
|
+
type: type,
|
|
304
|
+
exports: exports$1,
|
|
305
|
+
main: main,
|
|
306
|
+
typesVersions: typesVersions,
|
|
307
|
+
imports: imports,
|
|
308
|
+
style: style,
|
|
309
|
+
files: files,
|
|
310
|
+
scripts: scripts,
|
|
311
|
+
dependencies: dependencies,
|
|
312
|
+
devDependencies: devDependencies,
|
|
313
|
+
"lint-staged": {
|
|
314
|
+
"*.{js,ts,json,vue}": [
|
|
315
|
+
"prettier --write",
|
|
316
|
+
"eslint --fix"
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
directories: directories,
|
|
320
|
+
author: author,
|
|
321
|
+
bugs: bugs,
|
|
322
|
+
homepage: homepage
|
|
323
|
+
};
|
|
171
324
|
|
|
172
325
|
const module$1 = defineNuxtModule({
|
|
173
326
|
meta: {
|
|
174
|
-
name,
|
|
175
|
-
version,
|
|
327
|
+
name: pkg.name,
|
|
328
|
+
version: pkg.version,
|
|
176
329
|
configKey: "unaxt",
|
|
177
330
|
compatibility: {
|
|
178
331
|
nuxt: ">=4.0.0"
|
|
@@ -185,9 +338,9 @@ const module$1 = defineNuxtModule({
|
|
|
185
338
|
enabled: true,
|
|
186
339
|
sso: {
|
|
187
340
|
automaticSignIn: true,
|
|
188
|
-
postLoginRedirectUrl: "/",
|
|
189
341
|
signInRedirectUrl: "/auth/sso/login",
|
|
190
|
-
signOutRedirectUrl: "/auth/sso/logout"
|
|
342
|
+
signOutRedirectUrl: "/auth/sso/logout",
|
|
343
|
+
postLoginRedirect: "/"
|
|
191
344
|
},
|
|
192
345
|
middleware: {
|
|
193
346
|
authentication: {
|
|
@@ -207,7 +360,7 @@ const module$1 = defineNuxtModule({
|
|
|
207
360
|
},
|
|
208
361
|
moduleDependencies: {
|
|
209
362
|
"nuxt-security": {
|
|
210
|
-
version:
|
|
363
|
+
version: `>=${pkg.dependencies["nuxt-security"]}`,
|
|
211
364
|
optional: true,
|
|
212
365
|
defaults: {
|
|
213
366
|
removeLoggers: true
|
|
@@ -231,11 +384,26 @@ const module$1 = defineNuxtModule({
|
|
|
231
384
|
}
|
|
232
385
|
},
|
|
233
386
|
async setup(options, nuxt) {
|
|
234
|
-
const logger = useLogger(name);
|
|
387
|
+
const logger = useLogger(pkg.name);
|
|
235
388
|
const { resolve } = createResolver(import.meta.url);
|
|
236
389
|
options = defu(nuxt.options.runtimeConfig.public.unaxt, options);
|
|
237
390
|
nuxt.options.runtimeConfig.public.unaxt = options;
|
|
238
391
|
nuxt.options.alias["#unaxt"] = resolve("./runtime");
|
|
392
|
+
function injectComponentsConfig() {
|
|
393
|
+
if (nuxt.options.components === false) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
nuxt.options.components = {
|
|
397
|
+
dirs: [
|
|
398
|
+
{ path: "~/components/global", global: true },
|
|
399
|
+
{
|
|
400
|
+
path: "~/components",
|
|
401
|
+
pattern: ["*/**", "**"],
|
|
402
|
+
pathPrefix: false
|
|
403
|
+
}
|
|
404
|
+
]
|
|
405
|
+
};
|
|
406
|
+
}
|
|
239
407
|
function setupAutoImports() {
|
|
240
408
|
addImportsDir(
|
|
241
409
|
["composables", "constants", "enums", "types", "utils"].map(
|
|
@@ -303,12 +471,13 @@ const module$1 = defineNuxtModule({
|
|
|
303
471
|
if (options.auth?.enabled) {
|
|
304
472
|
logger.ready(green("Iniciando m\xF3dulo de autenticaci\xF3n"));
|
|
305
473
|
addImportsDir(
|
|
306
|
-
["auth/stores", "auth/composables"].map(
|
|
474
|
+
["auth/stores", "auth/composables", "auth/utils"].map(
|
|
307
475
|
(dir) => resolve(`./runtime/${dir}`)
|
|
308
476
|
)
|
|
309
477
|
);
|
|
310
478
|
logger.ready("\u251C\u2500\u2500 " + gray("Stores"));
|
|
311
479
|
logger.ready("\u251C\u2500\u2500 " + gray("Composables"));
|
|
480
|
+
logger.ready("\u251C\u2500\u2500 " + gray("Utils"));
|
|
312
481
|
addPlugin({
|
|
313
482
|
name: "auth",
|
|
314
483
|
src: resolve("./runtime/auth/plugins/auth"),
|
|
@@ -386,10 +555,11 @@ const module$1 = defineNuxtModule({
|
|
|
386
555
|
}
|
|
387
556
|
try {
|
|
388
557
|
console.log(banner);
|
|
389
|
-
console.log(yellow(bold(`\u279C v${version}
|
|
558
|
+
console.log(yellow(bold(`\u279C v${pkg.version}
|
|
390
559
|
`)));
|
|
391
560
|
logger.start(cyan(bold("Registro del m\xF3dulo iniciado...")));
|
|
392
561
|
const startTime = Date.now();
|
|
562
|
+
injectComponentsConfig();
|
|
393
563
|
setupAutoImports();
|
|
394
564
|
setupAuth();
|
|
395
565
|
setupComponents();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Middleware encargado de sincronizar los datos de la
|
|
2
|
+
* Middleware encargado de sincronizar los datos de la sesion del usuario.
|
|
3
3
|
*
|
|
4
|
-
* En el flujo de inicio de
|
|
4
|
+
* En el flujo de inicio de sesion mediante SSO, en el cual el usuario ingresa y hay una sesion activa en las cookies,
|
|
5
5
|
* este middleware sincroniza esos datos en el store de pinia.
|
|
6
6
|
*
|
|
7
|
-
* Nota: solo se ejecuta una vez, debido a que posteriormente los datos de la
|
|
7
|
+
* Nota: solo se ejecuta una vez, debido a que posteriormente los datos de la sesion estaran sincronizados en Pinia.
|
|
8
8
|
*/
|
|
9
9
|
declare const _default: import("#app").RouteMiddleware;
|
|
10
10
|
export default _default;
|
|
@@ -1,48 +1,43 @@
|
|
|
1
|
-
import { defineNuxtRouteMiddleware, useNuxtApp
|
|
1
|
+
import { defineNuxtRouteMiddleware, useNuxtApp } from "#app";
|
|
2
2
|
import { useAuthStore } from "../stores/auth.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { savePostLoginRedirect } from "../utils/postLoginRedirect.js";
|
|
4
|
+
import { parseUserInfo } from "../utils/parseUserInfo.js";
|
|
5
|
+
import { parseCedulaFromSub } from "../utils/parseCedulaFromSub.js";
|
|
6
|
+
import { isAuthCallback } from "../utils/isAuthCallback.js";
|
|
7
|
+
export default defineNuxtRouteMiddleware(async (to) => {
|
|
5
8
|
if (!import.meta.client) {
|
|
6
9
|
return;
|
|
7
10
|
}
|
|
11
|
+
if (isAuthCallback(to.path)) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
8
14
|
const { $pinia, $signIn, $authData, $isAuthenticated, $accessToken } = useNuxtApp();
|
|
9
|
-
const authorization = useAuthorization();
|
|
10
15
|
const authStore = useAuthStore($pinia);
|
|
11
16
|
const isAuthenticated = await $isAuthenticated();
|
|
12
17
|
if (!isAuthenticated) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!authConfig.sso?.automaticSignIn) {
|
|
16
|
-
await $signIn();
|
|
17
|
-
}
|
|
18
|
+
savePostLoginRedirect(to.fullPath);
|
|
19
|
+
await $signIn();
|
|
18
20
|
return;
|
|
19
21
|
}
|
|
20
22
|
if (!authStore.isAuthenticated) {
|
|
21
23
|
const authResponse = await $authData();
|
|
22
24
|
const token = await $accessToken();
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
email = rawEmail?.trim();
|
|
29
|
-
const [name, lastName] = email.toUpperCase().split(".");
|
|
30
|
-
return {
|
|
31
|
-
name,
|
|
32
|
-
lastName,
|
|
33
|
-
fullName: name + " " + lastName
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
};
|
|
25
|
+
const { email, name, lastName1, lastName2, fullName } = parseUserInfo({
|
|
26
|
+
email: authResponse?.email,
|
|
27
|
+
givenName: authResponse?.givenName,
|
|
28
|
+
familyName: authResponse?.familyName
|
|
29
|
+
});
|
|
37
30
|
const userInfo = {
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
name,
|
|
32
|
+
lastName1,
|
|
33
|
+
lastName2,
|
|
34
|
+
fullName,
|
|
35
|
+
cedula: parseCedulaFromSub(authResponse?.sub),
|
|
40
36
|
email
|
|
41
37
|
};
|
|
42
38
|
const authData = {
|
|
43
39
|
isAuthenticated,
|
|
44
|
-
accessToken: token
|
|
45
|
-
resources
|
|
40
|
+
accessToken: token
|
|
46
41
|
};
|
|
47
42
|
authStore.update(userInfo, authData);
|
|
48
43
|
}
|
|
@@ -11,7 +11,7 @@ const getPathWhitoutFormPart = (path) => {
|
|
|
11
11
|
parts.pop();
|
|
12
12
|
return parts?.join("/");
|
|
13
13
|
};
|
|
14
|
-
export default defineNuxtRouteMiddleware((to) => {
|
|
14
|
+
export default defineNuxtRouteMiddleware(async (to) => {
|
|
15
15
|
if (!import.meta.client) {
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
@@ -25,6 +25,12 @@ export default defineNuxtRouteMiddleware((to) => {
|
|
|
25
25
|
if (!authStore.isAuthenticated) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
+
if (!authStore.authData?.resources) {
|
|
29
|
+
const resources = await authorization.getResources(
|
|
30
|
+
authStore.token
|
|
31
|
+
);
|
|
32
|
+
authStore.setResources(resources);
|
|
33
|
+
}
|
|
28
34
|
if (isUserGoingToForm(resource)) {
|
|
29
35
|
const formModeTrackerStore = useFormModeTrackerStore($pinia);
|
|
30
36
|
const params = {
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
declare
|
|
2
|
-
type __VLS_Slots = {} & {
|
|
3
|
-
default?: (props: typeof __VLS_1) => any;
|
|
4
|
-
};
|
|
5
|
-
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
-
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
7
2
|
declare const _default: typeof __VLS_export;
|
|
8
3
|
export default _default;
|
|
9
|
-
type __VLS_WithSlots<T, S> = T & {
|
|
10
|
-
new (): {
|
|
11
|
-
$slots: S;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<LoadingSessionScreen />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import
|
|
7
|
-
import { navigateTo } from "#imports";
|
|
8
|
-
import { onMounted } from "vue";
|
|
9
|
-
onMounted(async () => {
|
|
10
|
-
const runtimeConfig = useRuntimeConfig();
|
|
11
|
-
await navigateTo(
|
|
12
|
-
runtimeConfig.public.unaxt.auth.sso?.postLoginRedirectUrl ?? "/"
|
|
13
|
-
);
|
|
14
|
-
});
|
|
6
|
+
import LoadingSessionScreen from "../../components/shared/LoadingSessionScreen.vue";
|
|
15
7
|
</script>
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
declare
|
|
2
|
-
type __VLS_Slots = {} & {
|
|
3
|
-
default?: (props: typeof __VLS_1) => any;
|
|
4
|
-
};
|
|
5
|
-
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
-
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
7
2
|
declare const _default: typeof __VLS_export;
|
|
8
3
|
export default _default;
|
|
9
|
-
type __VLS_WithSlots<T, S> = T & {
|
|
10
|
-
new (): {
|
|
11
|
-
$slots: S;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
declare
|
|
2
|
-
type __VLS_Slots = {} & {
|
|
3
|
-
default?: (props: typeof __VLS_1) => any;
|
|
4
|
-
};
|
|
5
|
-
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
-
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
7
2
|
declare const _default: typeof __VLS_export;
|
|
8
3
|
export default _default;
|
|
9
|
-
type __VLS_WithSlots<T, S> = T & {
|
|
10
|
-
new (): {
|
|
11
|
-
$slots: S;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<LoadingScreen />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import { useRuntimeConfig } from "#app";
|
|
7
6
|
import { navigateTo } from "#imports";
|
|
8
7
|
import { onMounted } from "vue";
|
|
8
|
+
import LoadingScreen from "../../components/shared/LoadingScreen.vue";
|
|
9
|
+
import { getPostLoginRedirect } from "../utils/postLoginRedirect";
|
|
9
10
|
onMounted(async () => {
|
|
10
|
-
|
|
11
|
-
await navigateTo(
|
|
12
|
-
runtimeConfig.public.unaxt.auth.sso?.signInRedirectUrl ?? "/"
|
|
13
|
-
);
|
|
11
|
+
await navigateTo(getPostLoginRedirect());
|
|
14
12
|
});
|
|
15
13
|
</script>
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
declare
|
|
2
|
-
type __VLS_Slots = {} & {
|
|
3
|
-
default?: (props: typeof __VLS_1) => any;
|
|
4
|
-
};
|
|
5
|
-
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
-
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
7
2
|
declare const _default: typeof __VLS_export;
|
|
8
3
|
export default _default;
|
|
9
|
-
type __VLS_WithSlots<T, S> = T & {
|
|
10
|
-
new (): {
|
|
11
|
-
$slots: S;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
defineNuxtPlugin,
|
|
3
|
+
navigateTo,
|
|
4
|
+
useRuntimeConfig,
|
|
5
|
+
useNuxtApp
|
|
6
|
+
} from "#app";
|
|
2
7
|
import {
|
|
3
8
|
AsgardeoSPAClient,
|
|
4
9
|
Hooks
|
|
5
10
|
} from "@asgardeo/auth-spa";
|
|
6
11
|
import { useAuthStore } from "../stores/auth.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
12
|
+
import {
|
|
13
|
+
getPostLoginRedirect,
|
|
14
|
+
savePostLoginRedirect
|
|
15
|
+
} from "../utils/postLoginRedirect.js";
|
|
16
|
+
import { isSignOutCallback } from "../utils/isAuthCallback.js";
|
|
17
|
+
import { parseUserInfo } from "../utils/parseUserInfo.js";
|
|
18
|
+
import { parseCedulaFromSub } from "../utils/parseCedulaFromSub.js";
|
|
19
|
+
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
9
20
|
const auth = AsgardeoSPAClient.getInstance();
|
|
10
21
|
const runtimeConfig = useRuntimeConfig();
|
|
11
22
|
const authConfig = runtimeConfig.public.unaxt.auth;
|
|
@@ -21,41 +32,47 @@ export default defineNuxtPlugin(() => {
|
|
|
21
32
|
signOutRedirectURL: origin + (authConfig.sso?.signOutRedirectUrl ?? "/"),
|
|
22
33
|
scope: authConfig.sso?.scopes !== void 0 ? authConfig.sso?.scopes?.split("|") : FALLBACK_SCOPES
|
|
23
34
|
};
|
|
24
|
-
auth?.initialize(config);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
await auth?.initialize(config);
|
|
36
|
+
const signInRedirectUrl = authConfig.sso?.signInRedirectUrl;
|
|
37
|
+
const isSignInCallbackPath = window.location.pathname === signInRedirectUrl;
|
|
38
|
+
const isSignOutCallbackPath = isSignOutCallback(window.location.pathname);
|
|
28
39
|
auth?.on(Hooks.SignIn, async (response) => {
|
|
29
40
|
const { $pinia } = useNuxtApp();
|
|
30
41
|
const authStore = useAuthStore($pinia);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
email = rawEmail?.trim();
|
|
37
|
-
const [name, lastName] = email.toUpperCase().split(".");
|
|
38
|
-
return {
|
|
39
|
-
name,
|
|
40
|
-
lastName,
|
|
41
|
-
fullName: name + " " + lastName
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
};
|
|
42
|
+
const { email, name, lastName1, lastName2, fullName } = parseUserInfo({
|
|
43
|
+
email: response?.email,
|
|
44
|
+
givenName: response?.givenName,
|
|
45
|
+
familyName: response?.familyName
|
|
46
|
+
});
|
|
45
47
|
const userInfo = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
name,
|
|
49
|
+
lastName1,
|
|
50
|
+
lastName2,
|
|
51
|
+
fullName,
|
|
52
|
+
cedula: parseCedulaFromSub(response.sub),
|
|
48
53
|
email
|
|
49
54
|
};
|
|
50
55
|
const token = await auth?.getAccessToken();
|
|
51
|
-
const resources = await authorization.getResources(token);
|
|
52
56
|
const authData = {
|
|
53
57
|
isAuthenticated: true,
|
|
54
|
-
accessToken: token
|
|
55
|
-
resources
|
|
58
|
+
accessToken: token
|
|
56
59
|
};
|
|
57
60
|
authStore.update(userInfo, authData);
|
|
58
61
|
});
|
|
62
|
+
if (authConfig.sso?.automaticSignIn && !isSignInCallbackPath && !isSignOutCallbackPath) {
|
|
63
|
+
savePostLoginRedirect(window.location.pathname);
|
|
64
|
+
await auth?.signIn();
|
|
65
|
+
}
|
|
66
|
+
if (isSignInCallbackPath) {
|
|
67
|
+
nuxtApp.hook("app:created", async () => {
|
|
68
|
+
try {
|
|
69
|
+
await auth?.signIn();
|
|
70
|
+
await navigateTo(getPostLoginRedirect());
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error("Error procesando callback SSO:", error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
59
76
|
return {
|
|
60
77
|
provide: {
|
|
61
78
|
/**
|
|
@@ -1,128 +1,137 @@
|
|
|
1
|
-
import type { IAuthData, IAuthenticatedUser, IHasAuthorizationInResourceParams } from '../../types/index.js';
|
|
1
|
+
import type { IAuthData, IAuthenticatedUser, IHasAuthorizationInResourceParams, IResource } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Store encargado de almacenar y gestionar la autenticación y autorización del usuario.
|
|
4
4
|
*/
|
|
5
5
|
export declare const useAuthStore: import("pinia").StoreDefinition<"AuthStore", Pick<{
|
|
6
6
|
user: import("vue").Ref<{
|
|
7
|
-
cedula
|
|
7
|
+
cedula?: string | undefined;
|
|
8
8
|
email: string;
|
|
9
9
|
fullName?: string | undefined;
|
|
10
10
|
name?: string | undefined;
|
|
11
|
-
|
|
11
|
+
lastName1?: string | undefined;
|
|
12
|
+
lastName2?: string | undefined;
|
|
12
13
|
} | null, IAuthenticatedUser | {
|
|
13
|
-
cedula
|
|
14
|
+
cedula?: string | undefined;
|
|
14
15
|
email: string;
|
|
15
16
|
fullName?: string | undefined;
|
|
16
17
|
name?: string | undefined;
|
|
17
|
-
|
|
18
|
+
lastName1?: string | undefined;
|
|
19
|
+
lastName2?: string | undefined;
|
|
18
20
|
} | null>;
|
|
19
21
|
authData: import("vue").Ref<{
|
|
20
22
|
isAuthenticated: boolean;
|
|
21
23
|
accessToken: string;
|
|
22
|
-
resources
|
|
24
|
+
resources?: {
|
|
23
25
|
id: number;
|
|
24
26
|
nombre: string;
|
|
25
27
|
permisoInsertar: boolean;
|
|
26
28
|
permisoModificar: boolean;
|
|
27
29
|
permisoEliminar: boolean;
|
|
28
|
-
}[];
|
|
30
|
+
}[] | undefined;
|
|
29
31
|
} | null, IAuthData | {
|
|
30
32
|
isAuthenticated: boolean;
|
|
31
33
|
accessToken: string;
|
|
32
|
-
resources
|
|
34
|
+
resources?: {
|
|
33
35
|
id: number;
|
|
34
36
|
nombre: string;
|
|
35
37
|
permisoInsertar: boolean;
|
|
36
38
|
permisoModificar: boolean;
|
|
37
39
|
permisoEliminar: boolean;
|
|
38
|
-
}[];
|
|
40
|
+
}[] | undefined;
|
|
39
41
|
} | null>;
|
|
40
42
|
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
41
43
|
token: import("vue").ComputedRef<string | null>;
|
|
42
44
|
logout: () => Promise<void>;
|
|
43
|
-
update: (userInfo: IAuthenticatedUser, data: IAuthData) => void;
|
|
45
|
+
update: (userInfo: IAuthenticatedUser, data: Pick<IAuthData, "isAuthenticated" | "accessToken">) => void;
|
|
46
|
+
setResources: (resources: IResource[]) => void;
|
|
44
47
|
hasResource: (resource: string) => boolean;
|
|
45
48
|
hasAuthorizationInResource: ({ resource, authorization }: IHasAuthorizationInResourceParams) => boolean;
|
|
46
49
|
}, "user" | "authData">, Pick<{
|
|
47
50
|
user: import("vue").Ref<{
|
|
48
|
-
cedula
|
|
51
|
+
cedula?: string | undefined;
|
|
49
52
|
email: string;
|
|
50
53
|
fullName?: string | undefined;
|
|
51
54
|
name?: string | undefined;
|
|
52
|
-
|
|
55
|
+
lastName1?: string | undefined;
|
|
56
|
+
lastName2?: string | undefined;
|
|
53
57
|
} | null, IAuthenticatedUser | {
|
|
54
|
-
cedula
|
|
58
|
+
cedula?: string | undefined;
|
|
55
59
|
email: string;
|
|
56
60
|
fullName?: string | undefined;
|
|
57
61
|
name?: string | undefined;
|
|
58
|
-
|
|
62
|
+
lastName1?: string | undefined;
|
|
63
|
+
lastName2?: string | undefined;
|
|
59
64
|
} | null>;
|
|
60
65
|
authData: import("vue").Ref<{
|
|
61
66
|
isAuthenticated: boolean;
|
|
62
67
|
accessToken: string;
|
|
63
|
-
resources
|
|
68
|
+
resources?: {
|
|
64
69
|
id: number;
|
|
65
70
|
nombre: string;
|
|
66
71
|
permisoInsertar: boolean;
|
|
67
72
|
permisoModificar: boolean;
|
|
68
73
|
permisoEliminar: boolean;
|
|
69
|
-
}[];
|
|
74
|
+
}[] | undefined;
|
|
70
75
|
} | null, IAuthData | {
|
|
71
76
|
isAuthenticated: boolean;
|
|
72
77
|
accessToken: string;
|
|
73
|
-
resources
|
|
78
|
+
resources?: {
|
|
74
79
|
id: number;
|
|
75
80
|
nombre: string;
|
|
76
81
|
permisoInsertar: boolean;
|
|
77
82
|
permisoModificar: boolean;
|
|
78
83
|
permisoEliminar: boolean;
|
|
79
|
-
}[];
|
|
84
|
+
}[] | undefined;
|
|
80
85
|
} | null>;
|
|
81
86
|
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
82
87
|
token: import("vue").ComputedRef<string | null>;
|
|
83
88
|
logout: () => Promise<void>;
|
|
84
|
-
update: (userInfo: IAuthenticatedUser, data: IAuthData) => void;
|
|
89
|
+
update: (userInfo: IAuthenticatedUser, data: Pick<IAuthData, "isAuthenticated" | "accessToken">) => void;
|
|
90
|
+
setResources: (resources: IResource[]) => void;
|
|
85
91
|
hasResource: (resource: string) => boolean;
|
|
86
92
|
hasAuthorizationInResource: ({ resource, authorization }: IHasAuthorizationInResourceParams) => boolean;
|
|
87
93
|
}, "isAuthenticated" | "token">, Pick<{
|
|
88
94
|
user: import("vue").Ref<{
|
|
89
|
-
cedula
|
|
95
|
+
cedula?: string | undefined;
|
|
90
96
|
email: string;
|
|
91
97
|
fullName?: string | undefined;
|
|
92
98
|
name?: string | undefined;
|
|
93
|
-
|
|
99
|
+
lastName1?: string | undefined;
|
|
100
|
+
lastName2?: string | undefined;
|
|
94
101
|
} | null, IAuthenticatedUser | {
|
|
95
|
-
cedula
|
|
102
|
+
cedula?: string | undefined;
|
|
96
103
|
email: string;
|
|
97
104
|
fullName?: string | undefined;
|
|
98
105
|
name?: string | undefined;
|
|
99
|
-
|
|
106
|
+
lastName1?: string | undefined;
|
|
107
|
+
lastName2?: string | undefined;
|
|
100
108
|
} | null>;
|
|
101
109
|
authData: import("vue").Ref<{
|
|
102
110
|
isAuthenticated: boolean;
|
|
103
111
|
accessToken: string;
|
|
104
|
-
resources
|
|
112
|
+
resources?: {
|
|
105
113
|
id: number;
|
|
106
114
|
nombre: string;
|
|
107
115
|
permisoInsertar: boolean;
|
|
108
116
|
permisoModificar: boolean;
|
|
109
117
|
permisoEliminar: boolean;
|
|
110
|
-
}[];
|
|
118
|
+
}[] | undefined;
|
|
111
119
|
} | null, IAuthData | {
|
|
112
120
|
isAuthenticated: boolean;
|
|
113
121
|
accessToken: string;
|
|
114
|
-
resources
|
|
122
|
+
resources?: {
|
|
115
123
|
id: number;
|
|
116
124
|
nombre: string;
|
|
117
125
|
permisoInsertar: boolean;
|
|
118
126
|
permisoModificar: boolean;
|
|
119
127
|
permisoEliminar: boolean;
|
|
120
|
-
}[];
|
|
128
|
+
}[] | undefined;
|
|
121
129
|
} | null>;
|
|
122
130
|
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
123
131
|
token: import("vue").ComputedRef<string | null>;
|
|
124
132
|
logout: () => Promise<void>;
|
|
125
|
-
update: (userInfo: IAuthenticatedUser, data: IAuthData) => void;
|
|
133
|
+
update: (userInfo: IAuthenticatedUser, data: Pick<IAuthData, "isAuthenticated" | "accessToken">) => void;
|
|
134
|
+
setResources: (resources: IResource[]) => void;
|
|
126
135
|
hasResource: (resource: string) => boolean;
|
|
127
136
|
hasAuthorizationInResource: ({ resource, authorization }: IHasAuthorizationInResourceParams) => boolean;
|
|
128
|
-
}, "logout" | "update" | "hasResource" | "hasAuthorizationInResource">>;
|
|
137
|
+
}, "logout" | "update" | "setResources" | "hasResource" | "hasAuthorizationInResource">>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { computed, ref, useNuxtApp, useRuntimeConfig } from "#imports";
|
|
1
|
+
import { computed, ref, useNuxtApp, useRoute, useRuntimeConfig } from "#imports";
|
|
2
2
|
import { defineStore } from "pinia";
|
|
3
3
|
import { EAuthorization } from "../../enums/EAuthorization.js";
|
|
4
|
+
import { savePostLoginRedirect } from "../utils/postLoginRedirect.js";
|
|
4
5
|
const LOGOUT_ENDPOINT = "/api/usuario/logout";
|
|
5
6
|
export const useAuthStore = defineStore("AuthStore", () => {
|
|
6
7
|
const user = ref(null);
|
|
@@ -12,7 +13,9 @@ export const useAuthStore = defineStore("AuthStore", () => {
|
|
|
12
13
|
const logout = async () => {
|
|
13
14
|
const { $signOut } = useNuxtApp();
|
|
14
15
|
const runtimeConfig = useRuntimeConfig();
|
|
16
|
+
const route = useRoute();
|
|
15
17
|
const baseURL = runtimeConfig.public.apiBaseUrl;
|
|
18
|
+
savePostLoginRedirect(route.fullPath);
|
|
16
19
|
try {
|
|
17
20
|
await $fetch(LOGOUT_ENDPOINT, {
|
|
18
21
|
baseURL,
|
|
@@ -29,7 +32,20 @@ export const useAuthStore = defineStore("AuthStore", () => {
|
|
|
29
32
|
};
|
|
30
33
|
const update = (userInfo, data) => {
|
|
31
34
|
user.value = userInfo;
|
|
32
|
-
authData.value =
|
|
35
|
+
authData.value = {
|
|
36
|
+
isAuthenticated: data.isAuthenticated,
|
|
37
|
+
accessToken: data.accessToken,
|
|
38
|
+
resources: authData.value?.resources
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const setResources = (resources) => {
|
|
42
|
+
if (!authData.value) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
authData.value = {
|
|
46
|
+
...authData.value,
|
|
47
|
+
resources
|
|
48
|
+
};
|
|
33
49
|
};
|
|
34
50
|
const hasResource = (resource) => {
|
|
35
51
|
return authData.value?.resources?.some(
|
|
@@ -40,7 +56,7 @@ export const useAuthStore = defineStore("AuthStore", () => {
|
|
|
40
56
|
resource,
|
|
41
57
|
authorization
|
|
42
58
|
}) => {
|
|
43
|
-
const resourceData = authData.value?.resources
|
|
59
|
+
const resourceData = authData.value?.resources?.find(
|
|
44
60
|
(currentResource) => currentResource.nombre === resource
|
|
45
61
|
);
|
|
46
62
|
if (!resourceData) return false;
|
|
@@ -58,6 +74,7 @@ export const useAuthStore = defineStore("AuthStore", () => {
|
|
|
58
74
|
token,
|
|
59
75
|
logout,
|
|
60
76
|
update,
|
|
77
|
+
setResources,
|
|
61
78
|
hasResource,
|
|
62
79
|
hasAuthorizationInResource
|
|
63
80
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isAuthCallback(path) {
|
|
2
|
+
return Boolean(path?.startsWith("/auth/sso/"));
|
|
3
|
+
}
|
|
4
|
+
export function isSignInCallback(path) {
|
|
5
|
+
return Boolean(path?.startsWith("/auth/sso/login"));
|
|
6
|
+
}
|
|
7
|
+
export function isSignOutCallback(path) {
|
|
8
|
+
return Boolean(path?.startsWith("/auth/sso/logout"));
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseCedulaFromSub(sub: string | undefined): string | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const INSTITUTIONAL_EMAIL_DOMAINS = ["una.cr", "est.una.ac.cr"];
|
|
2
|
+
function getInstitutionalNameParts(localPart) {
|
|
3
|
+
const parts = localPart.toUpperCase().split(".").filter(Boolean);
|
|
4
|
+
return parts.length === 3 ? parts : null;
|
|
5
|
+
}
|
|
6
|
+
function isInstitutionalEmail(email) {
|
|
7
|
+
if (!email.includes("@")) {
|
|
8
|
+
return getInstitutionalNameParts(email) !== null;
|
|
9
|
+
}
|
|
10
|
+
const [localPart, domain] = email.split("@");
|
|
11
|
+
return !!domain && INSTITUTIONAL_EMAIL_DOMAINS.includes(domain.toLowerCase()) && getInstitutionalNameParts(localPart ?? "") !== null;
|
|
12
|
+
}
|
|
13
|
+
function parseNamesFromFamilyName(familyName) {
|
|
14
|
+
const family = familyName.trim().toUpperCase();
|
|
15
|
+
if (!family) return {};
|
|
16
|
+
const spaceIndex = family.indexOf(" ");
|
|
17
|
+
if (spaceIndex === -1) {
|
|
18
|
+
return { lastName1: family };
|
|
19
|
+
}
|
|
20
|
+
const lastName1 = family.slice(0, spaceIndex);
|
|
21
|
+
const lastName2 = family.slice(spaceIndex + 1).trim() || void 0;
|
|
22
|
+
return { lastName1, lastName2 };
|
|
23
|
+
}
|
|
24
|
+
function normalizeEmail(rawEmail) {
|
|
25
|
+
return (Array.isArray(rawEmail) ? rawEmail[0]?.trim() : rawEmail)?.trim() ?? "";
|
|
26
|
+
}
|
|
27
|
+
export function parseUserInfo(claims) {
|
|
28
|
+
const email = normalizeEmail(claims.email);
|
|
29
|
+
if (email && isInstitutionalEmail(email)) {
|
|
30
|
+
const localPart = email.includes("@") ? email.split("@")[0] ?? "" : email;
|
|
31
|
+
const parts = getInstitutionalNameParts(localPart);
|
|
32
|
+
if (parts) {
|
|
33
|
+
const [name2, lastName12, lastName22] = parts;
|
|
34
|
+
return {
|
|
35
|
+
email,
|
|
36
|
+
name: name2,
|
|
37
|
+
lastName1: lastName12,
|
|
38
|
+
lastName2: lastName22,
|
|
39
|
+
fullName: [name2, lastName12, lastName22].join(" ")
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const name = claims.givenName?.trim().toUpperCase() || void 0;
|
|
44
|
+
const { lastName1, lastName2 } = parseNamesFromFamilyName(
|
|
45
|
+
claims.familyName ?? ""
|
|
46
|
+
);
|
|
47
|
+
const fullName = [name, lastName1, lastName2].filter(Boolean).join(" ");
|
|
48
|
+
return {
|
|
49
|
+
email,
|
|
50
|
+
name,
|
|
51
|
+
lastName1,
|
|
52
|
+
lastName2,
|
|
53
|
+
fullName: fullName || void 0
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useRuntimeConfig } from "#app";
|
|
2
|
+
import { isAuthCallback } from "./isAuthCallback.js";
|
|
3
|
+
const STORAGE_KEY = "postLoginRedirect";
|
|
4
|
+
export function isSafePath(path) {
|
|
5
|
+
return Boolean(path?.startsWith("/") && !path.startsWith("//"));
|
|
6
|
+
}
|
|
7
|
+
export function savePostLoginRedirect(path) {
|
|
8
|
+
if (!import.meta.client) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const runtimeConfig = useRuntimeConfig();
|
|
12
|
+
const postLoginRedirect = runtimeConfig.public.unaxt.auth.sso?.postLoginRedirect;
|
|
13
|
+
if (postLoginRedirect !== true) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!isSafePath(path) || isAuthCallback(path)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
sessionStorage.setItem(STORAGE_KEY, path);
|
|
20
|
+
}
|
|
21
|
+
export function getPostLoginRedirect() {
|
|
22
|
+
if (!import.meta.client) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const runtimeConfig = useRuntimeConfig();
|
|
26
|
+
const postLoginRedirect = runtimeConfig.public.unaxt.auth.sso?.postLoginRedirect;
|
|
27
|
+
if (typeof postLoginRedirect === "string") {
|
|
28
|
+
return postLoginRedirect;
|
|
29
|
+
}
|
|
30
|
+
const stored = sessionStorage.getItem(STORAGE_KEY);
|
|
31
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
32
|
+
if (postLoginRedirect === true && stored && isSafePath(stored)) {
|
|
33
|
+
return stored;
|
|
34
|
+
}
|
|
35
|
+
return "/";
|
|
36
|
+
}
|
|
@@ -2,10 +2,12 @@ import type { ApiFetch } from '../types/index.js';
|
|
|
2
2
|
declare const _default: import("#app").Plugin<{
|
|
3
3
|
api: {
|
|
4
4
|
fetch: ApiFetch;
|
|
5
|
+
publicFetch: ApiFetch;
|
|
5
6
|
};
|
|
6
7
|
}> & import("#app").ObjectPlugin<{
|
|
7
8
|
api: {
|
|
8
9
|
fetch: ApiFetch;
|
|
10
|
+
publicFetch: ApiFetch;
|
|
9
11
|
};
|
|
10
12
|
}>;
|
|
11
13
|
export default _default;
|
|
@@ -23,10 +23,14 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
+
const publicFetch = $fetch.create({
|
|
27
|
+
baseURL: nuxtApp.$config.public.apiBaseUrl
|
|
28
|
+
});
|
|
26
29
|
return {
|
|
27
30
|
provide: {
|
|
28
31
|
api: {
|
|
29
|
-
fetch
|
|
32
|
+
fetch,
|
|
33
|
+
publicFetch
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
};
|
|
@@ -21,7 +21,7 @@ interface ISSOConfig {
|
|
|
21
21
|
/**
|
|
22
22
|
* URL de redirección final después de completar el login SSO.
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
postLoginRedirect: boolean | string;
|
|
25
25
|
/**
|
|
26
26
|
* ID del cliente para la autenticación (OAuth Client Key del Service Provider).
|
|
27
27
|
*/
|
|
@@ -221,13 +221,12 @@ export interface IBaseEntityLite extends IIdentifiedEntity, IVersionedEntity, IA
|
|
|
221
221
|
* @property {string} email - Email del usuario
|
|
222
222
|
* @property {string} fullName - Nombre completo del usuario
|
|
223
223
|
* @property {string} name - Nombre del usuario
|
|
224
|
-
* @property {string}
|
|
225
|
-
* @property {string}
|
|
226
|
-
* @property {string} mainRole - Rol del usuario
|
|
224
|
+
* @property {string} lastName1 - Primer apellido del usuario
|
|
225
|
+
* @property {string} lastName2 - Segundo apellido del usuario
|
|
227
226
|
*/
|
|
228
227
|
export interface IAuthenticatedUser {
|
|
229
228
|
/** Cédula del usuario */
|
|
230
|
-
cedula
|
|
229
|
+
cedula?: string;
|
|
231
230
|
/** Email del usuario */
|
|
232
231
|
email: string;
|
|
233
232
|
/** Nombre completo del usuario */
|
|
@@ -235,7 +234,9 @@ export interface IAuthenticatedUser {
|
|
|
235
234
|
/** Nombre del usuario */
|
|
236
235
|
name?: string;
|
|
237
236
|
/** Primer apellido del usuario */
|
|
238
|
-
|
|
237
|
+
lastName1?: string;
|
|
238
|
+
/** Segundo apellido del usuario */
|
|
239
|
+
lastName2?: string;
|
|
239
240
|
}
|
|
240
241
|
/**
|
|
241
242
|
* Interfaz para la información de los recursos del usuario autenticado.
|
|
@@ -267,7 +268,7 @@ export interface IResource {
|
|
|
267
268
|
*
|
|
268
269
|
* @property {boolean} isAuthenticated - Almacena si el usuario está autenticado
|
|
269
270
|
* @property {string} accessToken - Access Token del usuario generado al iniciar sesión en WSO2
|
|
270
|
-
* @property {IResource[]} resources - Recursos del usuario
|
|
271
|
+
* @property {IResource[]} resources - Recursos del usuario. Se cargan en el middleware de autorización.
|
|
271
272
|
*/
|
|
272
273
|
export interface IAuthData {
|
|
273
274
|
/** Almacena si el usuario esta autenticado */
|
|
@@ -275,7 +276,7 @@ export interface IAuthData {
|
|
|
275
276
|
/** Access Token del usuario generado al iniciar sesión en WSO2 */
|
|
276
277
|
accessToken: string;
|
|
277
278
|
/** Recursos del usuario */
|
|
278
|
-
resources
|
|
279
|
+
resources?: IResource[];
|
|
279
280
|
}
|
|
280
281
|
/**
|
|
281
282
|
* Interfaz para los parámetros de métodos de validación de permisos en recursos.
|