mirror of
https://github.com/sp-tarkov/server.git
synced 2025-02-13 02:50:44 -05:00
Add MongoID validation to databaseService
- Validate that quests, traders, items and customizations all have MongoID IDs - If any validation fails, output an error and stop server startup
This commit is contained in:
parent
8e8b97ac26
commit
9a8cf9a8a9
@ -66,6 +66,7 @@
|
|||||||
"customisation-unable_to_find_suit_with_id": "Unable to find suit with offer id: %s",
|
"customisation-unable_to_find_suit_with_id": "Unable to find suit with offer id: %s",
|
||||||
"customisation-unable_to_get_trader_suits": "Unable to get suits from trader: %s",
|
"customisation-unable_to_get_trader_suits": "Unable to get suits from trader: %s",
|
||||||
"database-data_at_path_missing": "The database was unable to retrieve data from: [%s] Please ensure your configs are valid and the data at the location exists",
|
"database-data_at_path_missing": "The database was unable to retrieve data from: [%s] Please ensure your configs are valid and the data at the location exists",
|
||||||
|
"database-invalid_data": "Invalid data detected in database, please remove any outdated mods. See previous error for invalid data. Server stopped.",
|
||||||
"database-no_location_found_with_id": "No location found with an Id of: %s in database",
|
"database-no_location_found_with_id": "No location found with an Id of: %s in database",
|
||||||
"database-no_trader_found_with_id": "Unable to find trader: %s in database",
|
"database-no_trader_found_with_id": "Unable to find trader: %s in database",
|
||||||
"dialog-chatbot_id_already_exists": "Chat bot: %s being registered already exists, unable to register bot",
|
"dialog-chatbot_id_already_exists": "Chat bot: %s being registered already exists, unable to register bot",
|
||||||
|
@ -6,11 +6,11 @@ import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
|||||||
import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
|
import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
|
||||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
|
||||||
import { WebSocketServer } from "@spt/servers/WebSocketServer";
|
import { WebSocketServer } from "@spt/servers/WebSocketServer";
|
||||||
import { IHttpListener } from "@spt/servers/http/IHttpListener";
|
import { IHttpListener } from "@spt/servers/http/IHttpListener";
|
||||||
import { LocalisationService } from "@spt/services/LocalisationService";
|
import { LocalisationService } from "@spt/services/LocalisationService";
|
||||||
import { inject, injectAll, injectable } from "tsyringe";
|
import { inject, injectAll, injectable } from "tsyringe";
|
||||||
|
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class HttpServer {
|
export class HttpServer {
|
||||||
@ -19,7 +19,7 @@ export class HttpServer {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject("PrimaryLogger") protected logger: ILogger,
|
@inject("PrimaryLogger") protected logger: ILogger,
|
||||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||||
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
|
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
|
||||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||||
@injectAll("HttpListener") protected httpListeners: IHttpListener[],
|
@injectAll("HttpListener") protected httpListeners: IHttpListener[],
|
||||||
@ -36,6 +36,12 @@ export class HttpServer {
|
|||||||
public load(): void {
|
public load(): void {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
|
|
||||||
|
// If the database couldn't be validated, don't start the server
|
||||||
|
if (!this.databaseService.isDatabaseValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* create server */
|
/* create server */
|
||||||
const httpServer: Server = http.createServer();
|
const httpServer: Server = http.createServer();
|
||||||
|
|
||||||
|
@ -21,16 +21,19 @@ import { ITemplates } from "@spt/models/spt/templates/ITemplates";
|
|||||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||||
import { LocalisationService } from "@spt/services/LocalisationService";
|
import { LocalisationService } from "@spt/services/LocalisationService";
|
||||||
|
import { HashUtil } from "@spt/utils/HashUtil";
|
||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class DatabaseService {
|
export class DatabaseService {
|
||||||
protected locationConfig: ILocationConfig;
|
protected locationConfig: ILocationConfig;
|
||||||
|
protected isDataValid: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject("PrimaryLogger") protected logger: ILogger,
|
@inject("PrimaryLogger") protected logger: ILogger,
|
||||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||||
|
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -322,4 +325,53 @@ export class DatabaseService {
|
|||||||
|
|
||||||
return this.databaseServer.getTables().templates.locationServices;
|
return this.databaseServer.getTables().templates.locationServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that the database doesn't contain invalid ID data
|
||||||
|
*/
|
||||||
|
public validateDatabase(): void {
|
||||||
|
const start = performance.now();
|
||||||
|
|
||||||
|
this.isDataValid =
|
||||||
|
this.validateTable(this.getQuests(), 'quest') &&
|
||||||
|
this.validateTable(this.getTraders(), 'trader') &&
|
||||||
|
this.validateTable(this.getItems(), 'item') &&
|
||||||
|
this.validateTable(this.getCustomization(), 'customization');
|
||||||
|
|
||||||
|
if (!this.isDataValid)
|
||||||
|
{
|
||||||
|
this.logger.error(this.localisationService.getText("database-invalid_data"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateTime = performance.now() - start
|
||||||
|
this.logger.debug(`ID validation took: ${validateTime.toFixed(2)}ms`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the given table only contains valid MongoIDs
|
||||||
|
* @param table Table to validate for MongoIDs
|
||||||
|
* @param tableType The type of table, used in output message
|
||||||
|
* @returns True if the table only contains valid data
|
||||||
|
*/
|
||||||
|
private validateTable(table: Record<string, any>, tableType: string): boolean
|
||||||
|
{
|
||||||
|
for (const tableId in table)
|
||||||
|
{
|
||||||
|
if (!this.hashUtil.isValidMongoId(tableId))
|
||||||
|
{
|
||||||
|
this.logger.error(`Invalid ${tableType} ID: '${tableId}'`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the database is valid
|
||||||
|
* @returns True if the database contains valid data, false otherwise
|
||||||
|
*/
|
||||||
|
public isDatabaseValid(): boolean {
|
||||||
|
return this.isDataValid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,15 @@ export class PostDbLoadService {
|
|||||||
// add items gets left out,causing warnings
|
// add items gets left out,causing warnings
|
||||||
this.itemBaseClassService.hydrateItemBaseClassCache();
|
this.itemBaseClassService.hydrateItemBaseClassCache();
|
||||||
|
|
||||||
|
// Validate that only mongoIds exist in items, quests, and traders
|
||||||
|
// Kill the startup if not.
|
||||||
|
// TODO: We can probably remove this in a couple versions
|
||||||
|
this.databaseService.validateDatabase();
|
||||||
|
if (!this.databaseService.isDatabaseValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.addCustomLooseLootPositions();
|
this.addCustomLooseLootPositions();
|
||||||
|
|
||||||
this.adjustMinReserveRaiderSpawnChance();
|
this.adjustMinReserveRaiderSpawnChance();
|
||||||
|
@ -10,6 +10,7 @@ import { LocalisationService } from "@spt/services/LocalisationService";
|
|||||||
import { EncodingUtil } from "@spt/utils/EncodingUtil";
|
import { EncodingUtil } from "@spt/utils/EncodingUtil";
|
||||||
import { TimeUtil } from "@spt/utils/TimeUtil";
|
import { TimeUtil } from "@spt/utils/TimeUtil";
|
||||||
import { inject, injectAll, injectable } from "tsyringe";
|
import { inject, injectAll, injectable } from "tsyringe";
|
||||||
|
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class App {
|
export class App {
|
||||||
@ -23,6 +24,7 @@ export class App {
|
|||||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||||
@inject("EncodingUtil") protected encodingUtil: EncodingUtil,
|
@inject("EncodingUtil") protected encodingUtil: EncodingUtil,
|
||||||
@inject("HttpServer") protected httpServer: HttpServer,
|
@inject("HttpServer") protected httpServer: HttpServer,
|
||||||
|
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||||
@injectAll("OnLoad") protected onLoadComponents: OnLoad[],
|
@injectAll("OnLoad") protected onLoadComponents: OnLoad[],
|
||||||
@injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[],
|
@injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[],
|
||||||
) {
|
) {
|
||||||
@ -58,7 +60,7 @@ export class App {
|
|||||||
|
|
||||||
protected async update(onUpdateComponents: OnUpdate[]): Promise<void> {
|
protected async update(onUpdateComponents: OnUpdate[]): Promise<void> {
|
||||||
// If the server has failed to start, skip any update calls
|
// If the server has failed to start, skip any update calls
|
||||||
if (!this.httpServer.isStarted()) {
|
if (!this.httpServer.isStarted() || !this.databaseService.isDatabaseValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user