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

View File

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

View File

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

View File

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

View File

@ -1,12 +1,14 @@
import createError from 'http-errors'
import {BaseService} from '../services/BaseService'
import {DB} from '../database/DB'
import {UserTeam} from '../entities/UserTeam'
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}) {
const {userId, teamId} = params
const result = await this.getRepository(UserTeam)
const result = await this.db.getRepository(UserTeam)
.findOne({
where: {userId, teamId},
})