@sowell/quasar-app-extension-auth 0.2.6 → 0.2.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/README.md CHANGED
@@ -39,7 +39,7 @@ The default is http://localhost:3000, you must point it to your server base url
39
39
 
40
40
  6. Server route for authentication
41
41
 
42
- The default is /users/sign_in
42
+ The default is /auth
43
43
 
44
44
  7. Server route to reset password
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sowell/quasar-app-extension-auth",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
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",
@@ -145,6 +145,7 @@ export default defineComponent({
145
145
  },
146
146
  };
147
147
 
148
+
148
149
  post(AUTH_SERVER_RESET_PASSWORD_ROUTE, data)
149
150
  .then(() => {
150
151
  forgottenPassword.value = false;
@@ -41,7 +41,7 @@
41
41
  no-caps
42
42
  data-cy="send-new-password"
43
43
  class="full-width"
44
- :disable="canSubmit"
44
+ :disable="!canSubmit"
45
45
  />
46
46
  </div>
47
47
  </q-form>
@@ -52,50 +52,111 @@
52
52
 
53
53
  <script lang="ts">
54
54
  //@ts-ignore
55
- import { computed, defineComponent, ref } from "vue";
55
+ import { computed, defineComponent, ref, Ref, onMounted } from "vue";
56
56
  import { useQuasar } from "quasar";
57
57
  import { useI18n } from "vue-i18n";
58
- import { useRouter } from "vue-router";
59
- import { $api, $prompts } from "../../injects";
58
+ import { $api, $prompts, $router } from "../../injects";
59
+ import jwt from 'jwt-decode'
60
+ import { Buffer } from 'buffer'
61
+
62
+ interface DecodedToken { // FIXME: consider to move to its own file
63
+ sub: number,
64
+ email: string,
65
+ token: string
66
+ }
60
67
 
61
68
  export default defineComponent({
62
69
  name: "ResetPassword",
63
70
 
64
71
  setup() {
65
- const { patch } = $api();
72
+ const { patch, post } = $api();
66
73
  const {
74
+ AUTH_SERVER_SIGNING_ROUTE,
67
75
  AUTH_SERVER_UPDATE_PASSWORD_ROUTE,
68
- LOCAL_SUCCESS_REDIRECTION_ROUTE,
76
+ LOCAL_LOGIN_ROUTE,
69
77
  } = $prompts();
70
78
  const $q = useQuasar();
71
- const router = useRouter();
79
+ const router = $router()
80
+ const $route = router.currentRoute.value
72
81
  const password = ref("");
73
82
  const loading = ref(false);
74
83
  const { t } = useI18n();
75
84
 
76
- const canSubmit = computed(() => password.value.length < 6);
85
+ const token = ref("")
86
+
87
+ const decodedToken = computed(() => {
88
+ if (!token.value) return null
89
+ return jwt(token.value) as DecodedToken
90
+ }) as Ref<DecodedToken | null>
91
+
92
+ const canSubmit = computed(() => {
93
+ return decodedToken.value !== null && password.value.length >= 6
94
+ });
77
95
 
78
96
  const validations = {
79
97
  passwordRules: [
80
98
  (val: string) => !!val || t("auth.passwordPresenceError"),
81
- (val: string) => val.length >= 6 || t("auth.passwordLengthError"),
99
+ (val: string) => val.length >= 6 || t("auth.passwordLengthError")
100
+ ],
101
+ passwordConfirmationRules: [
102
+ (val: string) =>
103
+ val === password.value || t("auth.newPasswordConfirmationFailed"),
104
+ (val: string) => !!val || t("auth.resetPasswordPresenceError"),
105
+ (val: string) => val.length >= 6 || t("auth.resetPasswordLengthError"),
82
106
  ],
83
107
  };
84
108
 
109
+ const decodeKey = (key: string) => {
110
+ try {
111
+ const decodedKey = Buffer.from(key, "base64").toString("utf-8").split(',')
112
+ if (decodedKey.length !== 2) {
113
+ throw 'Invalid encoded key'
114
+ }
115
+ console.log('decodedKey', decodedKey)
116
+ const email = decodedKey[0].replace('{', '').split(':')[1]
117
+ const tmpToken = decodedKey[1].replace('}', '').split(':')[1]
118
+ return {
119
+ decoded: true,
120
+ email,
121
+ tmpToken
122
+ }
123
+ } catch (err) {
124
+ console.log('decodeKey err', err)
125
+ return {
126
+ decoded: false
127
+ }
128
+ }
129
+ }
130
+
85
131
  const onSubmit = () => {
86
- const data = {
87
- password: password.value,
88
- };
89
- patch(AUTH_SERVER_UPDATE_PASSWORD_ROUTE, data)
90
- .then(() => {
132
+ const updatePasswordPayload = {
133
+ data: {
134
+ type: "users",
135
+ id: decodedToken.value.sub,
136
+ attributes:
137
+ {
138
+ password: password.value
139
+ }
140
+ }
141
+ }
142
+ const updatePasswordHeaders = {
143
+ headers: {
144
+ 'Authorization': `Bearer ${token.value}`
145
+ }
146
+ }
147
+
148
+ patch(
149
+ AUTH_SERVER_UPDATE_PASSWORD_ROUTE.replace(':userId', String(decodedToken.value.sub)),
150
+ updatePasswordPayload,
151
+ updatePasswordHeaders
152
+ ).then(() => {
91
153
  $q.notify({
92
154
  message: t("auth.passwordRecoverySuccess"),
93
155
  color: "positive",
94
156
  position: "top",
95
157
  });
96
- router.push(LOCAL_SUCCESS_REDIRECTION_ROUTE);
97
- })
98
- .catch(() => {
158
+ router.push(LOCAL_LOGIN_ROUTE);
159
+ }).catch(() => {
99
160
  $q.notify({
100
161
  message: t("auth.passwordRecoveryFailed"),
101
162
  color: "negative",
@@ -104,6 +165,49 @@ export default defineComponent({
104
165
  });
105
166
  };
106
167
 
168
+ onMounted(() => {
169
+ let key = $route.query.key as string
170
+ const { decoded, email, tmpToken } = decodeKey(key)
171
+
172
+ if (!decoded) {
173
+ return $q.notify({
174
+ message: t("auth.passwordRecoveryInvalidLink"),
175
+ color: "negative",
176
+ position: "top",
177
+ })
178
+ }
179
+
180
+ const tmpAuthPayload = {
181
+ auth: {
182
+ email: email,
183
+ token: tmpToken
184
+ }
185
+ }
186
+
187
+ post(AUTH_SERVER_SIGNING_ROUTE, tmpAuthPayload)
188
+ .then((response) => {
189
+ token.value = response.data.jwt
190
+ if (!token.value) throw 'Error reading the temporary token'
191
+ })
192
+ .catch((error) => {
193
+ if (error.response) {
194
+ // Request made and server responded
195
+ if (error.response.status === 404) {
196
+ return $q.notify({
197
+ message: t("auth.passwordRecoveryExpiredLink"),
198
+ color: "negative",
199
+ position: "top",
200
+ });
201
+ }
202
+ }
203
+ return $q.notify({
204
+ message: t("auth.passwordRecoveryFailed"),
205
+ color: "negative",
206
+ position: "top",
207
+ });
208
+ });
209
+ })
210
+
107
211
  return {
108
212
  password,
109
213
  validations,
package/src/prompts.js CHANGED
@@ -27,7 +27,7 @@ module.exports = function () {
27
27
  type: "input",
28
28
  required: true,
29
29
  message: "Route to update the password (page)",
30
- default: "/reset_password",
30
+ default: "/ResetPassword/",
31
31
  },
32
32
  {
33
33
  name: "AUTH_SERVER_BASE_URL",
@@ -41,7 +41,7 @@ module.exports = function () {
41
41
  type: "input",
42
42
  required: true,
43
43
  message: "API endpoint for signin (without host)",
44
- default: "/users/sign_in",
44
+ default: "/auth",
45
45
  },
46
46
  {
47
47
  name: "AUTH_SERVER_RESET_PASSWORD_ROUTE",