From 2bd2790df2fe6261ebf8b90eb63642885f41af4e Mon Sep 17 00:00:00 2001 From: TechQuery Date: Sun, 1 Oct 2023 04:18:08 +0800 Subject: [PATCH] [add] User controller [add] Debugger configuration of VS Code [optimize] replace Mobile Phone with User ID on Event Checking [fix] some User detail bugs --- .vscode/launch.json | 14 ++++++++++++++ src/controller/CheckEvent.ts | 22 +++++++++++----------- src/controller/Session.ts | 17 ++++++++++++----- src/controller/User.ts | 16 ++++++++++++++++ src/controller/index.ts | 8 +++++++- src/index.ts | 2 +- src/model/Base.ts | 4 ++++ src/model/CheckEvent.ts | 17 ++++++++--------- src/model/User.ts | 4 ++++ type/package.json | 2 +- 10 files changed, 78 insertions(+), 28 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/controller/User.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..48d7d76 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Server", + "type": "node", + "request": "launch", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ] +} diff --git a/src/controller/CheckEvent.ts b/src/controller/CheckEvent.ts index 98c9cbe..e3e8d67 100644 --- a/src/controller/CheckEvent.ts +++ b/src/controller/CheckEvent.ts @@ -30,17 +30,20 @@ export class CheckEventController { @ResponseSchema(CheckEvent) async createOne( @CurrentUser() createdBy: User, - @Body() { mobilePhone, ...data }: CheckEventInput + @Body() { user, ...data }: CheckEventInput ) { - const user = await this.userStore.findOne({ where: { mobilePhone } }); + if (createdBy.id === user.id) + throw new ForbiddenError('No self-checking'); - if (!user) throw new BadRequestError('Invalid user: ' + mobilePhone); + user = await this.userStore.findOne({ where: user }); - const oldOne = await this.store.findOne({ + if (!user) throw new BadRequestError('Invalid user: ' + user.id); + + const checked = await this.store.findOne({ where: { ...data, user: { id: user.id } } }); - if (oldOne) throw new ForbiddenError('No duplicated check'); + if (checked) throw new ForbiddenError('No duplicated check'); return this.store.save({ ...data, createdBy, user }); } @@ -50,7 +53,7 @@ export class CheckEventController { async getSessionList( @QueryParams() { - mobilePhone, + user, activityId, agendaId, pageSize = 10, @@ -58,11 +61,8 @@ export class CheckEventController { }: CheckEventFilter ) { const [list, count] = await this.store.findAndCount({ - where: { - user: { mobilePhone }, - activityId, - agendaId - }, + where: { user, activityId, agendaId }, + relations: ['user'], skip: pageSize * (pageIndex - 1), take: pageSize }); diff --git a/src/controller/Session.ts b/src/controller/Session.ts index d285b34..42f435c 100644 --- a/src/controller/Session.ts +++ b/src/controller/Session.ts @@ -30,14 +30,17 @@ export class SessionController { return { ...user, token: sign({ ...user }, AUTHING_APP_SECRET) }; } + static fixPhoneNumber(raw: string) { + return raw.startsWith('+') ? raw : `+86${raw}`; + } + static getAuthingUser(token: string): AuthingSession { var { phone_number, ...session } = verify( token.split(/\s+/)[1], AUTHING_APP_SECRET ) as AuthingSession; - if (phone_number && !phone_number.startsWith('+86')) - phone_number = '+86' + phone_number; + if (phone_number) phone_number = this.fixPhoneNumber(phone_number); return { ...session, phone_number }; } @@ -50,9 +53,11 @@ export class SessionController { if (!user) return; if ('userpool_id' in user) - return dataSource - .getRepository(User) - .findOne({ where: { mobilePhone: user.phone_number } }); + return dataSource.getRepository(User).findOne({ + where: { + mobilePhone: this.fixPhoneNumber(user.phone_number) + } + }); delete user.iat; @@ -72,6 +77,7 @@ export class SessionController { @HeaderParam('Authorization', { required: true }) token: string ) { const { + sub, phone_number: mobilePhone, nickname, picture @@ -81,6 +87,7 @@ export class SessionController { const registered = await SessionController.register(this.store, { ...existed, + uuid: sub, mobilePhone, nickName: nickname, avatar: picture diff --git a/src/controller/User.ts b/src/controller/User.ts new file mode 100644 index 0000000..5fc38c5 --- /dev/null +++ b/src/controller/User.ts @@ -0,0 +1,16 @@ +import { Get, JsonController, OnNull, Param } from 'routing-controllers'; +import { ResponseSchema } from 'routing-controllers-openapi'; + +import { User, dataSource } from '../model'; + +@JsonController('/user') +export class UserController { + store = dataSource.getRepository(User); + + @Get('/:uuid') + @OnNull(404) + @ResponseSchema(User) + getOne(@Param('uuid') uuid: string) { + return this.store.findOne({ where: { uuid } }); + } +} diff --git a/src/controller/index.ts b/src/controller/index.ts index f1775a8..22ad925 100644 --- a/src/controller/index.ts +++ b/src/controller/index.ts @@ -5,8 +5,14 @@ import { isProduct } from '../utility'; import { CheckEventController } from './CheckEvent'; import { CrawlerController } from './Crawler'; import { SessionController } from './Session'; +import { UserController } from './User'; export const { router, swagger, mocker } = createAPI({ mock: !isProduct, - controllers: [SessionController, CheckEventController, CrawlerController] + controllers: [ + SessionController, + UserController, + CheckEventController, + CrawlerController + ] }); diff --git a/src/index.ts b/src/index.ts index 3015615..90bca8d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,7 +32,7 @@ useKoaServer(app, { !!(await SessionController.getSession(action)) ); }, - currentUserChecker: SessionController.getSession + currentUserChecker: action => SessionController.getSession(action) }); console.time('Server boot'); diff --git a/src/model/Base.ts b/src/model/Base.ts index 35fac66..dac4e95 100644 --- a/src/model/Base.ts +++ b/src/model/Base.ts @@ -14,6 +14,10 @@ import { } from 'typeorm'; export abstract class Base { + constructor(id: number) { + this.id = id; + } + @IsInt() @PrimaryGeneratedColumn() id: number; diff --git a/src/model/CheckEvent.ts b/src/model/CheckEvent.ts index 9bc9da6..33236c2 100644 --- a/src/model/CheckEvent.ts +++ b/src/model/CheckEvent.ts @@ -1,8 +1,7 @@ -import { Type } from 'class-transformer'; +import { Transform, Type } from 'class-transformer'; import { IsInt, IsLatLong, - IsMobilePhone, IsOptional, IsString, Min, @@ -42,15 +41,14 @@ export class CheckEvent extends UserBase { agendaTitle: string; } -export class CheckEventInput - implements Omit, 'user'> -{ +export class CheckEventInput implements UserInputData { @IsLatLong() @IsOptional() coordinate?: string; - @IsMobilePhone() - mobilePhone: string; + @Type(() => User) + @Transform(({ value }) => new User(value)) + user: User; @IsString() activityId: string; @@ -69,9 +67,10 @@ export class CheckEventFilter extends BaseFilter implements Partial { - @IsMobilePhone() + @Type(() => User) + @Transform(({ value }) => new User(value)) @IsOptional() - mobilePhone?: string; + user?: User; @IsString() @IsOptional() diff --git a/src/model/User.ts b/src/model/User.ts index 46f4171..7920990 100644 --- a/src/model/User.ts +++ b/src/model/User.ts @@ -23,6 +23,10 @@ export enum Gender { @Entity() export class User extends Base { + @IsString() + @Column({ unique: true }) + uuid: string; + @IsMobilePhone() @Column({ unique: true }) mobilePhone: string; diff --git a/type/package.json b/type/package.json index 7fb6087..446113e 100644 --- a/type/package.json +++ b/type/package.json @@ -1,6 +1,6 @@ { "name": "@kaiyuanshe/kys-service", - "version": "0.6.5", + "version": "0.6.7", "types": "index.d.ts", "files": [ "*.d.ts"