Further admin preparations
Improved exception handling in async functions
This commit is contained in:
parent
a07c9a3ef7
commit
8b9ed0e666
|
@ -3,4 +3,5 @@ data
|
||||||
custom/*.js
|
custom/*.js
|
||||||
public/dist
|
public/dist
|
||||||
config.js
|
config.js
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
/npm-debug.log
|
87
index.js
87
index.js
|
@ -16,69 +16,62 @@ const webpackDevMiddleware = require('webpack-dev-middleware');
|
||||||
const webpackHotMiddleware = require('webpack-hot-middleware');
|
const webpackHotMiddleware = require('webpack-hot-middleware');
|
||||||
const webpackConfig = require('./webpack.config.js');
|
const webpackConfig = require('./webpack.config.js');
|
||||||
|
|
||||||
|
(async () =>
|
||||||
(async function()
|
|
||||||
{
|
{
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
try
|
||||||
|
{
|
||||||
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
const repository = new Repository(config.database);
|
const repository = new Repository(config.database);
|
||||||
await repository.load()
|
await repository.load();
|
||||||
.catch((err) =>
|
|
||||||
{
|
const tusServer = new tus.Server();
|
||||||
console.log(err);
|
tusServer.datastore = new tus.FileStore({
|
||||||
|
path: config.fileUpload.url,
|
||||||
|
directory: config.fileUpload.path
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
const tusServer = new tus.Server();
|
app.disable('x-powered-by');
|
||||||
tusServer.datastore = new tus.FileStore({
|
|
||||||
path: config.fileUpload.url,
|
|
||||||
directory: config.fileUpload.path
|
|
||||||
});
|
|
||||||
|
|
||||||
const app = express();
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
|
||||||
app.use(bodyParser.json());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const registerAPI = (name) => { require('./lib/api/' + name)(app, repository) }
|
const loadAPI = (route, name) => { app.use(route, require('./lib/api/' + name)(repository)) }
|
||||||
|
|
||||||
fs.readdir('./lib/api', (err, files) =>
|
loadAPI('/', 'upload');
|
||||||
{
|
loadAPI('/token', 'token');
|
||||||
if (err)
|
loadAPI('/admin', 'admin');
|
||||||
|
|
||||||
|
|
||||||
|
// Frontend
|
||||||
|
if (isDevelopment)
|
||||||
{
|
{
|
||||||
console.log(err);
|
const compiler = webpack(webpackConfig);
|
||||||
return;
|
|
||||||
|
app.use(webpackDevMiddleware(compiler, {
|
||||||
|
publicPath: webpackConfig.output.publicPath
|
||||||
|
}));
|
||||||
|
|
||||||
|
app.use(webpackHotMiddleware(compiler));
|
||||||
}
|
}
|
||||||
|
|
||||||
_.forEach(files, (fileName) =>
|
app.use(express.static(path.join(__dirname, 'public', 'dist')));
|
||||||
{
|
|
||||||
console.log('Loading API ' + fileName + '...');
|
|
||||||
registerAPI(fileName);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Frontend
|
// Redirects to make Vue-router URLs less quirky
|
||||||
if (isDevelopment)
|
app.get('/c/:code', (req, res) => { res.redirect(301, '/#/c/' + req.params.code) });
|
||||||
{
|
app.get('/admin', (req, res) => { res.redirect(301, '/#/admin/') });
|
||||||
const compiler = webpack(webpackConfig);
|
|
||||||
|
|
||||||
app.use(webpackDevMiddleware(compiler, {
|
|
||||||
publicPath: webpackConfig.output.publicPath
|
|
||||||
}));
|
|
||||||
|
|
||||||
app.use(webpackHotMiddleware(compiler));
|
var server = app.listen(config.port, () => console.log('Recv running on port ' + server.address().port));
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(express.static(path.join(__dirname, 'public', 'dist')));
|
|
||||||
|
|
||||||
|
|
||||||
// Redirects to make Vue-router URLs less quirky
|
|
||||||
app.get('/c/:code', (req, res) => { res.redirect(301, '/#/c/' + req.params.code) });
|
|
||||||
app.get('/admin', (req, res) => { res.redirect(301, '/#/admin/') });
|
|
||||||
|
|
||||||
|
|
||||||
var server = app.listen(config.port, () => console.log('Recv running on port ' + server.address().port));
|
|
||||||
})();
|
})();
|
|
@ -0,0 +1,54 @@
|
||||||
|
const config = require('../../config');
|
||||||
|
const express = require('Express');
|
||||||
|
const asyncHandler = require('express-async-handler');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
|
||||||
|
async function checkAuthorization(req, res, onVerified)
|
||||||
|
{
|
||||||
|
if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer')
|
||||||
|
{
|
||||||
|
res.sendStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = req.headers.authorization.split(' ')[1];
|
||||||
|
jwt.verify(token, config.jwtSecret, async (err, decoded) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
res.sendStatus(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoded.userId)
|
||||||
|
await onVerified(decoded);
|
||||||
|
else
|
||||||
|
res.sendStatus(400);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
res.sendStatus(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (repository) =>
|
||||||
|
{
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.get('/codes', asyncHandler(async (req, res) =>
|
||||||
|
{
|
||||||
|
await checkAuthorization(req, res, async (decoded) =>
|
||||||
|
{
|
||||||
|
res.send(await repository.codes.getCodes(decoded.userId));
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
|
const express = require('Express');
|
||||||
|
const asyncHandler = require('express-async-handler');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
|
||||||
module.exports = (app, repository) =>
|
module.exports = (repository) =>
|
||||||
{
|
{
|
||||||
app.post('/token/upload', async (req, res) =>
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.post('/upload', asyncHandler(async (req, res) =>
|
||||||
{
|
{
|
||||||
if (!req.body.code)
|
if (!req.body.code)
|
||||||
{
|
{
|
||||||
|
@ -17,7 +21,7 @@ module.exports = (app, repository) =>
|
||||||
{
|
{
|
||||||
jwt.sign({
|
jwt.sign({
|
||||||
code: req.body.code,
|
code: req.body.code,
|
||||||
userId: userId
|
codeUserId: userId
|
||||||
}, config.jwtSecret, (err, token) =>
|
}, config.jwtSecret, (err, token) =>
|
||||||
{
|
{
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -28,5 +32,33 @@ module.exports = (app, repository) =>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res.sendStatus(403);
|
res.sendStatus(403);
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
router.post('/login', asyncHandler(async (req, res) =>
|
||||||
|
{
|
||||||
|
if (!req.body.username || !req.body.password)
|
||||||
|
{
|
||||||
|
res.sendStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await repository.users.getLoginUser(req.body.username, req.body.password);
|
||||||
|
if (user !== null)
|
||||||
|
{
|
||||||
|
jwt.sign({
|
||||||
|
userId: user.id
|
||||||
|
}, config.jwtSecret, (err, token) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
res.sendStatus(500);
|
||||||
|
else
|
||||||
|
res.send(token);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res.sendStatus(403);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return router;
|
||||||
}
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
const config = require('../../config');
|
const config = require('../../config');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
const asyncHandler = require('express-async-handler');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
|
||||||
function checkAuthorization(req, res, onVerified)
|
async function checkAuthorization(req, res, onVerified)
|
||||||
{
|
{
|
||||||
if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer')
|
if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer')
|
||||||
{
|
{
|
||||||
|
@ -12,24 +13,37 @@ function checkAuthorization(req, res, onVerified)
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = req.headers.authorization.split(' ')[1];
|
var token = req.headers.authorization.split(' ')[1];
|
||||||
jwt.verify(token, config.jwtSecret, (err, decoded) =>
|
jwt.verify(token, config.jwtSecret, async (err, decoded) =>
|
||||||
{
|
{
|
||||||
if (err)
|
try
|
||||||
{
|
{
|
||||||
res.sendStatus(403);
|
if (err)
|
||||||
return;
|
{
|
||||||
}
|
res.sendStatus(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
onVerified(decoded);
|
if (decoded.codeUserId)
|
||||||
|
await onVerified(decoded);
|
||||||
|
else
|
||||||
|
res.sendStatus(400);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
res.sendStatus(500);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = (app, repository) =>
|
module.exports = (repository) =>
|
||||||
{
|
{
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
// Upload API
|
// Upload API
|
||||||
app.post('/complete', (req, res) =>
|
router.post('/complete', asyncHandler(async (req, res) =>
|
||||||
{
|
{
|
||||||
if (!req.body.files)
|
if (!req.body.files)
|
||||||
{
|
{
|
||||||
|
@ -37,24 +51,25 @@ module.exports = (app, repository) =>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAuthorization(req, res, async (decoded) =>
|
await checkAuthorization(req, res, async (decoded) =>
|
||||||
{
|
{
|
||||||
var expiration = null; // TODO set expiration properties
|
var expiration = null; // TODO set expiration properties
|
||||||
var uploadId = await repository.uploads.addUpload(decoded.userId, req.body.files, expiration);
|
var uploadId = await repository.uploads.addUpload(decoded.codeUserId, req.body.files, expiration);
|
||||||
res.send({ id: uploadId });
|
res.send({ id: uploadId });
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
|
||||||
// Tus upload
|
// Tus upload
|
||||||
const uploadApp = express();
|
const uploadApp = express();
|
||||||
uploadApp.all('*', (req, res) =>
|
uploadApp.all('*', asyncHandler(async (req, res) =>
|
||||||
{
|
{
|
||||||
checkAuthorization(req, res, (decoded) =>
|
await checkAuthorization(req, res, async (decoded) =>
|
||||||
{
|
{
|
||||||
tusServer.handle(req, res);
|
tusServer.handle(req, res);
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
app.use('/upload', uploadApp);
|
router.use('/upload', uploadApp);
|
||||||
|
return router;
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
const AuthTokens = {
|
||||||
|
ManageUsers: 'manageUsers'
|
||||||
|
}
|
||||||
|
|
||||||
|
var all = [];
|
||||||
|
for (var key in AuthTokens)
|
||||||
|
{
|
||||||
|
if (AuthTokens.hasOwnProperty(key))
|
||||||
|
all.push(AuthTokens[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthTokens.all = all;
|
||||||
|
module.exports = AuthTokens;
|
|
@ -1,4 +1,21 @@
|
||||||
class CodesRepository
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
|
||||||
|
class Code
|
||||||
|
{
|
||||||
|
constructor(values)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.id = values.id || values._id || null;
|
||||||
|
self.userId = values.userId || null;
|
||||||
|
self.created = values.created || new Date();
|
||||||
|
self.expiration = values.expiration || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CodeRepository
|
||||||
{
|
{
|
||||||
constructor(store)
|
constructor(store)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +24,7 @@ class CodesRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async init()
|
init()
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -31,7 +48,7 @@ class CodesRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async findCodeUserId(code)
|
findCodeUserId(code)
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -76,7 +93,28 @@ class CodesRepository
|
||||||
maxTimeout: 0
|
maxTimeout: 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getCodes(userId)
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
{
|
||||||
|
self.store.find({ userId: userId }, (err, docs) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(_.map(docs, (doc) => new Code(doc)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = CodesRepository;
|
module.exports = {
|
||||||
|
Code,
|
||||||
|
CodeRepository
|
||||||
|
}
|
|
@ -2,14 +2,13 @@
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const mkdirp = require('mkdirp');
|
const mkdirp = require('mkdirp');
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const Datastore = require('nedb');
|
const Datastore = require('nedb');
|
||||||
const shortid = require('shortid');
|
const shortid = require('shortid');
|
||||||
const retry = require('async-retry');
|
const retry = require('async-retry');
|
||||||
|
|
||||||
const UsersRepository = require('./users');
|
const UserRepository = require('./user').UserRepository;
|
||||||
const CodesRepository = require('./codes');
|
const CodeRepository = require('./code').CodeRepository;
|
||||||
const UploadsRepository = require('./uploads');
|
const UploadRepository = require('./upload').UploadRepository;
|
||||||
|
|
||||||
|
|
||||||
class Repository
|
class Repository
|
||||||
|
@ -21,7 +20,7 @@ class Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async load()
|
load()
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class Repository
|
||||||
return store;
|
return store;
|
||||||
};
|
};
|
||||||
|
|
||||||
mkdirp(self.config.path, async (err) =>
|
mkdirp(self.config.path, (err) =>
|
||||||
{
|
{
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -46,12 +45,13 @@ class Repository
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.users = new UsersRepository(initStore('users.db'));
|
self.users = new UserRepository(initStore('user.db'));
|
||||||
self.codes = new CodesRepository(initStore('codes.db'));
|
self.codes = new CodeRepository(initStore('code.db'));
|
||||||
self.uploads = new UploadsRepository(initStore('uploads.db'));
|
self.uploads = new UploadRepository(initStore('upload.db'));
|
||||||
|
|
||||||
await self.users.init();
|
self.users.init()
|
||||||
resolve();
|
.then(() => { resolve() })
|
||||||
|
.catch((e) => { reject(e); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class UploadsRepository
|
class UploadRepository
|
||||||
{
|
{
|
||||||
constructor(store)
|
constructor(store)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ class UploadsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async init()
|
init()
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class UploadsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async addUpload(userId, files, expiration)
|
addUpload(userId, files, expiration)
|
||||||
{
|
{
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -67,4 +67,6 @@ class UploadsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = UploadsRepository;
|
module.exports = {
|
||||||
|
UploadRepository
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
const AuthTokens = require('../authtokens');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
|
||||||
|
|
||||||
|
class User
|
||||||
|
{
|
||||||
|
constructor(values)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.id = values.id || values._id || null;
|
||||||
|
self.username = values.username || null;
|
||||||
|
self.password = values.password || null;
|
||||||
|
self.email = values.email || null;
|
||||||
|
self.auth = values.auth || [];
|
||||||
|
|
||||||
|
if (values.hasOwnProperty('active'))
|
||||||
|
self.active = (values.active === true);
|
||||||
|
else
|
||||||
|
self.active = true;
|
||||||
|
|
||||||
|
self.created = values.created || new Date();
|
||||||
|
self.createdByUserId = values.createdByUserId || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAuth(token)
|
||||||
|
{
|
||||||
|
return self.auth.includes(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UserRepository
|
||||||
|
{
|
||||||
|
constructor(store)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
self.store = store;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
{
|
||||||
|
// Initialize database if empty
|
||||||
|
self.store.count({}, (err, count) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
self.addUser(new User({
|
||||||
|
username: 'admin',
|
||||||
|
password: 'changeme',
|
||||||
|
auth: AuthTokens.all
|
||||||
|
}))
|
||||||
|
.then(() => { resolve() })
|
||||||
|
.catch((e) => { reject(e); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getLoginUser(username, password)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
{
|
||||||
|
self.store.findOne({ username: username, active: true }, (err, doc) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc == null)
|
||||||
|
{
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bcrypt.compare(password, doc.hashedPassword, (err, res) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
reject(err)
|
||||||
|
else
|
||||||
|
resolve(res ? new User(doc) : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addUser(user)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
{
|
||||||
|
bcrypt.hash(user.password, 10, function(err, hash)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.store.insert({
|
||||||
|
username: user.username,
|
||||||
|
email: user.email,
|
||||||
|
hashedPassword: hash,
|
||||||
|
created: user.created,
|
||||||
|
createdByUserId: user.createdByUserId,
|
||||||
|
active: user.active,
|
||||||
|
auth: user.auth
|
||||||
|
}, (err, dbUser) =>
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(dbUser._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
User,
|
||||||
|
UserRepository
|
||||||
|
}
|
|
@ -1,104 +0,0 @@
|
||||||
class UsersRepository
|
|
||||||
{
|
|
||||||
constructor(store)
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
self.store = store;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async init()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) =>
|
|
||||||
{
|
|
||||||
// Initialize database if empty
|
|
||||||
self.store.count({}, (err, count) =>
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
self.addUser('admin', null, 'test', null);
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async isValidUser(username, password)
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) =>
|
|
||||||
{
|
|
||||||
self.store.findOne({ username: username }, (err, doc) =>
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doc == null)
|
|
||||||
{
|
|
||||||
resolve(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcrypt.compare(password, doc.password, (err, res) =>
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
reject(err)
|
|
||||||
else
|
|
||||||
resolve(res);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async addUser(username, email, password, createdByUserId)
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) =>
|
|
||||||
{
|
|
||||||
bcrypt.hash(password, 10, function(err, hash)
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = {
|
|
||||||
username: username,
|
|
||||||
email: email,
|
|
||||||
password: hash,
|
|
||||||
created: new Date(),
|
|
||||||
createdByUserId: createdByUserId
|
|
||||||
};
|
|
||||||
|
|
||||||
self.store.insert(user, (err, dbUser) =>
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(dbUser._id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = UsersRepository;
|
|
|
@ -20,6 +20,7 @@
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"debug": "^3.1.0",
|
"debug": "^3.1.0",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
|
"express-async-handler": "^1.1.2",
|
||||||
"jsonwebtoken": "^8.1.1",
|
"jsonwebtoken": "^8.1.1",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
|
|
|
@ -1,10 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="login">
|
<div id="login">
|
||||||
Login.
|
<form class="pure-form pure-form-stacked" @submit.prevent="login">
|
||||||
|
<fieldset class="pure-group">
|
||||||
|
<input type="text" class="pure-input-1-2" v-model="username" :placeholder="$t('landing.invitePlaceholder')">
|
||||||
|
<input type="password" class="pure-input-1-2" v-model="password" :placeholder="$t('landing.invitePlaceholder')">
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button type="submit" class="pure-button pure-button-primary" :disabled="username.trim() == '' || password.trim() == '' || checking">{{ $t(checking ? 'landing.inviteButtonChecking' : 'landing.inviteButton') }} <span v-if="checking"><i class="fas fa-spinner fa-pulse"></i></span></button>
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
data: () =>
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
checking: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
login()
|
||||||
|
{
|
||||||
|
alert('TODO');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
Loading…
Reference in New Issue