Updating dependencies and switching to ESModules where possible
Some checks failed
CI / build (push) Has been cancelled
Some checks failed
CI / build (push) Has been cancelled
This commit is contained in:
21
.yarnrc.yml
21
.yarnrc.yml
@ -1,9 +1,12 @@
|
|||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
npmRegistryServer: "https://npm.hibas123.de"
|
npmRegistryServer: "https://npm.hibas123.de"
|
||||||
|
npmScopes:
|
||||||
plugins:
|
"hibas123":
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
npmRegistryServer: "https://git.hibas.dev/api/packages/hibas123/npm/"
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
|
||||||
|
plugins:
|
||||||
yarnPath: .yarn/releases/yarn-3.5.0.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||||
|
spec: "@yarnpkg/plugin-interactive-tools"
|
||||||
|
|
||||||
|
yarnPath: .yarn/releases/yarn-3.5.0.cjs
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "run-s build-ts build-doc",
|
"build": "run-s build-ts build-doc",
|
||||||
"build-doc": "apidoc -i src/ -p apidoc/",
|
"build-doc": "apidoc -i src/ -p apidoc/",
|
||||||
"build-ts": "tsc",
|
"build-ts": "tsc",
|
||||||
"start": "node lib/index.js",
|
"start": "node lib/index.js",
|
||||||
"dev": "nodemon -e ts --exec ts-node src/index.ts",
|
"dev:js": "nodemon lib/index.ts",
|
||||||
|
"dev:ts": "tsc --watch",
|
||||||
|
"dev": "concurrently 'yarn run dev:js' 'yarn run dev:ts'",
|
||||||
"format": "prettier --write \"src/**\""
|
"format": "prettier --write \"src/**\""
|
||||||
},
|
},
|
||||||
"pipelines": {
|
"pipelines": {
|
||||||
@ -20,58 +23,59 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.19.2",
|
"@types/body-parser": "^1.19.6",
|
||||||
"@types/compression": "^1.7.2",
|
"@types/compression": "^1.8.1",
|
||||||
"@types/cookie-parser": "^1.4.3",
|
"@types/cookie-parser": "^1.4.9",
|
||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.3",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^5.0.3",
|
||||||
"@types/express-session": "^1.17.7",
|
"@types/express-serve-static-core": "^5.0.7",
|
||||||
"@types/i18n": "^0.13.6",
|
"@types/express-session": "^1.18.2",
|
||||||
"@types/ini": "^1.3.31",
|
"@types/i18n": "^0.13.12",
|
||||||
"@types/jsonwebtoken": "^9.0.1",
|
"@types/ini": "^4.1.1",
|
||||||
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/mongodb": "^4.0.7",
|
"@types/mongodb": "^4.0.7",
|
||||||
"@types/node": "^18.15.11",
|
"@types/node": "^24.4.0",
|
||||||
"@types/node-rsa": "^1.1.1",
|
"@types/node-rsa": "^1.1.4",
|
||||||
"@types/qrcode": "^1.5.0",
|
"@types/qrcode": "^1.5.5",
|
||||||
"@types/speakeasy": "^2.0.7",
|
"@types/speakeasy": "^2.0.10",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^10.0.0",
|
||||||
"apidoc": "^0.54.0",
|
"apidoc": "^1.2.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^9.2.1",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.1.10",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^3.6.2",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.9.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hibas123/config": "^1.1.2",
|
"@hibas123/config": "^1.1.2",
|
||||||
"@hibas123/nodelogging": "^3.1.3",
|
"@hibas123/nodelogging": "^4.0.0",
|
||||||
"@hibas123/nodeloggingserver_client": "^1.1.2",
|
"@hibas123/nodeloggingserver_client": "^1.1.2",
|
||||||
"@hibas123/openauth-internalapi": "workspace:^",
|
"@hibas123/openauth-internalapi": "workspace:^",
|
||||||
"@hibas123/openauth-views-v1": "workspace:^",
|
"@hibas123/openauth-views-v1": "workspace:^",
|
||||||
"@hibas123/safe_mongo": "2.0.1",
|
"@hibas123/safe_mongo": "2.1.0",
|
||||||
"@simplewebauthn/server": "^7.2.0",
|
"@simplewebauthn/server": "^13.2.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^2.2.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.8.1",
|
||||||
"connect-mongo": "^5.0.0",
|
"connect-mongo": "^5.1.0",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.7",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^17.2.2",
|
||||||
"express": "^4.18.2",
|
"express": "^5.1.0",
|
||||||
"express-session": "^1.17.3",
|
"express-session": "^1.18.2",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.8",
|
||||||
"i18n": "^0.15.1",
|
"i18n": "^0.15.1",
|
||||||
"ini": "^4.1.1",
|
"ini": "^5.0.0",
|
||||||
"joi": "^17.11.0",
|
"joi": "^18.0.1",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.30.1",
|
||||||
"mongodb": "^5.2.0",
|
"mongodb": "^6.19.0",
|
||||||
"node-rsa": "^1.1.1",
|
"node-rsa": "^1.1.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.4",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.2.2",
|
||||||
"speakeasy": "^2.0.0",
|
"speakeasy": "^2.0.0",
|
||||||
"u2f": "^0.1.3",
|
"u2f": "^0.1.3",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^13.0.0"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.5.0"
|
"packageManager": "yarn@3.5.0"
|
||||||
}
|
}
|
||||||
|
@ -1,191 +1,191 @@
|
|||||||
import { Router, Request } from "express";
|
import { Router, Request } from "express";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import verify, { Types } from "../middlewares/verify";
|
import verify, { Types } from "../middlewares/verify.js";
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
|
|
||||||
const ClientRouter: Router = Router();
|
const ClientRouter: Router = Router();
|
||||||
ClientRouter.route("/")
|
ClientRouter.route("/")
|
||||||
/**
|
/**
|
||||||
* @api {get} /admin/client
|
* @api {get} /admin/client
|
||||||
* @apiName AdminGetClients
|
* @apiName AdminGetClients
|
||||||
*
|
*
|
||||||
* @apiGroup admin_client
|
* @apiGroup admin_client
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiSuccess {Object[]} clients
|
* @apiSuccess {Object[]} clients
|
||||||
* @apiSuccess {String} clients._id The internally used id
|
* @apiSuccess {String} clients._id The internally used id
|
||||||
* @apiSuccess {String} clients.maintainer
|
* @apiSuccess {String} clients.maintainer
|
||||||
* @apiSuccess {Boolean} clients.internal
|
* @apiSuccess {Boolean} clients.internal
|
||||||
* @apiSuccess {String} clients.name
|
* @apiSuccess {String} clients.name
|
||||||
* @apiSuccess {String} clients.redirect_url
|
* @apiSuccess {String} clients.redirect_url
|
||||||
* @apiSuccess {String} clients.website
|
* @apiSuccess {String} clients.website
|
||||||
* @apiSuccess {String} clients.logo
|
* @apiSuccess {String} clients.logo
|
||||||
* @apiSuccess {String} clients.client_id Client ID used outside of DB
|
* @apiSuccess {String} clients.client_id Client ID used outside of DB
|
||||||
* @apiSuccess {String} clients.client_secret
|
* @apiSuccess {String} clients.client_secret
|
||||||
*/
|
*/
|
||||||
.get(
|
.get(
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let clients = await Client.find({});
|
let clients = await Client.find({});
|
||||||
//ToDo check if user is required!
|
//ToDo check if user is required!
|
||||||
res.json(clients);
|
res.json(clients);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* @api {get} /admin/client
|
* @api {get} /admin/client
|
||||||
* @apiName AdminAddClients
|
* @apiName AdminAddClients
|
||||||
*
|
*
|
||||||
* @apiGroup admin_client
|
* @apiGroup admin_client
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiParam {Boolean} internal Is it an internal app
|
* @apiParam {Boolean} internal Is it an internal app
|
||||||
* @apiParam {String} name
|
* @apiParam {String} name
|
||||||
* @apiParam {String} redirect_url
|
* @apiParam {String} redirect_url
|
||||||
* @apiParam {String} website
|
* @apiParam {String} website
|
||||||
* @apiParam {String} logo
|
* @apiParam {String} logo
|
||||||
*
|
*
|
||||||
* @apiSuccess {Object[]} clients
|
* @apiSuccess {Object[]} clients
|
||||||
* @apiSuccess {String} clients._id The internally used id
|
* @apiSuccess {String} clients._id The internally used id
|
||||||
* @apiSuccess {String} clients.maintainer
|
* @apiSuccess {String} clients.maintainer
|
||||||
* @apiSuccess {Boolean} clients.internal
|
* @apiSuccess {Boolean} clients.internal
|
||||||
* @apiSuccess {String} clients.name
|
* @apiSuccess {String} clients.name
|
||||||
* @apiSuccess {String} clients.redirect_url
|
* @apiSuccess {String} clients.redirect_url
|
||||||
* @apiSuccess {String} clients.website
|
* @apiSuccess {String} clients.website
|
||||||
* @apiSuccess {String} clients.logo
|
* @apiSuccess {String} clients.logo
|
||||||
* @apiSuccess {String} clients.client_id Client ID used outside of DB
|
* @apiSuccess {String} clients.client_id Client ID used outside of DB
|
||||||
* @apiSuccess {String} clients.client_secret
|
* @apiSuccess {String} clients.client_secret
|
||||||
*/
|
*/
|
||||||
.post(
|
.post(
|
||||||
verify(
|
verify(
|
||||||
{
|
{
|
||||||
internal: {
|
internal: {
|
||||||
type: Types.BOOLEAN,
|
type: Types.BOOLEAN,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
},
|
},
|
||||||
redirect_url: {
|
redirect_url: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
featured: {
|
featured: {
|
||||||
type: Types.BOOLEAN,
|
type: Types.BOOLEAN,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
req.body.client_secret = randomBytes(32).toString("hex");
|
req.body.client_secret = randomBytes(32).toString("hex");
|
||||||
let client = Client.new(req.body);
|
let client = Client.new(req.body);
|
||||||
client.maintainer = req.user._id;
|
client.maintainer = req.user._id;
|
||||||
await Client.save(client);
|
await Client.save(client);
|
||||||
res.json(client);
|
res.json(client);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
ClientRouter.route("/:id")
|
ClientRouter.route("/:id")
|
||||||
/**
|
/**
|
||||||
* @api {delete} /admin/client/:id
|
* @api {delete} /admin/client/:id
|
||||||
* @apiParam {String} id Client _id
|
* @apiParam {String} id Client _id
|
||||||
* @apiName AdminDeleteClient
|
* @apiName AdminDeleteClient
|
||||||
*
|
*
|
||||||
* @apiGroup admin_client
|
* @apiGroup admin_client
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiSuccess {Boolean} success
|
* @apiSuccess {Boolean} success
|
||||||
*/
|
*/
|
||||||
.delete(
|
.delete(
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let { id } = req.params;
|
let { id } = req.params;
|
||||||
await Client.delete(id);
|
await Client.delete(id);
|
||||||
res.json({ success: true });
|
res.json({ success: true });
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* @api {put} /admin/client/:id
|
* @api {put} /admin/client/:id
|
||||||
* @apiParam {String} id Client _id
|
* @apiParam {String} id Client _id
|
||||||
* @apiName AdminUpdateClient
|
* @apiName AdminUpdateClient
|
||||||
*
|
*
|
||||||
* @apiGroup admin_client
|
* @apiGroup admin_client
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiParam {Boolean} internal Is it an internal app
|
* @apiParam {Boolean} internal Is it an internal app
|
||||||
* @apiParam {String} name
|
* @apiParam {String} name
|
||||||
* @apiParam {String} redirect_url
|
* @apiParam {String} redirect_url
|
||||||
* @apiParam {String} website
|
* @apiParam {String} website
|
||||||
* @apiParam {String} logo
|
* @apiParam {String} logo
|
||||||
*
|
*
|
||||||
* @apiSuccess {String} _id The internally used id
|
* @apiSuccess {String} _id The internally used id
|
||||||
* @apiSuccess {String} maintainer UserID of client maintainer
|
* @apiSuccess {String} maintainer UserID of client maintainer
|
||||||
* @apiSuccess {Boolean} internal Defines if it is a internal client
|
* @apiSuccess {Boolean} internal Defines if it is a internal client
|
||||||
* @apiSuccess {String} name The name of the Client
|
* @apiSuccess {String} name The name of the Client
|
||||||
* @apiSuccess {String} redirect_url Redirect URL after login
|
* @apiSuccess {String} redirect_url Redirect URL after login
|
||||||
* @apiSuccess {String} website Website of Client
|
* @apiSuccess {String} website Website of Client
|
||||||
* @apiSuccess {String} logo The Logo of the Client (optional)
|
* @apiSuccess {String} logo The Logo of the Client (optional)
|
||||||
* @apiSuccess {String} client_id Client ID used outside of DB
|
* @apiSuccess {String} client_id Client ID used outside of DB
|
||||||
* @apiSuccess {String} client_secret The client secret, that can be used to obtain token
|
* @apiSuccess {String} client_secret The client secret, that can be used to obtain token
|
||||||
*/
|
*/
|
||||||
.put(
|
.put(
|
||||||
verify(
|
verify(
|
||||||
{
|
{
|
||||||
internal: {
|
internal: {
|
||||||
type: Types.BOOLEAN,
|
type: Types.BOOLEAN,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
redirect_url: {
|
redirect_url: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
featured: {
|
featured: {
|
||||||
type: Types.BOOLEAN,
|
type: Types.BOOLEAN,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let { id } = req.query as { [key: string]: string };
|
let { id } = req.query as { [key: string]: string };
|
||||||
let client = await Client.findById(id);
|
let client = await Client.findById(id);
|
||||||
if (!client)
|
if (!client)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Client not found"),
|
req.__("Client not found"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
for (let key in req.body) {
|
for (let key in req.body) {
|
||||||
client[key] = req.body[key];
|
client[key] = req.body[key];
|
||||||
}
|
}
|
||||||
await Client.save(client);
|
await Client.save(client);
|
||||||
res.json(client);
|
res.json(client);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export default ClientRouter;
|
export default ClientRouter;
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import { Request, Router } from "express";
|
import { Request, Router } from "express";
|
||||||
import ClientRoute from "./client";
|
import ClientRoute from "./client.js";
|
||||||
import UserRoute from "./user";
|
import UserRoute from "./user.js";
|
||||||
import RegCodeRoute from "./regcode";
|
import RegCodeRoute from "./regcode.js";
|
||||||
import PermissionRoute from "./permission";
|
import PermissionRoute from "./permission.js";
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
import { GetUserMiddleware } from "../middlewares/user.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
|
|
||||||
const AdminRoute: Router = Router();
|
const AdminRoute: Router = Router();
|
||||||
|
|
||||||
AdminRoute.use(GetUserMiddleware(true, true), (req: Request, res, next) => {
|
AdminRoute.use(GetUserMiddleware(true, true), (req: Request, res, next) => {
|
||||||
if (!req.isAdmin)
|
if (!req.isAdmin)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
"You have no permission to access this API",
|
"You have no permission to access this API",
|
||||||
HttpStatusCode.FORBIDDEN
|
HttpStatusCode.FORBIDDEN
|
||||||
);
|
);
|
||||||
else next();
|
else next();
|
||||||
});
|
});
|
||||||
|
|
||||||
AdminRoute.use("/client", ClientRoute);
|
AdminRoute.use("/client", ClientRoute);
|
||||||
AdminRoute.use("/regcode", RegCodeRoute);
|
AdminRoute.use("/regcode", RegCodeRoute);
|
||||||
AdminRoute.use("/user", UserRoute);
|
AdminRoute.use("/user", UserRoute);
|
||||||
AdminRoute.use("/permission", PermissionRoute);
|
AdminRoute.use("/permission", PermissionRoute);
|
||||||
export default AdminRoute;
|
export default AdminRoute;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { Request, Router } from "express";
|
import { Request, Router } from "express";
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import Permission from "../../models/permissions.js";
|
||||||
import Permission from "../../models/permissions";
|
import verify, { Types } from "../middlewares/verify.js";
|
||||||
import verify, { Types } from "../middlewares/verify";
|
import Client from "../../models/client.js";
|
||||||
import Client from "../../models/client";
|
|
||||||
import { ObjectId } from "bson";
|
import { ObjectId } from "bson";
|
||||||
|
|
||||||
const PermissionRoute: Router = Router();
|
const PermissionRoute: Router = Router();
|
||||||
|
@ -1,69 +1,67 @@
|
|||||||
import { Request, Router } from "express";
|
import { Request, Router } from "express";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import RegCode from "../../models/regcodes";
|
import RegCode from "../../models/regcodes.js";
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
|
||||||
import { HttpStatusCode } from "../../helper/request_error";
|
const RegCodeRoute: Router = Router();
|
||||||
|
RegCodeRoute.route("/")
|
||||||
const RegCodeRoute: Router = Router();
|
/**
|
||||||
RegCodeRoute.route("/")
|
* @api {get} /admin/regcode
|
||||||
/**
|
* @apiName AdminGetRegcodes
|
||||||
* @api {get} /admin/regcode
|
*
|
||||||
* @apiName AdminGetRegcodes
|
* @apiGroup admin_regcode
|
||||||
*
|
* @apiPermission admin
|
||||||
* @apiGroup admin_regcode
|
*
|
||||||
* @apiPermission admin
|
* @apiSuccess {Object[]} regcodes
|
||||||
*
|
* @apiSuccess {String} permissions._id The ID
|
||||||
* @apiSuccess {Object[]} regcodes
|
* @apiSuccess {String} permissions.token The Regcode Token
|
||||||
* @apiSuccess {String} permissions._id The ID
|
* @apiSuccess {String} permissions.valid Defines if the Regcode is valid
|
||||||
* @apiSuccess {String} permissions.token The Regcode Token
|
* @apiSuccess {String} permissions.validTill Expiration date of RegCode
|
||||||
* @apiSuccess {String} permissions.valid Defines if the Regcode is valid
|
*/
|
||||||
* @apiSuccess {String} permissions.validTill Expiration date of RegCode
|
.get(
|
||||||
*/
|
promiseMiddleware(async (req, res) => {
|
||||||
.get(
|
let regcodes = await RegCode.find({});
|
||||||
promiseMiddleware(async (req, res) => {
|
res.json(regcodes);
|
||||||
let regcodes = await RegCode.find({});
|
})
|
||||||
res.json(regcodes);
|
)
|
||||||
})
|
/**
|
||||||
)
|
* @api {delete} /admin/regcode
|
||||||
/**
|
* @apiName AdminDeleteRegcode
|
||||||
* @api {delete} /admin/regcode
|
*
|
||||||
* @apiName AdminDeleteRegcode
|
* @apiParam {String} id The id of the RegCode
|
||||||
*
|
*
|
||||||
* @apiParam {String} id The id of the RegCode
|
* @apiGroup admin_regcode
|
||||||
*
|
* @apiPermission admin
|
||||||
* @apiGroup admin_regcode
|
*
|
||||||
* @apiPermission admin
|
* @apiSuccess {Boolean} success
|
||||||
*
|
*/
|
||||||
* @apiSuccess {Boolean} success
|
.delete(
|
||||||
*/
|
promiseMiddleware(async (req, res) => {
|
||||||
.delete(
|
let { id } = req.query as { [key: string]: string };
|
||||||
promiseMiddleware(async (req, res) => {
|
await RegCode.delete(id);
|
||||||
let { id } = req.query as { [key: string]: string };
|
res.json({ success: true });
|
||||||
await RegCode.delete(id);
|
})
|
||||||
res.json({ success: true });
|
)
|
||||||
})
|
/**
|
||||||
)
|
* @api {post} /admin/regcode
|
||||||
/**
|
* @apiName AdminAddRegcode
|
||||||
* @api {post} /admin/regcode
|
*
|
||||||
* @apiName AdminAddRegcode
|
* @apiGroup admin_regcode
|
||||||
*
|
* @apiPermission admin
|
||||||
* @apiGroup admin_regcode
|
*
|
||||||
* @apiPermission admin
|
* @apiSuccess {String} code The newly created code
|
||||||
*
|
*/
|
||||||
* @apiSuccess {String} code The newly created code
|
.post(
|
||||||
*/
|
promiseMiddleware(async (req, res) => {
|
||||||
.post(
|
let regcode = RegCode.new({
|
||||||
promiseMiddleware(async (req, res) => {
|
token: randomBytes(10).toString("hex"),
|
||||||
let regcode = RegCode.new({
|
valid: true,
|
||||||
token: randomBytes(10).toString("hex"),
|
validTill: moment().add("1", "month").toDate(),
|
||||||
valid: true,
|
});
|
||||||
validTill: moment().add("1", "month").toDate(),
|
await RegCode.save(regcode);
|
||||||
});
|
res.json({ code: regcode.token });
|
||||||
await RegCode.save(regcode);
|
})
|
||||||
res.json({ code: regcode.token });
|
);
|
||||||
})
|
|
||||||
);
|
export default RegCodeRoute;
|
||||||
|
|
||||||
export default RegCodeRoute;
|
|
||||||
|
@ -1,93 +1,93 @@
|
|||||||
import { Request, Router } from "express";
|
import { Request, Router } from "express";
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
import { GetUserMiddleware } from "../middlewares/user.js";
|
||||||
import { HttpStatusCode } from "../../helper/request_error";
|
import { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
import Mail from "../../models/mail";
|
import Mail from "../../models/mail.js";
|
||||||
import RefreshToken from "../../models/refresh_token";
|
import RefreshToken from "../../models/refresh_token.js";
|
||||||
import LoginToken from "../../models/login_token";
|
import LoginToken from "../../models/login_token.js";
|
||||||
|
|
||||||
const UserRoute: Router = Router();
|
const UserRoute: Router = Router();
|
||||||
UserRoute.use(GetUserMiddleware(true, true), (req: Request, res, next) => {
|
UserRoute.use(GetUserMiddleware(true, true), (req: Request, res, next) => {
|
||||||
if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN);
|
if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN);
|
||||||
else next();
|
else next();
|
||||||
});
|
});
|
||||||
|
|
||||||
UserRoute.route("/")
|
UserRoute.route("/")
|
||||||
/**
|
/**
|
||||||
* @api {get} /admin/user
|
* @api {get} /admin/user
|
||||||
* @apiName AdminGetUsers
|
* @apiName AdminGetUsers
|
||||||
*
|
*
|
||||||
* @apiGroup admin_user
|
* @apiGroup admin_user
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
* @apiSuccess {Object[]} user
|
* @apiSuccess {Object[]} user
|
||||||
* @apiSuccess {String} user._id The internal id of the user
|
* @apiSuccess {String} user._id The internal id of the user
|
||||||
* @apiSuccess {String} user.uid The public UID of the user
|
* @apiSuccess {String} user.uid The public UID of the user
|
||||||
* @apiSuccess {String} user.username The username
|
* @apiSuccess {String} user.username The username
|
||||||
* @apiSuccess {String} user.name The real name
|
* @apiSuccess {String} user.name The real name
|
||||||
* @apiSuccess {Date} user.birthday The birthday
|
* @apiSuccess {Date} user.birthday The birthday
|
||||||
* @apiSuccess {Number} user.gender 0 = none, 1 = male, 2 = female, 3 = other
|
* @apiSuccess {Number} user.gender 0 = none, 1 = male, 2 = female, 3 = other
|
||||||
* @apiSuccess {Boolean} user.admin Is admin or not
|
* @apiSuccess {Boolean} user.admin Is admin or not
|
||||||
*/
|
*/
|
||||||
.get(
|
.get(
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let users = await User.find({});
|
let users = await User.find({});
|
||||||
users.forEach(
|
users.forEach(
|
||||||
(e) => delete e.password && delete e.salt && delete e.encryption_key
|
(e) => delete e.password && delete e.salt && delete e.encryption_key
|
||||||
);
|
);
|
||||||
res.json(users);
|
res.json(users);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* @api {delete} /admin/user
|
* @api {delete} /admin/user
|
||||||
* @apiName AdminDeleteUser
|
* @apiName AdminDeleteUser
|
||||||
*
|
*
|
||||||
* @apiParam {String} id The User ID
|
* @apiParam {String} id The User ID
|
||||||
*
|
*
|
||||||
* @apiGroup admin_user
|
* @apiGroup admin_user
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiSuccess {Boolean} success
|
* @apiSuccess {Boolean} success
|
||||||
*/
|
*/
|
||||||
.delete(
|
.delete(
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let { id } = req.query as { [key: string]: string };
|
let { id } = req.query as { [key: string]: string };
|
||||||
let user = await User.findById(id);
|
let user = await User.findById(id);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.mails.map((mail) => Mail.delete(mail)),
|
user.mails.map((mail) => Mail.delete(mail)),
|
||||||
[
|
[
|
||||||
RefreshToken.deleteFilter({ user: user._id }),
|
RefreshToken.deleteFilter({ user: user._id }),
|
||||||
LoginToken.deleteFilter({ user: user._id }),
|
LoginToken.deleteFilter({ user: user._id }),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await User.delete(user);
|
await User.delete(user);
|
||||||
res.json({ success: true });
|
res.json({ success: true });
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* @api {put} /admin/user
|
* @api {put} /admin/user
|
||||||
* @apiName AdminChangeUser
|
* @apiName AdminChangeUser
|
||||||
*
|
*
|
||||||
* @apiParam {String} id The User ID
|
* @apiParam {String} id The User ID
|
||||||
*
|
*
|
||||||
* @apiGroup admin_user
|
* @apiGroup admin_user
|
||||||
* @apiPermission admin
|
* @apiPermission admin
|
||||||
*
|
*
|
||||||
* @apiSuccess {Boolean} success
|
* @apiSuccess {Boolean} success
|
||||||
*
|
*
|
||||||
* @apiDescription Flipps the user role:
|
* @apiDescription Flipps the user role:
|
||||||
* admin -> user
|
* admin -> user
|
||||||
* user -> admin
|
* user -> admin
|
||||||
*/
|
*/
|
||||||
.put(
|
.put(
|
||||||
promiseMiddleware(async (req, res) => {
|
promiseMiddleware(async (req, res) => {
|
||||||
let { id } = req.query as { [key: string]: string };
|
let { id } = req.query as { [key: string]: string };
|
||||||
let user = await User.findById(id);
|
let user = await User.findById(id);
|
||||||
user.admin = !user.admin;
|
user.admin = !user.admin;
|
||||||
await User.save(user);
|
await User.save(user);
|
||||||
res.json({ success: true });
|
res.json({ success: true });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
export default UserRoute;
|
export default UserRoute;
|
||||||
|
@ -1,110 +1,110 @@
|
|||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import {
|
import {
|
||||||
GetClientAuthMiddleware,
|
GetClientAuthMiddleware,
|
||||||
GetClientApiAuthMiddleware,
|
GetClientApiAuthMiddleware,
|
||||||
} from "../middlewares/client";
|
} from "../middlewares/client.js";
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
import { GetUserMiddleware } from "../middlewares/user.js";
|
||||||
import { createJWT } from "../../keys";
|
import { createJWT } from "../../keys.js";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import config from "../../config";
|
import config from "../../config.js";
|
||||||
import Mail from "../../models/mail";
|
import Mail from "../../models/mail.js";
|
||||||
|
|
||||||
const ClientRouter = Router();
|
const ClientRouter = Router();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /client/user
|
* @api {get} /client/user
|
||||||
*
|
*
|
||||||
* @apiDescription Can be used for simple authentication of user. It will redirect the user to the redirect URI with a very short lived jwt.
|
* @apiDescription Can be used for simple authentication of user. It will redirect the user to the redirect URI with a very short lived jwt.
|
||||||
*
|
*
|
||||||
* @apiParam {String} redirect_uri URL to redirect to on success
|
* @apiParam {String} redirect_uri URL to redirect to on success
|
||||||
* @apiParam {String} state A optional state, that will be included in the JWT and redirect_uri as parameter
|
* @apiParam {String} state A optional state, that will be included in the JWT and redirect_uri as parameter
|
||||||
*
|
*
|
||||||
* @apiName ClientUser
|
* @apiName ClientUser
|
||||||
* @apiGroup client
|
* @apiGroup client
|
||||||
*
|
*
|
||||||
* @apiPermission user_client Requires ClientID and Authenticated User
|
* @apiPermission user_client Requires ClientID and Authenticated User
|
||||||
*/
|
*/
|
||||||
ClientRouter.get(
|
ClientRouter.get(
|
||||||
"/user",
|
"/user",
|
||||||
Stacker(
|
Stacker(
|
||||||
GetClientAuthMiddleware(false),
|
GetClientAuthMiddleware(false),
|
||||||
GetUserMiddleware(false, false),
|
GetUserMiddleware(false, false),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
let { redirect_uri, state } = req.query;
|
let { redirect_uri, state } = req.query;
|
||||||
|
|
||||||
if (redirect_uri !== req.client.redirect_url)
|
if (redirect_uri !== req.client.redirect_url)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
"Invalid redirect URI",
|
"Invalid redirect URI",
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
let jwt = await createJWT(
|
let jwt = await createJWT(
|
||||||
{
|
{
|
||||||
client: req.client.client_id,
|
client: req.client.client_id,
|
||||||
uid: req.user.uid,
|
uid: req.user.uid,
|
||||||
username: req.user.username,
|
username: req.user.username,
|
||||||
state: state,
|
state: state,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expiresIn: 30,
|
expiresIn: 30,
|
||||||
issuer: config.core.url,
|
issuer: config.core.url,
|
||||||
algorithm: "RS256",
|
algorithm: "RS256",
|
||||||
subject: req.user.uid,
|
subject: req.user.uid,
|
||||||
audience: req.client.client_id,
|
audience: req.client.client_id,
|
||||||
}
|
}
|
||||||
); //after 30 seconds this token is invalid
|
); //after 30 seconds this token is invalid
|
||||||
res.redirect(
|
res.redirect(
|
||||||
redirect_uri + "?jwt=" + jwt + (state ? `&state=${state}` : "")
|
redirect_uri + "?jwt=" + jwt + (state ? `&state=${state}` : "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
ClientRouter.get(
|
ClientRouter.get(
|
||||||
"/account",
|
"/account",
|
||||||
Stacker(GetClientApiAuthMiddleware(), async (req: Request, res) => {
|
Stacker(GetClientApiAuthMiddleware(), async (req: Request, res) => {
|
||||||
let mails = await Promise.all(
|
let mails = await Promise.all(
|
||||||
req.user.mails.map((id) => Mail.findById(id))
|
req.user.mails.map((id) => Mail.findById(id))
|
||||||
);
|
);
|
||||||
|
|
||||||
let mail = mails.find((e) => e.primary) || mails[0];
|
let mail = mails.find((e) => e.primary) || mails[0];
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
user: {
|
user: {
|
||||||
username: req.user.username,
|
username: req.user.username,
|
||||||
name: req.user.name,
|
name: req.user.name,
|
||||||
email: mail,
|
email: mail,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /client/featured
|
* @api {get} /client/featured
|
||||||
*
|
*
|
||||||
* @apiDescription Get a list of clients, that want to be featured on the home page
|
* @apiDescription Get a list of clients, that want to be featured on the home page
|
||||||
*
|
*
|
||||||
* @apiName GetFeaturedClients
|
* @apiName GetFeaturedClients
|
||||||
* @apiGroup client
|
* @apiGroup client
|
||||||
*/
|
*/
|
||||||
ClientRouter.get(
|
ClientRouter.get(
|
||||||
"/featured",
|
"/featured",
|
||||||
Stacker(async (req: Request, res) => {
|
Stacker(async (req: Request, res) => {
|
||||||
let clients = await Client.find({
|
let clients = await Client.find({
|
||||||
featured: true,
|
featured: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
clients: clients.map(({ name, logo, website, description }) => ({
|
clients: clients.map(({ name, logo, website, description }) => ({
|
||||||
name,
|
name,
|
||||||
logo,
|
logo,
|
||||||
website,
|
website,
|
||||||
description,
|
description,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export default ClientRouter;
|
export default ClientRouter;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import {
|
import {
|
||||||
ClientAuthMiddleware,
|
ClientAuthMiddleware,
|
||||||
GetClientAuthMiddleware,
|
GetClientAuthMiddleware,
|
||||||
} from "../middlewares/client";
|
} from "../middlewares/client.js";
|
||||||
import Permission from "../../models/permissions";
|
import Permission from "../../models/permissions.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
|
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import Grant from "../../models/grants";
|
import Grant from "../../models/grants.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export const GetPermissions = Stacker(
|
export const GetPermissions = Stacker(
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
import AdminRoute from "./admin";
|
import AdminRoute from "./admin/index.js";
|
||||||
import UserRoute from "./user";
|
import UserRoute from "./user/index.js";
|
||||||
import InternalRoute from "./internal";
|
import InternalRoute from "./internal/index.js";
|
||||||
import ClientRouter from "./client";
|
import ClientRouter from "./client/index.js";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import OAuthRoute from "./oauth";
|
import OAuthRoute from "./oauth/index.js";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import JRPCEndpoint from "./jrpc";
|
import JRPCEndpoint from "./jrpc/index.js";
|
||||||
|
|
||||||
const ApiRouter: express.IRouter = express.Router();
|
const ApiRouter: express.IRouter = express.Router();
|
||||||
ApiRouter.use("/admin", AdminRoute);
|
ApiRouter.use("/admin", AdminRoute);
|
||||||
@ -41,10 +41,10 @@ ApiRouter.post("/jrpc", JRPCEndpoint);
|
|||||||
ApiRouter.use("/", ClientRouter);
|
ApiRouter.use("/", ClientRouter);
|
||||||
|
|
||||||
ApiRouter.get("/config.json", (req, res) => {
|
ApiRouter.get("/config.json", (req, res) => {
|
||||||
return res.json({
|
return res.json({
|
||||||
name: config.core.name,
|
name: config.core.name,
|
||||||
url: config.core.url,
|
url: config.core.url,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ApiRouter;
|
export default ApiRouter;
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { OAuthInternalApp } from "./oauth";
|
import { OAuthInternalApp } from "./oauth.js";
|
||||||
import PasswordAuth from "./password";
|
import PasswordAuth from "./password.js";
|
||||||
|
|
||||||
const InternalRoute: Router = Router();
|
const InternalRoute: Router = Router();
|
||||||
/**
|
/**
|
||||||
* @api {get} /internal/oauth
|
* @api {get} /internal/oauth
|
||||||
* @apiName ClientInteralOAuth
|
* @apiName ClientInteralOAuth
|
||||||
*
|
*
|
||||||
* @apiGroup client_internal
|
* @apiGroup client_internal
|
||||||
* @apiPermission client_internal Only ClientID
|
* @apiPermission client_internal Only ClientID
|
||||||
*
|
*
|
||||||
* @apiParam {String} redirect_uri Redirect URI called after success
|
* @apiParam {String} redirect_uri Redirect URI called after success
|
||||||
* @apiParam {String} state State will be set in RedirectURI for the client to check
|
* @apiParam {String} state State will be set in RedirectURI for the client to check
|
||||||
*/
|
*/
|
||||||
InternalRoute.get("/oauth", OAuthInternalApp);
|
InternalRoute.get("/oauth", OAuthInternalApp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {post} /internal/password
|
* @api {post} /internal/password
|
||||||
* @apiName ClientInteralPassword
|
* @apiName ClientInteralPassword
|
||||||
*
|
*
|
||||||
* @apiGroup client_internal
|
* @apiGroup client_internal
|
||||||
* @apiPermission client_internal Requires ClientID and Secret
|
* @apiPermission client_internal Requires ClientID and Secret
|
||||||
*
|
*
|
||||||
* @apiParam {String} username Username (either username or UID)
|
* @apiParam {String} username Username (either username or UID)
|
||||||
* @apiParam {String} uid User ID (either username or UID)
|
* @apiParam {String} uid User ID (either username or UID)
|
||||||
* @apiParam {String} password Hashed and Salted according to specification
|
* @apiParam {String} password Hashed and Salted according to specification
|
||||||
*/
|
*/
|
||||||
InternalRoute.post("/password", PasswordAuth);
|
InternalRoute.post("/password", PasswordAuth);
|
||||||
export default InternalRoute;
|
export default InternalRoute;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import { GetClientAuthMiddleware } from "../middlewares/client";
|
import { GetClientAuthMiddleware } from "../middlewares/client.js";
|
||||||
import { UserMiddleware } from "../middlewares/user";
|
import { UserMiddleware } from "../middlewares/user.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import ClientCode from "../../models/client_code";
|
import ClientCode from "../../models/client_code.js";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
export const OAuthInternalApp = Stacker(
|
export const OAuthInternalApp = Stacker(
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import { GetClientAuthMiddleware } from "../middlewares/client";
|
import { GetClientAuthMiddleware } from "../middlewares/client.js";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
|
|
||||||
const PasswordAuth = Stacker(
|
const PasswordAuth = Stacker(
|
||||||
GetClientAuthMiddleware(true, true),
|
GetClientAuthMiddleware(true, true),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
let {
|
let {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
uid,
|
uid,
|
||||||
}: { username: string; password: string; uid: string } = req.body;
|
}: { username: string; password: string; uid: string } = req.body;
|
||||||
let query: any = { password: password };
|
let query: any = { password: password };
|
||||||
if (username) {
|
if (username) {
|
||||||
query.username = username.toLowerCase();
|
query.username = username.toLowerCase();
|
||||||
} else if (uid) {
|
} else if (uid) {
|
||||||
query.uid = uid;
|
query.uid = uid;
|
||||||
} else {
|
} else {
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("No username or uid set"),
|
req.__("No username or uid set"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = await User.findOne(query);
|
let user = await User.findOne(query);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
res.json({ error: req.__("Password or username wrong") });
|
res.json({ error: req.__("Password or username wrong") });
|
||||||
} else {
|
} else {
|
||||||
res.json({ success: true, uid: user.uid });
|
res.json({ success: true, uid: user.uid });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
export default PasswordAuth;
|
export default PasswordAuth;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { Format } from "@hibas123/logging";
|
import { Format } from "@hibas123/logging";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import { Server, } from "@hibas123/openauth-internalapi";
|
import { Server, } from "@hibas123/openauth-internalapi";
|
||||||
import { RequestObject, ResponseObject } from "@hibas123/openauth-internalapi/lib/service_base";
|
import { RequestObject, ResponseObject } from "@hibas123/openauth-internalapi/lib/service_base.js";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import AccountService from "./services/account";
|
import AccountService from "./services/account.js";
|
||||||
import LoginService from "./services/login";
|
import LoginService from "./services/login.js";
|
||||||
import SecurityService from "./services/security";
|
import SecurityService from "./services/security.js";
|
||||||
import TFAService from "./services/twofactor";
|
import TFAService from "./services/twofactor.js";
|
||||||
|
|
||||||
export type SessionContext = Request;
|
export type SessionContext = Request;
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Profile, ContactInfo, Gender, Server, UserRegisterInfo } from "@hibas123/openauth-internalapi";
|
import { Profile, ContactInfo, Gender, Server, UserRegisterInfo } from "@hibas123/openauth-internalapi";
|
||||||
import type { SessionContext } from "../index";
|
import type { SessionContext } from "../index.js";
|
||||||
import Mail from "../../../models/mail";
|
import Mail from "../../../models/mail.js";
|
||||||
import User from "../../../models/user";
|
import User from "../../../models/user.js";
|
||||||
import { RequireLogin } from "../../../helper/login";
|
import { RequireLogin } from "../../../helper/login.js";
|
||||||
|
|
||||||
export default class AccountService extends Server.AccountService<SessionContext> {
|
export default class AccountService extends Server.AccountService<SessionContext> {
|
||||||
Register(regcode: string, info: UserRegisterInfo, ctx: SessionContext): Promise<void> {
|
Register(regcode: string, info: UserRegisterInfo, ctx: SessionContext): Promise<void> {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { Server, LoginState, TFAOption, TFAType } from "@hibas123/openauth-internalapi";
|
import { Server, LoginState, TFAOption, TFAType } from "@hibas123/openauth-internalapi";
|
||||||
import type { SessionContext } from "../index";
|
import type { SessionContext } from "../index.js";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import User, { IUser } from "../../../models/user";
|
import User, { IUser } from "../../../models/user.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
import TwoFactor, { ITwoFactor, IWebAuthn } from "../../../models/twofactor";
|
import TwoFactor, { ITwoFactor, IWebAuthn } from "../../../models/twofactor.js";
|
||||||
import speakeasy from "speakeasy";
|
import speakeasy from "speakeasy";
|
||||||
import { generateAuthenticationOptions, verifyAuthenticationResponse } from "@simplewebauthn/server";
|
import { generateAuthenticationOptions, verifyAuthenticationResponse } from "@simplewebauthn/server";
|
||||||
import config from "../../../config";
|
import config from "../../../config.js";
|
||||||
|
|
||||||
//FIXME: There are a lot of uneccessary database requests happening here. Since this is not a "hot" path, it should not matter to much, but it should be fixed nontheless.
|
//FIXME: There are a lot of uneccessary database requests happening here. Since this is not a "hot" path, it should not matter to much, but it should be fixed nontheless.
|
||||||
|
|
||||||
@ -212,13 +212,12 @@ export default class LoginService extends Server.LoginService<SessionContext> {
|
|||||||
|
|
||||||
const rpID = new URL(config.core.url).hostname;
|
const rpID = new URL(config.core.url).hostname;
|
||||||
|
|
||||||
let options = generateAuthenticationOptions({
|
let options = await generateAuthenticationOptions({
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
userVerification: "discouraged",
|
userVerification: "discouraged",
|
||||||
rpID,
|
rpID,
|
||||||
allowCredentials: [{
|
allowCredentials: [{
|
||||||
id: tfa.data.device.credentialID.buffer,
|
id: typeof tfa.data.device.credentialID === "string" ? tfa.data.device.credentialID : Buffer.from(tfa.data.device.credentialID.buffer).toString("base64url"),
|
||||||
type: "public-key",
|
|
||||||
transports: tfa.data.device.transports
|
transports: tfa.data.device.transports
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
@ -241,10 +240,10 @@ export default class LoginService extends Server.LoginService<SessionContext> {
|
|||||||
|
|
||||||
let verification = await verifyAuthenticationResponse({
|
let verification = await verifyAuthenticationResponse({
|
||||||
response: JSON.parse(response),
|
response: JSON.parse(response),
|
||||||
authenticator: {
|
credential: {
|
||||||
|
id: typeof tfa.data.device.credentialID === "string" ? tfa.data.device.credentialID : Buffer.from(tfa.data.device.credentialID.buffer).toString("base64url"),
|
||||||
|
publicKey: Buffer.from(tfa.data.device.credentialPublicKey.buffer),
|
||||||
counter: tfa.data.device.counter,
|
counter: tfa.data.device.counter,
|
||||||
credentialID: tfa.data.device.credentialID.buffer,
|
|
||||||
credentialPublicKey: tfa.data.device.credentialPublicKey.buffer,
|
|
||||||
transports: tfa.data.device.transports
|
transports: tfa.data.device.transports
|
||||||
},
|
},
|
||||||
expectedChallenge: ctx.session.login_state.webauthn_challenge,
|
expectedChallenge: ctx.session.login_state.webauthn_challenge,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Server, Session } from "@hibas123/openauth-internalapi";
|
import { Server, Session } from "@hibas123/openauth-internalapi";
|
||||||
import type { SessionContext } from "../index";
|
import type { SessionContext } from "../index.js";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import { RequireLogin } from "../../../helper/login";
|
import { RequireLogin } from "../../../helper/login.js";
|
||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
import User from "../../../models/user";
|
import User from "../../../models/user.js";
|
||||||
|
|
||||||
export default class SecurityService extends Server.SecurityService<SessionContext> {
|
export default class SecurityService extends Server.SecurityService<SessionContext> {
|
||||||
@RequireLogin()
|
@RequireLogin()
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { TFANewTOTP, Server, TFAOption, UserRegisterInfo, TFAWebAuthRegister } from "@hibas123/openauth-internalapi";
|
import { TFANewTOTP, Server, TFAOption, UserRegisterInfo, TFAWebAuthRegister } from "@hibas123/openauth-internalapi";
|
||||||
import type { SessionContext } from "../index";
|
import type { SessionContext } from "../index.js";
|
||||||
import TwoFactorModel, { ITOTP, IWebAuthn, TFATypes } from "../../../models/twofactor";
|
import TwoFactorModel, { ITOTP, IWebAuthn, TFATypes } from "../../../models/twofactor.js";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
import * as speakeasy from "speakeasy";
|
import * as speakeasy from "speakeasy";
|
||||||
import * as qrcode from "qrcode";
|
import * as qrcode from "qrcode";
|
||||||
import config from "../../../config";
|
import config from "../../../config.js";
|
||||||
import { generateRegistrationOptions, verifyRegistrationResponse } from '@simplewebauthn/server';
|
import { generateRegistrationOptions, verifyRegistrationResponse } from '@simplewebauthn/server';
|
||||||
import type { RegistrationResponseJSON } from '@simplewebauthn/typescript-types';
|
// import type { RegistrationResponseJSON } from '@simplewebauthn/typescript-types';
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import { Binary } from "mongodb";
|
import { Binary } from "mongodb";
|
||||||
import { RequireLogin } from "../../../helper/login";
|
import { RequireLogin } from "../../../helper/login.js";
|
||||||
|
|
||||||
|
|
||||||
export default class TFAService extends Server.TFAService<SessionContext> {
|
export default class TFAService extends Server.TFAService<SessionContext> {
|
||||||
@ -111,10 +111,10 @@ export default class TFAService extends Server.TFAService<SessionContext> {
|
|||||||
// TODO: Get already registered options
|
// TODO: Get already registered options
|
||||||
|
|
||||||
const rpID = new URL(config.core.url).hostname;
|
const rpID = new URL(config.core.url).hostname;
|
||||||
const options = generateRegistrationOptions({
|
const options = await generateRegistrationOptions({
|
||||||
rpName: config.core.name,
|
rpName: config.core.name,
|
||||||
rpID,
|
rpID,
|
||||||
userID: ctx.user.uid,
|
userID: Buffer.from(ctx.user.uid, "utf-8"),
|
||||||
userName: ctx.user.username,
|
userName: ctx.user.username,
|
||||||
attestationType: 'direct',
|
attestationType: 'direct',
|
||||||
userDisplayName: ctx.user.name,
|
userDisplayName: ctx.user.name,
|
||||||
@ -156,7 +156,7 @@ export default class TFAService extends Server.TFAService<SessionContext> {
|
|||||||
|
|
||||||
const rpID = new URL(config.core.url).hostname;
|
const rpID = new URL(config.core.url).hostname;
|
||||||
|
|
||||||
const response = JSON.parse(registration) as RegistrationResponseJSON;
|
const response = JSON.parse(registration); // as RegistrationResponseJSON;
|
||||||
|
|
||||||
let verification = await verifyRegistrationResponse({
|
let verification = await verifyRegistrationResponse({
|
||||||
response,
|
response,
|
||||||
@ -167,7 +167,7 @@ export default class TFAService extends Server.TFAService<SessionContext> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (verification.verified) {
|
if (verification.verified) {
|
||||||
const { credentialPublicKey, credentialID, counter } = verification.registrationInfo;
|
const { credential, } = verification.registrationInfo;
|
||||||
|
|
||||||
//TODO: Check if already registered!
|
//TODO: Check if already registered!
|
||||||
// TwoFactorModel.find({
|
// TwoFactorModel.find({
|
||||||
@ -177,10 +177,11 @@ export default class TFAService extends Server.TFAService<SessionContext> {
|
|||||||
|
|
||||||
twofactor.data = {
|
twofactor.data = {
|
||||||
device: {
|
device: {
|
||||||
credentialPublicKey: new Binary(credentialPublicKey),
|
counter: credential.counter,
|
||||||
credentialID: new Binary(credentialID),
|
credentialPublicKey: new Binary(credential.publicKey),
|
||||||
counter: verification.registrationInfo.counter,
|
credentialID: credential.id,
|
||||||
transports: response.response.transports as any[]
|
// counter: verification.registrationInfo.counter,
|
||||||
|
transports: response.response.transports as any[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,123 +1,122 @@
|
|||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from "express";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import { validateJWT } from "../../keys";
|
import { validateJWT } from "../../keys.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
import Mail from "../../models/mail";
|
import { OAuthJWT } from "../../helper/jwt.js";
|
||||||
import { OAuthJWT } from "../../helper/jwt";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import Logging from "@hibas123/nodelogging";
|
|
||||||
|
export function GetClientAuthMiddleware(
|
||||||
export function GetClientAuthMiddleware(
|
checksecret = true,
|
||||||
checksecret = true,
|
internal = false,
|
||||||
internal = false,
|
checksecret_if_available = false
|
||||||
checksecret_if_available = false
|
) {
|
||||||
) {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
try {
|
||||||
try {
|
let client_id = req.query.client_id || req.body.client_id;
|
||||||
let client_id = req.query.client_id || req.body.client_id;
|
let client_secret = req.query.client_secret || req.body.client_secret;
|
||||||
let client_secret = req.query.client_secret || req.body.client_secret;
|
|
||||||
|
if (!client_id && !client_secret && req.headers.authorization) {
|
||||||
if (!client_id && !client_secret && req.headers.authorization) {
|
let header = req.headers.authorization;
|
||||||
let header = req.headers.authorization;
|
let [type, val] = header.split(" ");
|
||||||
let [type, val] = header.split(" ");
|
if (val) {
|
||||||
if (val) {
|
let str = Buffer.from(val, "base64").toString("utf-8");
|
||||||
let str = Buffer.from(val, "base64").toString("utf-8");
|
let [id, secret] = str.split(":");
|
||||||
let [id, secret] = str.split(":");
|
client_id = id;
|
||||||
client_id = id;
|
client_secret = secret;
|
||||||
client_secret = secret;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!client_id || (!client_secret && checksecret)) {
|
||||||
if (!client_id || (!client_secret && checksecret)) {
|
throw new RequestError(
|
||||||
throw new RequestError(
|
"No client credentials",
|
||||||
"No client credentials",
|
HttpStatusCode.BAD_REQUEST
|
||||||
HttpStatusCode.BAD_REQUEST
|
);
|
||||||
);
|
}
|
||||||
}
|
let w = { client_id: client_id, client_secret: client_secret };
|
||||||
let w = { client_id: client_id, client_secret: client_secret };
|
if (!checksecret && !(checksecret_if_available && client_secret))
|
||||||
if (!checksecret && !(checksecret_if_available && client_secret))
|
delete w.client_secret;
|
||||||
delete w.client_secret;
|
|
||||||
|
let client = await Client.findOne(w);
|
||||||
let client = await Client.findOne(w);
|
|
||||||
|
if (!client) {
|
||||||
if (!client) {
|
throw new RequestError(
|
||||||
throw new RequestError(
|
"Invalid client_id" + (checksecret ? "or client_secret" : ""),
|
||||||
"Invalid client_id" + (checksecret ? "or client_secret" : ""),
|
HttpStatusCode.BAD_REQUEST
|
||||||
HttpStatusCode.BAD_REQUEST
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
if (internal && !client.internal) {
|
||||||
if (internal && !client.internal) {
|
throw new RequestError(
|
||||||
throw new RequestError(
|
req.__("Client has no permission for access"),
|
||||||
req.__("Client has no permission for access"),
|
HttpStatusCode.FORBIDDEN
|
||||||
HttpStatusCode.FORBIDDEN
|
);
|
||||||
);
|
}
|
||||||
}
|
req.client = client;
|
||||||
req.client = client;
|
next();
|
||||||
next();
|
} catch (e) {
|
||||||
} catch (e) {
|
if (next) next(e);
|
||||||
if (next) next(e);
|
else throw e;
|
||||||
else throw e;
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
export const ClientAuthMiddleware = GetClientAuthMiddleware();
|
||||||
export const ClientAuthMiddleware = GetClientAuthMiddleware();
|
|
||||||
|
export function GetClientApiAuthMiddleware(permissions?: string[]) {
|
||||||
export function GetClientApiAuthMiddleware(permissions?: string[]) {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
try {
|
||||||
try {
|
const invalid_err = new RequestError(
|
||||||
const invalid_err = new RequestError(
|
req.__("Unauthorized"),
|
||||||
req.__("Unauthorized"),
|
HttpStatusCode.UNAUTHORIZED
|
||||||
HttpStatusCode.UNAUTHORIZED
|
);
|
||||||
);
|
let token =
|
||||||
let token =
|
(req.query.access_token as string) ||
|
||||||
(req.query.access_token as string) ||
|
(req.headers.authorization as string);
|
||||||
(req.headers.authorization as string);
|
if (!token) {
|
||||||
if (!token) {
|
Logging.debug("No token found. Searched in query (access_token) and header (authorization)");
|
||||||
Logging.debug("No token found. Searched in query (access_token) and header (authorization)");
|
throw invalid_err;
|
||||||
throw invalid_err;
|
}
|
||||||
}
|
|
||||||
|
if (token.toLowerCase().startsWith("bearer "))
|
||||||
if (token.toLowerCase().startsWith("bearer "))
|
token = token.substring(7);
|
||||||
token = token.substring(7);
|
|
||||||
|
let data: OAuthJWT;
|
||||||
let data: OAuthJWT;
|
try {
|
||||||
try {
|
data = await validateJWT(token);
|
||||||
data = await validateJWT(token);
|
} catch (err) {
|
||||||
} catch (err) {
|
Logging.debug("Invalid JWT", err.message);
|
||||||
Logging.debug("Invalid JWT", err.message);
|
throw invalid_err;
|
||||||
throw invalid_err;
|
}
|
||||||
}
|
|
||||||
|
let user = await User.findOne({ uid: data.user });
|
||||||
let user = await User.findOne({ uid: data.user });
|
|
||||||
|
if (!user) {
|
||||||
if (!user) {
|
Logging.debug("User not found");
|
||||||
Logging.debug("User not found");
|
throw invalid_err;
|
||||||
throw invalid_err;
|
}
|
||||||
}
|
|
||||||
|
let client = await Client.findOne({ client_id: data.application });
|
||||||
let client = await Client.findOne({ client_id: data.application });
|
if (!client) {
|
||||||
if (!client) {
|
Logging.debug("Client not found");
|
||||||
Logging.debug("Client not found");
|
throw invalid_err;
|
||||||
throw invalid_err;
|
}
|
||||||
}
|
|
||||||
|
if (
|
||||||
if (
|
permissions &&
|
||||||
permissions &&
|
(!data.permissions ||
|
||||||
(!data.permissions ||
|
!permissions.every((e) => data.permissions.indexOf(e) >= 0))
|
||||||
!permissions.every((e) => data.permissions.indexOf(e) >= 0))
|
) {
|
||||||
) {
|
Logging.debug("Invalid permissions");
|
||||||
Logging.debug("Invalid permissions");
|
throw invalid_err;
|
||||||
throw invalid_err;
|
}
|
||||||
}
|
|
||||||
|
req.user = user;
|
||||||
req.user = user;
|
req.client = client;
|
||||||
req.client = client;
|
next();
|
||||||
next();
|
} catch (e) {
|
||||||
} catch (e) {
|
if (next) next(e);
|
||||||
if (next) next(e);
|
else throw e;
|
||||||
else throw e;
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
import { Request, Response, NextFunction, RequestHandler } from "express";
|
import { Request, Response, NextFunction, RequestHandler } from "express";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
|
|
||||||
type RH = (req: Request, res: Response, next?: NextFunction) => any;
|
type RH = (req: Request, res: Response, next?: NextFunction) => any;
|
||||||
|
|
||||||
function call(handler: RH, req: Request, res: Response) {
|
function call(handler: RH, req: Request, res: Response) {
|
||||||
return new Promise<void>((yes, no) => {
|
return new Promise<void>((yes, no) => {
|
||||||
let p = handler(req, res, (err) => {
|
let p = handler(req, res, (err) => {
|
||||||
if (err) no(err);
|
if (err) no(err);
|
||||||
else yes();
|
else yes();
|
||||||
});
|
});
|
||||||
if (p && p.catch) p.catch((err) => no(err));
|
if (p && p.catch) p.catch((err) => no(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const Stacker = (...handler: RH[]) => {
|
const Stacker = (...handler: RH[]) => {
|
||||||
return promiseMiddleware(
|
return promiseMiddleware(
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
let hc = handler.concat();
|
let hc = handler.concat();
|
||||||
while (hc.length > 0) {
|
while (hc.length > 0) {
|
||||||
let h = hc.shift();
|
let h = hc.shift();
|
||||||
await call(h, req, res);
|
await call(h, req, res);
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default Stacker;
|
export default Stacker;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from "express";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import { requireLoginState } from "../../helper/login";
|
import { requireLoginState } from "../../helper/login.js";
|
||||||
|
|
||||||
class Invalid extends Error { }
|
class Invalid extends Error { }
|
||||||
|
|
||||||
|
@ -1,142 +1,141 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import {
|
import {
|
||||||
isString,
|
types
|
||||||
isDate,
|
} from "util";
|
||||||
} from "util";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
|
||||||
|
export enum Types {
|
||||||
export enum Types {
|
STRING,
|
||||||
STRING,
|
NUMBER,
|
||||||
NUMBER,
|
BOOLEAN,
|
||||||
BOOLEAN,
|
EMAIL,
|
||||||
EMAIL,
|
OBJECT,
|
||||||
OBJECT,
|
DATE,
|
||||||
DATE,
|
ARRAY,
|
||||||
ARRAY,
|
ENUM,
|
||||||
ENUM,
|
}
|
||||||
}
|
|
||||||
|
function isEmail(value: any): boolean {
|
||||||
function isEmail(value: any): boolean {
|
return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||||
return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
value
|
||||||
value
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
export interface CheckObject {
|
||||||
export interface CheckObject {
|
type: Types;
|
||||||
type: Types;
|
query?: boolean;
|
||||||
query?: boolean;
|
optional?: boolean;
|
||||||
optional?: boolean;
|
|
||||||
|
/**
|
||||||
/**
|
* Only when Type.ENUM
|
||||||
* Only when Type.ENUM
|
*
|
||||||
*
|
* values to check before
|
||||||
* values to check before
|
*/
|
||||||
*/
|
values?: string[];
|
||||||
values?: string[];
|
|
||||||
|
/**
|
||||||
/**
|
* Only when Type.STRING
|
||||||
* Only when Type.STRING
|
*/
|
||||||
*/
|
notempty?: boolean; // Only STRING
|
||||||
notempty?: boolean; // Only STRING
|
}
|
||||||
}
|
|
||||||
|
export interface Checks {
|
||||||
export interface Checks {
|
[index: string]: CheckObject; // | Types
|
||||||
[index: string]: CheckObject; // | Types
|
}
|
||||||
}
|
|
||||||
|
// req: Request, res: Response, next: NextFunction
|
||||||
// req: Request, res: Response, next: NextFunction
|
export default function (fields: Checks, noadditional = false) {
|
||||||
export default function (fields: Checks, noadditional = false) {
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
return (req: Request, res: Response, next: NextFunction) => {
|
let errors: { message: string; field: string }[] = [];
|
||||||
let errors: { message: string; field: string }[] = [];
|
|
||||||
|
function check(data: any, field_name: string, field: CheckObject) {
|
||||||
function check(data: any, field_name: string, field: CheckObject) {
|
if (data !== undefined && data !== null) {
|
||||||
if (data !== undefined && data !== null) {
|
switch (field.type) {
|
||||||
switch (field.type) {
|
case Types.STRING:
|
||||||
case Types.STRING:
|
if (typeof data === "string") {
|
||||||
if (isString(data)) {
|
if (!field.notempty) return;
|
||||||
if (!field.notempty) return;
|
if (data !== "") return;
|
||||||
if (data !== "") return;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case Types.NUMBER:
|
||||||
case Types.NUMBER:
|
if (typeof data == "number") return;
|
||||||
if (typeof data == "number") return;
|
break;
|
||||||
break;
|
case Types.EMAIL:
|
||||||
case Types.EMAIL:
|
if (isEmail(data)) return;
|
||||||
if (isEmail(data)) return;
|
break;
|
||||||
break;
|
case Types.BOOLEAN:
|
||||||
case Types.BOOLEAN:
|
if (typeof data == "boolean") return;
|
||||||
if (typeof data == "boolean") return;
|
break;
|
||||||
break;
|
case Types.OBJECT:
|
||||||
case Types.OBJECT:
|
if (typeof data == "object") return;
|
||||||
if (typeof data == "object") return;
|
break;
|
||||||
break;
|
case Types.ARRAY:
|
||||||
case Types.ARRAY:
|
if (Array.isArray(data)) return;
|
||||||
if (Array.isArray(data)) return;
|
break;
|
||||||
break;
|
case Types.DATE:
|
||||||
case Types.DATE:
|
if (types.isDate(data)) return;
|
||||||
if (isDate(data)) return;
|
break;
|
||||||
break;
|
case Types.ENUM:
|
||||||
case Types.ENUM:
|
if (typeof data == "string") {
|
||||||
if (typeof data == "string") {
|
if (field.values.indexOf(data) >= 0) return;
|
||||||
if (field.values.indexOf(data) >= 0) return;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
Logging.error(
|
||||||
Logging.error(
|
`Invalid type to check: ${field.type} ${Types[field.type]}`
|
||||||
`Invalid type to check: ${field.type} ${Types[field.type]}`
|
);
|
||||||
);
|
}
|
||||||
}
|
errors.push({
|
||||||
errors.push({
|
message: res.__(
|
||||||
message: res.__(
|
"Field {{field}} has wrong type. It should be from type {{type}}",
|
||||||
"Field {{field}} has wrong type. It should be from type {{type}}",
|
{ field: field_name, type: Types[field.type].toLowerCase() }
|
||||||
{ field: field_name, type: Types[field.type].toLowerCase() }
|
),
|
||||||
),
|
field: field_name,
|
||||||
field: field_name,
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
if (!field.optional)
|
||||||
if (!field.optional)
|
errors.push({
|
||||||
errors.push({
|
message: res.__("Field {{field}} is not defined", {
|
||||||
message: res.__("Field {{field}} is not defined", {
|
field: field_name,
|
||||||
field: field_name,
|
}),
|
||||||
}),
|
field: field_name,
|
||||||
field: field_name,
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
for (let field_name in fields) {
|
||||||
for (let field_name in fields) {
|
let field = fields[field_name];
|
||||||
let field = fields[field_name];
|
let data = fields[field_name].query
|
||||||
let data = fields[field_name].query
|
? req.query[field_name]
|
||||||
? req.query[field_name]
|
: req.body[field_name];
|
||||||
: req.body[field_name];
|
check(data, field_name, field);
|
||||||
check(data, field_name, field);
|
}
|
||||||
}
|
|
||||||
|
if (noadditional) {
|
||||||
if (noadditional) {
|
//Checks if the data given has additional parameters
|
||||||
//Checks if the data given has additional parameters
|
let should = Object.keys(fields);
|
||||||
let should = Object.keys(fields);
|
should = should.filter((e) => !fields[e].query); //Query parameters should not exist on body
|
||||||
should = should.filter((e) => !fields[e].query); //Query parameters should not exist on body
|
let has = Object.keys(req.body);
|
||||||
let has = Object.keys(req.body);
|
|
||||||
|
has.every((e) => {
|
||||||
has.every((e) => {
|
if (should.indexOf(e) >= 0) {
|
||||||
if (should.indexOf(e) >= 0) {
|
return true;
|
||||||
return true;
|
} else {
|
||||||
} else {
|
errors.push({
|
||||||
errors.push({
|
message: res.__("Field {{field}} should not be there", {
|
||||||
message: res.__("Field {{field}} should not be there", {
|
field: e,
|
||||||
field: e,
|
}),
|
||||||
}),
|
field: e,
|
||||||
field: e,
|
});
|
||||||
});
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
if (errors.length > 0) {
|
||||||
if (errors.length > 0) {
|
let err = new RequestError(errors, HttpStatusCode.BAD_REQUEST, true);
|
||||||
let err = new RequestError(errors, HttpStatusCode.BAD_REQUEST, true);
|
next(err);
|
||||||
next(err);
|
} else next();
|
||||||
} else next();
|
};
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import { GetUserMiddleware } from "../middlewares/user";
|
import { GetUserMiddleware } from "../middlewares/user.js";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import Permission, { IPermission } from "../../models/permissions";
|
import Permission, { IPermission } from "../../models/permissions.js";
|
||||||
import ClientCode from "../../models/client_code";
|
import ClientCode from "../../models/client_code.js";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
// import { ObjectId } from "bson";
|
// import { ObjectId } from "bson";
|
||||||
import Grant, { IGrant } from "../../models/grants";
|
import Grant, { IGrant } from "../../models/grants.js";
|
||||||
import GetAuthPage from "../../views/authorize";
|
import GetAuthPage from "../../views/authorize.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
// const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => {
|
// const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => {
|
||||||
|
@ -1,73 +1,73 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import GetAuthRoute from "./auth";
|
import GetAuthRoute from "./auth.js";
|
||||||
import JWTRoute from "./jwt";
|
import JWTRoute from "./jwt.js";
|
||||||
import Public from "./public";
|
import Public from "./public.js";
|
||||||
import RefreshTokenRoute from "./refresh";
|
import RefreshTokenRoute from "./refresh.js";
|
||||||
import ProfileRoute from "./profile";
|
import ProfileRoute from "./profile.js";
|
||||||
|
|
||||||
const OAuthRoute: Router = Router();
|
const OAuthRoute: Router = Router();
|
||||||
/**
|
/**
|
||||||
* @api {post} /oauth/auth
|
* @api {post} /oauth/auth
|
||||||
* @apiName OAuthAuth
|
* @apiName OAuthAuth
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
* @apiPermission user Special required
|
* @apiPermission user Special required
|
||||||
*
|
*
|
||||||
* @apiParam {String} response_type must be "code" others are not supported
|
* @apiParam {String} response_type must be "code" others are not supported
|
||||||
* @apiParam {String} client_id ClientID
|
* @apiParam {String} client_id ClientID
|
||||||
* @apiParam {String} redirect_uri The URI to redirect with code
|
* @apiParam {String} redirect_uri The URI to redirect with code
|
||||||
* @apiParam {String} scope Scope that contains the requested permissions (comma seperated list of permissions)
|
* @apiParam {String} scope Scope that contains the requested permissions (comma seperated list of permissions)
|
||||||
* @apiParam {String} state State, that will be passed to redirect_uri for client
|
* @apiParam {String} state State, that will be passed to redirect_uri for client
|
||||||
* @apiParam {String} nored Deactivates the Redirect response from server and instead returns the redirect URI in JSON response
|
* @apiParam {String} nored Deactivates the Redirect response from server and instead returns the redirect URI in JSON response
|
||||||
*/
|
*/
|
||||||
OAuthRoute.post("/auth", GetAuthRoute(false));
|
OAuthRoute.post("/auth", GetAuthRoute(false));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /oauth/jwt
|
* @api {get} /oauth/jwt
|
||||||
* @apiName OAuthJwt
|
* @apiName OAuthJwt
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
* @apiPermission none
|
* @apiPermission none
|
||||||
*
|
*
|
||||||
* @apiParam {String} refreshtoken
|
* @apiParam {String} refreshtoken
|
||||||
*
|
*
|
||||||
* @apiSuccess {String} token The JWT that allowes the application to access the recources granted for refresh token
|
* @apiSuccess {String} token The JWT that allowes the application to access the recources granted for refresh token
|
||||||
*/
|
*/
|
||||||
OAuthRoute.get("/jwt", JWTRoute);
|
OAuthRoute.get("/jwt", JWTRoute);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /oauth/public
|
* @api {get} /oauth/public
|
||||||
* @apiName OAuthPublic
|
* @apiName OAuthPublic
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
* @apiPermission none
|
* @apiPermission none
|
||||||
*
|
*
|
||||||
* @apiSuccess {String} public_key The applications public_key. Used to verify JWT.
|
* @apiSuccess {String} public_key The applications public_key. Used to verify JWT.
|
||||||
*/
|
*/
|
||||||
OAuthRoute.get("/public", Public);
|
OAuthRoute.get("/public", Public);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /oauth/refresh
|
* @api {get} /oauth/refresh
|
||||||
* @apiName OAuthRefreshGet
|
* @apiName OAuthRefreshGet
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
*/
|
*/
|
||||||
OAuthRoute.get("/refresh", RefreshTokenRoute);
|
OAuthRoute.get("/refresh", RefreshTokenRoute);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {post} /oauth/refresh
|
* @api {post} /oauth/refresh
|
||||||
* @apiName OAuthRefreshPost
|
* @apiName OAuthRefreshPost
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
*/
|
*/
|
||||||
OAuthRoute.post("/refresh", RefreshTokenRoute);
|
OAuthRoute.post("/refresh", RefreshTokenRoute);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /oauth/profile
|
* @api {get} /oauth/profile
|
||||||
* @apiName OAuthProfile
|
* @apiName OAuthProfile
|
||||||
*
|
*
|
||||||
* @apiGroup oauth
|
* @apiGroup oauth
|
||||||
*/
|
*/
|
||||||
OAuthRoute.get("/profile", ProfileRoute);
|
OAuthRoute.get("/profile", ProfileRoute);
|
||||||
|
|
||||||
export default OAuthRoute;
|
export default OAuthRoute;
|
||||||
|
@ -1,43 +1,43 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import RefreshToken from "../../models/refresh_token";
|
import RefreshToken from "../../models/refresh_token.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import { getAccessTokenJWT } from "../../helper/jwt";
|
import { getAccessTokenJWT } from "../../helper/jwt.js";
|
||||||
|
|
||||||
const JWTRoute = promiseMiddleware(async (req: Request, res: Response) => {
|
const JWTRoute = promiseMiddleware(async (req: Request, res: Response) => {
|
||||||
let { refreshtoken } = req.query as { [key: string]: string };
|
let { refreshtoken } = req.query as { [key: string]: string };
|
||||||
if (!refreshtoken)
|
if (!refreshtoken)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Refresh token not set"),
|
req.__("Refresh token not set"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
let token = await RefreshToken.findOne({ token: refreshtoken });
|
let token = await RefreshToken.findOne({ token: refreshtoken });
|
||||||
if (!token)
|
if (!token)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Invalid token"),
|
req.__("Invalid token"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
let user = await User.findById(token.user);
|
let user = await User.findById(token.user);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
token.valid = false;
|
token.valid = false;
|
||||||
await RefreshToken.save(token);
|
await RefreshToken.save(token);
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Invalid token"),
|
req.__("Invalid token"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = await Client.findById(token.client);
|
let client = await Client.findById(token.client);
|
||||||
|
|
||||||
let jwt = await getAccessTokenJWT({
|
let jwt = await getAccessTokenJWT({
|
||||||
user,
|
user,
|
||||||
permissions: token.permissions,
|
permissions: token.permissions,
|
||||||
client,
|
client,
|
||||||
});
|
});
|
||||||
res.json({ token: jwt });
|
res.json({ token: jwt });
|
||||||
});
|
});
|
||||||
export default JWTRoute;
|
export default JWTRoute;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Mail from "../../models/mail";
|
import Mail from "../../models/mail.js";
|
||||||
import { GetClientApiAuthMiddleware } from "../middlewares/client";
|
import { GetClientApiAuthMiddleware } from "../middlewares/client.js";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { public_key } from "../../keys";
|
import { public_key } from "../../keys.js";
|
||||||
|
|
||||||
export default function Public(req: Request, res: Response) {
|
export default function Public(req: Request, res: Response) {
|
||||||
res.json({ public_key: public_key });
|
res.json({ public_key: public_key });
|
||||||
}
|
}
|
||||||
|
@ -1,122 +1,122 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import User from "../../models/user";
|
import User from "../../models/user.js";
|
||||||
import Client from "../../models/client";
|
import Client from "../../models/client.js";
|
||||||
import {
|
import {
|
||||||
getAccessTokenJWT,
|
getAccessTokenJWT,
|
||||||
getIDToken,
|
getIDToken,
|
||||||
AccessTokenJWTExp,
|
AccessTokenJWTExp,
|
||||||
} from "../../helper/jwt";
|
} from "../../helper/jwt.js";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import { GetClientAuthMiddleware } from "../middlewares/client";
|
import { GetClientAuthMiddleware } from "../middlewares/client.js";
|
||||||
import ClientCode from "../../models/client_code";
|
import ClientCode from "../../models/client_code.js";
|
||||||
import Mail from "../../models/mail";
|
import Mail from "../../models/mail.js";
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
// import { JWTExpDur } from "../../keys";
|
// import { JWTExpDur } from "../../keys";
|
||||||
import RefreshToken from "../../models/refresh_token";
|
import RefreshToken from "../../models/refresh_token.js";
|
||||||
import { getEncryptionKey } from "../../helper/user_key";
|
import { getEncryptionKey } from "../../helper/user_key.js";
|
||||||
import { refreshTokenValidTime } from "../../config";
|
import { refreshTokenValidTime } from "../../config.js";
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
/*
|
/*
|
||||||
For example, the authorization server could employ refresh token
|
For example, the authorization server could employ refresh token
|
||||||
rotation in which a new refresh token is issued with every access
|
rotation in which a new refresh token is issued with every access
|
||||||
token refresh response. The previous refresh token is invalidated but retained by the authorization server. If a refresh token is
|
token refresh response. The previous refresh token is invalidated but retained by the authorization server. If a refresh token is
|
||||||
compromised and subsequently used by both the attacker and the
|
compromised and subsequently used by both the attacker and the
|
||||||
legitimate client, one of them will present an invalidated refresh
|
legitimate client, one of them will present an invalidated refresh
|
||||||
token, which will inform the authorization server of the breach.
|
token, which will inform the authorization server of the breach.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const RefreshTokenRoute = Stacker(
|
const RefreshTokenRoute = Stacker(
|
||||||
GetClientAuthMiddleware(false, false, true),
|
GetClientAuthMiddleware(false, false, true),
|
||||||
async (req: Request, res: Response) => {
|
async (req: Request, res: Response) => {
|
||||||
let grant_type = req.query.grant_type || req.body.grant_type;
|
let grant_type = req.query.grant_type || req.body.grant_type;
|
||||||
if (!grant_type || grant_type === "authorization_code") {
|
if (!grant_type || grant_type === "authorization_code") {
|
||||||
let code = req.query.code || req.body.code;
|
let code = req.query.code || req.body.code;
|
||||||
let nonce = req.query.nonce || req.body.nonce;
|
let nonce = req.query.nonce || req.body.nonce;
|
||||||
|
|
||||||
let c = await ClientCode.findOne({ code: code });
|
let c = await ClientCode.findOne({ code: code });
|
||||||
if (!c || moment(c.validTill).isBefore()) {
|
if (!c || moment(c.validTill).isBefore()) {
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Invalid code"),
|
req.__("Invalid code"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = await Client.findById(c.client);
|
let client = await Client.findById(c.client);
|
||||||
|
|
||||||
let user = await User.findById(c.user);
|
let user = await User.findById(c.user);
|
||||||
let mails = await Promise.all(user.mails.map((m) => Mail.findOne(m)));
|
let mails = await Promise.all(user.mails.map((m) => Mail.findOne(m)));
|
||||||
|
|
||||||
let token = RefreshToken.new({
|
let token = RefreshToken.new({
|
||||||
user: c.user,
|
user: c.user,
|
||||||
client: c.client,
|
client: c.client,
|
||||||
permissions: c.permissions,
|
permissions: c.permissions,
|
||||||
token: randomBytes(16).toString("hex"),
|
token: randomBytes(16).toString("hex"),
|
||||||
valid: true,
|
valid: true,
|
||||||
validTill: moment().add(refreshTokenValidTime).toDate(),
|
validTill: moment().add(refreshTokenValidTime).toDate(),
|
||||||
});
|
});
|
||||||
await RefreshToken.save(token);
|
await RefreshToken.save(token);
|
||||||
await ClientCode.delete(c);
|
await ClientCode.delete(c);
|
||||||
|
|
||||||
let mail = mails.find((e) => e.primary);
|
let mail = mails.find((e) => e.primary);
|
||||||
if (!mail) mail = mails[0];
|
if (!mail) mail = mails[0];
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
refresh_token: token.token,
|
refresh_token: token.token,
|
||||||
token: token.token,
|
token: token.token,
|
||||||
access_token: await getAccessTokenJWT({
|
access_token: await getAccessTokenJWT({
|
||||||
client: client,
|
client: client,
|
||||||
user: user,
|
user: user,
|
||||||
permissions: c.permissions,
|
permissions: c.permissions,
|
||||||
}),
|
}),
|
||||||
token_type: "bearer",
|
token_type: "bearer",
|
||||||
expires_in: AccessTokenJWTExp.asSeconds(),
|
expires_in: AccessTokenJWTExp.asSeconds(),
|
||||||
profile: {
|
profile: {
|
||||||
uid: user.uid,
|
uid: user.uid,
|
||||||
email: mail ? mail.mail : "",
|
email: mail ? mail.mail : "",
|
||||||
name: user.name,
|
name: user.name,
|
||||||
enc_key: getEncryptionKey(user, client),
|
enc_key: getEncryptionKey(user, client),
|
||||||
},
|
},
|
||||||
id_token: getIDToken(user, client.client_id, nonce),
|
id_token: getIDToken(user, client.client_id, nonce),
|
||||||
});
|
});
|
||||||
} else if (grant_type === "refresh_token") {
|
} else if (grant_type === "refresh_token") {
|
||||||
let refresh_token = req.query.refresh_token || req.body.refresh_token;
|
let refresh_token = req.query.refresh_token || req.body.refresh_token;
|
||||||
if (!refresh_token)
|
if (!refresh_token)
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("refresh_token not set"),
|
req.__("refresh_token not set"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
let token = await RefreshToken.findOne({ token: refresh_token });
|
let token = await RefreshToken.findOne({ token: refresh_token });
|
||||||
if (!token || !token.valid || moment(token.validTill).isBefore())
|
if (!token || !token.valid || moment(token.validTill).isBefore())
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
req.__("Invalid token"),
|
req.__("Invalid token"),
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
token.validTill = moment().add(refreshTokenValidTime).toDate();
|
token.validTill = moment().add(refreshTokenValidTime).toDate();
|
||||||
await RefreshToken.save(token);
|
await RefreshToken.save(token);
|
||||||
|
|
||||||
let user = await User.findById(token.user);
|
let user = await User.findById(token.user);
|
||||||
let client = await Client.findById(token.client);
|
let client = await Client.findById(token.client);
|
||||||
let jwt = await getAccessTokenJWT({
|
let jwt = await getAccessTokenJWT({
|
||||||
user,
|
user,
|
||||||
client,
|
client,
|
||||||
permissions: token.permissions,
|
permissions: token.permissions,
|
||||||
});
|
});
|
||||||
res.json({
|
res.json({
|
||||||
access_token: jwt,
|
access_token: jwt,
|
||||||
expires_in: AccessTokenJWTExp.asSeconds(),
|
expires_in: AccessTokenJWTExp.asSeconds(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new RequestError(
|
throw new RequestError(
|
||||||
"invalid grant_type",
|
"invalid grant_type",
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default RefreshTokenRoute;
|
export default RefreshTokenRoute;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import Register from "./register";
|
import Register from "./register.js";
|
||||||
import OAuthRoute from "./oauth";
|
import OAuthRoute from "./oauth/index.js";
|
||||||
|
|
||||||
const UserRoute: Router = Router();
|
const UserRoute: Router = Router();
|
||||||
|
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
|
import RequestError, { HttpStatusCode } from "../../../helper/request_error.js";
|
||||||
import Client, { IClient } from "../../../models/client";
|
import Client, { IClient } from "../../../models/client.js";
|
||||||
|
|
||||||
export async function getClientWithOrigin(client_id: string, origin: string) {
|
export async function getClientWithOrigin(client_id: string, origin: string) {
|
||||||
const client = await Client.findOne({
|
const client = await Client.findOne({
|
||||||
client_id,
|
client_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const clientNotFoundError = new RequestError(
|
const clientNotFoundError = new RequestError(
|
||||||
"Client not found!",
|
"Client not found!",
|
||||||
HttpStatusCode.BAD_REQUEST
|
HttpStatusCode.BAD_REQUEST
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!client) throw clientNotFoundError;
|
if (!client) throw clientNotFoundError;
|
||||||
|
|
||||||
const clientUrl = new URL(client.redirect_url);
|
const clientUrl = new URL(client.redirect_url);
|
||||||
|
|
||||||
if (clientUrl.hostname !== origin) throw clientNotFoundError;
|
if (clientUrl.hostname !== origin) throw clientNotFoundError;
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { GetJWTByUser } from "./jwt";
|
import { GetJWTByUser } from "./jwt.js";
|
||||||
import { GetPermissionsForAuthRequest } from "./permissions";
|
import { GetPermissionsForAuthRequest } from "./permissions.js";
|
||||||
import { GetTokenByUser } from "./refresh_token";
|
import { GetTokenByUser } from "./refresh_token.js";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get("/jwt", GetJWTByUser);
|
router.get("/jwt", GetJWTByUser);
|
||||||
router.get("/permissions", GetPermissionsForAuthRequest);
|
router.get("/permissions", GetPermissionsForAuthRequest);
|
||||||
router.get("/refresh_token", GetTokenByUser);
|
router.get("/refresh_token", GetTokenByUser);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Stacker from "../../middlewares/stacker";
|
import Stacker from "../../middlewares/stacker.js";
|
||||||
import { GetUserMiddleware } from "../../middlewares/user";
|
import { GetUserMiddleware } from "../../middlewares/user.js";
|
||||||
import { URL } from "url";
|
|
||||||
import Client from "../../../models/client";
|
import { getAccessTokenJWT } from "../../../helper/jwt.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
|
import { getClientWithOrigin } from "./_helper.js";
|
||||||
import { getAccessTokenJWT } from "../../../helper/jwt";
|
|
||||||
import { getClientWithOrigin } from "./_helper";
|
export const GetJWTByUser = Stacker(
|
||||||
|
GetUserMiddleware(true, false),
|
||||||
export const GetJWTByUser = Stacker(
|
async (req: Request, res: Response) => {
|
||||||
GetUserMiddleware(true, false),
|
const { client_id, origin } = req.query as { [key: string]: string };
|
||||||
async (req: Request, res: Response) => {
|
|
||||||
const { client_id, origin } = req.query as { [key: string]: string };
|
const client = await getClientWithOrigin(client_id, origin);
|
||||||
|
|
||||||
const client = await getClientWithOrigin(client_id, origin);
|
const jwt = await getAccessTokenJWT({
|
||||||
|
user: req.user,
|
||||||
const jwt = await getAccessTokenJWT({
|
client: client,
|
||||||
user: req.user,
|
permissions: [],
|
||||||
client: client,
|
});
|
||||||
permissions: [],
|
|
||||||
});
|
res.json({ jwt });
|
||||||
|
}
|
||||||
res.json({ jwt });
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Stacker from "../../middlewares/stacker";
|
import Stacker from "../../middlewares/stacker.js";
|
||||||
import { GetUserMiddleware } from "../../middlewares/user";
|
import { GetUserMiddleware } from "../../middlewares/user.js";
|
||||||
import { URL } from "url";
|
import RequestError, { HttpStatusCode } from "../../../helper/request_error.js";
|
||||||
import Client from "../../../models/client";
|
import { getClientWithOrigin } from "./_helper.js";
|
||||||
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
|
import Permission from "../../../models/permissions.js";
|
||||||
import { randomBytes } from "crypto";
|
|
||||||
import moment = require("moment");
|
|
||||||
import RefreshToken from "../../../models/refresh_token";
|
|
||||||
import { refreshTokenValidTime } from "../../../config";
|
|
||||||
import { getClientWithOrigin } from "./_helper";
|
|
||||||
import Permission from "../../../models/permissions";
|
|
||||||
|
|
||||||
export const GetPermissionsForAuthRequest = Stacker(
|
export const GetPermissionsForAuthRequest = Stacker(
|
||||||
GetUserMiddleware(true, false),
|
GetUserMiddleware(true, false),
|
||||||
|
@ -1,49 +1,47 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import Stacker from "../../middlewares/stacker";
|
import Stacker from "../../middlewares/stacker.js";
|
||||||
import { GetUserMiddleware } from "../../middlewares/user";
|
import { GetUserMiddleware } from "../../middlewares/user.js";
|
||||||
import { URL } from "url";
|
import RequestError, { HttpStatusCode } from "../../../helper/request_error.js";
|
||||||
import Client from "../../../models/client";
|
import { randomBytes } from "crypto";
|
||||||
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
|
import moment = require("moment");
|
||||||
import { randomBytes } from "crypto";
|
import RefreshToken from "../../../models/refresh_token.js";
|
||||||
import moment = require("moment");
|
import { refreshTokenValidTime } from "../../../config.js";
|
||||||
import RefreshToken from "../../../models/refresh_token";
|
import { getClientWithOrigin } from "./_helper.js";
|
||||||
import { refreshTokenValidTime } from "../../../config";
|
import Permission from "../../../models/permissions.js";
|
||||||
import { getClientWithOrigin } from "./_helper";
|
|
||||||
import Permission from "../../../models/permissions";
|
export const GetTokenByUser = Stacker(
|
||||||
|
GetUserMiddleware(true, false),
|
||||||
export const GetTokenByUser = Stacker(
|
async (req: Request, res: Response) => {
|
||||||
GetUserMiddleware(true, false),
|
const { client_id, origin, permissions } = req.query as {
|
||||||
async (req: Request, res: Response) => {
|
[key: string]: string;
|
||||||
const { client_id, origin, permissions } = req.query as {
|
};
|
||||||
[key: string]: string;
|
|
||||||
};
|
const client = await getClientWithOrigin(client_id, origin);
|
||||||
|
|
||||||
const client = await getClientWithOrigin(client_id, origin);
|
const perm = permissions.split(",").filter((e) => !!e);
|
||||||
|
|
||||||
const perm = permissions.split(",").filter((e) => !!e);
|
const resolved = await Promise.all(
|
||||||
|
perm.map((p) => Permission.findById(p))
|
||||||
const resolved = await Promise.all(
|
);
|
||||||
perm.map((p) => Permission.findById(p))
|
|
||||||
);
|
if (resolved.some((e) => e.grant_type !== "user")) {
|
||||||
|
throw new RequestError(
|
||||||
if (resolved.some((e) => e.grant_type !== "user")) {
|
"Invalid Permission requested",
|
||||||
throw new RequestError(
|
HttpStatusCode.BAD_REQUEST
|
||||||
"Invalid Permission requested",
|
);
|
||||||
HttpStatusCode.BAD_REQUEST
|
}
|
||||||
);
|
|
||||||
}
|
let token = RefreshToken.new({
|
||||||
|
user: req.user._id,
|
||||||
let token = RefreshToken.new({
|
client: client._id,
|
||||||
user: req.user._id,
|
permissions: resolved.map((e) => e._id),
|
||||||
client: client._id,
|
token: randomBytes(16).toString("hex"),
|
||||||
permissions: resolved.map((e) => e._id),
|
valid: true,
|
||||||
token: randomBytes(16).toString("hex"),
|
validTill: moment().add(refreshTokenValidTime).toDate(),
|
||||||
valid: true,
|
});
|
||||||
validTill: moment().add(refreshTokenValidTime).toDate(),
|
|
||||||
});
|
await RefreshToken.save(token);
|
||||||
|
|
||||||
await RefreshToken.save(token);
|
res.json({ token });
|
||||||
|
}
|
||||||
res.json({ token });
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@ -1,155 +1,155 @@
|
|||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import Stacker from "../middlewares/stacker";
|
import Stacker from "../middlewares/stacker.js";
|
||||||
import verify, { Types } from "../middlewares/verify";
|
import verify, { Types } from "../middlewares/verify.js";
|
||||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
import promiseMiddleware from "../../helper/promiseMiddleware.js";
|
||||||
import User, { Gender } from "../../models/user";
|
import User, { Gender } from "../../models/user.js";
|
||||||
import { HttpStatusCode } from "../../helper/request_error";
|
import { HttpStatusCode } from "../../helper/request_error.js";
|
||||||
import Mail from "../../models/mail";
|
import Mail from "../../models/mail.js";
|
||||||
import RegCode from "../../models/regcodes";
|
import RegCode from "../../models/regcodes.js";
|
||||||
|
|
||||||
const Register = Stacker(
|
const Register = Stacker(
|
||||||
verify({
|
verify({
|
||||||
mail: {
|
mail: {
|
||||||
type: Types.EMAIL,
|
type: Types.EMAIL,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
salt: {
|
salt: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
regcode: {
|
regcode: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
gender: {
|
gender: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: Types.STRING,
|
type: Types.STRING,
|
||||||
notempty: true,
|
notempty: true,
|
||||||
},
|
},
|
||||||
// birthday: {
|
// birthday: {
|
||||||
// type: Types.DATE
|
// type: Types.DATE
|
||||||
// }
|
// }
|
||||||
}),
|
}),
|
||||||
promiseMiddleware(async (req: Request, res: Response) => {
|
promiseMiddleware(async (req: Request, res: Response) => {
|
||||||
let {
|
let {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
salt,
|
salt,
|
||||||
mail,
|
mail,
|
||||||
gender,
|
gender,
|
||||||
name,
|
name,
|
||||||
birthday,
|
birthday,
|
||||||
regcode,
|
regcode,
|
||||||
} = req.body;
|
} = req.body;
|
||||||
let u = await User.findOne({ username: username.toLowerCase() });
|
let u = await User.findOne({ username: username.toLowerCase() });
|
||||||
if (u) {
|
if (u) {
|
||||||
let err = {
|
let err = {
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
message: req.__("Username taken"),
|
message: req.__("Username taken"),
|
||||||
field: "username",
|
field: "username",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
status: HttpStatusCode.BAD_REQUEST,
|
status: HttpStatusCode.BAD_REQUEST,
|
||||||
nolog: true,
|
nolog: true,
|
||||||
};
|
};
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let m = await Mail.findOne({ mail: mail });
|
let m = await Mail.findOne({ mail: mail });
|
||||||
if (m) {
|
if (m) {
|
||||||
let err = {
|
let err = {
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
message: req.__("Mail linked with other account"),
|
message: req.__("Mail linked with other account"),
|
||||||
field: "mail",
|
field: "mail",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
status: HttpStatusCode.BAD_REQUEST,
|
status: HttpStatusCode.BAD_REQUEST,
|
||||||
nolog: true,
|
nolog: true,
|
||||||
};
|
};
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let regc = await RegCode.findOne({ token: regcode });
|
let regc = await RegCode.findOne({ token: regcode });
|
||||||
if (!regc) {
|
if (!regc) {
|
||||||
let err = {
|
let err = {
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
message: req.__("Invalid registration code"),
|
message: req.__("Invalid registration code"),
|
||||||
field: "regcode",
|
field: "regcode",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
status: HttpStatusCode.BAD_REQUEST,
|
status: HttpStatusCode.BAD_REQUEST,
|
||||||
nolog: true,
|
nolog: true,
|
||||||
};
|
};
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!regc.valid) {
|
if (!regc.valid) {
|
||||||
let err = {
|
let err = {
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
message: req.__("Registration code already used"),
|
message: req.__("Registration code already used"),
|
||||||
field: "regcode",
|
field: "regcode",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
status: HttpStatusCode.BAD_REQUEST,
|
status: HttpStatusCode.BAD_REQUEST,
|
||||||
nolog: true,
|
nolog: true,
|
||||||
};
|
};
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let g = -1;
|
let g = -1;
|
||||||
switch (gender) {
|
switch (gender) {
|
||||||
case "male":
|
case "male":
|
||||||
g = Gender.male;
|
g = Gender.male;
|
||||||
break;
|
break;
|
||||||
case "female":
|
case "female":
|
||||||
g = Gender.female;
|
g = Gender.female;
|
||||||
break;
|
break;
|
||||||
case "other":
|
case "other":
|
||||||
g = Gender.other;
|
g = Gender.other;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g = Gender.none;
|
g = Gender.none;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = User.new({
|
let user = User.new({
|
||||||
username: username.toLowerCase(),
|
username: username.toLowerCase(),
|
||||||
password: password,
|
password: password,
|
||||||
salt: salt,
|
salt: salt,
|
||||||
gender: g,
|
gender: g,
|
||||||
name: name,
|
name: name,
|
||||||
// birthday: birthday,
|
// birthday: birthday,
|
||||||
admin: false,
|
admin: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
regc.valid = false;
|
regc.valid = false;
|
||||||
await RegCode.save(regc);
|
await RegCode.save(regc);
|
||||||
|
|
||||||
let ml = Mail.new({
|
let ml = Mail.new({
|
||||||
mail: mail,
|
mail: mail,
|
||||||
primary: true,
|
primary: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await Mail.save(ml);
|
await Mail.save(ml);
|
||||||
|
|
||||||
user.mails.push(ml._id);
|
user.mails.push(ml._id);
|
||||||
await User.save(user);
|
await User.save(user);
|
||||||
res.json({ success: true });
|
res.json({ success: true });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
export default Register;
|
export default Register;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import SafeMongo from "@hibas123/safe_mongo";
|
import SafeMongo from "@hibas123/safe_mongo";
|
||||||
import Config from "./config";
|
import Config from "./config.js";
|
||||||
|
|
||||||
|
|
||||||
const host = Config.database.host || "localhost";
|
const host = Config.database.host || "localhost";
|
||||||
|
4
Backend/src/express.d.ts
vendored
4
Backend/src/express.d.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
import { IUser } from "./models/user";
|
import { IUser } from "./models/user.js";
|
||||||
import { IClient } from "./models/client";
|
import { IClient } from "./models/client.js";
|
||||||
|
|
||||||
declare module "express" {
|
declare module "express" {
|
||||||
interface Request {
|
interface Request {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { IUser, Gender } from "../models/user";
|
import { IUser, Gender } from "../models/user.js";
|
||||||
import { ObjectId } from "bson";
|
import { ObjectId } from "bson";
|
||||||
import { createJWT } from "../keys";
|
import { createJWT } from "../keys.js";
|
||||||
import { IClient } from "../models/client";
|
import { IClient } from "../models/client.js";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
|
|
||||||
export interface OAuthJWT {
|
export interface OAuthJWT {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { SessionContext } from "../api/jrpc";
|
import { SessionContext } from "../api/jrpc/index.js";
|
||||||
|
|
||||||
export function requireLoginState(ctx: SessionContext, validated: boolean = true, special: boolean = false): boolean {
|
export function requireLoginState(ctx: SessionContext, validated: boolean = true, special: boolean = false): boolean {
|
||||||
if (!ctx.user) return false;
|
if (!ctx.user) return false;
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// import * as crypto from "crypto-js"
|
// import * as crypto from "crypto-js"
|
||||||
import { IUser } from "../models/user";
|
import { IUser } from "../models/user.js";
|
||||||
import { IClient } from "../models/client";
|
import { IClient } from "../models/client.js";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
|
|
||||||
function sha512(text: string) {
|
function sha512(text: string) {
|
||||||
let hash = crypto.createHash("sha512");
|
let hash = crypto.createHash("sha512");
|
||||||
hash.update(text);
|
hash.update(text);
|
||||||
return hash.digest("base64");
|
return hash.digest("base64");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEncryptionKey(user: IUser, client: IClient) {
|
export function getEncryptionKey(user: IUser, client: IClient) {
|
||||||
return sha512(
|
return sha512(
|
||||||
sha512(user.encryption_key) +
|
sha512(user.encryption_key) +
|
||||||
sha512(client._id.toHexString()) +
|
sha512(client._id.toHexString()) +
|
||||||
sha512(client.client_id)
|
sha512(client.client_id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,90 +1,90 @@
|
|||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import config from "./config";
|
import config from "./config.js";
|
||||||
|
|
||||||
// import NLS from "@hibas123/nodeloggingserver_client";
|
// import NLS from "@hibas123/nodeloggingserver_client";
|
||||||
// if (config.logging) {
|
// if (config.logging) {
|
||||||
// let s = NLS(Logging, config.logging.server, config.logging.appid, config.logging.token);
|
// let s = NLS(Logging, config.logging.server, config.logging.appid, config.logging.token);
|
||||||
// s.send(`[${new Date().toLocaleTimeString()}] Starting application`);
|
// s.send(`[${new Date().toLocaleTimeString()}] Starting application`);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if (!config.database) {
|
// if (!config.database) {
|
||||||
// Logging.error("No database config set. Terminating.")
|
// Logging.error("No database config set. Terminating.")
|
||||||
// process.exit();
|
// process.exit();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (!config.web) {
|
if (!config.web) {
|
||||||
Logging.error("No web config set. Terminating.");
|
Logging.error("No web config set. Terminating.");
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
import * as i18n from "i18n";
|
import * as i18n from "i18n";
|
||||||
i18n.configure({
|
i18n.configure({
|
||||||
locales: ["en", "de"],
|
locales: ["en", "de"],
|
||||||
directory: "./locales",
|
directory: "./locales",
|
||||||
});
|
});
|
||||||
|
|
||||||
import Web from "./web";
|
import Web from "./web.js";
|
||||||
import TestData from "./testdata";
|
import TestData from "./testdata.js";
|
||||||
import DB from "./database";
|
import DB from "./database.js";
|
||||||
|
|
||||||
Logging.log("Connecting to Database");
|
Logging.log("Connecting to Database");
|
||||||
if (config.core.dev) {
|
if (config.core.dev) {
|
||||||
Logging.warning("Running in dev mode! Database will be cleared!");
|
Logging.warning("Running in dev mode! Database will be cleared!");
|
||||||
}
|
}
|
||||||
DB.connect()
|
DB.connect()
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
Logging.log("Database connected", config);
|
Logging.log("Database connected", config);
|
||||||
if (config.core.dev) await TestData();
|
if (config.core.dev) await TestData();
|
||||||
let web = new Web(config.web);
|
let web = new Web(config.web);
|
||||||
web.listen();
|
web.listen();
|
||||||
|
|
||||||
let already = new Set();
|
let already = new Set();
|
||||||
function print(path, layer) {
|
function print(path, layer) {
|
||||||
if (layer.route) {
|
if (layer.route) {
|
||||||
layer.route.stack.forEach(
|
layer.route.stack.forEach(
|
||||||
print.bind(null, path.concat(split(layer.route.path)))
|
print.bind(null, path.concat(split(layer.route.path)))
|
||||||
);
|
);
|
||||||
} else if (layer.name === "router" && layer.handle.stack) {
|
} else if (layer.name === "router" && layer.handle.stack) {
|
||||||
layer.handle.stack.forEach(
|
layer.handle.stack.forEach(
|
||||||
print.bind(null, path.concat(split(layer.regexp)))
|
print.bind(null, path.concat(split(layer.regexp)))
|
||||||
);
|
);
|
||||||
} else if (layer.method) {
|
} else if (layer.method) {
|
||||||
let me: string = layer.method.toUpperCase();
|
let me: string = layer.method.toUpperCase();
|
||||||
me += " ".repeat(6 - me.length);
|
me += " ".repeat(6 - me.length);
|
||||||
let msg = `${me} /${path
|
let msg = `${me} /${path
|
||||||
.concat(split(layer.regexp))
|
.concat(split(layer.regexp))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join("/")}`;
|
.join("/")}`;
|
||||||
if (!already.has(msg)) {
|
if (!already.has(msg)) {
|
||||||
already.add(msg);
|
already.add(msg);
|
||||||
Logging.log(msg);
|
Logging.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function split(thing) {
|
function split(thing) {
|
||||||
if (typeof thing === "string") {
|
if (typeof thing === "string") {
|
||||||
return thing.split("/");
|
return thing.split("/");
|
||||||
} else if (thing.fast_slash) {
|
} else if (thing.fast_slash) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
var match = thing
|
var match = thing
|
||||||
.toString()
|
.toString()
|
||||||
.replace("\\/?", "")
|
.replace("\\/?", "")
|
||||||
.replace("(?=\\/|$)", "$")
|
.replace("(?=\\/|$)", "$")
|
||||||
.match(
|
.match(
|
||||||
/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//
|
/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//
|
||||||
);
|
);
|
||||||
return match
|
return match
|
||||||
? match[1].replace(/\\(.)/g, "$1").split("/")
|
? match[1].replace(/\\(.)/g, "$1").split("/")
|
||||||
: "<complex:" + thing.toString() + ">";
|
: "<complex:" + thing.toString() + ">";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Logging.log("--- Endpoints: ---");
|
// Logging.log("--- Endpoints: ---");
|
||||||
// web.server._router.stack.forEach(print.bind(null, []))
|
// web.server._router.stack.forEach(print.bind(null, []))
|
||||||
// Logging.log("--- Endpoints end ---")
|
// Logging.log("--- Endpoints end ---")
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
Logging.error(e);
|
Logging.error(e);
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,6 @@ export function verify(message: Buffer, signature: Buffer): boolean {
|
|||||||
export let public_key: string;
|
export let public_key: string;
|
||||||
|
|
||||||
import * as jwt from "jsonwebtoken";
|
import * as jwt from "jsonwebtoken";
|
||||||
import config from "./config";
|
|
||||||
|
|
||||||
export function createJWT(payload: any, options: jwt.SignOptions) {
|
export function createJWT(payload: any, options: jwt.SignOptions) {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { v4 } from "uuid";
|
|
||||||
|
|
||||||
export interface IClientCode extends ModelDataBase {
|
export interface IClientCode extends ModelDataBase {
|
||||||
user: ObjectId;
|
user: ObjectId;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export interface IGrant extends ModelDataBase {
|
export interface IGrant extends ModelDataBase {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
|
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo";
|
import { ModelDataBase } from "@hibas123/safe_mongo";
|
||||||
|
|
||||||
export interface IMail extends ModelDataBase {
|
export interface IMail extends ModelDataBase {
|
||||||
mail: string;
|
mail: string;
|
||||||
verified: boolean;
|
verified: boolean;
|
||||||
primary: boolean;
|
primary: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mail = DB.addModel<IMail>({
|
const Mail = DB.addModel<IMail>({
|
||||||
name: "mail",
|
name: "mail",
|
||||||
versions: [
|
versions: [
|
||||||
{
|
{
|
||||||
migration: () => {},
|
migration: () => { },
|
||||||
schema: {
|
schema: {
|
||||||
mail: { type: String },
|
mail: { type: String },
|
||||||
verified: { type: Boolean, default: false },
|
verified: { type: Boolean, default: false },
|
||||||
primary: { type: Boolean },
|
primary: { type: Boolean },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Mail;
|
export default Mail;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export interface IPermission extends ModelDataBase {
|
export interface IPermission extends ModelDataBase {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { TFAType } from "@hibas123/openauth-internalapi";
|
import { TFAType } from "@hibas123/openauth-internalapi";
|
||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "bson";
|
import { ObjectId } from "bson";
|
||||||
import { Binary } from "mongodb";
|
import { Binary } from "mongodb";
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ export interface IWebAuthn extends ITwoFactor {
|
|||||||
data: {
|
data: {
|
||||||
challenge?: any;
|
challenge?: any;
|
||||||
device?: {
|
device?: {
|
||||||
credentialID: Binary;
|
credentialID: Binary | string;
|
||||||
credentialPublicKey: Binary;
|
credentialPublicKey: Binary;
|
||||||
counter: number;
|
counter: number;
|
||||||
transports: AuthenticatorTransport[]
|
transports: AuthenticatorTransport[]
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import DB from "../database";
|
import DB from "../database.js";
|
||||||
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
|
|
||||||
|
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import { randomString } from "../helper/random";
|
import { randomString } from "../helper/random.js";
|
||||||
|
|
||||||
export enum Gender {
|
export enum Gender {
|
||||||
none,
|
none,
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import User, { Gender } from "./models/user";
|
import User, { Gender } from "./models/user.js";
|
||||||
import Client from "./models/client";
|
import Client from "./models/client.js";
|
||||||
import Logging from "@hibas123/nodelogging";
|
import Logging from "@hibas123/nodelogging";
|
||||||
import RegCode from "./models/regcodes";
|
import RegCode from "./models/regcodes.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Permission from "./models/permissions";
|
import Permission from "./models/permissions.js";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import DB from "./database";
|
import DB from "./database.js";
|
||||||
import TwoFactor from "./models/twofactor";
|
import TwoFactor from "./models/twofactor.js";
|
||||||
|
|
||||||
import LoginToken from "./models/login_token";
|
import LoginToken from "./models/login_token.js";
|
||||||
import Mail from "./models/mail";
|
import Mail from "./models/mail.js";
|
||||||
|
|
||||||
export default async function TestData() {
|
export default async function TestData() {
|
||||||
Logging.warn("Running in dev mode! Database will be cleared!");
|
Logging.warn("Running in dev mode! Database will be cleared!");
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { __ as i__ } from "i18n";
|
import { __ as i__ } from "i18n";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
||||||
|
|
||||||
export default function GetAdminPage(__: typeof i__): string {
|
export default function GetAdminPage(__: typeof i__): string {
|
||||||
let data = {};
|
let data = {};
|
||||||
return viewsv1.admin(config.core.dev)(data, { helpers: { i18n: __ } });
|
return viewsv1.admin(config.core.dev)(data, { helpers: { i18n: __ } });
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { __ as i__ } from "i18n";
|
import { __ as i__ } from "i18n";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
||||||
|
|
||||||
export default function GetAuthPage(
|
export default function GetAuthPage(
|
||||||
__: typeof i__,
|
__: typeof i__,
|
||||||
appname: string,
|
appname: string,
|
||||||
scopes: { name: string; description: string; logo: string }[]
|
scopes: { name: string; description: string; logo: string }[]
|
||||||
): string {
|
): string {
|
||||||
|
|
||||||
return viewsv1.authorize(config.core.dev)(
|
return viewsv1.authorize(config.core.dev)(
|
||||||
{
|
{
|
||||||
title: __("Authorize %s", appname),
|
title: __("Authorize %s", appname),
|
||||||
information: __(
|
information: __(
|
||||||
"By clicking on ALLOW, you allow this app to access the requested recources."
|
"By clicking on ALLOW, you allow this app to access the requested recources."
|
||||||
),
|
),
|
||||||
scopes: scopes,
|
scopes: scopes,
|
||||||
// request: request
|
// request: request
|
||||||
},
|
},
|
||||||
{ helpers: { i18n: __ } }
|
{ helpers: { i18n: __ } }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,12 @@ import {
|
|||||||
} from "express";
|
} from "express";
|
||||||
import * as Handlebars from "handlebars";
|
import * as Handlebars from "handlebars";
|
||||||
import moment = require("moment");
|
import moment = require("moment");
|
||||||
import { GetUserMiddleware, UserMiddleware } from "../api/middlewares/user";
|
import { GetUserMiddleware, UserMiddleware } from "../api/middlewares/user.js";
|
||||||
import GetAuthRoute from "../api/oauth/auth";
|
import GetAuthRoute from "../api/oauth/auth.js";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import { HttpStatusCode } from "../helper/request_error";
|
import { HttpStatusCode } from "../helper/request_error.js";
|
||||||
import GetAdminPage from "./admin";
|
import GetAdminPage from "./admin.js";
|
||||||
import GetRegistrationPage from "./register";
|
import GetRegistrationPage from "./register.js";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
const viewsv2_location = path.join(path.dirname(require.resolve("@hibas123/openauth-views-v2")), "build");
|
const viewsv2_location = path.join(path.dirname(require.resolve("@hibas123/openauth-views-v2")), "build");
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { __ as i__ } from "i18n";
|
import { __ as i__ } from "i18n";
|
||||||
import config from "../config";
|
import config from "../config.js";
|
||||||
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
import * as viewsv1 from "@hibas123/openauth-views-v1";
|
||||||
|
|
||||||
export default function GetRegistrationPage(__: typeof i__): string {
|
export default function GetRegistrationPage(__: typeof i__): string {
|
||||||
let data = {};
|
let data = {};
|
||||||
return viewsv1.register(config.core.dev)(data, { helpers: { i18n: __ } });
|
return viewsv1.register(config.core.dev)(data, { helpers: { i18n: __ } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import config, { WebConfig } from "./config";
|
import config, { WebConfig } from "./config.js";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { Express } from "express";
|
import { Express } from "express";
|
||||||
|
|
||||||
@ -11,14 +11,12 @@ import session from "express-session";
|
|||||||
import MongoStore from "connect-mongo";
|
import MongoStore from "connect-mongo";
|
||||||
|
|
||||||
import i18n from "i18n";
|
import i18n from "i18n";
|
||||||
import compression from "compression";
|
import ApiRouter from "./api/index.js";
|
||||||
import ApiRouter from "./api";
|
import ViewRouter from "./views/index.js";
|
||||||
import ViewRouter from "./views";
|
import RequestError, { HttpStatusCode } from "./helper/request_error.js";
|
||||||
import RequestError, { HttpStatusCode } from "./helper/request_error";
|
import DB from "./database.js";
|
||||||
import DB from "./database";
|
import promiseMiddleware from "./helper/promiseMiddleware.js";
|
||||||
import promiseMiddleware from "./helper/promiseMiddleware";
|
import User from "./models/user.js";
|
||||||
import User from "./models/user";
|
|
||||||
import LoginToken, { CheckToken } from "./models/login_token";
|
|
||||||
|
|
||||||
export default class Web {
|
export default class Web {
|
||||||
server: Express;
|
server: Express;
|
||||||
@ -41,7 +39,7 @@ export default class Web {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerMiddleware() {
|
private registerMiddleware() {
|
||||||
this.server.use(session({
|
const sess = session({
|
||||||
secret: config.core.secret,
|
secret: config.core.secret,
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
@ -57,7 +55,9 @@ export default class Web {
|
|||||||
secure: !config.core.dev,
|
secure: !config.core.dev,
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
}
|
}
|
||||||
}))
|
});
|
||||||
|
|
||||||
|
this.server.use(sess as any) // FIXME: These types seem to be brokenb, but they shouldn't
|
||||||
this.server.use(cookieparser());
|
this.server.use(cookieparser());
|
||||||
this.server.use(
|
this.server.use(
|
||||||
bodyparser.json(),
|
bodyparser.json(),
|
||||||
@ -103,16 +103,17 @@ export default class Web {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.server.use(
|
// Compression will be handled by the reverse proxy!
|
||||||
compression({
|
// this.server.use(
|
||||||
filter: (req, res) => {
|
// compression({
|
||||||
if (req.headers["x-no-compression"]) {
|
// filter: (req, res) => {
|
||||||
return false;
|
// if (req.headers["x-no-compression"]) {
|
||||||
}
|
// return false;
|
||||||
return compression.filter(req, res);
|
// }
|
||||||
},
|
// return compression.filter(req, res);
|
||||||
})
|
// },
|
||||||
);
|
// })
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerEndpoints() {
|
private registerEndpoints() {
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "esnext",
|
||||||
"module": "commonjs",
|
"isolatedModules": true,
|
||||||
|
"noEmit": false,
|
||||||
|
"allowImportingTsExtensions": false,
|
||||||
|
"module": "nodenext",
|
||||||
|
"moduleResolution": "nodenext",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
@ -11,7 +15,14 @@
|
|||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules/"],
|
"exclude": [
|
||||||
"files": ["src/express.d.ts"],
|
"node_modules/",
|
||||||
"include": ["./src"]
|
"../node_modules/",
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"src/express.d.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"./src"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,36 +6,36 @@
|
|||||||
"@hibas123/theme": "^2.0.7",
|
"@hibas123/theme": "^2.0.7",
|
||||||
"@hibas123/utils": "^2.2.18",
|
"@hibas123/utils": "^2.2.18",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@rollup/plugin-commonjs": "^24.0.1",
|
"@rollup/plugin-commonjs": "^28.0.6",
|
||||||
"@rollup/plugin-html": "^1.0.3",
|
"@rollup/plugin-html": "^2.0.0",
|
||||||
"@rollup/plugin-image": "^3.0.3",
|
"@rollup/plugin-image": "^3.0.3",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.2",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
"@simplewebauthn/browser": "^7.2.0",
|
"@simplewebauthn/browser": "^13.2.0",
|
||||||
"@tsconfig/svelte": "^4.0.1",
|
"@tsconfig/svelte": "^5.0.5",
|
||||||
"@types/cleave.js": "^1.4.7",
|
"@types/cleave.js": "^1.4.12",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.21",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.5.1",
|
||||||
"cleave.js": "^1.6.0",
|
"cleave.js": "^1.6.0",
|
||||||
"cssnano": "^6.0.1",
|
"cssnano": "^7.1.1",
|
||||||
"esbuild": "^0.17.16",
|
"esbuild": "^0.25.9",
|
||||||
"flowbite": "^1.6.5",
|
"flowbite": "^3.1.2",
|
||||||
"flowbite-svelte": "^0.34.9",
|
"flowbite-svelte": "^1.13.8",
|
||||||
"joi": "^17.11.0",
|
"joi": "^18.0.1",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.5.6",
|
||||||
"postcss-import": "^15.1.0",
|
"postcss-import": "^16.1.1",
|
||||||
"postcss-url": "^10.1.3",
|
"postcss-url": "^10.1.3",
|
||||||
"rollup": "^3.20.2",
|
"rollup": "^4.50.2",
|
||||||
"rollup-plugin-esbuild": "^5.0.0",
|
"rollup-plugin-esbuild": "^6.2.1",
|
||||||
"rollup-plugin-hash": "^1.3.0",
|
"rollup-plugin-hash": "^1.3.0",
|
||||||
"rollup-plugin-livereload": "^2.0.5",
|
"rollup-plugin-livereload": "^2.0.5",
|
||||||
"rollup-plugin-postcss": "^4.0.2",
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
"rollup-plugin-sizes": "^1.0.6",
|
"rollup-plugin-sizes": "^1.1.0",
|
||||||
"rollup-plugin-svelte": "^7.1.4",
|
"rollup-plugin-svelte": "^7.2.3",
|
||||||
"rollup-plugin-visualizer": "^5.9.0",
|
"rollup-plugin-visualizer": "^6.0.3",
|
||||||
"svelte": "^3.58.0",
|
"svelte": "^5.38.10",
|
||||||
"svelte-preprocess": "^5.0.3",
|
"svelte-preprocess": "^6.0.3",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^4.1.13",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.9.2",
|
||||||
"what-the-pack": "^2.0.3"
|
"what-the-pack": "^2.0.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -8,21 +8,21 @@
|
|||||||
"watch": "node build.js watch"
|
"watch": "node build.js watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"handlebars": "^4.7.7"
|
"handlebars": "^4.7.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@material/button": "^5.1.0",
|
"@material/button": "^14.0.0",
|
||||||
"@material/form-field": "^5.1.0",
|
"@material/form-field": "^14.0.0",
|
||||||
"@material/radio": "^5.1.0",
|
"@material/radio": "^14.0.0",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^4.0.3",
|
||||||
"gzip-size": "^6.0.0",
|
"gzip-size": "^7.0.0",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"preact": "^10.13.2",
|
"preact": "^10.27.2",
|
||||||
"rollup": "^3.20.2",
|
"rollup": "^4.50.2",
|
||||||
"rollup-plugin-includepaths": "^0.2.4",
|
"rollup-plugin-includepaths": "^0.2.4",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
"rollup-plugin-typescript2": "^0.36.0",
|
||||||
"sass": "^1.61.0",
|
"sass": "^1.92.1",
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@
|
|||||||
"author": "Fabian Stamm <Fabian.Stamm@polizei.hessen.de>",
|
"author": "Fabian Stamm <Fabian.Stamm@polizei.hessen.de>",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"outDir": "esm/",
|
"outDir": "esm/",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"preserveWatchOutput": true
|
"preserveWatchOutput": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules",
|
||||||
],
|
"../node_modules"
|
||||||
"include": [
|
],
|
||||||
"src"
|
"include": [
|
||||||
]
|
"src"
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"outDir": "lib/",
|
"outDir": "lib/",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"preserveWatchOutput": true
|
"preserveWatchOutput": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules",
|
||||||
],
|
"../node_modules"
|
||||||
"include": [
|
],
|
||||||
"src"
|
"include": [
|
||||||
]
|
"src"
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
@ -18,6 +18,6 @@
|
|||||||
"_API"
|
"_API"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hibas123/jrpcgen": "^1.2.14"
|
"@hibas123/jrpcgen": "^1.2.20"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user