From aded6b6111af50159382d6a29181a1ad15b448e5 Mon Sep 17 00:00:00 2001 From: Nora Date: Wed, 19 Dec 2018 16:10:40 -0500 Subject: [PATCH] fixup! more code --- src/application.ts | 1 - src/authentication-strategies/JWT.strategy.ts | 30 +++++++++++++++++ src/controllers/user.controller.ts | 27 ++++++++++++++-- src/providers/strategy.resolver.provider.ts | 32 +------------------ test/acceptance/user.controller.acceptance.ts | 5 ++- 5 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 src/authentication-strategies/JWT.strategy.ts diff --git a/src/application.ts b/src/application.ts index f34086292..792e8e414 100644 --- a/src/application.ts +++ b/src/application.ts @@ -14,7 +14,6 @@ import { AuthenticationBindings, AuthenticationComponent, } from '@loopback/authentication'; -import {JWTProvider} from './providers'; import {StrategyResolverProvider} from './providers/strategy.resolver.provider'; /** diff --git a/src/authentication-strategies/JWT.strategy.ts b/src/authentication-strategies/JWT.strategy.ts new file mode 100644 index 000000000..1d3d7e92c --- /dev/null +++ b/src/authentication-strategies/JWT.strategy.ts @@ -0,0 +1,30 @@ +const jwt = require('jsonwebtoken'); +import {promisify} from 'util'; +const signAsync = promisify(jwt.sign); +const verifyAsync = promisify(jwt.verify); +// Consider turn it to a binding +const SECRET = 'secretforjwt'; + +export class JWTStrategy { + // tslint:disable-next-line:no-any + async authenticate(request: Request): Promise { + // A mock for sign in + const payload = {admin: true}; + await signAsync(payload, SECRET, {expiresIn: 300}); + // const token = + // request.body!.token || + // request.query.token || + // request.headers['x-access-token']; + const token = 'not the right token'; + + if (token) { + try { + return await verifyAsync(token, SECRET); + } catch (err) { + if (err) return Promise.reject('Authentication failed!'); + } + } + // should we return some meaningful message? + return; + } +} diff --git a/src/controllers/user.controller.ts b/src/controllers/user.controller.ts index 110f4ea85..449910458 100644 --- a/src/controllers/user.controller.ts +++ b/src/controllers/user.controller.ts @@ -12,9 +12,7 @@ import {promisify} from 'util'; import * as isemail from 'isemail'; import {RecommenderService} from '../services/recommender.service'; import {inject} from '@loopback/core'; -import { - authenticate, -} from '@loopback/authentication'; +import {authenticate} from '@loopback/authentication'; const hashAsync = promisify(hash); @@ -91,4 +89,27 @@ export class UserController { ): Promise { return this.recommender.getProductRecommendations(userId); } + + @post('/users/login') + async login(@requestBody() user: User): Promise { + // Validate Email + if (!isemail.validate(user.email)) { + throw new HttpErrors.UnprocessableEntity('invalid email'); + } + + // Validate Password Length + if (user.password.length < 8) { + throw new HttpErrors.UnprocessableEntity( + 'password must be minimum 8 characters', + ); + } + + // Salt + Hash Password + user.password = await hashAsync(user.password, 10); + + // Save & Return Result + const savedUser = await this.userRepository.create(user); + delete savedUser.password; + return savedUser; + } } diff --git a/src/providers/strategy.resolver.provider.ts b/src/providers/strategy.resolver.provider.ts index c103e48d8..b59c35a68 100644 --- a/src/providers/strategy.resolver.provider.ts +++ b/src/providers/strategy.resolver.provider.ts @@ -1,16 +1,10 @@ import {Provider, ValueOrPromise} from '@loopback/core'; import {inject} from '@loopback/context'; import { - StrategyAdapter, AuthenticationBindings, AuthenticationMetadata, } from '@loopback/authentication'; -const jwt = require('jsonwebtoken'); -import {promisify} from 'util'; -const signAsync = promisify(jwt.sign); -const verifyAsync = promisify(jwt.verify); -// Consider turn it to a binding -const SECRET = 'secretforjwt'; +import {JWTStrategy} from '../authentication-strategies/JWT.strategy'; export class StrategyResolverProvider implements Provider { @@ -31,27 +25,3 @@ export class StrategyResolverProvider } } } - -export class JWTStrategy { - // tslint:disable-next-line:no-any - async authenticate(req: Request): Promise { - // A mock for sign in - const payload = {admin: true}; - await signAsync(payload, SECRET, {expiresIn: 5}); - // const token = - // request.body.token || - // request.query.token || - // request.headers['x-access-token']; - const token = 'not the right token'; - - if (token) { - try { - await verifyAsync(token, SECRET); - } catch (err) { - if (err) return Promise.reject('Authentication failed!'); - } - } - // should we return some meaningful message? - return; - } -} diff --git a/test/acceptance/user.controller.acceptance.ts b/test/acceptance/user.controller.acceptance.ts index f30b33bd7..512806d49 100644 --- a/test/acceptance/user.controller.acceptance.ts +++ b/test/acceptance/user.controller.acceptance.ts @@ -10,8 +10,7 @@ import {UserRepository, OrderRepository} from '../../src/repositories'; import {MongoDataSource} from '../../src/datasources'; import {setupApplication} from './helper'; import {createRecommendationServer} from '../../recommender'; -import {Server, ServerResponse} from 'http'; -import {authenticate} from '@loopback/authentication'; +import {Server} from 'http'; const recommendations = require('../../recommender/recommendations.json'); describe('UserController', () => { @@ -121,7 +120,7 @@ describe('UserController', () => { // since the REST API returns a string for the id property. newUser.id = newUser.id.toString(); await client - .post('/Users/login') + .post('/users/login') .send({username: 'the-username', password: 'the-password'}) .expect(200) .end(onResponse);