Skip to content

Commit

Permalink
Switch permission checking to async
Browse files Browse the repository at this point in the history
  • Loading branch information
MaddyUnderStars committed Aug 27, 2024
1 parent d1ca6c7 commit 75f2f59
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/entity/DMChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class DMChannel extends Channel {
};
}

public checkPermission = (
public checkPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
) => {
Expand Down
8 changes: 4 additions & 4 deletions src/entity/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ export class Channel extends Actor {
return this.toPublic();
}

public throwPermission = (
public throwPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
) => {
// todo: which permision?
if (!this.checkPermission(user, permission))
if (!(await this.checkPermission(user, permission)))
throw new HttpError("Missing permission", 400);
return true;
};

public checkPermission = (
public checkPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
): boolean => false;
): Promise<boolean> => false;
}

export type PublicChannel = Pick<Channel, "id" | "name" | "domain">;
Expand Down
6 changes: 3 additions & 3 deletions src/entity/guild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ export class Guild extends Actor {
return this.toPublic();
}

public throwPermission = (
public throwPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
) => {
// todo: which permision?
if (!this.checkPermission(user, permission))
if (!(await this.checkPermission(user, permission)))
throw new HttpError("Missing permission", 400);
return true;
};

public checkPermission = (
public checkPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
) => checkPermission(user, this, permission);
Expand Down
2 changes: 1 addition & 1 deletion src/entity/textChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class GuildTextChannel extends Channel {
return this.toPublic();
}

