Use EntitySchema and interfaces over typeorm decorators

This commit is contained in:
Jerko Steiner 2019-09-18 15:17:42 +07:00
parent 9c9c41aeaf
commit d4378719c5
33 changed files with 774 additions and 410 deletions

View File

@ -21,9 +21,13 @@ rules:
exports: always-multiline exports: always-multiline
functions: always-multiline functions: always-multiline
# semi: semi:
# - warn - warn
# - never - never
quotes:
- warn
- single
- allowTemplateLiterals: true
# interface-name-prefix: # interface-name-prefix:
'import/no-extraneous-dependencies': off 'import/no-extraneous-dependencies': off
'@typescript-eslint/member-delimiter-style': '@typescript-eslint/member-delimiter-style':

649
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,8 +22,6 @@
"@rondo.dev/db-typeorm": "file:packages/db-typeorm" "@rondo.dev/db-typeorm": "file:packages/db-typeorm"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/parser": "^2.2.0",
"@types/bcrypt": "^3.0.0", "@types/bcrypt": "^3.0.0",
"@types/body-parser": "^1.17.0", "@types/body-parser": "^1.17.0",
"@types/cls-hooked": "^4.2.1", "@types/cls-hooked": "^4.2.1",
@ -51,6 +49,8 @@
"@types/std-mocks": "^1.0.0", "@types/std-mocks": "^1.0.0",
"@types/supertest": "^2.0.7", "@types/supertest": "^2.0.7",
"@types/uuid": "^3.4.4", "@types/uuid": "^3.4.4",
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/parser": "^2.2.0",
"axios": "^0.19.0", "axios": "^0.19.0",
"bloomer": "^0.6.5", "bloomer": "^0.6.5",
"browser-unpack": "^1.4.2", "browser-unpack": "^1.4.2",
@ -96,6 +96,7 @@
"ts-transformer-keys": "^0.3.5", "ts-transformer-keys": "^0.3.5",
"tsify": "^4.0.1", "tsify": "^4.0.1",
"ttypescript": "^1.5.7", "ttypescript": "^1.5.7",
"typeorm": "^0.2.19",
"typescript": "^3.6.3", "typescript": "^3.6.3",
"typescript-tslint-plugin": "^0.5.4", "typescript-tslint-plugin": "^0.5.4",
"uglify-js": "^3.5.3", "uglify-js": "^3.5.3",

View File

@ -1,4 +1,5 @@
export * from './Config' export * from './Config'
export * from './ConfigReader'
import { ConfigReader } from './ConfigReader' import { ConfigReader } from './ConfigReader'
export default ConfigReader export default ConfigReader

View File

