Wrote test for /retropilot/0/useradmin
Converted a few more routes to return json New config option: flag: { useUserAdminApi: BOOLEAN } this will load the userAdminApi routes into the express app.pull/4/head
parent
6028036aa4
commit
2ec6e7650f
|
@ -20,8 +20,6 @@ var config = {
|
|||
smtpPassword: "",
|
||||
smtpFrom: "no-reply@retropilot.org",
|
||||
|
||||
SENDGRID_API_KEY: '',
|
||||
|
||||
baseUrl: 'http://192.168.1.165:3000/', // base url of the retropilot server
|
||||
baseUploadUrl: 'http://192.168.1.165:3000/backend/post_upload', // base url sent to devices for POSTing drives & logs
|
||||
|
||||
|
@ -35,7 +33,11 @@ var config = {
|
|||
deviceDriveExpirationDays: 30,
|
||||
|
||||
|
||||
welcomeMessage: `<><><><><><><><><><><><><><><><><><><><><><><br>2021 RetroPilot`
|
||||
welcomeMessage: `<><><><><><><><><><><><><><><><><><><><><><><br>2021 RetroPilot`,
|
||||
|
||||
flags: {
|
||||
useUserAdminApi: false,
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@commaai/log_reader": "^0.8.0",
|
||||
"@sendgrid/client": "^7.4.3",
|
||||
"chai": "^4.3.4",
|
||||
"chai-http": "^4.3.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
const router = require('express').Router();
|
||||
const bodyParser = require('body-parser');
|
||||
const crypto = require('crypto');
|
||||
const htmlspecialchars = require('htmlspecialchars');
|
||||
const dirTree = require("directory-tree");
|
||||
const cookieParser = require('cookie-parser');
|
||||
const config = require('./../config');
|
||||
|
||||
|
@ -23,7 +21,7 @@ let controllers;
|
|||
let logger;
|
||||
|
||||
|
||||
router.post('/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
router.post('/retropilot/0/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
const account = await models.__db.get('SELECT * FROM accounts WHERE email = ? AND password = ?', req.body.email, crypto.createHash('sha256').update(req.body.password + config.applicationSalt).digest('hex'));
|
||||
|
||||
if (!account || account.banned) {
|
||||
|
@ -34,13 +32,13 @@ router.post('/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsync
|
|||
}))
|
||||
|
||||
|
||||
router.get('/useradmin/signout', runAsyncWrapper(async (req, res) => {
|
||||
router.get('/retropilot/0/useradmin/signout', runAsyncWrapper(async (req, res) => {
|
||||
res.clearCookie('session');
|
||||
return res.json({success: true});
|
||||
}))
|
||||
|
||||
|
||||
router.get('/useradmin', runAsyncWrapper(async (req, res) => {
|
||||
router.get('/retropilot/0/useradmin', runAsyncWrapper(async (req, res) => {
|
||||
const accounts = await models.__db.get('SELECT COUNT(*) AS num FROM accounts');
|
||||
const devices = await models.__db.get('SELECT COUNT(*) AS num FROM devices');
|
||||
const drives = await models.__db.get('SELECT COUNT(*) AS num FROM drives');
|
||||
|
@ -98,18 +96,12 @@ router.get('/retropilot/0/register/verify/:token', bodyParser.urlencoded({extend
|
|||
return res.json({success: false, msg: 'contact server admin'}).status(500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}));
|
||||
|
||||
/*
|
||||
router.post('/useradmin/register/token', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
|
||||
|
||||
const email = req.body.email;
|
||||
|
||||
|
||||
if (!config.allowAccountRegistration) {
|
||||
res.send('Unauthorized.').status(401);
|
||||
return;
|
||||
|
@ -205,63 +197,41 @@ router.get('/useradmin/register', runAsyncWrapper(async (req, res) => {
|
|||
<input type="submit" value="Verify Email">
|
||||
</html>`);
|
||||
}))
|
||||
*/
|
||||
|
||||
|
||||
router.get('/useradmin/overview', runAsyncWrapper(async (req, res) => {
|
||||
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
router.get('/retropilot/0/overview', runAsyncWrapper(async (req, res) => {
|
||||
let account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
if (account == null) {
|
||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||
res.send({success: false, data: {session: false}})
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const devices = await models.__db.all('SELECT * FROM devices WHERE account_id = ? ORDER BY dongle_id ASC', account.id)
|
||||
|
||||
var response = '<html style="font-family: monospace"><h2>Welcome To The RetroPilot Server Dashboard!</h2>' +
|
||||
|
||||
`<br><br><h3>Account Overview</h3>
|
||||
<b>Account:</b> #` + account.id + `<br>
|
||||
<b>Email:</b> ` + account.email + `<br>
|
||||
<b>Created:</b> ` + controllers.helpers.formatDate(account.created) + `<br><br>
|
||||
<b>Devices:</b><br>
|
||||
<table border=1 cellpadding=2 cellspacing=2>
|
||||
<tr><th>dongle_id</th><th>device_type</th><th>created</th><th>last_ping</th><th>storage_used</th></tr>
|
||||
`;
|
||||
|
||||
for (var i in devices) {
|
||||
response += '<tr><td><a href="/useradmin/device/' + devices[i].dongle_id + '">' + devices[i].dongle_id + '</a></td><td>' + devices[i].device_type + '</td><td>' + controllers.helpers.formatDate(devices[i].created) + '</td><td>' + controllers.helpers.formatDate(devices[i].last_ping) + '</td><td>' + devices[i].storage_used + ' MB</td></tr>';
|
||||
}
|
||||
response += `</table>
|
||||
<br>
|
||||
<hr/>
|
||||
<h3>Pair New Devices</h3>
|
||||
<i>* To pair a new device, first have it auto-register on this server.<br>Then scan the QR Code and paste the Device Token below.</i><br>
|
||||
` + (req.query.linkstatus !== undefined ? '<br><u>' + htmlspecialchars(req.query.linkstatus) + '</u><br><br>' : '') + `
|
||||
<form action="/useradmin/pair_device" method="POST">
|
||||
<input type="text" name="qr_string" placeholder="QR Code Device Token" required>
|
||||
<input type="submit" value="Pair">
|
||||
</form><br><br>
|
||||
<hr/>
|
||||
<a href="/useradmin/signout">Sign Out</a>`;
|
||||
|
||||
res.status(200);
|
||||
res.send(response);
|
||||
// TODO implement a _safe_ get account for these use cases to allow for data to be stripped prior to sending to the client.
|
||||
delete(account.email_verify_token);
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
account: account,
|
||||
devices: devices,
|
||||
}
|
||||
|
||||
}).status(200)
|
||||
}))
|
||||
|
||||
|
||||
router.get('/useradmin/unpair_device/:dongleId', runAsyncWrapper(async (req, res) => {
|
||||
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
if (account == null) {
|
||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||
return;
|
||||
return res.json({success: false, data: {session: false}}).status(403)
|
||||
}
|
||||
|
||||
const device = await models.__db.get('SELECT * FROM devices WHERE account_id = ? AND dongle_id = ?', account.id, req.params.dongleId);
|
||||
|
||||
if (device == null) {
|
||||
res.status(400);
|
||||
res.send('Unauthorized.');
|
||||
return;
|
||||
return res.json({success: false}).status(400);
|
||||
}
|
||||
|
||||
const result = await models.__db.run(
|
||||
|
@ -270,9 +240,10 @@ router.get('/useradmin/unpair_device/:dongleId', runAsyncWrapper(async (req, res
|
|||
req.params.dongleId
|
||||
);
|
||||
|
||||
res.redirect('/useradmin/overview');
|
||||
})),
|
||||
res.json({success: true, data: {unlink: true}})
|
||||
}))
|
||||
|
||||
/*
|
||||
|
||||
router.post('/useradmin/pair_device', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
|
@ -571,7 +542,7 @@ router.get('/useradmin/drive/:dongleId/:driveIdentifier', runAsyncWrapper(async
|
|||
res.send(response);
|
||||
|
||||
}))
|
||||
|
||||
*/
|
||||
|
||||
module.exports = (_models, _controllers, _logger) => {
|
||||
models = _models;
|
||||
|
|
|
@ -53,7 +53,9 @@ const web = async () => {
|
|||
routers = routers(models, controllers, logger)
|
||||
app.use(routers.api);
|
||||
app.use(routers.useradmin);
|
||||
app.use(routers.useradminapi);
|
||||
|
||||
if (config.flags.useUserAdminApi) app.use(routers.useradminapi);
|
||||
|
||||
|
||||
app.use(cors());
|
||||
app.use(cookieParser(config.applicationSalt))
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
const request = require('supertest');
|
||||
const dummyGenerator = require('./../dummyGenerator');
|
||||
let app;
|
||||
|
||||
|
||||
|
||||
module.exports = (server) => {
|
||||
app = server;
|
||||
|
||||
describe('/api', function() {
|
||||
it('Load general server stats', function (done) {
|
||||
request(server)
|
||||
.get('/retropilot/0/useradmin')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.expect((req) => {
|
||||
const body = req.body;
|
||||
|
||||
try {
|
||||
if (
|
||||
body.hasOwnProperty('success') && body.success === true &&
|
||||
body.hasOwnProperty('data') &&
|
||||
body.data.hasOwnProperty('serverStats') &&
|
||||
body.data.serverStats.hasOwnProperty('config') &&
|
||||
typeof body.data.serverStats.config.registerAllowed === "boolean" &&
|
||||
typeof body.data.serverStats.config.welcomeMessage === "string" &&
|
||||
typeof body.data.serverStats['accounts'] === "number" &&
|
||||
typeof body.data.serverStats['devices'] === "number" &&
|
||||
typeof body.data.serverStats['drives'] === "number" &&
|
||||
(typeof body.data.serverStats['storageUsed'] === "number" || body.data.serverStats['storageUsed'] === "Unsupported Platform"))
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
throw new Error('Invalid returned parameters in GET /retropilot/0/useradmin')
|
||||
}
|
||||
} catch (exception) {
|
||||
throw new Error('Invalid returned parameters in GET /retropilot/0/useradmin ')
|
||||
}
|
||||
})
|
||||
.end(done)
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
var server = require('./../server')
|
||||
const config = require('./../config');
|
||||
var request = require('supertest');
|
||||
|
||||
// TODO better way to only run tests once server is up
|
||||
|
@ -19,4 +20,5 @@ describe('loading express', function () {
|
|||
|
||||
|
||||
require('./routes/api.test')(server);
|
||||
require('./routes/useradmin.test')(server);
|
||||
require('./routes/useradmin.test')(server);
|
||||
if (config.flags.useUserAdminApi) require('./routes/userAdminApi.test')(server);
|
Loading…
Reference in New Issue