1
0
mirror of https://github.com/spacebarchat/server.git synced 2024-11-06 02:42:37 +01:00

Merge branch 'feat/multiUploads' into feat/latestWebClient

This commit is contained in:
Madeline 2022-07-09 14:16:50 +10:00
commit e28ae77597
No known key found for this signature in database
GPG Key ID: 1958E017C36F2E47
5 changed files with 97 additions and 69 deletions

View File

@ -2,12 +2,18 @@
"MessageCreateSchema": { "MessageCreateSchema": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": {
"type": "integer"
},
"content": { "content": {
"type": "string" "type": "string"
}, },
"nonce": { "nonce": {
"type": "string" "type": "string"
}, },
"channel_id": {
"type": "string"
},
"tts": { "tts": {
"type": "boolean" "type": "boolean"
}, },

View File

@ -46,12 +46,14 @@ export default function rateLimit(opts: {
}): any { }): any {
return async (req: Request, res: Response, next: NextFunction): Promise<any> => { return async (req: Request, res: Response, next: NextFunction): Promise<any> => {
// exempt user? if so, immediately short circuit // exempt user? if so, immediately short circuit
const rights = await getRights(req.user_id); if (req.user_id) {
if (rights.has("BYPASS_RATE_LIMITS")) return; const rights = await getRights(req.user_id);
if (rights.has("BYPASS_RATE_LIMITS")) return;
}
const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, ""); const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
var executor_id = getIpAdress(req); var executor_id = getIpAdress(req);
if (!opts.onlyIp && req.user_id) executor_id = req.user_id; if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
var max_hits = opts.count; var max_hits = opts.count;
if (opts.bot && req.user_bot) max_hits = opts.bot; if (opts.bot && req.user_bot) max_hits = opts.bot;
@ -161,7 +163,7 @@ export async function initRateLimits(app: Router) {
app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register })); app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
} }
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number }) { async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number; }) {
const id = opts.executor_id + opts.bucket_id; const id = opts.executor_id + opts.bucket_id;
var limit = Cache.get(id); var limit = Cache.get(id);
if (!limit) { if (!limit) {

View File

@ -17,7 +17,7 @@ import {
} from "@fosscord/util"; } from "@fosscord/util";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { handleMessage, postHandleMessage, route } from "@fosscord/api"; import { handleMessage, postHandleMessage, route } from "@fosscord/api";
import multer from "multer"; import multer, { Multer } from "multer";
import { FindManyOptions, LessThan, MoreThan } from "typeorm"; import { FindManyOptions, LessThan, MoreThan } from "typeorm";
import { URL } from "url"; import { URL } from "url";
@ -50,8 +50,10 @@ export function isTextChannel(type: ChannelType): boolean {
} }
export interface MessageCreateSchema { export interface MessageCreateSchema {
type?: number;
content?: string; content?: string;
nonce?: string; nonce?: string;
channel_id?: string;
tts?: boolean; tts?: boolean;
flags?: string; flags?: string;
embeds?: Embed[]; embeds?: Embed[];
@ -161,7 +163,7 @@ const messageUpload = multer({
limits: { limits: {
fileSize: 1024 * 1024 * 100, fileSize: 1024 * 1024 * 100,
fields: 10, fields: 10,
files: 1 // files: 1
}, },
storage: multer.memoryStorage() storage: multer.memoryStorage()
}); // max upload 50 mb }); // max upload 50 mb
@ -176,7 +178,7 @@ const messageUpload = multer({
// Send message // Send message
router.post( router.post(
"/", "/",
messageUpload.single("file"), messageUpload.any(),
async (req, res, next) => { async (req, res, next) => {
if (req.body.payload_json) { if (req.body.payload_json) {
req.body = JSON.parse(req.body.payload_json); req.body = JSON.parse(req.body.payload_json);
@ -190,19 +192,22 @@ router.post(
var body = req.body as MessageCreateSchema; var body = req.body as MessageCreateSchema;
const attachments: Attachment[] = []; const attachments: Attachment[] = [];
if (req.file) {
try {
const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
attachments.push({ ...file, proxy_url: file.url });
} catch (error) {
return res.status(400).json(error);
}
}
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] }); const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
if (!channel.isWritable()) { if (!channel.isWritable()) {
throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400) throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400)
} }
const files = req.files as Express.Multer.File[] ?? [];
for (var currFile of files) {
try {
const file = await uploadFile(`/attachments/${channel.id}`, currFile);
attachments.push({ ...file, proxy_url: file.url });
}
catch (error) {
return res.status(400).json(error);
}
}
const embeds = body.embeds || []; const embeds = body.embeds || [];
if (body.embed) embeds.push(body.embed); if (body.embed) embeds.push(body.embed);
let message = await handleMessage({ let message = await handleMessage({

View File

@ -0,0 +1,68 @@
import { Router, Request, Response } from "express";
import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile } from "@fosscord/util";
import { route } from "@fosscord/api";
import { HTTPError } from "lambert-server";
import { RoleModifySchema } from "../";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id, role_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id);
const role = await Role.findOneOrFail({ guild_id, id: role_id });
return res.json(role);
});
router.delete("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { guild_id, role_id } = req.params;
if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
await Promise.all([
Role.delete({
id: role_id,
guild_id: guild_id
}),
emitEvent({
event: "GUILD_ROLE_DELETE",
guild_id,
data: {
guild_id,
role_id
}
} as GuildRoleDeleteEvent)
]);
res.sendStatus(204);
});
// TODO: check role hierarchy
router.patch("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { role_id, guild_id } = req.params;
const body = req.body as RoleModifySchema;
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
const role = new Role({
...body,
id: role_id,
guild_id,
permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0"))
});
await Promise.all([
role.save(),
emitEvent({
event: "GUILD_ROLE_UPDATE",
guild_id,
data: {
guild_id,
role
}
} as GuildRoleUpdateEvent)
]);
res.json(role);
});
export default router;

View File

@ -81,59 +81,6 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
res.json(role); res.json(role);
}); });
router.delete("/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const guild_id = req.params.guild_id;
const { role_id } = req.params;
if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
await Promise.all([
Role.delete({
id: role_id,
guild_id: guild_id
}),
emitEvent({
event: "GUILD_ROLE_DELETE",
guild_id,
data: {
guild_id,
role_id
}
} as GuildRoleDeleteEvent)
]);
res.sendStatus(204);
});
// TODO: check role hierarchy
router.patch("/:role_id", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { role_id, guild_id } = req.params;
const body = req.body as RoleModifySchema;
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
const role = new Role({
...body,
id: role_id,
guild_id,
permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0"))
});
await Promise.all([
role.save(),
emitEvent({
event: "GUILD_ROLE_UPDATE",
guild_id,
data: {
guild_id,
role
}
} as GuildRoleUpdateEvent)
]);
res.json(role);
});
router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Request, res: Response) => { router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Request, res: Response) => {
const { guild_id } = req.params; const { guild_id } = req.params;
const body = req.body as RolePositionUpdateSchema; const body = req.body as RolePositionUpdateSchema;