fix get resources after login
This commit is contained in:
1 parent
327f59104d
commit
9303a66aa8
9 files changed
+69
-12
No files matched your search
+26
-6
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useEventSource } from '@vueuse/core'
|
import { useEventSource } from '@vueuse/core'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed, onMounted, watch } from 'vue'
|
import { computed, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useStatusStore } from '@/stores/status.ts'
|
import { useStatusStore } from '@/stores/status.ts'
|
||||||
import { useIssueTypeStore } from '@/stores/issue-type.ts'
|
import { useIssueTypeStore } from '@/stores/issue-type.ts'
|
||||||
@@ -25,7 +25,7 @@ interface IssueSseEvent {
|
|||||||
type: string
|
type: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data, event } = useEventSource<string[], IssueSseEvent>(
|
const { event, open, close } = useEventSource<string[], IssueSseEvent>(
|
||||||
`${window.location.origin}/api/issues/events`,
|
`${window.location.origin}/api/issues/events`,
|
||||||
['issue.created', 'issue.updated', 'issue.deleted'],
|
['issue.created', 'issue.updated', 'issue.deleted'],
|
||||||
{
|
{
|
||||||
@@ -61,10 +61,30 @@ const layout = computed(() => {
|
|||||||
return layout ? `${layout}Layout` : 'DefaultLayout'
|
return layout ? `${layout}Layout` : 'DefaultLayout'
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
// Все эти ресурсы требуют авторизации: грузим при появлении сессии и чистим при выходе,
|
||||||
await Promise.all([statusStore.list(), issueTypeStore.list()])
|
// иначе запросы, ушедшие до логина, падают с 401 и больше не повторяются
|
||||||
await issueStore.getStat(currentProjectId.value)
|
watch(
|
||||||
})
|
() => session.value.data?.user.id,
|
||||||
|
async (userId) => {
|
||||||
|
if (!userId) {
|
||||||
|
close()
|
||||||
|
statusStore.reset()
|
||||||
|
issueTypeStore.reset()
|
||||||
|
issueStore.reset()
|
||||||
|
projectStore.reset()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
open()
|
||||||
|
try {
|
||||||
|
await Promise.all([statusStore.list(), issueTypeStore.list()])
|
||||||
|
await issueStore.getStat(currentProjectId.value)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load dictionaries', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { authClient } from '@/lib/auth-client.js'
|
import { authClient } from '@/lib/auth-client.js'
|
||||||
|
import { redirectTarget } from '@/lib/redirect.ts'
|
||||||
|
|
||||||
const REMEMBERED_EMAIL_KEY = 'rememberedEmail'
|
const REMEMBERED_EMAIL_KEY = 'rememberedEmail'
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const signInData = reactive({
|
const signInData = reactive({
|
||||||
email: localStorage.getItem(REMEMBERED_EMAIL_KEY) ?? '',
|
email: localStorage.getItem(REMEMBERED_EMAIL_KEY) ?? '',
|
||||||
@@ -25,6 +29,7 @@ const signIn = async () => {
|
|||||||
} else {
|
} else {
|
||||||
localStorage.removeItem(REMEMBERED_EMAIL_KEY)
|
localStorage.removeItem(REMEMBERED_EMAIL_KEY)
|
||||||
}
|
}
|
||||||
|
router.push(redirectTarget(route.query.redirect))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
import { authClient } from '@/lib/auth-client.js'
|
import { authClient } from '@/lib/auth-client.js'
|
||||||
import { useRouter } from 'vue-router'
|
import { redirectTarget } from '@/lib/redirect.ts'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
const REMEMBERED_EMAIL_KEY = 'rememberedEmail'
|
const REMEMBERED_EMAIL_KEY = 'rememberedEmail'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const otpError = ref('')
|
const otpError = ref('')
|
||||||
const signIn = reactive({
|
const signIn = reactive({
|
||||||
@@ -43,7 +45,7 @@ const checkOTP = async () => {
|
|||||||
email: signIn.email,
|
email: signIn.email,
|
||||||
otp: signIn.OTP,
|
otp: signIn.OTP,
|
||||||
})
|
})
|
||||||
if (data) router.push('/')
|
if (data) router.push(redirectTarget(route.query.redirect))
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.status === 400 && error.message) otpError.value = error.message
|
if (error.status === 400 && error.message) otpError.value = error.message
|
||||||
if (error.status === 403 && error.message) {
|
if (error.status === 403 && error.message) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const snackbarStore = useSnackbarStore()
|
|||||||
<v-snackbar-queue
|
<v-snackbar-queue
|
||||||
ref="queue"
|
ref="queue"
|
||||||
v-model="snackbarStore.snackbarQueue"
|
v-model="snackbarStore.snackbarQueue"
|
||||||
location="bottom end"
|
location="top end"
|
||||||
timeout="5000"
|
timeout="5000"
|
||||||
total-visible="5"
|
total-visible="5"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import type { LocationQueryValue } from 'vue-router'
|
||||||
|
|
||||||
|
/** Path to return to after sign-in; only same-origin paths are accepted to avoid open redirects */
|
||||||
|
export function redirectTarget(redirect: LocationQueryValue | LocationQueryValue[] | undefined): string {
|
||||||
|
const value = Array.isArray(redirect) ? redirect[0] : redirect
|
||||||
|
return value && value.startsWith('/') && !value.startsWith('//') ? value : '/'
|
||||||
|
}
|
||||||
@@ -9,5 +9,9 @@ export const useIssueTypeStore = defineStore('issueType', () => {
|
|||||||
issueTypes.value = await issueTypesList()
|
issueTypes.value = await issueTypesList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return { issueTypes, list }
|
function reset() {
|
||||||
|
issueTypes.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return { issueTypes, list, reset }
|
||||||
})
|
})
|
||||||
+8
-1
@@ -120,7 +120,14 @@ export const useIssueStore = defineStore('item', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { stats, dailyStats, list, calendar, getByKey, create, update, remove, getStat, getDailyStat }
|
function reset() {
|
||||||
|
issues.value = []
|
||||||
|
stats.value = undefined
|
||||||
|
dailyStats.value = undefined
|
||||||
|
error.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
return { stats, dailyStats, list, calendar, getByKey, create, update, remove, getStat, getDailyStat, reset }
|
||||||
})
|
})
|
||||||
|
|
||||||
/** Local YYYY-MM-DD `days` days before today */
|
/** Local YYYY-MM-DD `days` days before today */
|
||||||
|
|||||||
@@ -96,6 +96,13 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Clears loaded data on sign-out; the stored project id is kept and re-validated on next sign-in */
|
||||||
|
function reset() {
|
||||||
|
projects.value = []
|
||||||
|
current.value = null
|
||||||
|
error.value = null
|
||||||
|
}
|
||||||
|
|
||||||
async function restoreCurrent() {
|
async function restoreCurrent() {
|
||||||
const id = readStoredProjectId()
|
const id = readStoredProjectId()
|
||||||
if (!id) return
|
if (!id) return
|
||||||
@@ -118,5 +125,6 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
clearError,
|
clearError,
|
||||||
select,
|
select,
|
||||||
restoreCurrent,
|
restoreCurrent,
|
||||||
|
reset,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -9,5 +9,9 @@ export const useStatusStore = defineStore('counter', () => {
|
|||||||
statuses.value = await statusesList()
|
statuses.value = await statusesList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return { statuses, list }
|
function reset() {
|
||||||
|
statuses.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return { statuses, list, reset }
|
||||||
})
|
})
|
||||||
Reference in new issue
Block a user