@sowell/quasar-app-extension-auth 0.1.8 → 0.2.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.
Files changed (46) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc.js +13 -13
  3. package/.gitattributes +2 -0
  4. package/.github/workflows/main.yml +22 -0
  5. package/README.md +393 -28
  6. package/package.json +34 -19
  7. package/src/boot/axios.ts +17 -0
  8. package/src/boot/register.ts +8 -0
  9. package/src/boot/router-guards.ts +25 -0
  10. package/src/boot/router.ts +20 -0
  11. package/src/boot/store.ts +10 -0
  12. package/src/components/pages/Auth.vue +227 -0
  13. package/src/components/{ResetPassword.vue → pages/ResetPassword.vue} +40 -40
  14. package/src/i18n/en-US/index.ts +23 -0
  15. package/src/i18n/fr-FR/index.ts +23 -0
  16. package/src/i18n/index.ts +7 -0
  17. package/src/index.js +29 -24
  18. package/src/injects/api.ts +10 -0
  19. package/src/injects/index.ts +4 -0
  20. package/src/injects/prompts.ts +25 -0
  21. package/src/injects/router.ts +10 -0
  22. package/src/injects/store.ts +10 -0
  23. package/src/interfaces/Boot.ts +8 -0
  24. package/src/interfaces/TokenStateInterface.ts +11 -0
  25. package/src/interfaces/index.ts +2 -0
  26. package/src/prompts.js +40 -34
  27. package/src/routes/index.ts +22 -0
  28. package/src/shims-vue.d.ts +6 -0
  29. package/src/store/index.ts +56 -0
  30. package/tsconfig.json +14 -0
  31. package/.github/workflows/publish.yml +0 -23
  32. package/.prettierrc +0 -7
  33. package/.vscode/extensions.json +0 -12
  34. package/.vscode/settings.json +0 -22
  35. package/jsconfig.json +0 -7
  36. package/package-lock.json +0 -2344
  37. package/src/boot/axios.js +0 -19
  38. package/src/boot/navigation-guards.js +0 -16
  39. package/src/boot/register.js +0 -45
  40. package/src/components/Auth.vue +0 -275
  41. package/src/components/ResetCode.vue +0 -137
  42. package/src/components/prompt.js +0 -38
  43. package/src/config/setupHeaders.js +0 -6
  44. package/src/install.js +0 -10
  45. package/src/templates/.gitkeep +0 -0
  46. package/src/uninstall.js +0 -10
