Add Routes to application

This commit is contained in:
Jerko Steiner 2019-01-24 17:55:49 +01:00
parent f0943cfe80
commit 2ed3aeac26
14 changed files with 263 additions and 22 deletions

View File

@ -8,7 +8,6 @@ export interface ICommentProps {
export class CommentVote extends React.PureComponent { export class CommentVote extends React.PureComponent {
render() { render() {
return ( return (
) )
} }
} }

View File

@ -1,8 +1,7 @@
import assert from 'assert'
import axios from 'axios' import axios from 'axios'
import {IHTTPClient} from './IHTTPClient' import {IHTTPClient} from './IHTTPClient'
import {IHeader} from './IHeader' import {IHeader} from './IHeader'
import {IMethod, IRoutes} from '@rondo/common' import {IMethod, IRoutes, URLFormatter} from '@rondo/common'
import {IRequest} from './IRequest' import {IRequest} from './IRequest'
import {IResponse} from './IResponse' import {IResponse} from './IResponse'
import {ITypedRequestParams} from './ITypedRequestParams' import {ITypedRequestParams} from './ITypedRequestParams'
@ -13,12 +12,14 @@ interface IRequestor {
export class HTTPClient<T extends IRoutes> implements IHTTPClient<T> { export class HTTPClient<T extends IRoutes> implements IHTTPClient<T> {
protected readonly requestor: IRequestor protected readonly requestor: IRequestor
protected readonly formatter: URLFormatter
constructor( constructor(
protected readonly baseURL = '', protected readonly baseURL = '',
protected readonly headers?: IHeader, protected readonly headers?: IHeader,
) { ) {
this.requestor = this.createRequestor() this.requestor = this.createRequestor()
this.formatter = new URLFormatter()
} }
protected createRequestor(): IRequestor { protected createRequestor(): IRequestor {
@ -33,12 +34,7 @@ export class HTTPClient<T extends IRoutes> implements IHTTPClient<T> {
M extends IMethod, M extends IMethod,
>(params: ITypedRequestParams<T, P, M>): Promise<T[P][M]['response']> { >(params: ITypedRequestParams<T, P, M>): Promise<T[P][M]['response']> {
const url = params.path.replace(/:[a-zA-Z0-9-]+/g, (match) => { const url = this.formatter.format(params.path, params.params)
const key = match.substring(1)
assert(params.params, 'Params is required, but not defined')
assert(params.params!.hasOwnProperty(key))
return params.params![key]
})
const response = await this.requestor.request({ const response = await this.requestor.request({
method: params.method, method: params.method,

View File

@ -0,0 +1,3 @@
export interface IRequestParams {
[key: string]: string | number
}

View File

@ -0,0 +1,27 @@
import assert from 'assert'
import {IRequestParams} from './IRequestParams'
export interface IURLFormatterOptions {
readonly baseURL: string
readonly regex: RegExp
}
export class URLFormatter {
constructor(readonly params: IURLFormatterOptions = {
baseURL: '',
regex: /:[a-zA-Z0-9-]+/g,
}) {}
format(url: string, params?: IRequestParams) {
if (!params) {
return url
}
const formattedUrl = url.replace(this.params.regex, match => {
const key = match.substring(1)
assert(params.hasOwnProperty(key))
return String(params![key])
})
return this.params.baseURL + formattedUrl
}
}

View File

@ -3,6 +3,8 @@ export * from './IComment'
export * from './ICommentTree' export * from './ICommentTree'
export * from './ICredentials' export * from './ICredentials'
export * from './IRoutes' export * from './IRoutes'
export * from './IRequestParams'
export * from './ISite' export * from './ISite'
export * from './ITeam' export * from './ITeam'
export * from './IUser' export * from './IUser'
export * from './URLFormatter'

View File

@ -8,7 +8,7 @@ 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 {ITransactionManager} from '../database/ITransactionManager' import {ITransactionManager} from '../database/ITransactionManager'
import {IUserService, UserService} from '../services' import * as services from '../services'
import {loggerFactory, LoggerFactory} from '../logger/LoggerFactory' import {loggerFactory, LoggerFactory} from '../logger/LoggerFactory'
import {urlencoded, json} from 'body-parser' import {urlencoded, json} from 'body-parser'
@ -16,14 +16,26 @@ export class Application implements IApplication {
readonly transactionManager: ITransactionManager readonly transactionManager: ITransactionManager
readonly server: express.Application readonly server: express.Application
readonly userService: IUserService readonly userService: services.IUserService
readonly teamService: services.ITeamService
readonly siteService: services.ISiteService
readonly storyService: services.IStoryService
readonly commentService: services.ICommentService
readonly authenticator: middleware.Authenticator readonly authenticator: middleware.Authenticator
readonly loggerFactory: LoggerFactory = loggerFactory readonly loggerFactory: LoggerFactory = loggerFactory
constructor(readonly config: IConfig, readonly database: IDatabase) { constructor(readonly config: IConfig, readonly database: IDatabase) {
this.transactionManager = database.transactionManager this.transactionManager = database.transactionManager
this.userService = new UserService(this.transactionManager) this.userService = new services.UserService(this.transactionManager)
this.teamService = new services.TeamService(this.transactionManager)
this.siteService = new services.SiteService(this.transactionManager)
this.storyService = new services.StoryService(
this.transactionManager, this.siteService)
this.commentService = new services.CommentService(this.transactionManager)
this.authenticator = new middleware.Authenticator(this.userService) this.authenticator = new middleware.Authenticator(this.userService)
this.server = this.createServer() this.server = this.createServer()
@ -78,11 +90,32 @@ export class Application implements IApplication {
router.use('/app', routes.application) router.use('/app', routes.application)
router.use('/api', json()) router.use('/api', json())
router.use('/api', new routes.UserRoutes( router.use('/api', new routes.UserRoutes(
this.userService, this.userService,
this.createTransactionalRouter(), this.createTransactionalRouter(),
).handle) ).handle)
router.use('/api', new routes.TeamRoutes(
this.teamService,
this.createTransactionalRouter(),
).handle)
router.use('/api', new routes.SiteRoutes(
this.siteService,
this.createTransactionalRouter(),
).handle)
router.use('/api', new routes.StoryRoutes(
this.storyService,
this.createTransactionalRouter(),
).handle)
router.use('/api', new routes.CommentRoutes(
this.commentService,
this.createTransactionalRouter(),
).handle)
router.use('/api', new middleware.ErrorApiHandler(apiLogger).handle) router.use('/api', new middleware.ErrorApiHandler(apiLogger).handle)
} }

View File

@ -14,7 +14,6 @@ export class Team extends BaseEntity {
userId!: number userId!: number
@ManyToOne(type => User) @ManyToOne(type => User)
@Column()
user?: User user?: User
@OneToMany(type => Site, site => site.team) @OneToMany(type => Site, site => site.team)

View File

@ -0,0 +1,101 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class test1548347305012 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`);
await queryRunner.query(`DROP INDEX "IDX_fe13edd1431a248a0eeac11ae4"`);
await queryRunner.query(`CREATE TABLE "temporary_spam" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "FK_ec8bc4fa789466cf62f5949f5cc" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1bf468db8f4d18b424bb3eafae5" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_spam"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "spam"`);
await queryRunner.query(`DROP TABLE "spam"`);
await queryRunner.query(`ALTER TABLE "temporary_spam" RENAME TO "spam"`);
await queryRunner.query(`CREATE TABLE "temporary_vote" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "FK_f5de237a438d298031d11a57c3b" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_ad37adcff60fdb9670a97868ab1" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_vote"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "vote"`);
await queryRunner.query(`DROP TABLE "vote"`);
await queryRunner.query(`ALTER TABLE "temporary_vote" RENAME TO "vote"`);
await queryRunner.query(`CREATE TABLE "temporary_site" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "domain" varchar NOT NULL, "userId" integer NOT NULL, "teamId" integer NOT NULL, CONSTRAINT "FK_4a06baede7d9cf51aef879fb0e4" FOREIGN KEY ("teamId") REFERENCES "team" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e03827c061fbf85fd3aae454aec" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_site"("id", "createDate", "updateDate", "name", "domain", "userId", "teamId") SELECT "id", "createDate", "updateDate", "name", "domain", "userId", "teamId" FROM "site"`);
await queryRunner.query(`DROP TABLE "site"`);
await queryRunner.query(`ALTER TABLE "temporary_site" RENAME TO "site"`);
await queryRunner.query(`CREATE TABLE "temporary_team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')))`);
await queryRunner.query(`INSERT INTO "temporary_team"("id", "createDate", "updateDate") SELECT "id", "createDate", "updateDate" FROM "team"`);
await queryRunner.query(`DROP TABLE "team"`);
await queryRunner.query(`ALTER TABLE "temporary_team" RENAME TO "team"`);
await queryRunner.query(`CREATE TABLE "temporary_team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "userId" integer NOT NULL)`);
await queryRunner.query(`INSERT INTO "temporary_team"("id", "createDate", "updateDate") SELECT "id", "createDate", "updateDate" FROM "team"`);
await queryRunner.query(`DROP TABLE "team"`);
await queryRunner.query(`ALTER TABLE "temporary_team" RENAME TO "team"`);
await queryRunner.query(`CREATE TABLE "temporary_site" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "domain" varchar NOT NULL, "userId" integer NOT NULL, "teamId" integer NOT NULL, CONSTRAINT "UQ_a8c109f03677d373ab0256f82c6" UNIQUE ("domain"), CONSTRAINT "FK_4a06baede7d9cf51aef879fb0e4" FOREIGN KEY ("teamId") REFERENCES "team" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e03827c061fbf85fd3aae454aec" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_site"("id", "createDate", "updateDate", "name", "domain", "userId", "teamId") SELECT "id", "createDate", "updateDate", "name", "domain", "userId", "teamId" FROM "site"`);
await queryRunner.query(`DROP TABLE "site"`);
await queryRunner.query(`ALTER TABLE "temporary_site" RENAME TO "site"`);
await queryRunner.query(`CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `);
await queryRunner.query(`CREATE INDEX "IDX_55a938fda82579fd3ec29b3c28" ON "team" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_e03827c061fbf85fd3aae454ae" ON "site" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_4a06baede7d9cf51aef879fb0e" ON "site" ("teamId") `);
await queryRunner.query(`CREATE INDEX "IDX_fe13edd1431a248a0eeac11ae4" ON "comment" ("storyId") `);
await queryRunner.query(`CREATE TABLE "temporary_spam" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "spam_userid_commentid" UNIQUE ("userId", "commentId"), CONSTRAINT "FK_ec8bc4fa789466cf62f5949f5cc" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1bf468db8f4d18b424bb3eafae5" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_spam"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "spam"`);
await queryRunner.query(`DROP TABLE "spam"`);
await queryRunner.query(`ALTER TABLE "temporary_spam" RENAME TO "spam"`);
await queryRunner.query(`CREATE TABLE "temporary_vote" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "vote_userid_commentid" UNIQUE ("userId", "commentId"), CONSTRAINT "FK_f5de237a438d298031d11a57c3b" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_ad37adcff60fdb9670a97868ab1" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_vote"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "vote"`);
await queryRunner.query(`DROP TABLE "vote"`);
await queryRunner.query(`ALTER TABLE "temporary_vote" RENAME TO "vote"`);
await queryRunner.query(`DROP INDEX "IDX_55a938fda82579fd3ec29b3c28"`);
await queryRunner.query(`CREATE TABLE "temporary_team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "userId" integer NOT NULL, CONSTRAINT "FK_55a938fda82579fd3ec29b3c28e" FOREIGN KEY ("userId") REFERENCES "user" ("id"))`);
await queryRunner.query(`INSERT INTO "temporary_team"("id", "createDate", "updateDate", "name", "userId") SELECT "id", "createDate", "updateDate", "name", "userId" FROM "team"`);
await queryRunner.query(`DROP TABLE "team"`);
await queryRunner.query(`ALTER TABLE "temporary_team" RENAME TO "team"`);
await queryRunner.query(`CREATE INDEX "IDX_55a938fda82579fd3ec29b3c28" ON "team" ("userId") `);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP INDEX "IDX_55a938fda82579fd3ec29b3c28"`);
await queryRunner.query(`ALTER TABLE "team" RENAME TO "temporary_team"`);
await queryRunner.query(`CREATE TABLE "team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "userId" integer NOT NULL)`);
await queryRunner.query(`INSERT INTO "team"("id", "createDate", "updateDate", "name", "userId") SELECT "id", "createDate", "updateDate", "name", "userId" FROM "temporary_team"`);
await queryRunner.query(`DROP TABLE "temporary_team"`);
await queryRunner.query(`CREATE INDEX "IDX_55a938fda82579fd3ec29b3c28" ON "team" ("userId") `);
await queryRunner.query(`ALTER TABLE "vote" RENAME TO "temporary_vote"`);
await queryRunner.query(`CREATE TABLE "vote" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "FK_f5de237a438d298031d11a57c3b" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_ad37adcff60fdb9670a97868ab1" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "vote"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "temporary_vote"`);
await queryRunner.query(`DROP TABLE "temporary_vote"`);
await queryRunner.query(`ALTER TABLE "spam" RENAME TO "temporary_spam"`);
await queryRunner.query(`CREATE TABLE "spam" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "FK_ec8bc4fa789466cf62f5949f5cc" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1bf468db8f4d18b424bb3eafae5" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "spam"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "temporary_spam"`);
await queryRunner.query(`DROP TABLE "temporary_spam"`);
await queryRunner.query(`DROP INDEX "IDX_fe13edd1431a248a0eeac11ae4"`);
await queryRunner.query(`DROP INDEX "IDX_4a06baede7d9cf51aef879fb0e"`);
await queryRunner.query(`DROP INDEX "IDX_e03827c061fbf85fd3aae454ae"`);
await queryRunner.query(`DROP INDEX "IDX_55a938fda82579fd3ec29b3c28"`);
await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`);
await queryRunner.query(`ALTER TABLE "site" RENAME TO "temporary_site"`);
await queryRunner.query(`CREATE TABLE "site" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "domain" varchar NOT NULL, "userId" integer NOT NULL, "teamId" integer NOT NULL, CONSTRAINT "FK_4a06baede7d9cf51aef879fb0e4" FOREIGN KEY ("teamId") REFERENCES "team" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e03827c061fbf85fd3aae454aec" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "site"("id", "createDate", "updateDate", "name", "domain", "userId", "teamId") SELECT "id", "createDate", "updateDate", "name", "domain", "userId", "teamId" FROM "temporary_site"`);
await queryRunner.query(`DROP TABLE "temporary_site"`);
await queryRunner.query(`ALTER TABLE "team" RENAME TO "temporary_team"`);
await queryRunner.query(`CREATE TABLE "team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')))`);
await queryRunner.query(`INSERT INTO "team"("id", "createDate", "updateDate") SELECT "id", "createDate", "updateDate" FROM "temporary_team"`);
await queryRunner.query(`DROP TABLE "temporary_team"`);
await queryRunner.query(`ALTER TABLE "team" RENAME TO "temporary_team"`);
await queryRunner.query(`CREATE TABLE "team" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "url" varchar NOT NULL)`);
await queryRunner.query(`INSERT INTO "team"("id", "createDate", "updateDate") SELECT "id", "createDate", "updateDate" FROM "temporary_team"`);
await queryRunner.query(`DROP TABLE "temporary_team"`);
await queryRunner.query(`ALTER TABLE "site" RENAME TO "temporary_site"`);
await queryRunner.query(`CREATE TABLE "site" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "name" varchar NOT NULL, "domain" varchar NOT NULL, "userId" integer NOT NULL, "teamId" integer NOT NULL, CONSTRAINT "FK_4a06baede7d9cf51aef879fb0e4" FOREIGN KEY ("teamId") REFERENCES "team" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e03827c061fbf85fd3aae454aec" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "site"("id", "createDate", "updateDate", "name", "domain", "userId", "teamId") SELECT "id", "createDate", "updateDate", "name", "domain", "userId", "teamId" FROM "temporary_site"`);
await queryRunner.query(`DROP TABLE "temporary_site"`);
await queryRunner.query(`ALTER TABLE "vote" RENAME TO "temporary_vote"`);
await queryRunner.query(`CREATE TABLE "vote" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "UQ_5ef3b030c86a67d7c3cce97a978" UNIQUE ("userId", "commentId"), CONSTRAINT "FK_f5de237a438d298031d11a57c3b" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_ad37adcff60fdb9670a97868ab1" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "vote"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "temporary_vote"`);
await queryRunner.query(`DROP TABLE "temporary_vote"`);
await queryRunner.query(`ALTER TABLE "spam" RENAME TO "temporary_spam"`);
await queryRunner.query(`CREATE TABLE "spam" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createDate" datetime NOT NULL DEFAULT (datetime('now')), "updateDate" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "UQ_885dac94f112af83664ccd06dd9" UNIQUE ("userId", "commentId"), CONSTRAINT "FK_ec8bc4fa789466cf62f5949f5cc" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1bf468db8f4d18b424bb3eafae5" FOREIGN KEY ("commentId") REFERENCES "comment" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "spam"("id", "createDate", "updateDate", "userId", "commentId") SELECT "id", "createDate", "updateDate", "userId", "commentId" FROM "temporary_spam"`);
await queryRunner.query(`DROP TABLE "temporary_spam"`);
await queryRunner.query(`CREATE INDEX "IDX_fe13edd1431a248a0eeac11ae4" ON "comment" ("storyId") `);
await queryRunner.query(`CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `);
}
}

View File

@ -33,7 +33,7 @@ export class LoginRoutes extends BaseRoute<IAPIDef> {
} }
await req.logInPromise(user) await req.logInPromise(user)
res.redirect(req.baseUrl) res.redirect(req.baseUrl)
// TODO return user return user
}) })
t.get('/auth/logout', async (req, res) => { t.get('/auth/logout', async (req, res) => {

View File

@ -0,0 +1,61 @@
import {test} from '../test'
describe('team', () => {
test.withDatabase()
const t = test.request('/api')
let cookie!: string
let token!: string
beforeEach(async () => {
const session = await test.registerAccount()
cookie = session.cookie
token = session.token
t.setHeaders({ cookie, 'x-csrf-token': token })
})
async function createTeam(name: string) {
const response = await t
.post('/teams')
.send({
name: 'test',
})
.expect(200)
expect(response.body.id).toBeTruthy()
return response.body
}
describe('POST /teams', () => {
it('creates a new team', async () => {
const team = await createTeam('test')
expect(team.name).toEqual('test')
})
})
describe('GET /teams/:id', () => {
it('retrieves a team by id', async () => {
const team = await createTeam('test')
const response = await t
.get('/teams/:id', {
id: team.id,
})
.expect(200)
expect(response.body).toEqual(team)
})
})
describe('GET /my/teams', () => {
it('retrieves all teams belonging to current user', async () => {
const team = await createTeam('test')
const response = await t
.get('/my/teams')
.expect(200)
expect(response.body).toContainEqual(team)
})
})
// describe('GET /my/teams', () => {
// })
})

View File

@ -1,4 +1,8 @@
export * from './application'
export * from './BaseRoute' export * from './BaseRoute'
export * from './CommentRoutes'
export * from './LoginRoutes' export * from './LoginRoutes'
export * from './SiteRoutes'
export * from './StoryRoutes'
export * from './TeamRoutes'
export * from './UserRoutes' export * from './UserRoutes'
export * from './application'

View File

@ -1,2 +1,10 @@
export * from './UserService' export * from './CommentService'
export * from './ICommentService'
export * from './ISiteService'
export * from './IStoryService'
export * from './ITeamService'
export * from './IUserService' export * from './IUserService'
export * from './SiteService'
export * from './StoryService'
export * from './TeamService'
export * from './UserService'

View File

@ -1,5 +1,10 @@
import supertest from 'supertest' import supertest from 'supertest'
import {IMethod, IRoutes} from '@rondo/common' import {
IMethod,
IRequestParams,
IRoutes,
URLFormatter,
} from '@rondo/common'
// https://stackoverflow.com/questions/48215950/exclude-property-from-type // https://stackoverflow.com/questions/48215950/exclude-property-from-type
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
@ -37,6 +42,7 @@ export interface IHeaders {
export class RequestTester<R extends IRoutes> { export class RequestTester<R extends IRoutes> {
protected headers: IHeaders = {} protected headers: IHeaders = {}
protected formatter: URLFormatter = new URLFormatter()
constructor( constructor(
readonly app: Express.Application, readonly app: Express.Application,
@ -49,21 +55,22 @@ export class RequestTester<R extends IRoutes> {
} }
request<M extends IMethod, P extends keyof R & string>( request<M extends IMethod, P extends keyof R & string>(
method: M, path: P, method: M, path: P, params?: IRequestParams,
) )
: IRequest<R, P, M> { : IRequest<R, P, M> {
const test = supertest(this.app)[method](`${this.baseUrl}${path}`) const url = this.formatter.format(path, params)
const test = supertest(this.app)[method](`${this.baseUrl}${url}`)
Object.keys(this.headers).forEach(key => { Object.keys(this.headers).forEach(key => {
test.set(key, this.headers[key]) test.set(key, this.headers[key])
}) })
return test return test
} }
get<P extends keyof R & string>(path: P) { get<P extends keyof R & string>(path: P, params?: IRequestParams) {
return this.request('get', path) return this.request('get', path, params)
} }
post<P extends keyof R & string>(path: P) { post<P extends keyof R & string>(path: P, params?: IRequestParams) {
return this.request('post', path) return this.request('post', path)
} }
} }

View File

@ -101,6 +101,7 @@ export class TestUtils<T extends IRoutes> {
return { return {
cookie: response.header['set-cookie'] as string, cookie: response.header['set-cookie'] as string,
userId: response.body.userId, userId: response.body.userId,
token,
} }
} }