init
This commit is contained in:
parent
10dc3e5ffe
commit
ef35a8aa6c
26
.eslintrc.js
Normal file
26
.eslintrc.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
commonjs: true,
|
||||||
|
es2021: true,
|
||||||
|
},
|
||||||
|
extends: 'eslint:recommended',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 12,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
argsIgnorePattern: '^_',
|
||||||
|
varsIgnorePattern: '^_',
|
||||||
|
caughtErrorsIgnorePattern: '^_',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-useless-escape': 0,
|
||||||
|
'no-empty': ['warn'],
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
process: true,
|
||||||
|
},
|
||||||
|
}
|
3542
package-lock.json
generated
Normal file
3542
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
package.json
Normal file
37
package.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "manager-bh",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "commonjs",
|
||||||
|
"scripts": {
|
||||||
|
"eslint": "eslint .",
|
||||||
|
"start": "cross-env NODE_ENV=\"development\" nodemon ./server/index.js",
|
||||||
|
"start:prod": "cross-env NODE_ENV=\"production\" nodemon ./server/index.js",
|
||||||
|
"up:prod": "cross-env NODE_ENV=\"production\" node ./server/index.js",
|
||||||
|
"deploy:d:stop": "docker compose down",
|
||||||
|
"deploy:d:build": "docker compose build",
|
||||||
|
"deploy:d:up": "docker compose up -d",
|
||||||
|
"redeploy": "npm run deploy:d:build && npm run deploy:d:stop && npm run deploy:d:up"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.17.6",
|
||||||
|
"eslint": "^7.30.0",
|
||||||
|
"nodemon": "^2.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@brojs/mailer": "^1.4.0-alpha.0",
|
||||||
|
"@keycloak/keycloak-admin-client": "^26.0.5",
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^5.0.1",
|
||||||
|
"express-session": "^1.18.1",
|
||||||
|
"js-sha256": "^0.11.0",
|
||||||
|
"keycloak-connect": "^26.0.5",
|
||||||
|
"uuid": "^11.0.2"
|
||||||
|
}
|
||||||
|
}
|
27
postman/manager.postman_collection.json
Normal file
27
postman/manager.postman_collection.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "64d9b604-a7c8-46b3-bd31-8249649ec269",
|
||||||
|
"name": "manager",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
|
"_exporter_id": "26924638"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "healthcheck",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{host}}/healthcheck",
|
||||||
|
"host": [
|
||||||
|
"{{host}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"healthcheck"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
8
server/.serverrc.js
Normal file
8
server/.serverrc.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
dataPath: path.resolve(__dirname, 'data'),
|
||||||
|
maxLogCount: 3,
|
||||||
|
mailStepTimer: 3000,
|
||||||
|
protocol: 'http',
|
||||||
|
}
|
40
server/_helpers/authorize.js
Normal file
40
server/_helpers/authorize.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const assignParam = (dev, prod) =>
|
||||||
|
process.env.NODE_ENV !== 'production' ? dev : prod
|
||||||
|
|
||||||
|
const parseToken = (req, res, next) => {
|
||||||
|
req.isAdmin = assignParam(
|
||||||
|
true,
|
||||||
|
Boolean(
|
||||||
|
req?.kauth?.grant?.access_token?.content?.resource_access?.[
|
||||||
|
'manager-admin'
|
||||||
|
]?.roles?.includes('manager_admin'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
req.userId = assignParam(
|
||||||
|
process.env['KC.DEV.ID'],
|
||||||
|
req.kauth?.grant?.access_token?.content?.sub,
|
||||||
|
)
|
||||||
|
req.user = assignParam(
|
||||||
|
{ sub: '123', name: 'dev' },
|
||||||
|
req.kauth?.grant?.access_token?.content,
|
||||||
|
)
|
||||||
|
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
const adminOnly = [
|
||||||
|
parseToken,
|
||||||
|
(req, res, next) => {
|
||||||
|
if (!req.isAdmin) {
|
||||||
|
// user's role is not authorized
|
||||||
|
return res.status(403).send({ code: 4, error: 'Access denied' })
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
adminOnly,
|
||||||
|
parseToken,
|
||||||
|
}
|
18
server/_helpers/error-handler.js
Normal file
18
server/_helpers/error-handler.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const { getAnswer } = require('../utils/common');
|
||||||
|
|
||||||
|
function errorHandler(err, req, res, _next) {
|
||||||
|
console.error(err);
|
||||||
|
if (typeof (err) === 'string') {
|
||||||
|
return res.status(400).json(getAnswer([{ message: err }]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err.name === 'UnauthorizedError') {
|
||||||
|
// jwt authentication error
|
||||||
|
return res.status(401).json(getAnswer([{ message: 'Invalid Token' }]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// default to 500 server error
|
||||||
|
return res.status(500).json(getAnswer([{ message: err?.message || 'Invalid Token' }]));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = errorHandler;
|
36
server/index.js
Normal file
36
server/index.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const bodyParser = require("body-parser");
|
||||||
|
const cookieParser = require("cookie-parser");
|
||||||
|
const session = require("express-session");
|
||||||
|
const app = express();
|
||||||
|
require("dotenv").config();
|
||||||
|
require("./mailer");
|
||||||
|
|
||||||
|
const errorHandler = require("./_helpers/error-handler");
|
||||||
|
|
||||||
|
const { keycloak } = require("./kc");
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
process.env.NODE_ENV !== "production"
|
||||||
|
? (_, __, next) => next()
|
||||||
|
: keycloak.middleware()
|
||||||
|
);
|
||||||
|
|
||||||
|
app.use(cookieParser());
|
||||||
|
app.use(
|
||||||
|
session({ secret: "so secret", resave: true, saveUninitialized: true })
|
||||||
|
);
|
||||||
|
|
||||||
|
app.use('/api', require('./routes'));
|
||||||
|
|
||||||
|
|
||||||
|
app.use(bodyParser.json({ limit: "50mb" }));
|
||||||
|
app.use(bodyParser.urlencoded({ limit: "50mb", extended: true }));
|
||||||
|
|
||||||
|
app.use(errorHandler);
|
||||||
|
|
||||||
|
app.listen(process.env.MANAGER_PORT, () =>
|
||||||
|
console.log(`Listening on http://localhost:${process.env.MANAGER_PORT}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = app;
|
39
server/kc.js
Normal file
39
server/kc.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
const Keycloak = require("keycloak-connect");
|
||||||
|
|
||||||
|
const keycloak = new Keycloak(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
clientId: "microfrontend-admin",
|
||||||
|
bearerOnly: true,
|
||||||
|
serverUrl: "https://kc.bro-js.ru",
|
||||||
|
realm: "bro-js",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const kcAdminClientPromise = import("@keycloak/keycloak-admin-client")
|
||||||
|
.then(
|
||||||
|
async ({ default: KcAdminClient }) =>
|
||||||
|
new KcAdminClient({
|
||||||
|
baseUrl: "https://kc.bro-js.ru",
|
||||||
|
realmName: "bro-js",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(async (kcAdminClient) => {
|
||||||
|
const credentials = {
|
||||||
|
username: process.env['KC.TUZ.USERNAME'],
|
||||||
|
password: process.env['KC.TUZ.PASSWORD'],
|
||||||
|
grant_type: "password",
|
||||||
|
grantType: "password",
|
||||||
|
clientId: "microfrontend-admin",
|
||||||
|
}
|
||||||
|
await kcAdminClient.auth(credentials);
|
||||||
|
|
||||||
|
setInterval(() => kcAdminClient.auth(credentials), 3 * 24 * 60 *60 * 1000);
|
||||||
|
|
||||||
|
return kcAdminClient;
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
keycloak,
|
||||||
|
kcAdminClientPromise,
|
||||||
|
}
|
16
server/mailer.js
Normal file
16
server/mailer.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const { AdminNotificationRequest, addToQueue, configs, init } = require('@brojs/mailer');
|
||||||
|
|
||||||
|
const rc = require('./.serverrc');
|
||||||
|
const pkg = require('../package');
|
||||||
|
|
||||||
|
init({
|
||||||
|
userName: process.env.SMTP_MAIL_LOGIN,
|
||||||
|
password: process.env.SMTP_MAIL_PASSWORD,
|
||||||
|
adminMails: process.env.MAIL_TO_1,
|
||||||
|
smtpConfig: configs.yandex,
|
||||||
|
queTimer: rc.mailStepTimer,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (process.env.MAIL_TO_1 && process.env.NODE_ENV === 'production') {
|
||||||
|
addToQueue(new AdminNotificationRequest(`Деплой kc админки v${pkg.version} прошёл успешно (${process.env.ADMIN_FRONT_BASE_NAME}) (Время ${new Date().toLocaleString()})`));
|
||||||
|
}
|
8
server/routes/index.js
Normal file
8
server/routes/index.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const router = require('express').Router();
|
||||||
|
const pkg = require('../../package.json')
|
||||||
|
|
||||||
|
router.get('/healthcheck', (req, res) => {
|
||||||
|
res.send({ ok: true, version: pkg.version })
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router;
|
22
server/utils/common.js
Normal file
22
server/utils/common.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const getAnswer = (error, body = null, success = true) => {
|
||||||
|
if (error) {
|
||||||
|
return { success: false, error, body }
|
||||||
|
} else {
|
||||||
|
return { success, body }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanId(entity) {
|
||||||
|
if (Array.isArray(entity)) {
|
||||||
|
return entity.map(cleanId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { _id, ...other } = entity;
|
||||||
|
|
||||||
|
return { ...other, id: _id };
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getAnswer,
|
||||||
|
cleanId,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user