@hostlink/nuxt-light 1.58.0 → 1.59.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.58.0",
4
+ "version": "1.59.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -84,16 +84,28 @@ const submit = async () => {
84
84
  emits("login");
85
85
  } catch (e) {
86
86
  data.code = "";
87
- if (e.message == "two factor authentication code is required") {
87
+ const errorMessage = e instanceof Error ? e.message : String(e);
88
+ if (errorMessage == "setup_2fa_required") {
89
+ await $q.dialog({
90
+ component: resolveComponent("l-setup-2fa-dialog"),
91
+ componentProps: {
92
+ username: data.username,
93
+ password: data.password
94
+ },
95
+ persistent: true
96
+ });
97
+ return;
98
+ }
99
+ if (errorMessage == "two factor authentication code is required") {
88
100
  loginWithCode(data.username, data.password);
89
101
  return;
90
102
  }
91
- if (e.message == "password is expired") {
103
+ if (errorMessage == "password is expired") {
92
104
  passwordExpiredProcess(data.username, data.password);
93
105
  return;
94
106
  }
95
107
  $q.notify({
96
- message: e.message,
108
+ message: errorMessage,
97
109
  color: "negative",
98
110
  icon: "sym_o_error"
99
111
  });
@@ -264,8 +276,8 @@ const facebookLogin = (accessToken) => {
264
276
  <q-icon name="sym_o_lock" />
265
277
  </template>
266
278
  </l-input>
267
- <l-input color="primary" v-if="twoFactorAuthentication" v-model="data.code" label="2FA code"
268
- :rules="[(v) => !!v || $t('2FA code is required')]" type="text" clearable stackLabel :outlined="false">
279
+ <l-input color="primary" v-if="twoFactorAuthentication" v-model="data.code" label="2FA code" type="text"
280
+ clearable stackLabel :outlined="false">
269
281
  <template v-slot:prepend>
270
282
  <q-icon name="sym_o_key" />
271
283
  </template>
@@ -0,0 +1,13 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: import("vue").DefineComponent<{}, {
4
+ $emit: typeof __VLS_emit;
5
+ $props: Partial<typeof props>;
6
+ username: string;
7
+ password: string;
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
9
+ declare const __VLS_emit: (event: "hide" | "ok", ...args: any[]) => void;
10
+ declare const props: {
11
+ readonly username: string;
12
+ readonly password: string;
13
+ };
@@ -0,0 +1,94 @@
1
+ <script setup>
2
+ import { useDialogPluginComponent } from "quasar";
3
+ import { onMounted, q, m } from "#imports";
4
+ import { ref } from "vue";
5
+ import { useQuasar } from "quasar";
6
+ const $q = useQuasar();
7
+ const props = defineProps({
8
+ username: {
9
+ type: String,
10
+ required: true
11
+ },
12
+ password: {
13
+ type: String,
14
+ required: true
15
+ }
16
+ });
17
+ const secret = ref("");
18
+ const code = ref("");
19
+ defineEmits([
20
+ // REQUIRED; need to specify some events that your
21
+ // component will emit through useDialogPluginComponent()
22
+ ...useDialogPluginComponent.emits
23
+ ]);
24
+ const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
25
+ function onOKClick() {
26
+ m("updateTwoFactorAuthentication", {
27
+ username: props.username,
28
+ password: props.password,
29
+ secret: secret.value,
30
+ code: code.value
31
+ }).then(() => {
32
+ $q.notify({
33
+ type: "positive",
34
+ message: "Two-factor authentication has been successfully set up. Please use your authenticator app to log in."
35
+ });
36
+ onDialogOK();
37
+ }).catch((error) => {
38
+ $q.notify({
39
+ type: "negative",
40
+ message: error.message || "Failed to update two-factor authentication."
41
+ });
42
+ });
43
+ }
44
+ const image = ref("");
45
+ onMounted(async () => {
46
+ const { app } = await q({
47
+ app: {
48
+ generate2FASecret: {
49
+ __args: {
50
+ username: props.username
51
+ }
52
+ }
53
+ }
54
+ });
55
+ image.value = app.generate2FASecret.image;
56
+ secret.value = app.generate2FASecret.secret;
57
+ });
58
+ </script>
59
+
60
+ <template>
61
+ <q-dialog ref="dialogRef" @hide="onDialogHide">
62
+ <q-card class="q-dialog-plugin">
63
+
64
+ <q-card-section>
65
+ <div class="text-h6">Setup Two Factor Authentication</div>
66
+ <div>
67
+ To enhance the security of your account, please set up two-factor authentication (2FA) using an
68
+ authenticator app such as Google Authenticator or Microsoft Authenticator. Scan the QR code below
69
+ with your chosen app
70
+ to link it to your account.
71
+ </div>
72
+
73
+ <div class="q-mt-md q-mb-md flex flex-center" v-if="image">
74
+ <img :src="image" alt="2FA QR Code" />
75
+ </div>
76
+
77
+ <div>
78
+ <q-input label="Enter the 6-digit code from your authenticator app" type="text" v-model="code"
79
+ clearable stackLabel :outlined="false">
80
+ <template v-slot:prepend>
81
+ <q-icon name="sym_o_key" />
82
+ </template>
83
+ </q-input>
84
+ </div>
85
+
86
+ </q-card-section>
87
+
88
+ <q-card-actions align="right">
89
+ <q-btn color="primary" label="OK" @click="onOKClick" />
90
+ <q-btn color="primary" label="Cancel" @click="onDialogCancel" />
91
+ </q-card-actions>
92
+ </q-card>
93
+ </q-dialog>
94
+ </template>
@@ -0,0 +1,13 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: import("vue").DefineComponent<{}, {
4
+ $emit: typeof __VLS_emit;
5
+ $props: Partial<typeof props>;
6
+ username: string;
7
+ password: string;
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
9
+ declare const __VLS_emit: (event: "hide" | "ok", ...args: any[]) => void;
10
+ declare const props: {
11
+ readonly username: string;
12
+ readonly password: string;
13
+ };
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
2
  import { ref, reactive } from "vue";
3
3
  import { useQuasar } from "quasar";
4
- import { q, m } from "#imports";
4
+ import { q, m, navigateTo } from "#imports";
5
5
  const $q = useQuasar();
6
6
  const { my } = await q({
7
7
  my: {
@@ -85,8 +85,9 @@ const onCopy = async () => {
85
85
  <q-stepper v-model="currentStep" vertical color="primary" animated flat>
86
86
  <q-step :name="1" title="Download Authenticator App" icon="download" :done="currentStep > 1">
87
87
  <div class="q-mb-md">
88
- <p class="text-body1 q-mb-md">{{ $t('Choose and download an authenticator app for your device:') }}</p>
89
-
88
+ <p class="text-body1 q-mb-md">{{ $t('Choose and download an authenticator app for your device:')
89
+ }}</p>
90
+
90
91
  <!-- App Selection Cards -->
91
92
  <div class="row q-gutter-md q-mb-lg">
92
93
  <div class="col-12 col-md-5">
@@ -94,120 +95,69 @@ const onCopy = async () => {
94
95
  <q-card-section class="q-pa-md">
95
96
  <div class="text-h6 q-mb-sm">📱 Android</div>
96
97
  <div class="q-gutter-sm">
97
- <q-btn
98
- outline
99
- color="primary"
100
- size="sm"
101
- target="_blank"
98
+ <q-btn outline color="primary" size="sm" target="_blank"
102
99
  href="https://play.google.com/store/apps/details?id=com.azure.authenticator"
103
- label="Microsoft Authenticator"
104
- class="full-width"
105
- />
106
- <q-btn
107
- outline
108
- color="primary"
109
- size="sm"
110
- target="_blank"
100
+ label="Microsoft Authenticator" class="full-width" />
101
+ <q-btn outline color="primary" size="sm" target="_blank"
111
102
  href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"
112
- label="Google Authenticator"
113
- class="full-width"
114
- />
103
+ label="Google Authenticator" class="full-width" />
115
104
  </div>
116
105
  </q-card-section>
117
106
  </q-card>
118
107
  </div>
119
-
108
+
120
109
  <div class="col-12 col-md-5">
121
110
  <q-card flat bordered class="app-card">
122
111
  <q-card-section class="q-pa-md">
123
112
  <div class="text-h6 q-mb-sm">🍎 iOS</div>
124
113
  <div class="q-gutter-sm">
125
- <q-btn
126
- outline
127
- color="primary"
128
- size="sm"
129
- target="_blank"
114
+ <q-btn outline color="primary" size="sm" target="_blank"
130
115
  href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458"
131
- label="Microsoft Authenticator"
132
- class="full-width"
133
- />
134
- <q-btn
135
- outline
136
- color="primary"
137
- size="sm"
138
- target="_blank"
116
+ label="Microsoft Authenticator" class="full-width" />
117
+ <q-btn outline color="primary" size="sm" target="_blank"
139
118
  href="https://apps.apple.com/us/app/google-authenticator/id388497605"
140
- label="Google Authenticator"
141
- class="full-width"
142
- />
119
+ label="Google Authenticator" class="full-width" />
143
120
  </div>
144
121
  </q-card-section>
145
122
  </q-card>
146
123
  </div>
147
124
  </div>
148
125
 
149
- <q-btn
150
- color="primary"
151
- @click="currentStep = 2"
152
- :label="$t('I have installed the app')"
153
- icon-right="arrow_forward"
154
- />
126
+ <q-btn color="primary" @click="currentStep = 2" :label="$t('I have installed the app')"
127
+ icon-right="arrow_forward" />
155
128
  </div>
156
129
  </q-step>
157
130
 
158
131
  <q-step :name="2" title="Scan QR Code" icon="qr_code" :done="currentStep > 2">
159
132
  <div class="text-center q-mb-md">
160
133
  <p class="text-body1 q-mb-md">{{ $t('Scan this QR code with your authenticator app:') }}</p>
161
-
134
+
162
135
  <q-card flat bordered class="qr-card inline-block q-pa-lg">
163
136
  <q-img :src="my.my2FA.image" width="200px" class="q-mb-md" />
164
-
137
+
165
138
  <!-- Manual Entry Option -->
166
- <q-expansion-item
167
- icon="key"
168
- :label="$t('Enter manually instead')"
169
- class="text-left"
170
- >
139
+ <q-expansion-item icon="key" :label="$t('Enter manually instead')" class="text-left">
171
140
  <div class="q-pa-md bg-grey-1 rounded-borders">
172
141
  <div class="text-caption text-grey-7 q-mb-xs">{{ $t('Secret Key:') }}</div>
173
142
  <div class="row items-center q-gutter-sm">
174
143
  <div class="col">
175
- <q-input
176
- :model-value="secretVisible ? (my.my2FA?.secret || '') : '●'.repeat(my.my2FA?.secret?.length || 16)"
177
- readonly
178
- dense
179
- outlined
180
- class="secret-input"
181
- />
144
+ <q-input
145
+ :model-value="secretVisible ? (my.my2FA?.secret || '') : '●'.repeat(my.my2FA?.secret?.length || 16)"
146
+ readonly dense outlined class="secret-input" />
182
147
  </div>
183
- <q-btn
184
- flat
185
- round
186
- dense
187
- :icon="secretVisible ? 'visibility_off' : 'visibility'"
148
+ <q-btn flat round dense :icon="secretVisible ? 'visibility_off' : 'visibility'"
188
149
  @click="secretVisible = !secretVisible"
189
- :title="secretVisible ? $t('Hide') : $t('Show')"
190
- />
191
- <q-btn
192
- flat
193
- round
194
- dense
195
- icon="content_copy"
196
- @click="onCopy"
197
- :title="$t('Copy to clipboard')"
198
- />
150
+ :title="secretVisible ? $t('Hide') : $t('Show')" />
151
+ <q-btn flat round dense icon="content_copy" @click="onCopy"
152
+ :title="$t('Copy to clipboard')" />
199
153
  </div>
200
154
  </div>
201
155
  </q-expansion-item>
202
156
  </q-card>
203
157
 
204
158
  <div class="q-mt-md">
205
- <q-btn
206
- color="primary"
207
- @click="currentStep = 3"
208
- :label="$t('I have scanned the code')"
209
- icon-right="arrow_forward"
210
- />
159
+ <q-btn color="primary" @click="currentStep = 3" :label="$t('I have scanned the code')"
160
+ icon-right="arrow_forward" />
211
161
  </div>
212
162
  </div>
213
163
  </q-step>
@@ -217,21 +167,12 @@ const onCopy = async () => {
217
167
  <p class="text-body1 q-mb-md">
218
168
  {{ $t('Enter the 6-digit code from your authenticator app to complete setup:') }}
219
169
  </p>
220
-
170
+
221
171
  <div class="row justify-center q-mb-lg">
222
172
  <div class="col-12 col-sm-8 col-md-6">
223
- <q-input
224
- v-model="obj.code"
225
- :label="$t('Verification Code')"
226
- hint="6-digit code from your authenticator app"
227
- type="tel"
228
- inputmode="numeric"
229
- pattern="[0-9]*"
230
- outlined
231
- maxlength="6"
232
- class="text-center code-input"
233
- required
234
- >
173
+ <q-input v-model="obj.code" :label="$t('Verification Code')"
174
+ hint="6-digit code from your authenticator app" type="tel" inputmode="numeric"
175
+ pattern="[0-9]*" outlined maxlength="6" class="text-center code-input" required>
235
176
  <template v-slot:prepend>
236
177
  <q-icon name="security" />
237
178
  </template>
@@ -240,14 +181,8 @@ const onCopy = async () => {
240
181
  </div>
241
182
 
242
183
  <div class="text-center">
243
- <q-btn
244
- @click="save"
245
- color="positive"
246
- size="lg"
247
- :label="$t('Complete Setup')"
248
- icon="check_circle"
249
- :loading="loading"
250
- />
184
+ <q-btn @click="save" color="positive" size="lg" :label="$t('Complete Setup')"
185
+ icon="check_circle" :loading="loading" />
251
186
  </div>
252
187
  </div>
253
188
  </q-step>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "1.58.0",
3
+ "version": "1.59.0",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": {
6
6
  "type": "git",