@sowell/quasar-app-extension-auth 0.3.4 → 0.3.7
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 +4 -2
- package/src/assets/Email-sent.svg +32 -0
- package/src/assets/Illustration-password.svg +79 -0
- package/src/assets/Ok-illustration.svg +13 -0
- package/src/assets/Sowell-logo.svg +4 -0
- package/src/assets/User-not-found.svg +23 -0
- package/src/assets/illustration-login.svg +98 -0
- package/src/boot/router-guards.ts +11 -7
- package/src/components/dialogs/Message.vue +47 -23
- package/src/components/dialogs/SendEmail.vue +8 -5
- package/src/components/dialogs/WebSendEmail.vue +108 -0
- package/src/components/dialogs/sw-info-dialog.vue +87 -0
- package/src/components/pages/Auth.vue +36 -157
- package/src/components/pages/ResetPassword.vue +20 -191
- package/src/components/pages/WebAuth.vue +168 -218
- package/src/components/pages/WebResetPassword.vue +128 -0
- package/src/composables/auth.ts +120 -0
- package/src/composables/resetPassword.ts +219 -0
- package/src/index.js +4 -0
- package/src/injects/index.ts +1 -0
- package/src/injects/prompts.ts +3 -1
- package/src/injects/states.ts +58 -0
- package/src/prompts.js +28 -0
- package/src/routes/index.ts +8 -1
- package/tsconfig.json +0 -1
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
class="full-width q-mb-md"
|
|
41
41
|
>
|
|
42
42
|
<template #prepend>
|
|
43
|
-
<q-icon :name="ionLockClosedOutline" />
|
|
43
|
+
<q-icon :name="icons.ionLockClosedOutline" />
|
|
44
44
|
</template>
|
|
45
45
|
</q-input>
|
|
46
46
|
</div>
|
|
@@ -60,7 +60,10 @@
|
|
|
60
60
|
</q-form>
|
|
61
61
|
</div>
|
|
62
62
|
<q-dialog v-model="passwordUpdated" persistent>
|
|
63
|
-
<sowell-message
|
|
63
|
+
<sowell-message
|
|
64
|
+
:passwordUpdated="passwordUpdated"
|
|
65
|
+
@goToLoginPage="goToLoginPage"
|
|
66
|
+
/>
|
|
64
67
|
</q-dialog>
|
|
65
68
|
</q-page>
|
|
66
69
|
</q-layout>
|
|
@@ -68,210 +71,36 @@
|
|
|
68
71
|
|
|
69
72
|
<script lang="ts">
|
|
70
73
|
//@ts-ignore
|
|
71
|
-
import {
|
|
74
|
+
import { defineComponent } from "vue";
|
|
72
75
|
import SowellMessage from "../dialogs/Message.vue";
|
|
73
|
-
import {
|
|
74
|
-
import { useI18n } from "vue-i18n";
|
|
75
|
-
import { $api, $prompts, $router } from "../../injects";
|
|
76
|
-
import jwt from 'jwt-decode'
|
|
77
|
-
import { Buffer } from 'buffer/' // NOTE: the trailing '/' is intentional and required by buffer
|
|
78
|
-
import {
|
|
79
|
-
ionLockClosedOutline,
|
|
80
|
-
ionCloseOutline,
|
|
81
|
-
ionAlertCircleOutline
|
|
82
|
-
} from "@quasar/extras/ionicons-v5";
|
|
83
|
-
|
|
84
|
-
interface DecodedToken { // FIXME: consider to move to its own file
|
|
85
|
-
sub: number,
|
|
86
|
-
email: string,
|
|
87
|
-
token: string
|
|
88
|
-
}
|
|
76
|
+
import { useResetPassword } from "composables/resetPassword";
|
|
89
77
|
|
|
90
78
|
export default defineComponent({
|
|
91
79
|
name: "ResetPassword",
|
|
92
80
|
components: { SowellMessage },
|
|
93
81
|
setup() {
|
|
94
|
-
const { patch, post } = $api();
|
|
95
82
|
const {
|
|
96
|
-
|
|
97
|
-
|
|
83
|
+
password,
|
|
84
|
+
loading,
|
|
85
|
+
passwordUpdated,
|
|
86
|
+
validations,
|
|
98
87
|
LOCAL_LOGIN_ROUTE,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const loading = ref(false);
|
|
105
|
-
const passwordUpdated = ref(false)
|
|
106
|
-
const { t } = useI18n();
|
|
107
|
-
|
|
108
|
-
const token = ref("")
|
|
109
|
-
|
|
110
|
-
const decodedToken = computed(() => {
|
|
111
|
-
if (!token.value) return null
|
|
112
|
-
return jwt(token.value) as DecodedToken
|
|
113
|
-
}) as Ref<DecodedToken | null>
|
|
114
|
-
|
|
115
|
-
const canSubmit = computed(() => {
|
|
116
|
-
return decodedToken.value !== null && password.value.length >= 6
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const validations = {
|
|
120
|
-
passwordRules: [
|
|
121
|
-
(val: string) => !!val || t("auth.passwordPresenceError"),
|
|
122
|
-
(val: string) => val.length >= 6 || t("auth.passwordLengthError")
|
|
123
|
-
],
|
|
124
|
-
passwordConfirmationRules: [
|
|
125
|
-
(val: string) =>
|
|
126
|
-
val === password.value || t("auth.newPasswordConfirmationFailed"),
|
|
127
|
-
(val: string) => !!val || t("auth.passwordPresenceError"),
|
|
128
|
-
(val: string) => val.length >= 6 || t("auth.passwordLengthError"),
|
|
129
|
-
],
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const decodeKey = (key: string) => {
|
|
133
|
-
try {
|
|
134
|
-
// remove backslash to avoid decoding error
|
|
135
|
-
key = key.replace(/\\n/g, '')
|
|
136
|
-
const decodedKey = Buffer.from(key, 'base64').toString('utf-8').split(',')
|
|
137
|
-
// split instead of JSON.parse as JSON.parse doesn't work
|
|
138
|
-
|
|
139
|
-
if (decodedKey.length !== 2) {
|
|
140
|
-
throw 'Invalid encoded key'
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const email = decodedKey[0].replace('{', '').split(':')[1]
|
|
144
|
-
const tmpToken = decodedKey[1].replace('}', '').split(':')[1]
|
|
145
|
-
return {
|
|
146
|
-
decoded: true,
|
|
147
|
-
email,
|
|
148
|
-
tmpToken
|
|
149
|
-
}
|
|
150
|
-
} catch (err) {
|
|
151
|
-
console.log('decodeKey err', err)
|
|
152
|
-
return {
|
|
153
|
-
decoded: false
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const onSubmit = () => {
|
|
159
|
-
const updatePasswordPayload = {
|
|
160
|
-
data: {
|
|
161
|
-
type: "users",
|
|
162
|
-
id: decodedToken.value.sub,
|
|
163
|
-
attributes:
|
|
164
|
-
{
|
|
165
|
-
password: password.value
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const updatePasswordHeaders = {
|
|
170
|
-
headers: {
|
|
171
|
-
'Authorization': `Bearer ${token.value}`
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
patch(
|
|
176
|
-
AUTH_SERVER_UPDATE_PASSWORD_ROUTE.replace(':userId', String(decodedToken.value.sub)),
|
|
177
|
-
updatePasswordPayload,
|
|
178
|
-
updatePasswordHeaders
|
|
179
|
-
).then(() => {
|
|
180
|
-
passwordUpdated.value = true;
|
|
181
|
-
}).catch(() => {
|
|
182
|
-
$q.notify({
|
|
183
|
-
message: t("auth.passwordRecoveryFailed"),
|
|
184
|
-
color: "negative",
|
|
185
|
-
icon:ionAlertCircleOutline,
|
|
186
|
-
position: "top",
|
|
187
|
-
actions: [
|
|
188
|
-
{
|
|
189
|
-
color: "white",
|
|
190
|
-
icon: ionCloseOutline,
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const goToLoginPage = () => {
|
|
198
|
-
router.push(LOCAL_LOGIN_ROUTE);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
onMounted(() => {
|
|
202
|
-
let key = $route.query.key as string
|
|
203
|
-
const { decoded, email, tmpToken } = decodeKey(key)
|
|
204
|
-
|
|
205
|
-
if (!decoded) {
|
|
206
|
-
return $q.notify({
|
|
207
|
-
message: t("auth.passwordRecoveryInvalidLink"),
|
|
208
|
-
color: "negative",
|
|
209
|
-
position: "top",
|
|
210
|
-
icon: ionAlertCircleOutline,
|
|
211
|
-
actions: [
|
|
212
|
-
{
|
|
213
|
-
color: "white",
|
|
214
|
-
icon: ionCloseOutline,
|
|
215
|
-
},
|
|
216
|
-
],
|
|
217
|
-
})
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const tmpAuthPayload = {
|
|
221
|
-
auth: {
|
|
222
|
-
email: email,
|
|
223
|
-
token: tmpToken
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
post(AUTH_SERVER_SIGNING_ROUTE, tmpAuthPayload)
|
|
228
|
-
.then((response) => {
|
|
229
|
-
token.value = response.data.jwt
|
|
230
|
-
if (!token.value) throw 'Error reading the temporary token'
|
|
231
|
-
})
|
|
232
|
-
.catch((error) => {
|
|
233
|
-
if (error.response) {
|
|
234
|
-
// Request made and server responded
|
|
235
|
-
if (error.response.status === 404) {
|
|
236
|
-
return $q.notify({
|
|
237
|
-
message: t("auth.passwordRecoveryExpiredLink"),
|
|
238
|
-
color: "negative",
|
|
239
|
-
icon: ionAlertCircleOutline,
|
|
240
|
-
position: "top",
|
|
241
|
-
actions: [
|
|
242
|
-
{
|
|
243
|
-
color: "white",
|
|
244
|
-
icon: ionCloseOutline,
|
|
245
|
-
},
|
|
246
|
-
],
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return $q.notify({
|
|
251
|
-
message: t("auth.passwordRecoveryFailed"),
|
|
252
|
-
color: "negative",
|
|
253
|
-
position: "top",
|
|
254
|
-
icon: ionAlertCircleOutline,
|
|
255
|
-
actions: [
|
|
256
|
-
{
|
|
257
|
-
color: "white",
|
|
258
|
-
icon: ionCloseOutline,
|
|
259
|
-
},
|
|
260
|
-
],
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
})
|
|
88
|
+
canSubmit,
|
|
89
|
+
onSubmit,
|
|
90
|
+
goToLoginPage,
|
|
91
|
+
icons,
|
|
92
|
+
} = useResetPassword();
|
|
264
93
|
|
|
265
94
|
return {
|
|
266
95
|
password,
|
|
267
|
-
validations,
|
|
268
96
|
loading,
|
|
269
|
-
onSubmit,
|
|
270
97
|
canSubmit,
|
|
271
98
|
passwordUpdated,
|
|
272
99
|
LOCAL_LOGIN_ROUTE,
|
|
273
|
-
|
|
274
|
-
|
|
100
|
+
validations,
|
|
101
|
+
onSubmit,
|
|
102
|
+
goToLoginPage,
|
|
103
|
+
icons
|
|
275
104
|
};
|
|
276
105
|
},
|
|
277
106
|
});
|
|
@@ -1,67 +1,89 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<q-layout>
|
|
3
3
|
<div class="row window-height">
|
|
4
|
-
<div class="column
|
|
5
|
-
<div
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
<div class="col column content-center bgWhite">
|
|
5
|
+
<div class="q-mt-xl">
|
|
6
|
+
<img
|
|
7
|
+
src="../../assets/Sowell-logo.svg"
|
|
8
|
+
style="width: 210px"
|
|
9
|
+
class="logoWhite"
|
|
10
|
+
/>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="column col content-center justify-center bgWhite">
|
|
13
|
+
<div style="max-width: 500px">
|
|
14
|
+
<h4 class="title">{{ WELCOME_TITLE }}</h4>
|
|
15
|
+
<div class="subtitle">{{ WELCOME_SUBTITLE }}</div>
|
|
16
|
+
<q-form @submit="onSubmit">
|
|
17
|
+
<div>
|
|
18
|
+
<div class="q-ml-xs q-mb-xs text-subtitle2 text-weight-bold">
|
|
19
|
+
{{ $t("auth.email") }}
|
|
20
|
+
</div>
|
|
21
|
+
<q-input
|
|
22
|
+
v-model.trim="email"
|
|
23
|
+
type="email"
|
|
24
|
+
:rules="validations['email']"
|
|
25
|
+
lazy-rules
|
|
26
|
+
dense
|
|
27
|
+
outlined
|
|
28
|
+
input-class="text-subtitle2 text-weight-medium"
|
|
29
|
+
/>
|
|
30
|
+
<div class="q-ml-xs q-mb-xs text-subtitle2 text-weight-bold">
|
|
31
|
+
{{ $t("auth.password") }}
|
|
32
|
+
</div>
|
|
33
|
+
<q-input
|
|
34
|
+
v-model="password"
|
|
35
|
+
:type="showPassword ? 'text' : 'password'"
|
|
36
|
+
:rules="validations['password']"
|
|
37
|
+
lazy-rules
|
|
38
|
+
dense
|
|
39
|
+
outlined
|
|
40
|
+
input-class="text-subtitle2 text-weight-bold"
|
|
41
|
+
>
|
|
42
|
+
<template #append>
|
|
43
|
+
<q-icon
|
|
44
|
+
:name="
|
|
45
|
+
showPassword ? icons.ionEyeSharp : icons.ionEyeOffSharp
|
|
46
|
+
"
|
|
47
|
+
class="cursor-pointer q-mr-sm lightenDark"
|
|
48
|
+
@click="showPassword = !showPassword"
|
|
49
|
+
/>
|
|
50
|
+
</template>
|
|
51
|
+
</q-input>
|
|
14
52
|
</div>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
53
|
+
<div class="row justify-between items-center">
|
|
54
|
+
<q-btn
|
|
55
|
+
:label="$t('auth.login')"
|
|
56
|
+
color="primary"
|
|
57
|
+
no-caps
|
|
58
|
+
unelevated
|
|
59
|
+
text-color="white"
|
|
60
|
+
:loading="loading"
|
|
61
|
+
type="submit"
|
|
62
|
+
:disable="isSubmitBtnDisabled()"
|
|
63
|
+
class="submitBtn text-subtitle2 text-weight-bold"
|
|
64
|
+
/>
|
|
65
|
+
<div
|
|
66
|
+
class="cursor-pointer text-primary text-subtitle2"
|
|
67
|
+
@click="forgottenPassword = true"
|
|
68
|
+
>
|
|
69
|
+
{{ $t("auth.forgottenPassword") }}
|
|
70
|
+
</div>
|
|
28
71
|
</div>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
:type="showPassword ? 'text' : 'password'"
|
|
32
|
-
:rules="validations['password']"
|
|
33
|
-
lazy-rules
|
|
34
|
-
outlined
|
|
35
|
-
dense
|
|
36
|
-
input-class="text-subtitle2 text-weight-bold"
|
|
37
|
-
>
|
|
38
|
-
<template #append>
|
|
39
|
-
<q-icon
|
|
40
|
-
:name="showPassword ? ionEyeOutline : ionEyeOffOutline"
|
|
41
|
-
class="cursor-pointer q-mr-sm"
|
|
42
|
-
@click="showPassword = !showPassword"
|
|
43
|
-
/>
|
|
44
|
-
</template>
|
|
45
|
-
</q-input>
|
|
46
|
-
</div>
|
|
47
|
-
<div class="row justify-between items-center">
|
|
48
|
-
<q-btn
|
|
49
|
-
:label="$t('auth.login')"
|
|
50
|
-
color="primary"
|
|
51
|
-
no-caps
|
|
52
|
-
unelevated
|
|
53
|
-
text-color="white"
|
|
54
|
-
:loading="loading"
|
|
55
|
-
type="submit"
|
|
56
|
-
:disable="submitBtnDisabled"
|
|
57
|
-
/>
|
|
58
|
-
<div class="cursor-pointer" @click="forgottenPassword = true">{{ $t('auth.forgottenPassword') }}</div>
|
|
59
|
-
</div>
|
|
60
|
-
</q-form>
|
|
72
|
+
</q-form>
|
|
73
|
+
</div>
|
|
61
74
|
</div>
|
|
62
75
|
</div>
|
|
63
|
-
<div
|
|
64
|
-
|
|
76
|
+
<div
|
|
77
|
+
class="column col justify-center content-center"
|
|
78
|
+
:style="isManager ? 'background: #eef8fd' : ''"
|
|
79
|
+
:class="!isManager ? 'bgBlue' : ''"
|
|
80
|
+
>
|
|
81
|
+
<img
|
|
82
|
+
v-if="isManager"
|
|
83
|
+
src="../../assets/illustration-login.svg"
|
|
84
|
+
style="width: 600px"
|
|
85
|
+
/>
|
|
86
|
+
<img v-else src="../../assets/SowellWhite.svg" class="logoWhite" />
|
|
65
87
|
</div>
|
|
66
88
|
</div>
|
|
67
89
|
<div>
|
|
@@ -73,14 +95,13 @@
|
|
|
73
95
|
transition-hide="fade"
|
|
74
96
|
persistent
|
|
75
97
|
>
|
|
76
|
-
<send-email @resetPassword="resetPassword" />
|
|
98
|
+
<web-send-email @resetPassword="resetPassword" />
|
|
77
99
|
</q-dialog>
|
|
78
|
-
<q-dialog v-model="
|
|
79
|
-
<
|
|
80
|
-
:
|
|
81
|
-
:
|
|
82
|
-
:
|
|
83
|
-
@retypeEmail="retypeEmail"
|
|
100
|
+
<q-dialog v-model="isNotification" persistent>
|
|
101
|
+
<sw-info-dialog
|
|
102
|
+
:title="infoDialog.title"
|
|
103
|
+
:content="infoDialog.content"
|
|
104
|
+
:image="infoDialog.image"
|
|
84
105
|
/>
|
|
85
106
|
</q-dialog>
|
|
86
107
|
</div>
|
|
@@ -89,203 +110,132 @@
|
|
|
89
110
|
|
|
90
111
|
<script lang="ts">
|
|
91
112
|
import isEmail from "validator/es/lib/isEmail";
|
|
92
|
-
import { defineComponent, ref,
|
|
93
|
-
import {
|
|
94
|
-
import { useQuasar } from "quasar";
|
|
113
|
+
import { defineComponent, ref, computed } from "vue";
|
|
114
|
+
import { useAuthState } from "../../injects";
|
|
95
115
|
import { useI18n } from "vue-i18n";
|
|
96
|
-
import
|
|
97
|
-
import
|
|
98
|
-
|
|
99
|
-
import
|
|
100
|
-
import {
|
|
101
|
-
ionMailOutline,
|
|
102
|
-
ionLockClosedOutline,
|
|
103
|
-
ionEyeOutline,
|
|
104
|
-
ionEyeOffOutline,
|
|
105
|
-
ionAlertCircleOutline,
|
|
106
|
-
ionCloseOutline
|
|
107
|
-
} from "@quasar/extras/ionicons-v5";
|
|
116
|
+
import SwInfoDialog from "../dialogs/sw-info-dialog.vue";
|
|
117
|
+
import WebSendEmail from "../dialogs/WebSendEmail.vue";
|
|
118
|
+
|
|
119
|
+
import { useAuth } from "composables/auth";
|
|
108
120
|
|
|
109
121
|
interface HeadersInterface {
|
|
110
122
|
headers: {
|
|
111
|
-
"x-requested-roles"?: string
|
|
112
|
-
}
|
|
123
|
+
"x-requested-roles"?: string;
|
|
124
|
+
};
|
|
113
125
|
}
|
|
114
126
|
export default defineComponent({
|
|
115
|
-
name:
|
|
116
|
-
components: {
|
|
127
|
+
name: "Auth",
|
|
128
|
+
components: { WebSendEmail, SwInfoDialog },
|
|
117
129
|
setup() {
|
|
118
|
-
const {
|
|
119
|
-
"@sowell/auth": { X_REQUESTED_ROLES },
|
|
120
|
-
} = prompts;
|
|
121
|
-
const email = ref("");
|
|
122
|
-
const password = ref("");
|
|
123
|
-
const loading = ref(false);
|
|
124
|
-
const showPassword = ref(false);
|
|
125
|
-
const forgottenPassword = ref(false);
|
|
126
|
-
const isReset = ref(false);
|
|
127
|
-
const sendEmailSuccess = ref(false);
|
|
128
|
-
const emailResetPassword = ref("");
|
|
129
|
-
const { post } = $api();
|
|
130
|
-
const {
|
|
131
|
-
LOCAL_SUCCESS_REDIRECTION_ROUTE,
|
|
132
|
-
AUTH_SERVER_SIGNING_ROUTE,
|
|
133
|
-
AUTH_SERVER_RESET_PASSWORD_ROUTE,
|
|
134
|
-
APP_SERVER_BASE_URL,
|
|
135
|
-
} = $prompts();
|
|
136
|
-
const $q = useQuasar();
|
|
137
|
-
const { push, replace } = $router();
|
|
138
|
-
const { dispatch, getters } = $store();
|
|
139
130
|
const { t } = useI18n();
|
|
131
|
+
const authState = useAuthState();
|
|
140
132
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
133
|
+
const {
|
|
134
|
+
email,
|
|
135
|
+
password,
|
|
136
|
+
loading,
|
|
137
|
+
showPassword,
|
|
138
|
+
validations,
|
|
139
|
+
forgottenPassword,
|
|
140
|
+
emailResetPassword,
|
|
141
|
+
WELCOME_TITLE,
|
|
142
|
+
WELCOME_SUBTITLE,
|
|
143
|
+
X_REQUESTED_ROLES,
|
|
144
|
+
APP_SERVER_BASE_URL,
|
|
145
|
+
onSubmit,
|
|
146
|
+
retypeEmail,
|
|
147
|
+
isSubmitBtnDisabled,
|
|
148
|
+
icons,
|
|
149
|
+
} = useAuth();
|
|
146
150
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
password: [(val: string) => !!val || t("auth.passwordPresenceError")],
|
|
151
|
+
const isNotification = ref(false);
|
|
152
|
+
const infoDialog = ref({
|
|
153
|
+
title: "",
|
|
154
|
+
content: "",
|
|
155
|
+
image: "",
|
|
153
156
|
});
|
|
154
157
|
|
|
155
|
-
const
|
|
158
|
+
const submitBtnDisabled = computed(
|
|
159
|
+
() =>
|
|
160
|
+
!(
|
|
161
|
+
email.value &&
|
|
162
|
+
isEmail(email.value) &&
|
|
163
|
+
password.value &&
|
|
164
|
+
password.value.length > 5
|
|
165
|
+
),
|
|
166
|
+
);
|
|
167
|
+
const isManager = computed(() => X_REQUESTED_ROLES === "clean_manager");
|
|
168
|
+
const resetPassword = async (email: string) => {
|
|
156
169
|
const data = {
|
|
157
170
|
auth: {
|
|
158
171
|
email,
|
|
159
172
|
base: APP_SERVER_BASE_URL,
|
|
160
173
|
},
|
|
161
174
|
};
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
loading.value = true;
|
|
181
|
-
const data = {
|
|
182
|
-
auth: {
|
|
183
|
-
email: email.value,
|
|
184
|
-
password: password.value,
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
const options: HeadersInterface = {
|
|
188
|
-
headers:{}
|
|
189
|
-
};
|
|
190
|
-
// @ts-ignore
|
|
191
|
-
let requestedRoles = window.Cypress ? window.Cypress.requestedRoles : X_REQUESTED_ROLES;
|
|
192
|
-
if (requestedRoles) options.headers["x-requested-roles"] = requestedRoles;
|
|
193
|
-
|
|
194
|
-
post(AUTH_SERVER_SIGNING_ROUTE, data, options)
|
|
195
|
-
.then((response: AxiosResponse) => {
|
|
196
|
-
const token = response.data.jwt;
|
|
197
|
-
dispatch("token/updateRaw", token);
|
|
198
|
-
push(LOCAL_SUCCESS_REDIRECTION_ROUTE);
|
|
199
|
-
})
|
|
200
|
-
.catch((error: AxiosError) => {
|
|
201
|
-
loading.value = false;
|
|
202
|
-
switch (error.response?.status) {
|
|
203
|
-
case 403:
|
|
204
|
-
$q.notify({
|
|
205
|
-
message: t("auth.403"),
|
|
206
|
-
color: "negative",
|
|
207
|
-
icon: ionAlertCircleOutline,
|
|
208
|
-
position: "top",
|
|
209
|
-
actions: [
|
|
210
|
-
{
|
|
211
|
-
color: "white",
|
|
212
|
-
icon: ionCloseOutline,
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
});
|
|
216
|
-
break;
|
|
217
|
-
case 404:
|
|
218
|
-
$q.notify({
|
|
219
|
-
message: t("auth.404"),
|
|
220
|
-
color: "negative",
|
|
221
|
-
icon: ionAlertCircleOutline,
|
|
222
|
-
position: "top",
|
|
223
|
-
actions: [
|
|
224
|
-
{
|
|
225
|
-
color: "white",
|
|
226
|
-
icon: ionCloseOutline,
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
});
|
|
230
|
-
break;
|
|
231
|
-
default:
|
|
232
|
-
$q.notify({
|
|
233
|
-
message: t("auth.loginFailed"),
|
|
234
|
-
color: "negative",
|
|
235
|
-
icon: ionAlertCircleOutline,
|
|
236
|
-
position: "top",
|
|
237
|
-
actions: [
|
|
238
|
-
{
|
|
239
|
-
color: "white",
|
|
240
|
-
icon: ionCloseOutline,
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
});
|
|
175
|
+
try {
|
|
176
|
+
await authState.resetPassword(data);
|
|
177
|
+
forgottenPassword.value = false;
|
|
178
|
+
infoDialog.value = {
|
|
179
|
+
title: t("auth.mailVerificationTitle"),
|
|
180
|
+
content: t("auth.mailVerificationSubtitle"),
|
|
181
|
+
image: "emailVerification",
|
|
182
|
+
};
|
|
183
|
+
forgottenPassword.value = false;
|
|
184
|
+
isNotification.value = true;
|
|
185
|
+
} catch {
|
|
186
|
+
infoDialog.value = {
|
|
187
|
+
title: t("auth.userNotFoundTitle"),
|
|
188
|
+
content: t("auth.userNotFoundSubtitle"),
|
|
189
|
+
image: "userNotFound",
|
|
190
|
+
};
|
|
191
|
+
isNotification.value = true;
|
|
192
|
+
}
|
|
246
193
|
};
|
|
247
194
|
|
|
248
|
-
const submitBtnDisabled = computed(() => !(
|
|
249
|
-
email.value &&
|
|
250
|
-
isEmail(email.value) &&
|
|
251
|
-
password.value &&
|
|
252
|
-
password.value.length > 5
|
|
253
|
-
)
|
|
254
|
-
)
|
|
255
195
|
return {
|
|
256
196
|
email,
|
|
197
|
+
infoDialog,
|
|
257
198
|
password,
|
|
258
199
|
loading,
|
|
259
200
|
showPassword,
|
|
260
201
|
validations,
|
|
261
202
|
submitBtnDisabled,
|
|
262
|
-
onSubmit,
|
|
263
203
|
forgottenPassword,
|
|
264
204
|
emailResetPassword,
|
|
205
|
+
isNotification,
|
|
206
|
+
isManager,
|
|
207
|
+
WELCOME_SUBTITLE,
|
|
208
|
+
WELCOME_TITLE,
|
|
209
|
+
isSubmitBtnDisabled,
|
|
265
210
|
resetPassword,
|
|
266
|
-
isReset,
|
|
267
211
|
retypeEmail,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
ionEyeOutline,
|
|
272
|
-
ionEyeOffOutline,
|
|
273
|
-
}
|
|
212
|
+
onSubmit,
|
|
213
|
+
icons,
|
|
214
|
+
};
|
|
274
215
|
},
|
|
275
|
-
})
|
|
216
|
+
});
|
|
276
217
|
</script>
|
|
277
218
|
|
|
278
219
|
<style scoped>
|
|
220
|
+
.bgWhite {
|
|
221
|
+
background: #ffffff;
|
|
222
|
+
}
|
|
279
223
|
.bgBlue {
|
|
280
224
|
background: var(--q-primary);
|
|
281
225
|
}
|
|
226
|
+
.lightenDark {
|
|
227
|
+
color: rgba(0, 0, 0, 0.24);
|
|
228
|
+
}
|
|
282
229
|
.title {
|
|
283
230
|
margin: 0px 0px 16px 0px;
|
|
284
231
|
}
|
|
285
232
|
.subtitle {
|
|
286
|
-
margin-bottom:
|
|
233
|
+
margin-bottom: 80px;
|
|
287
234
|
}
|
|
288
235
|
.logoWhite {
|
|
289
|
-
width: 30
|
|
236
|
+
width: 30%;
|
|
237
|
+
}
|
|
238
|
+
.submitBtn {
|
|
239
|
+
width: 254px;
|
|
290
240
|
}
|
|
291
241
|
</style>
|