Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(db): Validate input config beforehand #358

Merged
merged 1 commit into from
Oct 10, 2023
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
12 changes: 12 additions & 0 deletions src/common/url.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, it, expect } from "@jest/globals";
import { getHostDomain } from "./url.js";

describe("url", () => {
it("should return the full url if it is a top level domain", () => {
expect(getHostDomain("google.com")).toBe("google.com");
});

it("should sanitize the third-level domains", () => {
expect(getHostDomain("myapp.google.com")).toBe("***.google.com");
});
});
7 changes: 7 additions & 0 deletions src/common/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const getHostDomain = (url: string): string => {
const urlParts = url.split(".");
if (urlParts.length < 3) {
return url;
}
return ["***", urlParts.at(-2), urlParts.at(-1)].join(".");
};
45 changes: 29 additions & 16 deletions src/db/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pg, { type PoolConfig } from "pg";
import { Logger } from "../logger/index.js";
import { getHostDomain } from "../common/url.js";
import { type DbConnectionConfig, validateConfigState } from "./utils.js";
import { NodesClient } from "./nodes.js";
import { UsagesClient } from "./usages.js";
import { Logger } from "../logger/index.js";
import { DonationsClient } from "./donations.js";
import { UsedEmailClient } from "./emails.js";
import { DurationsClient } from "./durations.js";
Expand Down Expand Up @@ -35,15 +37,6 @@ const getPool = (config: DbConnectionConfig, threadId: number): pg.Pool => {
});
};

export type DbConnectionConfig = {
user: string;
password: string;
host: string;
database: string;
port: number;
certificate?: string;
};

