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
- useCookie('accessToken', {
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
- useCookie('accessToken', {
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 { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
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 IdAutoLogoutModal from '#adata-ui/components/modals/id/IdAutoLogoutModal.vue'
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
- useCookie('accessToken', {
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
- window.location.reload()
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
- useCookie('accessToken', {
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
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "adata-ui",
3
3
  "type": "module",
4
- "version": "2.1.40-beta.6",
4
+ "version": "2.1.40-beta.7",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground",