user managment

This commit is contained in:
2024-06-24 18:37:04 +02:00
parent bafef0f6b3
commit 0c7fc6fdf7
50 changed files with 2748 additions and 219 deletions
+23
View File
@@ -0,0 +1,23 @@
module.exports = {
db: {
connectionString: "mongodb://db:27017",
dbName: "jucundus",
},
session: {
sessionCollection: "Session",
sessionConfig: {
name: "jucundus.sid",
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
httpOnly: true, // only accessible by the server
secure: true,
},
resave: false, // don't save session if unmodified
saveUninitialized: true,
}
},
jwtOptions: {
issuer: "jucundus.com",
audience: "yoursite",
}
};
+64 -1
View File
@@ -38,7 +38,6 @@ exports.getPictures = asyncHandler(async (req, res, next) => {
});
});
exports.getLotsBySale = asyncHandler(async (req, res, next) => {
let id = req.params.id
@@ -165,3 +164,67 @@ exports.AuctionedItem = asyncHandler(async (req, res, next) => {
}
});
// DB
exports.get = asyncHandler(async (req, res, next) => {
try{
const id = req.params.id;
let result = await lotDb.get(id);
res.status(200).send(result);
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.post = asyncHandler(async (req, res, next) => {
try{
// check if double
let Lot = await lotDb.getByIDPlatform(req.body.idPlatform, req.body.platform);
if(Sale){
return res.status(500).send("Lot already exists");
}
let createLot = await lotDb.post(req.body);
res.status(204).send();
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.put = asyncHandler(async (req, res, next) => {
try{
const id = req.params.id;
let updatedDocument = { ...req.body };
delete updatedDocument._id;
console.log(updatedDocument);
let result = await lotDb.put(id, updatedDocument);
console.log(result);
res.status(200).send(result);
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.delete = asyncHandler(async (req, res, next) => {
try{
const id = req.params.id;
// Remove the lot
await lotDb.remove(id);
res.status(200).send({"message": "Lots deleted"});
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
+164 -6
View File
@@ -8,7 +8,7 @@ const lotDb = new LotDb();
const agenda = require('../services/agenda');
const {Agent} = require('../services/agent');
const agent = new Agent();
const ExcelJS = require('exceljs');
exports.getSaleInfos = asyncHandler(async (req, res, next) => {
let url = req.params.url
@@ -218,31 +218,102 @@ exports.postProcessing = asyncHandler(async (req, res, next) => {
}
Lots = await lotDb.getBySaleId(Sale._id.toString(),Sale.platform);
TimestampInSecond = (timestamp) => {
const stringTimestamp = String(timestamp);
if (stringTimestamp.length === 13) {
return timestamp / 1000;
} else if (stringTimestamp.length === 10) {
return timestamp;
} else {
return 0;
}
}
// Create an array to hold the updated lots
let updatedLots = [];
let bidsDuration = 0;
// process each lot
for (let lot of Lots) {
let highestBid, duration, percentageAboveUnderLow, percentageAboveUnderHigh = 0;
// if bid
let nbrBids = 0;
if (Array.isArray(lot.Bids)) {
nbrBids = lot.Bids.length;
highestBid = lot.Bids.reduce((prev, current) => (prev.amount > current.amount) ? prev : current).amount;
let startTime = TimestampInSecond(lot.Bids[0].timestamp);
let endTime = TimestampInSecond(lot.Bids[lot.Bids.length-1].timestamp);
duration = endTime - startTime;
// total time of bids
bidsDuration += duration;
duration = duration.toFixed(0);
}
// if auctioned
percentageAboveUnderLow = 0;
percentageAboveUnderHigh = 0;
if (lot.auctioned) {
if(lot.EstimateLow){
percentageAboveUnderLow = ((lot.auctioned.amount - lot.EstimateLow) / lot.EstimateLow) * 100;
}
if(lot.EstimateHigh){
percentageAboveUnderHigh = ((lot.auctioned.amount - lot.EstimateHigh) / lot.EstimateHigh) * 100;
}
}
let lotPostProcessing = {
nbrBids: nbrBids,
highestBid: highestBid,
duration: duration,
percentageAboveUnderLow: percentageAboveUnderLow.toFixed(0),
percentageAboveUnderHigh: percentageAboveUnderHigh.toFixed(0)
}
lot.postProcessing = lotPostProcessing;
await lotDb.put(lot._id, lot);
// Add the updated lot to the array
updatedLots.push(lot);
}
// refresh with postprocess datas
Lots = updatedLots;
let startTime = 0;
if (Array.isArray(Lots[0].Bids)) {
startTime = Lots[0].Bids[0].timestamp;
startTime = TimestampInSecond(Lots[0].Bids[0].timestamp);
}else{
startTime = Lots[0].timestamp;
startTime = TimestampInSecond(Lots[0].timestamp);
}
let LastBid = [...Lots].reverse().find(lot => lot.auctioned !== undefined);
let endTime = 0;
if (Array.isArray(LastBid.Bids)) {
endTime = LastBid.Bids[LastBid.Bids.length-1].timestamp;
endTime = TimestampInSecond(LastBid.Bids[LastBid.Bids.length-1].timestamp);
}else{
endTime = LastBid.timestamp;
endTime = TimestampInSecond(LastBid.timestamp);
}
console.log("Start Time: "+startTime);
console.log("End Time: "+endTime);
let duration = endTime-startTime;
let duration = (endTime-startTime).toFixed(0);
let totalAmount = 0;
let unsoldLots = 0;
for (let lot of Lots) {
if (lot.auctioned) {
totalAmount += lot.auctioned.amount;
} else {
unsoldLots++;
}
}
@@ -262,10 +333,15 @@ exports.postProcessing = asyncHandler(async (req, res, next) => {
let postProcessing = {
nbrLots: Lots.length,
duration: duration,
bidsDuration: bidsDuration.toFixed(0),
durationPerLots: (duration/Lots.length).toFixed(0),
totalAmount: totalAmount,
averageAmount: (totalAmount/Lots.length).toFixed(2),
medianAmount: calculateMedian(amounts).toFixed(2),
minAmount: Math.min(...amounts).toFixed(2),
maxAmount: Math.max(...amounts).toFixed(2),
unsoldLots: unsoldLots,
unsoldPercentage: ((unsoldLots/Lots.length)*100).toFixed(2)
}
console.log(postProcessing);
@@ -279,4 +355,86 @@ exports.postProcessing = asyncHandler(async (req, res, next) => {
return res.status(500).send(err);
}
});
exports.SaleStatXsl = asyncHandler(async (req, res, next) => {
try{
const id = req.params.id;
Sale = await saleDb.get(id);
if(!Sale){
console.error("Sale not found");
return res.status(404).send("Sale not found");
}
Lots = await lotDb.getBySaleId(Sale._id.toString(),Sale.platform);
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sale Stats');
worksheet.columns = [
{ header: 'Lot #', key: 'lotNumber', width: 10 },
{ header: 'Description', key: 'description', width: 100 },
{ header: 'Auctioned Amount', key: 'auctionedAmount', width: 20 },
{ header: 'Estimate Low', key: 'estimateLow', width: 20 },
{ header: 'Estimate High', key: 'estimateHigh', width: 20 },
{ header: 'Bids', key: 'nbrBids', width: 10 },
{ header: 'Highest Bid', key: 'highestBid', width: 20 },
{ header: 'Duration (in s)', key: 'duration', width: 10 },
{ header: '% Above Low', key: 'percentageAboveUnderLow', width: 20 },
{ header: '% Above High', key: 'percentageAboveUnderHigh', width: 20 }
];
let row = 2;
for (let lot of Lots) {
let Row = worksheet.addRow({
lotNumber: lot.lotNumber,
description: lot.description,
auctionedAmount: lot.auctioned?.amount,
estimateLow: lot.EstimateLow,
estimateHigh: lot.EstimateHigh,
nbrBids: lot.postProcessing?.nbrBids,
highestBid: lot.postProcessing?.highestBid,
duration: lot.postProcessing?.duration,
percentageAboveUnderLow: lot.postProcessing?.percentageAboveUnderLow/100,
percentageAboveUnderHigh: lot.postProcessing?.percentageAboveUnderHigh/100
});
Row.getCell('C').numFmt = '€0.00';
Row.getCell('D').numFmt = '€0.00';
Row.getCell('E').numFmt = '€0.00';
Row.getCell('B').numFmt = '€0.00';
Row.getCell('G').numFmt = '€0.00';
Row.getCell('I').numFmt = '0%';
Row.getCell('J').numFmt = '0%';
row++;
}
worksheet.addRow({
lotNumber: 'Total',
auctionedAmount: Sale.postProcessing?.totalAmount,
estimateLow: '',
estimateHigh: '',
nbrBids: '',
highestBid: '',
duration: Sale.postProcessing?.duration,
percentageAboveUnderLow: '',
percentageAboveUnderHigh: ''
});
// send the Xls File
res.setHeader(
"Content-Disposition",
"attachment; filename=" + "SaleStats.xlsx"
);
await workbook.xlsx.write(res);
return res.status(200).end();
}catch(err){
console.log(err);
return res.status(500).send
}
});
+199
View File
@@ -0,0 +1,199 @@
const asyncHandler = require("express-async-handler");
const moment = require('moment-timezone');
const { ObjectId } = require('mongodb');
const { UserDb } = require("../services/userDb");
const crypto = require('crypto');
function ClearUserData(user){
delete user.salt;
delete user.hashed_password;
delete user.salt;
delete user.isAgent;
return user;
}
function ClearUserDataForAdmin(user){
delete user.salt;
delete user.hashed_password;
delete user.salt;
return user;
}
// DB
exports.get = asyncHandler(async (req, res, next) => {
try{
const userDb = await UserDb.init();
const id = req.params.id;
let result = await userDb.get(id);
if (req.user.isAdmin){
res.status(200).send(ClearUserDataForAdmin(result));
}else{
res.status(200).send(ClearUserData(result));
}
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.post = asyncHandler(async (req, res, next) => {
try{
const userDb = await UserDb.init();
// check if double
let User = await userDb.getByEmail(req.body.email);
if(User){
return res.status(500).send("User already exists");
}
// check password
if(!req.body.password){
return res.status(500).send("Password not set");
}
if(req.body.password != req.body.confirmPassword){
return res.status(500).send("Passwords do not match");
}
if(req.body.password.length < 8){
return res.status(500).send("Password too short");
}
if(req.body.isAdmin){
if(req.user){
if(!req.user.isAdmin){
return res.status(500).send("You are not allowed to create an admin user");
}
}else{
req.body.isAdmin = false
}
}
if(req.body.isAgent){
if(req.user){
if(!req.user.isAgent){
return res.status(500).send("You are not allowed to create an agent user");
}
}else{
req.body.isAgent = false
}
}
let salt = crypto.randomBytes(16).toString('hex');
let user = {
username: req.body.username,
hashed_password: crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256').toString('hex'),
salt: salt,
email: req.body.email,
isAdmin: req.body.isAdmin,
isAgent: req.body.isAgent,
}
let createData = await userDb.post(user);
res.status(204).send();
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.put = asyncHandler(async (req, res, next) => {
try{
const userDb = await UserDb.init();
const id = req.params.id;
const User = await userDb.get(id);
if(!User){
return res.status(500).send("User not found");
}
// check password
let hashed_password = "";
let salt = "";
if(req.body.password){
if(req.body.password != req.body.confirmPassword){
return res.status(500).send("Passwords do not match");
}
if(req.body.password.length < 8){
return res.status(500).send("Password too short");
}
salt = crypto.randomBytes(16).toString('hex');
hashed_password = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256').toString('hex');
}else{
salt = User.salt;
hashed_password = User.hashed_password;
}
if(req.body.isAdmin){
if(!req.user.isAdmin){
return res.status(500).send("You are not allowed to create an admin user");
}
}
if(req.body.isAgent){
if(!req.user.isAdmin){
return res.status(500).send("You are not allowed to create an agent user");
}
}
let user = {
username: req.body.username,
hashed_password: hashed_password,
salt: salt,
email: req.body.email,
isAdmin: req.body.isAdmin,
isAgent: req.body.isAgent,
}
let result = await userDb.put(id, user);
console.log(result);
res.status(200).send(result);
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.delete = asyncHandler(async (req, res, next) => {
try{
const userDb = await UserDb.init();
const id = req.params.id;
// Remove the sale
await userDb.remove(id);
res.status(200).send({"message": "User deleted"});
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
// Functions
exports.current = asyncHandler(async (req, res, next) => {
try{
const user = ClearUserData(req.user);
res.status(200).send(user);
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.getAllUsers = asyncHandler(async (req, res, next) => {
try{
const userDb = await UserDb.init();
let result = await userDb.getAll();
result = result.map(user => ClearUserDataForAdmin(user));
res.status(200).send(result);
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
+46 -2
View File
@@ -1,3 +1,4 @@
const config = require("./config.js");
const express = require('express')
const app = express()
@@ -9,17 +10,60 @@ app.use(cors());
// Enable preflight requests for all routes
app.options('*', cors());
// Session support
const session = require('express-session');
app.use(session({
secret: 'jucundus.ses',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
// const MongoStore = require('connect-mongo');
// const keys = require("./.Keys.js");
// const sassionConfig = {
// ...config.session.sessionConfig,
// secret: keys.session,
// store: MongoStore.create({
// mongoUrl: `${config.db.connectionString}/${config.db.dbName}`,
// collection: config.session.sessionCollection,
// stringify: false,
// autoReconnect: true,
// autoRemove: 'native'
// })};
// app.use(session(sassionConfig));
// Authentication
const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());
app.use('/', require('./routes/auth'));
// Agenda Scheduller
const agenda = require('./services/agenda');
(async function() {
//lunch sheduller
await agenda.start();
})();
//create first user
const { UserDb } = require('./services/userDb');
const userDb = await UserDb.init();
userDb.creatFirstUserifEmpty();
})();
// Agenda UI
var Agendash = require("agendash");
app.use("/dash", Agendash(agenda));
// routes
app.use('/api/user', require('./routes/user'));
app.use('/api/lot', require('./routes/lot'));
app.use('/api/sale', require('./routes/sale'));
app.use('/api/favorite', require('./routes/favorite'));
+33
View File
@@ -0,0 +1,33 @@
function checkIsConcernedUserOrAdmin(req, res, next) {
const user = req.user; // User is set by Passport
const userIdParam = req.params.id;
if (user.isAdmin === true || user._id === userIdParam) {
next();
} else {
res.status(403).json({ error: 'Forbidden' });
}
}
function checkIsAdmin(req, res, next) {
const user = req.user; // User is set by Passport
if (user.isAdmin === true) {
next();
} else {
res.status(403).json({ error: 'Forbidden' });
}
}
function checkIsAgent(req, res, next) {
const user = req.user; // User is set by Passport
if (user.isAgent === true) {
next();
} else {
res.status(403).json({ error: 'Forbidden' });
}
}
module.exports = { checkIsConcernedUserOrAdmin, checkIsAgent, checkIsAdmin };
+1111 -30
View File
File diff suppressed because it is too large Load Diff
+9 -2
View File
@@ -6,7 +6,7 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
"dev": "nodemon --watch ./ server.js --ignore node_modules/"
"dev": "nodemon --inspect=0.0.0.0 --watch ./ server.js --ignore node_modules/"
},
"keywords": [],
"author": "",
@@ -15,11 +15,18 @@
"@angular/cli": "^17.1.3",
"@hokify/agenda": "^6.3.0",
"agendash": "^4.0.0",
"connect-mongo": "^5.1.0",
"cors": "^2.8.5",
"exceljs": "^4.4.0",
"express": "^4.18.2",
"express-async-handler": "^1.2.0",
"express-session": "^1.18.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.5.0",
"node-fetch": "^2.7.0"
"node-fetch": "^2.7.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0"
},
"devDependencies": {
"nodemon": "^3.0.3"
+113
View File
@@ -0,0 +1,113 @@
var passport = require('passport');
var LocalStrategy = require('passport-local');
var crypto = require('crypto');
const router = require('express').Router()
const config = require("../config.js");
const keys = require("../.Keys.js");
/* Configure password authentication strategy.
*
* The `LocalStrategy` authenticates users by verifying a username and password.
* The strategy parses the username and password from the request and calls the
* `verify` function.
*
* The `verify` function queries the database for the user record and verifies
* the password by hashing the password supplied by the user and comparing it to
* the hashed password stored in the database. If the comparison succeeds, the
* user is authenticated; otherwise, not.
*/
const { UserDb }= require('../services/userDb');
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},async function verify(email, password, cb) {
try {
const userDb = await UserDb.init();
const user = await userDb.getByEmail(email);
if (!user) {
return cb(null, false, { message: 'Incorrect username or password.' });
}
crypto.pbkdf2(password, user.salt, 310000, 32, 'sha256', async function(err, hashedPassword) {
if (err) { return cb(err); }
if (!crypto.timingSafeEqual(Buffer.from(user.hashed_password, 'hex'), Buffer.from(hashedPassword, 'hex'))) {
return cb(null, false, { message: 'Incorrect username or password.' });
}
return cb(null, user);
});
} catch (err) {
return cb(err);
}
}));
/* Configure session management.
*
* When a login session is established, information about the user will be
* stored in the session. This information is supplied by the `serializeUser`
* function, which is yielding the user ID and username.
*
* As the user interacts with the app, subsequent requests will be authenticated
* by verifying the session. The same user information that was serialized at
* session establishment will be restored when the session is authenticated by
* the `deserializeUser` function.
*
* Since every request to the app needs the user ID and username, in order to
* fetch todo records and render the user element in the navigation bar, that
* information is stored in the session.
*/
passport.serializeUser(function(user, cb) {
process.nextTick(function() {
cb(null, { id: user._id, username: user.email });
});
});
passport.deserializeUser(function(user, cb) {
process.nextTick(function() {
return cb(null, user);
});
});
// JWT
var jwt = require('jsonwebtoken');
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.jwt;
opts.issuer = config.jwtOptions.issuer;
opts.audience = config.jwtOptions.audience;
passport.use(new JwtStrategy(opts, async function(jwt_payload, done) {
const userDb = await UserDb.init();
try {
const user = await userDb.get(jwt_payload.sub);
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
} catch (err) {
return done(err, false);
}
}));
router.post('/authenticate', async function(req, res) {
passport.authenticate('local', async function(err, user, info) {
if (err) { return res.status(500).json({message: err.message}); }
if (!user) { return res.status(401).json({message: 'Incorrect email or password.'}); }
// User found, generate a JWT for the user
var token = jwt.sign({ sub: user._id, email: user.email }, opts.secretOrKey, {
issuer: opts.issuer,
audience: opts.audience,
expiresIn: 86400 * 30 // 30 days
});
res.json({ token: token });
//return res.status(500).json({message: 'Incorrect email or password.'})
})(req, res);
});
module.exports = router;
+4 -2
View File
@@ -1,7 +1,9 @@
const controllers = require('../controllers/favorite')
const router = require('express').Router()
const passport = require('passport');
const { checkIsConcernedUserOrAdmin } = require('../middleware/authMiddleware')
router.post('/save/', controllers.save)
router.get('/getAll/', controllers.getAll)
router.post('/save/', passport.authenticate('jwt', { session: false }), controllers.save)
router.get('/getAll/', passport.authenticate('jwt', { session: false }), controllers.getAll)
module.exports = router
+15 -6
View File
@@ -1,12 +1,21 @@
const controllers = require('../controllers/lot')
const router = require('express').Router()
const passport = require('passport');
const { checkIsAgent, checkIsAdmin } = require('../middleware/authMiddleware')
router.get('/getInfos/:url', controllers.getInfos)
router.get('/getPictures/:url', controllers.getPictures)
router.get('/getLotsBySale/:id', controllers.getLotsBySale)
router.get('/getInfos/:url', passport.authenticate('jwt', { session: false }), controllers.getInfos)
router.get('/getPictures/:url', passport.authenticate('jwt', { session: false }), controllers.getPictures)
router.get('/getLotsBySale/:id', passport.authenticate('jwt', { session: false }), controllers.getLotsBySale)
router.post('/NextItem/', controllers.NextItem)
router.post('/AuctionedItem/', controllers.AuctionedItem)
router.post('/Bid/', controllers.Bid)
// DB
router.get('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.get)
router.post('/lot/', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.post)
router.put('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.put)
router.delete('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.delete)
// Live Data
router.post('/NextItem/', checkIsAgent, controllers.NextItem)
router.post('/AuctionedItem/', checkIsAgent, controllers.AuctionedItem)
router.post('/Bid/', checkIsAgent, controllers.Bid)
module.exports = router
+4 -1
View File
@@ -1,4 +1,5 @@
const controllers = require('../controllers/sale')
const passport = require('passport');
const router = require('express').Router()
// AuctionAgent
@@ -13,9 +14,11 @@ router.post('/sale/', controllers.post)
router.put('/sale/:id', controllers.put)
router.delete('/sale/:id', controllers.delete)
router.get('/getAll/', controllers.getAll)
//router.get('/getAll/', controllers.getAll)
router.get('/getAll/', passport.authenticate('jwt', { session: false }), controllers.getAll);
router.get('/getByUrl/:url', controllers.getByUrl)
router.get('/postProcessing/:id', controllers.postProcessing)
router.get('/SaleStatXsl/:id', controllers.SaleStatXsl)
module.exports = router
+15
View File
@@ -0,0 +1,15 @@
const controllers = require('../controllers/user')
const passport = require('passport');
const router = require('express').Router()
const { checkIsConcernedUserOrAdmin, checkIsAdmin } = require('../middleware/authMiddleware')
// DB
router.get('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.get);
router.post('/user/', controllers.post)
router.put('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.put)
router.delete('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.delete)
router.get('/current', passport.authenticate('jwt', { session: false }), controllers.current)
router.get('/getAllUsers', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.getAllUsers)
module.exports = router
+3 -2
View File
@@ -1,5 +1,6 @@
const MongoClient = require("mongodb").MongoClient;
const connectionString = "mongodb://db:27017";
const config = require("../config.js");
const connectionString = config.db.connectionString;
const client = new MongoClient(connectionString);
let db;
@@ -8,7 +9,7 @@ const connectDb = async () => {
if (db) return db;
try {
const conn = await client.connect();
db = conn.db("jucundus");
db = conn.db(config.db.dbName);
return db;
} catch(e) {
console.error(e);
+91
View File
@@ -0,0 +1,91 @@
const { ObjectId } = require('mongodb');
const connectDb = require("./db");
const crypto = require('crypto');
const UserDb = class
{
constructor()
{
}
static async init() {
const userDb = new UserDb();
await userDb.getCollection();
return userDb;
}
async getCollection()
{
const db = await connectDb();
if (!db) {
throw new Error('Database not connected');
}
this.collection = db.collection("Users");
}
// CRUD
async get(id)
{
let result = await this.collection.findOne({_id: new ObjectId(id)});
return result;
}
async post(newDocument)
{
delete newDocument._id;
let result = await this.collection.insertOne(newDocument);
return result;
}
async put(id, data)
{
delete data._id;
let result = await this.collection.updateOne({_id: new ObjectId(id)}, {$set: data});
return result;
}
async remove(id)
{
let result = await this.collection.deleteOne({_id: new ObjectId(id)});
return result;
}
// Functions
async getAll()
{
let result = await this.collection.find({}).toArray();
return result;
}
async getByUsername(username)
{
let result = await this.collection.findOne({username: username});
return result;
}
async getByEmail(email)
{
let result = await this.collection.findOne({email: email});
return result;
}
async creatFirstUserifEmpty( ){
const allUsers = await this.getAll();
if(allUsers.length == 0){
console.log("Creating first user");
let salt = crypto.randomBytes(16).toString('hex');
let user = {
username: "admin",
hashed_password: crypto.pbkdf2Sync('admin', salt, 310000, 32, 'sha256').toString('hex'),
salt: salt,
email: "admin@admin.com",
isAdmin: true,
isAgent: false,
}
this.post(user);
}
}
}
module.exports = { UserDb };