@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.
@@ -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 :passwordUpdated="passwordUpdated" @goToLoginPage="goToLoginPage"/>
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 { computed, defineComponent, ref, Ref, onMounted } from "vue";
74
+ import { defineComponent } from "vue";
72
75
  import SowellMessage from "../dialogs/Message.vue";
73
- import { useQuasar } from "quasar";
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
- AUTH_SERVER_SIGNING_ROUTE,
97
- AUTH_SERVER_UPDATE_PASSWORD_ROUTE,
83
+ password,
84
+ loading,
85
+ passwordUpdated,
86
+ validations,
98
87
  LOCAL_LOGIN_ROUTE,
99
- } = $prompts();
100
- const $q = useQuasar();
101
- const router = $router()
102
- const $route = router.currentRoute.value
103
- const password = ref("");
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
- ionLockClosedOutline,
274
- goToLoginPage
100
+ validations,
101
+ onSubmit,
102
+ goToLoginPage,
103
+ icons
275
104
  };
276
105
  },
277
106
  });