Files
Fabric.Backend.Guild/src/canvas/canvas.controller.ts
hzhang 58badf328c feat(guild): file upload/retention + channel canvas
Files:
- StoredFile entity + FilesModule: multipart upload (configurable
  FABRIC_BACKEND_GUILD_FILE_MAX_BYTES, default 100MB; no type limit),
  authenticated download (Bearer or ?access_token=), hourly + on-boot
  retention sweep (FABRIC_BACKEND_GUILD_FILE_TTL_DAYS, default 7).
- ApiKeyGuard also accepts ?access_token= (browser <img>/<a>).

Canvas:
- ChannelCanvas entity (one active per channel) + CanvasModule:
  GET / PUT|POST (share-replace, caller becomes sharer) /
  PATCH (sharer-only in-place update, version++) / DELETE (sharer-only).
  Emits canvas.updated / canvas.removed to the channel room.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:17:02 +01:00

59 lines
1.3 KiB
TypeScript

import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
Patch,
Req,
UnauthorizedException,
} from '@nestjs/common';
import { CanvasService } from './canvas.service.js';
type AuthedRequest = { userId?: string };
type CanvasBody = { title?: string; format?: string; source?: string };
@Controller('channels/:id/canvas')
export class CanvasController {
constructor(private readonly canvas: CanvasService) {}
private uid(req: AuthedRequest): string {
const userId = req.userId ?? '';
if (!userId) throw new UnauthorizedException('missing user');
return userId;
}
@Get()
get(@Req() req: AuthedRequest, @Param('id') channelId: string) {
return this.canvas.get(channelId, this.uid(req));
}
// share / replace (caller becomes the sharer)
@Put()
@Post()
share(
@Req() req: AuthedRequest,
@Param('id') channelId: string,
@Body() body: CanvasBody,
) {
return this.canvas.share(channelId, this.uid(req), body ?? {});
}
// update in place (original sharer only)
@Patch()
update(
@Req() req: AuthedRequest,
@Param('id') channelId: string,
@Body() body: CanvasBody,
) {
return this.canvas.update(channelId, this.uid(req), body ?? {});
}
@Delete()
remove(@Req() req: AuthedRequest, @Param('id') channelId: string) {
return this.canvas.remove(channelId, this.uid(req));
}
}