Files
few-line-engine/src/databaseManager/databaseNode/database.node.service.ts

114 lines
3.1 KiB
TypeScript

import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { DatabaseNode } from "../entities/database.node.entity";
import { Repository } from "typeorm";
import { DatabaseEncryptionService } from "../database.encryption.service";
import * as mysql from "mysql2/promise";
@Injectable()
export class DatabaseNodeService extends DatabaseEncryptionService {
constructor(
@InjectRepository(DatabaseNode)
private databaseNodeRepository: Repository<DatabaseNode>
) {
super();
}
async findById(id: string): Promise<DatabaseNode | null> {
return this.databaseNodeRepository.findOne({ where: { id } });
}
async findOptimalNode(): Promise<DatabaseNode | null> {
const nodes = await this.databaseNodeRepository.find({
relations: ["databases"],
});
if (nodes.length === 0) {
return null;
}
nodes.sort((a, b) => a.databases.length - b.databases.length);
return nodes[0];
}
async initDatabase(
data: {
database: string;
c_username: string;
q_username: string;
password: string;
},
databaseNodeId: string
): Promise<void> {
try {
const dbConnection = await mysql.createConnection({
...(await this.getConnectionOptions(databaseNodeId)),
enableKeepAlive: true,
});
await dbConnection.execute(`CREATE DATABASE \`${data.database}\`;`);
await dbConnection.execute(
`CREATE USER '${data.c_username}'@'%' IDENTIFIED BY '${data.password}';`
);
await dbConnection.execute(
`CREATE USER '${data.q_username}'@'%' IDENTIFIED BY '${data.password}';`
);
await dbConnection.execute(
`GRANT ALL PRIVILEGES ON \`${data.database}\`.* TO '${data.c_username}'@'%';`
);
await dbConnection.execute(
`GRANT SELECT, SHOW VIEW ON \`${data.database}\`.* TO '${data.q_username}'@'%';`
);
await dbConnection.execute(`FLUSH PRIVILEGES;`);
await dbConnection.end();
} catch (error) {
console.error("Error initializing database:", error);
throw error;
}
}
async create(
host: string,
port: number,
username: string,
password: string
): Promise<DatabaseNode> {
const existingNode = await this.databaseNodeRepository.findOne({
where: { host, port },
});
if (existingNode) {
existingNode.password = this.encryptPassword(password);
existingNode.username = username;
return this.databaseNodeRepository.save(existingNode);
}
const encryptedPassword = this.encryptPassword(password);
const databaseNode = this.databaseNodeRepository.create({
host,
port,
username,
password: encryptedPassword,
});
return this.databaseNodeRepository.save(databaseNode);
}
async getConnectionOptions(id: string) {
const node = await this.databaseNodeRepository.findOne({ where: { id } });
if (!node) {
throw new Error("Database node not found");
}
return {
host: node.host,
port: node.port,
user: node.username,
password: this.decryptPassword(node.password),
};
}
}