Skip to content

Commit

Permalink
feat(south): create backend endpoint and repository for generic south…
Browse files Browse the repository at this point in the history
… connector
  • Loading branch information
burgerni10 authored and burgerni10 committed Jun 21, 2023
1 parent 18fde83 commit c95f95f
Show file tree
Hide file tree
Showing 18 changed files with 911 additions and 192 deletions.
43 changes: 43 additions & 0 deletions backend/model/south-connector.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* DTO for South connectors
*/
export interface SouthConnectorDTO {
id: string;
name: string;
type: string;
description: string;
enabled: boolean;
settings: object;
}

/**
* Command DTO for South connector
*/
export interface SouthConnectorCommandDTO {
name: string;
type: string;
description: string;
enabled: boolean;
settings: object;
}

/**
* DTO used for South scan (a point/query/regexp and its settings linked to a scan mode)
*/
export interface SouthScanDTO {
id: string;
name: string;
southId: string;
settings: object;
scanModeId: string;
}

/**
* Command DTO used for South scan (a point/query/folder and its settings linked to a scan mode)
*/
export interface SouthScanCommandDTO {
southId: string;
name: string;
settings: object;
scanModeId: string;
}
5 changes: 3 additions & 2 deletions backend/repository/engine.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
EngineSettingsDTO,
} from "../model/engine.model";
import { generateRandomId } from "./utils";
import { PROXY_TABLE } from "./proxy.repository";

const ENGINE_TABLE = "engine";

