mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-17 03:01:08 +01:00
committed by
GitHub
parent
f9c882cb1d
commit
49ba5af5fa
@@ -13,6 +13,11 @@ define('admin/advanced/events', function () {
|
||||
$('.events-list').empty();
|
||||
});
|
||||
});
|
||||
|
||||
$('#filter').on('change', function () {
|
||||
var filter = $(this).val();
|
||||
ajaxify.go('admin/advanced/events' + (filter ? '?filter=' + filter : ''));
|
||||
});
|
||||
};
|
||||
|
||||
return Events;
|
||||
|
||||
@@ -14,24 +14,35 @@ eventsController.get = function (req, res, next) {
|
||||
var start = (page - 1) * itemsPerPage;
|
||||
var stop = start + itemsPerPage - 1;
|
||||
|
||||
var currentFilter = req.query.filter || '';
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
eventCount: function (next) {
|
||||
db.sortedSetCard('events:time', next);
|
||||
db.sortedSetCard('events:time' + (currentFilter ? ':' + currentFilter : ''), next);
|
||||
},
|
||||
events: function (next) {
|
||||
events.getEvents(start, stop, next);
|
||||
events.getEvents(currentFilter, start, stop, next);
|
||||
},
|
||||
}, next);
|
||||
},
|
||||
function (results) {
|
||||
var types = [''].concat(events.types);
|
||||
var filters = types.map(function (type) {
|
||||
return {
|
||||
value: type,
|
||||
name: type || 'all',
|
||||
selected: type === currentFilter,
|
||||
};
|
||||
});
|
||||
|
||||
var pageCount = Math.max(1, Math.ceil(results.eventCount / itemsPerPage));
|
||||
|
||||
res.render('admin/advanced/events', {
|
||||
events: results.events,
|
||||
pagination: pagination.create(page, pageCount),
|
||||
next: 20,
|
||||
pagination: pagination.create(page, pageCount, req.query),
|
||||
filters: filters,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
var async = require('async');
|
||||
var validator = require('validator');
|
||||
var winston = require('winston');
|
||||
var _ = require('lodash');
|
||||
|
||||
var db = require('./database');
|
||||
var batch = require('./batch');
|
||||
@@ -12,6 +13,39 @@ var utils = require('./utils');
|
||||
|
||||
var events = module.exports;
|
||||
|
||||
events.types = [
|
||||
'plugin-activate',
|
||||
'plugin-deactivate',
|
||||
'restart',
|
||||
'build',
|
||||
'config-change',
|
||||
'settings-change',
|
||||
'category-purge',
|
||||
'privilege-change',
|
||||
'post-delete',
|
||||
'post-restore',
|
||||
'post-purge',
|
||||
'topic-delete',
|
||||
'topic-restore',
|
||||
'topic-purge',
|
||||
'topic-rename',
|
||||
'password-reset',
|
||||
'user-ban',
|
||||
'user-unban',
|
||||
'user-delete',
|
||||
'password-change',
|
||||
'email-change',
|
||||
'username-change',
|
||||
'registration-approved',
|
||||
'registration-rejected',
|
||||
'accept-membership',
|
||||
'reject-membership',
|
||||
'theme-set',
|
||||
'export:uploads',
|
||||
'account-locked',
|
||||
'getUsersCSV',
|
||||
];
|
||||
|
||||
/**
|
||||
* Useful options in data: type, uid, ip, targetUid
|
||||
* Everything else gets stringified and shown as pretty JSON string
|
||||
@@ -31,6 +65,9 @@ events.log = function (data, callback) {
|
||||
function (next) {
|
||||
db.sortedSetAdd('events:time', data.timestamp, eid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('events:time:' + data.type, data.timestamp, eid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.setObject('event:' + eid, data, next);
|
||||
},
|
||||
@@ -41,10 +78,10 @@ events.log = function (data, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
events.getEvents = function (start, stop, callback) {
|
||||
events.getEvents = function (filter, start, stop, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getSortedSetRevRange('events:time', start, stop, next);
|
||||
db.getSortedSetRevRange('events:time' + (filter ? ':' + filter : ''), start, stop, next);
|
||||
},
|
||||
function (eids, next) {
|
||||
var keys = eids.map(function (eid) {
|
||||
@@ -123,15 +160,24 @@ function addUserData(eventsData, field, objectName, callback) {
|
||||
|
||||
events.deleteEvents = function (eids, callback) {
|
||||
callback = callback || function () {};
|
||||
async.parallel([
|
||||
var keys;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
var keys = eids.map(function (eid) {
|
||||
keys = eids.map(function (eid) {
|
||||
return 'event:' + eid;
|
||||
});
|
||||
db.getObjectsFields(keys, ['type'], next);
|
||||
},
|
||||
function (eventData, next) {
|
||||
var sets = _.uniq(['events:time'].concat(eventData.map(e => 'events:time:' + e.type)));
|
||||
async.parallel([
|
||||
function (next) {
|
||||
db.deleteAll(keys, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetRemove('events:time', eids, next);
|
||||
db.sortedSetRemove(sets, eids, next);
|
||||
},
|
||||
], next);
|
||||
},
|
||||
], callback);
|
||||
};
|
||||
@@ -146,7 +192,7 @@ events.deleteAll = function (callback) {
|
||||
|
||||
events.output = function () {
|
||||
console.log('\nDisplaying last ten administrative events...'.bold);
|
||||
events.getEvents(0, 9, function (err, events) {
|
||||
events.getEvents('', 0, 9, function (err, events) {
|
||||
if (err) {
|
||||
winston.error('Error fetching events', err);
|
||||
throw err;
|
||||
|
||||
@@ -84,8 +84,10 @@ Categories.setPrivilege = function (socket, data, callback) {
|
||||
function onSetComplete() {
|
||||
events.log({
|
||||
uid: socket.uid,
|
||||
type: 'privilege-change',
|
||||
ip: socket.ip,
|
||||
privilege: data.privilege.toString(),
|
||||
cid: data.cid,
|
||||
action: data.set ? 'grant' : 'rescind',
|
||||
target: data.member,
|
||||
}, callback);
|
||||
|
||||
46
src/upgrades/1.10.2/event_filters.js
Normal file
46
src/upgrades/1.10.2/event_filters.js
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
var db = require('../../database');
|
||||
|
||||
var async = require('async');
|
||||
var batch = require('../../batch');
|
||||
|
||||
module.exports = {
|
||||
name: 'add filters to events',
|
||||
timestamp: Date.UTC(2018, 9, 4),
|
||||
method: function (callback) {
|
||||
const progress = this.progress;
|
||||
|
||||
batch.processSortedSet('events:time', function (eids, next) {
|
||||
async.eachSeries(eids, function (eid, next) {
|
||||
progress.incr();
|
||||
|
||||
db.getObject('event:' + eid, function (err, eventData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (!eventData) {
|
||||
return db.sortedSetRemove('events:time', eid, next);
|
||||
}
|
||||
// privilege events we're missing type field
|
||||
if (!eventData.type && eventData.privilege) {
|
||||
eventData.type = 'privilege-change';
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setObjectField('event:' + eid, 'type', 'privilege-change', next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('events:time:' + eventData.type, eventData.timestamp, eid, next);
|
||||
},
|
||||
], next);
|
||||
return;
|
||||
}
|
||||
|
||||
db.sortedSetAdd('events:time:' + (eventData.type || ''), eventData.timestamp, eid, next);
|
||||
});
|
||||
}, next);
|
||||
}, {
|
||||
progress: this.progress,
|
||||
}, callback);
|
||||
},
|
||||
};
|
||||
@@ -1,8 +1,13 @@
|
||||
<div class="row events">
|
||||
<div class="col-lg-9">
|
||||
<select id="filter" class="form-control">
|
||||
<!-- BEGIN filters -->
|
||||
<option value="{filters.value}" <!-- IF filters.selected -->selected<!-- ENDIF filters.selected -->>{filters.name}</option>
|
||||
<!-- END filters -->
|
||||
</select>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-calendar-o"></i> [[admin/advanced/events:events]]</div>
|
||||
<div class="panel-body" data-next="{next}">
|
||||
<div class="panel-body">
|
||||
<!-- IF !events.length -->
|
||||
<div class="alert alert-info">[[admin/advanced/events:no-events]]</div>
|
||||
<!-- ENDIF !events.length -->
|
||||
|
||||
Reference in New Issue
Block a user