feat: bind room tickets to member sessions and disconnect revoked sessions
This commit is contained in:
1 parent
54efdb6dd2
commit
e69dc18581
43 files changed
+944
-140
No files matched your search
@@ -11,6 +11,14 @@ type Handler = (token: string | null) => Response | Promise<Response>
|
||||
class FakeStorage {
|
||||
readonly #items = new Map<string, string>()
|
||||
|
||||
get length(): number {
|
||||
return this.#items.size
|
||||
}
|
||||
|
||||
key(index: number): string | null {
|
||||
return [...this.#items.keys()][index] ?? null
|
||||
}
|
||||
|
||||
getItem(key: string): string | null {
|
||||
return this.#items.get(key) ?? null
|
||||
}
|
||||
@@ -172,6 +180,18 @@ describe('token 失效时更换身份', () => {
|
||||
expect(events).toEqual([{ kind: 'rejected' }, { kind: 'renewed', member: issued }])
|
||||
})
|
||||
|
||||
it('票据属于被拒绝的身份,一并删除', async () => {
|
||||
local.setItem(memberTokenKey, 'expired')
|
||||
local.setItem('alisten.ticket.r1', 't1')
|
||||
local.setItem('alisten.ticket.r2', 't2')
|
||||
routes.set('PATCH /api/me', unauthorized)
|
||||
const { api, IdentityRenewedError } = await load()
|
||||
await expect(api.updateMe({ name: 'alice' })).rejects.toBeInstanceOf(IdentityRenewedError)
|
||||
|
||||
expect(local.getItem('alisten.ticket.r1')).toBeNull()
|
||||
expect(local.getItem('alisten.ticket.r2')).toBeNull()
|
||||
})
|
||||
|
||||
it('同时被拒绝的请求只更换一次身份', async () => {
|
||||
local.setItem(memberTokenKey, 'expired')
|
||||
routes.set('PATCH /api/me', unauthorized)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Auth, CreateTicketRequest, CreateTicketResponse, ErrorResponse, HttpRequest } from './http.gen'
|
||||
import type { ErrorCode, Member } from '@/core/realtime'
|
||||
import { Emitter } from '@/shared/lib/emitter'
|
||||
import { deleteMemberToken, loadAdminToken, loadMemberToken, saveMemberToken } from './credentials'
|
||||
import { deleteAllTickets, deleteMemberToken, loadAdminToken, loadMemberToken, saveMemberToken } from './credentials'
|
||||
import { httpClient } from './http.gen'
|
||||
|
||||
export class ApiError extends Error {
|
||||
@@ -159,9 +159,11 @@ function renewIdentity(rejected: string): Promise<void> {
|
||||
|
||||
// 更换过程中用 unrenewed 读取成员:新 token 也被拒绝时不再更换,避免循环。
|
||||
async function replaceIdentity(rejected: string): Promise<void> {
|
||||
// 其他标签页可能已经更换了身份,只删除被拒绝的那个 token。
|
||||
if (loadMemberToken() === rejected)
|
||||
// 其他标签页可能已经更换了身份,只删除被拒绝的那个 token。票据属于被拒绝的身份,一并删除。
|
||||
if (loadMemberToken() === rejected) {
|
||||
deleteMemberToken()
|
||||
deleteAllTickets()
|
||||
}
|
||||
identityEvents.emit({ kind: 'rejected' })
|
||||
let member: Member
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user