1
0
Fork 0

Compare commits

...

11 Commits

Author SHA1 Message Date
kolaente e3e4b8a563
fix: follow the happy path 2023-04-11 18:40:22 +02:00
kolaente 367459edd2
feat: change the link share hash name 2023-04-04 11:35:45 +02:00
kolaente 2d66393874
feat: check link share auth from store instead 2023-04-01 17:56:30 +02:00
kolaente 007282b758
chore: follow the happy path 2023-04-01 17:16:51 +02:00
kolaente 56396643dd
chore: move const 2023-04-01 15:17:09 +02:00
kolaente e8cb7c1083
chore: reduce nesting 2023-04-01 14:19:28 +02:00
kolaente a7fdec956f
fix: return redirect 2023-04-01 14:18:38 +02:00
kolaente 90d54bdae8
feat: rename link share hash prefix 2023-04-01 14:17:05 +02:00
kolaente c21587d779
chore: import const instead of redeclaring it 2023-04-01 14:15:54 +02:00
kolaente 6bf378ec90
chore: rename getRedirectRoute 2023-04-01 14:12:47 +02:00
kolaente 9c81a57791
feat: persist link share auth rule in url hash
This allows sharing links to a task directly. We're using hashes instead
of query parameters because hash values are usually not logged in access
logs.

With this change, when a user uses a link share, the link share hash
will be appended to all urls while browsing. When a link share hash is
encountered in the current url and the user is not authenticated, they
will be redirected to the link share auth page, get authenticated and
then get redirected to whatever url they were previously on.
2023-04-01 12:15:02 +02:00
5 changed files with 77 additions and 22 deletions

View File

@ -56,11 +56,13 @@ import {useOnline} from '@/composables/useOnline'
import {getAuthForRoute} from '@/router'
import {useBaseStore} from '@/stores/base'
import {useAuthStore} from '@/stores/auth'
const router = useRouter()
const route = useRoute()
const baseStore = useBaseStore()
const authStore = useAuthStore()
const ready = computed(() => baseStore.ready)
const online = useOnline()
@ -72,7 +74,7 @@ async function load() {
try {
await baseStore.loadApp()
baseStore.setReady(true)
const redirectTo = await getAuthForRoute(route)
const redirectTo = await getAuthForRoute(route, authStore)
if (typeof redirectTo !== 'undefined') {
await router.push(redirectTo)
}

View File

@ -5,22 +5,31 @@ export function useRedirectToLastVisited() {
const router = useRouter()
function redirectIfSaved() {
function getLastVisitedRoute() {
const last = getLastVisited()
if (last !== null) {
router.push({
name: last.name,
params: last.params,
query: last.query,
})
clearLastVisited()
return
if (last === null) {
return null
}
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 {
redirectIfSaved,
getLastVisitedRoute,
}
}

View File

@ -0,0 +1 @@
export const LINK_SHARE_HASH_PREFIX = '#share-auth-token='

View File

@ -6,6 +6,7 @@ import {saveProjectView, getProjectView} from '@/helpers/projectView'
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
import {getNextWeekDate} from '@/helpers/time/getNextWeekDate'
import {setTitle} from '@/helpers/setTitle'
import {LINK_SHARE_HASH_PREFIX} from '@/constants/linkShareHash'
import {useProjectStore} from '@/stores/projects'
import {useAuthStore} from '@/stores/auth'
@ -89,7 +90,7 @@ const router = createRouter({
}
// Scroll to anchor should still work
if (to.hash) {
if (to.hash && !to.hash.startsWith(LINK_SHARE_HASH_PREFIX)) {
return {el: to.hash}
}
@ -485,8 +486,7 @@ const router = createRouter({
],
})
export async function getAuthForRoute(route: RouteLocation) {
const authStore = useAuthStore()
export async function getAuthForRoute(to: RouteLocation, authStore) {
if (authStore.authUser || authStore.authLinkShare) {
return
}
@ -507,26 +507,52 @@ export async function getAuthForRoute(route: RouteLocation) {
'user.register',
'link-share.auth',
'openid.auth',
].includes(route.name as string) &&
].includes(to.name as string) &&
localStorage.getItem('passwordResetToken') === 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'}
}
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'}
}
if(localStorage.getItem('emailConfirmToken') !== null && route.name !== 'user.login') {
if(localStorage.getItem('emailConfirmToken') !== null && to.name !== 'user.login') {
return {name: 'user.login'}
}
}
router.beforeEach(async (to) => {
return getAuthForRoute(to)
router.beforeEach(async (to, from) => {
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

View File

@ -40,12 +40,15 @@ import {useTitle} from '@vueuse/core'
import Message from '@/components/misc/message.vue'
import {PROJECT_VIEWS, type ProjectView} from '@/types/ProjectView'
import {LINK_SHARE_HASH_PREFIX} from '@/constants/linkShareHash'
import {useBaseStore} from '@/stores/base'
import {useAuthStore} from '@/stores/auth'
import {useRedirectToLastVisited} from '@/composables/useRedirectToLastVisited'
const {t} = useI18n({useScope: 'global'})
useTitle(t('sharing.authenticating'))
const {getLastVisitedRoute} = useRedirectToLastVisited()
function useAuth() {
const baseStore = useBaseStore()
@ -87,7 +90,21 @@ function useAuth() {
? route.query.view
: '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) {
if (e.response?.data?.code === 13001) {
authenticateWithPassword.value = true