@sowell/quasar-app-extension-auth 0.5.0 → 0.5.2

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/.eslintrc.js CHANGED
@@ -2,29 +2,26 @@ module.exports = {
2
2
  env: {
3
3
  browser: true,
4
4
  commonjs: true,
5
- es2021: true,
5
+ es2021: true
6
6
  },
7
7
  extends: [
8
- "eslint:recommended",
9
- "plugin:vue/vue3-strongly-recommended",
10
- "prettier",
8
+ 'eslint:recommended',
9
+ 'plugin:vue/vue3-strongly-recommended',
10
+ 'prettier'
11
11
  ],
12
12
  parserOptions: {
13
- parser: "@typescript-eslint/parser",
13
+ parser: '@typescript-eslint/parser',
14
14
  ecmaVersion: 2018,
15
- sourceType: "module",
15
+ sourceType: 'module'
16
16
  },
17
- plugins: ["vue"],
17
+ plugins: ['vue'],
18
18
  rules: {
19
- "comma-dangle": ["error", "only-multiline"],
20
- "space-before-function-paren": [
21
- "error",
22
- { anonymous: "always", named: "never", asyncArrow: "always" },
19
+ 'comma-dangle': ['error', 'only-multiline'],
20
+ 'space-before-function-paren': [
21
+ 'error',
22
+ { anonymous: 'always', named: 'never', asyncArrow: 'always' }
23
23
  ],
24
- semi: "off",
25
- "no-unreachable": "off",
26
- "no-unused-vars": "off",
27
- "@typescript-eslint/no-unsafe-member-access": "off",
28
- "@typescript-eslint/no-explicit-any": "off",
29
- },
24
+ semi: 'off',
25
+ 'no-unreachable': 'off'
26
+ }
30
27
  };
@@ -15,7 +15,7 @@ jobs:
15
15
  - name: Nodejs
16
16
  uses: actions/setup-node@v2
17
17
  with:
18
- node-version: "18"
18
+ node-version: "16"
19
19
  cache: yarn
20
20
  registry-url: https://registry.npmjs.org
21
21
  - name: publish
@@ -0,0 +1,19 @@
1
+ name: Remove stale branches
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ - cron: "0 0 * * *" # Everday at midnight
7
+
8
+ jobs:
9
+ remove-stale-branches:
10
+ name: Remove Stale Branches
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: fpicalausa/remove-stale-branches@v1.6.0
14
+ with:
15
+ dry-run: false # Check out the console output before setting this to false
16
+ days-before-branch-stale: 180
17
+ days-before-branch-delete: 0
18
+ operations-per-run: 50
19
+ exempt-authors-regex: "^dependabot"
package/README.md CHANGED
@@ -53,28 +53,6 @@ The default is /users/passwords
53
53
 
54
54
  The default is Bearer but you can change it according to your needs
55
55
 
56
- 10. Vuex mutation to set token
57
-
58
- The default is auth/setToken in the auth module.
59
- It can be changed from the moment it takes the token in parameter
60
-
61
- 11. Vuex mutation to clear token and all user state
62
-
63
- The default is auth/clearToken in the auth module but can be changed
64
-
65
- 12. Vuex mutation to set user information when resetting password (email or phone number)
66
-
67
- The default is auth/setInfosUser in auth module.
68
- It takes email or phone number, can be changed
69
-
70
- 13. Vuex getter to return token
71
-
72
- The default is auth/getToken and return token, can be changed.
73
-
74
- 14. Vuex getter to return user information
75
-
76
- The default is auth/getInfosUser and return email or phone number
77
-
78
56
  # Uninstall
79
57
 
80
58
  ```bash
@@ -173,8 +151,11 @@ Launch test E2E with Continuous integration mode and cypress test all file in di
173
151
  ```
174
152
 
175
153
  # netlify-plugin-cypress
