Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 1 addition & 20 deletions src/apps/main/device/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,10 @@ export async function getDevices(): Promise<Array<Device>> {
return [];
} else {
const devices = response.getRight();
return devices
.filter(({ removed, hasBackups }) => !removed && hasBackups)
.map((device) => decryptDeviceName(device));
return devices.filter(({ removed, hasBackups }) => !removed && hasBackups).map((device) => device);
}
}

export function decryptDeviceName({ name, ...rest }: Device): Device {
let nameDevice;
let key;
try {
key = `${process.env.NEW_CRYPTO_KEY}-${rest.bucket}`;
nameDevice = aes.decrypt(name, key);
} catch (error) {
key = `${process.env.NEW_CRYPTO_KEY}-${null}`;
nameDevice = aes.decrypt(name, key);
}
logger.debug({ tag: 'BACKUPS', msg: 'Decrypted device', nameDevice });
return {
name: nameDevice,
...rest,
};
}

export async function fetchFolderTree(folderUuid: string): Promise<{
tree: FolderTree;
folderDecryptedNames: Record<number, string>;
Expand Down
4 changes: 2 additions & 2 deletions src/backend/features/device/createNewDevice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Either, right } from './../../../context/shared/domain/Either';
import { decryptDeviceName, Device } from '../../../apps/main/device/service';
import { Device } from '../../../apps/main/device/service';
import { createUniqueDevice } from './createUniqueDevice';
import { saveDeviceToConfig } from './saveDeviceToConfig';
import { DeviceIdentifierDTO } from './device.types';
Expand All @@ -9,7 +9,7 @@ export async function createNewDevice(deviceIdentifier: DeviceIdentifierDTO): Pr
if (createUniqueDeviceEither.isRight()) {
const device = createUniqueDeviceEither.getRight();
saveDeviceToConfig(device);
return right(decryptDeviceName(device));
return right(device);
}
return createUniqueDeviceEither;
}
7 changes: 3 additions & 4 deletions src/backend/features/device/fetchDevice.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { driveServerModule } from './../../../infra/drive-server/drive-server.module';
import { Either, left, right } from '../../../context/shared/domain/Either';
import { decryptDeviceName, Device } from '../../../apps/main/device/service';
import { Device } from '../../../apps/main/device/service';
import { logger } from '@internxt/drive-desktop-core/build/backend';
import { BackupError } from '../../../infra/drive-server/services/backup/backup.error';
import { addUnknownDeviceIssue } from './addUnknownDeviceIssue';
Expand Down Expand Up @@ -52,13 +52,12 @@ export async function fetchDevice(props: FetchDeviceProps): Promise<Either<Error
if (getDeviceEither.isRight()) {
const device = getDeviceEither.getRight();
if (device && !device.removed) {
const decryptedDevice = decryptDeviceName(device);
logger.debug({
tag: 'BACKUPS',
msg: '[DEVICE] Found device',
device: decryptedDevice.name,
device: device.name,
});
return right(decryptedDevice);
return right(device);
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/backend/features/device/renameDevice.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Device } from '../../../apps/main/device/service';
import { driveServerModule } from '../../../infra/drive-server/drive-server.module';
import { decryptDeviceName } from '../../../apps/main/device/service';
import { getDeviceIdentifier } from './getDeviceIdentifier';

export async function renameDevice(deviceName: string): Promise<Device> {
Expand All @@ -11,8 +10,7 @@ export async function renameDevice(deviceName: string): Promise<Device> {

const response = await driveServerModule.backup.updateDeviceByIdentifier(deviceIdentifier.getRight().key, deviceName);
if (response.isRight()) {
const device = response.getRight();
return decryptDeviceName(device);
return response.getRight();
} else {
throw new Error('Error in the request to rename a device');
}
Expand Down
2 changes: 1 addition & 1 deletion src/backend/features/device/utils/deviceMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function mapDeviceAsFolderToDevice(deviceAsFolder: components['schemas'][
return {
id: deviceAsFolder.id,
uuid: deviceAsFolder.uuid,
name: deviceAsFolder.name,
name: deviceAsFolder.plainName,
bucket: deviceAsFolder.bucket,
removed: deviceAsFolder.removed,
hasBackups: deviceAsFolder.hasBackups,
Expand Down
120 changes: 53 additions & 67 deletions src/infra/drive-server/services/backup/backup.service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { BackupService } from './backup.service';
import { driveServerClient } from '../../client/drive-server.client.instance';
import { logger } from '@internxt/drive-desktop-core/build/backend';
import { Mock } from 'vitest';
import { mapError } from '../utils/mapError';
import { calls, partialSpyOn } from 'tests/vitest/utils.helper';
import * as mapErrorModule from '../utils/mapError';
import * as authServiceModule from '../../../../apps/main/auth/service';

vi.mock('axios', async (importOriginal) => {
const actual = await importOriginal<typeof import('axios')>();
Expand All @@ -12,195 +10,183 @@ vi.mock('axios', async (importOriginal) => {
};
});

vi.mock('../utils/mapError', () => ({
mapError: vi.fn(),
}));

vi.mock('@internxt/drive-desktop-core/build/backend', () => ({
logger: {
error: vi.fn(),
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
},
}));

vi.mock('../../client/drive-server.client.instance', () => ({
driveServerClient: {
GET: vi.fn(),
POST: vi.fn(),
PATCH: vi.fn(),
},
}));

vi.mock('../../../../apps/main/auth/service', () => ({
getNewApiHeaders: vi.fn(() => ({})),
}));
import { BackupService } from './backup.service';
import { driveServerClient } from '../../client/drive-server.client.instance';
import { loggerMock } from 'tests/vitest/mocks.helper';

describe('BackupService', () => {
let sut: BackupService;

const driveServerGetMock = partialSpyOn(driveServerClient, 'GET');
const driveServerPostMock = partialSpyOn(driveServerClient, 'POST');
const driveServerPatchMock = partialSpyOn(driveServerClient, 'PATCH');
const mapErrorMock = partialSpyOn(mapErrorModule, 'mapError');
const getNewApiHeadersMock = partialSpyOn(authServiceModule, 'getNewApiHeaders');

beforeEach(() => {
sut = new BackupService();
vi.clearAllMocks();
// Default mock behavior: mapError returns the error as an Error instance
vi.mocked(mapError).mockImplementation((error) => (error instanceof Error ? error : new Error(String(error))));
getNewApiHeadersMock.mockReturnValue({});
mapErrorMock.mockImplementation((error) => (error instanceof Error ? error : new Error(String(error))));
});

describe('getDevices', () => {
it('should return a list of devices when the response is successful', async () => {
const data = [{ uuid: '123', name: 'Device 1' }];
(driveServerClient.GET as Mock).mockResolvedValue({ data });
const apiData = [{ id: 1, uuid: '123', plainName: 'Device 1' }];
const expectedData = [{ id: 1, uuid: '123', name: 'Device 1' }];
driveServerGetMock.mockResolvedValue({ data: apiData } as object);

const result = await sut.getDevices();

expect(result.isRight()).toBe(true);
expect(result.getRight()).toEqual(data);
expect(result.getRight()).toMatchObject(expectedData);
});

it('should return an error when response is not successful', async () => {
(driveServerClient.GET as Mock).mockResolvedValue({ data: undefined });
driveServerGetMock.mockResolvedValue({ data: undefined });

const result = await sut.getDevices();

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toBeInstanceOf(Error);
expect(logger.error).toHaveBeenCalled();
});

it('should return an error when the request throws an exception', async () => {
const error = new Error('Request failed');
(driveServerClient.GET as Mock).mockRejectedValue(error);
driveServerGetMock.mockRejectedValue(error);

const result = await sut.getDevices();

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toEqual(error);
expect(logger.error).toHaveBeenCalled();
calls(loggerMock.error).toHaveLength(1);
});
});

describe('getDevice', () => {
it('should return a device when the response is successful', async () => {
const data = { uuid: '123', name: 'Device A' };
(driveServerClient.GET as Mock).mockResolvedValue({ data });
const apiData = { id: 1, uuid: '123', plainName: 'Device A' };
const expectedData = { id: 1, uuid: '123', name: 'Device A' };
driveServerGetMock.mockResolvedValue({ data: apiData } as object);

const result = await sut.getDevice('123');

expect(result.isRight()).toBe(true);
expect(result.getRight()).toEqual(data);
expect(result.getRight()).toMatchObject(expectedData);
});

it('should return an error when response is not successful', async () => {
(driveServerClient.GET as Mock).mockResolvedValue({ data: undefined });
driveServerGetMock.mockResolvedValue({ data: undefined });

const result = await sut.getDevice('123');

expect(result.isLeft()).toBe(true);
expect(logger.error).toHaveBeenCalled();
calls(loggerMock.error).toHaveLength(1);
});

it('should return an error when the request throws an exception', async () => {
const error = new Error('Error fetching device');
(driveServerClient.GET as Mock).mockRejectedValue(error);
driveServerGetMock.mockRejectedValue(error);

const result = await sut.getDevice('123');

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toEqual(error);
expect(result.getLeft()).toStrictEqual(error);
});
});

describe('getDeviceById', () => {
it('should get a device by id and return it when the response is successful', async () => {
const data = { uuid: 'id-123', name: 'Device B' };
(driveServerClient.GET as Mock).mockResolvedValue({ data });
const apiData = { id: 2, uuid: 'id-123', plainName: 'Device B' };
const expectedData = { id: 2, uuid: 'id-123', name: 'Device B' };
driveServerGetMock.mockResolvedValue({ data: apiData } as object);

const result = await sut.getDeviceById('id-123');

expect(result.isRight()).toBe(true);
expect(result.getRight()).toEqual(data);
expect(result.getRight()).toMatchObject(expectedData);
});

it('should return an error when response is not successful', async () => {
(driveServerClient.GET as Mock).mockResolvedValue({ data: undefined });
driveServerGetMock.mockResolvedValue({ data: undefined });

const result = await sut.getDeviceById('id-123');

expect(result.isLeft()).toBe(true);
expect(logger.error).toHaveBeenCalled();
calls(loggerMock.error).toHaveLength(1);
});

it('should return an error when the request throws an exception', async () => {
const error = new Error('Exception occurred');
(driveServerClient.GET as Mock).mockRejectedValue(error);
driveServerGetMock.mockRejectedValue(error);

const result = await sut.getDeviceById('id-123');

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toEqual(error);
expect(result.getLeft()).toStrictEqual(error);
});
});

describe('createDevice', () => {
it('should create a device and return it when the response is successful', async () => {
const data = { uuid: 'new-123', name: 'New Device' };
(driveServerClient.POST as Mock).mockResolvedValue({ data });
const apiData = { id: 3, uuid: 'new-123', plainName: 'New Device' };
const expectedData = { id: 3, uuid: 'new-123', name: 'New Device' };
driveServerPostMock.mockResolvedValue({ data: apiData } as object);

const result = await sut.createDevice('New Device');

expect(result.isRight()).toBe(true);
expect(result.getRight()).toEqual(data);
expect(result.getRight()).toMatchObject(expectedData);
});

it('should return an error when response is not successful', async () => {
(driveServerClient.POST as Mock).mockResolvedValue({ data: undefined });
driveServerPostMock.mockResolvedValue({ data: undefined });

const result = await sut.createDevice('New Device');

expect(result.isLeft()).toBe(true);
expect(logger.error).toHaveBeenCalled();
calls(loggerMock.error).toHaveLength(1);
});

it('should return an error when the request throws an exception', async () => {
const error = new Error('Create failed');
(driveServerClient.POST as Mock).mockRejectedValue(error);
driveServerPostMock.mockRejectedValue(error);

const result = await sut.createDevice('New Device');

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toEqual(error);
expect(result.getLeft()).toStrictEqual(error);
});
});

describe('updateDevice', () => {
it('should update a device and return it when the response is successful', async () => {
const data = { uuid: 'device-123', name: 'Updated Device' };
(driveServerClient.PATCH as Mock).mockResolvedValue({ data });
const apiData = { id: 4, uuid: 'device-123', plainName: 'Updated Device' };
const expectedData = { id: 4, uuid: 'device-123', name: 'Updated Device' };
driveServerPatchMock.mockResolvedValue({ data: apiData } as object);

const result = await sut.updateDevice('device-123', 'Updated Device');

expect(result.isRight()).toBe(true);
expect(result.getRight()).toEqual(data);
expect(result.getRight()).toEqual(expectedData);
});

it('should return an error when response is not successful', async () => {
(driveServerClient.PATCH as Mock).mockResolvedValue({ data: undefined });
driveServerPatchMock.mockResolvedValue({ data: undefined });

const result = await sut.updateDevice('device-123', 'Updated Device');

expect(result.isLeft()).toBe(true);
expect(logger.error).toHaveBeenCalled();
calls(loggerMock.error).toHaveLength(1);
});

it('should return an error when the request throws an exception', async () => {
const error = new Error('Update failed');
(driveServerClient.PATCH as Mock).mockRejectedValue(error);
driveServerPatchMock.mockRejectedValue(error);

const result = await sut.updateDevice('device-123', 'Updated Device');

expect(result.isLeft()).toBe(true);
expect(result.getLeft()).toEqual(error);
expect(result.getLeft()).toStrictEqual(error);
});
});
});
Loading