mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Add interface to block ip-addresses or clients due to abuse (#15484)
* Read IP blocks from database * begin building general blocking solution * add new frontend files * Add UI for managing blockers * correctly reset local data after creating blocker * Tweak wording * Add UI for managing blockers * restructure admin pages * improve test coverage * Improve blocker UI * add blocker to block emails from registration * lint fix * fix * lint fixes * fix import * add new permission for managing blockers * improve permission check * fix managing permissions from admin * improve navbar display for non fullAccess admin * update block error strings * lint fix * add option to errorHandler to skip logging * validate blocker value during input * improve blocker form display * chore(subproj): reconcile habitica-images * fix(scripts): use same Mongo version for dev/test * fix(whitespace): eof * documentation improvements * remove nconf import * remove old test --------- Co-authored-by: Kalista Payne <kalista@habitica.com> Co-authored-by: Kalista Payne <sabrecat@gmail.com>
This commit is contained in:
103
website/server/models/blocker.js
Normal file
103
website/server/models/blocker.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import mongoose from 'mongoose';
|
||||
import EventEmitter from 'events';
|
||||
import baseModel from '../libs/baseModel';
|
||||
|
||||
export const blockTypes = [
|
||||
'ipaddress',
|
||||
'email',
|
||||
'client',
|
||||
];
|
||||
|
||||
export const blockArea = [
|
||||
'full',
|
||||
'payments',
|
||||
];
|
||||
|
||||
export const schema = new mongoose.Schema({
|
||||
disabled: {
|
||||
$type: Boolean, default: false, // If true, the block is disabled
|
||||
},
|
||||
type: {
|
||||
$type: String, enum: blockTypes, required: true,
|
||||
},
|
||||
area: {
|
||||
$type: String, enum: blockArea, default: 'full', // full or payment
|
||||
},
|
||||
value: {
|
||||
$type: String, required: true, // e.g. IP address
|
||||
},
|
||||
blockSource: {
|
||||
$type: String, enum: ['administrator', 'system', 'worker'], default: 'administrator', // who created the block
|
||||
},
|
||||
reason: {
|
||||
$type: String, required: false, // e.g. 'abusive behavior'
|
||||
},
|
||||
}, {
|
||||
strict: true,
|
||||
minimize: false, // So empty objects are returned
|
||||
typeKey: '$type', // So that we can use fields named `type`
|
||||
});
|
||||
|
||||
schema.plugin(baseModel, {
|
||||
timestamps: true,
|
||||
});
|
||||
|
||||
schema.statics.watchBlockers = function watchBlockers (query, options) {
|
||||
const emitter = new EventEmitter();
|
||||
const matchQuery = {
|
||||
$match: {},
|
||||
};
|
||||
if (query) {
|
||||
if (query.type) {
|
||||
matchQuery.$match['fullDocument.type'] = query.type;
|
||||
}
|
||||
if (query.area) {
|
||||
matchQuery.$match['fullDocument.area'] = query.area;
|
||||
}
|
||||
}
|
||||
process.nextTick(() => {
|
||||
this.watch([matchQuery], {
|
||||
fullDocument: 'updateLookup',
|
||||
})
|
||||
.on('change', change => {
|
||||
if (!change.fullDocument) {
|
||||
return; // Ignore changes that don't have a fullDocument
|
||||
}
|
||||
if (change.operationType === 'insert' || !change.fullDocument.disabled) {
|
||||
emitter.emit('change', {
|
||||
operation: 'add',
|
||||
blocker: change.fullDocument,
|
||||
});
|
||||
} else if (change.operationType === 'update' && change.fullDocument.disabled) {
|
||||
emitter.emit('change', {
|
||||
operation: 'delete',
|
||||
blocker: change.fullDocument,
|
||||
});
|
||||
}
|
||||
})
|
||||
.on('error', error => {
|
||||
emitter.emit('error', error);
|
||||
});
|
||||
if (options.initial) {
|
||||
const initialQuery = {
|
||||
disabled: false,
|
||||
...query,
|
||||
};
|
||||
this.find(initialQuery).then(docs => {
|
||||
for (const doc of docs) {
|
||||
emitter.emit('change', {
|
||||
operation: 'add',
|
||||
blocker: doc,
|
||||
});
|
||||
}
|
||||
}).catch(error => {
|
||||
emitter.emit('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
return emitter;
|
||||
};
|
||||
|
||||
export const model = mongoose.model('Blocker', schema);
|
||||
Reference in New Issue
Block a user