154
+
176
155
  [![CircleCI](https://circleci.com/gh/cypress-io/netlify-plugin-cypress/tree/master.svg?style=svg&circle-token=9cbb587a5a0ae4ce28b011dd03d10d66de906708)](https://circleci.com/gh/cypress-io/netlify-plugin-cypress/tree/master) [![renovate-app badge][renovate-badge]][renovate-app] [![netlify-plugin-cypress](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/ixroqc/master&style=flat&logo=cypress)](https://dashboard.cypress.io/projects/ixroqc/runs) [![Netlify Status](https://api.netlify.com/api/v1/badges/76892baf-2ad8-4642-b283-f2135963ff51/deploy-status)](https://app.netlify.com/sites/sad-lumiere-6a00a5/deploys)
156
+
177
157
  > Runs Cypress end-to-end tests on Netlify Build
158
+
178
159
  ## Install and use
179
160
 
180
161
  You can install this plugin in the Netlify UI from this [direct in-app installation link](https://app.netlify.com/plugins/netlify-plugin-cypress/install) or from the [Plugins directory](https://app.netlify.com/plugins).
@@ -189,8 +170,7 @@ yarn add -D netlify-plugin-cypress
189
170
 
190
171
  And then add the plugin's name to the list of build plugins in `netlify.toml` file as shown in the examples below.
191
172
 
192
- *note:* this plugin assumes you have already installed Cypress as a dev NPM dependency.
193
-
173
+ _note:_ this plugin assumes you have already installed Cypress as a dev NPM dependency.
194
174
 
195
175
  ## How does it work
196
176
 
@@ -488,9 +468,10 @@ public/
488
468
  The `public` folder is served automatically and the following test successfully visits both the root and the `about.html` pages:
489
469
 
490
470
  ```js
491
- cy.visit('/')
492
- cy.visit('/pages/about') // visits the about.html
471
+ cy.visit("/");
472
+ cy.visit("/pages/about"); // visits the about.html
493
473
  ```
474
+
494
475
  **Warning:** be careful with verbose logging, since it can print all environment variables passed to the plugin, including tokens, API keys, and other secrets.
495
476
 
496
477
  Error: error:0308010C:digital envelope routines::unsupported
@@ -502,4 +483,4 @@ If you appreciate the work that went into this App Extension, make donation to [
502
483
 
503
484
  # License
504
485
 
505
- MIT (c) Sowell
486
+ MIT (c) Sowell
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sowell/quasar-app-extension-auth",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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",
@@ -10,7 +10,7 @@
10
10
  "dep": "cd dev && yarn",
11
11
  "test:link": "cd dev && yarn test:link",
12
12
  "test:browser": "cd dev && yarn test:browser",
13
- "test": "cd dev && yarn ci"
13
+ "test": "cd dev && yarn test"
14
14
  },
15
15
  "keywords": [],
16
16
  "author": "SoWell SAS",
@@ -21,7 +21,7 @@
21
21
  "yarn": ">= 1.6.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@quasar/cli": "^1.2.2",
24
+ "@quasar/cli": "^2.2.3",
25
25
  "@quasar/quasar-app-extension-testing-e2e-cypress": "^3.1.0",
26
26
  "@types/node": "^16.9.1",
27
27
  "@types/validator": "^13.6.3",
@@ -32,7 +32,8 @@
32
32
  "eslint-plugin-vue": "^7.0.0",
33
33
  "jwt-decode": "^3.1.2",
34
34
  "quasar": "^2.6.2",
35
- "typescript": "^5.3.3"
35
+ "vue": "3.4.21",
36
+ "typescript": "^4.4.2"
36
37
  },
37
38
  "directories": {
38
39
  "test": "test"
@@ -40,13 +41,11 @@
40
41
  "dependencies": {
41
42
  "@capacitor/core": "^4.6.2",
42
43
  "@quasar/extras": "^1.13.4",
43
- "@typescript-eslint/parser": "^6.19.1",
44
44
  "axios": "^0.21.1",
45
45
  "buffer": "^6.0.3",
46
46
  "pinia": "^2.0.12",
47
47
  "qs": "^6.10.1",
48
48
  "validator": "^13.6.0",
49
- "vue-router": "^4.0.0",
50
- "vuex": "4.0"
49
+ "vue-router": "^4.0.0"
51
50
  }
52
51
  }
@@ -2,6 +2,7 @@
2
2
  import prompts from "app/quasar.extensions.json";
3
3
  import { boot } from "quasar/wrappers";
4
4
  import { BootInterface } from "../interfaces";
5
+ import { LocalStorage } from "quasar";
5
6
 
6
7
  export default boot(({ app, router }: BootInterface) => {
7
8
  const {
package/src/boot/store.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  //@ts-ignore
2
2
  import { boot } from "quasar/wrappers";
3
3
  import { BootInterface } from "../interfaces";
4
- import tokenModule from "../store";
5
4
 
6
5
  export default boot(({ app, store }: BootInterface) => {
7
6
  // Register store module
8
- store.registerModule("token", tokenModule);
9
7
  app.provide("$store", store);
10
8
  });
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <q-card style="max-width: 343px; border-radius: 10px; background: #f4f5f6">
2
+ <q-card style="max-width: 343px; border-radius: 10px; background: #f4f5f6" data-testid="feedback-dialog">
3
3
  <q-card-section class="text-center q-mt-lg">
4
4
  <img
5
5
  v-if="emailSended"
@@ -23,11 +23,13 @@
23
23
  class="text-subtitle1 q-mt-sm q-mb-md text-center text-dark"
24
24
  style="font-size: 24px; font-weight: 600"
25
25
  data-cy="resetErrorMessage"
26
+ data-testid="header-dialog"
26
27
  >
27
28
  {{ messageTitle }}
28
29
  </div>
29
30
  <div
30
31
  data-cy="resetMessage"
32
+ data-testid="message-dialog"
31
33
  class="text-subtitle1 q-mt-sm text-center"
32
34
  style="font-size: 16px; font-weight: 400"
33
35
  >
@@ -57,6 +59,7 @@
57
59
  />
58
60
  <slot>
59
61
  <q-btn
62
+ data-testid="close-btn"
60
63
  class="q-mt-md full-width"
61
64
  unelevated
62
65
  style="background: #fff"
@@ -2,6 +2,7 @@
2
2
  <q-card
3
3
  class="row justify-center full-height q-pl-sm q-pr-sm"
4
4
  style="background: #f4f5f6"
5
+ data-testid="ask-password-change-form"
5
6
  >
6
7
  <q-page class="column" style="max-width: 447px">
7
8
  <q-card-section>
@@ -40,6 +41,7 @@
40
41
  </div>
41
42
  </div>
42
43
  <q-input
44
+ data-testid="email-input"
43
45
  v-model="email"
44
46
  dense
45
47
  borderless
@@ -56,6 +58,7 @@
56
58
  <q-space class="mobile" />
57
59
  <q-card-actions class="q-ml-lg q-mr-lg q-mb-lg row justify-center">
58
60
  <q-btn
61
+ data-testid="submit-btn"
59
62
  color="primary"
60
63
  :icon="icons.ionPaperPlaneOutline"
61
64
  style="max-width: 330px"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <q-card>
2
+ <q-card data-testid="ask-password-change-form">
3
3
  <q-page class="row bg-white">
4
4
  <div class="col-6 q-pa-xl row justify-center center">
5
5
  <div class="left-side full-width full-height">
@@ -22,6 +22,7 @@
22
22
  {{ $t("auth.email") }}
23
23
  </div>
24
24
  <q-input
25
+ data-testid="email-input"
25
26
  v-model="email"
26
27
  dense
27
28
  outlined
@@ -31,6 +32,7 @@
31
32
  />
32
33
  <div class="q-mt-lg row justify-between items-center">
33
34
  <q-btn
35
+ data-testid="submit-btn"
34
36
  color="primary"
35
37
  :icon-right="icons.ionPaperPlaneOutline"
36
38
  style="max-width: 330px"
@@ -46,6 +48,7 @@
46
48
  />
47
49
 
48
50
  <q-btn
51
+ data-testid="back-btn"
49
52
  color="primary"
50
53
  style="max-width: 330px"
51
54
  data-cy="close_send_email"
@@ -124,8 +127,8 @@ export default defineComponent({
124
127
  .bg-image {
125
128
  display: none;
126
129
  }
127
- .center{
130
+ .center {
128
131
  width: 100%;
129
132
  }
130
133
  }
131
- </style>
134
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <q-card>
2
+ <q-card data-testid="feedback-dialog">
3
3
  <q-card-section class="top">
4
4
  <div class="full-width button-close row justify-end">
5
5
  <q-btn
@@ -14,15 +14,21 @@
14
14
  />
15
15
  </div>
16
16
  <div class="row justify-center">
17
- <img :src="imageSVG" />
17
+ <img :src="image" />
18
18
  </div>
19
19
  </q-card-section>
20
20
 
21
21
  <q-card-section class="content q-pl-lg q-pr-lg">
22
- <h5 class="q-mt-sm q-mb-md text-center text-dark">
22
+ <h5
23
+ class="q-mt-sm q-mb-md text-center text-dark"
24
+ data-testid="header-dialog"
25
+ >
23
26
  {{ title }}
24
27
  </h5>
25
- <div class="text-subtitle1 q-mt-sm text-center text-dark">
28
+ <div
29
+ class="text-subtitle1 q-mt-sm text-center text-dark"
30
+ data-testid="message-dialog"
31
+ >
26
32
  {{ content }}
27
33
  </div>
28
34
  </q-card-section>
@@ -30,6 +36,7 @@
30
36
  <div>
31
37
  <slot>
32
38
  <q-btn
39
+ data-testid="close-btn"
33
40
  class="bg-white submitBtn"
34
41
  unelevated
35
42
  outline
@@ -52,7 +59,7 @@ import emailVerification from "../../assets/Email-sent.svg";
52
59
  import { ionCloseOutline } from "@quasar/extras/ionicons-v5";
53
60
 
54
61
  export default defineComponent({
55
- name: "SwInfoDialog",
62
+ name: "swInfoDialog",
56
63
  props: {
57
64
  title: { type: String, required: true },
58
65
  content: { type: String, required: true },
@@ -60,9 +67,9 @@ export default defineComponent({
60
67
  passwordUpdated: { type: Boolean },
61
68
  isOtp: { type: Boolean, default: false, required: false },
62
69
  },
63
- emits: ["goToLoginPage"],
70
+ emit: ["goToLoginPage"],
64
71
  setup(props: any) {
65
- const imageSVG = computed(() => {
72
+ const image = computed(() => {
66
73
  switch (props.image) {
67
74
  case "userNotFound":
68
75
  return userNotFound;
@@ -72,11 +79,9 @@ export default defineComponent({
72
79
 
73
80
  case "emailVerification":
74
81
  return emailVerification;
75
- default:
76
- return "";
77
82
  }
78
83
  });
79
- return { imageSVG, icons: { ionCloseOutline } };
84
+ return { image, icons: { ionCloseOutline } };
80
85
  },
81
86
  });
82
87
  </script>
@@ -99,7 +99,7 @@
99
99
  :title="infoDialog.title"
100
100
  :content="infoDialog.content"
101
101
  :image="infoDialog.image"
102
- :is-otp="true"
102
+ :isOtp="true"
103
103
  >
104
104
  <q-btn
105
105
  v-if="requestedOtp"
@@ -128,6 +128,11 @@ import WebSendEmail from "../dialogs/WebSendEmail.vue";
128
128
 
129
129
  import { useAuth } from "composables/auth";
130
130
 
131
+ interface HeadersInterface {
132
+ headers: {
133
+ "x-requested-roles"?: string;
134
+ };
135
+ }
131
136
  export default defineComponent({
132
137
  name: "Auth",
133
138
  components: { WebSendEmail, SwInfoDialog },
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <q-layout>
3
- <q-page class="column justify-center items-center">
2
+ <q-layout class="column justify-end items-center q-pb-lg">
3
+ <div>
4
4
  <div class="q-pa-lg">
5
5
  <div class="column justify-center items-center">
6
6
  <div class="row justify-center">
@@ -98,6 +98,7 @@
98
98
  class="q-mb-lg q-mt-xl text-primary"
99
99
  @click="forgottenPassword = true"
100
100
  data-cy="forgot-password"
101
+ data-testid="ask-password-change-btn"
101
102
  style="font-size: 16px; font-weight: 500; cursor: pointer"
102
103
  >
103
104
  {{ $t("auth.forgottenPassword") }}
@@ -143,6 +144,7 @@
143
144
  transition-show="fade"
144
145
  transition-hide="fade"
145
146
  persistent
147
+ data-testid="ask-password-change-modal"
146
148
  >
147
149
  <send-email @resetPassword="resetPassword" />
148
150
  </q-dialog>
@@ -155,7 +157,7 @@
155
157
  />
156
158
  </q-dialog>
157
159
  </div>
158
- </q-page>
160
+ </div>
159
161
  <q-footer class="footer">
160
162
  <q-toolbar>
161
163
  <q-toolbar-title>
@@ -262,3 +264,4 @@ export default defineComponent({
262
264
  background: transparent;
263
265
  }
264
266
  </style>
267
+
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <q-layout>
3
- <q-page class="column justify-end items-center">
2
+ <q-layout class="column justify-end items-center q-pb-lg">
3
+ <div>
4
4
  <div class="column">
5
5
  <div class="column justify-center" style="height: 35vh">
6
6
  <div class="row justify-center">
@@ -99,6 +99,7 @@
99
99
  <div
100
100
  class="q-mb-xl q-mt-lg text-primary text-center"
101
101
  @click="forgottenPassword = true"
102
+ data-testid="ask-password-change-btn"
102
103
  data-cy="forgot-password"
103
104
  style="font-size: 14px; cursor: pointer; width: 350px"
104
105
  >
@@ -116,6 +117,7 @@
116
117
  transition-show="fade"
117
118
  transition-hide="fade"
118
119
  persistent
120
+ data-testid="ask-password-change-modal"
119
121
  >
120
122
  <send-email @resetPassword="resetPassword" />
121
123
  </q-dialog>
@@ -127,7 +129,8 @@
127
129
  @retypeEmail="retypeEmail"
128
130
  >
129
131
  <q-btn
130
- v-if="(sendEmailSuccess && isOtp)"
132
+ v-if="sendEmailSuccess && isOtp"
133
+ data-testid="next-btn"
131
134
  class="q-mt-md full-width"
132
135
  unelevated
133
136
  style="background: #fff"
@@ -141,7 +144,7 @@
141
144
  </sowell-message>
142
145
  </q-dialog>
143
146
  </div>
144
- </q-page>
147
+ </div>
145
148
  <q-footer class="footer">
146
149
  <q-toolbar>
147
150
  <q-toolbar-title>
@@ -188,15 +191,15 @@ export default defineComponent({
188
191
  } = useAuth();
189
192
 
190
193
  const handleSubmit = () => {
191
- onSubmit()
192
- }
194
+ onSubmit();
195
+ };
193
196
 
194
197
  const appVersion = reactive({
195
198
  versionNumber: "",
196
199
  });
197
200
 
198
- const isOtp = computed(() => IS_OTP.toLowerCase() === "y")
199
-
201
+ const isOtp = computed(() => IS_OTP.toLowerCase() === "y");
202
+
200
203
  const resetPassword = async (email: string) => {
201
204
  const data = {
202
205
  auth: {
@@ -260,3 +263,4 @@ div.q-field__messages {
260
263
  display: none;
261
264
  }
262
265
  </style>
266
+
@@ -1,18 +1,15 @@
1
1
  <template>
2
- <q-layout>
3
- <q-page class="q-pa-md row justify-center">
2
+ <q-layout class="q-pa-md row justify-center">
3
+ <div>
4
4
  <div>
5
5
  <div class="q-mt-xl">
6
6
  <img
7
7
  src="../../assets/Sowell-logo.svg"
8
- class="q-mb-sm q-mr-md"
8
+ class="q-mb-sm"
9
9
  style="width: 190px"
10
10
  />
11
11
  </div>
12
- <div
13
- class="column justify-center full-height"
14
- style="max-width: 550px; margin-top: -90px"
15
- >
12
+ <div class="column justify-center full-height" style="max-width: 550px">
16
13
  <div></div>
17
14
  <div
18
15
  class="text-subtitle1 q-mt-lg"
@@ -27,12 +24,17 @@
27
24
  >
28
25
  {{ $t("auth.subtitleOtpValidation") }}
29
26
  </div>
30
- <q-form class="column form" @submit="onSubmit">
27
+ <q-form
28
+ class="column form"
29
+ data-testid="otp-validation-form"
30
+ @submit="onSubmit"
31
+ >
31
32
  <div>
32
33
  <div class="q-mb-sm" style="font-size: 14px; font-weight: 600">
33
34
  {{ $t("auth.validationCode") }}
34
35
  </div>
35
36
  <q-input
37
+ data-testid="otp-input"
36
38
  v-model="otp"
37
39
  dense
38
40
  :borderless="isReporterUi"
@@ -46,6 +48,7 @@
46
48
  <q-space />
47
49
  <div class="row justify-between">
48
50
  <q-btn
51
+ data-testid="next-btn"
49
52
  :label="$t('auth.next')"
50
53
  color="primary"
51
54
  :loading="loading"
@@ -54,12 +57,11 @@
54
57
  class="submitBtn"
55
58
  data-cy="send-new-otp"
56
59
  :disable="canSubmit"
57
- @click="onSubmit"
58
60
  />
59
61
  <q-btn
62
+ data-testid="back-btn"
60
63
  :label="$t('auth.login')"
61
64
  text-color="primary"
62
- type="submit"
63
65
  no-caps
64
66
  data-cy="login-page"
65
67
  @click="() => router.push(LOCAL_LOGIN_ROUTE)"
@@ -68,7 +70,7 @@
68
70
  </q-form>
69
71
  </div>
70
72
  </div>
71
- </q-page>
73
+ </div>
72
74
  </q-layout>
73
75
  </template>
74
76
 
@@ -175,3 +177,4 @@ export default defineComponent({
175
177
  width: 254px;
176
178
  }
177
179
  </style>
180
+
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <q-layout>
3
- <q-page class="q-pa-md row justify-center full-height">
2
+ <q-layout class="q-pa-md row justify-center full-height">
3
+ <div>
4
4
  <div style="max-width: 342px">
5
5
  <div>
6
6
  <q-btn
@@ -24,12 +24,17 @@
24
24
  >
25
25
  {{ $t("auth.recommendPassword") }}
26
26
  </div>
27
- <q-form class="column form" @submit="onSubmit">
27
+ <q-form
28
+ class="column form"
29
+ @submit="onSubmit"
30
+ data-testid="reset-password-form"
31
+ >
28
32
  <div>
29
33
  <div class="q-mb-sm" style="font-size: 14px; font-weight: 600">
30
34
  {{ $t("auth.newPassword") }}
31
35
  </div>
32
36
  <q-input
37
+ data-testid="password-input"
33
38
  id="password"
34
39
  v-model="password"
35
40
  data-cy="reset-password"
@@ -47,6 +52,7 @@
47
52
  <q-space class="mobile" />
48
53
  <div>
49
54
  <q-btn
55
+ data-testid="submit-btn"
50
56
  :label="$t('common.register')"
51
57
  color="primary"
52
58
  :loading="loading"
@@ -65,7 +71,7 @@
65
71
  @goToLoginPage="goToLoginPage"
66
72
  />
67
73
  </q-dialog>
68
- </q-page>
74
+ </div>
69
75
  </q-layout>
70
76
  </template>
71
77
 
@@ -100,7 +106,7 @@ export default defineComponent({
100
106
  validations,
101
107
  onSubmit,
102
108
  goToLoginPage,
103
- icons
109
+ icons,
104
110
  };
105
111
  },
106
112
  });
@@ -105,6 +105,7 @@
105
105
  />
106
106
  <div
107
107
  class="cursor-pointer text-primary text-subtitle2"
108
+ data-testid="ask-password-change-btn"
108
109
  data-cy="forgot-password"
109
110
  @click="forgottenPassword = true"
110
111
  >
@@ -140,6 +141,7 @@
140
141
  transition-show="fade"
141
142
  transition-hide="fade"
142
143
  persistent
144
+ data-testid="ask-password-change-modal"
143
145
  >
144
146
  <web-send-email @resetPassword="resetPassword" />
145
147
  </q-dialog>
@@ -151,14 +153,15 @@
151
153
  :isOtp="isOtp"
152
154
  >
153
155
  <q-btn
156
+ :data-testid="infoDialog.canGoNext ? 'next-btn' : 'close-btn'"
154
157
  v-if="isOtp"
155
158
  class="bg-white submitBtn"
156
159
  unelevated
157
160
  outline
158
161
  no-caps
159
- :label="$t('auth.next')"
162
+ :label="infoDialog.canGoNext ? $t('auth.next') : $t('auth.close')"
160
163
  color="primary"
161
- @click="goToOtpValidation"
164
+ @click="handleInfoDialog"
162
165
  v-close-popup
163
166
  />
164
167
  </sw-info-dialog>
@@ -245,6 +248,7 @@ export default defineComponent({
245
248
  await authState.resetPassword(data).then(() => {
246
249
  localStorage.setItem("emailResetPassword", email);
247
250
  infoDialog.value = {
251
+ canGoNext: true,
248
252
  title: t("auth.mailVerificationTitle"),
249
253
  content:
250
254
  IS_OTP.toLowerCase() === "y"
@@ -259,11 +263,12 @@ export default defineComponent({
259
263
  isNotification.value = false;
260
264
 
261
265
  infoDialog.value = {
266
+ canGoNext: false,
262
267
  title: t("auth.userNotFoundTitle"),
263
268
  content: t("auth.userNotFoundSubtitle"),
264
269
  image: "userNotFound",
265
270
  };
266
-
271
+
267
272
  isNotification.value = true;
268
273
  }
269
274
  }
@@ -273,6 +278,12 @@ export default defineComponent({
273
278
  onSubmit("SoWell");
274
279
  };
275
280
 
281
+ const handleInfoDialog = () => {
282
+ if (infoDialog.value.canGoNext) {
283
+ goToOtpValidation()
284
+ }
285
+ }
286
+
276
287
  return {
277
288
  email,
278
289
  infoDialog,
@@ -289,7 +300,7 @@ export default defineComponent({
289
300
  WELCOME_SUBTITLE,
290
301
  WELCOME_TITLE,
291
302
  isSubmitBtnDisabled,
292
- goToOtpValidation,
303
+ handleInfoDialog,
293
304
  retypeEmail,
294
305
  onSubmit,
295
306
  icons,
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <q-layout>
3
- <q-page class="q-pa-md row justify-center">
2
+ <q-layout class="q-pa-md row justify-center">
3
+ <div>
4
4
  <div>
5
5
  <div class="q-mt-xl">
6
6
  <img
@@ -26,12 +26,17 @@
26
26
  >
27
27
  {{ $t("auth.recommendPassword") }}
28
28
  </div>
29
- <q-form class="column form" @submit="onSubmit">
29
+ <q-form
30
+ class="column form"
31
+ @submit="onSubmit"
32
+ data-testid="reset-password-form"
33
+ >
30
34
  <div>
31
35
  <div class="q-mb-sm" style="font-size: 14px; font-weight: 600">
32
36
  {{ $t("auth.newPassword") }}
33
37
  </div>
34
38
  <q-input
39
+ data-testid="password-input"
35
40
  id="password"
36
41
  v-model="password"
37
42
  data-cy="reset-password"
@@ -58,6 +63,7 @@
58
63
  <q-space class="mobile" />
59
64
  <div>
60
65
  <q-btn
66
+ data-testid="submit-btn"
61
67
  :label="$t('common.register')"
62
68
  color="primary"
63
69
  :loading="loading"
@@ -80,7 +86,7 @@
80
86
  @goToLoginPage="goToLoginPage"
81
87
  />
82
88
  </q-dialog>
83
- </q-page>
89
+ </div>
84
90
  </q-layout>
85
91
  </template>
86
92
 
@@ -103,7 +109,7 @@ export default defineComponent({
103
109
  canSubmit,
104
110
  onSubmit,
105
111
  goToLoginPage,
106
- icons
112
+ icons,
107
113
  } = useResetPassword();
108
114
 
109
115
  return {
@@ -115,7 +121,7 @@ export default defineComponent({
115
121
  showPassword,
116
122
  goToLoginPage,
117
123
  onSubmit,
118
- icons
124
+ icons,
119
125
  };
120
126
  },
121
127
  });
@@ -126,3 +132,4 @@ export default defineComponent({
126
132
  width: 254px;
127
133
  }
128
134
  </style>
135
+
@@ -65,7 +65,7 @@ export function useAuth() {
65
65
  const validations = ref({
66
66
  email: [
67
67
  (val: string) => {
68
- errorEmailMessage.value = val ? "" : t("auth.emailPresenceError");
68
+ errorEmailMessage.value = !!val ? "" : t("auth.emailPresenceError");
69
69
  return !!val || t("auth.emailPresenceError");
70
70
  },
71
71
  (val: string) => {
@@ -77,7 +77,9 @@ export function useAuth() {
77
77
  ],
78
78
  password: [
79
79
  (val: string) => {
80
- errorPasswordMessage.value = val ? "" : t("auth.passwordPresenceError");
80
+ errorPasswordMessage.value = !!val
81
+ ? ""
82
+ : t("auth.passwordPresenceError");
81
83
  return !!val || t("auth.passwordPresenceError");
82
84
  },
83
85
  ],
package/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  const path = require("path");
3
- function extendConf(conf, api) {
3
+ function extendConf(conf) {
4
4
  const requiredPlugins = ["Notify"];
5
5
 
6
6
  requiredPlugins.forEach((plugin) => {
@@ -20,9 +20,7 @@ function extendConf(conf, api) {
20
20
  );
21
21
  conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/axios.ts");
22
22
 
23
- if (api.hasWebpack) {
24
- conf.build.transpileDependencies.push(/quasar-app-extension-auth[\\/]src/);
25
- }
23
+ conf.build.transpileDependencies.push(/quasar-app-extension-auth[\\/]src/);
26
24
 
27
25
  console.log("Boot sowell auth");
28
26
  }
@@ -36,24 +34,9 @@ const chainWebpack = (ctx, chain) => {
36
34
  path.resolve(__dirname, "./composables")
37
35
  );
38
36
  };
39
-
40
- const aliasVite = (viteConf) => {
41
- viteConf.define.global = {};
42
- viteConf.resolve.alias = {
43
- ...viteConf.resolve.alias,
44
- "@sowell/auth": path.resolve(__dirname, "./components"),
45
- composables: path.resolve(__dirname, "./composables"),
46
- };
47
- };
48
-
49
37
  module.exports = function (api) {
50
38
  api.compatibleWith("quasar", "^2.0.0");
51
- if (api.hasVite === true) {
52
- api.compatibleWith("@quasar/app-vite", "^1.3.0");
53
- api.extendViteConf(aliasVite);
54
- } else {
55
- api.compatibleWith("@quasar/app", "^3.0.0");
56
- api.chainWebpack((chain) => chainWebpack(api.ctx, chain));
57
- }
39
+ api.compatibleWith("@quasar/app", "^3.0.0");
40
+ api.chainWebpack((chain) => chainWebpack(api.ctx, chain));
58
41
  api.extendQuasarConf(extendConf);
59
42
  };
@@ -1,5 +1,4 @@
1
1
  export * from "./api";
2
2
  export * from "./prompts";
3
3
  export * from "./router";
4
- export * from "./store";
5
4
  export * from './states'
@@ -10,11 +10,6 @@ export interface PromptsInterface {
10
10
  AUTH_SERVER_RESET_PASSWORD_ROUTE: string;
11
11
  AUTH_SERVER_UPDATE_PASSWORD_ROUTE: string;
12
12
  AUTH_TYPE: string;
13
- VUEX_SET_TOKEN_MUTATION: string;
14
- VUEX_CLEAR_TOKEN_MUTATION: string;
15
- VUEX_SET_INFOS_USER_MUTATION: string;
16
- VUEX_GET_TOKEN_GETTER: string;
17
- VUEX_GET_INFOS_USER_GETTER: string;
18
13
  X_REQUESTED_ROLES: string;
19
14
  WELCOME_TITLE: string;
20
15
  WELCOME_SUBTITLE: string;
@@ -23,7 +18,7 @@ export interface PromptsInterface {
23
18
  AUTH_SERVER_VERIFY_OTP: string;
24
19
  UI_PAGE: string;
25
20
  APP_VERSION: string;
26
- USE_SSO: boolean
21
+ USE_SSO: boolean;
27
22
  }
28
23
  export const $prompts = (): PromptsInterface => {
29
24
  const $prompts = inject<Record<"@sowell/auth", PromptsInterface>>("$prompts");
@@ -1,5 +1,6 @@
1
1
  import { inject } from "vue";
2
2
  import { Store } from "pinia";
3
+ import { AxiosResponse } from "axios";
3
4
  import { $prompts } from "../injects";
4
5
 
5
6
  export interface AuthStatePayload {
@@ -71,7 +72,22 @@ export interface ResetPasswordPayload {
71
72
  };
72
73
  }
73
74
 
74
- export const useAuthState = () => {
75
+ export const useAuthState = (): Store<
76
+ "auth",
77
+ AuthState,
78
+ {
79
+ getIsValid(state: AuthState): boolean;
80
+ },
81
+ {
82
+ signin(
83
+ data: SignInPayload,
84
+ options: RequestOptions
85
+ ): Promise<AxiosResponse>;
86
+ msalSignin(): Promise<AxiosResponse>;
87
+ resetPassword(data: ResetPasswordPayload): Promise<AxiosResponse>;
88
+ updateRaw(value: string): void;
89
+ }
90
+ > => {
75
91
  const authState = inject<Store<"auth", AuthState>>("authState");
76
92
  if (authState == undefined) {
77
93
  throw Error("Could not inject authState");
@@ -1,8 +1,6 @@
1
1
  import { Router } from "vue-router";
2
- import { Store } from "vuex";
3
2
  import { App } from "vue";
4
3
  export interface BootInterface {
5
4
  router: Router;
6
- store: Store<any>;
7
5
  app: App<any>;
8
6
  }
package/src/prompts.js CHANGED
@@ -64,20 +64,6 @@ module.exports = function () {
64
64
  message: "Authorization type",
65
65
  default: "Bearer",
66
66
  },
67
- {
68
- name: "VUEX_SET_TOKEN_MUTATION",
69
- type: "input",
70
- required: true,
71
- message: "Vuex mutation to set token",
72
- default: "auth/set_token",
73
- },
74
- {
75
- name: "VUEX_CLEAR_TOKEN_MUTATION",
76
- type: "input",
77
- required: true,
78
- message: "Vuex mutation to clear token",
79
- default: "auth/clear_token",
80
- },
81
67
  {
82
68
  name: "UI_PAGE",
83
69
  type: "input",
@@ -85,34 +71,6 @@ module.exports = function () {
85
71
  message: "Login page for mobile app",
86
72
  default: "",
87
73
  },
88
- {
89
- name: "VUEX_SET_EMAIL_MUTATION",
90
- type: "input",
91
- required: true,
92
- message: "Vuex mutation to store user email when authenticated",
93
- default: "auth/set_email_user",
94
- },
95
- {
96
- name: "VUEX_SET_INFOS_USER_MUTATION",
97
- type: "input",
98
- required: true,
99
- message: "Vuex mutation to set user information to reset password",
100
- default: "auth/set_infos_user",
101
- },
102
- {
103
- name: "VUEX_GET_TOKEN_GETTER",
104
- type: "input",
105
- required: true,
106
- message: "Vuex getter token",
107
- default: "auth/get_token",
108
- },
109
- {
110
- name: "VUEX_GET_INFOS_USER_GETTER",
111
- type: "input",
112
- required: true,
113
- message: "Vuex getter user information",
114
- default: "auth/get_infos_user",
115
- },
116
74
  {
117
75
  name: "X_REQUESTED_ROLES",
118
76
  type: "input",
@@ -1,13 +1,6 @@
1
1
  //@ts-ignore
2
2
  import prompts from "app/quasar.extensions.json";
3
3
  import { RouteRecordRaw } from "vue-router";
4
- import AdminAuth from "../components/pages/AdminAuth.vue";
5
- import WebAuth from "../components/pages/WebAuth.vue";
6
- import WebResetPassword from "../components/pages/WebResetPassword.vue";
7
- import ResetPaswword from "../components/pages/ResetPassword.vue";
8
-
9
- import Auth from "../components/pages/Auth.vue";
10
- import AuthReporter from "../components/pages/AuthReporter.vue";
11
4
 
12
5
  const {
13
6
  "@sowell/auth": {
@@ -27,50 +20,54 @@ let authPage = "";
27
20
 
28
21
  switch (UI_PAGE) {
29
22
  case "mobile_clean":
30
- authPage = Auth;
23
+ authPage = "Auth.vue";
31
24
  break;
32
25
  case "reporter":
33
- authPage = AuthReporter;
26
+ authPage = "AuthReporter.vue";
34
27
  break;
35
28
  case "admin":
36
- authPage = AdminAuth;
29
+ authPage = "AdminAuth.vue";
37
30
  break;
38
31
  default:
39
- authPage = Auth;
32
+ authPage = "Auth.vue";
40
33
  break;
41
34
  }
42
35
 
43
- const loginPage = (X_REQUESTED_ROLES: string) => {
36
+ const loginPage = (X_REQUESTED_ROLES: string): string => {
44
37
  return X_REQUESTED_ROLES === "admin"
45
- ? AdminAuth
38
+ ? "AdminAuth.vue"
46
39
  : webAuthRoles.includes(X_REQUESTED_ROLES)
47
- ? WebAuth
48
- : authPage;
40
+ ? "WebAuth.vue"
41
+ : authPage;
49
42
  };
50
43
 
51
- const isInRoles = (X_REQUESTED_ROLES: string) => {
44
+ const isInRoles = (X_REQUESTED_ROLES: string): string => {
52
45
  return webAuthRoles.includes(X_REQUESTED_ROLES) ||
53
46
  AdminAuthRoles.includes(X_REQUESTED_ROLES)
54
- ? WebResetPassword
55
- : ResetPaswword;
47
+ ? "WebResetPassword.vue"
48
+ : "ResetPassword.vue";
56
49
  };
57
50
 
58
51
  const routes: RouteRecordRaw[] = [
59
52
  {
60
53
  path: LOCAL_LOGIN_ROUTE,
61
- component: () => loginPage(X_REQUESTED_ROLES),
54
+ component: () =>
55
+ // @ts-ignore
56
+ import(`@sowell/auth/pages/${loginPage(X_REQUESTED_ROLES)}`),
62
57
  },
63
58
  {
64
59
  path: LOCAL_UPDATE_PASSWORD_ROUTE,
65
60
  name: "update_password",
66
- component: () => isInRoles(X_REQUESTED_ROLES),
61
+ component: () =>
62
+ // @ts-ignore
63
+ import(`@sowell/auth/pages/${isInRoles(X_REQUESTED_ROLES)}`),
67
64
  },
68
65
  {
69
66
  path: LOCAL_OTP_ROUTE,
70
67
  name: "otp_validation",
71
68
  component: () =>
72
69
  // @ts-ignore
73
- import("../components/pages/OtpValidation.vue"),
70
+ import("@sowell/auth/pages/OtpValidation.vue"),
74
71
  },
75
72
  ];
76
73
 
@@ -1,22 +0,0 @@
1
- name: Cypress Tests
2
-
3
- on: [push]
4
-
5
- jobs:
6
- cypress-run:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - name: Checkout
10
- uses: actions/checkout@v4
11
- - name: Nodejs
12
- uses: actions/setup-node@v4
13
- with:
14
- node-version: '18'
15
- cache: yarn
16
- - run: yarn install
17
- - run: yarn dep
18
- - name: Cypress run
19
- uses: cypress-io/github-action@v6
20
- with:
21
- working-directory: dev
22
- command: yarn ci
@@ -1,10 +0,0 @@
1
- import { inject } from "vue";
2
- import { Store } from "vuex";
3
-
4
- export const $store = (): Store<any> => {
5
- const $store = inject<Store<any>>("$store");
6
- if ($store == undefined) {
7
- throw Error("Could not inject store");
8
- }
9
- return $store;
10
- };
@@ -1,71 +0,0 @@
1
- import { Module, GetterTree, MutationTree, ActionTree } from "vuex";
2
- import { tokenStateInterface, payload } from "../interfaces";
3
-
4
- const state: tokenStateInterface = {
5
- raw: "",
6
- payload: {
7
- company_hp: undefined,
8
- exp: undefined,
9
- gm_key: "",
10
- roles: [],
11
- sub: null
12
- }
13
- }
14
-
15
- const getters: GetterTree<tokenStateInterface, any> = {
16
- getRaw(state) {
17
- return state.raw
18
- },
19
- getPayload(state) {
20
- return state.payload
21
- },
22
- getIsValid(state) {
23
- if (state.payload.exp) {
24
- return new Date(state.payload.exp * 1000) >= new Date() ? true : false;
25
- } else {
26
- return false
27
- }
28
- }
29
- }
30
-
31
- const mutations: MutationTree<tokenStateInterface> = {
32
- setRaw(state, value: string) {
33
- state.raw = value
34
- },
35
- setPayload(state, value: payload) {
36
- state.payload = {...value}
37
- },
38
- reset(state) {
39
- state.raw = ""
40
- state.payload = {
41
- company_hp: undefined,
42
- exp: undefined,
43
- gm_key: "",
44
- roles: [],
45
- sub: null
46
- }
47
- }
48
- }
49
-
50
- const actions: ActionTree<tokenStateInterface, any> = {
51
- updateRaw({ commit }, value: string) {
52
- commit("setRaw", value);
53
- let parseJwt: string
54
- try {
55
- parseJwt = JSON.parse(window.atob(value.split(".")[1]));
56
- } catch (error) {
57
- parseJwt = ""
58
- }
59
- commit("setPayload", parseJwt)
60
- }
61
- }
62
-
63
- const tokenModule: Module<tokenStateInterface, any> = {
64
- namespaced: true,
65
- getters,
66
- mutations,
67
- actions,
68
- state
69
- }
70
-
71
- export default tokenModule;