@sowell/quasar-app-extension-auth 0.3.6 → 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.
@@ -1,68 +1,89 @@
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
+ 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
- <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') }}
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
- <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>
72
+ </q-form>
73
+ </div>
62
74
  </div>
63
75
  </div>
64
- <div class="column col bgBlue justify-center content-center">
65
- <img src="../../assets/SowellWhite.svg" class="logoWhite"/>
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" />
66
87
  </div>
67
88
  </div>
68
89
  <div>
@@ -74,14 +95,13 @@
74
95
  transition-hide="fade"
75
96
  persistent
76
97
  >
77
- <send-email @resetPassword="resetPassword" />
98
+ <web-send-email @resetPassword="resetPassword" />
78
99
  </q-dialog>
79
- <q-dialog v-model="isReset" persistent>
80
- <sowell-message
81
- :emailResetPassword="emailResetPassword"
82
- :sendEmailSuccess="sendEmailSuccess"
83
- :loading="loading"
84
- @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"
85
105
  />
86
106
  </q-dialog>
87
107
  </div>
@@ -90,210 +110,130 @@
90
110
 
91
111
  <script lang="ts">
92
112
  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";
113
+ import { defineComponent, ref, computed } from "vue";
114
+ import { useAuthState } from "../../injects";
96
115
  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";
116
+ import SwInfoDialog from "../dialogs/sw-info-dialog.vue";
117
+ import WebSendEmail from "../dialogs/WebSendEmail.vue";
118
+
119
+ import { useAuth } from "composables/auth";
109
120
 
110
121
  interface HeadersInterface {
111
122
  headers: {
112
- "x-requested-roles"?: string
113
- }
123
+ "x-requested-roles"?: string;
124
+ };
114
125
  }
115
126
  export default defineComponent({
116
- name: 'Auth',
117
- components: { SendEmail, SowellMessage },
127
+ name: "Auth",
128
+ components: { WebSendEmail, SwInfoDialog },
118
129
  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
130
  const { t } = useI18n();
131
+ const authState = useAuthState();
141
132
 
142
- onMounted(() => {
143
- if (getters["token/getRaw"]) {
144
- replace(LOCAL_SUCCESS_REDIRECTION_ROUTE);
145
- }
146
- });
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();
147
150
 
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")],
151
+ const isNotification = ref(false);
152
+ const infoDialog = ref({
153
+ title: "",
154
+ content: "",
155
+ image: "",
154
156
  });
155
157
 
156
- const resetPassword = (email: string) => {
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) => {
157
169
  const data = {
158
170
  auth: {
159
171
  email,
160
172
  base: APP_SERVER_BASE_URL,
161
173
  },
162
174
  };
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
- });
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
+ }
247
193
  };
248
194
 
249
- const submitBtnDisabled = computed(() => !(
250
- email.value &&
251
- isEmail(email.value) &&
252
- password.value &&
253
- password.value.length > 5
254
- )
255
- )
256
195
  return {
257
196
  email,
197
+ infoDialog,
258
198
  password,
259
199
  loading,
260
200
  showPassword,
261
201
  validations,
262
202
  submitBtnDisabled,
263
- onSubmit,
264
203
  forgottenPassword,
265
204
  emailResetPassword,
205
+ isNotification,
206
+ isManager,
207
+ WELCOME_SUBTITLE,
208
+ WELCOME_TITLE,
209
+ isSubmitBtnDisabled,
266
210
  resetPassword,
267
- isReset,
268
211
  retypeEmail,
269
- sendEmailSuccess,
270
- ionMailOutline,
271
- ionLockClosedOutline,
272
- ionEyeSharp,
273
- ionEyeOffSharp,
274
- }
212
+ onSubmit,
213
+ icons,
214
+ };
275
215
  },
276
- })
216
+ });
277
217
  </script>
278
218
 
279
219
  <style scoped>
280
220
  .bgWhite {
281
- background: #FFFFFF
221
+ background: #ffffff;
282
222
  }
283
223
  .bgBlue {
284
- background: var(--q-primary)
224
+ background: var(--q-primary);
285
225
  }
286
226
  .lightenDark {
287
- color: rgba(0, 0, 0, 0.24)
227
+ color: rgba(0, 0, 0, 0.24);
288
228
  }
289
229
  .title {
290
230
  margin: 0px 0px 16px 0px;
291
231
  }
292
232
  .subtitle {
293
- margin-bottom: 104px
233
+ margin-bottom: 80px;
294
234
  }
295
235
  .logoWhite {
296
- width: 30%
236
+ width: 30%;
297
237
  }
298
238
  .submitBtn {
299
239
  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>