diff --git a/.env.example b/.env.example index 0d9bf9d..22b3a14 100644 --- a/.env.example +++ b/.env.example @@ -44,4 +44,7 @@ USE_SECURITY_LIMIT = (true|false) # default ist true SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500 -TRUST_PROXY = # wenn leer, wird dieser Wert nicht angewendet. \ No newline at end of file +TRUST_PROXY = # wenn leer, wird dieser Wert nicht angewendet. + +WEBAPI_URL = webapi host url +WEBAPI_TOKEN = webapi token \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7410d05..d20a6de 100644 --- a/.gitignore +++ b/.gitignore @@ -133,4 +133,5 @@ dist files .idea -*.db \ No newline at end of file +*.db +.npmrc \ No newline at end of file diff --git a/.npmrc.example b/.npmrc.example new file mode 100644 index 0000000..842fb8b --- /dev/null +++ b/.npmrc.example @@ -0,0 +1,2 @@ +@ff-admin:registry=https://npm.registry.jk-effects.cloud +//npm.registry.jk-effects.cloud/:_authToken="xxx" # hier optional token einfügen - ff-admin packages sind öffentlich \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index abc3c61..dce2290 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "license": "AGPL-3.0-only", "dependencies": { + "@ff-admin/webapi-client": "^1.1.1", "@socket.io/admin-ui": "^0.5.1", "cors": "^2.8.5", "dotenv": "^16.4.5", @@ -87,6 +88,16 @@ "node": ">=12" } }, + "node_modules/@ff-admin/webapi-client": { + "version": "1.1.1", + "resolved": "https://npm.registry.jk-effects.cloud/@ff-admin/webapi-client/-/webapi-client-1.1.1.tgz", + "integrity": "sha512-vqUrHSXcVPIXZ7lmlw5l1dm+NRI2eCQf3fkyMiCfIYdCLaHfnOmponvqjG0urgBENazch5Gk+yWW7BNBI13Bwg==", + "license": "AGPL-3.0-only", + "dependencies": { + "axios": "^1.6.2", + "typeorm": "^0.3.20" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -716,6 +727,23 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1259,6 +1287,18 @@ "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1432,6 +1472,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1676,6 +1725,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -1824,6 +1888,26 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -1839,6 +1923,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2067,6 +2166,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3535,6 +3649,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", diff --git a/package.json b/package.json index 8d6f71b..3d2797d 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "author": "JK Effects", "license": "AGPL-3.0-only", "dependencies": { + "@ff-admin/webapi-client": "^1.1.1", "@socket.io/admin-ui": "^0.5.1", "cors": "^2.8.5", "dotenv": "^16.4.5", diff --git a/src/env.defaults.ts b/src/env.defaults.ts index eed7d89..9a046ba 100644 --- a/src/env.defaults.ts +++ b/src/env.defaults.ts @@ -23,7 +23,7 @@ export const MAIL_PORT = Number(process.env.MAIL_PORT ?? "587"); export const MAIL_SECURE = process.env.MAIL_SECURE ?? "false"; export const CLUB_NAME = process.env.CLUB_NAME ?? "FF Admin"; -export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? ""; +export const CLUB_WEBSITE = (process.env.CLUB_WEBSITE ?? "") == "" ? null : new URL(process.env.CLUB_WEBSITE); //process.env.CLUB_WEBSITE ?? ""; export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1"); export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7"); @@ -54,6 +54,9 @@ export const TRUST_PROXY = ((): Array | string | boolean | number | null return null; })(); +export const WEBAPI_URL = (process.env.WEBAPI_URL ?? "") == "" ? null : new URL(process.env.WEBAPI_URL); +export const WEBAPI_TOKEN = process.env.WEBAPI_TOKEN ?? ""; + export function configCheck() { if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres") throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)"); @@ -78,10 +81,7 @@ export function configCheck() { if (isNaN(MAIL_PORT)) throw new Error("set valid numeric value to MAIL_PORT"); if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE"); - if ( - CLUB_WEBSITE != "" && - !/^(http(s):\/\/.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/.test(CLUB_WEBSITE) - ) + if (CLUB_WEBSITE != null && !(CLUB_WEBSITE.protocol == "https:" || CLUB_WEBSITE.protocol == "http:")) throw new Error("CLUB_WEBSITE is not valid url"); if (BACKUP_AUTO_RESTORE != "true" && BACKUP_AUTO_RESTORE != "false") @@ -102,6 +102,11 @@ export function configCheck() { if (!TRUST_PROXY && process.env.TRUST_PROXY) { throw new Error("set valid boolean, number, ip or ips value to TRUST_PROXY"); } + + if (WEBAPI_URL != null && !(WEBAPI_URL.protocol == "https:" || WEBAPI_URL.protocol == "http:")) + throw new Error("WEBAPI_URL is not valid url"); + + if (WEBAPI_URL != null && WEBAPI_TOKEN == "") throw new Error("WEBAPI_TOKEN is empty though WEBAPI_URL is set"); } function checkMS(input: string, origin: string) { diff --git a/src/index.ts b/src/index.ts index 45edc90..4fe112c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,7 @@ import "dotenv/config"; import express from "express"; import { createServer } from "http"; -import { BACKUP_AUTO_RESTORE, configCheck, SERVER_PORT } from "./env.defaults"; +import { BACKUP_AUTO_RESTORE, configCheck, SERVER_PORT, WEBAPI_TOKEN, WEBAPI_URL } from "./env.defaults"; configCheck(); import { PermissionObject } from "./type/permissionTypes"; @@ -29,6 +29,9 @@ dataSource.initialize().then(async () => { } }); +import webapiClient from "./webapi-client"; +if (WEBAPI_URL && WEBAPI_TOKEN) webapiClient.initialize(); + const app = express(); import router from "./routes/index"; router(app); diff --git a/src/webapi-client.ts b/src/webapi-client.ts new file mode 100644 index 0000000..5f462c2 --- /dev/null +++ b/src/webapi-client.ts @@ -0,0 +1,7 @@ +import { WebApiClient } from "@ff-admin/webapi-client"; +import { WEBAPI_TOKEN, WEBAPI_URL } from "./env.defaults"; + +export default new WebApiClient({ + serverAdress: WEBAPI_URL.origin, + webapiToken: WEBAPI_TOKEN, +});