improved login/logout process, eliminating 403 errors

This commit is contained in:
Henry Jameson 2026-08-25 19:36:24 +03:00
commit 1fac5b006d
7 changed files with 155 additions and 20 deletions

View file

@ -268,14 +268,17 @@ const Chat = {
},
attachSocket() {
const et = new EventTarget()
const socket = { et }
const socket = {
name: 'chatview',
et,
}
et.addEventListener('update', this.onStreamMessage)
et.addEventListener('open', this.onStreamConnect)
et.addEventListener('close', this.onStreamDisconnect)
useStreamingStore().addSubscriber(socket)
this.socket = socket
useStreamingStore().addSubscriber(this.socket)
},
detachSocket() {
const { et } = this.socket

View file

@ -37,7 +37,10 @@ export const useChatsStore = defineStore('chats', {
actions: {
attachSocket() {
const et = new EventTarget()
const socket = { et }
const socket = {
name: 'chats',
et,
}
et.addEventListener('pleroma:chat_update', this.updateChat)

View file

@ -96,7 +96,10 @@ export const useInterfaceStore = defineStore('interface', {
actions: {
attachSocket() {
const et = new EventTarget()
const socket = { et }
const socket = {
name: 'interface',
et,
}
et.addEventListener('open', this.onStreamConnect)
et.addEventListener('close', this.onStreamDisconnect)

View file

@ -31,7 +31,9 @@ export const defaultState = () => ({
statusIdStore: new Set(),
socket: null,
streaming: false,
fetching: true,
fetcher: null,
paused: false,
})
export const useNotificationsStore = defineStore('notifications', {
@ -40,14 +42,29 @@ export const useNotificationsStore = defineStore('notifications', {
// Init
attachSocket() {
const et = new EventTarget()
const socket = { et }
const socket = {
name: 'notifications',
et,
}
et.addEventListener('notification', this.addNewNotifications)
et.addEventListener('open', this.onStreamConnect)
et.addEventListener('close', this.onStreamDisconnect)
useStreamingStore().addSubscriber(socket)
this.socket = socket
useStreamingStore().addSubscriber(this.socket)
},
pause() {
this.paused = true
if (this.fetcher && this.fetching) {
this.stopFetching('Notifications paused')
}
},
resume() {
this.paused = false
if (this.fetcher && this.fetching) {
this.startFetching('Notifications resumed')
}
},
activate() {
this.attachSocket()
@ -62,7 +79,7 @@ export const useNotificationsStore = defineStore('notifications', {
this.startFetching('Notifications activated')
},
deactivate() {
if (!this.streaming) {
if (this.fetching) {
this.stopFetching('Notifications deactivated')
}
@ -77,6 +94,7 @@ export const useNotificationsStore = defineStore('notifications', {
Object.keys(blankState).forEach((k) => {
this[k] = blankState[k]
})
console.log('[Notifications] Deactivated', this.fetcher)
},
// Poll & Push
@ -91,20 +109,30 @@ export const useNotificationsStore = defineStore('notifications', {
this.startFetching('Socket disconnected')
},
startFetching(reason) {
if (this.paused) {
console.debug(
'[Notificatiosn] NOT Starting notifications fetcher because it is paused',
'Original Reason:',
reason,
)
return
}
console.debug(
'[Notifications] Starting fetching notifications',
'[Notifications] Starting notifications fetcher',
'Reason:',
reason,
)
this.fetcher.startFetching()
this.fetching = true
},
stopFetching(reason) {
this.fetcher.stopFetching()
this.fetching = false
console.debug(
'[Notifications] Stopped fetching notifications',
'[Notifications] Stopped notifications fetcher',
'Reason:',
reason,
)
this.fetcher.stopFetching()
},
// Updates

View file

@ -49,6 +49,7 @@ export const useStatusesStore = defineStore('statuses', {
data.forEach((id) => this.setDeleted(id))
const socket = {
name: 'statuses',
et,
handlers: {
handleUpdate,

View file

@ -16,9 +16,11 @@ const emptyTl = (name, argument = null) => {
maxId: '',
minId: '',
streaming: false,
fetching: false,
reloadNeeded: false,
fetcher: null,
socket: null,
paused: false,
}
const property = ARGUMENT_MAP[name]
@ -114,6 +116,7 @@ export const useTimelinesStore = defineStore('timelines', {
et.addEventListener('update', messageHandler)
timeline.socket = {
name: 'timelines',
stream: {
name: streamName,
argument,
@ -132,7 +135,7 @@ export const useTimelinesStore = defineStore('timelines', {
deactivate(timelineName, persistent) {
const timeline = this[timelineName]
if (timeline.persistent && !persistent) return
if (!timeline.streaming) {
if (timeline.fetching) {
this.stopFetchingTimeline(timelineName, 'Timeline deactivation')
}
@ -176,6 +179,48 @@ export const useTimelinesStore = defineStore('timelines', {
})
},
// Pause
pause(name) {
const timeline = this[name]
timeline.paused = true
console.debug(
'[Timelines] Pausing timeline',
name,
)
if (timeline.fetcher && timeline.fetching) {
timeline.fetcher.stopFetching()
}
},
resume(name) {
const timeline = this[name]
timeline.paused = false
console.debug(
'[Timelines] Resuming timeline',
name,
)
if (timeline.fetcher && timeline.fetching) {
timeline.fetcher.startFetching()
}
},
pauseAll() {
TIMELINES.forEach((name) => {
try {
this.pause(name)
} catch (e) {
console.error(`[Timelines] Failed to pause timeline ${name}:`, e)
}
})
},
resumeAll() {
TIMELINES.forEach((name) => {
try {
this.resume(name)
} catch (e) {
console.error(`[Timelines] Failed to pause timeline ${name}:`, e)
}
})
},
// Update stuff
addStatusesToTimeline(
timelineName,
@ -246,15 +291,28 @@ export const useTimelinesStore = defineStore('timelines', {
this.startFetchingTimeline(timeline, argument, 'Socket disconnected')
},
startFetchingTimeline(timelineName, argument, reason) {
const timeline = this[timelineName]
console.log('[Timelines]', toValue(timeline))
if (timeline.paused) {
console.debug(
'[Timelines] NOT Starting timeline fetcher because it is paused',
timelineName,
argument,
'Original Reason:',
reason,
)
return
}
console.debug(
'[Timelines] Starting fetching timeline',
'[Timelines] Starting timeline fetcher',
timelineName,
argument,
'Reason:',
reason,
)
const timeline = this[timelineName]
timeline.fetcher.startFetching()
timeline.fetching = true
},
stopFetchingTimeline(timelineName, reason) {
const timeline = this[timelineName]
@ -274,6 +332,7 @@ export const useTimelinesStore = defineStore('timelines', {
'Reason:',
reason,
)
timeline.fetching = false
}
},

View file

@ -2,6 +2,8 @@ import Cookies from 'js-cookie'
import { last } from 'lodash'
import { defineStore } from 'pinia'
import { WSConnectionStatus } from 'src/api/websocket.js'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
import { useChatsStore } from 'src/stores/chats.js'
@ -708,6 +710,16 @@ export const useUsersStore = defineStore('users', {
const store = window.vuex
const oauth = useOAuthStore()
// Pause fetching
useNotificationsStore().pause()
useTimelinesStore().pauseAll()
// Pause-less stores
useAnnouncementsStore().stopFetching()
useListsStore().stopFetching()
useBookmarkFoldersStore().stopFetching()
store?.dispatch('stopFetchingFollowRequests')
// NOTE: No need to verify the app still exists, because if it doesn't,
// the token will be invalid too
return oauth
@ -722,6 +734,8 @@ export const useUsersStore = defineStore('users', {
return revokeToken(params)
})
.then(() => {
oauth.clearToken()
this.currentUser = null
this.lastLoginName = null
@ -729,21 +743,45 @@ export const useUsersStore = defineStore('users', {
this.usersByName = new Map()
this.usersByURL = new Map()
this.relationships = new Map()
useNotificationsStore().deactivate()
useAnnouncementsStore().stopFetching()
useListsStore().stopFetching()
useBookmarkFoldersStore().stopFetching()
store?.dispatch('stopFetchingFollowRequests')
useTimelinesStore().deactivateAll()
// Full reset on logout success
useStatusesStore().resetStatuses()
if (useMergedConfigStore().mergedConfig.useStreamingApi) {
useTimelinesStore().deactivateAll()
useChatsStore().resetChats()
// Socket is most likely already closed by server
if (
useMergedConfigStore().mergedConfig.useStreamingApi
&& useStreamingStore().state !== WSConnectionStatus.CLOSED
) {
useStreamingStore().stopSocket()
}
useChatsStore().resetChats()
oauth.clearToken()
Cookies.remove('__Host-pleroma_key', { path: '/' })
useInterfaceStore().onLogout()
})
.catch((e) => {
useInterfaceStore().pushGlobalNotice({
messageKey: 'user.logout_failure',
messageArgs: {
error: e,
},
level: 'error',
})
console.error('Logout error!', e)
useAnnouncementsStore().startFetching()
useListsStore().startFetching()
useBookmarkFoldersStore().startFetching()
store?.dispatch('startFetchingFollowRequests')
})
.finally(() => {
useNotificationsStore().resume()
useTimelinesStore().resumeAll()
})
},
},
persist: {