adata-ui 2.1.40-beta.6 → 2.1.40-beta.8

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.
@@ -262,7 +262,7 @@ const layoutClass = computed(() => {
262
262
 
263
263
  const iconOffsetClass = computed(() => {
264
264
  if (!props.label) return ''
265
- return props.size === 'md' ? '-translate-y-[4px]' : '-translate-y-[2px]'
265
+ return props.size === 'md' ? '-translate-y-[7px]' : '-translate-y-[5px]'
266
266
  })
267
267
 
268
268
  const showClearButton = computed(() =>
@@ -308,11 +308,11 @@ function rowDisplay(item: T): unknown {
308
308
  >
309
309
  <div
310
310
  ref="fieldRef"
311
- class="input-v2__field text-deepblue-900 relative flex w-full cursor-text items-center gap-2 rounded-[10px] border border-solid pl-4 transition-colors duration-200 focus-within:border-blue-600 focus-within:ring-2 focus-within:ring-blue-600/20 hover:border-blue-500 dark:text-gray-200 dark:focus-within:border-blue-400 dark:focus-within:ring-blue-400/20 dark:hover:border-blue-400"
311
+ class="input-v2__field text-deepblue-900 relative flex w-full cursor-text items-center gap-2 rounded-[10px] border border-solid transition-colors duration-200 focus-within:border-blue-600 focus-within:ring-2 focus-within:ring-blue-600/20 hover:border-blue-500 dark:text-gray-200 dark:focus-within:border-blue-400 dark:focus-within:ring-blue-400/20 dark:hover:border-blue-400"
312
312
  :class="[
313
313
  layoutClass,
314
314
  fieldClass,
315
- startIcon ? 'pl-3' : '',
315
+ startIcon ? 'pl-3' : 'pl-4',
316
316
  clearable || endIcon || loading || $slots.endButton ? 'pr-3' : 'pr-4',
317
317
  { 'input-v2__field--error': hasError, 'input-v2__field--disabled': disabled },
318
318
  ]"
@@ -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.8",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground",