@sowell/quasar-app-extension-auth 1.1.1 → 1.2.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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sowell/quasar-app-extension-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A Quasar app extension to manage Authentication",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"repository": "https://github.com/sowell-ai/quasar.extension.auth",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@quasar/app-webpack": "^4.0.0-beta.16",
|
|
25
25
|
"@quasar/cli": "^2.2.3",
|
|
26
|
+
"@types/crypto-js": "^4.2.2",
|
|
26
27
|
"@types/node": "^16.9.1",
|
|
27
28
|
"@types/validator": "^13.6.3",
|
|
28
29
|
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<q-card
|
|
2
|
+
<q-card
|
|
3
|
+
style="max-width: 343px; border-radius: 10px; background: #f4f5f6"
|
|
4
|
+
data-testid="feedback-dialog">
|
|
3
5
|
<q-card-section class="text-center q-mt-lg">
|
|
4
6
|
<img
|
|
5
7
|
v-if="emailSended"
|
|
6
8
|
src="../../assets/mailbox.svg"
|
|
7
|
-
style="width: 175px; height: 150px"
|
|
8
|
-
/>
|
|
9
|
+
style="width: 175px; height: 150px" />
|
|
9
10
|
<img
|
|
10
11
|
v-if="passwordUpdated"
|
|
11
12
|
src="../../assets/success.svg"
|
|
12
|
-
style="width: 100px; height: 80px"
|
|
13
|
-
/>
|
|
13
|
+
style="width: 100px; height: 80px" />
|
|
14
14
|
<img
|
|
15
15
|
v-if="emailNotSend"
|
|
16
16
|
src="../../assets/error.svg"
|
|
17
|
-
style="width: 100px; height: 80px"
|
|
18
|
-
/>
|
|
17
|
+
style="width: 100px; height: 80px" />
|
|
19
18
|
</q-card-section>
|
|
20
19
|
|
|
21
20
|
<q-card-section class="q-pt-none q-pl-lg q-pr-lg">
|
|
@@ -23,29 +22,26 @@
|
|
|
23
22
|
class="text-subtitle1 q-mt-sm q-mb-md text-center text-dark"
|
|
24
23
|
style="font-size: 24px; font-weight: 600"
|
|
25
24
|
data-cy="resetErrorMessage"
|
|
26
|
-
data-testid="header-dialog"
|
|
27
|
-
>
|
|
25
|
+
data-testid="header-dialog">
|
|
28
26
|
{{ messageTitle }}
|
|
29
27
|
</div>
|
|
30
28
|
<div
|
|
31
29
|
data-cy="resetMessage"
|
|
32
30
|
data-testid="message-dialog"
|
|
33
31
|
class="text-subtitle1 q-mt-sm text-center"
|
|
34
|
-
style="font-size: 16px; font-weight: 400"
|
|
35
|
-
>
|
|
32
|
+
style="font-size: 16px; font-weight: 400">
|
|
36
33
|
{{ messageSubtitle }}
|
|
37
34
|
</div>
|
|
38
35
|
<div
|
|
39
36
|
class="q-mt-sm text-center q-mb-xl"
|
|
40
37
|
style="font-size: 15px; color: #737676"
|
|
41
|
-
v-if="
|
|
42
|
-
>
|
|
38
|
+
v-if="sendEmailCode === 200">
|
|
43
39
|
{{ emailResetPassword }}
|
|
44
40
|
</div>
|
|
45
41
|
</q-card-section>
|
|
46
42
|
<q-card-actions class="q-ml-lg q-mr-lg q-mb-lg">
|
|
47
43
|
<q-btn
|
|
48
|
-
v-if="emailNotSend"
|
|
44
|
+
v-if="emailNotSend && sendEmailCode !== 403"
|
|
49
45
|
data-cy="submit-login"
|
|
50
46
|
:label="$t('auth.reSend')"
|
|
51
47
|
color="primary"
|
|
@@ -55,8 +51,7 @@
|
|
|
55
51
|
unelevated
|
|
56
52
|
type="submit"
|
|
57
53
|
@click="retypeEmail"
|
|
58
|
-
class="full-width"
|
|
59
|
-
/>
|
|
54
|
+
class="full-width" />
|
|
60
55
|
<slot>
|
|
61
56
|
<q-btn
|
|
62
57
|
data-testid="close-btn"
|
|
@@ -68,24 +63,23 @@
|
|
|
68
63
|
no-caps
|
|
69
64
|
:label="$t('auth.close')"
|
|
70
65
|
color="dark"
|
|
71
|
-
v-close-popup
|
|
72
|
-
/>
|
|
66
|
+
v-close-popup />
|
|
73
67
|
</slot>
|
|
74
68
|
</q-card-actions>
|
|
75
69
|
</q-card>
|
|
76
70
|
</template>
|
|
77
71
|
|
|
78
72
|
<script lang="ts">
|
|
79
|
-
import { defineComponent, computed } from "vue"
|
|
80
|
-
import { useI18n } from "vue-i18n"
|
|
73
|
+
import { defineComponent, computed } from "vue"
|
|
74
|
+
import { useI18n } from "vue-i18n"
|
|
81
75
|
|
|
82
76
|
export default defineComponent({
|
|
83
77
|
props: {
|
|
84
78
|
emailResetPassword: {
|
|
85
79
|
type: String
|
|
86
80
|
},
|
|
87
|
-
|
|
88
|
-
type:
|
|
81
|
+
sendEmailCode: {
|
|
82
|
+
type: Number
|
|
89
83
|
},
|
|
90
84
|
loading: {
|
|
91
85
|
type: Boolean
|
|
@@ -98,34 +92,40 @@ export default defineComponent({
|
|
|
98
92
|
setup(props: any, { emit }: any) {
|
|
99
93
|
const { t } = useI18n()
|
|
100
94
|
|
|
101
|
-
const messageSubtitle = computed(() =>
|
|
102
|
-
props.
|
|
95
|
+
const messageSubtitle = computed(() => {
|
|
96
|
+
if (props.sendEmailCode === 403) {
|
|
97
|
+
return t("auth.forbidden.subtitle")
|
|
98
|
+
}
|
|
99
|
+
return props.sendEmailCode === 200
|
|
103
100
|
? t("auth.emailSent")
|
|
104
101
|
: !props.passwordUpdated
|
|
105
102
|
? t("auth.emailNotRecognize")
|
|
106
103
|
: t("auth.passwordUpdated")
|
|
107
|
-
)
|
|
108
|
-
const messageTitle = computed(() =>
|
|
109
|
-
props.
|
|
104
|
+
})
|
|
105
|
+
const messageTitle = computed(() => {
|
|
106
|
+
if (props.sendEmailCode === 403) {
|
|
107
|
+
return t("auth.forbidden.title")
|
|
108
|
+
}
|
|
109
|
+
return props.sendEmailCode === 200
|
|
110
110
|
? t("auth.emailVerification")
|
|
111
111
|
: !props.passwordUpdated
|
|
112
112
|
? t("auth.loginFailed")
|
|
113
113
|
: t("auth.passwordChanged")
|
|
114
|
-
)
|
|
114
|
+
})
|
|
115
115
|
|
|
116
116
|
const emailNotSend = computed(
|
|
117
|
-
() =>
|
|
117
|
+
() => props.sendEmailCode !== 200 && !props.passwordUpdated
|
|
118
118
|
)
|
|
119
119
|
const emailSended = computed(
|
|
120
|
-
() => props.
|
|
120
|
+
() => props.sendEmailCode === 200 && !props.passwordUpdated
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
const retypeEmail = () => {
|
|
124
124
|
emit("retypeEmail")
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
const handlePasswordUpdate = () =>{
|
|
128
|
-
if(props.passwordUpdated){
|
|
127
|
+
const handlePasswordUpdate = () => {
|
|
128
|
+
if (props.passwordUpdated) {
|
|
129
129
|
emit("goToLoginPage")
|
|
130
130
|
} else {
|
|
131
131
|
emit("close")
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
<q-dialog v-model="isReset" persistent>
|
|
135
135
|
<sowell-message
|
|
136
136
|
:emailResetPassword="emailResetPassword"
|
|
137
|
-
:
|
|
137
|
+
:sendEmailCode="sendEmailCode"
|
|
138
138
|
:loading="loading"
|
|
139
139
|
@retypeEmail="retypeEmail"
|
|
140
140
|
@close="() => isReset= false"/>
|
|
@@ -177,7 +177,7 @@ export default defineComponent({
|
|
|
177
177
|
forgottenPassword,
|
|
178
178
|
emailResetPassword,
|
|
179
179
|
isReset,
|
|
180
|
-
|
|
180
|
+
sendEmailCode,
|
|
181
181
|
authState,
|
|
182
182
|
APP_SERVER_BASE_URL,
|
|
183
183
|
icons,
|
|
@@ -201,11 +201,11 @@ export default defineComponent({
|
|
|
201
201
|
try {
|
|
202
202
|
forgottenPassword.value = false
|
|
203
203
|
await authState.resetPassword(data).then(() => {
|
|
204
|
-
|
|
204
|
+
sendEmailCode.value = 200
|
|
205
205
|
isReset.value = true
|
|
206
206
|
})
|
|
207
207
|
} catch {
|
|
208
|
-
|
|
208
|
+
sendEmailCode.value = 404
|
|
209
209
|
isReset.value = true
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -228,7 +228,7 @@ export default defineComponent({
|
|
|
228
228
|
forgottenPassword,
|
|
229
229
|
emailResetPassword,
|
|
230
230
|
isReset,
|
|
231
|
-
|
|
231
|
+
sendEmailCode,
|
|
232
232
|
icons,
|
|
233
233
|
appVersion,
|
|
234
234
|
USE_SSO,
|
|
@@ -7,13 +7,11 @@
|
|
|
7
7
|
<img
|
|
8
8
|
src="../../assets/Logo.svg"
|
|
9
9
|
class="q-mb-sm q-mr-md"
|
|
10
|
-
style="width: 27px; height: 47px"
|
|
11
|
-
/>
|
|
10
|
+
style="width: 27px; height: 47px" />
|
|
12
11
|
<img
|
|
13
12
|
src="../../assets/Sowell.svg"
|
|
14
13
|
class="q-mb-sm"
|
|
15
|
-
style="width: 146px; height: 38px"
|
|
16
|
-
/>
|
|
14
|
+
style="width: 146px; height: 38px" />
|
|
17
15
|
</div>
|
|
18
16
|
</div>
|
|
19
17
|
<div class="login-page">
|
|
@@ -21,8 +19,7 @@
|
|
|
21
19
|
<div>
|
|
22
20
|
<div
|
|
23
21
|
class="q-ml-xs q-mb-xs"
|
|
24
|
-
style="font-size: 14px; font-weight: 600"
|
|
25
|
-
>
|
|
22
|
+
style="font-size: 14px; font-weight: 600">
|
|
26
23
|
{{ $t("auth.email") }}
|
|
27
24
|
</div>
|
|
28
25
|
<q-input
|
|
@@ -32,8 +29,7 @@
|
|
|
32
29
|
borderless
|
|
33
30
|
:rules="validations['email']"
|
|
34
31
|
lazy-rules
|
|
35
|
-
:input-style="{ fontSize: '14px', fontWeight: '500' }"
|
|
36
|
-
>
|
|
32
|
+
:input-style="{ fontSize: '14px', fontWeight: '500' }">
|
|
37
33
|
<template #prepend>
|
|
38
34
|
<q-icon :name="icons.ionMailOutline" />
|
|
39
35
|
</template>
|
|
@@ -42,8 +38,7 @@
|
|
|
42
38
|
<div>
|
|
43
39
|
<div
|
|
44
40
|
class="q-ml-xs q-mb-xs"
|
|
45
|
-
style="font-size: 14px; font-weight: 600"
|
|
46
|
-
>
|
|
41
|
+
style="font-size: 14px; font-weight: 600">
|
|
47
42
|
{{ $t("auth.password") }}
|
|
48
43
|
</div>
|
|
49
44
|
<q-input
|
|
@@ -54,8 +49,7 @@
|
|
|
54
49
|
lazy-rules
|
|
55
50
|
borderless
|
|
56
51
|
dense
|
|
57
|
-
:input-style="{ fontSize: '14px', fontWeight: '600' }"
|
|
58
|
-
>
|
|
52
|
+
:input-style="{ fontSize: '14px', fontWeight: '600' }">
|
|
59
53
|
<template #prepend>
|
|
60
54
|
<q-icon :name="icons.ionLockClosedOutline" />
|
|
61
55
|
</template>
|
|
@@ -67,15 +61,13 @@
|
|
|
67
61
|
: icons.ionEyeOutline
|
|
68
62
|
"
|
|
69
63
|
class="cursor-pointer q-mr-sm"
|
|
70
|
-
@click="showPassword = !showPassword"
|
|
71
|
-
/>
|
|
64
|
+
@click="showPassword = !showPassword" />
|
|
72
65
|
</template>
|
|
73
66
|
</q-input>
|
|
74
67
|
</div>
|
|
75
68
|
<div
|
|
76
69
|
v-if="errorEmailMessage || errorPasswordMessage"
|
|
77
|
-
class="q-pl-sm text-red column justify-center error_input"
|
|
78
|
-
>
|
|
70
|
+
class="q-pl-sm text-red column justify-center error_input">
|
|
79
71
|
<div>{{ errorEmailMessage }}</div>
|
|
80
72
|
<div>{{ errorPasswordMessage }}</div>
|
|
81
73
|
</div>
|
|
@@ -89,8 +81,7 @@
|
|
|
89
81
|
:loading="loading"
|
|
90
82
|
type="submit"
|
|
91
83
|
class="full-width q-mt-lg"
|
|
92
|
-
:disable="isSubmitBtnDisabled()"
|
|
93
|
-
>
|
|
84
|
+
:disable="isSubmitBtnDisabled()">
|
|
94
85
|
<div style="font-weight: 600; font-size: 16px">
|
|
95
86
|
{{ $t("auth.login") }}
|
|
96
87
|
</div>
|
|
@@ -101,10 +92,44 @@
|
|
|
101
92
|
@click="forgottenPassword = true"
|
|
102
93
|
data-testid="ask-password-change-btn"
|
|
103
94
|
data-cy="forgot-password"
|
|
104
|
-
style="font-size: 14px; cursor: pointer; width: 350px"
|
|
105
|
-
>
|
|
95
|
+
style="font-size: 14px; cursor: pointer; width: 350px">
|
|
106
96
|
{{ $t("auth.forgottenPassword") }}
|
|
107
97
|
</div>
|
|
98
|
+
<div v-if="USE_SSO">
|
|
99
|
+
<div
|
|
100
|
+
style="
|
|
101
|
+
display: flex;
|
|
102
|
+
justify-content: space-between;
|
|
103
|
+
align-items: center;
|
|
104
|
+
">
|
|
105
|
+
<div
|
|
106
|
+
style="
|
|
107
|
+
width: 35%;
|
|
108
|
+
border: 1px solid #bcc3c7;
|
|
109
|
+
height: 1px;
|
|
110
|
+
"></div>
|
|
111
|
+
<div class="text-weight-bold">{{ $t("common.or") }}</div>
|
|
112
|
+
<div
|
|
113
|
+
style="
|
|
114
|
+
width: 35%;
|
|
115
|
+
border: 1px solid #bcc3c7;
|
|
116
|
+
height: 1px;
|
|
117
|
+
"></div>
|
|
118
|
+
</div>
|
|
119
|
+
<q-btn
|
|
120
|
+
data-cy="submit-sso-login"
|
|
121
|
+
:label="$t('auth.msalLogin')"
|
|
122
|
+
color="primary"
|
|
123
|
+
no-caps
|
|
124
|
+
unelevated
|
|
125
|
+
text-color="black"
|
|
126
|
+
:loading="msalLoading"
|
|
127
|
+
:disable="msalLoading || loading"
|
|
128
|
+
:icon="`img:${MicrosoftLogo}`"
|
|
129
|
+
class="full-width q-mt-lg"
|
|
130
|
+
@click="msalAuth"
|
|
131
|
+
outline />
|
|
132
|
+
</div>
|
|
108
133
|
</div>
|
|
109
134
|
</q-form>
|
|
110
135
|
</div>
|
|
@@ -117,20 +142,20 @@
|
|
|
117
142
|
transition-show="fade"
|
|
118
143
|
transition-hide="fade"
|
|
119
144
|
persistent
|
|
120
|
-
data-testid="ask-password-change-modal"
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
data-testid="ask-password-change-modal">
|
|
146
|
+
<send-email
|
|
147
|
+
@resetPassword="resetPassword"
|
|
148
|
+
@close="() => (forgottenPassword = false)" />
|
|
123
149
|
</q-dialog>
|
|
124
150
|
<q-dialog v-model="isReset" persistent>
|
|
125
151
|
<sowell-message
|
|
126
152
|
:emailResetPassword="emailResetPassword"
|
|
127
|
-
:
|
|
153
|
+
:sendEmailCode="sendEmailCode"
|
|
128
154
|
:loading="loading"
|
|
129
155
|
@retypeEmail="retypeEmail"
|
|
130
|
-
@close="() => isReset = false"
|
|
131
|
-
>
|
|
156
|
+
@close="() => (isReset = false)">
|
|
132
157
|
<q-btn
|
|
133
|
-
v-if="
|
|
158
|
+
v-if="sendEmailCode === 200 && isOtp"
|
|
134
159
|
data-testid="next-btn"
|
|
135
160
|
class="q-mt-md full-width"
|
|
136
161
|
unelevated
|
|
@@ -140,8 +165,7 @@
|
|
|
140
165
|
no-caps
|
|
141
166
|
:label="$t('auth.next')"
|
|
142
167
|
color="dark"
|
|
143
|
-
v-close-popup
|
|
144
|
-
/>
|
|
168
|
+
v-close-popup />
|
|
145
169
|
</sowell-message>
|
|
146
170
|
</q-dialog>
|
|
147
171
|
</div>
|
|
@@ -164,6 +188,8 @@ import * as packageInfo from "app/package.json"
|
|
|
164
188
|
import SendEmail from "../dialogs/SendEmail.vue"
|
|
165
189
|
import SowellMessage from "../dialogs/Message.vue"
|
|
166
190
|
import { useAuth } from "composables/auth"
|
|
191
|
+
import { AxiosError } from "axios"
|
|
192
|
+
import MicrosoftLogo from "../../assets/logo-microsoft.svg"
|
|
167
193
|
|
|
168
194
|
export default defineComponent({
|
|
169
195
|
name: "Auth",
|
|
@@ -180,11 +206,14 @@ export default defineComponent({
|
|
|
180
206
|
forgottenPassword,
|
|
181
207
|
emailResetPassword,
|
|
182
208
|
isReset,
|
|
183
|
-
|
|
209
|
+
sendEmailCode,
|
|
184
210
|
authState,
|
|
185
211
|
APP_SERVER_BASE_URL,
|
|
186
212
|
IS_OTP,
|
|
187
213
|
icons,
|
|
214
|
+
USE_SSO,
|
|
215
|
+
msalAuth,
|
|
216
|
+
msalLoading,
|
|
188
217
|
onSubmit,
|
|
189
218
|
retypeEmail,
|
|
190
219
|
isSubmitBtnDisabled,
|
|
@@ -206,20 +235,25 @@ export default defineComponent({
|
|
|
206
235
|
auth: {
|
|
207
236
|
email,
|
|
208
237
|
base: APP_SERVER_BASE_URL
|
|
209
|
-
}
|
|
238
|
+
}
|
|
210
239
|
}
|
|
211
240
|
try {
|
|
212
241
|
forgottenPassword.value = false
|
|
213
242
|
await authState.resetPassword(data).then(() => {
|
|
214
243
|
localStorage.setItem("emailResetPassword", email)
|
|
215
|
-
|
|
244
|
+
sendEmailCode.value = 200
|
|
216
245
|
isReset.value = true
|
|
217
246
|
})
|
|
218
|
-
} catch {
|
|
219
|
-
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if ((error as AxiosError).response?.status === 403) {
|
|
249
|
+
// NOTE: 403 is returned when the user is not allowed to reset the password
|
|
250
|
+
sendEmailCode.value = 403
|
|
251
|
+
} else {
|
|
252
|
+
sendEmailCode.value = 404
|
|
253
|
+
}
|
|
220
254
|
isReset.value = true
|
|
221
255
|
}
|
|
222
|
-
}
|
|
256
|
+
}
|
|
223
257
|
|
|
224
258
|
onMounted(() => {
|
|
225
259
|
appVersion.versionNumber = packageInfo.version
|
|
@@ -236,13 +270,17 @@ export default defineComponent({
|
|
|
236
270
|
forgottenPassword,
|
|
237
271
|
emailResetPassword,
|
|
238
272
|
isReset,
|
|
239
|
-
|
|
273
|
+
sendEmailCode,
|
|
240
274
|
icons,
|
|
241
275
|
appVersion,
|
|
242
276
|
isOtp,
|
|
243
277
|
goToOtpValidation,
|
|
244
278
|
isSubmitBtnDisabled,
|
|
245
279
|
retypeEmail,
|
|
280
|
+
msalLoading,
|
|
281
|
+
USE_SSO,
|
|
282
|
+
msalAuth,
|
|
283
|
+
MicrosoftLogo,
|
|
246
284
|
handleSubmit,
|
|
247
285
|
resetPassword
|
|
248
286
|
}
|
|
@@ -264,4 +302,3 @@ export default defineComponent({
|
|
|
264
302
|
display: none;
|
|
265
303
|
}
|
|
266
304
|
</style>
|
|
267
|
-
|
package/src/composables/auth.ts
CHANGED
|
@@ -61,7 +61,7 @@ export function useAuth() {
|
|
|
61
61
|
const showPassword = ref(false)
|
|
62
62
|
const forgottenPassword = ref(false)
|
|
63
63
|
const isReset = ref(false)
|
|
64
|
-
const
|
|
64
|
+
const sendEmailCode = ref(0)
|
|
65
65
|
const emailResetPassword = ref("")
|
|
66
66
|
const errorEmailMessage = ref("")
|
|
67
67
|
const errorPasswordMessage = ref("")
|
|
@@ -227,7 +227,7 @@ export function useAuth() {
|
|
|
227
227
|
forgottenPassword,
|
|
228
228
|
emailResetPassword,
|
|
229
229
|
isReset,
|
|
230
|
-
|
|
230
|
+
sendEmailCode,
|
|
231
231
|
authState,
|
|
232
232
|
APP_SERVER_BASE_URL,
|
|
233
233
|
WELCOME_TITLE,
|