Fix JWT authentication, add custom user service

This commit is contained in:
Norbi Peti 2021-11-16 22:28:56 +01:00
parent ee2d7b4838
commit cfc3d48a7b
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
4 changed files with 87 additions and 30 deletions

View file

@ -11,7 +11,7 @@ import path from 'path';
import {MySequence} from './sequence';
import {AuthenticationComponent} from '@loopback/authentication';
import {JWTAuthenticationComponent, UserServiceBindings} from '@loopback/authentication-jwt';
import {DatabaseDataSource} from './datasources';
import {SzakdolgozatUserService} from './services';
export {ApplicationConfig};
@ -36,7 +36,7 @@ export class SzakdolgozatBackendApplication extends BootMixin(
// Authentication
this.component(AuthenticationComponent);
this.component(JWTAuthenticationComponent);
this.dataSource(DatabaseDataSource, UserServiceBindings.DATASOURCE_NAME)
this.service(SzakdolgozatUserService, UserServiceBindings.USER_SERVICE);
this.projectRoot = __dirname;
// Customize @loopback/boot Booter Conventions here

View file

@ -1,41 +1,28 @@
import {Count, CountSchema, Filter, FilterExcludingWhere, MODEL_PROPERTIES_KEY, repository, Where,} from '@loopback/repository';
import {Count, CountSchema, Filter, FilterExcludingWhere, repository, Where,} from '@loopback/repository';
import {del, get, getModelSchemaRef, param, patch, post, put, requestBody, response,} from '@loopback/rest';
import {User} from '../models';
import {UserRepository} from '../repositories';
import {
Credentials,
MyUserService,
TokenServiceBindings,
UserServiceBindings
} from '@loopback/authentication-jwt';
import {inject, MetadataInspector} from '@loopback/core';
import {inject} from '@loopback/core';
import {TokenService} from '@loopback/authentication';
import {SecurityBindings, UserProfile} from '@loopback/security';
import {genSalt, hash} from 'bcryptjs';
import _ from 'lodash';
import {UserRepository as UserRepo} from '@loopback/authentication-jwt';
import {SzakdolgozatUserService} from '../services';
export class UserController {
constructor(
@inject(TokenServiceBindings.TOKEN_SERVICE)
public jwtService: TokenService,
@inject(UserServiceBindings.USER_SERVICE)
public userService: MyUserService,
public userService: SzakdolgozatUserService,
@inject(SecurityBindings.USER, {optional: true})
public user: UserProfile,
@repository(UserRepo)
public userRepository : UserRepo,
@repository(UserRepository)
public userDataRepository : UserRepository,
) {}
static includeToExclude(values: (keyof User)[]): (keyof User)[] {
const metadata = MetadataInspector.getAllPropertyMetadata(MODEL_PROPERTIES_KEY, User);
if (metadata) {
return _.without(Object.keys(metadata), ...values) as (keyof User)[];
}
else throw new Error("No property metadata found");
}
public userRepository : UserRepository,
) { }
@post('/users')
@response(200, {
@ -62,7 +49,7 @@ export class UserController {
password: password,
role: 'student'
} as User;
return this.userDataRepository.create(user);
return this.userRepository.create(user);
}
@post('/users/login', {
@ -92,7 +79,7 @@ export class UserController {
'application/json': {
schema: getModelSchemaRef(User, {exclude: ['id', 'role', 'name']})
},
}}) credentials: Credentials,
}}) credentials: Pick<User, 'email' | 'password'>,
): Promise<{token: string}> {
// ensure the user exists, and the password is correct
const user = await this.userService.verifyCredentials(credentials);
@ -112,7 +99,7 @@ export class UserController {
async count(
@param.where(User) where?: Where<User>,
): Promise<Count> {
return this.userDataRepository.count(where);
return this.userRepository.count(where);
}
@get('/users')
@ -130,7 +117,7 @@ export class UserController {
async find(
@param.filter(User) filter?: Filter<User>,
): Promise<User[]> {
return this.userDataRepository.find(filter);
return this.userRepository.find(filter);
}
@patch('/users')
@ -149,7 +136,7 @@ export class UserController {
user: User,
@param.where(User) where?: Where<User>,
): Promise<Count> {
return this.userDataRepository.updateAll(user, where);
return this.userRepository.updateAll(user, where);
}
@get('/users/{id}')
@ -165,7 +152,7 @@ export class UserController {
@param.path.number('id') id: number,
@param.filter(User, {exclude: 'where'}) filter?: FilterExcludingWhere<User>
): Promise<User> {
return this.userDataRepository.findById(id, filter);
return this.userRepository.findById(id, filter);
}
@patch('/users/{id}')
@ -183,7 +170,7 @@ export class UserController {
})
user: User,
): Promise<void> {
await this.userDataRepository.updateById(id, user);
await this.userRepository.updateById(id, user);
}
@put('/users/{id}')
@ -194,7 +181,7 @@ export class UserController {
@param.path.number('id') id: number,
@requestBody() user: User,
): Promise<void> {
await this.userDataRepository.replaceById(id, user);
await this.userRepository.replaceById(id, user);
}
@del('/users/{id}')
@ -202,6 +189,6 @@ export class UserController {
description: 'User DELETE success',
})
async deleteById(@param.path.number('id') id: number): Promise<void> {
await this.userDataRepository.deleteById(id);
await this.userRepository.deleteById(id);
}
}

View file

@ -0,0 +1 @@
export * from './user.service';

View file

@ -0,0 +1,69 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/authentication-jwt
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {UserService} from '@loopback/authentication';
import {repository} from '@loopback/repository';
import {HttpErrors} from '@loopback/rest';
import {securityId, UserProfile} from '@loopback/security';
import {compare} from 'bcryptjs';
import {User, UserWithRelations} from '../models';
import {UserRepository} from '../repositories';
/**
* A pre-defined type for user credentials. It assumes a user logs in
* using the email and password. You can modify it if your app has different credential fields
*/
export type Credentials = {
email: string;
password: string;
};
export class SzakdolgozatUserService implements UserService<User, Credentials> {
constructor(
@repository(UserRepository) public userRepository: UserRepository,
) { }
async verifyCredentials(credentials: Credentials): Promise<User> {
const invalidCredentialsError = 'Invalid email or password.';
const foundUser = await this.userRepository.findOne({
where: {email: credentials.email},
});
if (!foundUser) {
throw new HttpErrors.Unauthorized(invalidCredentialsError);
}
const passwordMatched = await compare(
credentials.password,
foundUser.password,
);
if (!passwordMatched) {
throw new HttpErrors.Unauthorized(invalidCredentialsError);
}
return foundUser;
}
convertToUserProfile({email, id, name}: User): UserProfile {
return {
[securityId]: id!.toString(),
name,
id,
email,
};
}
//function to find user by id
async findUserById(id: number): Promise<User & UserWithRelations> {
const userNotfound = 'invalid user';
const foundUser = await this.userRepository.findById(id);
if (!foundUser) {
throw new HttpErrors.Unauthorized(userNotfound);
}
return foundUser;
}
}