feat: persist link share auth rule in url hash (#3336)
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/3336
This commit is contained in:
commit
da3eaf0d35
@ -56,11 +56,13 @@ import {useOnline} from '@/composables/useOnline'
|
|||||||
import {getAuthForRoute} from '@/router'
|
import {getAuthForRoute} from '@/router'
|
||||||
|
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const baseStore = useBaseStore()
|
const baseStore = useBaseStore()
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const ready = computed(() => baseStore.ready)
|
const ready = computed(() => baseStore.ready)
|
||||||
const online = useOnline()
|
const online = useOnline()
|
||||||
@ -72,7 +74,7 @@ async function load() {
|
|||||||
try {
|
try {
|
||||||
await baseStore.loadApp()
|
await baseStore.loadApp()
|
||||||
baseStore.setReady(true)
|
baseStore.setReady(true)
|
||||||
const redirectTo = await getAuthForRoute(route)
|
const redirectTo = await getAuthForRoute(route, authStore)
|
||||||
if (typeof redirectTo !== 'undefined') {
|
if (typeof redirectTo !== 'undefined') {
|
||||||
await router.push(redirectTo)
|
await router.push(redirectTo)
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,31 @@ export function useRedirectToLastVisited() {
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
function redirectIfSaved() {
|
function getLastVisitedRoute() {
|
||||||
const last = getLastVisited()
|
const last = getLastVisited()
|
||||||
if (last !== null) {
|
if (last === null) {
|
||||||
router.push({
|
return null
|
||||||
name: last.name,
|
|
||||||
params: last.params,
|
|
||||||
query: last.query,
|
|
||||||
})
|
|
||||||
clearLastVisited()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
router.push({name: 'home'})
|
clearLastVisited()
|
||||||
|
return {
|
||||||
|
name: last.name,
|
||||||
|
params: last.params,
|
||||||
|
query: last.query,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectIfSaved() {
|
||||||
|
const lastRoute = getLastVisitedRoute()
|
||||||
|
if (!lastRoute) {
|
||||||
|
return router.push({name: 'home'})
|
||||||
|
}
|
||||||
|
|
||||||
|
return router.push(lastRoute)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
redirectIfSaved,
|
redirectIfSaved,
|
||||||
|
getLastVisitedRoute,
|
||||||
}
|
}
|
||||||
}
|
}
|
1
src/constants/linkShareHash.ts
Normal file
1
src/constants/linkShareHash.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const LINK_SHARE_HASH_PREFIX = '#share-auth-token='
|
@ -6,6 +6,7 @@ import {saveProjectView, getProjectView} from '@/helpers/projectView'
|
|||||||
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
|
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
|
||||||
import {getNextWeekDate} from '@/helpers/time/getNextWeekDate'
|
import {getNextWeekDate} from '@/helpers/time/getNextWeekDate'
|
||||||
import {setTitle} from '@/helpers/setTitle'
|
import {setTitle} from '@/helpers/setTitle'
|
||||||
|
import {LINK_SHARE_HASH_PREFIX} from '@/constants/linkShareHash'
|
||||||
|
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
@ -80,7 +81,7 @@ const router = createRouter({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to anchor should still work
|
// Scroll to anchor should still work
|
||||||
if (to.hash) {
|
if (to.hash && !to.hash.startsWith(LINK_SHARE_HASH_PREFIX)) {
|
||||||
return {el: to.hash}
|
return {el: to.hash}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,8 +443,7 @@ const router = createRouter({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
export async function getAuthForRoute(route: RouteLocation) {
|
export async function getAuthForRoute(to: RouteLocation, authStore) {
|
||||||
const authStore = useAuthStore()
|
|
||||||
if (authStore.authUser || authStore.authLinkShare) {
|
if (authStore.authUser || authStore.authLinkShare) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -464,26 +464,52 @@ export async function getAuthForRoute(route: RouteLocation) {
|
|||||||
'user.register',
|
'user.register',
|
||||||
'link-share.auth',
|
'link-share.auth',
|
||||||
'openid.auth',
|
'openid.auth',
|
||||||
].includes(route.name as string) &&
|
].includes(to.name as string) &&
|
||||||
localStorage.getItem('passwordResetToken') === null &&
|
localStorage.getItem('passwordResetToken') === null &&
|
||||||
localStorage.getItem('emailConfirmToken') === null &&
|
localStorage.getItem('emailConfirmToken') === null &&
|
||||||
!(route.name === 'home' && (typeof route.query.userPasswordReset !== 'undefined' || typeof route.query.userEmailConfirm !== 'undefined'))
|
!(to.name === 'home' && (typeof to.query.userPasswordReset !== 'undefined' || typeof to.query.userEmailConfirm !== 'undefined'))
|
||||||
) {
|
) {
|
||||||
saveLastVisited(route.name as string, route.params, route.query)
|
saveLastVisited(to.name as string, to.params, to.query)
|
||||||
return {name: 'user.login'}
|
return {name: 'user.login'}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(localStorage.getItem('passwordResetToken') !== null && route.name !== 'user.password-reset.reset') {
|
if(localStorage.getItem('passwordResetToken') !== null && to.name !== 'user.password-reset.reset') {
|
||||||
return {name: 'user.password-reset.reset'}
|
return {name: 'user.password-reset.reset'}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(localStorage.getItem('emailConfirmToken') !== null && route.name !== 'user.login') {
|
if(localStorage.getItem('emailConfirmToken') !== null && to.name !== 'user.login') {
|
||||||
return {name: 'user.login'}
|
return {name: 'user.login'}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.beforeEach(async (to) => {
|
router.beforeEach(async (to, from) => {
|
||||||
return getAuthForRoute(to)
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
|
if(from.hash && from.hash.startsWith(LINK_SHARE_HASH_PREFIX)) {
|
||||||
|
to.hash = from.hash
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to.hash.startsWith(LINK_SHARE_HASH_PREFIX) && !authStore.authLinkShare) {
|
||||||
|
saveLastVisited(to.name as string, to.params, to.query)
|
||||||
|
return {
|
||||||
|
name: 'link-share.auth',
|
||||||
|
params: {
|
||||||
|
share: to.hash.replace(LINK_SHARE_HASH_PREFIX, ''),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newRoute = await getAuthForRoute(to, authStore)
|
||||||
|
if(newRoute) {
|
||||||
|
return {
|
||||||
|
...newRoute,
|
||||||
|
hash: to.hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!to.fullPath.endsWith(to.hash)) {
|
||||||
|
return to.fullPath + to.hash
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
@ -40,12 +40,15 @@ import {useTitle} from '@vueuse/core'
|
|||||||
|
|
||||||
import Message from '@/components/misc/message.vue'
|
import Message from '@/components/misc/message.vue'
|
||||||
import {PROJECT_VIEWS, type ProjectView} from '@/types/ProjectView'
|
import {PROJECT_VIEWS, type ProjectView} from '@/types/ProjectView'
|
||||||
|
import {LINK_SHARE_HASH_PREFIX} from '@/constants/linkShareHash'
|
||||||
|
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
import {useRedirectToLastVisited} from '@/composables/useRedirectToLastVisited'
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
useTitle(t('sharing.authenticating'))
|
useTitle(t('sharing.authenticating'))
|
||||||
|
const {getLastVisitedRoute} = useRedirectToLastVisited()
|
||||||
|
|
||||||
function useAuth() {
|
function useAuth() {
|
||||||
const baseStore = useBaseStore()
|
const baseStore = useBaseStore()
|
||||||
@ -87,7 +90,21 @@ function useAuth() {
|
|||||||
? route.query.view
|
? route.query.view
|
||||||
: 'list'
|
: 'list'
|
||||||
|
|
||||||
router.push({name: `project.${view}`, params: {projectId}})
|
const hash = LINK_SHARE_HASH_PREFIX + route.params.share
|
||||||
|
|
||||||
|
const last = getLastVisitedRoute()
|
||||||
|
if (last) {
|
||||||
|
return router.push({
|
||||||
|
...last,
|
||||||
|
hash,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return router.push({
|
||||||
|
name: `project.${view}`,
|
||||||
|
params: {projectId},
|
||||||
|
hash,
|
||||||
|
})
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e.response?.data?.code === 13001) {
|
if (e.response?.data?.code === 13001) {
|
||||||
authenticateWithPassword.value = true
|
authenticateWithPassword.value = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user