mirror of
https://github.com/immich-app/immich.git
synced 2026-02-16 00:09:42 -05:00
198 lines
6.2 KiB
TypeScript
198 lines
6.2 KiB
TypeScript
import { jwtVerify } from 'jose';
|
|
import { MaintenanceAction, SystemMetadataKey } from 'src/enum';
|
|
import { CliService } from 'src/services/cli.service';
|
|
import { factory } from 'test/small.factory';
|
|
import { newTestService, ServiceMocks } from 'test/utils';
|
|
import { describe, it } from 'vitest';
|
|
|
|
describe(CliService.name, () => {
|
|
let sut: CliService;
|
|
let mocks: ServiceMocks;
|
|
|
|
beforeEach(() => {
|
|
({ sut, mocks } = newTestService(CliService));
|
|
});
|
|
|
|
describe('listUsers', () => {
|
|
it('should list users', async () => {
|
|
mocks.user.getList.mockResolvedValue([factory.userAdmin({ isAdmin: true })]);
|
|
await expect(sut.listUsers()).resolves.toEqual([expect.objectContaining({ isAdmin: true })]);
|
|
expect(mocks.user.getList).toHaveBeenCalledWith({ withDeleted: true });
|
|
});
|
|
});
|
|
|
|
describe('resetAdminPassword', () => {
|
|
it('should only work when there is an admin account', async () => {
|
|
mocks.user.getAdmin.mockResolvedValue(void 0);
|
|
const ask = vitest.fn().mockResolvedValue('new-password');
|
|
|
|
await expect(sut.resetAdminPassword(ask)).rejects.toThrowError('Admin account does not exist');
|
|
|
|
expect(ask).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should default to a random password', async () => {
|
|
const admin = factory.userAdmin({ isAdmin: true });
|
|
|
|
mocks.user.getAdmin.mockResolvedValue(admin);
|
|
mocks.user.update.mockResolvedValue(factory.userAdmin({ isAdmin: true }));
|
|
|
|
const ask = vitest.fn().mockImplementation(() => {});
|
|
|
|
const response = await sut.resetAdminPassword(ask);
|
|
|
|
const [id, update] = mocks.user.update.mock.calls[0];
|
|
|
|
expect(response.provided).toBe(false);
|
|
expect(ask).toHaveBeenCalled();
|
|
expect(id).toEqual(admin.id);
|
|
expect(update.password).toBeDefined();
|
|
});
|
|
|
|
it('should use the supplied password', async () => {
|
|
const admin = factory.userAdmin({ isAdmin: true });
|
|
|
|
mocks.user.getAdmin.mockResolvedValue(admin);
|
|
mocks.user.update.mockResolvedValue(admin);
|
|
|
|
const ask = vitest.fn().mockResolvedValue('new-password');
|
|
|
|
const response = await sut.resetAdminPassword(ask);
|
|
|
|
const [id, update] = mocks.user.update.mock.calls[0];
|
|
|
|
expect(response.provided).toBe(true);
|
|
expect(ask).toHaveBeenCalled();
|
|
expect(id).toEqual(admin.id);
|
|
expect(update.password).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('disablePasswordLogin', () => {
|
|
it('should disable password login', async () => {
|
|
await sut.disablePasswordLogin();
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith('system-config', { passwordLogin: { enabled: false } });
|
|
});
|
|
});
|
|
|
|
describe('enablePasswordLogin', () => {
|
|
it('should enable password login', async () => {
|
|
await sut.enablePasswordLogin();
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith('system-config', {});
|
|
});
|
|
});
|
|
|
|
describe('disableMaintenanceMode', () => {
|
|
it('should not do anything if not in maintenance mode', async () => {
|
|
mocks.systemMetadata.get.mockResolvedValue({ isMaintenanceMode: false });
|
|
await expect(sut.disableMaintenanceMode()).resolves.toEqual({
|
|
alreadyDisabled: true,
|
|
});
|
|
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledTimes(0);
|
|
expect(mocks.event.emit).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('should disable maintenance mode', async () => {
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
isMaintenanceMode: true,
|
|
secret: 'secret',
|
|
action: {
|
|
action: MaintenanceAction.Start,
|
|
},
|
|
});
|
|
|
|
await expect(sut.disableMaintenanceMode()).resolves.toEqual({
|
|
alreadyDisabled: false,
|
|
});
|
|
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith(SystemMetadataKey.MaintenanceMode, {
|
|
isMaintenanceMode: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('enableMaintenanceMode', () => {
|
|
it('should not do anything if in maintenance mode', async () => {
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
isMaintenanceMode: true,
|
|
secret: 'secret',
|
|
action: {
|
|
action: MaintenanceAction.Start,
|
|
},
|
|
});
|
|
|
|
await expect(sut.enableMaintenanceMode()).resolves.toEqual(
|
|
expect.objectContaining({
|
|
alreadyEnabled: true,
|
|
}),
|
|
);
|
|
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledTimes(0);
|
|
expect(mocks.event.emit).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('should enable maintenance mode', async () => {
|
|
mocks.systemMetadata.get.mockResolvedValue({ isMaintenanceMode: false });
|
|
await expect(sut.enableMaintenanceMode()).resolves.toEqual(
|
|
expect.objectContaining({
|
|
alreadyEnabled: false,
|
|
}),
|
|
);
|
|
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith(SystemMetadataKey.MaintenanceMode, {
|
|
isMaintenanceMode: true,
|
|
secret: expect.stringMatching(/^\w{128}$/),
|
|
action: {
|
|
action: 'start',
|
|
},
|
|
});
|
|
});
|
|
|
|
const RE_LOGIN_URL = /https:\/\/my.immich.app\/maintenance\?token=([A-Za-z0-9-_]*\.[A-Za-z0-9-_]*\.[A-Za-z0-9-_]*)/;
|
|
|
|
it('should return a valid login URL', async () => {
|
|
mocks.systemMetadata.get.mockResolvedValue({
|
|
isMaintenanceMode: true,
|
|
secret: 'secret',
|
|
action: {
|
|
action: MaintenanceAction.Start,
|
|
},
|
|
});
|
|
|
|
const result = await sut.enableMaintenanceMode();
|
|
|
|
expect(result).toEqual(
|
|
expect.objectContaining({
|
|
authUrl: expect.stringMatching(RE_LOGIN_URL),
|
|
alreadyEnabled: true,
|
|
}),
|
|
);
|
|
|
|
const token = RE_LOGIN_URL.exec(result.authUrl)![1];
|
|
|
|
await expect(jwtVerify(token, new TextEncoder().encode('secret'))).resolves.toEqual(
|
|
expect.objectContaining({
|
|
payload: expect.objectContaining({
|
|
username: 'cli-admin',
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('disableOAuthLogin', () => {
|
|
it('should disable oauth login', async () => {
|
|
await sut.disableOAuthLogin();
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith('system-config', {});
|
|
});
|
|
});
|
|
|
|
describe('enableOAuthLogin', () => {
|
|
it('should enable oauth login', async () => {
|
|
await sut.enableOAuthLogin();
|
|
expect(mocks.systemMetadata.set).toHaveBeenCalledWith('system-config', { oauth: { enabled: true } });
|
|
});
|
|
});
|
|
});
|