From de160c219a84e718d1792de633789d248fd33fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Mon, 12 Dec 2022 00:30:26 +0100 Subject: [PATCH] feat: prevent mixing data on account switch (#384) --- composables/cache.ts | 36 +++++++++++++++--------- composables/users.ts | 12 ++------ middleware/permalink.global.ts | 15 ++++++++-- pages/[[server]]/@[account]/[status].vue | 1 + pages/[[server]]/@[account]/index.vue | 4 +++ 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/composables/cache.ts b/composables/cache.ts index c496567f..536efdf5 100644 --- a/composables/cache.ts +++ b/composables/cache.ts @@ -15,7 +15,8 @@ export function setCached(key: string, value: any, override = false) { } export function fetchStatus(id: string, force = false): Promise { - const key = `status:${id}` + const server = currentServer.value + const key = `${server}:status:${id}` const cached = cache.get(key) if (cached && !force) return cached @@ -32,30 +33,37 @@ export function fetchAccountById(id?: string | null): Promise { if (!id) return Promise.resolve(null) - const key = `account:${id}` + const server = currentServer.value + const key = `${server}:account:${id}` const cached = cache.get(key) if (cached) return cached + const uri = currentInstance.value?.uri const promise = useMasto().accounts.fetch(id) - .then((account) => { - cacheAccount(account, true) - return account + .then((r) => { + if (!r.acct.includes('@') && uri) + r.acct = `${r.acct}@${uri}` + + cacheAccount(r, server, true) + return r }) cache.set(key, promise) return promise } export async function fetchAccountByHandle(acct: string): Promise { - const key = `account:${acct}` + const server = currentServer.value + const key = `${server}:account:${acct}` const cached = cache.get(key) if (cached) return cached + const uri = currentInstance.value?.uri const account = useMasto().accounts.lookup({ acct }) .then((r) => { - if (!r.acct.includes('@') && currentInstance.value) - r.acct = `${r.acct}@${currentInstance.value.uri}` + if (!r.acct.includes('@') && uri) + r.acct = `${r.acct}@${uri}` - cacheAccount(r, true) + cacheAccount(r, server, true) return r }) cache.set(key, account) @@ -70,11 +78,11 @@ export function useAccountById(id?: string | null) { return useAsyncState(() => fetchAccountById(id), null).state } -export function cacheStatus(status: Status, override?: boolean) { - setCached(`status:${status.id}`, status, override) +export function cacheStatus(status: Status, server = currentServer.value, override?: boolean) { + setCached(`${server}:status:${status.id}`, status, override) } -export function cacheAccount(account: Account, override?: boolean) { - setCached(`account:${account.id}`, account, override) - setCached(`account:${account.acct}`, account, override) +export function cacheAccount(account: Account, server = currentServer.value, override?: boolean) { + setCached(`${server}:account:${account.id}`, account, override) + setCached(`${server}:account:${account.acct}`, account, override) } diff --git a/composables/users.ts b/composables/users.ts index 8e7c9390..4250f85d 100644 --- a/composables/users.ts +++ b/composables/users.ts @@ -31,12 +31,6 @@ export const currentInstance = computed(() => currentUserId.val export const characterLimit = computed(() => currentInstance.value?.configuration.statuses.maxCharacters ?? DEFAULT_POST_CHARS_LIMIT) export async function loginTo(user?: Omit & { account?: AccountCredentials }) { - if (user) { - const existing = users.value.find(u => u.server === user.server && u.token === user.token) - if (existing && currentUserId.value !== user.account?.id) - currentUserId.value = user.account?.id - } - const config = useRuntimeConfig() const route = useRoute() const router = useRouter() @@ -76,7 +70,7 @@ export async function loginTo(user?: Omit & { account?: Ac setMasto(masto) - if ('server' in route.params) { + if ('server' in route.params && user?.token) { await router.push({ ...route, force: true, @@ -110,7 +104,7 @@ export async function signout() { currentUserId.value = users.value[0]?.account?.id if (!currentUserId.value) - await useRouter().push(`/${currentServer.value}/public`) + await useRouter().push('/') await loginTo(currentUser.value) } @@ -127,7 +121,7 @@ export const useNotifications = () => { } async function connect(): Promise { - if (!id || notifications[id]) + if (!id || notifications[id] || !currentUser.value?.token) return const masto = useMasto() diff --git a/middleware/permalink.global.ts b/middleware/permalink.global.ts index c0350207..d9f621a0 100644 --- a/middleware/permalink.global.ts +++ b/middleware/permalink.global.ts @@ -6,7 +6,9 @@ export default defineNuxtRouteMiddleware(async (to, from) => { if (!('server' in to.params)) return - if (!currentUser.value) { + const user = currentUser.value + + if (!user) { if (from.params.server !== to.params.server) { await loginTo({ server: to.params.server as string, @@ -16,7 +18,7 @@ export default defineNuxtRouteMiddleware(async (to, from) => { } // No need to additionally resolve an id if we're already logged in - if (currentUser.value.server === to.params.server) + if (user.server === to.params.server) return // Tags don't need to be redirected to a local id @@ -29,12 +31,19 @@ export default defineNuxtRouteMiddleware(async (to, from) => { ...to, params: { ...to.params, - server: currentUser.value.server, + server: user.server, }, } } try { + // If we're already on an account page, we can search for this on the new instance + if (to.params.account) { + const account = await fetchAccountByHandle(to.params.account as string) + if (account) + return getAccountRoute(account) + } + // If we're logged in, search for the local id the account or status corresponds to const { value } = await useMasto().search({ q: `https:/${to.fullPath}`, resolve: true, limit: 1 }).next() diff --git a/pages/[[server]]/@[account]/[status].vue b/pages/[[server]]/@[account]/[status].vue index 642db1f0..3f5fdbd7 100644 --- a/pages/[[server]]/@[account]/[status].vue +++ b/pages/[[server]]/@[account]/[status].vue @@ -4,6 +4,7 @@ import type { ComponentPublicInstance } from 'vue' definePageMeta({ name: 'status', + key: route => route.path, }) const route = useRoute() diff --git a/pages/[[server]]/@[account]/index.vue b/pages/[[server]]/@[account]/index.vue index 01e81a7d..a6bbb4d5 100644 --- a/pages/[[server]]/@[account]/index.vue +++ b/pages/[[server]]/@[account]/index.vue @@ -1,4 +1,8 @@