mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
Read IP blocks from database
This commit is contained in:
113
website/server/models/blocker.js
Normal file
113
website/server/models/blocker.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import mongoose from 'mongoose';
|
||||
import EventEmitter from 'events';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import validator from 'validator';
|
||||
import baseModel from '../libs/baseModel';
|
||||
|
||||
export const blockTypes = [
|
||||
'ipaddress',
|
||||
'email',
|
||||
];
|
||||
|
||||
export const blockArea = [
|
||||
'full',
|
||||
'payment',
|
||||
];
|
||||
|
||||
export const schema = new mongoose.Schema({
|
||||
id: {
|
||||
$type: String,
|
||||
default: uuid,
|
||||
validate: [v => validator.isUUID(v), 'Invalid uuid for tag.'],
|
||||
required: true,
|
||||
},
|
||||
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: ['user', 'system', 'worker'], default: 'user', // who created the block
|
||||
},
|
||||
reason: {
|
||||
$type: String, required: false, // e.g. 'abusive behavior'
|
||||
},
|
||||
}, {
|
||||
strict: true,
|
||||
minimize: false, // So empty objects are returned
|
||||
_id: false, // use id instead of _id
|
||||
typeKey: '$type', // So that we can use fields named `type`
|
||||
});
|
||||
|
||||
schema.plugin(baseModel, {
|
||||
timestamps: true,
|
||||
noSet: ['_id'],
|
||||
_id: false, // use id instead of _id
|
||||
});
|
||||
|
||||
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