public checkPermission = (
public checkPermission = async (
user: User,
permission: PERMISSION | PERMISSION[],
) => checkPermission(user, this.guild, permission);
Expand Down
38 changes: 16 additions & 22 deletions src/gateway/handlers/members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const onSubscribeMembers = makeHandler(async function (payload) {
const channel = await getChannel(payload.channel_id);
if (!channel) throw new Error("Channel does not exist");

channel.throwPermission(
await channel.throwPermission(
User.create({ id: this.user_id }),
PERMISSION.VIEW_CHANNEL,
);
Expand Down Expand Up @@ -97,27 +97,21 @@ export const onSubscribeMembers = makeHandler(async function (payload) {
const [role_members] = partition(members, (m) => m.role_id === role);

items.push(role);
items.push(
...role_members.reduce<{ id: string; name: string }[]>(
(ret, member) => {
if (
true
// channel.checkPermission(
// User.create({ id: member.user_id }),
// PERMISSION.VIEW_CHANNEL,
// )
) {
listenRangeEvent(this, member.member_id);
ret.push({
id: member.user_id,
name: member.name,
});
}
return ret;
},
[],
),
);

for (const member of role_members) {
if (
await channel.checkPermission(
User.create({ id: member.user_id }),
PERMISSION.VIEW_CHANNEL,
)
) {
listenRangeEvent(this, member.member_id);
items.push({
id: member.user_id,
name: member.name,
});
}
}
}

// Subscribe to their changes
Expand Down
2 changes: 1 addition & 1 deletion src/http/api/channel/#id/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ router.post(
async (req, res) => {
const channel = await getOrFetchChannel(req.params.channel_id);

channel.throwPermission(req.user, PERMISSION.CALL_CHANNEL);
await channel.throwPermission(req.user, PERMISSION.CALL_CHANNEL);

// If this channel is remote, we have to request the token from them
// It'll be delivered to our inbox, and we can send it to the client over gateway
Expand Down
4 changes: 2 additions & 2 deletions src/http/api/channel/#id/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ router.get(
async (req, res) => {
const channel = await getOrFetchChannel(req.params.channel_id);

channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);
await channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);

return res.json(channel.toPublic());
},
Expand All @@ -45,7 +45,7 @@ router.patch(

const channel = await getOrFetchChannel(req.params.channel_id);

channel.throwPermission(req.user, PERMISSION.MANAGE_CHANNELS);
await channel.throwPermission(req.user, PERMISSION.MANAGE_CHANNELS);

if (channel.domain === config.federation.webapp_url.hostname) {
// This is a local channel
Expand Down
2 changes: 1 addition & 1 deletion src/http/api/channel/#id/messages/#id/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ router.get(
async (req, res) => {
const channel = await getOrFetchChannel(req.params.channel_id);

channel.throwPermission(req.user, [PERMISSION.VIEW_CHANNEL]);
await channel.throwPermission(req.user, [PERMISSION.VIEW_CHANNEL]);

// TODO: fetch remote messages

Expand Down
4 changes: 2 additions & 2 deletions src/http/api/channel/#id/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ router.post(

const channel = await getOrFetchChannel(channel_id);

channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);
await channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);

const message = Message.create({
channel,
Expand Down Expand Up @@ -59,7 +59,7 @@ router.get(
async (req, res) => {
const channel = await getOrFetchChannel(req.params.channel_id);

channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);
await channel.throwPermission(req.user, PERMISSION.VIEW_CHANNEL);

// TODO: handle not fetched federated channels

Expand Down
2 changes: 1 addition & 1 deletion src/util/activitypub/inbox/handlers/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const CreateAtChannel = async (activity: APActivity, target: Channel) => {

const message = await buildMessageFromAPNote(inner, target);

target.throwPermission(message.author, [
await target.throwPermission(message.author, [
PERMISSION.VIEW_CHANNEL,
PERMISSION.SEND_MESSAGES,
]);
Expand Down
2 changes: 1 addition & 1 deletion src/util/activitypub/inbox/handlers/join.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const JoinActivityHandler: ActivityHandler = async (

const user = await getOrFetchUser(activity.actor);

target.throwPermission(user, [
await target.throwPermission(user, [
PERMISSION.VIEW_CHANNEL,
PERMISSION.CALL_CHANNEL,
]);
Expand Down
6 changes: 3 additions & 3 deletions src/util/entity/guild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export const createGuildFromRemoteOrg = async (lookup: string | APActor) => {

await guild.save();

const channels = (await Promise.all([
const channels = await Promise.all([
...(
await resolveCollectionEntries(new URL(obj.following.toString()))
).reduce(
Expand All @@ -260,9 +260,9 @@ export const createGuildFromRemoteOrg = async (lookup: string | APActor) => {
},
[] as Array<Promise<Channel>>,
),
])) as GuildTextChannel[];
]);

guild.channels = channels;
guild.channels = channels as GuildTextChannel[];
await guild.save();

const roles = await Promise.all([
Expand Down
49 changes: 44 additions & 5 deletions src/util/permission.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Permissions regarding actions within a channel.

import type { Guild, User } from "../entity";
import { type Guild, Member, Role, type User } from "../entity";
import { getDatabase } from "./database";

// Stored within the role or channel overwrites
export enum PERMISSION {
Expand All @@ -27,7 +28,7 @@ export const DefaultPermissions: PERMISSION[] = [
PERMISSION.CREATE_INVITE,
];

export const checkPermission = (
export const checkPermission = async (
user: User,
guild: Guild,
permission: PERMISSION | PERMISSION[],
Expand All @@ -36,9 +37,47 @@ export const checkPermission = (

if (guild.owner.id === user.id) return true;

const roles = guild.roles
// every role our user is a member of
.filter((x) => x.members.find((x) => x.user.id === user.id));
// const roles = guild.roles
// // every role our user is a member of
// .filter((x) => x.members.find((x) => x.user.id === user.id))
// .sort((a, b) => a.position - b.position);

/*
const roles = (
await Role.find({
where: {
members: {
user: {
id: user.id,
},
},
guild: {
id: guild.id,
},
},
})
).sort((a, b) => a.position - b.position);
*/

// TODO: making this function async may have consequences
const roles = (
await getDatabase()
.getRepository(Role)
.createQueryBuilder("roles")
.leftJoin("roles.members", "members")
.where("roles.guildId = :guild_id", { guild_id: guild.id })
.andWhere((qb) => {
const sub = qb
.subQuery()
.select("id")
.from(Member, "members")
.where("members.userId = :user_id", { user_id: user.id })
.getQuery();

qb.where(`roles_members.guildMembersId in ${sub}`);
})
.getMany()
).sort((a, b) => a.position - b.position);

let allowed = false;
// for every role in order
Expand Down
4 changes: 2 additions & 2 deletions src/util/voice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ export const validateMediaToken = (
if (!channel) return reject(INVALID_TOKEN);

if (
!channel.checkPermission(user, [
!(await channel.checkPermission(user, [
PERMISSION.CALL_CHANNEL,
PERMISSION.VIEW_CHANNEL,
])
]))
)
return reject(INVALID_TOKEN);

Expand Down

0 comments on commit 75f2f59

Please sign in to comment.