feat: add administrators, require administrator perms to change server config in webui (#628)
This commit is contained in:
		
							parent
							
								
									eeaac6f07e
								
							
						
					
					
						commit
						103e9bc431
					
				@ -8,6 +8,7 @@
 | 
			
		||||
  "myAddress": "localhost",
 | 
			
		||||
  "httpPort": 80,
 | 
			
		||||
  "httpsPort": 443,
 | 
			
		||||
  "administratorNames": [],
 | 
			
		||||
  "autoCreateAccount": true,
 | 
			
		||||
  "skipStoryModeChoice": true,
 | 
			
		||||
  "skipTutorial": true,
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ import buildConfig from "@/static/data/buildConfig.json";
 | 
			
		||||
 | 
			
		||||
import { toLoginRequest } from "@/src/helpers/loginHelpers";
 | 
			
		||||
import { Account } from "@/src/models/loginModel";
 | 
			
		||||
import { createAccount, isCorrectPassword } from "@/src/services/loginService";
 | 
			
		||||
import { createAccount, isCorrectPassword, isNameTaken } from "@/src/services/loginService";
 | 
			
		||||
import { IDatabaseAccountJson, ILoginResponse } from "@/src/types/loginTypes";
 | 
			
		||||
import { DTLS, groups, HUB, platformCDNs } from "@/static/fixed_responses/login_static";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
@ -26,10 +26,19 @@ export const loginController: RequestHandler = async (request, response) => {
 | 
			
		||||
 | 
			
		||||
    if (!account && config.autoCreateAccount && loginRequest.ClientType != "webui") {
 | 
			
		||||
        try {
 | 
			
		||||
            const nameFromEmail = loginRequest.email.substring(0, loginRequest.email.indexOf("@"));
 | 
			
		||||
            let name = nameFromEmail;
 | 
			
		||||
            if (await isNameTaken(name)) {
 | 
			
		||||
                let suffix = 0;
 | 
			
		||||
                do {
 | 
			
		||||
                    ++suffix;
 | 
			
		||||
                    name = nameFromEmail + suffix;
 | 
			
		||||
                } while (await isNameTaken(name));
 | 
			
		||||
            }
 | 
			
		||||
            const newAccount = await createAccount({
 | 
			
		||||
                email: loginRequest.email,
 | 
			
		||||
                password: loginRequest.password,
 | 
			
		||||
                DisplayName: loginRequest.email.substring(0, loginRequest.email.indexOf("@")),
 | 
			
		||||
                DisplayName: name,
 | 
			
		||||
                CountryCode: loginRequest.lang.toUpperCase(),
 | 
			
		||||
                ClientType: loginRequest.ClientType,
 | 
			
		||||
                CrossPlatformAllowed: true,
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,16 @@
 | 
			
		||||
import { toCreateAccount, toDatabaseAccount } from "@/src/helpers/customHelpers/customHelpers";
 | 
			
		||||
import { createAccount } from "@/src/services/loginService";
 | 
			
		||||
import { createAccount, isNameTaken } from "@/src/services/loginService";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
 | 
			
		||||
const createAccountController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const createAccountData = toCreateAccount(req.body);
 | 
			
		||||
    const databaseAccount = toDatabaseAccount(createAccountData);
 | 
			
		||||
 | 
			
		||||
    const account = await createAccount(databaseAccount);
 | 
			
		||||
 | 
			
		||||
    res.json(account);
 | 
			
		||||
    if (await isNameTaken(createAccountData.DisplayName)) {
 | 
			
		||||
        res.status(409).json("Name already in use");
 | 
			
		||||
    } else {
 | 
			
		||||
        const databaseAccount = toDatabaseAccount(createAccountData);
 | 
			
		||||
        const account = await createAccount(databaseAccount);
 | 
			
		||||
        res.json(account);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { createAccountController };
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,14 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { config } from "@/src/services/configService";
 | 
			
		||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
			
		||||
 | 
			
		||||
const getConfigDataController: RequestHandler = (_req, res) => {
 | 
			
		||||
    res.json(config);
 | 
			
		||||
const getConfigDataController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const account = await getAccountForRequest(req);
 | 
			
		||||
    if (isAdministrator(account)) {
 | 
			
		||||
        res.json(config);
 | 
			
		||||
    } else {
 | 
			
		||||
        res.status(401).end();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { getConfigDataController };
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,16 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { getAccountForRequest, isNameTaken } from "@/src/services/loginService";
 | 
			
		||||
 | 
			
		||||
export const renameAccountController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const account = await getAccountForRequest(req);
 | 
			
		||||
    if (typeof req.query.newname == "string") {
 | 
			
		||||
        account.DisplayName = req.query.newname;
 | 
			
		||||
        await account.save();
 | 
			
		||||
        res.end();
 | 
			
		||||
        if (await isNameTaken(req.query.newname)) {
 | 
			
		||||
            res.status(409).json("Name already in use");
 | 
			
		||||
        } else {
 | 
			
		||||
            account.DisplayName = req.query.newname;
 | 
			
		||||
            await account.save();
 | 
			
		||||
            res.end();
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        res.status(400).end();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,15 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { updateConfig } from "@/src/services/configService";
 | 
			
		||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
			
		||||
 | 
			
		||||
const updateConfigDataController: RequestHandler = async (req, res) => {
 | 
			
		||||
    await updateConfig(String(req.body));
 | 
			
		||||
    res.end();
 | 
			
		||||
    const account = await getAccountForRequest(req);
 | 
			
		||||
    if (isAdministrator(account)) {
 | 
			
		||||
        await updateConfig(String(req.body));
 | 
			
		||||
        res.end();
 | 
			
		||||
    } else {
 | 
			
		||||
        res.status(401).end();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { updateConfigDataController };
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
 | 
			
		||||
    {
 | 
			
		||||
        email: { type: String, required: true, unique: true },
 | 
			
		||||
        password: { type: String, required: true },
 | 
			
		||||
        DisplayName: { type: String, required: true },
 | 
			
		||||
        DisplayName: { type: String, required: true, unique: true },
 | 
			
		||||
        CountryCode: { type: String, required: true },
 | 
			
		||||
        ClientType: { type: String },
 | 
			
		||||
        CrossPlatformAllowed: { type: Boolean, required: true },
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,13 @@ fs.watchFile(configPath, () => {
 | 
			
		||||
        amnesia = false;
 | 
			
		||||
    } else {
 | 
			
		||||
        logger.info("Detected a change to config.json, reloading its contents.");
 | 
			
		||||
 | 
			
		||||
        // Set all values to undefined now so if the new config.json omits some fields that were previously present, it's correct in-memory.
 | 
			
		||||
        for (const key of Object.keys(config)) {
 | 
			
		||||
            // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
 | 
			
		||||
            (config as any)[key] = undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Object.assign(config, JSON.parse(fs.readFileSync(configPath, "utf-8")));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@ -25,6 +32,7 @@ interface IConfig {
 | 
			
		||||
    httpPort?: number;
 | 
			
		||||
    httpsPort?: number;
 | 
			
		||||
    myIrcAddresses?: string[];
 | 
			
		||||
    administratorNames?: string[];
 | 
			
		||||
    autoCreateAccount?: boolean;
 | 
			
		||||
    skipStoryModeChoice?: boolean;
 | 
			
		||||
    skipTutorial?: boolean;
 | 
			
		||||
 | 
			
		||||
@ -2,16 +2,21 @@ import { Account } from "@/src/models/loginModel";
 | 
			
		||||
import { createInventory } from "@/src/services/inventoryService";
 | 
			
		||||
import { IDatabaseAccount, IDatabaseAccountJson } from "@/src/types/loginTypes";
 | 
			
		||||
import { createShip } from "./shipService";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { Document, Types } from "mongoose";
 | 
			
		||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
 | 
			
		||||
import new_personal_rooms from "@/static/fixed_responses/personalRooms.json";
 | 
			
		||||
import { Request } from "express";
 | 
			
		||||
import { config } from "@/src/services/configService";
 | 
			
		||||
 | 
			
		||||
export const isCorrectPassword = (requestPassword: string, databasePassword: string): boolean => {
 | 
			
		||||
    return requestPassword === databasePassword;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const isNameTaken = async (name: string): Promise<boolean> => {
 | 
			
		||||
    return !!(await Account.findOne({ DisplayName: name }));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const createAccount = async (accountData: IDatabaseAccount): Promise<IDatabaseAccountJson> => {
 | 
			
		||||
    const account = new Account(accountData);
 | 
			
		||||
    try {
 | 
			
		||||
@ -44,20 +49,21 @@ export const createPersonalRooms = async (accountId: Types.ObjectId, shipId: Typ
 | 
			
		||||
    await personalRooms.save();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getAccountForRequest = async (req: Request) => {
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/ban-types
 | 
			
		||||
type TAccountDocument = Document<unknown, {}, IDatabaseAccountJson> &
 | 
			
		||||
    IDatabaseAccountJson & { _id: Types.ObjectId; __v: number };
 | 
			
		||||
 | 
			
		||||
export const getAccountForRequest = async (req: Request): Promise<TAccountDocument> => {
 | 
			
		||||
    if (!req.query.accountId) {
 | 
			
		||||
        throw new Error("Request is missing accountId parameter");
 | 
			
		||||
    }
 | 
			
		||||
    if (!req.query.nonce || parseInt(req.query.nonce as string) === 0) {
 | 
			
		||||
        throw new Error("Request is missing nonce parameter");
 | 
			
		||||
    }
 | 
			
		||||
    const account = await Account.findOne(
 | 
			
		||||
        {
 | 
			
		||||
            _id: req.query.accountId,
 | 
			
		||||
            Nonce: req.query.nonce
 | 
			
		||||
        },
 | 
			
		||||
        "_id"
 | 
			
		||||
    );
 | 
			
		||||
    const account = await Account.findOne({
 | 
			
		||||
        _id: req.query.accountId,
 | 
			
		||||
        Nonce: req.query.nonce
 | 
			
		||||
    });
 | 
			
		||||
    if (!account) {
 | 
			
		||||
        throw new Error("Invalid accountId-nonce pair");
 | 
			
		||||
    }
 | 
			
		||||
@ -67,3 +73,7 @@ export const getAccountForRequest = async (req: Request) => {
 | 
			
		||||
export const getAccountIdForRequest = async (req: Request): Promise<string> => {
 | 
			
		||||
    return (await getAccountForRequest(req))._id.toString();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const isAdministrator = (account: TAccountDocument): boolean => {
 | 
			
		||||
    return !!config.administratorNames?.find(x => x == account.DisplayName);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -198,75 +198,80 @@
 | 
			
		||||
                    <div class="col-lg-4">
 | 
			
		||||
                        <div class="card mb-4">
 | 
			
		||||
                            <h5 class="card-header">Server</h5>
 | 
			
		||||
                            <form class="card-body" onsubmit="doChangeSettings();return false;">
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="skipStoryModeChoice" />
 | 
			
		||||
                                    <label class="form-check-label" for="skipStoryModeChoice">Skip Story Mode Choice</label>
 | 
			
		||||
                            <div class="card-body">
 | 
			
		||||
                                <div id="server-settings-no-perms" class="d-none">
 | 
			
		||||
                                    <p>You must be an administrator to use this feature. To become an administrator, add <code>"<span class="displayname"></span>"</code> to <code>administratorNames</code> in the config.json.</p>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="skipTutorial" />
 | 
			
		||||
                                    <label class="form-check-label" for="skipTutorial">Skip Tutorial</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="skipAllDialogue" />
 | 
			
		||||
                                    <label class="form-check-label" for="skipAllDialogue">Skip All Dialogue</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllScans" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllScans">Unlock All Scans</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllMissions" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllMissions">Unlock All Missions</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllQuests" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllQuests">Unlock All Quests</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="completeAllQuests" />
 | 
			
		||||
                                    <label class="form-check-label" for="completeAllQuests">Complete All Quests</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="infiniteCredits" />
 | 
			
		||||
                                    <label class="form-check-label" for="infiniteCredits">Infinite Credits</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="infinitePlatinum" />
 | 
			
		||||
                                    <label class="form-check-label" for="infinitePlatinum">Infinite Platinum</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllShipFeatures" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllShipFeatures">Unlock All Ship Features</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllShipDecorations" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllShipDecorations">Unlock All Ship Decorations</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllFlavourItems" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllFlavourItems">
 | 
			
		||||
                                        Unlock All <abbr title="Animation Sets, Glyphs, Plattes, etc.">Flavor Items</abbr>
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="unlockAllSkins" />
 | 
			
		||||
                                    <label class="form-check-label" for="unlockAllSkins">Unlock All Skins</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input class="form-check-input" type="checkbox" id="universalPolarityEverywhere" />
 | 
			
		||||
                                    <label class="form-check-label" for="universalPolarityEverywhere">
 | 
			
		||||
                                        Universal Polarity Everywhere
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-group mt-2">
 | 
			
		||||
                                    <label class="form-label" for="spoofMasteryRank">
 | 
			
		||||
                                        Spoofed Mastery Rank (-1 to disable)
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                    <input class="form-control" id="spoofMasteryRank" type="number" min="-1" />
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <button class="btn btn-primary mt-3" type="submit">Save Settings</button>
 | 
			
		||||
                            </form>
 | 
			
		||||
                                <form id="server-settings" class="d-none" onsubmit="doChangeSettings();return false;">
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="skipStoryModeChoice" />
 | 
			
		||||
                                        <label class="form-check-label" for="skipStoryModeChoice">Skip Story Mode Choice</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="skipTutorial" />
 | 
			
		||||
                                        <label class="form-check-label" for="skipTutorial">Skip Tutorial</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="skipAllDialogue" />
 | 
			
		||||
                                        <label class="form-check-label" for="skipAllDialogue">Skip All Dialogue</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllScans" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllScans">Unlock All Scans</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllMissions" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllMissions">Unlock All Missions</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllQuests" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllQuests">Unlock All Quests</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="completeAllQuests" />
 | 
			
		||||
                                        <label class="form-check-label" for="completeAllQuests">Complete All Quests</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="infiniteCredits" />
 | 
			
		||||
                                        <label class="form-check-label" for="infiniteCredits">Infinite Credits</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="infinitePlatinum" />
 | 
			
		||||
                                        <label class="form-check-label" for="infinitePlatinum">Infinite Platinum</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllShipFeatures" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllShipFeatures">Unlock All Ship Features</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllShipDecorations" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllShipDecorations">Unlock All Ship Decorations</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllFlavourItems" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllFlavourItems">
 | 
			
		||||
                                            Unlock All <abbr title="Animation Sets, Glyphs, Plattes, etc.">Flavor Items</abbr>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="unlockAllSkins" />
 | 
			
		||||
                                        <label class="form-check-label" for="unlockAllSkins">Unlock All Skins</label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-check">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="universalPolarityEverywhere" />
 | 
			
		||||
                                        <label class="form-check-label" for="universalPolarityEverywhere">
 | 
			
		||||
                                            Universal Polarity Everywhere
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="form-group mt-2">
 | 
			
		||||
                                        <label class="form-label" for="spoofMasteryRank">
 | 
			
		||||
                                            Spoofed Mastery Rank (-1 to disable)
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                        <input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" />
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <button class="btn btn-primary mt-3" type="submit">Save Settings</button>
 | 
			
		||||
                                </form>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="col-lg-4">
 | 
			
		||||
 | 
			
		||||
@ -792,7 +792,7 @@ const uiConfigs = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function doChangeSettings() {
 | 
			
		||||
    fetch("/custom/config")
 | 
			
		||||
    fetch("/custom/config?" + window.authz)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(json => {
 | 
			
		||||
            for (const i of uiConfigs) {
 | 
			
		||||
@ -810,7 +810,7 @@ function doChangeSettings() {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $.post({
 | 
			
		||||
                url: "/custom/config",
 | 
			
		||||
                url: "/custom/config?" + window.authz,
 | 
			
		||||
                contentType: "text/plain",
 | 
			
		||||
                data: JSON.stringify(json, null, 2)
 | 
			
		||||
            });
 | 
			
		||||
@ -820,23 +820,34 @@ function doChangeSettings() {
 | 
			
		||||
// Cheats route
 | 
			
		||||
 | 
			
		||||
single.getRoute("/webui/cheats").on("beforeload", function () {
 | 
			
		||||
    fetch("/custom/config")
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(json =>
 | 
			
		||||
            Object.entries(json).forEach(entry => {
 | 
			
		||||
                const [key, value] = entry;
 | 
			
		||||
                var x = document.getElementById(`${key}`);
 | 
			
		||||
                if (x != null) {
 | 
			
		||||
                    if (x.type == "checkbox") {
 | 
			
		||||
                        if (value === true) {
 | 
			
		||||
                            x.setAttribute("checked", "checked");
 | 
			
		||||
                        }
 | 
			
		||||
                    } else if (x.type == "number") {
 | 
			
		||||
                        x.setAttribute("value", `${value}`);
 | 
			
		||||
                    }
 | 
			
		||||
    let interval;
 | 
			
		||||
    interval = setInterval(() => {
 | 
			
		||||
        if (window.authz) {
 | 
			
		||||
            clearInterval(interval);
 | 
			
		||||
            fetch("/custom/config?" + window.authz).then(res => {
 | 
			
		||||
                if (res.status == 200) {
 | 
			
		||||
                    $("#server-settings").removeClass("d-none");
 | 
			
		||||
                    res.json().then(json =>
 | 
			
		||||
                        Object.entries(json).forEach(entry => {
 | 
			
		||||
                            const [key, value] = entry;
 | 
			
		||||
                            var x = document.getElementById(`${key}`);
 | 
			
		||||
                            if (x != null) {
 | 
			
		||||
                                if (x.type == "checkbox") {
 | 
			
		||||
                                    if (value === true) {
 | 
			
		||||
                                        x.setAttribute("checked", "checked");
 | 
			
		||||
                                    }
 | 
			
		||||
                                } else if (x.type == "number") {
 | 
			
		||||
                                    x.setAttribute("value", `${value}`);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                    );
 | 
			
		||||
                } else {
 | 
			
		||||
                    $("#server-settings-no-perms").removeClass("d-none");
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }, 10);
 | 
			
		||||
 | 
			
		||||
    fetch("http://localhost:61558/ping", { mode: "no-cors" })
 | 
			
		||||
        .then(() => {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user