implement login
This commit is contained in:
parent
f2e8b301e9
commit
cd4738377b
@ -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>) {
|
||||||
|
@ -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
3
src/utils/now.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default function now() {
|
||||||
|
return new Date().getTime() / 1000;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user