import { AuthenticationComponent } from '@loopback/authentication' ; import { JWTAuthenticationComponent , TokenServiceBindings , } from '@loopback/authentication-jwt' ; import { AuthorizationComponent } from '@loopback/authorization' ; import { BootMixin } from '@loopback/boot' ; import { ApplicationConfig , BindingKey , createBindingFromClass , } from '@loopback/core' ; import { RepositoryMixin , SchemaMigrationOptions } from '@loopback/repository' ; import { RestApplication } from '@loopback/rest' ; import { RestExplorerBindings , RestExplorerComponent , } from '@loopback/rest-explorer' ; import { ServiceMixin } from '@loopback/service-proxy' ; import crypto from 'crypto' ; import fs from 'fs' ; import path from 'path' ; import { PasswordHasherBindings , UserServiceBindings } from './keys' ; import { UserWithPassword } from './models' ; import { OrderRepository , ProductRepository , ShoppingCartRepository , UserRepository , } from './repositories' ; import { ShoppySequence } from './sequence' ; import { UserManagementService , BcryptHasher , SecuritySpecEnhancer , JWTService , } from './services' ; import YAML = require ( 'yaml' ) ; import { ErrorHandlerMiddlewareProvider } from './middlewares' ; /**
 * Information from package.json
 */ export interface PackageInfo { name : string ; version : string ; description : string ; } export const PackageKey = BindingKey . create < PackageInfo > ( 'application.package' ) ; const pkg = require ( '../package.json' ) ; export class ShoppingApplication extends BootMixin ( ServiceMixin ( RepositoryMixin ( RestApplication ) ) ) { constructor ( options ? ) { super ( options ) ; this . component ( AuthenticationComponent ) ; this . component ( JWTAuthenticationComponent ) ; this . component ( AuthorizationComponent ) ; this . setUpBindings ( ) ; this . sequence ( ShoppySequence ) ; this . static ( '/' , path . join ( __dirname , '../public' ) ) ; this . bind ( RestExplorerBindings . CONFIG ) . to ( { path : '/explorer' , } ) ; this . component ( RestExplorerComponent ) ; this . projectRoot = __dirname ; this . bootOptions = { controllers : { dirs : [ 'controllers' ] , extensions : [ '.controller.js' ] , nested : true , } , } ; } setUpBindings ( ) { this . bind ( PackageKey ) . to ( pkg ) ; this . bind ( PasswordHasherBindings . ROUNDS ) . to ( 10 ) ; this . bind ( PasswordHasherBindings . PASSWORD_HASHER ) . toClass ( BcryptHasher ) ; this . bind ( TokenServiceBindings . TOKEN_SERVICE ) . toClass ( JWTService ) ; this . bind ( UserServiceBindings . USER_SERVICE ) . toClass ( UserManagementService ) ; this . add ( createBindingFromClass ( SecuritySpecEnhancer ) ) ; this . add ( createBindingFromClass ( ErrorHandlerMiddlewareProvider ) ) ; const secret = process . env . JWT_SECRET ?? crypto . randomBytes ( 32 ) . toString ( 'hex' ) ; this . bind ( TokenServiceBindings . TOKEN_SECRET ) . to ( secret ) ; } async start ( ) { if ( this . options . databaseSeeding !== false ) { await this . migrateSchema ( ) ; } return super . start ( ) ; } async migrateSchema ( options ? ) { await super . migrateSchema ( options ) ; const productRepo = await this . getRepository ( ProductRepository ) ; await productRepo . deleteAll ( ) ; const productsDir = path . join ( __dirname , '../fixtures/products' ) ; const productFiles = fs . readdirSync ( productsDir ) ; for ( const file of productFiles ) { if ( file . endsWith ( '.yml' ) ) { const productFile = path . join ( productsDir , file ) ; const yamlString = fs . readFileSync ( productFile , 'utf8' ) ; const product = YAML . parse ( yamlString ) ; await productRepo . create ( product ) ; } } const userRepo = await this . getRepository ( UserRepository ) ; await userRepo . deleteAll ( ) ; const usersDir = path . join ( __dirname , '../fixtures/users' ) ; const userFiles = fs . readdirSync ( usersDir ) ; for ( const file of userFiles ) { if ( file . endsWith ( '.yml' ) ) { const userFile = path . join ( usersDir , file ) ; const yamlString = YAML . parse ( fs . readFileSync ( userFile , 'utf8' ) ) ; const userWithPassword = new UserWithPassword ( yamlString ) ; const userManagementService = await this . get < UserManagementService > ( UserServiceBindings . USER_SERVICE ) ; await userManagementService . createUser ( userWithPassword ) ; } } const cartRepo = await this . getRepository ( ShoppingCartRepository ) ; await cartRepo . deleteAll ( ) ; const orderRepo = await this . getRepository ( OrderRepository ) ; await orderRepo . deleteAll ( ) ; } }