Spaces:
Paused
Paused
| ; | |
| /** | |
| * Tests for Punishments. | |
| * | |
| * @author mia-pi-git | |
| * @author Annika | |
| */ | |
| const assert = require('../assert'); | |
| const { makeUser, makeConnection } = require('../users-utils'); | |
| const { Punishments } = require('../../dist/server/punishments'); | |
| const TEST_PUNISHMENT_DURATION = 1000; // 1 second | |
| describe("Punishments", () => { | |
| it("Should properly sort punishments by weight", () => { | |
| const list = [ | |
| { type: "LOCK", id: "User 1", expireTime: Date.now() + 1000, reason: '' }, | |
| { type: "SEMILOCK", id: "User 2", expireTime: Date.now() + 1000, reason: '' }, | |
| { type: "BAN", id: "", expireTime: Date.now() + 1000, reason: '' }, | |
| ]; | |
| Punishments.byWeight(list); | |
| assert.equal(list[0].type, 'BAN'); | |
| }); | |
| it("Should prevent a user from having two punishments of the same type", () => { | |
| Punishments.userids.add('banmeplease', { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: '' }); | |
| Punishments.userids.add("banmeplease", { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: 'ok' }); | |
| assert.equal(Punishments.userids.get('banmeplease').length, 1); | |
| }); | |
| it("Should overwrite the old reason when a user receives two of the same punishment", () => { | |
| Punishments.userids.add('banmeplease', { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: '' }); | |
| Punishments.userids.add("banmeplease", { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: 'ok' }); | |
| assert.equal(Punishments.userids.getByType('banmeplease', 'BAN').reason, 'ok'); | |
| }); | |
| it("Should properly filter out expiring punishments", () => { | |
| const punishments = [{ type: 'BAN', expireTime: Date.now() - 1000, id: 'banmeplease', reason: '' }]; | |
| Punishments.userids.removeExpiring(punishments); | |
| assert.equal(punishments.length, 0); | |
| }); | |
| it("Should be able to remove only one punishment from the list by passing an object", () => { | |
| const [expireTime, reason, id] = [Date.now() + 1000, '', 'banmeplease']; | |
| Punishments.userids.add(id, { type: 'BAN', expireTime, reason, id }); | |
| Punishments.userids.add(id, { type: 'RICKROLL', expireTime, reason, id }); | |
| Punishments.userids.deleteOne(id, { type: 'RICKROLL', expireTime, reason, id }); | |
| assert.equal(Punishments.userids.get(id).length, 1); | |
| }); | |
| it('should properly search for IP punishments by type', () => { | |
| const [expireTime, reason, id] = [Date.now() + 1000, '', 'banmeplease']; | |
| Punishments.ips.add('127.0.0.1', { type: 'BAN', expireTime, reason, id }); | |
| Punishments.ips.add('127.0.0.1', { type: 'RICKROLL', expireTime, reason, id }); | |
| Punishments.ips.add('127.0.*', { type: 'RANGEBAN', expireTime, reason, id }); | |
| const allIPPunishments = Punishments.ipSearch('127.0.0.1'); | |
| assert(Array.isArray(allIPPunishments)); | |
| assert.equal(allIPPunishments.length, 3); | |
| const ban = Punishments.ipSearch('127.0.0.1', 'BAN'); | |
| assert(!Array.isArray(ban)); | |
| assert.equal(ban.type, 'BAN'); | |
| const rickroll = Punishments.ipSearch('127.0.0.1', 'RICKROLL'); | |
| assert(!Array.isArray(rickroll)); | |
| assert.equal(rickroll.type, 'RICKROLL'); | |
| }); | |
| }); | |
| describe('broader, more integrated Punishments tests', function () { | |
| before(() => { | |
| this.room = Rooms.get('lobby'); | |
| this.parse = async function (message) { | |
| Chat.loadPlugins(); | |
| const context = new Chat.CommandContext({ | |
| message, | |
| room: this.room, | |
| user: this.user, | |
| connection: this.connection, | |
| }); | |
| return context.parse(); | |
| }; | |
| }); | |
| describe('room bans', () => { | |
| before(() => { | |
| this.user = makeUser("Roomban Me Please", '127.0.0.8'); | |
| this.connection = this.user.connections[0]; | |
| this.user.joinRoom(this.room.roomid, this.connection); | |
| }); | |
| beforeEach(async () => Punishments.roomBan(this.room, this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test')); | |
| afterEach(() => Punishments.roomUnban(this.room, this.user.id)); | |
| it('should force the user to leave the room and prevent them from rejoining', async () => { | |
| assert.equal(this.user.id in this.room.users, false, `user should not be in the room`); | |
| let joinAttempt = await this.user.tryJoinRoom(this.room, this.connection); | |
| assert.equal(joinAttempt, false, `user should be unable to join a room they are banned from`); | |
| Punishments.roomUnban(this.room, this.user.id); | |
| joinAttempt = await this.user.tryJoinRoom(this.room, this.connection); | |
| assert.equal(joinAttempt, true, `user should be able to join the room once they are unbanned`); | |
| }); | |
| it.skip('should expire on its own', done => { | |
| assert(Punishments.hasRoomPunishType(this.room, 'roombanmeplease', 'ROOMBAN'), `should be in effect`); | |
| setTimeout(() => { | |
| assert(!Punishments.hasRoomPunishType(this.room, 'roombanmeplease', 'ROOMBAN'), `should have expired`); | |
| done(); | |
| }, TEST_PUNISHMENT_DURATION); | |
| }); | |
| }); | |
| describe('locks (network) (slow)', () => { | |
| before(() => { | |
| this.user = makeUser("Lock Me Please", '127.0.0.3'); | |
| this.connection = this.user.connections[0]; | |
| this.user.joinRoom(this.room.roomid, this.connection); | |
| }); | |
| beforeEach(async () => Punishments.lock(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test')); | |
| afterEach(() => Punishments.unlock(this.user.id)); | |
| it('should prevent users from chatting in rooms while they are locked', async () => { | |
| const initialLogLength = this.room.log.log.length; | |
| await this.parse("Hi! I'm a locked user!"); | |
| assert.equal(this.room.log.log.length, initialLogLength, `user should be unable to sucessfully chat while locked`); | |
| Punishments.unlock(this.user.id); | |
| await this.parse("/msgroom lobby,Hi! I'm no longer locked!"); | |
| // we can't just check the roomlog length because unlocking adds a |n| message to | |
| const lastMessage = this.room.log.log.pop(); | |
| assert(lastMessage.endsWith(` Lock Me Please|Hi! I'm no longer locked!`), `user should have sucessfuly sent a message after being locked`); | |
| }); | |
| // This test relies on Chat#parse returning `false` when permission is denied. | |
| // I'm not sure if this is an intended feature, but the way Chat is currently implemented, | |
| // an `ErrorMessage` is the only time `false` will be returned by Chat#parse (unless a chat command returns it, which /msg does not). | |
| // If you are here because this test is failing, check if the above assumptions are still valid. | |
| // If they are not, the test should either be refactored to use another way of | |
| // determining whether a PM was sucessful (such as modifying Chat.sendPM), or skipped entirely. | |
| it('should prevent users from sending PMs other than to staff while they are locked', async () => { | |
| makeUser("Some Random Reg", '127.0.0.4'); | |
| makeUser("Annika", '127.0.0.5').tempGroup = '~'; | |
| let result = await this.parse("/msg Some Random Reg, Hi! I'm a locked user!"); | |
| assert.equal(result, false, `user should be unable to sucessfully send PMs while locked`); | |
| result = await this.parse("/msg Annika, Hi! I'm a locked user!"); | |
| assert.notEqual(result, false, `user should be able to send PMs to global staff while locked`); | |
| Punishments.unlock(this.user.id); | |
| result = await this.parse("/msg Annika, Hi! I'm a locked user!"); | |
| assert.notEqual(result, false, `user should be able to send PMs after being unlocked`); | |
| result = await this.parse("/msg Some Random Reg, Hi! I'm a locked user!"); | |
| assert.notEqual(result, false, `user should be able to send PMs after being unlocked`); | |
| }); | |
| // expiry tests are skipped because they fail when another test fails. | |
| // I don't know why this happens; I'm guessing it's an ideosycrasy of Mocha. | |
| it.skip('should expire on its own', done => { | |
| assert(this.user.locked); | |
| assert(Punishments.hasPunishType(this.user.id, 'LOCK')); | |
| setTimeout(() => { | |
| assert(!this.user.locked); | |
| assert(!Punishments.hasPunishType(this.user.id, 'LOCK')); | |
| done(); | |
| }, TEST_PUNISHMENT_DURATION); | |
| }); | |
| }); | |
| describe('namelocks (network) (slow)', () => { | |
| before(() => { | |
| this.user = makeUser("Namelock Me Please", '127.0.0.6'); | |
| this.connection = this.user.connections[0]; | |
| this.user.joinRoom(this.room.roomid, this.connection); | |
| }); | |
| beforeEach(async () => Punishments.namelock(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test')); | |
| afterEach(() => Punishments.unnamelock(this.user.id)); | |
| it('should prevent the user from having a username', async () => { | |
| assert(this.user.id.startsWith('guest')); | |
| await this.user.rename('some other name', '', false, this.connection); | |
| assert(this.user.id.startsWith('guest')); | |
| }); | |
| it.skip('should expire on its own', done => { | |
| assert(this.user.locked); | |
| assert(this.user.namelocked); | |
| assert(Punishments.hasPunishType('namelockmeplease', 'NAMELOCK')); | |
| setTimeout(() => { | |
| assert(!this.user.locked); | |
| assert(!this.user.namelocked); | |
| assert(!Punishments.hasPunishType('namelockmeplease', 'NAMELOCK')); | |
| done(); | |
| }, TEST_PUNISHMENT_DURATION); | |
| }); | |
| }); | |
| describe('global bans (network) (slow)', () => { | |
| before(() => { | |
| this.user = makeUser("Ban Me Please", '127.0.0.7'); | |
| this.connection = this.user.connections[0]; | |
| this.user.joinRoom(this.room.roomid, this.connection); | |
| }); | |
| beforeEach(async () => Punishments.ban(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test')); | |
| afterEach(() => Punishments.unban(this.user.id)); | |
| it('should disconnect the user and prevent them from reconnecting', () => { | |
| assert.equal(this.user.connected, false, `user should be disconnected`); | |
| const conn = makeConnection('127.0.0.7'); | |
| assert(Punishments.checkIpBanned(conn), `IP should be banned`); | |
| }); | |
| it.skip('should expire on its own', done => { | |
| assert(Punishments.checkIpBanned(makeConnection('127.0.0.7')), `IP should be banned`); | |
| assert(Punishments.hasPunishType('banmeplease', 'BAN')); | |
| setTimeout(() => { | |
| assert(!Punishments.checkIpBanned(makeConnection('127.0.0.7')), `IP should no longer be banned`); | |
| assert(!Punishments.hasPunishType('banmeplease', 'BAN')); | |
| done(); | |
| }, TEST_PUNISHMENT_DURATION); | |
| }); | |
| }); | |
| }); | |