implement login

This commit is contained in:
TopchetoEU 2023-06-27 06:18:19 +03:00
parent f2e8b301e9
commit cd4738377b
No known key found for this signature in database
GPG Key ID: 24E57B2E9C61AD19
4 changed files with 41 additions and 7 deletions

View File

@ -1,10 +1,13 @@
import { Collection } from "https://deno.land/x/mongo@v0.31.2/mod.ts"; 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 * as bcrypt from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";
import { body, rest, schema } from "../server/decorators.ts"; import { auth, body, rest, schema } from "../server/decorators.ts";
import HttpError from "../server/HttpError.ts"; import HttpError from "../server/HttpError.ts";
import User from "../models/User.ts"; import User from "../models/User.ts";
import AppRouter from "./AppRouter.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 { export interface SignupRequest {
username: string; username: string;
@ -16,7 +19,7 @@ export interface LoginRequest {
} }
export default class UserRouter extends AppRouter { export default class UserRouter extends AppRouter {
@rest('GET', '/:username') @rest('GET', '/')
async get(@schema('string') username: string) { async get(@schema('string') username: string) {
const res = await this.users.findOne({ username }); const res = await this.users.findOne({ username });
@ -24,6 +27,15 @@ export default class UserRouter extends AppRouter {
return { username: res.username }; 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') @rest('POST', '/signup')
async signup( async signup(
@ -54,8 +66,16 @@ export default class UserRouter extends AppRouter {
) { ) {
const res = await this.users.findOne({ username: body.username }); const res = await this.users.findOne({ username: body.username });
if (!res) throw new HttpError('Incorrect username or password.'); if (!res) throw new HttpError('Incorrect username or password.');
bcrypt.hash(res.password, this.salt); 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>) { public constructor(private salt: string, private users: Collection<User>) {

View File

@ -1,10 +1,21 @@
import JWT from "../../JWT.ts"; import JWT from "../../utils/JWT.ts";
import HttpError from "../HttpError.ts";
import Router, { makeParameterModifier } from "../Router.ts"; import Router, { makeParameterModifier } from "../Router.ts";
export default function jwt<T extends Router>(salt: ((self: T) => string) | keyof T) { export default function jwt<T extends Router>(salt: ((self: T) => string) | keyof T, required = false) {
return makeParameterModifier<T>(function (_req, val?: string) { return makeParameterModifier<T>(function (_req, val?: string) {
if (val === undefined) return undefined; if (val === undefined) return undefined;
const s = typeof salt === 'function' ? salt(this) : this[salt] as string; const s = typeof salt === 'function' ? salt(this) : this[salt] as string;
return JWT.decode(val, s); try {
const res = JWT.decode(val, s);
if (required && res === undefined) throw new HttpError('You are not logged in.');
return res;
}
catch (e) {
if (e instanceof Error && !(e instanceof HttpError)) {
throw new HttpError(e.message, 400);
}
else throw e;
}
}); });
} }

3
src/utils/now.ts Normal file
View File

@ -0,0 +1,3 @@
export default function now() {
return new Date().getTime() / 1000;
}