@@ -0,0 +1,20 @@
1
+ //@ts-ignore
2
+ import { boot } from "quasar/wrappers";
3
+ import { BootInterface } from "../interfaces";
4
+ import newRoutes from "../routes";
5
+
6
+ export default boot(({ app, router }: BootInterface) => {
7
+ // Register auth routes
8
+ let { routes } = router.options;
9
+ let routeData = routes.find((r) => r.path === "/");
10
+ if (routeData?.children) {
11
+ const currentRoutes = routeData.children.map((route) => route.path);
12
+
13
+ newRoutes.forEach((route) => {
14
+ if (!currentRoutes.includes(route.path)) {
15
+ router.addRoute(route);
16
+ }
17
+ });
18
+ }
19
+ app.provide("$router", router);
20
+ });
@@ -0,0 +1,10 @@
1
+ //@ts-ignore
2
+ import { boot } from "quasar/wrappers";
3
+ import { BootInterface } from "../interfaces";
4
+ import tokenModule from "../store";
5
+
6
+ export default boot(({ app, store }: BootInterface) => {
7
+ // Register store module
8
+ store.registerModule("token", tokenModule);
9
+ app.provide("$store", store);
10
+ });
@@ -0,0 +1,227 @@
1
+ <template>
2
+ <q-layout>
3
+ <q-page-container>
4
+ <q-page class="flex flex-center">
5
+ <q-card square>
6
+ <q-card-section>
7
+ <div class="text-h5 text-center head">
8
+ {{ $t("auth.title") }}
9
+ </div>
10
+ </q-card-section>
11
+
12
+ <q-form class="q-gutter-md" @submit="onSubmit">
13
+ <q-card-section>
14
+ <q-input
15
+ data-cy="email"
16
+ v-model.trim="email"
17
+ type="email"
18
+ :label="$t('auth.email')"
19
+ :rules="validations['email']"
20
+ lazy-rules
21
+ autofocus
22
+ rounded
23
+ outlined
24
+ dense
25
+ class="full-width q-mb-md"
26
+ />
27
+ <q-input
28
+ data-cy="password"
29
+ v-model="password"
30
+ :type="showPassword ? 'text' : 'password'"
31
+ :label="$t('auth.password')"
32
+ :rules="validations['password']"
33
+ lazy-rules
34
+ rounded
35
+ outlined
36
+ dense
37
+ class="full-width q-mb-md"
38
+ >
39
+ <template #append>
40
+ <q-icon
41
+ :name="showPassword ? 'visibility' : 'visibility_off'"
42
+ class="cursor-pointer"
43
+ @click="showPassword = !showPassword"
44
+ />
45
+ </template>
46
+ </q-input>
47
+ </q-card-section>
48
+ <div class="forgottenPass">
49
+ <q-btn
50
+ @click="forgottenPassword = true"
51
+ no-caps
52
+ flat
53
+ :label="$t('auth.forgottenPassword')"
54
+ />
55
+ </div>
56
+ <q-card-actions>
57
+ <q-btn
58
+ data-cy="submit-login"
59
+ rounded
60
+ :label="$t('auth.login')"
61
+ color="primary"
62
+ :loading="loading"
63
+ type="submit"
64
+ class="full-width"
65
+ :disable="isSubmitBtnDisabled()"
66
+ />
67
+ </q-card-actions>
68
+ </q-form>
69
+ </q-card>
70
+ <div>
71
+ <q-dialog v-model="forgottenPassword" persistent>
72
+ <q-card style="min-width: 350px">
73
+ <q-card-section>
74
+ <p class="resetPasswordTitle">
75
+ {{ $t("auth.tapEmail") }}
76
+ </p>
77
+ </q-card-section>
78
+
79
+ <q-card-section class="q-pt-none">
80
+ <q-input
81
+ v-model="emailResetPassword"
82
+ dense
83
+ rounded
84
+ outlined
85
+ :placeholder="$t('auth.email')"
86
+ autofocus
87
+ />
88
+ </q-card-section>
89
+
90
+ <q-card-actions align="right">
91
+ <q-btn
92
+ outline
93
+ rounded
94
+ :label="$t('common.cancel')"
95
+ class="btn-min"
96
+ v-close-popup
97
+ />
98
+ <q-btn
99
+ rounded
100
+ color="primary"
101
+ :label="$t('common.send')"
102
+ class="btn-min"
103
+ @click="resetPassword"
104
+ />
105
+ </q-card-actions>
106
+ </q-card>
107
+ </q-dialog>
108
+ </div>
109
+ </q-page>
110
+ </q-page-container>
111
+ </q-layout>
112
+ </template>
113
+
114
+ <script lang="ts">
115
+ //import prompts from "app/quasar.extensions.json";
116
+ import isEmail from "validator/es/lib/isEmail";
117
+ import { defineComponent, ref, onMounted } from "vue";
118
+ import { $api, $prompts, $router, $store } from "../../injects";
119
+ import { useQuasar } from "quasar";
120
+ import { useI18n } from "vue-i18n";
121
+ import { AxiosError, AxiosResponse } from "axios";
122
+ export default defineComponent({
123
+ name: "Auth",
124
+ setup() {
125
+ const email = ref("");
126
+ const password = ref("");
127
+ const loading = ref(false);
128
+ const showPassword = ref(false);
129
+ const forgottenPassword = ref(false);
130
+ const emailResetPassword = ref("");
131
+ const { post } = $api();
132
+ const {
133
+ LOCAL_SUCCESS_REDIRECTION_ROUTE,
134
+ AUTH_SERVER_SIGNING_ROUTE,
135
+ AUTH_SERVER_RESET_PASSWORD_ROUTE,
136
+ } = $prompts();
137
+ const $q = useQuasar();
138
+ const { push, replace } = $router();
139
+ const { dispatch, getters } = $store();
140
+ const { t } = useI18n();
141
+
142
+ onMounted(() => {
143
+ if (getters["token/getRaw"]) {
144
+ replace(LOCAL_SUCCESS_REDIRECTION_ROUTE);
145
+ }
146
+ });
147
+
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")],
154
+ });
155
+
156
+ const resetPassword = () => {
157
+ const data = {
158
+ email: emailResetPassword.value,
159
+ };
160
+
161
+ post(AUTH_SERVER_RESET_PASSWORD_ROUTE, data)
162
+ .then(() => {
163
+ $q.notify({
164
+ message: t("auth.emailSent"),
165
+ color: "positive",
166
+ position: "top",
167
+ });
168
+ forgottenPassword.value = false;
169
+ })
170
+ .catch(() => {
171
+ $q.notify({
172
+ message: t("auth.emailNotRecognize"),
173
+ color: "negative",
174
+ position: "top",
175
+ });
176
+ });
177
+ };
178
+
179
+ const onSubmit = () => {
180
+ loading.value = true;
181
+ const data = {
182
+ auth: {
183
+ email: email.value,
184
+ password: password.value,
185
+ },
186
+ };
187
+
188
+ post(AUTH_SERVER_SIGNING_ROUTE, data)
189
+ .then((response: AxiosResponse) => {
190
+ const token = response.data.jwt;
191
+ dispatch("token/updateRaw", token);
192
+ push(LOCAL_SUCCESS_REDIRECTION_ROUTE);
193
+ })
194
+ .catch((error: AxiosError) => {
195
+ loading.value = false;
196
+ $q.notify({
197
+ message: t("auth.loginFailed"),
198
+ color: "negative",
199
+ position: "top",
200
+ });
201
+ });
202
+ };
203
+
204
+ const isSubmitBtnDisabled = () => {
205
+ return !(
206
+ email.value &&
207
+ isEmail(email.value) &&
208
+ password.value &&
209
+ password.value.length > 5
210
+ );
211
+ };
212
+
213
+ return {
214
+ email,
215
+ password,
216
+ loading,
217
+ showPassword,
218
+ validations,
219
+ isSubmitBtnDisabled,
220
+ onSubmit,
221
+ forgottenPassword,
222
+ emailResetPassword,
223
+ resetPassword,
224
+ };
225
+ },
226
+ });
227
+ </script>
@@ -51,68 +51,68 @@
51
51
  </q-page>
