diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/app.module.ts | 5 | ||||
-rw-r--r-- | server/controllers/chat_room.controller.ts | 51 | ||||
-rw-r--r-- | server/controllers/users.controller.ts | 1 | ||||
-rw-r--r-- | server/database/migrations/1648605030863-AddChatRoom.ts | 20 | ||||
-rw-r--r-- | server/database/migrations/1648669551959-AddDistanceFunction.ts | 45 | ||||
-rw-r--r-- | server/entities/chat_room.entity.ts | 9 | ||||
-rw-r--r-- | server/entities/user.entity.ts | 4 | ||||
-rw-r--r-- | server/modules/chat_room.module.ts | 8 | ||||
-rw-r--r-- | server/modules/users.module.ts | 3 | ||||
-rw-r--r-- | server/providers/services/chat_room.service.ts | 18 |
10 files changed, 144 insertions, 20 deletions
diff --git a/server/app.module.ts b/server/app.module.ts index bbc3c1c..5fc4654 100644 --- a/server/app.module.ts +++ b/server/app.module.ts @@ -3,17 +3,19 @@ import { APP_GUARD } from '@nestjs/core'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { config } from './database/config'; +import { ChatRoomModule } from './modules/chat_room.module'; import { UsersModule } from './modules/users.module'; import { PingGateway } from './providers/gateways/ping.gateway'; import { AuthGuard } from './providers/guards/auth.guard'; import { RolesGuard } from './providers/guards/roles.guard'; +import { ChatRoomService } from './providers/services/chat_room.service'; import { JwtService } from './providers/services/jwt.service'; import { RolesService } from './providers/services/roles.service'; import { UsersService } from './providers/services/users.service'; import { GuardUtil } from './providers/util/guard.util'; @Module({ - imports: [TypeOrmModule.forRoot(config), UsersModule], + imports: [TypeOrmModule.forRoot(config), UsersModule, ChatRoomModule], controllers: [AppController], providers: [ PingGateway, @@ -21,6 +23,7 @@ import { GuardUtil } from './providers/util/guard.util'; RolesService, JwtService, GuardUtil, + ChatRoomService, { provide: APP_GUARD, useClass: AuthGuard }, // auth guard should come before roles guard { provide: APP_GUARD, useClass: RolesGuard }, // otherwise users won't be authenticated before roles check ], diff --git a/server/controllers/chat_room.controller.ts b/server/controllers/chat_room.controller.ts index 5a8da66..bd9ba4a 100644 --- a/server/controllers/chat_room.controller.ts +++ b/server/controllers/chat_room.controller.ts @@ -1,12 +1,55 @@ -import { Controller, Get } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; +import { JwtBody } from 'server/decorators/jwt_body.decorator'; +import { JwtBodyDto } from 'server/dto/jwt_body.dto'; import { ChatRoomService } from 'server/providers/services/chat_room.service'; +import { UsersService } from 'server/providers/services/users.service'; @Controller() export class ChatRoomController { - constructor(private chatRoomService: ChatRoomService) {} + constructor(private chatRoomService: ChatRoomService, private usersService: UsersService) {} @Get('/chat_rooms') - async get() { - return await this.chatRoomService.all(); + async get(@Query() query: any) { + console.log(query); + return await this.chatRoomService.near(query); + } + + @Post('/chat_rooms') + async create(@JwtBody() jwtBody: JwtBodyDto, @Body() chatRoom: any) { + chatRoom.user = await this.usersService.find(jwtBody.userId); + console.log(jwtBody); + return await this.chatRoomService.create(chatRoom); + } + + private async authorized(jwtBody: JwtBodyDto, chatRoom: any) { + const user = await this.usersService.find(jwtBody.userId); + if (user.id !== chatRoom.user.id) { + return { + error: 'You are not the owner of this chat room', + }; + } + return true; + } + + @Put('/chat_rooms/:id') + async update(@JwtBody() jwtBody: JwtBodyDto, @Param('id') id: number, @Body() chatRoom: any) { + console.log(id); + const chat_room = await this.chatRoomService.findById(id, ['user']); + if (!(await this.authorized(jwtBody, chat_room))) { + return chat_room; + } + chat_room.latitude = chatRoom.latitude; + chat_room.longitude = chatRoom.longitude; + chat_room.radius = chatRoom.radius; + return await this.chatRoomService.save(chat_room); + } + + @Delete('/chat_rooms/:id') + async delete(@JwtBody() jwtBody: JwtBodyDto, @Param('id') id: number) { + const chat_room = await this.chatRoomService.findById(id, ['user']); + if (!(await this.authorized(jwtBody, chat_room))) { + return false; + } + return await this.chatRoomService.remove(chat_room); } } diff --git a/server/controllers/users.controller.ts b/server/controllers/users.controller.ts index 652b5b6..82d6215 100644 --- a/server/controllers/users.controller.ts +++ b/server/controllers/users.controller.ts @@ -35,6 +35,7 @@ export class UsersController { @Get('/users/me') async getCurrentUser(@JwtBody() jwtBody: JwtBodyDto) { const user = await this.usersService.find(jwtBody.userId); + delete user.passwordHash; return { user }; } diff --git a/server/database/migrations/1648605030863-AddChatRoom.ts b/server/database/migrations/1648605030863-AddChatRoom.ts index d8eed52..e4b5ca9 100644 --- a/server/database/migrations/1648605030863-AddChatRoom.ts +++ b/server/database/migrations/1648605030863-AddChatRoom.ts @@ -1,10 +1,10 @@ -import { MigrationInterface, QueryRunner, Table } from 'typeorm'; +import { MigrationInterface, QueryRunner, Table, TableForeignKey } from 'typeorm'; export class AddChatRoom1648605030863 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.createTable( new Table({ - name: 'chatroom', + name: 'chat_room', columns: [ { name: 'id', @@ -13,8 +13,8 @@ export class AddChatRoom1648605030863 implements MigrationInterface { isGenerated: true, }, { - name: 'name', - type: 'text', + name: 'userId', + type: 'int', isNullable: false, }, { @@ -35,9 +35,19 @@ export class AddChatRoom1648605030863 implements MigrationInterface { ], }), ); + + await queryRunner.createForeignKey( + 'chat_room', + new TableForeignKey({ + columnNames: ['userId'], + referencedColumnNames: ['id'], + referencedTableName: 'user', + onDelete: 'CASCADE', + }), + ); } public async down(queryRunner: QueryRunner): Promise<void> { - await queryRunner.dropTable('chatroom'); + await queryRunner.dropTable('chat_room'); } } diff --git a/server/database/migrations/1648669551959-AddDistanceFunction.ts b/server/database/migrations/1648669551959-AddDistanceFunction.ts new file mode 100644 index 0000000..0890936 --- /dev/null +++ b/server/database/migrations/1648669551959-AddDistanceFunction.ts @@ -0,0 +1,45 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDistanceFunction1648669551959 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise<void> { + // From https://stackoverflow.com/questions/61135374/postgresql-calculate-distance-between-two-points-without-using-postgis + await queryRunner.query(` +CREATE OR REPLACE FUNCTION calculate_distance(lat1 float, lon1 float, lat2 float, lon2 float, units varchar) + RETURNS float AS $dist$ + DECLARE + dist float = 0; + radlat1 float; + radlat2 float; + theta float; + radtheta float; + BEGIN + IF lat1 = lat2 OR lon1 = lon2 + THEN RETURN dist; + ELSE + radlat1 = pi() * lat1 / 180; + radlat2 = pi() * lat2 / 180; + theta = lon1 - lon2; + radtheta = pi() * theta / 180; + dist = sin(radlat1) * sin(radlat2) + cos(radlat1) * cos(radlat2) * cos(radtheta); + + IF dist > 1 THEN dist = 1; END IF; + + dist = acos(dist); + dist = dist * 180 / pi(); + dist = dist * 60 * 1.1515; + + IF units = 'K' THEN dist = dist * 1.609344; END IF; + IF units = 'N' THEN dist = dist * 0.8684; END IF; + + RETURN dist; + END IF; + END; + $dist$ LANGUAGE plpgsql;`); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `DROP FUNCTION IF EXISTS calculate_distance(lat1 float, lon1 float, lat2 float, lon2 float, units varchar);`, + ); + } +} diff --git a/server/entities/chat_room.entity.ts b/server/entities/chat_room.entity.ts index 9550d26..6f46c97 100644 --- a/server/entities/chat_room.entity.ts +++ b/server/entities/chat_room.entity.ts @@ -1,4 +1,5 @@ -import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'; +import { User } from './user.entity'; @Entity() export class ChatRoom { @@ -6,9 +7,6 @@ export class ChatRoom { id: number; @Column() - name: string; - - @Column() latitude: number; @Column() @@ -16,4 +14,7 @@ export class ChatRoom { @Column() radius: number; + + @ManyToOne(() => User, (user) => user.chatRooms) + user: User; } diff --git a/server/entities/user.entity.ts b/server/entities/user.entity.ts index aeef107..c3ece96 100644 --- a/server/entities/user.entity.ts +++ b/server/entities/user.entity.ts @@ -1,4 +1,5 @@ import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; +import { ChatRoom } from './chat_room.entity'; import { RefreshToken } from './refresh_token.entity'; import { UserRole } from './user_role.entity'; @@ -24,4 +25,7 @@ export class User { @OneToMany(() => UserRole, (userRole) => userRole.user, { cascade: true }) userRoles: UserRole[]; + + @OneToMany(() => ChatRoom, (chatRoom) => chatRoom.user) + chatRooms: ChatRoom[]; } diff --git a/server/modules/chat_room.module.ts b/server/modules/chat_room.module.ts index 07b2553..7acc672 100644 --- a/server/modules/chat_room.module.ts +++ b/server/modules/chat_room.module.ts @@ -3,11 +3,13 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ChatRoomController } from 'server/controllers/chat_room.controller'; import { ChatRoom } from 'server/entities/chat_room.entity'; import { ChatRoomService } from 'server/providers/services/chat_room.service'; +import { UsersService } from 'server/providers/services/users.service'; +import { UsersModule } from './users.module'; @Module({ - imports: [TypeOrmModule.forFeature([ChatRoom])], + imports: [TypeOrmModule.forFeature([ChatRoom]), UsersModule], controllers: [ChatRoomController], - providers: [ChatRoomService], + providers: [ChatRoomService, UsersService], exports: [TypeOrmModule], }) -export class UsersModule {} +export class ChatRoomModule {} diff --git a/server/modules/users.module.ts b/server/modules/users.module.ts index 69c533b..5b5b2ff 100644 --- a/server/modules/users.module.ts +++ b/server/modules/users.module.ts @@ -11,9 +11,10 @@ import { RefreshTokensController } from 'server/controllers/refresh_tokens.contr import { Role } from 'server/entities/role.entity'; import { RolesService } from 'server/providers/services/roles.service'; import { UserRole } from 'server/entities/user_role.entity'; +import { ChatRoom } from 'server/entities/chat_room.entity'; @Module({ - imports: [TypeOrmModule.forFeature([User, RefreshToken, Role, UserRole])], + imports: [TypeOrmModule.forFeature([User, RefreshToken, Role, UserRole, ChatRoom])], controllers: [SessionsController, UsersController, RefreshTokensController], providers: [UsersService, RolesService, RefreshTokensService, JwtService], exports: [TypeOrmModule], diff --git a/server/providers/services/chat_room.service.ts b/server/providers/services/chat_room.service.ts index 6c87539..a6af023 100644 --- a/server/providers/services/chat_room.service.ts +++ b/server/providers/services/chat_room.service.ts @@ -18,7 +18,21 @@ export class ChatRoomService { return this.chatRoomRepository.find(); } - findById(id: number) { - return this.chatRoomRepository.findOne(id); + near({ lat, lng }: { lat: number; lng: number }) { + return this.chatRoomRepository.query( + `SELECT * FROM chat_room WHERE calculate_distance(latitude, longitude, ${lat}, ${lng}, 'M') < 5`, + ); + } + + findById(id: number, relations: string[] = []) { + return this.chatRoomRepository.findOne(id, { relations }); + } + + save(chatRoom: ChatRoom) { + return this.chatRoomRepository.save(chatRoom); + } + + remove(chatRoom: ChatRoom) { + return this.chatRoomRepository.remove(chatRoom); } } |