@hostlink/nuxt-light 1.16.0 → 1.17.0

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "1.16.0",
4
+ "version": "1.17.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
@@ -74,7 +74,7 @@ const onSubmit = async (d) => {
74
74
  <FormKit type="l-input" label="SMTP Password" name="mail_password"></FormKit>
75
75
 
76
76
  <FormKit type="l-select" label="SMTP Encryption" name="mail_encryption" :options="[
77
- { label: 'None', value: 'none' },
77
+ { label: 'None', value: '' },
78
78
  { label: 'SSL', value: 'ssl' },
79
79
  { label: 'TLS', value: 'tls' },
80
80
  ]"></FormKit>
@@ -18,7 +18,16 @@ watch(route, (to, from) => {
18
18
 
19
19
  let app = null
20
20
  try {
21
- app = (await q({ app: ['company', 'companyLogo', 'logged', 'twoFactorAuthentication', 'googleClientId'] })).app;
21
+ app = (await q({
22
+ app: {
23
+ company: true,
24
+ companyLogo: true,
25
+ logged: true,
26
+ twoFactorAuthentication: true,
27
+ googleClientId: true,
28
+ forgetPasswordEnabled: true
29
+ }
30
+ })).app;
22
31
  light.setCompany(app.company);
23
32
  light.setCompanyLogo(app.companyLogo);
24
33
  } catch (e) {
@@ -41,8 +50,7 @@ provide('color', color)
41
50
  <q-layout v-if="!app.logged">
42
51
  <q-page-container class="bg-grey-2" style="color:#1f1f1f">
43
52
  <q-page padding>
44
- <l-login :two-factor-authentication="app.twoFactorAuthentication"
45
- :google-client-id="app.googleClientId"></l-login>
53
+ <l-login v-bind="app"></l-login>
46
54
  </q-page>
47
55
  </q-page-container>
48
56
  </q-layout>
@@ -53,7 +61,7 @@ provide('color', color)
53
61
  <slot name="header"></slot>
54
62
  </template>
55
63
 
56
-
64
+
57
65
 
58
66
 
59
67
 
@@ -3,14 +3,15 @@ import { useLight } from "#imports";
3
3
  import { ref, reactive, onMounted } from 'vue'
4
4
  import { useQuasar } from 'quasar';
5
5
  import { useI18n } from 'vue-i18n';
6
- import { m, notify, api } from '#imports';
6
+ import { m, api } from '#imports';
7
7
 
8
8
 
9
9
  const light = useLight();
10
10
 
11
11
  const props = defineProps({
12
12
  twoFactorAuthentication: Boolean,
13
- googleClientId: String
13
+ googleClientId: String,
14
+ forgetPasswordEnabled: Boolean
14
15
  })
15
16
 
16
17
  const { t } = useI18n();
@@ -20,8 +21,28 @@ const data = reactive({
20
21
  username: "", password: "", code: ""
21
22
  });
22
23
 
24
+
23
25
  const $q = useQuasar()
24
26
 
27
+ const loginWithCode = (username, password) => {
28
+ $q.dialog({
29
+ title: "Enter your code",
30
+ message: "Please enter your two factor authentication code (If you lost your authenticator, please contact your administrator)",
31
+ prompt: {
32
+ type: "text",
33
+ required: true
34
+ },
35
+ cancel: true,
36
+ persistent: true
37
+ }).onOk(async code => {
38
+ data.username = username;
39
+ data.password = password;
40
+ data.code = code;
41
+ submit();
42
+ });
43
+
44
+ }
45
+
25
46
  const submit = async () => {
26
47
  if (await form1.value.validate()) {
27
48
 
@@ -29,7 +50,20 @@ const submit = async () => {
29
50
  await api.auth.login(data.username, data.password, data.code)
30
51
  window.self.location.reload();
31
52
  } catch (e) {
32
- notify(e.message, "negative");
53
+ data.code = "";
54
+
55
+ if (e.message == "two factor authentication code is required") {
56
+
57
+ loginWithCode(data.username, data.password);
58
+ return;
59
+ }
60
+
61
+ $q.notify({
62
+ message: e.message,
63
+ color: "negative",
64
+ icon: "sym_o_error",
65
+ });
66
+
33
67
 
34
68
  }
35
69
  }
@@ -1,7 +1,10 @@
1
1
  <script setup>
2
- import { useLight, getObject } from "#imports";
2
+ import { useLight, getObject, m } from "#imports";
3
3
  import { useRoute } from "vue-router"
4
4
  import { ref } from 'vue';
5
+ import { useQuasar } from 'quasar';
6
+
7
+ const $q = useQuasar();
5
8
  const route = useRoute();
6
9
 
7
10
  const obj = await getObject(["canUpdate"]);
@@ -11,6 +14,36 @@ const light = useLight();
11
14
  const tab = ref('overview');
12
15
  const id = route.params.user_id;
13
16
 
17
+ const reset2fa = async () => {
18
+
19
+ //confirm
20
+ await $q.dialog({
21
+ title: "Reset 2FA",
22
+ message: "Are you sure you want to reset 2FA?",
23
+ color: "negative",
24
+ ok: true,
25
+ cancel: true
26
+ }).onOk(async () => {
27
+ try {
28
+ await m('reset2FA', { id: parseInt(id) });
29
+ $q.notify({
30
+ type: 'positive',
31
+ message: '2FA reset successfully'
32
+ });
33
+ } catch (e) {
34
+ $q.notify({
35
+ type: 'negative',
36
+ message: e.message
37
+ });
38
+ }
39
+
40
+ })
41
+
42
+
43
+
44
+
45
+
46
+ }
14
47
 
15
48
  </script>
16
49
 
@@ -21,6 +54,7 @@ const id = route.params.user_id;
21
54
  <l-btn to="change-password" icon="sym_o_key" permission="user.changePassword"
22
55
  label="Change password"></l-btn>
23
56
  <l-btn to="update-role" icon="sym_o_people" permission="user.role.add" label="Update role"></l-btn>
57
+ <l-btn label="Reset 2FA" icon="sym_o_key" permission="user.reset2fa" @click="reset2fa"></l-btn>
24
58
  </template>
25
59
 
26
60
  <q-card flat bordered>
@@ -1,6 +1,8 @@
1
1
  <script setup>
2
2
  import { ref, reactive } from "vue"
3
+ import { useQuasar } from "quasar"
3
4
  import { q, m, notify } from '#imports'
5
+ const $q = useQuasar()
4
6
 
5
7
  const my = await q("my", ["twoFactorEnabled"])
6
8
  const my2FA = await m("my2FA", [])
@@ -25,6 +27,21 @@ if (my.twoFactorEnabled) {
25
27
  show.value = false;
26
28
  }
27
29
 
30
+ const onCopy = () => {
31
+ navigator.clipboard.writeText(my2FA.secret).then(() => {
32
+ $q.notify({
33
+ message: "Secret copied",
34
+ color: "green",
35
+ })
36
+ }, () => {
37
+ $q.notify({
38
+ message: "Failed to copy",
39
+ color: "red",
40
+ })
41
+
42
+ })
43
+ }
44
+
28
45
 
29
46
  </script>
30
47
  <template>
@@ -37,18 +54,33 @@ if (my.twoFactorEnabled) {
37
54
  <p>
38
55
  For Android user, install
39
56
  <a type="primary" target="_blank"
40
- href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Authenticator</a>
57
+ href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Microsoft
58
+ Authenticator</a>
59
+
60
+ or
61
+ <a type="primary" target="_blank"
62
+ href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google
63
+ Authenticator</a>
64
+
41
65
  </p>
42
66
 
43
67
  <p>
44
68
  For iOS user, install
45
69
  <a type="primary" target="_blank"
46
- href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Authenticator</a>
70
+ href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Microsoft
71
+ Authenticator</a>
72
+ or
73
+ <a type="primary" target="_blank"
74
+ href="https://apps.apple.com/us/app/google-authenticator/id388497605">Google
75
+ Authenticator</a>
76
+
47
77
  </p>
48
78
  </div>
49
79
  <q-img :src="my2FA.image" width="250px" />
50
80
  <p>
51
- Secret : {{ my2FA.secret }}
81
+ Secret : <strong>{{ my2FA.secret }}</strong>
82
+
83
+ <q-btn flat round dense icon="sym_o_content_copy" @click="onCopy" />
52
84
  </p>
53
85
 
54
86
  <l-input v-model="obj.code" label="Code"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": {
6
6
  "type": "git",