Do not extend/modify existing entities

Typeorm loads all @Entities and decorator-defined relations into a
global variable, and thus makes it impossible to override already
defined variables.

Will have to think about how to disable this behaviour in case the user
of this library does not want to use predefined variables, but for now
we will use the predefined defaults.
This commit is contained in:
Jerko Steiner 2019-08-02 20:17:08 +07:00
parent a6649def72
commit 4c3570a9ce
7 changed files with 46 additions and 30 deletions

View File

@ -6,13 +6,14 @@ import * as user from '../user'
import cookieParser from 'cookie-parser' import cookieParser from 'cookie-parser'
import express from 'express' import express from 'express'
import {AsyncRouter, TransactionalRouter} from '../router' import {AsyncRouter, TransactionalRouter} from '../router'
import {DB} from '../database/DB'
import {IApplication} from './IApplication' import {IApplication} from './IApplication'
import {IConfig} from './IConfig' import {IConfig} from './IConfig'
import {IDatabase} from '../database/IDatabase' import {IDatabase} from '../database/IDatabase'
import {ILogger} from '../logger/ILogger' import {ILogger} from '../logger/ILogger'
import {IRoutes} from '@rondo/common' import {IRoutes} from '@rondo/common'
import {IServices} from './IServices'
import {ITransactionManager} from '../database/ITransactionManager' import {ITransactionManager} from '../database/ITransactionManager'
import {DB} from '../database/DB'
import {loggerFactory, LoggerFactory} from '../logger/LoggerFactory' import {loggerFactory, LoggerFactory} from '../logger/LoggerFactory'
import {json} from 'body-parser' import {json} from 'body-parser'
@ -21,10 +22,7 @@ export class Application implements IApplication {
readonly transactionManager: ITransactionManager readonly transactionManager: ITransactionManager
readonly server: express.Application readonly server: express.Application
readonly userService: services.IUserService readonly services: IServices
readonly teamService: team.ITeamService
readonly userPermissions: user.IUserPermissions
readonly authenticator: middleware.Authenticator readonly authenticator: middleware.Authenticator
readonly loggerFactory: LoggerFactory = loggerFactory readonly loggerFactory: LoggerFactory = loggerFactory
@ -32,16 +30,22 @@ export class Application implements IApplication {
constructor(readonly config: IConfig, readonly database: IDatabase) { constructor(readonly config: IConfig, readonly database: IDatabase) {
this.transactionManager = database.transactionManager this.transactionManager = database.transactionManager
this.db = new DB(this.transactionManager) this.db = new DB(this.transactionManager)
this.userService = new services.UserService(this.db)
this.teamService = new team.TeamService(this.transactionManager) this.services = this.configureServices()
this.userPermissions = new user.UserPermissions(this.transactionManager)
this.authenticator = new middleware.Authenticator(this.userService) this.authenticator = new middleware.Authenticator(this.services.userService)
this.server = this.createServer() this.server = this.createServer()
} }
protected configureServices(): IServices {
return {
userService: new services.UserService(this.db),
teamService: new team.TeamService(this.db),
userPermissions: new user.UserPermissions(this.db),
}
}
protected getApiLogger(): ILogger { protected getApiLogger(): ILogger {
return this.loggerFactory.getLogger('api') return this.loggerFactory.getLogger('api')
} }
@ -90,18 +94,18 @@ export class Application implements IApplication {
router.use('/app', routes.application) router.use('/app', routes.application)
router.use('/api', new routes.LoginRoutes( router.use('/api', new routes.LoginRoutes(
this.userService, this.services.userService,
this.authenticator, this.authenticator,
this.createTransactionalRouter(), this.createTransactionalRouter(),
).handle) ).handle)
router.use('/api', new routes.UserRoutes( router.use('/api', new routes.UserRoutes(
this.userService, this.services.userService,
this.createTransactionalRouter(), this.createTransactionalRouter(),
).handle) ).handle)
router.use('/api', new team.TeamRoutes( router.use('/api', new team.TeamRoutes(
this.teamService, this.services.teamService,
this.userPermissions, this.services.userPermissions,
this.createTransactionalRouter(), this.createTransactionalRouter(),
).handle) ).handle)
} }

View File

@ -0,0 +1,9 @@
import {IUserService} from '../services'
import {ITeamService} from '../team'
import {IUserPermissions} from '../user'
export interface IServices {
userService: IUserService
teamService: ITeamService
userPermissions: IUserPermissions
}

View File

@ -2,3 +2,4 @@ export * from './Application'
export * from './Bootstrap' export * from './Bootstrap'
export * from './IApplication' export * from './IApplication'
export * from './IConfig' export * from './IConfig'
export * from './IServices'

View File

@ -4,9 +4,6 @@ import {User} from './User'
@Entity() @Entity()
export class UserEmail extends BaseEntity { export class UserEmail extends BaseEntity {
@PrimaryGeneratedColumn()
id!: number
@Column({unique: true}) @Column({unique: true})
email!: string email!: string

View File

@ -10,4 +10,5 @@ export * from './routes'
export * from './services' export * from './services'
export * from './session' export * from './session'
export * from './user' export * from './user'
export * from './team'
export * from './validator' export * from './validator'

View File

@ -1,4 +1,4 @@
import {BaseService} from '../services/BaseService' import {DB} from '../database/DB'
import {ITeamService} from './ITeamService' import {ITeamService} from './ITeamService'
import {IUserInTeam, trim} from '@rondo/common' import {IUserInTeam, trim} from '@rondo/common'
import {IUserTeamParams} from './IUserTeamParams' import {IUserTeamParams} from './IUserTeamParams'
@ -6,7 +6,9 @@ import {Team} from '../entities/Team'
import {UserTeam} from '../entities/UserTeam' import {UserTeam} from '../entities/UserTeam'
import {Validator} from '../validator' import {Validator} from '../validator'
export class TeamService extends BaseService implements ITeamService { export class TeamService implements ITeamService {
constructor(protected readonly db: DB) {}
// TODO check team limit per user // TODO check team limit per user
async create({name, userId}: {name: string, userId: number}) { async create({name, userId}: {name: string, userId: number}) {
@ -17,7 +19,7 @@ export class TeamService extends BaseService implements ITeamService {
.ensure('userId') .ensure('userId')
.throw() .throw()
const team = await this.getRepository(Team).save({ const team = await this.db.getRepository(Team).save({
name, name,
userId, userId,
}) })
@ -33,17 +35,17 @@ export class TeamService extends BaseService implements ITeamService {
} }
async remove({id, userId}: {id: number, userId: number}) { async remove({id, userId}: {id: number, userId: number}) {
await this.getRepository(UserTeam) await this.db.getRepository(UserTeam)
.delete({teamId: id, userId}) .delete({teamId: id, userId})
await this.getRepository(Team) await this.db.getRepository(Team)
.delete(id) .delete(id)
return {id} return {id}
} }
async update({id, name, userId}: {id: number, name: string, userId: number}) { async update({id, name, userId}: {id: number, name: string, userId: number}) {
await this.getRepository(Team) await this.db.getRepository(Team)
.update({ .update({
id, id,
}, { }, {
@ -55,7 +57,7 @@ export class TeamService extends BaseService implements ITeamService {
async addUser(params: IUserTeamParams) { async addUser(params: IUserTeamParams) {
const {userId, teamId, roleId} = params const {userId, teamId, roleId} = params
await this.getRepository(UserTeam) await this.db.getRepository(UserTeam)
.save({userId, teamId, roleId}) .save({userId, teamId, roleId})
const userTeam = await this.createFindUserInTeamQuery() const userTeam = await this.createFindUserInTeamQuery()
@ -71,7 +73,7 @@ export class TeamService extends BaseService implements ITeamService {
async removeUser({teamId, userId, roleId}: IUserTeamParams) { async removeUser({teamId, userId, roleId}: IUserTeamParams) {
// TODO check if this is the last admin team member // TODO check if this is the last admin team member
await this.getRepository(UserTeam) await this.db.getRepository(UserTeam)
.delete({userId, teamId, roleId}) .delete({userId, teamId, roleId})
} }
@ -86,11 +88,11 @@ export class TeamService extends BaseService implements ITeamService {
} }
async findOne(id: number) { async findOne(id: number) {
return this.getRepository(Team).findOne(id) return this.db.getRepository(Team).findOne(id)
} }
async find(userId: number) { async find(userId: number) {
return this.getRepository(Team) return this.db.getRepository(Team)
.createQueryBuilder('team') .createQueryBuilder('team')
.select('team') .select('team')
.innerJoin('team.userTeams', 'ut') .innerJoin('team.userTeams', 'ut')
@ -99,7 +101,7 @@ export class TeamService extends BaseService implements ITeamService {
} }
protected createFindUserInTeamQuery() { protected createFindUserInTeamQuery() {
return this.getRepository(UserTeam) return this.db.getRepository(UserTeam)
.createQueryBuilder('ut') .createQueryBuilder('ut')
.select('ut') .select('ut')
.innerJoinAndSelect('ut.user', 'user') .innerJoinAndSelect('ut.user', 'user')

View File

@ -1,12 +1,14 @@
import createError from 'http-errors' import createError from 'http-errors'
import {BaseService} from '../services/BaseService' import {DB} from '../database/DB'
import {UserTeam} from '../entities/UserTeam' import {UserTeam} from '../entities/UserTeam'
import {IUserPermissions} from './IUserPermissions' import {IUserPermissions} from './IUserPermissions'
export class UserPermissions extends BaseService implements IUserPermissions { export class UserPermissions implements IUserPermissions {
constructor(protected readonly db: DB) {}
async belongsToTeam(params: {userId: number, teamId: number}) { async belongsToTeam(params: {userId: number, teamId: number}) {
const {userId, teamId} = params const {userId, teamId} = params
const result = await this.getRepository(UserTeam) const result = await this.db.getRepository(UserTeam)
.findOne({ .findOne({
where: {userId, teamId}, where: {userId, teamId},
}) })