@drax/identity-vue 3.14.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.15.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"@drax/common-vue": "^3.11.0",
|
|
29
29
|
"@drax/crud-front": "^3.11.0",
|
|
30
30
|
"@drax/crud-share": "^3.14.0",
|
|
31
|
-
"@drax/crud-vue": "^3.
|
|
32
|
-
"@drax/identity-front": "^3.
|
|
33
|
-
"@drax/identity-share": "^3.
|
|
31
|
+
"@drax/crud-vue": "^3.15.0",
|
|
32
|
+
"@drax/identity-front": "^3.15.0",
|
|
33
|
+
"@drax/identity-share": "^3.15.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"pinia": "^3.0.4",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"vue-tsc": "^3.2.4",
|
|
56
56
|
"vuetify": "^3.11.8"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "a3bd3419f580b111b26da9e6be2e1cc4c75a056e"
|
|
59
59
|
}
|
|
@@ -38,6 +38,10 @@ export function useAuth() {
|
|
|
38
38
|
return await authSystem.changeOwnPassword(currentPassword, newPassword)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
const passwordPolicy = async () => {
|
|
42
|
+
return await authSystem.passwordPolicy()
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
const recoveryPasswordRequest = async (email: string) => {
|
|
42
46
|
return await authSystem.recoveryPasswordRequest(email)
|
|
43
47
|
}
|
|
@@ -99,7 +103,7 @@ export function useAuth() {
|
|
|
99
103
|
login, logout, loginWithToken,
|
|
100
104
|
tokenIsValid, hasPermission,
|
|
101
105
|
isAuthenticated, fetchAuthUser,
|
|
102
|
-
changeOwnPassword, changeAvatar,
|
|
106
|
+
changeOwnPassword, changeAvatar, passwordPolicy,
|
|
103
107
|
recoveryPasswordRequest, recoveryPasswordComplete,
|
|
104
108
|
register, switchTenant
|
|
105
109
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {computed, onMounted, ref} from "vue";
|
|
3
|
+
import {useAuth} from "../composables/useAuth";
|
|
4
|
+
import type {IPasswordPolicy} from "@drax/identity-front";
|
|
5
|
+
|
|
6
|
+
const {passwordPolicy} = useAuth()
|
|
7
|
+
|
|
8
|
+
const loading = ref(true)
|
|
9
|
+
const errorMsg = ref('')
|
|
10
|
+
const policy = ref<IPasswordPolicy | null>(null)
|
|
11
|
+
|
|
12
|
+
const rules = computed(() => {
|
|
13
|
+
if (!policy.value) {
|
|
14
|
+
return []
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
{
|
|
19
|
+
label: `Longitud mínima de ${policy.value.minLength} caracteres`,
|
|
20
|
+
enabled: true,
|
|
21
|
+
icon: 'mdi-format-letter-case'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: `Longitud máxima de ${policy.value.maxLength} caracteres`,
|
|
25
|
+
enabled: true,
|
|
26
|
+
icon: 'mdi-ruler'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: 'Debe incluir al menos una mayúscula',
|
|
30
|
+
enabled: policy.value.requireUppercase,
|
|
31
|
+
icon: 'mdi-format-letter-case-upper'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Debe incluir al menos una minúscula',
|
|
35
|
+
enabled: policy.value.requireLowercase,
|
|
36
|
+
icon: 'mdi-format-letter-case-lower'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Debe incluir al menos un número',
|
|
40
|
+
enabled: policy.value.requireNumber,
|
|
41
|
+
icon: 'mdi-numeric'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: 'Debe incluir al menos un carácter especial',
|
|
45
|
+
enabled: policy.value.requireSpecialChar,
|
|
46
|
+
icon: 'mdi-asterisk'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'No se permiten espacios',
|
|
50
|
+
enabled: policy.value.disallowSpaces,
|
|
51
|
+
icon: 'mdi-keyboard-space'
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const metadata = computed(() => {
|
|
57
|
+
if (!policy.value) {
|
|
58
|
+
return []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
label: 'Reutilización',
|
|
64
|
+
value: policy.value.preventReuse > 0
|
|
65
|
+
? `No se pueden repetir las últimas ${policy.value.preventReuse} contraseñas`
|
|
66
|
+
: 'Sin restricción de reutilización'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: 'Expiración',
|
|
70
|
+
value: policy.value.expirationDays
|
|
71
|
+
? `La contraseña expira cada ${policy.value.expirationDays} días`
|
|
72
|
+
: 'Sin expiración configurada'
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
async function loadPolicy() {
|
|
78
|
+
try {
|
|
79
|
+
loading.value = true
|
|
80
|
+
errorMsg.value = ''
|
|
81
|
+
policy.value = await passwordPolicy()
|
|
82
|
+
} catch (error) {
|
|
83
|
+
const err = error as Error
|
|
84
|
+
errorMsg.value = err.message || 'No se pudo obtener la política de contraseñas'
|
|
85
|
+
} finally {
|
|
86
|
+
loading.value = false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onMounted(loadPolicy)
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<template>
|
|
94
|
+
<v-container fluid class="fill-height">
|
|
95
|
+
<v-row justify="center" align="center">
|
|
96
|
+
<v-col cols="12" md="8" lg="6">
|
|
97
|
+
<v-card variant="elevated">
|
|
98
|
+
<v-card-title class="pa-4">
|
|
99
|
+
Política de contraseñas
|
|
100
|
+
</v-card-title>
|
|
101
|
+
|
|
102
|
+
<v-card-text v-if="loading">
|
|
103
|
+
<div class="text-medium-emphasis">Cargando política...</div>
|
|
104
|
+
</v-card-text>
|
|
105
|
+
|
|
106
|
+
<v-card-text v-else-if="errorMsg">
|
|
107
|
+
<v-alert type="error" variant="tonal">
|
|
108
|
+
{{ errorMsg }}
|
|
109
|
+
</v-alert>
|
|
110
|
+
</v-card-text>
|
|
111
|
+
|
|
112
|
+
<template v-else-if="policy">
|
|
113
|
+
<v-card-text class="pb-2">
|
|
114
|
+
Requisitos que debe cumplir una contraseña válida.
|
|
115
|
+
</v-card-text>
|
|
116
|
+
|
|
117
|
+
<v-card-text class="pt-0">
|
|
118
|
+
<v-list lines="two">
|
|
119
|
+
<v-list-item
|
|
120
|
+
v-for="rule in rules"
|
|
121
|
+
:key="rule.label"
|
|
122
|
+
:prepend-icon="rule.icon"
|
|
123
|
+
>
|
|
124
|
+
<v-list-item-title>{{ rule.label }}</v-list-item-title>
|
|
125
|
+
<template #append>
|
|
126
|
+
<v-chip
|
|
127
|
+
:color="rule.enabled ? 'success' : 'default'"
|
|
128
|
+
size="small"
|
|
129
|
+
variant="tonal"
|
|
130
|
+
>
|
|
131
|
+
{{ rule.enabled ? 'Requerido' : 'Opcional' }}
|
|
132
|
+
</v-chip>
|
|
133
|
+
</template>
|
|
134
|
+
</v-list-item>
|
|
135
|
+
</v-list>
|
|
136
|
+
</v-card-text>
|
|
137
|
+
|
|
138
|
+
<v-divider />
|
|
139
|
+
|
|
140
|
+
<v-card-text>
|
|
141
|
+
<v-row>
|
|
142
|
+
<v-col
|
|
143
|
+
v-for="item in metadata"
|
|
144
|
+
:key="item.label"
|
|
145
|
+
cols="12"
|
|
146
|
+
sm="6"
|
|
147
|
+
>
|
|
148
|
+
<v-sheet class="info-box pa-4 fill-height" rounded>
|
|
149
|
+
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
|
150
|
+
<div class="text-body-1">{{ item.value }}</div>
|
|
151
|
+
</v-sheet>
|
|
152
|
+
</v-col>
|
|
153
|
+
</v-row>
|
|
154
|
+
</v-card-text>
|
|
155
|
+
</template>
|
|
156
|
+
</v-card>
|
|
157
|
+
</v-col>
|
|
158
|
+
</v-row>
|
|
159
|
+
</v-container>
|
|
160
|
+
</template>
|
|
161
|
+
|
|
162
|
+
<style scoped>
|
|
163
|
+
.info-box {
|
|
164
|
+
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import LoginPage from '../pages/LoginPage.vue'
|
|
2
2
|
import ProfilePage from '../pages/ProfilePage.vue'
|
|
3
3
|
import PasswordPage from '../pages/PasswordChangePage.vue'
|
|
4
|
+
import PasswordPolicyPage from '../pages/PasswordPolicyPage.vue'
|
|
4
5
|
import RegistrationPage from '../pages/RegistrationPage.vue'
|
|
5
6
|
import PasswordRecoveryRequestPage from '../pages/PasswordRecoveryRequestPage.vue'
|
|
6
7
|
import PasswordRecoveryCompletePage from '../pages/PasswordRecoveryCompletePage.vue'
|
|
@@ -38,6 +39,14 @@ const routes = [
|
|
|
38
39
|
auth: false,
|
|
39
40
|
}
|
|
40
41
|
},
|
|
42
|
+
{
|
|
43
|
+
name: 'PasswordPolicy',
|
|
44
|
+
path: '/password-policy',
|
|
45
|
+
component: PasswordPolicyPage,
|
|
46
|
+
meta: {
|
|
47
|
+
auth: false,
|
|
48
|
+
}
|
|
49
|
+
},
|
|
41
50
|
{
|
|
42
51
|
name: 'PasswordRecoveryRequest',
|
|
43
52
|
path: '/password/recovery/request',
|