Files
pronature-platform/backend/app/AccessManager.js
T
2026-02-05 17:02:27 +02:00

154 lines
5.3 KiB
JavaScript

class AccessManager {
name = 'am'
init(app){
['user', 'editor', 'admin'].forEach(f => {
this[f] = this.oneOfThese([f]);
});
}
start(app){
}
getIp(req){
return req.headers['x-forwarded-for'] || req.socket.remoteAddress;
}
async audit(req, action, objectId, custom){
let data = {
t: Math.floor(Date.now() / 1000),
s: req.session?.id,
i: this.getIp(req),
r: req.headers.referer,
ua: req.headers['user-agent'],
l: req?.lang?.code,
u: req.user?._id && this.app.db.ObjectId(req.user._id),
a: action,
o: objectId,
c: custom
}
await this.app.db.create('log', data);
}
async addToHistory(id, collection, action){
let o;
if (typeof id == 'string') o = await this.app.db.get(collection, {'_id': this.app.db.ObjectId(id)});
else if (typeof id == 'number') o = await this.app.db.get(collection, {id});
else o = id;
o._oid = this.app.db.ObjectId(o._id);
o._from = collection;
o._action = action;
await this.app.db.create('history', o);
return o;
}
async getObjectHistory(collection, match){
let object = await this.app.db.aggregate( collection, [
{ $match: match },
{ $lookup: {from: 'users', foreignField: '_id', localField: '_meta.user', as: '_user'} },
{ $project: {action:'$_meta.action', time:'$_meta.time', user:"$_user.email", type:'current'} },
{ $unwind: {path:'$user', preserveNullAndEmptyArrays:true}}
]);
let history = await this.app.db.aggregate('history',[
{ $match: {_oid:object._id, _from:collection}},
{ $lookup: {from: 'users', foreignField: '_id', localField: '_meta.user', as: '_user'} },
{ $project: {action:'$_meta.action', time:'$_meta.time', user:"$_user.email", type:'history'} },
{ $sort: { time:-1 }},
{ $unwind: {path:'$user', preserveNullAndEmptyArrays:true}}
]);
return {object, history};
}
setMeta(m, action, user, time, custom){
delete m.revert;
m.user = user && user._id && this.app.db.ObjectId(user._id);
m.creator = m.creator || m.user;
m.time = time || Math.floor(Date.now() / 1000);
m.ctime = m.ctime || m.time;
m.action = action;
custom && Object.assign(m, custom);
}
async processSocialLogin(p1, p2, profile, done){
//console.log(p1, p2, profile);
let externalProfile = {
loginProvider: profile.provider,
providerKey: profile.id
};
let user;
let dbUser = await this.app.db.get(collection, {social: externalProfile});
if (dbUser){
user = this.getUserProfile(dbUser);
}else{
let dbUser = {
email: (profile.emails && profile.emails[0].value) || ((profile.username || profile.id) + "@" + profile.provider),
firstName: (profile.name && profile.name.givenName) || profile.displayName,
lastName: profile.name && profile.name.familyName,
displayName: profile.displayName || (profile.name && profile.name.givenName),
profilePicture:
(profile.photos && profile.photos[0] && profile.photos[0].value)
|| (profile._json.data && profile._json.data.profile_picture),
status: 1,
social:[
externalProfile
],
roles:['user']
};
let r = await this.app.db.create(collection, dbUser);
user = this.getUserProfile(dbUser);
user._id = r.insertedId;
}
done(null, user);
}
getUserProfile(dbUser){
return {
_id: dbUser._id,
email: dbUser.email,
roles: dbUser.roles || ['user'],
groups: dbUser.groups || [],
firstName: dbUser.firstName,
lastName: dbUser.lastName,
displayName: dbUser.displayName,
profilePicture: dbUser.profilePicture,
status: dbUser.status
}
}
getSocialCallback(provider){
const am = this;
return function(req, res, next) {
passport.authenticate(provider, function(err, user, info) {
if (err) { return next(err); }
let lang = req.cookies.lang || am.app.config.langs[0].code;
if (!user) { return res.redirect(`/${lang}/user/signin`); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect(`/${lang}`);
});
})(req, res, next);
}
}
is(user, role){
return user && user.roles.indexOf(role) > -1;
}
oneOfThese(roles){
return function(req, res, next){
let result = false;
roles.forEach(r=>{
if (req.user && (req.user.roles?.indexOf(r)>-1 || req.user.groups?.filter(g=>g.startsWith(r+'.')).length)
|| r == 'guest' ){
result = true;
}
});
if (result) next();
else res.status(401).json({status:'error', error:'noPermissions'}).end();
}
}
}
export { AccessManager }