una-nuxt-module 3.0.36 → 3.0.37

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.
Files changed (28) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +19 -3
  3. package/dist/runtime/auth/middleware/authentication.d.ts +3 -3
  4. package/dist/runtime/auth/middleware/authentication.js +22 -27
  5. package/dist/runtime/auth/middleware/authorization.js +7 -1
  6. package/dist/runtime/auth/pages/login.d.vue.ts +1 -11
  7. package/dist/runtime/auth/pages/login.vue +2 -10
  8. package/dist/runtime/auth/pages/login.vue.d.ts +1 -11
  9. package/dist/runtime/auth/pages/logout.d.vue.ts +1 -11
  10. package/dist/runtime/auth/pages/logout.vue +4 -6
  11. package/dist/runtime/auth/pages/logout.vue.d.ts +1 -11
  12. package/dist/runtime/auth/plugins/auth.js +45 -26
  13. package/dist/runtime/auth/stores/auth.d.ts +38 -29
  14. package/dist/runtime/auth/stores/auth.js +20 -3
  15. package/dist/runtime/auth/utils/isAuthCallback.d.ts +3 -0
  16. package/dist/runtime/auth/utils/isAuthCallback.js +9 -0
  17. package/dist/runtime/auth/utils/parseCedulaFromSub.d.ts +1 -0
  18. package/dist/runtime/auth/utils/parseCedulaFromSub.js +4 -0
  19. package/dist/runtime/auth/utils/parseUserInfo.d.ts +6 -0
  20. package/dist/runtime/auth/utils/parseUserInfo.js +55 -0
  21. package/dist/runtime/auth/utils/postLoginRedirect.d.ts +3 -0
  22. package/dist/runtime/auth/utils/postLoginRedirect.js +25 -0
  23. package/dist/runtime/composables/useFonts.d.ts +3 -0
  24. package/dist/runtime/composables/useFonts.js +10 -0
  25. package/dist/runtime/repository-pattern/plugins/api-fetch.d.ts +2 -0
  26. package/dist/runtime/repository-pattern/plugins/api-fetch.js +5 -1
  27. package/dist/runtime/types/index.d.ts +8 -7
  28. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "una-nuxt-module",
3
- "version": "3.0.36",
3
+ "version": "3.0.37",
4
4
  "configKey": "unaxt",
