mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
committed by
GitHub
parent
7d0ec72a0c
commit
2c5eceb0c1
@@ -1,44 +1,36 @@
|
||||
const { notificationAdapterRouter } = require('./routes/notificationAdapterRouter');
|
||||
const { authInterceptor, cookieSession, adminInterceptor } = require('./security');
|
||||
const { generalSettingsRouter } = require('./routes/generalSettingsRoute');
|
||||
const { analyticsRouter } = require('./routes/analyticsRouter');
|
||||
const { providerRouter } = require('./routes/providerRouter');
|
||||
const { loginRouter } = require('./routes/loginRoute');
|
||||
const config = require('../../conf/config.json');
|
||||
const { userRouter } = require('./routes/userRoute');
|
||||
const { jobRouter } = require('./routes/jobRouter');
|
||||
const bodyParser = require('body-parser');
|
||||
const service = require('restana')();
|
||||
const files = require('serve-static');
|
||||
const path = require('path');
|
||||
|
||||
const staticService = files(path.join(__dirname, '../../ui/public'));
|
||||
|
||||
import { notificationAdapterRouter } from './routes/notificationAdapterRouter.js';
|
||||
import { authInterceptor, cookieSession, adminInterceptor } from './security.js';
|
||||
import { generalSettingsRouter } from './routes/generalSettingsRoute.js';
|
||||
import { analyticsRouter } from './routes/analyticsRouter.js';
|
||||
import { providerRouter } from './routes/providerRouter.js';
|
||||
import { loginRouter } from './routes/loginRoute.js';
|
||||
import { config } from '../utils.js';
|
||||
import { userRouter } from './routes/userRoute.js';
|
||||
import { jobRouter } from './routes/jobRouter.js';
|
||||
import bodyParser from 'body-parser';
|
||||
import restana from 'restana';
|
||||
import files from 'serve-static';
|
||||
import path from 'path';
|
||||
import { getDirName } from '../utils.js';
|
||||
const service = restana();
|
||||
const staticService = files(path.join(getDirName(), '../../ui/public'));
|
||||
const PORT = config.port || 9998;
|
||||
|
||||
service.use(bodyParser.json());
|
||||
|
||||
service.use(cookieSession());
|
||||
|
||||
service.use(staticService);
|
||||
|
||||
service.use('/api/admin', authInterceptor());
|
||||
service.use('/api/jobs', authInterceptor());
|
||||
|
||||
// /admin can only be accessed when user is having admin permissions
|
||||
service.use('/api/admin', adminInterceptor());
|
||||
|
||||
service.use('/api/jobs/notificationAdapter', notificationAdapterRouter);
|
||||
service.use('/api/admin/generalSettings', generalSettingsRouter);
|
||||
service.use('/api/jobs/provider', providerRouter);
|
||||
service.use('/api/jobs/insights', analyticsRouter);
|
||||
service.use('/api/admin/users', userRouter);
|
||||
service.use('/api/jobs', jobRouter);
|
||||
|
||||
service.use('/api/login', loginRouter);
|
||||
|
||||
/* eslint-disable no-console */
|
||||
service.start(PORT).then(() => {
|
||||
console.info(`Started API service on port ${PORT}`);
|
||||
});
|
||||
/* eslint-enable no-console */
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
const service = require('restana')();
|
||||
import restana from 'restana';
|
||||
import * as listingStorage from '../../services/storage/listingsStorage.js';
|
||||
const service = restana();
|
||||
const analyticsRouter = service.newRouter();
|
||||
const listingStorage = require('../../services/storage/listingsStorage');
|
||||
|
||||
analyticsRouter.get('/:jobId', async (req, res) => {
|
||||
const { jobId } = req.params;
|
||||
|
||||
res.body = listingStorage.getListingProviderDataForAnalytics(jobId) || {};
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.analyticsRouter = analyticsRouter;
|
||||
export { analyticsRouter };
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
const service = require('restana')();
|
||||
import restana from 'restana';
|
||||
import { config, getDirName } from '../../utils.js';
|
||||
import fs from 'fs';
|
||||
const service = restana();
|
||||
const generalSettingsRouter = service.newRouter();
|
||||
const config = require('../../../conf/config.json');
|
||||
const fs = require('fs');
|
||||
|
||||
generalSettingsRouter.get('/', async (req, res) => {
|
||||
res.body = Object.assign({}, config);
|
||||
res.send();
|
||||
});
|
||||
|
||||
generalSettingsRouter.post('/', async (req, res) => {
|
||||
const settings = req.body;
|
||||
|
||||
try {
|
||||
fs.writeFileSync(`${__dirname}/../../../conf/config.json`, JSON.stringify(settings));
|
||||
fs.writeFileSync(`${getDirName()}/../conf/config.json`, JSON.stringify(settings));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.send(new Error('Error while trying to write settings.'));
|
||||
@@ -20,5 +18,4 @@ generalSettingsRouter.post('/', async (req, res) => {
|
||||
}
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.generalSettingsRouter = generalSettingsRouter;
|
||||
export { generalSettingsRouter };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const service = require('restana')();
|
||||
import restana from 'restana';
|
||||
import fetch from 'node-fetch';
|
||||
import * as jobStorage from '../../services/storage/jobStorage.js';
|
||||
import * as userStorage from '../../services/storage/userStorage.js';
|
||||
import * as immoscoutProvider from '../../provider/immoscout.js';
|
||||
import { config } from '../../utils.js';
|
||||
import { isAdmin } from '../security.js';
|
||||
const service = restana();
|
||||
const jobRouter = service.newRouter();
|
||||
const fetch = require('node-fetch');
|
||||
const jobStorage = require('../../services/storage/jobStorage');
|
||||
const userStorage = require('../../services/storage/userStorage');
|
||||
const immoscoutProvider = require('../../provider/immoscout');
|
||||
const config = require('../../../conf/config.json');
|
||||
const { isAdmin } = require('../security');
|
||||
|
||||
function doesJobBelongsToUser(job, req) {
|
||||
const userId = req.session.currentUser;
|
||||
if (userId == null) {
|
||||
@@ -16,22 +16,16 @@ function doesJobBelongsToUser(job, req) {
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return user.isAdmin || job.userId === job.userId;
|
||||
}
|
||||
|
||||
jobRouter.get('/', async (req, res) => {
|
||||
const isUserAdmin = isAdmin(req);
|
||||
|
||||
//show only the jobs which belongs to the user (or all of the user is an admin)
|
||||
res.body = jobStorage.getJobs().filter((job) => isUserAdmin || job.userId === req.session.currentUser);
|
||||
|
||||
res.send();
|
||||
});
|
||||
|
||||
jobRouter.get('/processingTimes', async (req, res) => {
|
||||
let scrapingAntData = null;
|
||||
|
||||
if (config.scrapingAnt.apiKey != null && config.scrapingAnt.apiKey.length > 0) {
|
||||
try {
|
||||
const response = await fetch(`https://api.scrapingant.com/v1/usage?x-api-key=${config.scrapingAnt.apiKey}`);
|
||||
@@ -40,16 +34,13 @@ jobRouter.get('/processingTimes', async (req, res) => {
|
||||
console.error('Could not query plan data from scraping ant.', Exception);
|
||||
}
|
||||
}
|
||||
|
||||
res.body = {
|
||||
interval: config.interval,
|
||||
lastRun: config.lastRun || null,
|
||||
scrapingAntData,
|
||||
};
|
||||
|
||||
res.send();
|
||||
});
|
||||
|
||||
jobRouter.post('/', async (req, res) => {
|
||||
const { provider, notificationAdapter, name, blacklist = [], jobId, enabled } = req.body;
|
||||
if (
|
||||
@@ -77,7 +68,6 @@ jobRouter.post('/', async (req, res) => {
|
||||
}
|
||||
res.send();
|
||||
});
|
||||
|
||||
jobRouter.delete('', async (req, res) => {
|
||||
const { jobId } = req.body;
|
||||
try {
|
||||
@@ -93,7 +83,6 @@ jobRouter.delete('', async (req, res) => {
|
||||
}
|
||||
res.send();
|
||||
});
|
||||
|
||||
jobRouter.put('/:jobId/status', async (req, res) => {
|
||||
const { status } = req.body;
|
||||
const { jobId } = req.params;
|
||||
@@ -113,5 +102,4 @@ jobRouter.put('/:jobId/status', async (req, res) => {
|
||||
}
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.jobRouter = jobRouter;
|
||||
export { jobRouter };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const service = require('restana')();
|
||||
import restana from 'restana';
|
||||
import * as userStorage from '../../services/storage/userStorage.js';
|
||||
import * as hasher from '../../services/security/hash.js';
|
||||
const service = restana();
|
||||
const loginRouter = service.newRouter();
|
||||
const userStorage = require('../../services/storage/userStorage');
|
||||
const hasher = require('../../services/security/hash');
|
||||
|
||||
loginRouter.get('/user', async (req, res) => {
|
||||
const currentUserId = req.session.currentUser;
|
||||
const currentUser = currentUserId == null ? null : userStorage.getUser(currentUserId);
|
||||
@@ -16,17 +16,13 @@ loginRouter.get('/user', async (req, res) => {
|
||||
}
|
||||
res.send();
|
||||
});
|
||||
|
||||
loginRouter.post('/', async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
|
||||
const user = userStorage.getUsers(true).find((user) => user.username === username);
|
||||
|
||||
if (user == null) {
|
||||
res.send(401);
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.password === hasher.hash(password)) {
|
||||
req.session.currentUser = user.id;
|
||||
userStorage.setLastLoginToNow({ userId: user.id });
|
||||
@@ -35,13 +31,10 @@ loginRouter.post('/', async (req, res) => {
|
||||
} else {
|
||||
console.error(`User ${username} tried to login, but password was wrong.`);
|
||||
}
|
||||
|
||||
res.send(401);
|
||||
});
|
||||
|
||||
loginRouter.post('/logout', async (req, res) => {
|
||||
req.session = null;
|
||||
res.send(200);
|
||||
});
|
||||
|
||||
exports.loginRouter = loginRouter;
|
||||
export { loginRouter };
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const fs = require('fs');
|
||||
const service = require('restana')();
|
||||
import fs from 'fs';
|
||||
import restana from 'restana';
|
||||
const service = restana();
|
||||
const notificationAdapterRouter = service.newRouter();
|
||||
|
||||
const notificationAdapterList = fs.readdirSync('./lib//notification/adapter').filter((file) => file.endsWith('.js'));
|
||||
|
||||
const notificationAdapter = notificationAdapterList.map((pro) => {
|
||||
return require(`../../notification/adapter/${pro}`);
|
||||
});
|
||||
|
||||
const notificationAdapter = await Promise.all(
|
||||
notificationAdapterList.map(async (pro) => {
|
||||
return await import(`../../notification/adapter/${pro}`);
|
||||
})
|
||||
);
|
||||
notificationAdapterRouter.post('/try', async (req, res) => {
|
||||
const { id, fields } = req.body;
|
||||
const adapter = notificationAdapter.find((adapter) => adapter.config.id === id);
|
||||
@@ -24,7 +24,6 @@ notificationAdapterRouter.post('/try', async (req, res) => {
|
||||
enabled: true,
|
||||
id,
|
||||
});
|
||||
|
||||
try {
|
||||
await adapter.send({
|
||||
serviceName: 'TestCall',
|
||||
@@ -40,16 +39,13 @@ notificationAdapterRouter.post('/try', async (req, res) => {
|
||||
notificationConfig,
|
||||
jobKey: 'TestJob',
|
||||
});
|
||||
|
||||
res.send();
|
||||
} catch (Exception) {
|
||||
res.send(new Error(Exception));
|
||||
}
|
||||
});
|
||||
|
||||
notificationAdapterRouter.get('/', async (req, res) => {
|
||||
res.body = notificationAdapter.map((adapter) => adapter.config);
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.notificationAdapterRouter = notificationAdapterRouter;
|
||||
export { notificationAdapterRouter };
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
const fs = require('fs');
|
||||
const service = require('restana')();
|
||||
import fs from 'fs';
|
||||
import restana from 'restana';
|
||||
const service = restana();
|
||||
const providerRouter = service.newRouter();
|
||||
|
||||
const providerList = fs.readdirSync('./lib/provider').filter((file) => file.endsWith('.js'));
|
||||
|
||||
const provider = providerList.map((pro) => {
|
||||
return require(`../../provider/${pro}`).metaInformation;
|
||||
});
|
||||
|
||||
const provider = await Promise.all(
|
||||
providerList.map(async (pro) => {
|
||||
return await import(`../../provider/${pro}`);
|
||||
})
|
||||
);
|
||||
providerRouter.get('/', async (req, res) => {
|
||||
res.body = provider;
|
||||
res.body = provider.map((p) => p.metaInformation);
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.providerRouter = providerRouter;
|
||||
export { providerRouter };
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
const service = require('restana')();
|
||||
import restana from 'restana';
|
||||
import * as userStorage from '../../services/storage/userStorage.js';
|
||||
import * as jobStorage from '../../services/storage/jobStorage.js';
|
||||
const service = restana();
|
||||
const userRouter = service.newRouter();
|
||||
const userStorage = require('../../services/storage/userStorage');
|
||||
const jobStorage = require('../../services/storage/jobStorage');
|
||||
|
||||
function checkIfAnyAdminAfterRemovingUser(userIdToBeRemoved, allUser) {
|
||||
return allUser.filter((user) => user.id !== userIdToBeRemoved && user.isAdmin).length > 0;
|
||||
}
|
||||
|
||||
function checkIfUserToBeRemovedIsLoggedIn(userIdToBeRemoved, req) {
|
||||
return req.session.currentUser === userIdToBeRemoved;
|
||||
}
|
||||
|
||||
const nullOrEmpty = (str) => str == null || str.length === 0;
|
||||
|
||||
userRouter.get('/', async (req, res) => {
|
||||
res.body = userStorage.getUsers(false);
|
||||
res.send();
|
||||
});
|
||||
|
||||
userRouter.get('/:userId', async (req, res) => {
|
||||
const { userId } = req.params;
|
||||
res.body = userStorage.getUser(userId);
|
||||
res.send();
|
||||
});
|
||||
|
||||
userRouter.delete('/', async (req, res) => {
|
||||
const { userId } = req.body;
|
||||
const allUser = userStorage.getUsers(false);
|
||||
|
||||
if (!checkIfAnyAdminAfterRemovingUser(userId, allUser)) {
|
||||
res.send(new Error('You are trying to remove the last admin user. This is prohibited.'));
|
||||
return;
|
||||
@@ -36,14 +30,11 @@ userRouter.delete('/', async (req, res) => {
|
||||
res.send(new Error('You are trying to remove yourself. This is prohibited.'));
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Remove also analytics
|
||||
jobStorage.removeJobsByUserId(userId);
|
||||
userStorage.removeUser(userId);
|
||||
|
||||
res.send();
|
||||
});
|
||||
|
||||
userRouter.post('/', async (req, res) => {
|
||||
const { username, password, password2, isAdmin, userId } = req.body;
|
||||
if (password !== password2) {
|
||||
@@ -55,22 +46,18 @@ userRouter.post('/', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
const allUser = userStorage.getUsers(false);
|
||||
|
||||
if (!isAdmin && !checkIfAnyAdminAfterRemovingUser(userId, allUser)) {
|
||||
res.send(
|
||||
new Error('You cannot change the admin flag for this user as otherwise, there is no other user in the system')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
userStorage.upsertUser({
|
||||
userId,
|
||||
username,
|
||||
password,
|
||||
isAdmin,
|
||||
});
|
||||
|
||||
res.send();
|
||||
});
|
||||
|
||||
exports.userRouter = userRouter;
|
||||
export { userRouter };
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
const userStorage = require('../services/storage/userStorage');
|
||||
const cookieSession = require('cookie-session');
|
||||
const { nanoid } = require('nanoid');
|
||||
|
||||
import * as userStorage from '../services/storage/userStorage.js';
|
||||
import cookieSession from 'cookie-session';
|
||||
import { nanoid } from 'nanoid';
|
||||
const unauthorized = (res) => {
|
||||
return res.send(401);
|
||||
};
|
||||
|
||||
const isUnauthorized = (req) => {
|
||||
return req.session.currentUser == null;
|
||||
};
|
||||
|
||||
const isAdmin = (req) => {
|
||||
if (!isUnauthorized(req)) {
|
||||
const user = userStorage.getUser(req.session.currentUser);
|
||||
@@ -17,7 +14,6 @@ const isAdmin = (req) => {
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const authInterceptor = () => {
|
||||
return (req, res, next) => {
|
||||
if (isUnauthorized(req)) {
|
||||
@@ -27,7 +23,6 @@ const authInterceptor = () => {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const adminInterceptor = () => {
|
||||
return (req, res, next) => {
|
||||
if (!isAdmin(req)) {
|
||||
@@ -37,8 +32,7 @@ const adminInterceptor = () => {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.cookieSession = (userId) => {
|
||||
const cookieSession$0 = (userId) => {
|
||||
return cookieSession({
|
||||
name: 'fredy-admin-session',
|
||||
keys: ['fredy', 'super', 'fancy', 'key', nanoid()],
|
||||
@@ -46,8 +40,8 @@ exports.cookieSession = (userId) => {
|
||||
maxAge: 8 * 60 * 60 * 1000, // 8 hours
|
||||
});
|
||||
};
|
||||
|
||||
exports.adminInterceptor = adminInterceptor;
|
||||
exports.authInterceptor = authInterceptor;
|
||||
exports.isUnauthorized = isUnauthorized;
|
||||
exports.isAdmin = isAdmin;
|
||||
export { cookieSession$0 as cookieSession };
|
||||
export { adminInterceptor };
|
||||
export { authInterceptor };
|
||||
export { isUnauthorized };
|
||||
export { isAdmin };
|
||||
|
||||
Reference in New Issue
Block a user