@tapni/auth 0.0.168 → 1.0.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/dist/.vite/manifest.json +48 -10
- package/dist/Account-IR-XgmiM.js +153 -0
- package/dist/Apps-CQXLKu2F.js +112 -0
- package/dist/CustomApp-FxfYHVid.js +112 -0
- package/dist/General-BVjTsECb.js +477 -0
- package/dist/{QR-UQySwgoT.js → QR-B60f-H2Q.js} +11 -11
- package/dist/TapniAuth.es.js +1 -1
- package/dist/TapniAuth.umd.js +17 -17
- package/dist/index.css +193 -0
- package/dist/{install-KFv1Z6O7.js → install-BOPYSGGa.js} +3487 -3504
- package/dist/style.css +1 -1
- package/dist/{web-NrPZl3qD.js → web-XbruGdlD.js} +2 -5
- package/package.json +3 -3
- package/src/App.vue +6 -19
- package/src/components/{Language.vue → DELETE_Language.vue} +26 -16
- package/src/components/{LinkIcon.vue → DELETE_LinkIcon.vue} +1 -1
- package/src/components/{ModalOverlay.vue → DELETE_ModalOverlay.vue} +2 -2
- package/src/components/{OTP.vue → DELETE_OTP.vue} +3 -3
- package/src/main.js +1 -0
- package/src/mixins/DELETE_mfa-auth.mixin.js +53 -0
- package/src/mixins/auth.mixin.js +7 -1
- package/src/mixins/global.mixin.js +7 -0
- package/src/routes.js +27 -15
- package/src/store/auth.js +1 -1
- package/src/store/constants.js +2 -6
- package/src/store/locales/cn.js +1 -1
- package/src/store/locales/en.js +28 -3
- package/src/views/Account.vue +72 -110
- package/src/views/Apps.vue +106 -0
- package/src/views/CustomApp.vue +106 -0
- package/src/views/General.vue +192 -0
- package/src/views/Login.vue +27 -10
- package/src/views/QR.vue +1 -1
- package/src/views/Security.vue +322 -0
- package/src/views/Welcome.vue +10 -4
- package/dist/Account-uZVmDKkt.js +0 -113
- package/src/mixins/mfa-auth.mixin.js +0 -76
- package/src/views/MFA.vue +0 -117
- /package/dist/{web-L3jORB19.js → web-AXRKjAOB.js} +0 -0
- /package/dist/{web-5VtGcKeU.js → web-IFGkBi0t.js} +0 -0
- /package/dist/{web-AImUTDQQ.js → web-LIfHmYL2.js} +0 -0
package/src/views/Login.vue
CHANGED
|
@@ -80,9 +80,27 @@
|
|
|
80
80
|
/>
|
|
81
81
|
</em>
|
|
82
82
|
</div>
|
|
83
|
+
<div v-if="showOTP" class="page-login-field half-bottom">
|
|
84
|
+
<i style="padding-top: 15px">
|
|
85
|
+
<img
|
|
86
|
+
src="https://cdn.tapni.co/icons/padlock.png"
|
|
87
|
+
class="responsive-image"
|
|
88
|
+
style="width: 50%"
|
|
89
|
+
/>
|
|
90
|
+
</i>
|
|
91
|
+
<input
|
|
92
|
+
v-model="otpToken"
|
|
93
|
+
type="text"
|
|
94
|
+
:placeholder="ssoLang[this.appLanguage].otp_code"
|
|
95
|
+
name="otpToken"
|
|
96
|
+
required
|
|
97
|
+
minlength="6"
|
|
98
|
+
/>
|
|
99
|
+
<em></em>
|
|
100
|
+
</div>
|
|
83
101
|
<button
|
|
84
102
|
type="submit"
|
|
85
|
-
class="button black-button google-button bg-tapni-grey button-90 button-center uppercase bold full-top"
|
|
103
|
+
class="button black-button google-button bg-tapni-grey button-90 button-center uppercase bold full-top pointer"
|
|
86
104
|
>
|
|
87
105
|
<span v-if="!submitted">{{ ssoLang[appLanguage].login }}</span>
|
|
88
106
|
<span v-else class="button--loading button__loader"></span>
|
|
@@ -290,20 +308,12 @@ import MicrosoftMixin from "../mixins/microsoft.mixin";
|
|
|
290
308
|
import OktaMixin from "../mixins/okta.mixin";
|
|
291
309
|
import SamlMixin from "../mixins/saml.mixin";
|
|
292
310
|
import AuthMixin from "../mixins/auth.mixin";
|
|
293
|
-
import MFAMixin from "../mixins/mfa-auth.mixin";
|
|
294
311
|
import QRAuthMixin from "../mixins/qr-auth.mixin";
|
|
295
312
|
import { EventBus } from "../store/event-bus";
|
|
296
313
|
import to from "await-to-js";
|
|
297
314
|
export default {
|
|
298
315
|
name: "AuthLogin",
|
|
299
|
-
mixins: [GoogleMixin, FacebookMixin, AppleMixin, MicrosoftMixin, OktaMixin, SamlMixin, AuthMixin, QRAuthMixin
|
|
300
|
-
props: {
|
|
301
|
-
isModal: {
|
|
302
|
-
type: Boolean,
|
|
303
|
-
required: false,
|
|
304
|
-
default: false,
|
|
305
|
-
},
|
|
306
|
-
},
|
|
316
|
+
mixins: [GoogleMixin, FacebookMixin, AppleMixin, MicrosoftMixin, OktaMixin, SamlMixin, AuthMixin, QRAuthMixin],
|
|
307
317
|
data() {
|
|
308
318
|
return {
|
|
309
319
|
loading: true,
|
|
@@ -313,6 +323,9 @@ export default {
|
|
|
313
323
|
captcha: "",
|
|
314
324
|
revealPassword: false,
|
|
315
325
|
emailLogin: true,
|
|
326
|
+
|
|
327
|
+
otpToken: '',
|
|
328
|
+
showOTP: false
|
|
316
329
|
};
|
|
317
330
|
},
|
|
318
331
|
computed: {
|
|
@@ -342,6 +355,10 @@ export default {
|
|
|
342
355
|
}
|
|
343
356
|
}, 2500)
|
|
344
357
|
}
|
|
358
|
+
|
|
359
|
+
EventBus.$on("toggleOTPField", () => {
|
|
360
|
+
this.showOTP = !this.showOTP;
|
|
361
|
+
});
|
|
345
362
|
},
|
|
346
363
|
methods: {
|
|
347
364
|
async submit() {
|
package/src/views/QR.vue
CHANGED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="page-login content-boxed content-boxed-padding">
|
|
3
|
+
<a v-if="isModal" @click="close" class="color-black pull-right pointer" style="margin-top: 0px; position: absolute; right: -20px; text-align: right;">
|
|
4
|
+
<i class="font-17 color-black">
|
|
5
|
+
<img src="https://cdn.tapni.co/icons/down-arrow.png" class="responsive-image" style="width: 35%;"/>
|
|
6
|
+
</i>
|
|
7
|
+
</a>
|
|
8
|
+
<div class="subheaderContainer full-top">
|
|
9
|
+
<!-- Back Button -->
|
|
10
|
+
<router-link to="/account" class="button gray-button pointer left-button">
|
|
11
|
+
<img
|
|
12
|
+
:src="getIcon('arrow-gray-right.svg')"
|
|
13
|
+
height="20"
|
|
14
|
+
width="20"
|
|
15
|
+
class="btn-icon"
|
|
16
|
+
style="rotate: 180deg;"
|
|
17
|
+
/>
|
|
18
|
+
</router-link>
|
|
19
|
+
|
|
20
|
+
<!-- Centered Text -->
|
|
21
|
+
<h2 class="center-text" style="flex-grow: 1; text-align: center; margin: 0; font-weight: 600;">
|
|
22
|
+
{{ssoLang[appLanguage].security }}
|
|
23
|
+
</h2>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="container center-text">
|
|
27
|
+
<p>{{ssoLang[appLanguage].security_p }}</p>
|
|
28
|
+
|
|
29
|
+
<div class="full-top">
|
|
30
|
+
<!-- MFA -->
|
|
31
|
+
<div class="settingRow">
|
|
32
|
+
<div class="firstRow">
|
|
33
|
+
<h4>{{ssoLang[appLanguage].mfa_auth }}</h4>
|
|
34
|
+
|
|
35
|
+
<div class="ios-switch" style="display: inline-block">
|
|
36
|
+
<input
|
|
37
|
+
type="checkbox"
|
|
38
|
+
name="ios-switch"
|
|
39
|
+
class="ios-switch-checkbox"
|
|
40
|
+
:id="'mfa-open-switch'"
|
|
41
|
+
v-model="mfaEnable"
|
|
42
|
+
/>
|
|
43
|
+
<label class="ios-switch-label" :for="'mfa-open-switch'"></label>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div v-show="mfaEnable && !account.mfaEnabled" class="center-text half-top">
|
|
48
|
+
<div id="qrCodeContainer"
|
|
49
|
+
class="qrCodeRounded"
|
|
50
|
+
style="max-width: 100%;"/>
|
|
51
|
+
<br>
|
|
52
|
+
<div class="settingRow" @click="copy(otpSecret)">
|
|
53
|
+
<div class="firstRow">
|
|
54
|
+
<h4 class="center-text no-margin">{{ otpSecret }}</h4>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="margin-center left-text padding-left small-top">
|
|
58
|
+
<p class="">{{ssoLang[appLanguage].mfa_auth_qr }}</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<form @submit.prevent="validateMFA" v-if="account.mfaEnabled !== mfaEnable" class="half-top">
|
|
62
|
+
<div>
|
|
63
|
+
<input
|
|
64
|
+
type="text"
|
|
65
|
+
v-model="otp"
|
|
66
|
+
:placeholder="ssoLang[appLanguage].otp_code"
|
|
67
|
+
class="edit-input h-40 lh-40"
|
|
68
|
+
style="margin: 0 auto; height: 25px; width: 100%;"
|
|
69
|
+
required
|
|
70
|
+
@keydown.space.prevent
|
|
71
|
+
/>
|
|
72
|
+
<p class="small-top full-bottom padding-left left-text" v-html="ssoLang[appLanguage].otp_subtitle"></p>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<button
|
|
76
|
+
type="submit"
|
|
77
|
+
class="button black-button google-button bg-tapni-grey button-90 button-center uppercase bold full-top pointer"
|
|
78
|
+
>
|
|
79
|
+
<span v-if="!loading">{{ ssoLang[appLanguage].continue }}</span>
|
|
80
|
+
<span v-else class="button--loading button__loader"></span>
|
|
81
|
+
</button>
|
|
82
|
+
|
|
83
|
+
<p class="close-text center-text half-top">
|
|
84
|
+
<span v-html="ssoLang[appLanguage].otp_p1"></span>
|
|
85
|
+
<a href="mailto:support@tapni.com?subject=MFA Authentication Problem"> support@tapni.com</a>
|
|
86
|
+
</p>
|
|
87
|
+
</form>
|
|
88
|
+
<div v-else class="margin-center small-top" style="width: 100%;">
|
|
89
|
+
<div class="left-text">
|
|
90
|
+
<p v-if="mfaEnable">
|
|
91
|
+
{{ssoLang[appLanguage].mfa_auth_enabled }}
|
|
92
|
+
</p>
|
|
93
|
+
<p v-else>
|
|
94
|
+
{{ssoLang[appLanguage].mfa_auth_p }}
|
|
95
|
+
</p>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- Password -->
|
|
100
|
+
<div class="settingRow full-top" @click="changePassword = !changePassword">
|
|
101
|
+
<div class="firstRow">
|
|
102
|
+
<h4>{{ssoLang[appLanguage].change_password }}</h4>
|
|
103
|
+
|
|
104
|
+
<img class="transition-icon" :class="{ 'rotate-icon': !!changePassword }" :src="getIcon('arrow-gray-down.svg')" />
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<form v-show="changePassword" class="center-text half-top">
|
|
108
|
+
<form @submit.prevent="submitChangePassword">
|
|
109
|
+
<input type="password" v-model="currentPassword" :placeholder="ssoLang[appLanguage].password_current_p"
|
|
110
|
+
class="edit-input h-40 lh-40" required minlength="8" style="width: 100%"/>
|
|
111
|
+
<p class="small-text small-top-padding small-bottom">{{ssoLang[appLanguage].password_current}}</p>
|
|
112
|
+
|
|
113
|
+
<input type="password" v-model="password" :placeholder="ssoLang[appLanguage].password_new_p"
|
|
114
|
+
class="bg-white edit-input h-40 lh-40" required minlength="8" style="width: 100%"/>
|
|
115
|
+
<p class="small-text small-top-padding small-bottom">{{ssoLang[appLanguage].password_new}}</p>
|
|
116
|
+
|
|
117
|
+
<input type="password" v-model="passwordRepeat" :placeholder="ssoLang[appLanguage].password_new_repeat_p"
|
|
118
|
+
class="edit-input h-40 lh-40" required minlength="8" style="width: 100%"/>
|
|
119
|
+
<p class="small-text small-top-padding small-bottom">{{ssoLang[appLanguage].password_new_repeat}}</p>
|
|
120
|
+
|
|
121
|
+
<button
|
|
122
|
+
type="submit"
|
|
123
|
+
class="button black-button google-button bg-tapni-grey button-90 button-center uppercase bold full-top pointer"
|
|
124
|
+
>
|
|
125
|
+
<span v-if="!loading">{{ ssoLang[appLanguage].password_update }}</span>
|
|
126
|
+
<span v-else class="button--loading button__loader"></span>
|
|
127
|
+
</button>
|
|
128
|
+
|
|
129
|
+
<p class="center-text font-13 half-top half-bottom">
|
|
130
|
+
<span v-html="ssoLang[appLanguage].password_reset"></span>
|
|
131
|
+
<router-link to="/reset" exact class="color-black">{{ssoLang[appLanguage].by_clicking_here}}</router-link>
|
|
132
|
+
</p>
|
|
133
|
+
</form>
|
|
134
|
+
</form>
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
<!-- Delete Account -->
|
|
138
|
+
<div class="settingRow full-top" @click="accountDelete = !accountDelete">
|
|
139
|
+
<div class="firstRow">
|
|
140
|
+
<h4 class="red-text">{{ssoLang[appLanguage].delete_account }}</h4>
|
|
141
|
+
|
|
142
|
+
<img class="transition-icon" :class="{ 'rotate-icon': !!accountDelete }" :src="getIcon('arrow-gray-down.svg')" />
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div v-show="accountDelete" class="center-text half-top">
|
|
146
|
+
|
|
147
|
+
<!-- Active Account -->
|
|
148
|
+
<div class="settingRow full-top">
|
|
149
|
+
<div class="firstRow">
|
|
150
|
+
<h4>{{ssoLang[appLanguage].active_account }}</h4>
|
|
151
|
+
|
|
152
|
+
<div class="ios-switch" style="display: inline-block">
|
|
153
|
+
<input
|
|
154
|
+
type="checkbox"
|
|
155
|
+
name="ios-switch"
|
|
156
|
+
class="ios-switch-checkbox"
|
|
157
|
+
:id="'active-open-switch'"
|
|
158
|
+
v-model="account.is_active"
|
|
159
|
+
/>
|
|
160
|
+
<label class="ios-switch-label" :for="'active-open-switch'"></label>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
<p class="left-text small-top">{{ssoLang[appLanguage].active_account_p }}</p>
|
|
165
|
+
|
|
166
|
+
<!-- Delete Account -->
|
|
167
|
+
<form @submit.prevent="deleteAccountSubmit">
|
|
168
|
+
<button
|
|
169
|
+
type="submit"
|
|
170
|
+
class="button black-button button-full google-button bg-tapni-grey button-90 button-center uppercase bold full-top pointer"
|
|
171
|
+
>
|
|
172
|
+
<span v-if="!loading">{{ ssoLang[appLanguage].permanent_delete }}</span>
|
|
173
|
+
<span v-else class="button--loading button__loader"></span>
|
|
174
|
+
</button>
|
|
175
|
+
<p class="small-bottom red-text">{{ssoLang[appLanguage].permanent_delete_p}}</p>
|
|
176
|
+
</form>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</template>
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
<script>
|
|
185
|
+
import AuthMixin from "../mixins/auth.mixin";
|
|
186
|
+
import AuthService from '../services/AuthService'
|
|
187
|
+
import to from "await-to-js";
|
|
188
|
+
import {EventBus} from "@/store/event-bus.js";
|
|
189
|
+
import {authenticator} from "@otplib/preset-browser";
|
|
190
|
+
import QRCodeStyling from "qr-code-styling";
|
|
191
|
+
|
|
192
|
+
export default {
|
|
193
|
+
name: "AuthSecurity",
|
|
194
|
+
mixins: [AuthMixin],
|
|
195
|
+
props: {
|
|
196
|
+
payload: {
|
|
197
|
+
type: Object,
|
|
198
|
+
default: {}
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
data () {
|
|
202
|
+
return {
|
|
203
|
+
accountDelete: false,
|
|
204
|
+
|
|
205
|
+
changePassword: false,
|
|
206
|
+
password: '',
|
|
207
|
+
passwordRepeat: '',
|
|
208
|
+
currentPassword: '',
|
|
209
|
+
|
|
210
|
+
otpSecret: null,
|
|
211
|
+
mfaEnable: false,
|
|
212
|
+
qrCodeHash: null,
|
|
213
|
+
qrCodeRefreshInterval: null,
|
|
214
|
+
poolingInterval: null,
|
|
215
|
+
loading: false,
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
async mounted() {
|
|
219
|
+
if (!this.isLoggedIn) this.$router.push('/login');
|
|
220
|
+
|
|
221
|
+
if (this.renderView === 'AuthSecurity') {
|
|
222
|
+
await this.getAccountSettings();
|
|
223
|
+
this.generateOTPQrCode();
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
methods: {
|
|
227
|
+
close () {
|
|
228
|
+
EventBus.$emit('ssoEvent', {name: 'toggleAuthModal', data: true})
|
|
229
|
+
},
|
|
230
|
+
async deleteAccountSubmit() {
|
|
231
|
+
const result = await this.deleteAccount();
|
|
232
|
+
if (result === true) {
|
|
233
|
+
this.successSnack(this.ssoLang[this.appLanguage].profile_delete_account_success);
|
|
234
|
+
setTimeout(this.$store.dispatch("logout"), 1000);
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
generateOTPQrCode() {
|
|
238
|
+
console.log('Generating QR code');
|
|
239
|
+
const user = this.account.email;
|
|
240
|
+
|
|
241
|
+
if (this.account.mfaEnabled) {
|
|
242
|
+
this.mfaEnable = true;
|
|
243
|
+
} else {
|
|
244
|
+
const service = "Tapni";
|
|
245
|
+
|
|
246
|
+
const secret = authenticator.generateSecret();
|
|
247
|
+
this.otpSecret = secret;
|
|
248
|
+
|
|
249
|
+
const otpQR = authenticator.keyuri(user, service, secret);
|
|
250
|
+
|
|
251
|
+
const otpQrCode = new QRCodeStyling({
|
|
252
|
+
width: 200,
|
|
253
|
+
height: 200,
|
|
254
|
+
data: otpQR,
|
|
255
|
+
});
|
|
256
|
+
otpQrCode.append(document.getElementById("qrCodeContainer"));
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
async cancelMFA() {
|
|
260
|
+
if (import.meta.env.VITE_APP_MODE === 'npm') {
|
|
261
|
+
EventBus.$emit('ssoEvent', {name: 'mfaCancel', data: true})
|
|
262
|
+
} else {
|
|
263
|
+
this.$router.push('/account');
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
async validateMFA() {
|
|
267
|
+
if (!this.otp || this.otp.length !== 6) {
|
|
268
|
+
return this.errorSnack(this.ssoLang[this.appLanguage].invalid_code)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.loading = true;
|
|
272
|
+
|
|
273
|
+
let data = {
|
|
274
|
+
otpToken: this.otp,
|
|
275
|
+
otpSecret: this.otpSecret,
|
|
276
|
+
enable: this.mfaEnable,
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
if (!this.mfaEnable) {
|
|
280
|
+
delete data.otpSecret;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const [err, response] = await to(AuthService.setMfa(data, this.$storex))
|
|
284
|
+
if (err) {
|
|
285
|
+
EventBus.$emit('ssoEvent', {name: 'setLoading', data: false})
|
|
286
|
+
return this.errorHandler(err)
|
|
287
|
+
}
|
|
288
|
+
if (response.data.success) {
|
|
289
|
+
this.getAccountSettings();
|
|
290
|
+
this.successSnack(response.data.message);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.loading = false;
|
|
294
|
+
},
|
|
295
|
+
async submitChangePassword () {
|
|
296
|
+
if (this.password.length < 8) return this.errorSnack(this.ssoLang[this.appLanguage].password_8_chars)
|
|
297
|
+
if (this.password !== this.passwordRepeat) return this.errorSnack(this.ssoLang[this.appLanguage].password_not_match)
|
|
298
|
+
|
|
299
|
+
const result = await this.newPassword({
|
|
300
|
+
currentPassword: this.currentPassword,
|
|
301
|
+
password: this.password,
|
|
302
|
+
passwordRepeat: this.passwordRepeat
|
|
303
|
+
})
|
|
304
|
+
if (result === true) {
|
|
305
|
+
this.successSnack(this.ssoLang[this.appLanguage].password_change_success)
|
|
306
|
+
this.changePassword = false;
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
</script>
|
|
312
|
+
|
|
313
|
+
<style scoped>
|
|
314
|
+
.firstRow img {
|
|
315
|
+
width: 25px;
|
|
316
|
+
height: 25px;
|
|
317
|
+
position: absolute;
|
|
318
|
+
top: 50%;
|
|
319
|
+
right: 0;
|
|
320
|
+
transform: translate(-50%, -50%);
|
|
321
|
+
}
|
|
322
|
+
</style>
|
package/src/views/Welcome.vue
CHANGED
|
@@ -17,10 +17,16 @@
|
|
|
17
17
|
Test
|
|
18
18
|
</button>
|
|
19
19
|
-->
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
<div class="page-login-links center-text">
|
|
21
|
+
<router-link to="/login">{{ssoLang[this.appLanguage].already_registered}}? <b>{{ssoLang[this.appLanguage].sign_in}}</b></router-link>
|
|
22
|
+
<div class="clear"></div>
|
|
23
|
+
</div>
|
|
24
|
+
<a v-if="display === 'redirect'"
|
|
25
|
+
@click="toggleSSOLanguageModal"
|
|
26
|
+
class="font-18 no-border pointer color-black"
|
|
27
|
+
style="position: absolute; right: 20px; top: -10px; z-index: 1;">
|
|
28
|
+
<span class="lang-icon">{{ appLanguage.toUpperCase() }}</span>
|
|
29
|
+
</a>
|
|
24
30
|
<div v-if=(!this.isNative) style="display: flex; flex-direction: row; justify-content: space-around; width: 90%; margin: 0 auto; margin-top: 40px;" >
|
|
25
31
|
<a href="https://play.google.com/store/apps/details?id=co.tapni.app" target="_blank"><img src="https://cdn.tapni.co/images/playstore.png" class="app-store-icon pointer" style="width:55px"/></a>
|
|
26
32
|
<a href="https://apps.apple.com/ag/app/tapni/id1552930233" target="_blank"><img src="https://cdn.tapni.co/images/appstore.png" class="app-store-icon pointer" style="width:55px"/></a>
|
package/dist/Account-uZVmDKkt.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { _ as l, A as d, E as r } from "./install-KFv1Z6O7.js";
|
|
2
|
-
import { openBlock as g, createElementBlock as u, createElementVNode as t, toDisplayString as i, createCommentVNode as a, pushScopeId as p, popScopeId as _ } from "vue";
|
|
3
|
-
var h = { VITE_APP_MODE: "npm", VITE_APP_APP_ROOT: "https://t.link", VITE_APP_API_ROOT: "https://api.tapni.co", VITE_APP_GOOGLE_RECAPTCHA_SITE_KEY: "6LenkC0mAAAAADWBxPOhpmwXCwzCJd7cilNgtOLk", VITE_APP_SSO_ID: "9cd47053-080a-4df8-8fd8-ca4389163fde", VITE_APP_POPUP_LOGIN_ALLOWED_ORIGIN: "https://auth.tapni.com", BASE_URL: "/", MODE: "production", DEV: !1, PROD: !0, SSR: !1 };
|
|
4
|
-
const m = {
|
|
5
|
-
mixins: [d],
|
|
6
|
-
data() {
|
|
7
|
-
return {
|
|
8
|
-
expanded: !1,
|
|
9
|
-
addAccountReady: !1,
|
|
10
|
-
appVersion: h.APP_VERSION
|
|
11
|
-
};
|
|
12
|
-
},
|
|
13
|
-
async mounted() {
|
|
14
|
-
if (!this.isLoggedIn)
|
|
15
|
-
return this.$router.push("/");
|
|
16
|
-
this.getAccountSettings();
|
|
17
|
-
},
|
|
18
|
-
methods: {
|
|
19
|
-
continueTo(e) {
|
|
20
|
-
console.log("continue to " + e);
|
|
21
|
-
},
|
|
22
|
-
addAccount() {
|
|
23
|
-
this.$router.push("/login");
|
|
24
|
-
},
|
|
25
|
-
switchAccount(e) {
|
|
26
|
-
console.log("switch", e);
|
|
27
|
-
},
|
|
28
|
-
toggleAccountSettingsModal() {
|
|
29
|
-
this.$router.push("/mfa");
|
|
30
|
-
},
|
|
31
|
-
toggleLanguageModal() {
|
|
32
|
-
r.$emit("toggleSSOLanguageModal");
|
|
33
|
-
},
|
|
34
|
-
logoutAccount() {
|
|
35
|
-
this.logout({ refreshToken: this.refreshTokens[0], sendRequest: !0 });
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}, o = (e) => (p("data-v-992c1e64"), e = e(), _(), e), f = {
|
|
39
|
-
class: "page-login content-boxed content-boxed-padding center-text",
|
|
40
|
-
style: { "margin-top": "-1px", overflow: "hidden", border: "solid 0px #ffffff" }
|
|
41
|
-
}, v = /* @__PURE__ */ o(() => /* @__PURE__ */ t("br", null, null, -1)), A = { class: "bold full-top no-bottom center-text" }, E = { class: "full-bottom half-top center-text color-black font-16" };
|
|
42
|
-
const L = { class: "container" }, P = { class: "settingsCard pointer left-text" }, b = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "left" }, [
|
|
43
|
-
/* @__PURE__ */ t("img", {
|
|
44
|
-
src: "https://cdn.tapni.co/icons/newSettings.svg",
|
|
45
|
-
style: { width: "50px", "border-radius": "20px" }
|
|
46
|
-
})
|
|
47
|
-
], -1)), S = { class: "middle" }, k = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "right" }, [
|
|
48
|
-
/* @__PURE__ */ t("img", { src: "https://cdn.tapni.co/icons/newArrowRight.svg" })
|
|
49
|
-
], -1)), w = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "divider" }, null, -1)), x = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "left" }, [
|
|
50
|
-
/* @__PURE__ */ t("img", {
|
|
51
|
-
src: "https://cdn.tapni.co/icons/newPublicProfile.svg",
|
|
52
|
-
style: { width: "50px", "border-radius": "20px" }
|
|
53
|
-
})
|
|
54
|
-
], -1)), I = { class: "middle" }, O = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "right" }, [
|
|
55
|
-
/* @__PURE__ */ t("img", { src: "https://cdn.tapni.co/icons/newArrowRight.svg" })
|
|
56
|
-
], -1)), V = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "divider" }, null, -1)), T = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "left" }, [
|
|
57
|
-
/* @__PURE__ */ t("img", {
|
|
58
|
-
src: "https://cdn.tapni.co/icons/newLogout.svg",
|
|
59
|
-
style: { width: "50px", "border-radius": "20px" }
|
|
60
|
-
})
|
|
61
|
-
], -1)), N = { class: "middle" }, R = /* @__PURE__ */ o(() => /* @__PURE__ */ t("div", { class: "right" }, [
|
|
62
|
-
/* @__PURE__ */ t("img", { src: "https://cdn.tapni.co/icons/newArrowRight.svg" })
|
|
63
|
-
], -1));
|
|
64
|
-
function y(e, n, C, D, M, c) {
|
|
65
|
-
return g(), u("div", f, [
|
|
66
|
-
v,
|
|
67
|
-
t("h1", A, i(e.ssoLang[e.appLanguage].welcome), 1),
|
|
68
|
-
t("p", E, i(e.account.email), 1),
|
|
69
|
-
(e.display, a("", !0)),
|
|
70
|
-
t("div", L, [
|
|
71
|
-
a("", !0),
|
|
72
|
-
t("div", P, [
|
|
73
|
-
t("div", {
|
|
74
|
-
class: "device",
|
|
75
|
-
onClick: n[4] || (n[4] = (...s) => c.toggleAccountSettingsModal && c.toggleAccountSettingsModal(...s))
|
|
76
|
-
}, [
|
|
77
|
-
b,
|
|
78
|
-
t("div", S, [
|
|
79
|
-
t("h4", null, i(e.ssoLang[e.appLanguage].mfa), 1)
|
|
80
|
-
]),
|
|
81
|
-
k
|
|
82
|
-
]),
|
|
83
|
-
w,
|
|
84
|
-
t("div", {
|
|
85
|
-
class: "device",
|
|
86
|
-
onClick: n[5] || (n[5] = (...s) => c.toggleLanguageModal && c.toggleLanguageModal(...s))
|
|
87
|
-
}, [
|
|
88
|
-
x,
|
|
89
|
-
t("div", I, [
|
|
90
|
-
t("h4", null, i(e.ssoLang[e.appLanguage].change_language), 1)
|
|
91
|
-
]),
|
|
92
|
-
O
|
|
93
|
-
]),
|
|
94
|
-
V,
|
|
95
|
-
t("div", {
|
|
96
|
-
class: "device",
|
|
97
|
-
onClick: n[6] || (n[6] = (...s) => c.logoutAccount && c.logoutAccount(...s))
|
|
98
|
-
}, [
|
|
99
|
-
T,
|
|
100
|
-
t("div", N, [
|
|
101
|
-
t("h4", null, i(e.ssoLang[e.appLanguage].logout), 1)
|
|
102
|
-
]),
|
|
103
|
-
R
|
|
104
|
-
]),
|
|
105
|
-
a("", !0)
|
|
106
|
-
])
|
|
107
|
-
])
|
|
108
|
-
]);
|
|
109
|
-
}
|
|
110
|
-
const U = /* @__PURE__ */ l(m, [["render", y], ["__scopeId", "data-v-992c1e64"]]);
|
|
111
|
-
export {
|
|
112
|
-
U as default
|
|
113
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import QRCodeStyling from "qr-code-styling";
|
|
2
|
-
import { authenticator } from "@otplib/preset-browser";
|
|
3
|
-
import {EventBus} from "@/store/event-bus.js";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
data () {
|
|
7
|
-
return {
|
|
8
|
-
otpToken: null,
|
|
9
|
-
otpSecret: null,
|
|
10
|
-
mfaEnable: false,
|
|
11
|
-
qrCodeHash: null,
|
|
12
|
-
qrCodeRefreshInterval: null,
|
|
13
|
-
poolingInterval: null,
|
|
14
|
-
loading: false,
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
props: {
|
|
18
|
-
isModal: {
|
|
19
|
-
type: Boolean,
|
|
20
|
-
required: false,
|
|
21
|
-
default: false,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
computed: {
|
|
25
|
-
promptMFA () {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
async mounted () {
|
|
30
|
-
if (this.renderView === 'AuthMFA') {
|
|
31
|
-
await this.getAccountSettings();
|
|
32
|
-
this.generateOTPQrCode();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
EventBus.$on('otpSubmitted', this.otpSubmitted)
|
|
36
|
-
},
|
|
37
|
-
methods: {
|
|
38
|
-
otpSubmitted(code) {
|
|
39
|
-
this.otpToken = code;
|
|
40
|
-
|
|
41
|
-
// Assuming that the parent component had a method called submit
|
|
42
|
-
this.submit();
|
|
43
|
-
},
|
|
44
|
-
generateOTPQrCode() {
|
|
45
|
-
const user = this.account.email;
|
|
46
|
-
|
|
47
|
-
if (this.account.mfaEnabled) {
|
|
48
|
-
this.mfaEnable = true;
|
|
49
|
-
} else {
|
|
50
|
-
const service = "Tapni";
|
|
51
|
-
|
|
52
|
-
const secret = authenticator.generateSecret();
|
|
53
|
-
this.otpSecret = secret;
|
|
54
|
-
|
|
55
|
-
const otpQR = authenticator.keyuri(user, service, secret);
|
|
56
|
-
|
|
57
|
-
const otpQrCode = new QRCodeStyling({
|
|
58
|
-
width: 200,
|
|
59
|
-
height: 200,
|
|
60
|
-
data: otpQR,
|
|
61
|
-
});
|
|
62
|
-
otpQrCode.append(document.getElementById("qrCodeContainer"));
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
async cancelMFA() {
|
|
66
|
-
if (import.meta.env.VITE_APP_MODE === 'npm') {
|
|
67
|
-
EventBus.$emit('ssoEvent', {name: 'mfaCancel', data: true})
|
|
68
|
-
} else {
|
|
69
|
-
this.$router.push('/account');
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
async validateMFA() {
|
|
73
|
-
EventBus.$emit('toggleOTPModal', true);
|
|
74
|
-
},
|
|
75
|
-
}
|
|
76
|
-
}
|