Expand Down Expand Up @@ -68,8 +69,8 @@ export default class EngineRepository {
"health_signal_http_interval INTEGER, health_signal_http_verbose INTEGER, health_signal_http_address TEXT, " +
"health_signal_http_proxy_id TEXT, health_signal_http_authentication_type TEXT, health_signal_http_authentication_key TEXT, " +
"health_signal_http_authentication_secret TEXT, " +
"FOREIGN KEY(log_loki_proxy_id) REFERENCES proxy(id), " +
"FOREIGN KEY(health_signal_http_proxy_id) REFERENCES proxy(id));";
`FOREIGN KEY(log_loki_proxy_id) REFERENCES ${PROXY_TABLE}(id), ` +
`FOREIGN KEY(health_signal_http_proxy_id) REFERENCES ${PROXY_TABLE}(id));`;
this.database.prepare(query).run();

this.createEngineSettings(defaultEngineSettings);
Expand Down
2 changes: 1 addition & 1 deletion backend/repository/proxy.repository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { generateRandomId } from "./utils";
import { ProxyCommandDTO, ProxyDTO } from "../model/proxy.model";

const PROXY_TABLE = "proxy";
export const PROXY_TABLE = "proxy";

/**
* Repository used for proxies
Expand Down
2 changes: 1 addition & 1 deletion backend/repository/scan-mode.repository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ScanModeCommandDTO, ScanModeDTO } from "../model/scan-mode.model";
import { generateRandomId } from "./utils";

const SCAN_MODE_TABLE = "scan_mode";
export const SCAN_MODE_TABLE = "scan_mode";

/**
* Repository used for scan modes (cron definitions)
Expand Down
155 changes: 155 additions & 0 deletions backend/repository/south-connector.repository.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import SqliteDatabaseMock from "../tests/__mocks__/database.mock";
import { generateRandomId } from "./utils";
import {
SouthConnectorCommandDTO,
SouthConnectorDTO,
} from "../model/south-connector.model";
import SouthConnectorRepository from "./south-connector.repository";

jest.mock("../tests/__mocks__/database.mock");
jest.mock("./utils", () => ({
generateRandomId: jest.fn(() => "123456"),
}));

let database;
let repository: SouthConnectorRepository;
describe("South connector repository", () => {
beforeEach(() => {
jest.clearAllMocks();
database = new SqliteDatabaseMock();
repository = new SouthConnectorRepository(database);
});

it("should properly init south connector table", () => {
expect(database.prepare).toHaveBeenCalledWith(
"CREATE TABLE IF NOT EXISTS south_connector (id TEXT PRIMARY KEY, name TEXT, type TEXT, description TEXT, " +
"enabled INTEGER, settings TEXT);"
);
expect(database.run).toHaveBeenCalledTimes(1);
});

it("should properly get south connectors", () => {
const expectedValue: Array<SouthConnectorDTO> = [
{
id: "id1",
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: {},
},
{
id: "id2",
name: "south2",
type: "SouthConnector",
description: "My second south connector",
enabled: true,
settings: {},
},
];
database.all.mockReturnValueOnce([
{
id: "id1",
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: JSON.stringify({}),
},
{
id: "id2",
name: "south2",
type: "SouthConnector",
description: "My second south connector",
enabled: true,
settings: JSON.stringify({}),
},
]);
const southConnectors = repository.getSouthConnectors();
expect(database.prepare).toHaveBeenCalledWith(
"SELECT id, name, type, description, enabled, settings FROM south_connector;"
);
expect(southConnectors).toEqual(expectedValue);
});

it("should properly get a south connector", () => {
const expectedValue: SouthConnectorDTO = {
id: "id1",
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: {},
};
database.get.mockReturnValueOnce({
id: "id1",
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: JSON.stringify({}),
});
const southConnector = repository.getSouthConnector("id1");
expect(database.prepare).toHaveBeenCalledWith(
"SELECT id, name, type, description, enabled, settings FROM south_connector WHERE id = ?;"
);
expect(database.get).toHaveBeenCalledWith("id1");
expect(southConnector).toEqual(expectedValue);
});

it("should create a south connector", () => {
const command: SouthConnectorCommandDTO = {
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: {},
};
repository.createSouthConnector(command);
expect(generateRandomId).toHaveBeenCalledWith(6);
expect(database.prepare).toHaveBeenCalledWith(
"INSERT INTO south_connector (id, name, type, description, enabled, settings) VALUES (?, ?, ?, ?, ?, ?);"
);
expect(database.run).toHaveBeenCalledWith(
"123456",
command.name,
command.type,
command.description,
+command.enabled,
JSON.stringify(command.settings)
);

expect(database.prepare).toHaveBeenCalledWith(
"SELECT id, name, type, description, enabled, settings FROM south_connector WHERE ROWID = ?;"
);
});

it("should update a south connector", () => {
const command: SouthConnectorCommandDTO = {
name: "south1",
type: "SouthConnector",
description: "My south connector",
enabled: true,
settings: {},
};
repository.updateSouthConnector("id1", command);
expect(database.prepare).toHaveBeenCalledWith(
"UPDATE south_connector SET name = ?, description = ?, enabled = ?, settings = ? WHERE id = ?;"
);
expect(database.run).toHaveBeenCalledWith(
command.name,
command.description,
+command.enabled,
JSON.stringify(command.settings),
"id1"
);
});

it("should delete a south connector", () => {
repository.deleteSouthConnector("id1");
expect(database.prepare).toHaveBeenCalledWith(
"DELETE FROM south_connector WHERE id = ?;"
);
expect(database.run).toHaveBeenCalledWith("id1");
});
});
112 changes: 112 additions & 0 deletions backend/repository/south-connector.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { generateRandomId } from "./utils";
import {
SouthConnectorCommandDTO,
SouthConnectorDTO,
} from "../model/south-connector.model";

export const SOUTH_CONNECTOR_TABLE = "south_connector";

/**
* Repository used for South connectors (Data sources)
*/
export default class SouthConnectorRepository {
private readonly database;
constructor(database) {
this.database = database;
const query =
`CREATE TABLE IF NOT EXISTS ${SOUTH_CONNECTOR_TABLE} (id TEXT PRIMARY KEY, name TEXT, type TEXT, description TEXT, ` +
`enabled INTEGER, settings TEXT);`;
this.database.prepare(query).run();
}

/**
* Retrieve all South connectors
*/
getSouthConnectors(): Array<SouthConnectorDTO> {
const query = `SELECT id, name, type, description, enabled, settings FROM ${SOUTH_CONNECTOR_TABLE};`;
return this.database
.prepare(query)
.all()
.map((result) => ({
id: result.id,
name: result.name,
type: result.type,
description: result.description,
enabled: result.enabled,
settings: JSON.parse(result.settings),
}));
}

/**
* Retrieve a South connector by its ID
*/
getSouthConnector(id: string): SouthConnectorDTO {
const query = `SELECT id, name, type, description, enabled, settings FROM ${SOUTH_CONNECTOR_TABLE} WHERE id = ?;`;
const result = this.database.prepare(query).get(id);
return {
id: result.id,
name: result.name,
type: result.type,
description: result.description,
enabled: result.enabled,
settings: JSON.parse(result.settings),
};
}

/**
* Create a South connector with a random generated ID
*/
createSouthConnector(command: SouthConnectorCommandDTO): SouthConnectorDTO {
const id = generateRandomId(6);
const insertQuery =
`INSERT INTO ${SOUTH_CONNECTOR_TABLE} (id, name, type, description, enabled, settings) ` +
`VALUES (?, ?, ?, ?, ?, ?);`;
const insertResult = this.database
.prepare(insertQuery)
.run(
id,
command.name,
command.type,
command.description,
+command.enabled,
JSON.stringify(command.settings)
);

const query = `SELECT id, name, type, description, enabled, settings FROM ${SOUTH_CONNECTOR_TABLE} WHERE ROWID = ?;`;
const result = this.database
.prepare(query)
.get(insertResult.lastInsertRowid);
return {
id: result.id,
name: result.name,
type: result.type,
description: result.description,
enabled: result.enabled,
settings: JSON.parse(result.settings),
};
}

/**
* Update a South connector by its ID
*/
updateSouthConnector(id: string, command: SouthConnectorCommandDTO): void {
const query = `UPDATE ${SOUTH_CONNECTOR_TABLE} SET name = ?, description = ?, enabled = ?, settings = ? WHERE id = ?;`;
return this.database
.prepare(query)
.run(
command.name,
command.description,
+command.enabled,
JSON.stringify(command.settings),
id
);
}

/**
* Delete a South Connector by its ID
*/
deleteSouthConnector(id: string): void {
const query = `DELETE FROM ${SOUTH_CONNECTOR_TABLE} WHERE id = ?;`;
return this.database.prepare(query).run(id);
}
}
Loading

0 comments on commit c95f95f

Please sign in to comment.