52
52
  </template>
53
53
 
54
- <script>
55
- import { ref, defineComponent, computed, inject } from "vue"
56
- import { useQuasar } from "quasar"
57
- import { useRouter } from "vue-router"
58
- import prompts from "./prompt.js"
59
- import { api } from "../boot/axios"
54
+ <script lang="ts">
55
+ import { useQuasar } from "quasar";
56
+ import { computed, defineComponent, ref } from "vue";
57
+ import { useI18n } from "vue-i18n";
58
+ import { useRouter } from "vue-router";
59
+ import { $api, $prompts } from "../../injects";
60
60
 
61
61
  export default defineComponent({
62
62
  name: "ResetPassword",
63
63
 
64
64
  setup() {
65
- const i18n = inject("i18n")
65
+ const { patch } = $api();
66
66
  const {
67
- auth_server_update_password_route,
68
- local_success_redirection_route
69
- } = prompts()
70
- const $q = useQuasar()
71
- const router = useRouter()
72
- const password = ref("")
73
- const passwordConfirmation = ref("")
74
- const loading = ref(false)
67
+ AUTH_SERVER_UPDATE_PASSWORD_ROUTE,
68
+ LOCAL_SUCCESS_REDIRECTION_ROUTE,
69
+ } = $prompts();
70
+ const $q = useQuasar();
71
+ const router = useRouter();
72
+ const password = ref("");
73
+ const passwordConfirmation = ref("");
74
+ const loading = ref(false);
75
+ const { t } = useI18n();
75
76
 
76
77
  const canSubmit = computed(() => {
77
78
  return password.value != "" &&
78
79
  password.value === passwordConfirmation.value
79
80
  ? false
80
- : true
81
- })
81
+ : true;
82
+ });
82
83
 
83
84
  const validations = {
84
85
  passwordRules: [
85
- (val) => !!val || i18n.t("auth.newPasswordPresenceError")
86
+ (val: string) => !!val || t("auth.newPasswordPresenceError"),
86
87
  ],
87
88
  passwordConfirmationRules: [
88
- (val) =>
89
- val === password.value || i18n.t("auth.newPasswordConfirmationFailed")
90
- ]
91
- }
89
+ (val: string) =>
90
+ val === password.value || t("auth.newPasswordConfirmationFailed"),
91
+ ],
92
+ };
92
93
 
93
- function onSubmit() {
94
+ const onSubmit = () => {
94
95
  const data = {
95
96
  password: password.value,
96
- password_confirmation: passwordConfirmation.value
97
- }
98
- api
99
- .patch(auth_server_update_password_route, data)
97
+ password_confirmation: passwordConfirmation.value,
98
+ };
99
+ patch(AUTH_SERVER_UPDATE_PASSWORD_ROUTE, data)
100
100
  .then(() => {
101
101
  $q.notify({
102
- message: i18n.t("auth.passwordRecoverySuccess"),
102
+ message: t("auth.passwordRecoverySuccess"),
103
103
  color: "positive",
104
- position: "top"
105
- })
106
- router.push(local_success_redirection_route)
104
+ position: "top",
105
+ });
106
+ router.push(LOCAL_SUCCESS_REDIRECTION_ROUTE);
107
107
  })
