import { Schema } from 'jsonschema' import { TestUsersSchema, isJsonValidAndLogError, PeersInfoSchema, ModulesSchema, SelfInfoSchema, } from '../types/typeSchemas' import logger from './logger' import utils from './utils' // FIXME: remove all file exists checks from everywhere for files that are created / checked here type FileDescriptor = { path: string schema?: Schema defaultValue?: string shouldBe?: string description?: string } export const validateFiles = (): boolean => { let everythingValid = true Object.entries(files).forEach(([key, file]: [string, FileDescriptor]) => { let fileExists = utils.FileExists(file.path) if (file.defaultValue != null && !fileExists) { // FIXME: create path too utils.WriteFile(file.defaultValue, file.path) fileExists = true } if (file.shouldBe && !fileExists) { const errMsg = [`File "${file.path}" does not exist! (${key})`] if (file.shouldBe) { errMsg.push(`Should be: ${file.shouldBe}`) } logger.Log(errMsg.join(' '), 'redbg') everythingValid = false return } if (file.schema && fileExists) { const val = utils.ReadJSON(file.path) if (!isJsonValidAndLogError(val, file.schema, file.path)) { everythingValid = false return } } }) return everythingValid } export const files = { // -------------------------------------------------------------------------------- // server / modules files // -------------------------------------------------------------------------------- serverPath: { path: 'dist/server.js', shouldBe: 'server main entry file, created after running "npm run build"', }, qminingPageDir: { path: 'submodules/qmining-page', shouldBe: 'qmining page submodule directory, created by pulling submodules / setup script', }, qminingIndexPath: { path: 'nextStatic/qminingPagePublic/index.html', shouldBe: 'qmining page-s build index.html, created by "npm run build" in qmining page submodule dir', }, dataEditorPageDir: { path: 'submodules/qmining-data-editor', shouldBe: 'qmining data editor page submodule directory, created by pulling submodules / setup script', }, dataEditorIndexPath: { path: 'nextStatic/dataEditorPublic/index.html', shouldBe: 'qmining data editor-s build index.html, created by "npm run build" in qmining data editor submodule dir', }, moodleTestUserscriptDir: { path: 'submodules/moodle-test-userscript', shouldBe: 'moodle test userscript submodule directory, created by pulling submodules / setup script', }, moodleTestUserscriptPath: { path: 'submodules/moodle-test-userscript/stable.user.js', shouldBe: 'moodle test userscript file, created by pulling submodules / setup script', }, domainFile: { path: 'data/domain', shouldBe: 'server domain for cookies and stuff, for ex.: "frylabs.net", no "http://" and things like that, just the domain', }, // -------------------------------------------------------------------------------- // stats files // -------------------------------------------------------------------------------- registeredScriptsFile: { path: 'stats/registeredScripts.json', defaultValue: JSON.stringify([]), }, askedQuestionFile: { path: 'stats/askedQuestions', description: 'text file of recieved data on /ask', }, recievedQuestionFile: { path: 'stats/recievedQuestions', description: 'text file of recieved data on /isAdding', }, dailyDataCountFile: { path: 'stats/dailyDataCount', description: 'text file of daily data count', }, dataEditsLog: { path: 'stats/dataEdits', description: 'text file of data edit logs', }, // -------------------------------------------------------------------------------- // https files // -------------------------------------------------------------------------------- privkeyFile: { path: '/etc/letsencrypt/live/frylabs.net/privkey.pem', description: 'private key file for https', }, fullchainFile: { path: '/etc/letsencrypt/live/frylabs.net/fullchain.pem', description: 'full chain key file for https', }, chainFile: { path: '/etc/letsencrypt/live/frylabs.net/chain.pem', description: 'chain key file for https', }, // -------------------------------------------------------------------------------- // api files // -------------------------------------------------------------------------------- rootRedirectToFile: { path: 'data/apiRootRedirectTo', description: 'url to redirect users trying to acces root api path', }, modulesFile: { path: './src/modules.json', shouldBe: 'module files for server', schema: ModulesSchema, }, extraModulesFile: { path: './src/extraModules/extraModules.json', description: 'extra private modules for server, not tracked by git', schema: ModulesSchema, }, statExcludeFile: { path: './data/statExclude.json', shouldBe: 'array of strings which if included in requests url-s then the request itself is not counted in stats', defaultValue: JSON.stringify([]), schema: { type: 'array', items: { type: 'string' } }, }, usersDBPath: { path: './data/dbs/users.db', shouldBe: 'users sqlite db file', }, // -------------------------------------------------------------------------------- // qmining api // -------------------------------------------------------------------------------- testUsersFile: { path: 'data/testUsers.json', defaultValue: JSON.stringify({ userIds: [] }), schema: TestUsersSchema, description: 'test users, recieved data from them wont get added to question dbs', }, // -------------------------------------------------------------------------------- // log files // -------------------------------------------------------------------------------- vlogDir: { path: 'stats/vlogs/', description: 'verbose logs directory', }, logDir: { path: 'stats/logs/', description: 'basic logs directory', }, statFile: { path: 'stats/stats', defaultValue: JSON.stringify({}), description: 'json of visited paths all time', }, vStatFile: { path: 'stats/vstats', defaultValue: JSON.stringify({}), description: 'json of visited paths by day', }, uStatsFile: { path: 'stats/ustats', defaultValue: JSON.stringify({}), description: 'json of visits per user', }, uvStatsFile: { path: 'stats/uvstats', defaultValue: JSON.stringify({}), description: 'json of visits per user by day', }, nologFile: { path: './data/nolog', defaultValue: '', description: 'text file of users seperated by new lines to ignore in logging / stats', }, // -------------------------------------------------------------------------------- // peer files // -------------------------------------------------------------------------------- peersPath: { path: 'data/p2p/', description: 'p2p files directory', }, peersFile: { path: 'data/p2p/peers.json', description: 'json of list of peers', defaultValue: JSON.stringify([]), schema: PeersInfoSchema, }, selfInfoFile: { path: 'data/p2p/selfInfo.json', description: 'json of info of this servers peer functionality', defaultValue: JSON.stringify({}), schema: SelfInfoSchema, }, thirdPartyPeersFile: { path: 'data/p2p/thirdPartyPeers.json', description: 'json of third party peers reported by other peers', }, keyFile: { path: 'data/p2p/key', }, } as const satisfies Record export const paths = Object.entries(files).reduce( (acc, [key, value]) => ({ ...acc, [key]: value.path }), {} ) as Record