export class DbClient {
public readonly nodes: NodesClient;
public readonly usages: UsagesClient;
Expand All @@ -56,17 +49,27 @@ export class DbClient {
private ready = false;

constructor(config: DbConnectionConfig, threadId = 0, p?: pg.Pool) {
const { certificate, ...cfg } = config;
this.initialized = Object.values(cfg).every((val) => val);
const configState = validateConfigState(config);
const domain = config.host ? getHostDomain(config.host) : "missing.domain";
logger.info(`Initializing the database ${Logger.y(domain)}`);
this.initialized = configState !== "invalid";
if (!this.initialized) {
logger.error(
"Missing connection data for postgres server. Check the config",
new Error("Missing connection data for postgres server"),
`Missing connection data for postgres server. Check the config for ${Logger.y(
domain,
)}`,
new Error("Missing connection data for postgres server", {
cause: {
domain,
},
}),
);
}
if (!certificate) {
if (configState === "unsecure") {
logger.warn(
"Postgres connection is not secure, ssl certificate is not provided",
`Postgres connection is not secure, ssl certificate is not provided for ${Logger.y(
domain,
)}`,
);
}

Expand Down Expand Up @@ -103,6 +106,16 @@ export class DbClient {
return this.ready;
}

public setSecondary(): this {
this.nodes.setSecondary();
this.usages.setSecondary();
this.donations.setSecondary();
this.emails.setSecondary();
this.durations.setSecondary();
this.ignoredChats.setSecondary();
return this;
}

private setParsers(): void {
pg.types.setTypeParser(pg.types.builtins.INT8, (val) => parseInt(val));
}
Expand Down
32 changes: 22 additions & 10 deletions src/db/donations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ const logger = new Logger("postgres-donations");

export class DonationsClient {
private readonly db: DonationsDb;
private secondary = false;

constructor(pool: Pool) {
this.db = new DonationsDb(pool);
}

public init(): Promise<void> {
logger.info("Initializing the table");
this.logInfo("Initializing the table");
return this.db
.init()
.then(() =>
logger.info(`Table ${Logger.y("donations")} has been initialized`),
this.logInfo(`Table ${Logger.y("donations")} has been initialized`),
)
.catch((err) => {
logger.error(
Expand All @@ -31,18 +32,21 @@ export class DonationsClient {
});
}

public setSecondary(): void {
this.secondary = true;
}

public updateRow(
donationId: number,
status: DonationStatus,
): Promise<DonationRowScheme> {
logger.info(`Updating the row with id=${donationId}`);
this.logInfo(`Updating the row with id=${donationId}`);
return this.db
.updateRow(donationId, status)
.then((row) => {
const id = this.getRowId(row);
logger.info(
`The row with id=${donationId} has been updated`,
id === donationId,
this.logInfo(
`The row with id=${donationId} has been updated ${id === donationId}`,
);
return row;
})
Expand All @@ -53,12 +57,12 @@ export class DonationsClient {
}

public createRow(chatId: number, price: number): Promise<DonationRowScheme> {
logger.info("Creating a new row");
this.logInfo("Creating a new row");
return this.db
.createRow(chatId, price)
.then((row) => {
const donationId = this.getRowId(row);
logger.info(`The row with id=${donationId} has been created`);
this.logInfo(`The row with id=${donationId} has been created`);
return row;
})
.catch((err) => {
Expand All @@ -68,11 +72,11 @@ export class DonationsClient {
}

public getPendingRows(): Promise<DonationRowScheme[]> {
logger.info(`Looking for rows for status=${DonationStatus.Pending}`);
this.logInfo(`Looking for rows for status=${DonationStatus.Pending}`);
return this.db
.getRows(DonationStatus.Pending)
.then((rows) => {
logger.info(
this.logInfo(
`Row search has been executed for status=${DonationStatus.Pending}`,
);
return rows;
Expand All @@ -89,4 +93,12 @@ export class DonationsClient {
public getRowId(row: DonationRowScheme): number {
return this.db.getId(row);
}

private logInfo(message: string): void {
if (this.secondary) {
return;
}

logger.info(message);
}
}
21 changes: 17 additions & 4 deletions src/db/durations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ const logger = new Logger("postgres-durations");

export class DurationsClient {
private readonly db: DurationsDb;
private secondary = false;

constructor(pool: Pool) {
this.db = new DurationsDb(pool);
}

public init(): Promise<void> {
logger.info("Initializing the table");
this.logInfo("Initializing the table");
return this.db
.init()
.then(() =>
logger.info(`Table ${Logger.y("durations")} has been initialized`),
this.logInfo(`Table ${Logger.y("durations")} has been initialized`),
)
.catch((err) => {
logger.error(
Expand All @@ -27,21 +28,33 @@ export class DurationsClient {
});
}

public setSecondary(): void {
this.secondary = true;
}

public createRow(
chatId: number,
duration: number,
): Promise<DurationRowScheme> {
logger.info("Creating a new row");
this.logInfo("Creating a new row");
return this.db
.createRow(chatId, duration)
.then((row) => {
const durationId = this.db.getId(row);
logger.info(`The row with id=${durationId} has been created`);
this.logInfo(`The row with id=${durationId} has been created`);
return row;
})
.catch((err) => {
logger.error("Unable to create a row", err);
throw err;
});
}

private logInfo(message: string): void {
if (this.secondary) {
return;
}

logger.info(message);
}
}
32 changes: 22 additions & 10 deletions src/db/emails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ const logger = new Logger("postgres-emails");

export class UsedEmailClient {
private readonly db: UsedEmailDb;
private secondary = false;

constructor(pool: Pool) {
this.db = new UsedEmailDb(pool);
}

public init(): Promise<void> {
logger.info("Initializing the table");
this.logInfo("Initializing the table");
return this.db
.init()
.then(() =>
logger.info(`Table ${Logger.y("usedemails")} has been initialized`),
this.logInfo(`Table ${Logger.y("usedemails")} has been initialized`),
)
.catch((err) => {
logger.error(
Expand All @@ -27,16 +28,19 @@ export class UsedEmailClient {
});
}

public setSecondary(): void {
this.secondary = true;
}

public updateRow(emailId: number): Promise<UsedEmailRowScheme> {
logger.info(`Updating the row with id=${emailId}`);
this.logInfo(`Updating the row with id=${emailId}`);

return this.db
.updateRow(emailId)
.then((row) => {
const id = this.getRowId(row);
logger.info(
`The row with id=${emailId} has been updated`,
id === emailId,
this.logInfo(
`The row with id=${emailId} has been updated ${id === emailId}`,
);
return row;
})
Expand All @@ -47,12 +51,12 @@ export class UsedEmailClient {
}

public createRow(email: string): Promise<UsedEmailRowScheme> {
logger.info("Creating a new row");
this.logInfo("Creating a new row");
return this.db
.createRow(email)
.then((row) => {
const emailId = this.getRowId(row);
logger.info(`The row with id=${emailId} has been created`);
this.logInfo(`The row with id=${emailId} has been created`);
return row;
})
.catch((err) => {
Expand All @@ -62,11 +66,11 @@ export class UsedEmailClient {
}

public getRows(email: string): Promise<UsedEmailRowScheme[]> {
logger.info(`Looking for rows for email=${email}`);
this.logInfo(`Looking for rows for email=${email}`);
return this.db
.getRows(email)
.then((rows) => {
logger.info(`Row search has been executed for email=${email}`);
this.logInfo(`Row search has been executed for email=${email}`);
return rows;
})
.catch((err) => {
Expand All @@ -78,4 +82,12 @@ export class UsedEmailClient {
public getRowId(row: UsedEmailRowScheme): number {
return this.db.getId(row);
}

private logInfo(message: string): void {
if (this.secondary) {
return;
}

logger.info(message);
}
}
21 changes: 17 additions & 4 deletions src/db/ignoredchats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ const logger = new Logger("postgres-ignored-chats");

export class IgnoredChatsClient {
private readonly db: IgnoredChatsDb;
private secondary = false;

constructor(pool: Pool) {
this.db = new IgnoredChatsDb(pool);
}

public init(): Promise<void> {
logger.info("Initializing the table");
this.logInfo("Initializing the table");
return this.db
.init()
.then(() =>
logger.info(`Table ${Logger.y("ignoredchats")} has been initialized`),
this.logInfo(`Table ${Logger.y("ignoredchats")} has been initialized`),
)
.catch((err) => {
logger.error(
Expand All @@ -30,17 +31,29 @@ export class IgnoredChatsClient {
});
}

public setSecondary(): void {
this.secondary = true;
}

public getRow(chatId: number): Promise<IgnoredChatsRowScheme | null> {
logger.info(`Looking for row for chatId=${chatId}`);
this.logInfo(`Looking for row for chatId=${chatId}`);
return this.db
.getRow(chatId)
.then((row) => {
logger.info(`Row search has been executed for chatId=${chatId}`);
this.logInfo(`Row search has been executed for chatId=${chatId}`);
return row;
})
.catch((err) => {
logger.error(`Unable provide a search for chatId=${chatId}`, err);
throw err;
});
}

private logInfo(message: string): void {
if (this.secondary) {
return;
}

logger.info(message);
}
}
Loading