diff --git a/README.md b/README.md index 8bfd120..ce553e8 100755 --- a/README.md +++ b/README.md @@ -38,17 +38,21 @@ threads, and serve more requests at once. The used cores can be limited with env Run `./scripts/setup.sh`, then `npm run dev` for development, or `npm run start` for prod. -**Gitlab specific notes**: You need a gitlab account with SSH keys set up in order to be able to use -SSH for cloning this (and any) project. This includes git modules of this project. See -`CLONE_WITH_HTTPS` in environment variables below. - On the first run there will be a number of errors, that some files weren't found. Please create them according to the messages, these are necessary for the server to function. There will be also a lot of information about files and other necessary things being created. **Please read them very carefully, you should know about what was created!** -The setup script can be also used to update and rebuild all git modules. +### Setup notes + + * **Gitlab specific notes**: You need a gitlab account with SSH keys set up in order to be able to use + SSH for cloning this (and any) project. This includes git modules of this project. See + `CLONE_WITH_HTTPS` in environment variables below. + * The `DOMAIN` env var can be replaced by making the file `./data/domain`. This is necesarry, to make + xmlhttp requests and some redirects work in statically built HTML files (by next.js), in the + userscript, and in the server itself. + * The setup script can be also used to update and rebuild all git modules. ## Web server paths @@ -63,12 +67,12 @@ server instances, and merge the response data to its own databases. To setup P2P functionality you have to create a few files in `./data/p2p`: * `selfInfo.json`: information of this peer. Required: - ``` + ```json { "name": "any name you choose", "contact": "contact to server administrator (irc server, e-mail, anything)", "host": "server host (like somesite.com, without 'http(s):// and /-s')", - "pw": "password to the host, so the server can log in there", + "pw": "password to the host, so the server can log in there. Please use a dedicated password, that only the server uses!", "port": "server port, number" } ``` @@ -153,13 +157,14 @@ result can be found in the directory it was ran. | NS_LOGLEVEL | number | Debug log level, 0 is the least verbose | | NS_NOLOG | boolean | If logging should be skipped | | NS_SQL_DEBUG_LOG | boolean | If the SQL queries should be logged | + | DOMAIN | string | The domain that the server should use for redirects, cookies, etc. ex.: `qmining.com`, without 'https://', and '/'-s. If not specified `./data/domain` will be used | -### For the setup script +### For the setup script (`./scripts/setup.sh`) | Name | Type | Description | | --- | --- | --- | | CLONE_WITH_HTTPS | boolean | By default git clones with ssh, which can cause troubles. Set this - to use https for git modules | + | DOMAIN | string | The domain that the server should use for redirects, cookies, etc. ex.: `qmining.com`, without 'https://', and '/'-s. If not specified `./data/domain` will be used | ## npm scripts @@ -209,7 +214,7 @@ https://gitlab.com/MrFry/moodle-test-userscript │ ├── admins.json forum admins. should be removed and should use admin column from user db │ ├── apiRootRedirectTo url where domain/api should redirect to │ ├── dbs/ directory for databases, and for their backups -│ ├── domain the domain the server is hosted on +│ ├── domain the domain the server is hosted on. Used when `DOMAIN` env var is empty │ ├── f/ user files received TODO: check if this is needed │ ├── links.json urls for irc, patreon and donate │ ├── nolog ids of users separated by new lines to ignore on logging diff --git a/scripts/setup.sh b/scripts/setup.sh index 431be56..939689b 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -38,10 +38,18 @@ makeNextSubmodule() { checkFile "$PWD/src/server.ts" checkFile "$PWD/package.json" checkFile "$PWD/package-lock.json" -if [ ! -f "${domainPath}" ]; then - error "${domainPath} does not exist!" - echo "Please create it, and re-run this script." - echo "Expected content: domain, ex.:'frylabs.net' (without http:// and /)" + +domain="${DOMAIN}" + +if [ -z "${domain}" ] && [ -f "${domainPath}" ]; then + domain=$(cat "${domainPath}") +fi + +if [ -z "${domain}" ]; then + error "DOMAIN is not set, and ${domainPath} does not exist!" + echo "Set DOMAIN to the preferred domain" + echo "Or please create the file ${domainPath}, and re-run this script" + echo "Expected content: domain, ex.:'frylabs.net' (without 'http://' and '/')" exit 1 fi @@ -113,3 +121,4 @@ fi # ------------------------------------------------------------------------------------ log "Done! development mode: 'npm run dev', prod mode: 'npm run start', tests: 'npm run test'" +exit 0 diff --git a/src/constants.json b/src/constants.json deleted file mode 100644 index 8a940bd..0000000 --- a/src/constants.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "savedQuestionsFileName": "savedQuestions.json" -} diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..eb90e87 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,15 @@ +import { paths } from './utils/files' +import utils from './utils/utils' + +const domain = process.env.DOMAIN || utils.ReadFile(paths.domainFile).trim() + +if (!domain) { + throw new Error( + `Domain is undefined! Should be set with 'DOMAIN' environment variable, or written to '${paths.domainFile}'` + ) +} + +export default { + savedQuestionsFileName: 'savedQuestions.json', + domain: domain, +} diff --git a/src/middlewares/auth.middleware.ts b/src/middlewares/auth.middleware.ts index 916cfb6..e9a559a 100644 --- a/src/middlewares/auth.middleware.ts +++ b/src/middlewares/auth.middleware.ts @@ -24,10 +24,7 @@ import type { Database } from 'better-sqlite3' import logger from '../utils/logger' import dbtools from '../utils/dbtools' -import { paths } from '../utils/files' -import utils from '../utils/utils' - -const domain = utils.ReadFile(paths.domainFile).trim() +import constants from '../constants' interface Options { userDB: Database @@ -56,7 +53,7 @@ function renderLogin(req: Request, res: Response) { } else { res.render('login', { useHttp: process.env.NS_NO_HTTPS_FORCE, - domain: domain, + domain: constants.domain, }) } } diff --git a/src/modules/api/submodules/p2p.ts b/src/modules/api/submodules/p2p.ts index f3bcee2..69cbbf4 100644 --- a/src/modules/api/submodules/p2p.ts +++ b/src/modules/api/submodules/p2p.ts @@ -96,6 +96,7 @@ interface SyncDataRes { function updateThirdPartyPeers( newVal: Omit[] ) { + // TODO: check if thirdPartyPeersFile exists! const prevVal = utils.ReadJSON(paths.thirdPartyPeersFile) const dataToWrite = newVal.reduce((acc, peer) => { const isIncluded = acc.find((x) => { @@ -963,6 +964,7 @@ function setup(data: SubmoduleData): Submodule { remoteInfo: getSelfInfo(), } + // TODO: hostname is invalid, should be remote host? let hostToLog = req.hostname if (remoteHost) { const remotePeerInfo = peers.find((peer) => { @@ -998,6 +1000,7 @@ function setup(data: SubmoduleData): Submodule { ) if (remoteHost.includes(':')) { const [host, port] = remoteHost.split(':') + // TODO: add public key updateThirdPartyPeers([ { host: host, diff --git a/src/modules/api/submodules/qminingapi.ts b/src/modules/api/submodules/qminingapi.ts index fd12029..16313f5 100644 --- a/src/modules/api/submodules/qminingapi.ts +++ b/src/modules/api/submodules/qminingapi.ts @@ -60,7 +60,7 @@ import { SearchResultQuestion, } from '../../../utils/qdbUtils' import { paths } from '../../../utils/files' -import constants from '../../../constants.json' +import constants from '../../../constants' import { isJsonValidAndLogError, TestUsersSchema, diff --git a/src/server.ts b/src/server.ts index 5631b83..4f8ef43 100755 --- a/src/server.ts +++ b/src/server.ts @@ -42,6 +42,7 @@ import dbtools from './utils/dbtools' import reqlogger from './middlewares/reqlogger.middleware' import idStats from './utils/ids' import { paths, validateFiles } from './utils/files' +import constants from './constants' const logFile = paths.logDir + logger.logFileName const vlogFile = paths.vlogDir + logger.logFileName @@ -226,8 +227,6 @@ app.use( }) ) -const domain = utils.ReadFile(paths.domainFile).trim() - Object.keys(modules).forEach(function (key) { const module = modules[key] try { @@ -240,7 +239,7 @@ Object.keys(modules).forEach(function (key) { if (mod.setup) { mod.setup({ - url: domain, + url: constants.domain, userDB: userDB, publicdirs: module.publicdirs, nextdir: module.nextdir, @@ -268,7 +267,7 @@ app.get('*', (req, res) => { if (req.is('application/json')) { res.status(404).end() } else { - res.status(404).render('404', { domain: domain }) + res.status(404).render('404', { domain: constants.domain }) } }) diff --git a/src/utils/files.ts b/src/utils/files.ts index ad1edfa..8910077 100644 --- a/src/utils/files.ts +++ b/src/utils/files.ts @@ -124,9 +124,8 @@ export const files = { domainFile: { path: 'data/domain', - errorIfMissing: true, description: - 'server domain for cookies and stuff, for ex.: "frylabs.net", no "http://" and things like that, just the domain', + 'server domain for cookies and stuff, for ex.: "qmining.com", no "http://" and things like that, just the domain', }, // -------------------------------------------------------------------------------- // stats files