114 lines
3.1 KiB
TypeScript
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),
|
|
};
|
|
}
|
|
}
|