108
108
  .catch(() => {
109
109
  $q.notify({
110
- message: i18n.t("auth.passwordRecoveryFailed"),
110
+ message: t("auth.passwordRecoveryFailed"),
111
111
  color: "negative",
112
- position: "top"
113
- })
114
- })
115
- }
112
+ position: "top",
113
+ });
114
+ });
115
+ };
116
116
 
117
117
  return {
118
118
  password,
@@ -120,10 +120,10 @@ export default defineComponent({
120
120
  validations,
121
121
  loading,
122
122
  onSubmit,
123
- canSubmit
124
- }
125
- }
126
- })
123
+ canSubmit,
124
+ };
125
+ },
126
+ });
127
127
  </script>
128
128
 
129
129
  <style scoped>
@@ -0,0 +1,23 @@
1
+ export default {
2
+ auth: {
3
+ title: "Log in to access the management interface",
4
+ email: "Email",
5
+ password: "Password",
6
+ forgottenPassword: "Forgotten password",
7
+ login: "Login",
8
+ emailPresenceError: "The email must be provided",
9
+ emailValidationError: "The email is not valid",
10
+ passwordPresenceError: "The password must be provided",
11
+ passwordLengthError: "The password length be at least 6",
12
+ loginFailed: "Incorrect credentials",
13
+ emailNotRecognize: "Login failed, please check your credentials",
14
+ emailSent: "Email sent, check your inbox",
15
+ tapEmail: "Please enter your email",
16
+ 404: "No user found with the provided credentials",
17
+ },
18
+ common: {
19
+ register: "Save",
20
+ send: "Send",
21
+ cancel: "Cancel",
22
+ },
23
+ };
@@ -0,0 +1,23 @@
1
+ export default {
2
+ auth: {
3
+ title: "Connectez vous",
4
+ email: "Email",
5
+ password: "Mot de passe",
6
+ forgottenPassword: "Mot de passe oublié",
7
+ login: "Connexion",
8
+ emailPresenceError: "L'adresse email doit être fournie",
9
+ emailValidationError: "L'adresse email fournie est invalide",
10
+ passwordPresenceError: "Le mot de passe doit être fourni",
11
+ passwordLengthError: "La longueur du mot de passe doit être au minimum 6",
12
+ loginFailed: "Identifiants incorrectes",
13
+ emailNotRecognize: "L'adresse email fournie n'est pas reconnue",
14
+ emailSent: "Email envoyé, vérifier votre boite email",
15
+ tapEmail: "Entrer votre email",
16
+ 404: "Aucun utilisateur trouvé avec les identifiants donnés",
17
+ },
18
+ common: {
19
+ register: "Enregistre",
20
+ send: "Envoyer",
21
+ cancel: "Annuler",
22
+ },
23
+ };
@@ -0,0 +1,7 @@
1
+ import enUS from "./en-US";
2
+ import frFR from "./fr-FR";
3
+
4
+ export default {
5
+ "en-US": enUS,
6
+ "fr-FR": frFR,
7
+ };
package/src/index.js CHANGED
@@ -1,33 +1,38 @@
1
- const path = require("path")
2
-
1
+ "use strict";
2
+ const path = require("path");
3
3
  function extendConf(conf) {
4
- conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/register.js")
5
- conf.boot.push(
6
- "~@sowell/quasar-app-extension-auth/src/boot/navigation-guards.js"
7
- )
4
+ const requiredPlugins = ["Notify"];
8
5
 
9
- conf.build.transpileDependencies.push(/quasar-app-extension-auth[\\/]src/)
10
-
11
- const requiredPlugins = ["Notify"]
12
6
  requiredPlugins.forEach((plugin) => {
13
7
  if (!conf.framework.plugins.includes(plugin)) {
14
- conf.framework.plugins.push(plugin)
8
+ conf.framework.plugins.push(plugin);
15
9
  }
16
- })
17
- }
10
+ });
11
+
12
+ conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/register.ts");
13
+
14
+ conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/store.ts");
15
+
16
+ conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/router.ts");
18
17
 
