adata-ui 2.1.40-beta.6 → 2.1.40-beta.7
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
3
2
|
import IdOtpInput from '#adata-ui/components/modals/id/IdOtpInput.vue'
|
|
3
|
+
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
4
|
+
import { writeAccessTokenCookie } from '#adata-ui/composables/useAccessTokenCookie'
|
|
4
5
|
|
|
5
6
|
const { $toast } = useNuxtApp()
|
|
6
7
|
const { t, locale } = useI18n()
|
|
@@ -40,17 +41,11 @@ async function loginUser() {
|
|
|
40
41
|
},
|
|
41
42
|
})
|
|
42
43
|
const { data: cookiesData } = await response.json()
|
|
43
|
-
if (cookiesData) {
|
|
44
|
+
if (cookiesData?.access_token) {
|
|
44
45
|
const { access_token, expire_in } = cookiesData
|
|
45
|
-
const hostname = location.hostname.split('.').reverse()
|
|
46
46
|
useCookie('autoLogout').value = true
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
maxAge: expire_in,
|
|
50
|
-
domain: `.${hostname[1]}.${hostname[0]}`,
|
|
51
|
-
path: '/',
|
|
52
|
-
secure: true,
|
|
53
|
-
}).value = access_token
|
|
48
|
+
await writeAccessTokenCookie(access_token, expire_in)
|
|
54
49
|
}
|
|
55
50
|
}
|
|
56
51
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
3
|
+
import { writeAccessTokenCookie } from '#adata-ui/composables/useAccessTokenCookie'
|
|
3
4
|
import { navigateToLocalizedPage } from '#adata-ui/utils/localizedNavigation'
|
|
4
5
|
import * as z from 'zod'
|
|
5
6
|
import { useUrls } from '#adata-ui/composables/useUrls'
|
|
@@ -127,17 +128,11 @@ async function submit() {
|
|
|
127
128
|
},
|
|
128
129
|
})
|
|
129
130
|
const { data: cookiesData } = await response.json()
|
|
130
|
-
if (cookiesData) {
|
|
131
|
+
if (cookiesData?.access_token) {
|
|
131
132
|
const { access_token, expire_in } = cookiesData
|
|
132
|
-
const hostname = location.hostname.split('.').reverse()
|
|
133
133
|
useCookie('autoLogout').value = true
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
maxAge: expire_in,
|
|
137
|
-
domain: COOKIE_DOMAIN,
|
|
138
|
-
path: '/',
|
|
139
|
-
secure: true,
|
|
140
|
-
}).value = access_token
|
|
135
|
+
await writeAccessTokenCookie(access_token, expire_in)
|
|
141
136
|
}
|
|
142
137
|
$toast.success(t('reuse.successfully'))
|
|
143
138
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import IdAutoLogoutModal from '#adata-ui/components/modals/id/IdAutoLogoutModal.vue'
|
|
3
3
|
import IdConfirmAccountOtpModal from '#adata-ui/components/modals/id/IdConfirmAccountOtpModal.vue'
|
|
4
4
|
import IdConfirmSuccessfulModal from '#adata-ui/components/modals/id/IdConfirmSuccessfulModal.vue'
|
|
5
5
|
import IdLoginModal from '#adata-ui/components/modals/id/IdLoginModal.vue'
|
|
@@ -9,7 +9,8 @@ import IdRecoveryModal from '#adata-ui/components/modals/id/IdRecoveryModal.vue'
|
|
|
9
9
|
import IdRegistrationModal from '#adata-ui/components/modals/id/IdRegistrationModal.vue'
|
|
10
10
|
import IdResetPasswordOtpModal from '#adata-ui/components/modals/id/IdResetPasswordOtpModal.vue'
|
|
11
11
|
import IdTwoFactorModal from '#adata-ui/components/modals/id/IdTwoFactorModal.vue'
|
|
12
|
-
import
|
|
12
|
+
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
13
|
+
import { writeAccessTokenCookie } from '#adata-ui/composables/useAccessTokenCookie'
|
|
13
14
|
|
|
14
15
|
const emit = defineEmits<{
|
|
15
16
|
(e: 'closed', value: boolean): void
|
|
@@ -35,6 +36,10 @@ const authApiURL = commonAuth.authApiURL
|
|
|
35
36
|
const accessToken = useCookie('accessToken')
|
|
36
37
|
const isAuthenticated = computed(() => !!accessToken.value)
|
|
37
38
|
|
|
39
|
+
// one-shot флаг: обмен по auth-сессии перезагружает страницу максимум один раз,
|
|
40
|
+
// иначе нечитаемая кука accessToken зацикливает reload
|
|
41
|
+
const AUTH_RELOAD_FLAG = 'auth-exchange-reloaded'
|
|
42
|
+
|
|
38
43
|
onMounted(async () => {
|
|
39
44
|
const response = await fetch(`${removeTrailingSlash(authApiURL)}/access/cookie`, {
|
|
40
45
|
method: 'GET',
|
|
@@ -46,17 +51,25 @@ onMounted(async () => {
|
|
|
46
51
|
const { data: cookiesData } = await response.json()
|
|
47
52
|
if (cookiesData?.access_token && !accessToken.value) {
|
|
48
53
|
const { access_token, expire_in } = cookiesData
|
|
49
|
-
const hostname = location.hostname.split('.').reverse()
|
|
50
54
|
useCookie('autoLogout').value = true
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
maxAge: expire_in,
|
|
54
|
-
domain: `.${hostname[1]}.${hostname[0]}`,
|
|
55
|
-
path: '/',
|
|
56
|
-
secure: true,
|
|
57
|
-
}).value = access_token
|
|
56
|
+
const persisted = await writeAccessTokenCookie(access_token, expire_in)
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
if (persisted && !sessionStorage.getItem(AUTH_RELOAD_FLAG)) {
|
|
59
|
+
sessionStorage.setItem(AUTH_RELOAD_FLAG, '1')
|
|
60
|
+
window.location.reload()
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
sessionStorage.removeItem(AUTH_RELOAD_FLAG)
|
|
64
|
+
console.warn(
|
|
65
|
+
persisted
|
|
66
|
+
? '[auth] accessToken cookie is erased between page loads (SSR resetTokens?), reload skipped to avoid a loop'
|
|
67
|
+
: '[auth] accessToken cookie was not persisted (domain/secure/maxAge rejected by browser), reload skipped',
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
sessionStorage.removeItem(AUTH_RELOAD_FLAG)
|
|
60
73
|
}
|
|
61
74
|
})
|
|
62
75
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
3
2
|
import IdOtpInput from '#adata-ui/components/modals/id/IdOtpInput.vue'
|
|
3
|
+
import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
|
|
4
|
+
import { writeAccessTokenCookie } from '#adata-ui/composables/useAccessTokenCookie'
|
|
4
5
|
import { useUrls } from '#adata-ui/composables/useUrls'
|
|
5
6
|
|
|
6
7
|
const { $toast } = useNuxtApp()
|
|
@@ -54,15 +55,9 @@ async function onConfirm() {
|
|
|
54
55
|
const { data: cookiesData } = await response.json()
|
|
55
56
|
if (cookiesData?.access_token) {
|
|
56
57
|
const { access_token, expire_in } = cookiesData
|
|
57
|
-
const hostname = location.hostname.split('.').reverse()
|
|
58
58
|
useCookie('autoLogout').value = true
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
maxAge: expire_in,
|
|
62
|
-
domain: `.${hostname[1]}.${hostname[0]}`,
|
|
63
|
-
path: '/',
|
|
64
|
-
secure: true,
|
|
65
|
-
}).value = access_token
|
|
60
|
+
await writeAccessTokenCookie(access_token, expire_in)
|
|
66
61
|
}
|
|
67
62
|
$toast.success(t('login.successfully'))
|
|
68
63
|
twoFactorModal.value = false
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useUrls } from '#adata-ui/composables/useUrls'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Единая точка записи куки accessToken (логин, 2FA, OTP, обмен по auth-сессии).
|
|
5
|
+
* Домен должен совпадать с доменом удаления в resetTokens (adata-common-auth),
|
|
6
|
+
* иначе кука не находится на следующей загрузке и логин-флоу зацикливается на reload.
|
|
7
|
+
*/
|
|
8
|
+
export async function writeAccessTokenCookie(accessToken: string, expireIn?: number): Promise<boolean> {
|
|
9
|
+
const { mode } = useUrls()
|
|
10
|
+
const sharedDomain = `${mode}.kz`
|
|
11
|
+
const onSharedDomain = location.hostname === sharedDomain || location.hostname.endsWith(`.${sharedDomain}`)
|
|
12
|
+
const maxAge = Number(expireIn) > 0 ? Number(expireIn) : undefined
|
|
13
|
+
|
|
14
|
+
useCookie('accessToken', {
|
|
15
|
+
maxAge,
|
|
16
|
+
// на localhost/превью-хостах атрибут domain невалиден — пишем host-only куку
|
|
17
|
+
domain: onSharedDomain ? `.${sharedDomain}` : undefined,
|
|
18
|
+
path: '/',
|
|
19
|
+
secure: location.protocol === 'https:',
|
|
20
|
+
}).value = accessToken
|
|
21
|
+
|
|
22
|
+
// useCookie пишет document.cookie на следующем flush, не синхронно
|
|
23
|
+
await nextTick()
|
|
24
|
+
return document.cookie.split('; ').some(part => part.startsWith('accessToken='))
|
|
25
|
+
}
|