Test: Roles.isHigher

This commit is contained in:
ADAMJR 2021-10-05 19:20:46 +01:00
parent a788e4b3ae
commit b21d2f8ff6
8 changed files with 79 additions and 32 deletions

View File

@ -17,17 +17,27 @@ export default class Roles extends DBWrapper<string, RoleDocument> {
return await Role.findOne({ guildId, name: '@everyone' }) as RoleDocument;
}
// TODO: test
public async isHigher(guild: Entity.Guild, selfMember: Entity.GuildMember, theirRoleIds: string[]) {
const guildRoles = await Role.find({ guildId: guild.id });
const [myRoles, theirRoles] = await Promise.all([
Role.find({ _id: { $in: selfMember.roleIds } }),
Role.find({ _id: { $in: theirRoleIds } }),
]);
const max = (key: string) => (max, val) => (max > val[key]) ? max : val[key];
const highestRole: Entity.Role = guildRoles.reduce(max('position'));
const myHighestRole: Entity.Role = myRoles.reduce(max('position'));
const theirHighestRole: Entity.Role = theirRoles.reduce(max('position'));
return selfMember.userId === guild.ownerId
|| (selfMember.roleIds.includes(highestRole.id)
&& !theirRoleIds.includes(highestRole.id));
const selfIsOwner = selfMember.userId === guild.ownerId;
const selfHasHigherRole = myHighestRole.position >= theirHighestRole.position;
console.log('isOwner', selfMember.userId);
console.log('isOwner', guild.ownerId);
console.log('selfHasHigherRole', selfHasHigherRole);
return !selfIsOwner && !selfHasHigherRole;
}
public async hasPermission(guild: Entity.Guild, member: Entity.GuildMember, permission: PermissionTypes.Permission) {
public async hasPermission(guild: Entity.Guild, member: Entity.GuildMember, permission: PermissionTypes.Permission | string) {
const guildRoles = await Role.find({ guildId: guild.id });
const totalPerms = guildRoles
.filter(r => member.roleIds.includes(r.id))

View File

@ -6,7 +6,6 @@ import { WSEvent, } from './ws-event';
import { WS } from '../../types/ws';
import Roles from '../../data/roles';
import Guilds from '../../data/guilds';
import { Guild } from '../../data/models/guild';
import GuildMembers from '../../data/guild-members';
export default class implements WSEvent<'GUILD_ROLE_UPDATE'> {

View File

@ -0,0 +1,40 @@
import { expect } from 'chai';
import { GuildDocument } from '../../../src/data/models/guild';
import { GuildMember, GuildMemberDocument } from '../../../src/data/models/guild-member';
import { Role, RoleDocument } from '../../../src/data/models/role';
import Roles from '../../../src/data/roles';
import { Mock } from '../../mock/mock';
describe('data/roles', () => {
let roles: Roles;
let guild: GuildDocument;
let noobMember: GuildMemberDocument;
let everyoneRole: RoleDocument;
beforeEach(async () => {
roles = new Roles();
guild = await Mock.guild();
noobMember = (await GuildMember.find({ guildId: guild.id }))![1];
everyoneRole = await Role.findOne({ guildId: guild.id });
});
afterEach(() => Mock.cleanDB());
it('isHigher: is noob, same level role, returns false', async () => {
const result = await roles.isHigher(guild, noobMember, [everyoneRole.id]);
expect(result).to.be.false;
});
it('isHigher: is owner, not highest role, returns false', async () => {
await Mock.role(guild);
const ownerMember = await GuildMember.findOne({ guildId: guild.id, userId: guild.ownerId });
const result = await roles.isHigher(guild, ownerMember, [everyoneRole.id]);
expect(result).to.be.false;
});
it('isHigher: is noob, not highest role, returns true', async () => {
const higherRole = await Mock.role(guild);
const result = await roles.isHigher(guild, noobMember, [higherRole.id]);
expect(result).to.be.true;
});
});

View File

@ -17,16 +17,13 @@ describe.only('ws-guard', () => {
let guard: WSGuard;
let guild: GuildDocument;
let ownerMember: GuildMemberDocument;
let noobMember: GuildMemberDocument;
let ownerUser: SelfUserDocument;
let noobUser: SelfUserDocument;
let everyoneRole: RoleDocument;
let ws: WebSocket;
let textChannel: ChannelDocument;
beforeEach(async () => {
({ ws, guild, ownerUser, noobUser, noobMember, ownerMember, everyoneRole, textChannel } = await Mock.defaultSetup(client));
({ ws, guild, ownerUser, everyoneRole, textChannel } = await Mock.defaultSetup(client));
guard = Deps.get<WSGuard>(WSGuard);
});

View File

@ -58,7 +58,8 @@ console.log(`${space(48 * 3)}TESTS${space(54 * 2)}`.bgWhite.black);
// import('./integration/ws/message-delete.tests'); // fail
// import('./integration/ws/ready.tests');
// import('./integration/ws/user-update.tests');
import('./integration/ws/ws-guard.tests'); // fail
// import('./integration/ws/ws-guard.tests');
import('./integration/data/roles.tests');
// import('./unit/models/app.tests');
// import('./unit/models/channel.tests');
@ -68,7 +69,6 @@ console.log(`${space(48 * 3)}TESTS${space(54 * 2)}`.bgWhite.black);
// import('./unit/models/message.tests');
// import('./unit/models/role.tests');
// import('./unit/models/user.tests');
// import('./unit/snowflake-entity.tests');
// import('./unit/ws/ws-cooldowns.tests');
})();

View File

@ -37,7 +37,9 @@ const GuildDropdown: React.FunctionComponent = () => {
icon={faPlusCircle} />
</a>
)}
{perms.can('MANAGE_GUILD', guild.id) && (
{(perms.can('MANAGE_GUILD', guild.id)
|| perms.can('MANAGE_ROLES', guild.id)
|| perms.can('MANAGE_INVITES', guild.id)) && (
<a onClick={() => dispatch(ui.openedModal('GuildSettings'))}
className="rounded-sm flex items-center justify-between p-2 h-8 text-sm">
<span className="font">Guild settings</span>

View File

@ -5,17 +5,17 @@ import { getMember, getSelfMember } from '../store/members';
// FIXME: import this namespace from types
export namespace PermissionTypes {
export enum General {
MANAGE_INVITES = 2048,
VIEW_CHANNELS = 1024,
// MANAGE_NICKNAMES = 512,
// CHANGE_NICKNAME = 256,
// MANAGE_NICKNAMES = 512, // change number
// CHANGE_NICKNAME = 256, // change number
MANAGE_INVITES = 256,
CREATE_INVITE = 128,
KICK_MEMBERS = 64,
// BAN_MEMBERS = 32,
// BAN_MEMBERS = 32, // change number
MANAGE_CHANNELS = 16,
MANAGE_ROLES = 8,
MANAGE_GUILD = 4,
// VIEW_AUDIT_LOG = 2,
// VIEW_AUDIT_LOG = 2, // change number
ADMINISTRATOR = 1,
}
export enum Text {
@ -54,8 +54,9 @@ export class PermService {
'KICK_MEMBERS': 'Ability to kick members from this guild.',
'MANAGE_CHANNELS': 'Ability to create, edit, or delete channels.',
'MANAGE_GUILD': `Ability to edit general guild settings.`,
'MANAGE_ROLES': 'Ability to manage guild roles.',
'MANAGE_ROLES': 'Ability to create, update, and delete guild roles.',
'VIEW_CHANNELS': 'Ability to view channels.',
'MANAGE_INVITES': 'Ability to delete invites.',
},
text: {
'MANAGE_MESSAGES': `Ability to manage message other member's messages.`,

View File

@ -2,17 +2,17 @@
export namespace PermissionTypes {
export enum General {
MANAGE_INVITES = 2048,
VIEW_CHANNELS = 1024,
// MANAGE_NICKNAMES = 512,
// CHANGE_NICKNAME = 256,
// MANAGE_NICKNAMES = 512, // change number
// CHANGE_NICKNAME = 256, // change number
MANAGE_INVITES = 256,
CREATE_INVITE = 128,
KICK_MEMBERS = 64,
// BAN_MEMBERS = 32,
// BAN_MEMBERS = 32, // change number
MANAGE_CHANNELS = 16,
MANAGE_ROLES = 8,
MANAGE_GUILD = 4,
// VIEW_AUDIT_LOG = 2,
// VIEW_AUDIT_LOG = 2, // change number
ADMINISTRATOR = 1,
}
export enum Text {
@ -23,8 +23,8 @@ export namespace PermissionTypes {
SEND_MESSAGES = 2048,
}
export enum Voice {
// MOVE_MEMBERS = 32768 * 8,
// MUTE_MEMBERS = 32768 * 4,
MOVE_MEMBERS = 32768 * 8,
MUTE_MEMBERS = 32768 * 4,
SPEAK = 32768 * 2,
CONNECT = 32768,
}
@ -42,13 +42,11 @@ export namespace PermissionTypes {
| PermissionTypes.Text.SEND_MESSAGES
| PermissionTypes.Text.READ_MESSAGES
// | PermissionTypes.Text.ADD_REACTIONS
// | PermissionTypes.Voice.CONNECT
// | PermissionTypes.Voice.SPEAK;
| PermissionTypes.Voice.CONNECT
| PermissionTypes.Voice.SPEAK;
}
export function getPermString(integer: number | string): string {
console.log('integer', integer);
export function getPermString(integer: number | string): string {
return (typeof integer === 'string')
? Object
.entries(PermissionTypes.All)