Skip to content

Commit

Permalink
Move bans into core.
Browse files Browse the repository at this point in the history
  • Loading branch information
goto-bus-stop committed Oct 6, 2017
1 parent a37870d commit 5d7c636
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Uwave.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import chat from './plugins/chat';
import motd from './plugins/motd';
import playlists from './plugins/playlists';
import users from './plugins/users';
import bans from './plugins/bans';
import history from './plugins/history';
import acl from './plugins/acl';

Expand Down Expand Up @@ -56,6 +57,7 @@ export default class UWaveServer extends EventEmitter {
this.use(motd());
this.use(playlists());
this.use(users());
this.use(bans());
this.use(history());
this.use(acl());
}
Expand Down
4 changes: 4 additions & 0 deletions src/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ export default function userModel() {
async isMuted(): Promise<boolean> {
return uw.chat.isMuted(this);
}

isBanned(): Promise<boolean> {
return uw.bans.isBanned(this);
}
}

const UserSchema = createSchema({ minimize: true })(User);
Expand Down
135 changes: 135 additions & 0 deletions src/plugins/bans.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import clamp from 'clamp';
import escapeStringRegExp from 'escape-string-regexp';
import Page from '../Page';

function isValidBan(user) {
return !!(user.banned && user.banned.expiresAt > Date.now());
}

class Bans {
constructor(uw) {
this.uw = uw;
}

/**
* Check whether a user is currently banned.
*
* @param {string|ObjectId|User} userID A user object or ID.
*/
async isBanned(userID) {
const { users } = this.uw;

const user = await users.getUser(userID);
return isValidBan(user);
}

/**
* List banned users.
*
* @param {string} filter Optional filter to search for usernames.
* @param {*} pagination A pagination object.
*/
async getBans(filter = null, pagination = {}): Page {
const User = this.uw.model('User');

const offset = pagination.offset || 0;
const size = clamp(
'limit' in pagination ? pagination.limit : 50,
0, 100
);

const queryFilter = {
banned: { $ne: null },
'banned.expiresAt': { $gt: new Date() }
};
if (filter) {
Object.assign(queryFilter, {
username: { $regex: RegExp(escapeStringRegExp(filter), 'i') }
});
}

const total = await User.find().where(queryFilter).count();

const bannedUsers = await User.find()
.where(queryFilter)
.skip(offset)
.limit(size)
.populate('banned.moderator')
.lean();

const results = bannedUsers.map((user) => {
const ban = user.banned;
delete user.banned; // eslint-disable-line no-param-reassign
ban.user = user;
return ban;
});

return new Page(results, {
pageSize: pagination ? pagination.limit : null,
filtered: total,
total,
current: { offset, limit: size },
next: pagination ? { offset: offset + size, limit: size } : null,
previous: offset > 0
? { offset: Math.max(offset - size, 0), limit: size }
: null,
results
});
}

async ban(userID, { duration, moderator, permanent = false, reason = '' }) {
const { users } = this.uw;

const user = await users.getUser(userID);
if (!user) throw new Error('User not found.');

if (duration <= 0 && !permanent) {
throw new Error('Ban duration should be at least 0ms.');
}

user.banned = {
duration: permanent ? -1 : duration,
expiresAt: permanent ? 0 : Date.now() + duration,
moderator: typeof moderator === 'object' ? moderator._id : moderator,
reason
};

await user.save();
await user.populate('banned.moderator').execPopulate();

this.uw.publish('user:ban', {
userID: user.id,
moderatorID: user.banned.moderator.id,
duration: user.banned.duration,
expiresAt: user.banned.expiresAt,
permanent
});

return user.banned;
}

async unban(userID, { moderator }) {
const { users } = this.uw;

const user = await users.getUser(userID);
if (!user) {
throw new Error('User not found.');
}
if (!user.banned) {
throw new Error(`User "${user.username}" is not banned.`);
}

await user.update({ banned: null });

this.uw.publish('user:unban', {
userID: `${user.id}`,
moderatorID: typeof moderator === 'object' ? `${moderator.id}` : moderator
});
}
}

export default function bans() {
return (uw) => {
uw.bans = new Bans(uw); // eslint-disable-line no-param-reassign
};
}

0 comments on commit 5d7c636

Please sign in to comment.