clonegur/src/routers/UserRouter.ts
2023-06-27 06:18:19 +03:00

85 lines
2.7 KiB
TypeScript

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";
import HttpError from "../server/HttpError.ts";
import User from "../models/User.ts";
import AppRouter from "./AppRouter.ts";
import jwt from "../server/decorators/jwt.ts";
import JWT, { JWTPayload } from "../utils/JWT.ts";
import now from "../utils/now.ts";
export interface SignupRequest {
username: string;
password: string;
}
export interface LoginRequest {
username: string;
password: string;
}
export default class UserRouter extends AppRouter {
@rest('GET', '/')
async get(@schema('string') username: string) {
const res = await this.users.findOne({ username });
if (res === undefined) throw new HttpError('User not found.');
return { username: res.username };
}
@rest('GET', '/self')
async self(@jwt(self => self.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 });
if (res === undefined) throw new HttpError('User not found.');
return { username: res.username };
}
@rest('POST', '/signup')
async signup(
@schema({
username: 'string',
password: 'string',
}) @body() body: SignupRequest
) {
if (await this.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({
username: body.username,
password: password,
});
return {};
}
@rest('POST', '/login')
async login(
@schema({
username: 'string',
password: 'string'
}) @body() body: LoginRequest
) {
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);
if (res.password !== hashed) throw new HttpError('Incorrect username or password.');
const time = now();
return JWT.encode({
iat: time,
exp: time + 3600 * 12,
name: res.username,
}, this.salt);
}
public constructor(private salt: string, private users: Collection<User>) {
super();
users.createIndexes({ indexes: [ { key: { username: 1 }, name: 'Username Index' } ] });
}
}