19
- //Create aliases to import or require certain modules or file more easily.
18
+ conf.boot.push(
19
+ "~@sowell/quasar-app-extension-auth/src/boot/router-guards.ts"
20
+ );
21
+ conf.boot.push("~@sowell/quasar-app-extension-auth/src/boot/axios.ts");
22
+
23
+ conf.build.transpileDependencies.push(/quasar-app-extension-auth[\\/]src/);
24
+
25
+ console.log("Boot sowell auth");
26
+ }
20
27
  const chainWebpack = (ctx, chain) => {
21
28
  chain.resolve.alias.set(
22
- "setupHeaders",
23
- // eslint-disable-next-line no-undef
24
- path.resolve(__dirname, "./config/setupHeaders")
25
- )
26
- }
27
-
29
+ "@sowell/auth",
30
+ path.resolve(__dirname, "./components")
31
+ );
32
+ };
28
33
  module.exports = function (api) {
29
- api.compatibleWith("quasar", "^2.0.0-beta.12")
30
- api.compatibleWith("@quasar/app", "^3.0.0-beta.12")
31
- api.chainWebpack((chain) => chainWebpack(api.ctx, chain))
32
- api.extendQuasarConf(extendConf)
33
- }
34
+ api.compatibleWith("quasar", "^2.0.0");
35
+ api.compatibleWith("@quasar/app", "^3.0.0");
36
+ api.chainWebpack((chain) => chainWebpack(api.ctx, chain));
37
+ api.extendQuasarConf(extendConf);
38
+ };
@@ -0,0 +1,10 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { inject } from "vue";
3
+
4
+ export const $api = (): AxiosInstance => {
5
+ const $api = inject<AxiosInstance>("$api");
6
+ if ($api == undefined) {
7
+ throw Error("Could not inject api");
8
+ }
9
+ return $api;
10
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./api";
2
+ export * from "./prompts";
3
+ export * from "./router";
4
+ export * from "./store";
@@ -0,0 +1,25 @@
1
+ import { inject } from "vue";
2
+ export interface PromptsInterface {
3
+ LOCAL_LOGIN_ROUTE: string;
4
+ LOCAL_SUCCESS_REDIRECTION_ROUTE: string;
5
+ LOCAL_CHECK_CODE_ROUTE: string;
6
+ LOCAL_UPDATE_PASSWORD_ROUTE: string;
7
+ AUTH_SERVER_BASE_URL: string;
8
+ AUTH_SERVER_SIGNING_ROUTE: string;
9
+ AUTH_SERVER_RESET_PASSWORD_ROUTE: string;
10
+ AUTH_SERVER_UPDATE_PASSWORD_ROUTE: string;
11
+ AUTH_TYPE: string;
12
+ VUEX_SET_TOKEN_MUTATION: string;
13
+ VUEX_CLEAR_TOKEN_MUTATION: string;
14
+ VUEX_SET_EMAIL_OR_PHONENUMBER_USER_MUTATION: string;
15
+ VUEX_SET_INFOS_USER_MUTATION: string;
16
+ VUEX_GET_TOKEN_GETTER: string;
17
+ VUEX_GET_INFOS_USER_GETTER: string;
18
+ }
19
+ export const $prompts = (): PromptsInterface => {
20
+ const $prompts = inject<Record<"@sowell/auth", PromptsInterface>>("$prompts");
21
+ if ($prompts == undefined) {
22
+ throw Error("Could not inject prompts");
23
+ }
24
+ return $prompts["@sowell/auth"];
25
+ };
@@ -0,0 +1,10 @@
1
+ import { inject } from "vue";
2
+ import { Router } from "vue-router";
3
+
4
+ export const $router = (): Router => {
5
+ const $router = inject<Router>("$router");
6
+ if ($router == undefined) {
7
+ throw Error("Could not inject router");
8
+ }
9
+ return $router;
10
+ };
@@ -0,0 +1,10 @@
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
+ };
@@ -0,0 +1,8 @@
1
+ import { Router } from "vue-router";
2
+ import { Store } from "vuex";
3
+ import { App } from "vue";
4
+ export interface BootInterface {
5
+ router: Router;
6
+ store: Store<any>;
7
+ app: App<any>;
8
+ }
@@ -0,0 +1,11 @@
1
+ export interface payload {
2
+ company_hp?: number
3
+ exp?: number
4
+ gm_key: string
5
+ roles: string[] | []
6
+ sub: number | null
7
+ }
8
+ export interface tokenStateInterface {
9
+ raw: string
10
+ payload: payload
11
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./Boot";
2
+ export * from "./TokenStateInterface";