refactor: some minor changes
This commit is contained in:
parent
cd04773504
commit
d8cec0bc2d
15
src/AppDatabase.ts
Normal file
15
src/AppDatabase.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Collection, Database } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
|
||||
import Image from "./models/Image.ts";
|
||||
import User from "./models/User.ts";
|
||||
|
||||
export default class AppDatabase {
|
||||
public readonly db: Database;
|
||||
public readonly users: Collection<User>;
|
||||
public readonly images: Collection<Image>;
|
||||
|
||||
public constructor(db: Database) {
|
||||
this.db = db;
|
||||
this.users = db.collection('users');
|
||||
this.images = db.collection('images');
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { MongoClient } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
|
||||
import { RootRouter } from "./routers/RootRouter.ts";
|
||||
import * as bcrypt from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";
|
||||
import AppDatabase from "./AppDatabase.ts";
|
||||
|
||||
export default async function clonegur() {
|
||||
let salt;
|
||||
@ -17,7 +18,7 @@ export default async function clonegur() {
|
||||
db: 'clonegur',
|
||||
servers: [ { host: '127.0.0.1', port: 27017 } ]
|
||||
});
|
||||
await new RootRouter(salt, db).attach(Deno.listen({ port: 4000, hostname: 'localhost' }));
|
||||
return new RootRouter(salt, new AppDatabase(db));
|
||||
}
|
||||
|
||||
await clonegur();
|
||||
(await clonegur()).attach(Deno.listen({ port: 4000, hostname: 'localhost' }));
|
||||
|
@ -1,16 +1,15 @@
|
||||
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, body, headers, jwt, page, rest, schema } 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";
|
||||
import { Page } from "../server/decorators/page.ts";
|
||||
import { Headers } from "../server/RestRequest.ts";
|
||||
import { convert } from "../server/decorators/schema.ts";
|
||||
import { now } from "../utils/utils.ts";
|
||||
import AppDatabase from "../AppDatabase.ts";
|
||||
|
||||
export default class ImageRouter extends AppRouter {
|
||||
public static deserialize(image: Image) {
|
||||
@ -25,7 +24,7 @@ export default class ImageRouter extends AppRouter {
|
||||
|
||||
@rest('GET', '/')
|
||||
async get(@schema('uuid') id: UUID, @jwt(v => v.salt, false) @auth() jwt?: JWTPayload) {
|
||||
const image = await this.images.findOne({ _id: new UUID(id) });
|
||||
const image = await this.db.images.findOne({ _id: new UUID(id) });
|
||||
|
||||
if (
|
||||
!image ||
|
||||
@ -36,14 +35,14 @@ export default class ImageRouter extends AppRouter {
|
||||
}
|
||||
@rest('GET', '/feed')
|
||||
async self(@page() page: Page) {
|
||||
const res = await page.apply(this.images.find({})).toArray();
|
||||
const res = await page.apply(this.db.images.find({})).toArray();
|
||||
if (!res) throw new HttpError('User not found.');
|
||||
return res.map(v => ImageRouter.deserialize(v));
|
||||
}
|
||||
|
||||
@rest('POST', '/upload')
|
||||
async upload(@body() body: Blob, @headers() headers: Headers, @jwt(v => v.salt, true) @auth() jwt: JWTPayload) {
|
||||
const user = await this.users.findOne({ username: jwt.name });
|
||||
const user = await this.db.users.findOne({ username: jwt.name });
|
||||
if (!user) throw new HttpError("You don't exist.");
|
||||
|
||||
// Parse body
|
||||
@ -89,8 +88,8 @@ export default class ImageRouter extends AppRouter {
|
||||
|
||||
// Write to DB
|
||||
try {
|
||||
await this.images.insertOne(img);
|
||||
await this.users.updateOne({ username: user.username }, { $push: { images: img._id } });
|
||||
await this.db.images.insertOne(img);
|
||||
await this.db.users.updateOne({ username: user.username }, { $push: { images: img._id } });
|
||||
return ImageRouter.deserialize(img);
|
||||
}
|
||||
catch (e) {
|
||||
@ -101,18 +100,18 @@ export default class ImageRouter extends AppRouter {
|
||||
@rest('POST', '/change')
|
||||
async change(@body() raw: unknown, @jwt(v => v.salt, true) @auth() jwt: JWTPayload) {
|
||||
const body = await convert(raw, { id: 'uuid', name: 'string?', visibility: 'number?' });
|
||||
const user = await this.users.findOne({ username: jwt.name });
|
||||
const user = await this.db.users.findOne({ username: jwt.name });
|
||||
if (!user) throw new HttpError("You don't exist.");
|
||||
|
||||
const img = await this.images.findOne({ _id: body.id });
|
||||
const img = await this.db.images.findOne({ _id: body.id });
|
||||
if (!img) throw new HttpError("Image doesn't exist.");
|
||||
if (user.username !== img.author) throw new HttpError("You don't own the image.");
|
||||
|
||||
await this.images.updateOne({ _id: body.id }, { $set: { name: body.name, visibility: body.visibility } });
|
||||
await this.db.images.updateOne({ _id: body.id }, { $set: { name: body.name, visibility: body.visibility } });
|
||||
return ImageRouter.deserialize(img);
|
||||
}
|
||||
|
||||
public constructor(private images: Collection<Image>, private users: Collection<User>) {
|
||||
public constructor(private db: AppDatabase) {
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
import { Database } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
|
||||
import UserRouter from "../routers/UserRouter.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";
|
||||
import { stream } from "../utils/utils.ts";
|
||||
import AppDatabase from "../AppDatabase.ts";
|
||||
|
||||
export class RootRouter extends AppRouter {
|
||||
@route('users/*') users;
|
||||
@ -17,13 +15,10 @@ export class RootRouter extends AppRouter {
|
||||
return new RestResponse().body(stream('Page not found :/')).status(404);
|
||||
}
|
||||
|
||||
constructor(salt: string, db: Database) {
|
||||
constructor(salt: string, db: AppDatabase) {
|
||||
super();
|
||||
|
||||
const users = db.collection<User>('users');
|
||||
const images = db.collection<Image>('images');
|
||||
|
||||
this.users = new UserRouter(salt, users);
|
||||
this.images = new ImageRouter(images, users);
|
||||
this.users = new UserRouter(salt, db);
|
||||
this.images = new ImageRouter(db);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { Collection } from "https://deno.land/x/mongo@v0.31.2/mod.ts";
|
||||
import * as bcrypt from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";
|
||||
|
||||
import { auth, body, rest, schema } from "../server/decorators.ts";
|
||||
@ -8,53 +7,60 @@ import AppRouter from "./AppRouter.ts";
|
||||
import jwt from "../server/decorators/jwt.ts";
|
||||
import JWT, { JWTPayload } from "../utils/JWT.ts";
|
||||
import { now } from "../utils/utils.ts";
|
||||
import { convert } from "../server/decorators/schema.ts";
|
||||
import AppDatabase from "../AppDatabase.ts";
|
||||
import { Visibility } from "../models/Image.ts";
|
||||
|
||||
export interface SignupRequest {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
export interface LoginRequest {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export default class UserRouter extends AppRouter {
|
||||
public static deserialize(user: User) {
|
||||
return { username: user.username, images: user.images };
|
||||
public deserialize(user: User, self = false) {
|
||||
let images = user.images;
|
||||
if (!self) {
|
||||
images = [];
|
||||
Promise.all(user.images.map(async v => {
|
||||
if ((await this.db.images.findOne({ _id: v }))?.visibility === Visibility.Public) {
|
||||
images.push(v);
|
||||
}
|
||||
}));
|
||||
}
|
||||
return { username: user.username, images };
|
||||
}
|
||||
|
||||
@rest('GET', '/')
|
||||
async get(@schema('string') username: string) {
|
||||
const res = await this.users.findOne({ username });
|
||||
|
||||
async get(@schema('string') username: string, @jwt('salt', true) @auth() jwt: JWTPayload) {
|
||||
const res = await this.db.users.findOne({ username });
|
||||
if (res === undefined) throw new HttpError('User not found.');
|
||||
|
||||
return UserRouter.deserialize(res);
|
||||
return this.deserialize(res, jwt.name === username);
|
||||
}
|
||||
@rest('GET', '/self')
|
||||
async self(@jwt(self => self.salt, true) @auth() auth: JWTPayload) {
|
||||
async self(@jwt('salt', true) @auth() auth: JWTPayload) {
|
||||
if (auth === undefined) throw new HttpError('You are not logged in.');
|
||||
const res = await this.users.findOne({ username: auth.name });
|
||||
const res = await this.db.users.findOne({ username: auth.name });
|
||||
|
||||
if (res === undefined) throw new HttpError('User not found.');
|
||||
|
||||
return UserRouter.deserialize(res);
|
||||
return this.deserialize(res);
|
||||
}
|
||||
|
||||
@rest('POST', '/signup')
|
||||
async signup(
|
||||
@schema({
|
||||
async signup(@body() raw: unknown) {
|
||||
const body = await convert(raw, {
|
||||
username: 'string',
|
||||
password: 'string',
|
||||
}) @body() body: SignupRequest
|
||||
) {
|
||||
if (await this.users.countDocuments({ username: body.username }) > 0) {
|
||||
});
|
||||
|
||||
if (await this.db.users.countDocuments({ username: body.username }) > 0) {
|
||||
throw new HttpError('User with the same username already exists.');
|
||||
}
|
||||
|
||||
const password = await bcrypt.hash(body.password, this.salt);
|
||||
|
||||
await this.users.insertOne({
|
||||
await this.db.users.insertOne({
|
||||
username: body.username,
|
||||
password: password,
|
||||
images: [],
|
||||
@ -63,13 +69,12 @@ export default class UserRouter extends AppRouter {
|
||||
return {};
|
||||
}
|
||||
@rest('POST', '/login')
|
||||
async login(
|
||||
@schema({
|
||||
async login(@body() raw: unknown) {
|
||||
const body = await convert(raw, {
|
||||
username: 'string',
|
||||
password: 'string'
|
||||
}) @body() body: LoginRequest
|
||||
) {
|
||||
const res = await this.users.findOne({ username: body.username });
|
||||
});
|
||||
const res = await this.db.users.findOne({ username: body.username });
|
||||
if (!res) throw new HttpError('Incorrect username or password.');
|
||||
const hashed = await bcrypt.hash(body.password, this.salt);
|
||||
|
||||
@ -83,8 +88,8 @@ export default class UserRouter extends AppRouter {
|
||||
}, this.salt);
|
||||
}
|
||||
|
||||
public constructor(private salt: string, private users: Collection<User>) {
|
||||
public constructor(private salt: string, private db: AppDatabase) {
|
||||
super();
|
||||
users.createIndexes({ indexes: [ { key: { username: 1 }, name: 'Username Index' } ] });
|
||||
db.users.createIndexes({ indexes: [ { key: { username: 1 }, name: 'Username Index' } ] });
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user