@sowell/quasar-app-extension-auth 0.3.6 → 0.3.9

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