add image router

This commit is contained in:
TopchetoEU 2023-06-27 06:55:56 +03:00
parent 21bcf5c5ac
commit 2b79aff2c7
No known key found for this signature in database
GPG Key ID: 24E57B2E9C61AD19
7 changed files with 97 additions and 18 deletions

16
src/models/Image.ts Normal file
View File

@ -0,0 +1,16 @@
import { UUID } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
export enum Visibility {
Public,
Unlisted,
Private,
}
export default interface Image {
_id: UUID;
backingURL: string;
name: string;
visibility: Visibility;
created: Date;
author: UUID;
}

View File

@ -0,0 +1,38 @@
import { Collection } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
import { UUID } from "https://deno.land/x/web_bson@v0.3.0/mod.js";
import { auth, jwt, rest, schema, uuid } from "../server/decorators.ts";
import { JWTPayload } from "../utils/JWT.ts";
import AppRouter from "./AppRouter.ts";
import HttpError from "../server/HttpError.ts";
import User from "../models/User.ts";
import Image, { Visibility } from "../models/Image.ts";
export default class ImageRouter extends AppRouter {
public static serialize(image: Image) {
return {
author: image.author,
created: image.created.getTime() / 1000,
name: image.name,
visibility: image.visibility,
id: image._id,
};
}
@rest('GET', '/')
async get(@uuid() @schema('string') id: string, @jwt(v => v.salt, false) @auth() jwt?: JWTPayload) {
const image = await this.images.findOne({ _id: new UUID(id) });
if (
!image ||
image.visibility === Visibility.Private && image.author !== jwt?.name
) throw new HttpError("Image doesn't exist.");
return ImageRouter.serialize(image);
}
public constructor(private salt: string, private images: Collection<Image>, private users: Collection<User>) {
super();
users.createIndexes({ indexes: [ { key: { username: 1 }, name: 'Username Index' } ] });
}
}

View File

@ -1,20 +1,28 @@
import { Collection } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
import { Database } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
import UserRouter from "../routers/UserRouter.ts";
import User from "../models/User.ts";
import Response from "../server/RestResponse.ts";
import Router from "../server/Router.ts";
import ImageRouter from "./ImageRouter.ts";
import AppRouter from "./AppRouter.ts";
import RestResponse from "../server/RestResponse.ts";
import { rest, route } from "../server/decorators.ts";
import User from "../models/User.ts";
import Image from "../models/Image.ts";
export class RootRouter extends Router {
export class RootRouter extends AppRouter {
@route('users/*') users;
@route('images/*') images;
@rest('*', '*')
default() {
return new Response().body(new Blob(['Page not found :/'])).status(404);
return new RestResponse().body(new Blob(['Page not found :/'])).status(404);
}
constructor(salt: string, users: Collection<User>) {
constructor(salt: string, db: Database) {
super();
const users = db.collection<User>('users');
const images = db.collection<Image>('images');
this.users = new UserRouter(salt, users);
this.images = new ImageRouter(salt, images, users);
}
}

View File

@ -66,7 +66,7 @@ export default class UserRouter extends AppRouter {
) {
const res = await this.users.findOne({ username: body.username });
if (!res) throw new HttpError('Incorrect username or password.');
const hashed = await bcrypt.hash(res.password, this.salt);
const hashed = await bcrypt.hash(body.password, this.salt);
if (res.password !== hashed) throw new HttpError('Incorrect username or password.');

View File

@ -3,5 +3,7 @@ import rest from "./decorators/rest.ts";
import auth from "./decorators/auth.ts";
import route from "./decorators/route.ts";
import schema from "./decorators/schema.ts";
import jwt from "./decorators/jwt.ts";
import uuid from "./decorators/uuid.ts";
export { body, schema, rest, route, auth };
export { body, schema, rest, route, auth , jwt, uuid };

View File

@ -0,0 +1,14 @@
import { UUID } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
import { makeParameterModifier } from "../Router.ts";
import HttpError from "../HttpError.ts";
export default function uuid() {
return makeParameterModifier((_req, val) => {
try {
return new UUID(val);
}
catch {
throw new HttpError("Invalid UUID given.");
}
});
}

View File

@ -2,12 +2,12 @@ const undefinedBuff = new Blob([new TextEncoder().encode('undefined')]);
const nullBuff = new Blob([new TextEncoder().encode('null')]);
export default async function serialize(val: unknown, depth = 16): Promise<Blob> {
while(true) {
if(depth <= 0) throw new Error("Call depth exceeded limit.");
while (true) {
if (depth <= 0) throw new Error("Call depth exceeded limit.");
if(val instanceof Promise) val = await val;
else if(val instanceof Function) {
if(val.length !== 0) throw new Error('Can\'t serialize an argument-accepting function');
if (val instanceof Promise) val = await val;
else if (val instanceof Function) {
if (val.length !== 0) throw new Error('Can\'t serialize an argument-accepting function');
val = val();
}
else break;
@ -15,11 +15,12 @@ export default async function serialize(val: unknown, depth = 16): Promise<Blob>
depth--;
}
if(val === undefined) return undefinedBuff;
if(val === null) return nullBuff;
if(val instanceof Blob) return val;
if (val === undefined) return undefinedBuff;
if (val === null) return nullBuff;
if (typeof val === 'string') return new Blob([val]);
if (val instanceof Blob) return val;
while(typeof val !== 'string' && val && val.toString !== Object.prototype.toString && val.toString instanceof Function) {
if (val.toString !== Object.prototype.toString && val.toString instanceof Function) {
val = val.toString();
}