5
5
  "compatibility": {
6
6
  "nuxt": ">=4.0.0"
package/dist/module.mjs CHANGED
@@ -167,7 +167,7 @@ function addTemplates() {
167
167
  }
168
168
 
169
169
  const name = "una-nuxt-module";
170
- const version = "3.0.36";
170
+ const version = "3.0.37";
171
171
 
172
172
  const module$1 = defineNuxtModule({
173
173
  meta: {
@@ -185,7 +185,6 @@ const module$1 = defineNuxtModule({
185
185
  enabled: true,
186
186
  sso: {
187
187
  automaticSignIn: true,
188
- postLoginRedirectUrl: "/",
189
188
  signInRedirectUrl: "/auth/sso/login",
190
189
  signOutRedirectUrl: "/auth/sso/logout"
191
190
  },
@@ -236,6 +235,21 @@ const module$1 = defineNuxtModule({
236
235
  options = defu(nuxt.options.runtimeConfig.public.unaxt, options);
237
236
  nuxt.options.runtimeConfig.public.unaxt = options;
238
237
  nuxt.options.alias["#unaxt"] = resolve("./runtime");
238
+ function injectComponentsConfig() {
239
+ if (nuxt.options.components === false) {
240
+ return;
241
+ }
242
+ nuxt.options.components = {
243
+ dirs: [
244
+ { path: "~/components/global", global: true },
245
+ {
246
+ path: "~/components",
247
+ pattern: ["*/**", "**"],
248
+ pathPrefix: false
249
+ }
250
+ ]
251
+ };
252
+ }
239
253
  function setupAutoImports() {
240
254
  addImportsDir(
241
255
  ["composables", "constants", "enums", "types", "utils"].map(
@@ -303,12 +317,13 @@ const module$1 = defineNuxtModule({
303
317
  if (options.auth?.enabled) {
304
318
  logger.ready(green("Iniciando m\xF3dulo de autenticaci\xF3n"));
305
319
  addImportsDir(
306
- ["auth/stores", "auth/composables"].map(
320
+ ["auth/stores", "auth/composables", "auth/utils"].map(
307
321
  (dir) => resolve(`./runtime/${dir}`)
308
322
  )
309
323
  );
310
324
  logger.ready("\u251C\u2500\u2500 " + gray("Stores"));
311
325
  logger.ready("\u251C\u2500\u2500 " + gray("Composables"));
326
+ logger.ready("\u251C\u2500\u2500 " + gray("Utils"));
312
327
  addPlugin({
313
328
  name: "auth",
314
329
  src: resolve("./runtime/auth/plugins/auth"),
@@ -390,6 +405,7 @@ const module$1 = defineNuxtModule({
390
405
  `)));
391
406
  logger.start(cyan(bold("Registro del m\xF3dulo iniciado...")));
392
407
  const startTime = Date.now();
408
+ injectComponentsConfig();
393
409
  setupAutoImports();
394
410
  setupAuth();
395
411
  setupComponents();
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Middleware encargado de sincronizar los datos de la sesión del usuario.
2
+ * Middleware encargado de sincronizar los datos de la sesion del usuario.
3
3
  *
4
- * En el flujo de inicio de sesión mediante SSO, en el cuál el usuario ingresa y hay una sesión activa en las cookies,
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 sesión estaran sincronizados en Pinia.
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, useRuntimeConfig } from "#app";
1
+ import { defineNuxtRouteMiddleware, useNuxtApp } from "#app";
2
2
  import { useAuthStore } from "../stores/auth.js";
3
- import { useAuthorization } from "../composables/useAuthorization.js";
4
- export default defineNuxtRouteMiddleware(async () => {
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
- const runtimeConfig = useRuntimeConfig();
14
- const authConfig = runtimeConfig.public.unaxt.auth;
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 resources = await authorization.getResources(token);
24
- let email = "";
25
- const getUserInfo = () => {
26
- if (authResponse?.email) {
27
- const rawEmail = Array.isArray(authResponse?.email) ? authResponse?.email[0] : authResponse?.email;
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
- ...getUserInfo(),
39
- cedula: authResponse?.displayName,
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 var __VLS_1: {};
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
- <slot />
2
+ <LoadingSessionScreen />
3
3
  </template>
4
4
 
5
5
  <script setup>
6
- import { useRuntimeConfig } from "#app";
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 var __VLS_1: {};
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 var __VLS_1: {};
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
- <slot />
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
- const runtimeConfig = useRuntimeConfig();
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 var __VLS_1: {};
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 { defineNuxtPlugin, useRuntimeConfig, useNuxtApp } from "#app";
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 { useAuthorization } from "../composables/useAuthorization.js";
8
- export default defineNuxtPlugin(() => {
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,49 @@ 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
- if (authConfig.sso?.automaticSignIn) {
26
- auth?.signIn();
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 authorization = useAuthorization();
32
- let email = "";
33
- const getUserInfo = () => {
34
- if (response?.email) {
35
- const rawEmail = Array.isArray(response?.email) ? response?.email[0] : response?.email;
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
- ...getUserInfo(),
47
- cedula: response.displayName,
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(
71
+ getPostLoginRedirect(authConfig.sso?.postLoginRedirectUrl)
72
+ );
73
+ } catch (error) {
74
+ console.error("Error procesando callback SSO:", error);
75
+ }
76
+ });
77
+ }
59
78
  return {
60
79
  provide: {
61
80
  /**
@@ -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: string;
7
+ cedula?: string | undefined;
8
8
  email: string;
9
9
  fullName?: string | undefined;
10
10
  name?: string | undefined;
11
- lastName?: string | undefined;
11
+ lastName1?: string | undefined;
12
+ lastName2?: string | undefined;
12
13
  } | null, IAuthenticatedUser | {
13
- cedula: string;
14
+ cedula?: string | undefined;
14
15
  email: string;
15
16
  fullName?: string | undefined;
16
17
  name?: string | undefined;
17
- lastName?: string | undefined;
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: string;
51
+ cedula?: string | undefined;
49
52
  email: string;
50
53
  fullName?: string | undefined;
51
54
  name?: string | undefined;
52
- lastName?: string | undefined;
55
+ lastName1?: string | undefined;
56
+ lastName2?: string | undefined;
53
57
  } | null, IAuthenticatedUser | {
54
- cedula: string;
58
+ cedula?: string | undefined;
55
59
  email: string;
56
60
  fullName?: string | undefined;
57
61
  name?: string | undefined;
58
- lastName?: string | undefined;
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: string;
95
+ cedula?: string | undefined;
90
96
  email: string;
91
97
  fullName?: string | undefined;
92
98
  name?: string | undefined;
93
- lastName?: string | undefined;
99
+ lastName1?: string | undefined;
100
+ lastName2?: string | undefined;
94
101
  } | null, IAuthenticatedUser | {
95
- cedula: string;
102
+ cedula?: string | undefined;
96
103
  email: string;
97
104
  fullName?: string | undefined;
98
105
  name?: string | undefined;
99
- lastName?: string | undefined;
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 = data;
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.find(
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,3 @@
1
+ export declare function isAuthCallback(path: string): boolean;
2
+ export declare function isSignInCallback(path: string): boolean;
3
+ export declare function isSignOutCallback(path: string): boolean;
@@ -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,4 @@
1
+ export function parseCedulaFromSub(sub) {
2
+ if (!sub) return void 0;
3
+ return /^\d{9}$/.test(sub) ? sub : void 0;
4
+ }
@@ -0,0 +1,6 @@
1
+ import type { IAuthenticatedUser } from '../../types/index.js';
2
+ export declare function parseUserInfo(claims: {
3
+ email?: string | string[];
4
+ givenName?: string;
5
+ familyName?: string;
6
+ }): Omit<IAuthenticatedUser, 'cedula'>;
@@ -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,3 @@
1
+ export declare function isSafePath(path: string): boolean;
2
+ export declare function savePostLoginRedirect(path: string): void;
3
+ export declare function getPostLoginRedirect(fallback?: string): string;
@@ -0,0 +1,25 @@
1
+ import { isAuthCallback } from "./isAuthCallback.js";
2
+ const STORAGE_KEY = "postLoginRedirect";
3
+ export function isSafePath(path) {
4
+ return Boolean(path?.startsWith("/") && !path.startsWith("//"));
5
+ }
6
+ export function savePostLoginRedirect(path) {
7
+ if (!import.meta.client) {
8
+ return;
9
+ }
10
+ if (!isSafePath(path) || isAuthCallback(path)) {
11
+ return;
12
+ }
13
+ sessionStorage.setItem(STORAGE_KEY, path);
14
+ }
15
+ export function getPostLoginRedirect(fallback = "/") {
16
+ if (!import.meta.client) {
17
+ return fallback;
18
+ }
19
+ const stored = sessionStorage.getItem(STORAGE_KEY);
20
+ sessionStorage.removeItem(STORAGE_KEY);
21
+ if (stored && isSafePath(stored)) {
22
+ return stored;
23
+ }
24
+ return fallback;
25
+ }
@@ -0,0 +1,3 @@
1
+ export declare function useFonts(): {
2
+ fontsReady: import("vue").Ref<boolean, boolean>;
3
+ };
@@ -0,0 +1,10 @@
1
+ import { onMounted, ref } from "#imports";
2
+ export function useFonts() {
3
+ const fontsReady = ref(false);
4
+ onMounted(() => {
5
+ document.fonts.ready.then(() => {
6
+ fontsReady.value = true;
7
+ });
8
+ });
9
+ return { fontsReady };
10
+ }
@@ -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
  };
@@ -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} lastName - Primer apellido del usuario
225
- * @property {string} photoUrl - Url de la foto del usuario
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: string;
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
- lastName?: string;
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: IResource[];
279
+ resources?: IResource[];
279
280
  }
280
281
  /**
281
282
  * Interfaz para los parámetros de métodos de validación de permisos en recursos.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "una-nuxt-module",
3
- "version": "3.0.36",
3
+ "version": "3.0.37",
4
4
  "description": "Módulo Nuxt para desarrollo CGI",
5
5
  "repository": {
6
6
  "type": "git",