Sign media per user
This commit is contained in:
parent
8922ca1518
commit
387cef269a
@ -30,12 +30,13 @@ import {
|
|||||||
emitEvent,
|
emitEvent,
|
||||||
getPermission,
|
getPermission,
|
||||||
getRights,
|
getRights,
|
||||||
uploadFile,
|
uploadFile, Config, getUrlSignature,
|
||||||
} from "@spacebar/util";
|
} from "@spacebar/util";
|
||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import multer from "multer";
|
import multer from "multer";
|
||||||
import { handleMessage, postHandleMessage, route } from "../../../../../util";
|
import { handleMessage, postHandleMessage, route } from "../../../../../util";
|
||||||
|
import { URL } from "url";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
// TODO: message content/embed string length limit
|
// TODO: message content/embed string length limit
|
||||||
@ -244,7 +245,7 @@ router.put(
|
|||||||
console.error("[Message] post-message handler failed", e),
|
console.error("[Message] post-message handler failed", e),
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json(message);
|
return res.json(message.withSignedAttachments(req));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -17,14 +17,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Server, ServerOptions } from "lambert-server";
|
import { Server, ServerOptions } from "lambert-server";
|
||||||
import { Config, initDatabase, registerRoutes, Sentry } from "@spacebar/util";
|
import {
|
||||||
|
Attachment,
|
||||||
|
Config,
|
||||||
|
initDatabase,
|
||||||
|
registerRoutes,
|
||||||
|
Sentry,
|
||||||
|
} from "@spacebar/util";
|
||||||
|
import { CORS, BodyParser } from "@spacebar/api";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import avatarsRoute from "./routes/avatars";
|
import avatarsRoute from "./routes/avatars";
|
||||||
import guildProfilesRoute from "./routes/guild-profiles";
|
import guildProfilesRoute from "./routes/guild-profiles";
|
||||||
import iconsRoute from "./routes/role-icons";
|
import iconsRoute from "./routes/role-icons";
|
||||||
import { CORS } from "../api/middlewares/CORS";
|
|
||||||
import { BodyParser } from "../api/middlewares/BodyParser";
|
|
||||||
import morgan from "morgan";
|
import morgan from "morgan";
|
||||||
|
import { Like, Or } from "typeorm";
|
||||||
|
|
||||||
export type CDNServerOptions = ServerOptions;
|
export type CDNServerOptions = ServerOptions;
|
||||||
|
|
||||||
@ -38,6 +44,7 @@ export class CDNServer extends Server {
|
|||||||
async start() {
|
async start() {
|
||||||
await initDatabase();
|
await initDatabase();
|
||||||
await Config.init();
|
await Config.init();
|
||||||
|
await this.cleanupSignaturesInDb();
|
||||||
await Sentry.init(this.app);
|
await Sentry.init(this.app);
|
||||||
|
|
||||||
const logRequests = process.env["LOG_REQUESTS"] != undefined;
|
const logRequests = process.env["LOG_REQUESTS"] != undefined;
|
||||||
@ -124,4 +131,26 @@ export class CDNServer extends Server {
|
|||||||
async stop() {
|
async stop() {
|
||||||
return super.stop();
|
return super.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async cleanupSignaturesInDb() {
|
||||||
|
this.log("verbose", "[Server] Cleaning up signatures in database");
|
||||||
|
const attachmentsToFix = await Attachment.find({
|
||||||
|
where: { url: Like("%?ex=%") },
|
||||||
|
});
|
||||||
|
if (attachmentsToFix.length === 0) {
|
||||||
|
this.log("verbose", "[Server] No attachments to fix");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log(
|
||||||
|
"verbose",
|
||||||
|
`[Server] Found ${attachmentsToFix.length} attachments to fix`,
|
||||||
|
);
|
||||||
|
for (const attachment of attachmentsToFix) {
|
||||||
|
attachment.url = attachment.url.split("?ex=")[0];
|
||||||
|
attachment.proxy_url = attachment.proxy_url?.split("?ex=")[0];
|
||||||
|
await attachment.save();
|
||||||
|
this.log("verbose", `[Server] Fixed attachment ${attachment.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,12 +69,7 @@ router.post(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let finalUrl = `${endpoint}/${path}`;
|
const finalUrl = `${endpoint}/${path}`;
|
||||||
|
|
||||||
if (Config.get().security.cdnSignUrls) {
|
|
||||||
const signatureData = getUrlSignature(path, req);
|
|
||||||
finalUrl = `${finalUrl}?ex=${signatureData.expiresAt}&is=${signatureData.issuedAt}&hm=${signatureData.hash}&ip=${req.ip}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const file = {
|
const file = {
|
||||||
id,
|
id,
|
||||||
@ -82,6 +77,7 @@ router.post(
|
|||||||
filename: filename,
|
filename: filename,
|
||||||
size,
|
size,
|
||||||
url: finalUrl,
|
url: finalUrl,
|
||||||
|
path,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import { createHmac, timingSafeEqual } from "crypto";
|
|||||||
import ms, { StringValue } from "ms";
|
import ms, { StringValue } from "ms";
|
||||||
import { ParsedQs } from "qs";
|
import { ParsedQs } from "qs";
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
|
import attachments from "../cdn/routes/attachments";
|
||||||
|
|
||||||
export const getUrlSignature = (
|
export const getUrlSignature = (
|
||||||
path: string,
|
path: string,
|
||||||
|
|||||||
@ -28,6 +28,8 @@ import { URL } from "url";
|
|||||||
import { deleteFile } from "../util/cdn";
|
import { deleteFile } from "../util/cdn";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { dbEngine } from "../util/Database";
|
import { dbEngine } from "../util/Database";
|
||||||
|
import { Request } from "express";
|
||||||
|
import { resignUrl } from "../Signing";
|
||||||
|
|
||||||
@Entity({
|
@Entity({
|
||||||
name: "attachments",
|
name: "attachments",
|
||||||
@ -73,4 +75,11 @@ export class Attachment extends BaseClass {
|
|||||||
onDelete() {
|
onDelete() {
|
||||||
return deleteFile(new URL(this.url).pathname);
|
return deleteFile(new URL(this.url).pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signUrls(req: Request) {
|
||||||
|
return {
|
||||||
|
url: this.url + resignUrl(this.url, req),
|
||||||
|
proxy_url: this.proxy_url + resignUrl(this.proxy_url, req),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import { Webhook } from "./Webhook";
|
|||||||
import { Sticker } from "./Sticker";
|
import { Sticker } from "./Sticker";
|
||||||
import { Attachment } from "./Attachment";
|
import { Attachment } from "./Attachment";
|
||||||
import { dbEngine } from "../util/Database";
|
import { dbEngine } from "../util/Database";
|
||||||
|
import { Request } from "express";
|
||||||
|
|
||||||
export enum MessageType {
|
export enum MessageType {
|
||||||
DEFAULT = 0,
|
DEFAULT = 0,
|
||||||
@ -260,6 +261,15 @@ export class Message extends BaseClass {
|
|||||||
content: this.content ?? "",
|
content: this.content ?? "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withSignedAttachments(req: Request) {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
attachments: this.attachments?.map((attachment: Attachment) =>
|
||||||
|
attachment.signUrls(req)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageComponent {
|
export interface MessageComponent {
|
||||||
|
|||||||
Reference in New Issue
Block a user