@ -69,7 +69,7 @@ export async function exec(...argv: string[]) {
export async function createMigration(...argv: string[]) { export async function createMigration(...argv: string[]) {
const args = argparse({ const args = argparse({
name: arg('string', {required: true, positional: true}), name: arg('string', {required: true, positional: true}),
project: arg('string', {default: '.'}), project: arg('string', {alias: 'p', default: '.'}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) })
.parse(argv) .parse(argv)
@ -82,7 +82,7 @@ export async function createMigration(...argv: string[]) {
if (!typeorm) { if (!typeorm) {
throw new Error('typeorm not found') throw new Error('typeorm not found')
} }
await run('ts-node', [typeorm, 'migration:create', '--name', name], project) await run('ts-node', [typeorm, 'migration:generate', '--name', name], project)
} }
function findTsConfig(file: string): string { function findTsConfig(file: string): string {

View File

@ -19,9 +19,9 @@ app:
migrationsRun: false migrationsRun: false
logging: true logging: true
entities: entities:
- src/entities/index.ts - src/entity-schemas/*Entity.ts
migrations: migrations:
- src/migrations/index.ts - src/migrations/index.ts
cli: cli:
migrationsDir: src/migrations migrationsDir: src/migrations
entitiesDir: src/entities entitiesDir: src/entity-schemas

View File

@ -1,3 +1,3 @@
const {ConfigReader} = require('@rondo.dev/server') const {ConfigReader} = require('@rondo.dev/config')
const config = new ConfigReader(__dirname).read() const config = new ConfigReader(__dirname).read()
module.exports = JSON.parse(JSON.stringify(config.get('app.db'))) module.exports = JSON.parse(JSON.stringify(config.get('app.db')))

View File

@ -20,10 +20,10 @@ export interface ServerBootstrapParams {
} }
// tslint:disable-next-line // tslint:disable-next-line
function getFunctions(obj: object): Function[] { function objToArray(obj: object): Function[] {
return Object.keys(obj) return Object.keys(obj)
.filter(k => !k.startsWith('_'))
.map(k => (obj as any)[k]) .map(k => (obj as any)[k])
.filter(f => typeof f === 'function')
} }
export class ServerBootstrap implements Bootstrap { export class ServerBootstrap implements Bootstrap {
@ -45,10 +45,10 @@ export class ServerBootstrap implements Bootstrap {
db: { db: {
...params.config.app.db, ...params.config.app.db,
entities: params.entities entities: params.entities
? getFunctions(params.entities) ? objToArray(params.entities)
: params.config.app.db.entities, : params.config.app.db.entities,
migrations: params.migrations migrations: params.migrations
? getFunctions(params.migrations) ? objToArray(params.migrations)
: params.config.app.db.migrations, : params.config.app.db.migrations,
}, },
}, },

View File

@ -1,7 +1,7 @@
import { ServerBootstrap } from './application' import { ServerBootstrap } from './application'
import { configureServer } from './application/configureServer' import { configureServer } from './application/configureServer'
import { config } from './config' import { config } from './config'
import * as entities from './entities' import * as entities from './entity-schemas'
import * as migrations from './migrations' import * as migrations from './migrations'
export default new ServerBootstrap({ export default new ServerBootstrap({

View File

@ -1,17 +1,17 @@
import { CreateDateColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' // import { CreateDateColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
const transformer = { // const transformer = {
from: (value: Date) => !isNaN(value.getTime()) ? value.toISOString() : value, // from: (value: Date) => !isNaN(value.getTime()) ? value.toISOString() : value,
to: (value: undefined | null | string) => value ? new Date(value) : value, // to: (value: undefined | null | string) => value ? new Date(value) : value,
} // }
export abstract class BaseEntity { // export abstract class BaseEntity {
@PrimaryGeneratedColumn({type: 'bigint'}) // @PrimaryGeneratedColumn({type: 'bigint'})
id!: number // id!: number
@CreateDateColumn({transformer, type: 'datetime'}) // @CreateDateColumn({transformer, type: 'datetime'})
createDate!: string // createDate!: string
@UpdateDateColumn({transformer, type: 'datetime'}) // @UpdateDateColumn({transformer, type: 'datetime'})
updateDate!: string // updateDate!: string
} // }

View File

@ -1,8 +1,8 @@
import { Column, Entity } from 'typeorm' // import { Column, Entity } from 'typeorm'
import { BaseEntity } from './BaseEntity' // import { BaseEntity } from './BaseEntity'
@Entity() // @Entity()
export class Role extends BaseEntity { // export class Role extends BaseEntity {
@Column({ unique: true }) // @Column({ unique: true })
name!: string // name!: string
} // }

View File

@ -1,22 +1,22 @@
import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm' // import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm'
import { DefaultSession } from '../session/DefaultSession' // import { DefaultSession } from '../session/DefaultSession'
import { User } from './User' // import { User } from './User'
@Entity() // @Entity()
export class Session implements DefaultSession { // export class Session implements DefaultSession {
@PrimaryColumn() // @PrimaryColumn()
id!: string // id!: string
@Index() // @Index()
@Column({type: 'bigint'}) // @Column({type: 'bigint'})
expiredAt: number = Date.now() // expiredAt: number = Date.now()
@ManyToOne(type => User, user => user.sessions) // @ManyToOne(type => User, user => user.sessions)
user?: User // user?: User
@Column({ nullable: true }) // @Column({ nullable: true })
userId!: number // userId!: number
@Column('text') // @Column('text')
json = '' // json = ''
} // }

View File

@ -1,20 +1,20 @@
import { Column, Entity, Index, ManyToOne, OneToMany } from 'typeorm' // import { Column, Entity, Index, ManyToOne, OneToMany } from 'typeorm'
import { BaseEntity } from './BaseEntity' // import { BaseEntity } from './BaseEntity'
import { User } from './User' // import { User } from './User'
import { UserTeam } from './UserTeam' // import { UserTeam } from './UserTeam'
@Entity() // @Entity()
export class Team extends BaseEntity { // export class Team extends BaseEntity {
@Column() // @Column()
name!: string // name!: string
@Column() // @Column()
@Index() // @Index()
userId!: number // userId!: number
@ManyToOne(type => User) // @ManyToOne(type => User)
user?: User // user?: User
@OneToMany(type => UserTeam, userTeam => userTeam.team) // @OneToMany(type => UserTeam, userTeam => userTeam.team)
userTeams!: UserTeam[] // userTeams!: UserTeam[]
} // }

View File

@ -1,27 +1,27 @@
import { Column, Entity, OneToMany } from 'typeorm' // import { Column, Entity, OneToMany } from 'typeorm'
import { BaseEntity } from './BaseEntity' // import { BaseEntity } from './BaseEntity'
import { Session } from './Session' // import { Session } from './Session'
import { UserEmail } from './UserEmail' // import { UserEmail } from './UserEmail'
import { UserTeam } from './UserTeam' // import { UserTeam } from './UserTeam'
@Entity() // @Entity()
export class User extends BaseEntity { // export class User extends BaseEntity {
@Column() // @Column()
firstName!: string // firstName!: string
@Column() // @Column()
lastName!: string // lastName!: string
@OneToMany(type => UserEmail, email => email.user) // @OneToMany(type => UserEmail, email => email.user)
emails!: UserEmail[] // emails!: UserEmail[]
// bcrypt encoded password // // bcrypt encoded password
@Column({nullable: true, length: '60', select: false}) // @Column({nullable: true, length: '60', select: false})
password?: string // password?: string
@OneToMany(type => Session, session => session.user) // @OneToMany(type => Session, session => session.user)
sessions!: Session[] // sessions!: Session[]
@OneToMany(type => UserTeam, userTeam => userTeam.user) // @OneToMany(type => UserTeam, userTeam => userTeam.user)
userTeams!: UserTeam[] // userTeams!: UserTeam[]
} // }

View File

@ -1,15 +1,15 @@
import { Column, Entity, ManyToOne } from 'typeorm' // import { Column, Entity, ManyToOne } from 'typeorm'
import { BaseEntity } from './BaseEntity' // import { BaseEntity } from './BaseEntity'
import { User } from './User' // import { User } from './User'
@Entity() // @Entity()
export class UserEmail extends BaseEntity { // export class UserEmail extends BaseEntity {
@Column({unique: true}) // @Column({unique: true})
email!: string // email!: string
@ManyToOne(type => User, user => user.emails) // @ManyToOne(type => User, user => user.emails)
user?: User // user?: User
@Column() // @Column()
userId?: number = undefined // userId?: number = undefined
} // }

View File

@ -1,26 +1,26 @@
import { Column, Entity, ManyToOne } from 'typeorm' // import { Column, Entity, ManyToOne } from 'typeorm'
import { BaseEntity } from './BaseEntity' // import { BaseEntity } from './BaseEntity'
import { Role } from './Role' // import { Role } from './Role'
import { Team } from './Team' // import { Team } from './Team'
import { User } from './User' // import { User } from './User'
@Entity() // @Entity()
export class UserTeam extends BaseEntity { // export class UserTeam extends BaseEntity {
@ManyToOne(type => User, user => user.userTeams) // @ManyToOne(type => User, user => user.userTeams)
user!: User // user!: User
@Column() // @Column()
userId!: number // userId!: number
@ManyToOne(type => Team, team => team.userTeams) // @ManyToOne(type => Team, team => team.userTeams)
team?: Team // team?: Team
@Column() // @Column()
teamId!: number // teamId!: number
@ManyToOne(type => Role) // @ManyToOne(type => Role)
role?: Role // role?: Role
@Column() // @Column()
roleId!: number // roleId!: number
} // }

View File

@ -1,7 +1,7 @@
export * from './BaseEntity' // export * from './BaseEntity'
export * from './Role' // export * from './Role'
export * from './Session' // export * from './Session'
export * from './Team' // export * from './Team'
export * from './User' // export * from './User'
export * from './UserEmail' // export * from './UserEmail'
export * from './UserTeam' // export * from './UserTeam'

View File

@ -0,0 +1,25 @@
import { EntitySchemaColumnOptions } from 'typeorm'
const transformer = {
from: (value: Date) => !isNaN(value.getTime()) ? value.toISOString() : value,
to: (value: undefined | null | string) => value ? new Date(value) : value,
}
export const BaseEntitySchemaPart: Record<
'id' | 'createDate' | 'updateDate', EntitySchemaColumnOptions> = {
id: {
type: 'integer',
primary: true,
generated: true,
},
createDate: {
type: 'datetime',
createDate: true,
transformer,
},
updateDate: {
type: 'datetime',
updateDate: true,
transformer,
},
}

View File

@ -0,0 +1,14 @@
import { EntitySchema } from 'typeorm'
import { Role } from '@rondo.dev/common'
import { BaseEntitySchemaPart } from './BaseEntitySchemaPart'
export const RoleEntity = new EntitySchema<Role>({
name: 'role',
columns: {
...BaseEntitySchemaPart,
name: {
type: String,
unique: true,
},
},
})

View File

@ -0,0 +1,34 @@
import { Session } from '@rondo.dev/common'
import { EntitySchema } from 'typeorm'
export const SessionEntity = new EntitySchema<Session>({
name: 'session',
columns: {
id: {
type: String,
primary: true,
},
expiredAt: {
type: Number,
// default: () => Date.now(),
},
userId: {
type: Number,
nullable: true,
},
json: {
type: 'text',
// default: '',
},
},
relations: {
user: {
type: 'many-to-one',
target: 'user',
inverseSide: 'sessions',
},
},
indices: [{
columns: ['expiredAt'],
}],
})

View File

@ -0,0 +1,29 @@
import { EntitySchema } from 'typeorm'
import { Team } from '@rondo.dev/common'
import { BaseEntitySchemaPart } from './BaseEntitySchemaPart'
export const TeamEntity = new EntitySchema<Team>({
name: 'team',
columns: {
...BaseEntitySchemaPart,
name: {
type: String,
},
userId: {
type: Number,
},
},
relations: {
user: {
type: 'many-to-one',
target: 'user',
},
userTeams: {
type: 'one-to-many',
target: 'user_team',
},
},
indices: [{
columns: ['userId'],
}],
})

View File

@ -0,0 +1,23 @@
import { BaseEntitySchemaPart } from './BaseEntitySchemaPart'
import { EntitySchema } from 'typeorm'
import { UserEmail } from '@rondo.dev/common'
export const UserEmailEntity = new EntitySchema<UserEmail>({
name: 'user_email',
columns: {
...BaseEntitySchemaPart,
email: {
type: String,
unique: true,
},
userId: {
type: Number,
},
},
relations: {
user: {
type: 'many-to-one',
target: 'user',
},
},
})

View File

@ -0,0 +1,36 @@
import { BaseEntitySchemaPart } from './BaseEntitySchemaPart'
import { EntitySchema } from 'typeorm'
import { User } from '@rondo.dev/common'
export const UserEntity = new EntitySchema<User>({
name: 'user',
columns: {
...BaseEntitySchemaPart,
firstName: {
type: String,
},
lastName: {
type: String,
},
password: {
type: String,
length: 60,
select: false,
nullable: true,
},
},
relations: {
emails: {
type: 'one-to-many',
target: 'user_email',
},
sessions: {
type: 'one-to-many',
target: 'session',
},
userTeams: {
type: 'one-to-many',
target: 'team',
},
},
})

View File

@ -0,0 +1,33 @@
import { BaseEntitySchemaPart } from './BaseEntitySchemaPart'
import { EntitySchema } from 'typeorm'
import { UserTeam } from '@rondo.dev/common'
export const UserTeamEntity = new EntitySchema<UserTeam>({
name: 'user_team',
columns: {
...BaseEntitySchemaPart,
userId: {
type: Number,
},
teamId: {
type: Number,
},
roleId: {
type: Number,
},
},
relations: {
user: {
type: 'many-to-one',
target: 'user',
},
team: {
type: 'many-to-one',
target: 'team',
},
role: {
type: 'many-to-one',
target: 'role',
},
},
})

View File

@ -0,0 +1,6 @@
export * from './RoleEntity'
export * from './SessionEntity'
export * from './TeamEntity'
export * from './UserEmailEntity'
export * from './UserEntity'
export * from './UserTeamEntity'

View File

@ -5,7 +5,7 @@ if (require.main === module) {
} }
export * from './application' export * from './application'
export * from './cli' export * from './cli'
export * from './entities' export * from './entity-schemas'
export * from './error' export * from './error'
export * from './logger' export * from './logger'
export * from './middleware' export * from './middleware'

View File

@ -1,12 +1,13 @@
import { Session } from '@rondo.dev/common'
import { TypeORMTransactionManager } from '@rondo.dev/db-typeorm'
import ExpressSession from 'express-session' import ExpressSession from 'express-session'
import { UrlWithStringQuery } from 'url' import { UrlWithStringQuery } from 'url'
import { Session as SessionEntity } from '../entities/Session' import { SessionEntity } from '../entity-schemas'
import { apiLogger } from '../logger' import { apiLogger } from '../logger'
import { DefaultSession } from '../session'
import { SessionStore } from '../session/SessionStore' import { SessionStore } from '../session/SessionStore'
import { Handler } from './Handler' import { Handler } from './Handler'
import { Middleware } from './Middleware' import { Middleware } from './Middleware'
import { DefaultSession } from '../session'
import { TypeORMTransactionManager } from '@rondo.dev/db-typeorm'
export interface SessionMiddlewareParams { export interface SessionMiddlewareParams {
transactionManager: TypeORMTransactionManager transactionManager: TypeORMTransactionManager
@ -45,7 +46,7 @@ export class SessionMiddleware implements Middleware {
protected buildSession = ( protected buildSession = (
sessionData: Express.SessionData, sessionData: Express.SessionData,
sess: DefaultSession, sess: DefaultSession,
): SessionEntity => { ): Session => {
return {...sess, userId: sessionData.userId } return {...sess, userId: sessionData.userId }
} }

View File

@ -1,10 +1,9 @@
import { TeamAddUserParams, TeamCreateParams, TeamRemoveParams, TeamService, TeamUpdateParams, trim, UserPermissions } from '@rondo.dev/common' import { TeamAddUserParams, TeamCreateParams, TeamRemoveParams, TeamService, TeamUpdateParams, trim, UserPermissions, UserTeam } from '@rondo.dev/common'
import { UserInTeam } from '@rondo.dev/common/lib/team/UserInTeam' import { UserInTeam } from '@rondo.dev/common/lib/team/UserInTeam'
import Validator from '@rondo.dev/validator' import Validator from '@rondo.dev/validator'
import { Team } from '../entities/Team'
import { UserTeam } from '../entities/UserTeam'
import { ensureLoggedIn, Context, RPC } from './RPC' import { ensureLoggedIn, Context, RPC } from './RPC'
import { TypeORMDatabase } from '@rondo.dev/db-typeorm' import { TypeORMDatabase } from '@rondo.dev/db-typeorm'
import { TeamEntity, UserTeamEntity } from '../entity-schemas'
@ensureLoggedIn @ensureLoggedIn
export class SQLTeamService implements RPC<TeamService> { export class SQLTeamService implements RPC<TeamService> {
@ -22,7 +21,7 @@ export class SQLTeamService implements RPC<TeamService> {
.ensure('userId') .ensure('userId')
.throw() .throw()
const team = await this.db.getRepository(Team).save({ const team = await this.db.getRepository(TeamEntity).save({
name, name,
userId, userId,
}) })
@ -45,10 +44,10 @@ export class SQLTeamService implements RPC<TeamService> {
userId, userId,
}) })
await this.db.getRepository(UserTeam) await this.db.getRepository(UserTeamEntity)
.delete({teamId: id, userId}) .delete({teamId: id, userId})
await this.db.getRepository(Team) await this.db.getRepository(TeamEntity)
.delete(id) .delete(id)
return {id} return {id}
@ -62,7 +61,7 @@ export class SQLTeamService implements RPC<TeamService> {
userId, userId,
}) })
await this.db.getRepository(Team) await this.db.getRepository(TeamEntity)
.update({ .update({
id, id,
}, { }, {
@ -74,7 +73,7 @@ export class SQLTeamService implements RPC<TeamService> {
async addUser(context: Context, params: TeamAddUserParams) { async addUser(context: Context, params: TeamAddUserParams) {
const {userId, teamId, roleId} = params const {userId, teamId, roleId} = params
await this.db.getRepository(UserTeam) await this.db.getRepository(UserTeamEntity)
.save({userId, teamId, roleId}) .save({userId, teamId, roleId})
const userTeam = await this._createFindUserInTeamQuery() const userTeam = await this._createFindUserInTeamQuery()
@ -97,20 +96,20 @@ export class SQLTeamService implements RPC<TeamService> {
}) })
// TODO check if this is the last admin team member // TODO check if this is the last admin team member
await this.db.getRepository(UserTeam) await this.db.getRepository(UserTeamEntity)
.delete({userId, teamId, roleId}) .delete({userId, teamId, roleId})
return {teamId, userId, roleId} return {teamId, userId, roleId}
} }
async findOne(context: Context, id: number) { async findOne(context: Context, id: number) {
return this.db.getRepository(Team).findOne(id) return this.db.getRepository(TeamEntity).findOne(id)
} }
async find(context: Context) { async find(context: Context) {
const userId = context.user!.id const userId = context.user!.id
return this.db.getRepository(Team) return this.db.getRepository(TeamEntity)
.createQueryBuilder('team') .createQueryBuilder('team')
.select('team') .select('team')
.innerJoin('team.userTeams', 'ut') .innerJoin('team.userTeams', 'ut')
@ -149,7 +148,7 @@ export class SQLTeamService implements RPC<TeamService> {
} }
protected _createFindUserInTeamQuery() { protected _createFindUserInTeamQuery() {
return this.db.getRepository(UserTeam) return this.db.getRepository(UserTeamEntity)
.createQueryBuilder('ut') .createQueryBuilder('ut')
.select('ut') .select('ut')
.innerJoinAndSelect('ut.user', 'user') .innerJoinAndSelect('ut.user', 'user')

View File

@ -1,9 +1,8 @@
import { UserService } from '@rondo.dev/common' import { UserService } from '@rondo.dev/common'
import { TypeORMDatabase } from '@rondo.dev/db-typeorm' import { TypeORMDatabase } from '@rondo.dev/db-typeorm'
import { hash } from 'bcrypt' import { hash } from 'bcrypt'
import { User } from '../entities/User'
import { UserEmail } from '../entities/UserEmail'
import { Context, ensureLoggedIn, RPC } from './RPC' import { Context, ensureLoggedIn, RPC } from './RPC'
import { UserEntity, UserEmailEntity } from '../entity-schemas'
const SALT_ROUNDS = 10 const SALT_ROUNDS = 10
// const MIN_PASSWORD_LENGTH = 10 // const MIN_PASSWORD_LENGTH = 10
@ -16,7 +15,7 @@ export class SQLUserService implements RPC<UserService> {
const userId = context.user!.id const userId = context.user!.id
// current user should always exist in the database // current user should always exist in the database
const user = (await this.db.getRepository(User).findOne(userId, { const user = (await this.db.getRepository(UserEntity).findOne(userId, {
relations: ['emails'], relations: ['emails'],
}))! }))!
@ -29,7 +28,7 @@ export class SQLUserService implements RPC<UserService> {
} }
async findUserByEmail(context: Context, email: string) { async findUserByEmail(context: Context, email: string) {
const userEmail = await this.db.getRepository(UserEmail) const userEmail = await this.db.getRepository(UserEmailEntity)
.findOne({ email }, { .findOne({ email }, {
relations: ['user'], relations: ['user'],
}) })

View File

@ -4,8 +4,7 @@ import Validator from '@rondo.dev/validator'
import { compare, hash } from 'bcrypt' import { compare, hash } from 'bcrypt'
import { validate as validateEmail } from 'email-validator' import { validate as validateEmail } from 'email-validator'
import createError from 'http-errors' import createError from 'http-errors'
import { User } from '../entities/User' import { UserEntity, UserEmailEntity } from '../entity-schemas'
import { UserEmail } from '../entities/UserEmail'
const SALT_ROUNDS = 10 const SALT_ROUNDS = 10
const MIN_PASSWORD_LENGTH = 10 const MIN_PASSWORD_LENGTH = 10
@ -35,11 +34,11 @@ export class SQLAuthService implements AuthService {
.throw() .throw()
const password = await this.hash(payload.password) const password = await this.hash(payload.password)
const user = await this.db.getRepository(User).save({ const user = await this.db.getRepository(UserEntity).save({
...newUser, ...newUser,
password, password,
}) })
await this.db.getRepository(UserEmail).save({ await this.db.getRepository(UserEmailEntity).save({
email: newUser.username, email: newUser.username,
userId: user.id, userId: user.id,
}) })
@ -50,7 +49,7 @@ export class SQLAuthService implements AuthService {
} }
async findOne(id: number) { async findOne(id: number) {
const user = await this.db.getRepository(User).findOne(id, { const user = await this.db.getRepository(UserEntity).findOne(id, {
relations: ['emails'], relations: ['emails'],
}) })
@ -67,7 +66,7 @@ export class SQLAuthService implements AuthService {
} }
async findUserByEmail(email: string) { async findUserByEmail(email: string) {
const userEmail = await this.db.getRepository(UserEmail) const userEmail = await this.db.getRepository(UserEmailEntity)
.findOne({ email }, { .findOne({ email }, {
relations: ['user'], relations: ['user'],
}) })
@ -92,7 +91,7 @@ export class SQLAuthService implements AuthService {
newPassword: string newPassword: string
}) { }) {
const {userId, oldPassword, newPassword} = params const {userId, oldPassword, newPassword} = params
const userRepository = this.db.getRepository(User) const userRepository = this.db.getRepository(UserEntity)
const user = await userRepository const user = await userRepository
.createQueryBuilder('user') .createQueryBuilder('user')
.select('user') .select('user')
@ -110,7 +109,7 @@ export class SQLAuthService implements AuthService {
async validateCredentials(credentials: Credentials) { async validateCredentials(credentials: Credentials) {
const {username, password} = credentials const {username, password} = credentials
const user = await this.db.getRepository(User) const user = await this.db.getRepository(UserEntity)
.createQueryBuilder('user') .createQueryBuilder('user')
.select('user') .select('user')
.addSelect('user.password') .addSelect('user.password')
@ -132,7 +131,7 @@ export class SQLAuthService implements AuthService {
} }
async findUserEmails(userId: number) { async findUserEmails(userId: number) {
return this.db.getRepository(UserEmail).find({ userId }) return this.db.getRepository(UserEmailEntity).find({ userId })
} }
protected async hash(password: string): Promise<string> { protected async hash(password: string): Promise<string> {

View File

@ -1,14 +1,14 @@
import { UserPermissions } from '@rondo.dev/common' import { UserPermissions } from '@rondo.dev/common'
import createError from 'http-errors' import createError from 'http-errors'
import { UserTeam } from '../entities/UserTeam'
import { TypeORMDatabase } from '@rondo.dev/db-typeorm' import { TypeORMDatabase } from '@rondo.dev/db-typeorm'
import { UserTeamEntity } from '../entity-schemas'
export class SQLUserPermissions implements UserPermissions { export class SQLUserPermissions implements UserPermissions {
constructor(protected readonly db: TypeORMDatabase) {} constructor(protected readonly db: TypeORMDatabase) {}
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.db.getRepository(UserTeam) const result = await this.db.getRepository(UserTeamEntity)
.findOne({ .findOne({
where: {userId, teamId}, where: {userId, teamId},
}) })

View File

@ -8,7 +8,6 @@ import supertest from 'supertest'
import { Connection, QueryRunner } from 'typeorm' import { Connection, QueryRunner } from 'typeorm'
import { AppServer } from '../application/AppServer' import { AppServer } from '../application/AppServer'
import { Bootstrap } from '../application/Bootstrap' import { Bootstrap } from '../application/Bootstrap'
import { Role } from '../entities/Role'
import { RequestTester } from './RequestTester' import { RequestTester } from './RequestTester'
import { TypeORMTransactionManager } from '@rondo.dev/db-typeorm' import { TypeORMTransactionManager } from '@rondo.dev/db-typeorm'
import { TRANSACTION_ID, TRANSACTION } from '@rondo.dev/db' import { TRANSACTION_ID, TRANSACTION } from '@rondo.dev/db'
@ -74,12 +73,6 @@ export class TestUtils<T extends Routes> {
}) })
} }
async createRole(name: string) {
return this.transactionManager
.getRepository(Role)
.save({name})
}
async getError(promise: Promise<unknown>): Promise<Error> { async getError(promise: Promise<unknown>): Promise<Error> {
let error!: Error let error!: Error
try { try {