| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- import { createPinia, setActivePinia } from 'pinia'
- import { beforeEach, expect, it, vi } from 'vitest'
- const mocks = vi.hoisted(() => ({
- login: vi.fn(),
- setup: vi.fn(),
- authorizeComputer: vi.fn(),
- bootstrap: vi.fn(),
- logout: vi.fn(),
- changeCredentials: vi.fn(),
- forgetLogin: vi.fn(),
- }))
- vi.mock('@/api/auth', () => ({
- login: mocks.login,
- setup: mocks.setup,
- bootstrap: mocks.bootstrap,
- logout: mocks.logout,
- fetchProfiles: vi.fn(),
- fetchProfileIdentities: vi.fn(),
- changeCredentials: mocks.changeCredentials,
- updateAccountAvatar: vi.fn(),
- }))
- vi.mock('@/api/serverIdentity', () => ({ fetchServerIdentity: vi.fn(), onServerIdentity: () => () => {} }))
- vi.mock('@/api/client', () => ({
- ApiError: class ApiError extends Error { status = 500 },
- clearApiSecurityContext: vi.fn(),
- onApiUnauthorized: () => () => {},
- }))
- import { useAuthStore } from '@/stores/auth'
- const response = (role: 'admin' | 'user') => ({
- authRequired: true,
- profiles: [],
- csrfToken: 'fresh-csrf',
- user: { id: 'user-1', username: '用户', role },
- })
- beforeEach(() => {
- setActivePinia(createPinia())
- mocks.login.mockReset()
- mocks.setup.mockReset()
- mocks.authorizeComputer.mockReset()
- mocks.bootstrap.mockReset()
- mocks.logout.mockReset()
- mocks.changeCredentials.mockReset()
- mocks.forgetLogin.mockReset()
- Object.defineProperty(window, 'yaoyaoDesktop', { configurable: true, value: { authorizeComputer: mocks.authorizeComputer, forgetLogin: mocks.forgetLogin } })
- })
- it('re-authorizes the computer only after an explicit administrator login', async () => {
- mocks.login.mockResolvedValue(response('admin'))
- mocks.authorizeComputer.mockResolvedValue({ registered: true, hostId: 'host-1' })
- const auth = useAuthStore()
- await auth.login({ username: 'admin', password: 'secret' })
- expect(mocks.authorizeComputer).toHaveBeenCalledWith('fresh-csrf')
- expect(auth.status).toBe('authenticated')
- })
- it('does not grant computer control to a non-administrator login', async () => {
- mocks.login.mockResolvedValue(response('user'))
- const auth = useAuthStore()
- await auth.login({ username: 'member', password: 'secret' })
- expect(mocks.authorizeComputer).not.toHaveBeenCalled()
- expect(auth.status).toBe('authenticated')
- })
- it('keeps the administrator signed in when computer authorization fails', async () => {
- mocks.login.mockResolvedValue(response('admin'))
- mocks.authorizeComputer.mockRejectedValue(new Error('computer offline'))
- const auth = useAuthStore()
- await expect(auth.login({ username: 'admin', password: 'secret' })).resolves.toBeUndefined()
- expect(auth.status).toBe('authenticated')
- })
- it('forgets native authorization on explicit logout even when the server is offline', async () => {
- mocks.login.mockResolvedValue(response('user'))
- const auth = useAuthStore()
- await auth.login({ username: 'member', password: 'secret' })
- mocks.logout.mockRejectedValue(new Error('offline'))
- mocks.bootstrap.mockRejectedValue(new Error('offline'))
- await auth.logout()
- expect(mocks.forgetLogin).toHaveBeenCalledOnce()
- expect(auth.status).toBe('anonymous')
- expect(auth.user).toBeUndefined()
- })
- it('returns a remote desktop to login after changing its password', async () => {
- mocks.login.mockResolvedValue(response('user'))
- const auth = useAuthStore()
- await auth.login({ username: 'member', password: 'secret' })
- mocks.changeCredentials.mockResolvedValue(response('user').user)
- mocks.bootstrap.mockResolvedValue({ authRequired: true, profiles: [], csrfToken: 'new-csrf' })
- await auth.changeCredentials({ currentPassword: 'secret', newPassword: 'new-secret' })
- expect(mocks.forgetLogin).toHaveBeenCalledOnce()
- expect(auth.status).toBe('anonymous')
- })
- it('keeps the native local administrator active after setting a remote password', async () => {
- const local = { ...response('admin'), user: { ...response('admin').user, localDesktop: true } }
- mocks.bootstrap.mockResolvedValue(local)
- const auth = useAuthStore()
- await auth.bootstrap()
- mocks.changeCredentials.mockResolvedValue(local.user)
- await auth.changeCredentials({ currentPassword: '', newPassword: 'remote-password' })
- expect(mocks.forgetLogin).not.toHaveBeenCalled()
- expect(auth.status).toBe('authenticated')
- expect(auth.user?.localDesktop).toBe(true)
- })
|