universo-platform-3d

Форк
0
437 строк · 13.3 Кб
1
import {
2
  Body,
3
  Controller,
4
  Delete,
5
  Get,
6
  NotFoundException,
7
  Param,
8
  Patch,
9
  Post,
10
  Query,
11
  UnauthorizedException,
12
  UploadedFile,
13
  UseInterceptors,
14
  UsePipes,
15
  ValidationPipe
16
} from '@nestjs/common'
17
import {
18
  ApiBody,
19
  ApiConsumes,
20
  ApiCreatedResponse,
21
  ApiOkResponse,
22
  ApiParam
23
} from '@nestjs/swagger'
24
import { FirebaseTokenAuthGuard } from '../auth/auth.guard'
25
import { User, UserPublicData } from './user.schema'
26
import { Friend, UserService } from './user.service'
27
import { UserToken } from '../auth/get-user.decorator'
28
import { FileUploadPublicApiResponse } from '../util/file-upload/file-upload'
29
import { FileInterceptor } from '@nestjs/platform-express'
30
import {
31
  AddRpmAvatarUrlDto,
32
  UpdateUserAvatarDto,
33
  RemoveRpmAvatarUrlDto,
34
  UpdateUserAvatarTypeDto,
35
  UpdateUserDeepLinkDto,
36
  UpdateUserProfileDto,
37
  UpdateUserTermsDto,
38
  UpdateUserTutorialDto,
39
  UpsertUserEntityActionDto,
40
  AddUserCartItemToUserCartDto
41
} from './dto/update-user.dto'
42
import { PublicFirebaseAuthNotRequired } from '../auth/public.decorator'
43
import { CreateUserAccessKeyDto } from './dto/create-user-access-key.dto'
44
import { SubmitUserAccessKeyDto } from './dto/submit-user-access-key.dto'
45
import { UserEntityActionId, UserId } from '../util/mongo-object-id-helpers'
46
import { PREMIUM_ACCESS } from '../option-sets/premium-tiers'
47
import { AddUserSidebarTagDto } from './dto/add-user-sidebar-tag.dto'
48
import { UpdateUserSidebarTagsDto } from './dto/update-user-sidebar-tags.dto'
49
import { UserRecents } from './models/user-recents.schema'
50

51
@UsePipes(new ValidationPipe({ whitelist: true }))
52
@Controller('user')
53
@FirebaseTokenAuthGuard()
54
export class UserController {
55
  constructor(private readonly userService: UserService) {}
56

57
  /*****************************
58
   PUBLICLY ACCESSIBLE ENDPOINTS
59
   ****************************/
60

61
  /**
62
   * @description Retrieves a Users public data
63
   * id prefix added to prevent wildcard route clashes with file method order
64
   */
65
  @PublicFirebaseAuthNotRequired()
66
  @Get('id/:id')
67
  @ApiParam({ name: 'id', type: 'string', required: true })
68
  public findOne(@Param('id') id: string): Promise<UserPublicData> {
69
    return this.userService.findPublicUser(id)
70
  }
71

72
  /** @description Retrieves a Users public profile data including populated
73
   *  fields like public assets and public groups */
74
  @PublicFirebaseAuthNotRequired()
75
  @Get(':id/public-profile')
76
  @ApiParam({ name: 'id', type: 'string', required: true })
77
  @ApiOkResponse({ type: UserPublicData })
78
  public findOneWithPublicProfile(@Param('id') id: string): Promise<User> {
79
    return this.userService.findPublicUserFullProfile(id)
80
  }
81

82
  /** @description Retrieves a collection of Users public data */
83
  @PublicFirebaseAuthNotRequired()
84
  @Get('search')
85
  @ApiOkResponse({ type: [UserPublicData] })
86
  public search(@Query('query') query: string): Promise<UserPublicData[]> {
87
    return this.userService.searchForPublicUsers(query)
88
  }
89

90
  /***********************
91
   AUTH REQUIRED ENDPOINTS
92
   **********************/
93

94
  /** @description /me gets the current user by checking their uid on the JWT */
95
  @Get('me')
96
  @ApiOkResponse({ type: User })
97
  public async getCurrentUser(@UserToken('uid') id: string) {
98
    const user = await this.userService.findUser(id)
99
    if (!user) {
100
      throw new NotFoundException()
101
    }
102
    return user
103
  }
104

105
  @Get('recents/me')
106
  @ApiOkResponse({ type: UserRecents })
107
  public async getUserRecents(@UserToken('user_id') userId: UserId) {
108
    return await this.userService.getUserRecents(userId)
109
  }
110

111
  /**
112
   * TODO - Would be nice to have 1 file upload endpoint that can handle all entity types and paths
113
   *  move logic to service
114
   */
115
  @Post('/upload/public')
116
  @FirebaseTokenAuthGuard() // 2023-03-08 00:28:04 can this line be removed since the controller has it?
117
  @ApiConsumes('multipart/form-data')
118
  @ApiBody({ schema: { type: 'file' } })
119
  @ApiCreatedResponse({ type: FileUploadPublicApiResponse })
120
  @UseInterceptors(FileInterceptor('file'))
121
  public async uploadPublic(
122
    @UserToken('user_id') userId: string,
123
    @UploadedFile() file: Express.Multer.File
124
  ) {
125
    return await this.userService.uploadProfileImage({ file, userId })
126
  }
127

128
  @Patch('profile')
129
  @ApiOkResponse({ type: User })
130
  public updateProfile(
131
    @UserToken('uid') id: string,
132
    @Body() dto: UpdateUserProfileDto
133
  ) {
134
    return this.userService.updateUserProfileAdmin(id, dto)
135
  }
136

137
  @Patch('tutorial')
138
  @ApiOkResponse({ type: User })
139
  public updateUserTutorial(
140
    @UserToken('uid') id: UserId,
141
    @Body() dto: UpdateUserTutorialDto
142
  ) {
143
    return this.userService.updateUserTutorial(id, dto)
144
  }
145

146
  @Patch('deep-link')
147
  public updateDeepLink(
148
    @UserToken('uid') id: string,
149
    @Body() dto: UpdateUserDeepLinkDto
150
  ) {
151
    return this.userService.updateDeepLink(id, dto)
152
  }
153

154
  @Patch('avatar')
155
  public updateAvatar(
156
    @UserToken('uid') id: string,
157
    @Body() dto: UpdateUserAvatarDto
158
  ) {
159
    return this.userService.updateUserAvatar(id, dto)
160
  }
161

162
  @Patch('terms')
163
  public updateTermsAgreedTo(
164
    @UserToken('uid') id: string,
165
    @Body() dto: UpdateUserTermsDto
166
  ) {
167
    return this.userService.updateUserTerms(id, dto)
168
  }
169

170
  @Patch('avatar-type')
171
  public updateAvatarType(
172
    @UserToken('uid') id: string,
173
    @Body() dto: UpdateUserAvatarTypeDto
174
  ) {
175
    return this.userService.updateUserAvatarType(id, dto)
176
  }
177

178
  /**
179
   * @param {string} entityId - The id of the entity that the action is for such as Space, Asset, User, etc., NOT the UserEntityAction ID
180
   * @date 2023-06-14 16:49
181
   */
182
  @Get('entity-action/for-entity/:entityId')
183
  @ApiParam({ name: 'entityId', type: 'string', required: true })
184
  public getUserEntityAction(
185
    @UserToken('uid') id: UserId,
186
    @Param('entityId') entityId: string
187
  ) {
188
    return this.userService.getPublicEntityActionStats(entityId)
189
  }
190

191
  /**
192
   * @param {string} entityId - The id of the entity that the action is for such as Space, Asset, User, etc., NOT the UserEntityAction ID
193
   * @date 2023-06-14 16:49
194
   */
195
  @Get('entity-action/me/for-entity/:entityId')
196
  @ApiParam({ name: 'entityId', type: 'string', required: true })
197
  public getUserEntityActionsByMeForEntity(
198
    @UserToken('uid') userId: UserId,
199
    @Param('entityId') entityId: string
200
  ) {
201
    return this.userService.findEntityActionsByUserForEntity(userId, entityId)
202
  }
203

204
  @Patch('entity-action')
205
  public upsertUserEntityAction(
206
    @UserToken('uid') id: UserId,
207
    @Body() dto: UpsertUserEntityActionDto
208
  ) {
209
    return this.userService.upsertUserEntityAction(id, dto)
210
  }
211

212
  @Delete('entity-action/:userEntityActionId')
213
  @ApiParam({ name: 'userEntityActionId', type: 'string', required: true })
214
  public deleteUserEntityAction(
215
    @UserToken('uid') id: UserId,
216
    @Param('userEntityActionId') userEntityActionId: UserEntityActionId
217
  ) {
218
    return this.userService.removeUserEntityAction(id, userEntityActionId)
219
  }
220

221
  /**
222
   * START Section: Friends and friend requests  ------------------------------------------------------
223
   */
224
  @Get('friends/me')
225
  @ApiOkResponse({
226
    type: [Friend],
227
    description: 'Gets friend requests for the current user from the token'
228
  })
229
  public getMyFriends(@UserToken('uid') userId: UserId): Promise<Friend[]> {
230
    return this.userService.findUserFriendsAdmin(userId)
231
  }
232

233
  @Get('friend-requests/me')
234
  @ApiOkResponse({ type: [Friend] })
235
  public getMyFriendRequests(
236
    @UserToken('uid') userId: UserId
237
  ): Promise<Friend[]> {
238
    return this.userService.findFriendRequestsSentToMeAdmin(userId)
239
  }
240

241
  @Post('friend-requests/accept/:fromUserId')
242
  @ApiParam({ name: 'fromUserId', type: 'string', required: true })
243
  @ApiOkResponse({
244
    type: [Friend],
245
    description:
246
      'Accepts a friend request. This uses the current user from the token as the accepting user'
247
  })
248
  public acceptFriendRequest(
249
    @UserToken('uid') userId: UserId,
250
    @Param('fromUserId') fromUserId: UserId
251
  ): Promise<Friend[]> {
252
    return this.userService.acceptFriendRequestAdmin(userId, fromUserId)
253
  }
254

255
  @Post('friend-requests/reject/:fromUserId')
256
  @ApiParam({ name: 'fromUserId', type: 'string', required: true })
257
  @ApiOkResponse({
258
    type: [Friend],
259
    description:
260
      'Rejects a friend request. This uses the current user from the token as the user that rejects the request'
261
  })
262
  public rejectFriendRequest(
263
    @UserToken('uid') userId: UserId,
264
    @Param('fromUserId') fromUserId: UserId
265
  ): Promise<Friend[]> {
266
    return this.userService.rejectFriendRequestAdmin(userId, fromUserId)
267
  }
268

269
  @Get('friend-requests/sent')
270
  @ApiOkResponse({
271
    type: [Friend],
272
    description: 'Gets SENT friend requests by the current user from the token'
273
  })
274
  public getSentFriendRequests(
275
    @UserToken('uid') userId: UserId
276
  ): Promise<Friend[]> {
277
    return this.userService.findSentFriendRequestsAdmin(userId)
278
  }
279

280
  @Post('friend-requests/:toUserId')
281
  @ApiParam({ name: 'toUserId', type: 'string', required: true })
282
  @ApiCreatedResponse({
283
    type: User,
284
    description:
285
      'Sends a friend request. This uses the current user from the token'
286
  })
287
  public sendFriendRequest(
288
    @UserToken('uid') userId: UserId,
289
    @Param('toUserId') toUserId: UserId
290
  ): Promise<User> {
291
    return this.userService.sendFriendRequestAdmin(userId, toUserId)
292
  }
293

294
  @Delete('friends/:friendUserIdToRemove')
295
  @ApiParam({ name: 'friendUserIdToRemove', type: 'string', required: true })
296
  @ApiOkResponse({
297
    type: User,
298
    description: 'Removes a friend and returns the updated friends list'
299
  })
300
  public removeFriend(
301
    @UserToken('uid') userId: UserId,
302
    @Param('friendUserIdToRemove') friendUserIdToRemove: UserId
303
  ): Promise<Friend[]> {
304
    return this.userService.removeFriendAdmin(userId, friendUserIdToRemove)
305
  }
306
  /**
307
   * END Section: Friends and friend requests  ------------------------------------------------------
308
   */
309

310
  /**
311
   * START Section: Cart  ------------------------------------------------------
312
   */
313
  @Get('cart')
314
  @ApiOkResponse({ type: User })
315
  public getUserCart(@UserToken('uid') userId: string) {
316
    return this.userService.getUserCartAdmin(userId)
317
  }
318

319
  @Post('cart')
320
  @ApiCreatedResponse({ type: User })
321
  public addUserCartItemToUserCart(
322
    @UserToken('uid') userId: string,
323
    @Body() dto: AddUserCartItemToUserCartDto
324
  ) {
325
    return this.userService.addUserCartItemToUserCartAdmin(userId, dto)
326
  }
327

328
  @Delete('cart/all')
329
  @ApiOkResponse({ type: User })
330
  public removeAllUserItemsFromCart(@UserToken('uid') userId: string) {
331
    return this.userService.removeAllUserCartItemsFromUserCartAdmin(userId)
332
  }
333

334
  @Delete('cart/:cartItemId')
335
  @ApiParam({ name: 'cartItemId', type: 'string', required: true })
336
  @ApiOkResponse({ type: User })
337
  public removeUserCartItemFromUserCart(
338
    @UserToken('uid') userId: string,
339
    @Param('cartItemId') cartItemId: string
340
  ) {
341
    return this.userService.removeUserCartItemFromUserCartAdmin(
342
      userId,
343
      cartItemId
344
    )
345
  }
346

347
  /**
348
   * END Section: Cart  ------------------------------------------------------
349
   */
350

351
  /** @description Add a url to the array of the user's RPM avatars, readyPlayerMeAvatarUrls in Mongo */
352
  @Post('rpm-avatar-url')
353
  public addRpmAvatarUrl(
354
    @UserToken('uid') id: string,
355
    @Body() dto: AddRpmAvatarUrlDto
356
  ) {
357
    return this.userService.addRpmAvatarUrl(id, dto)
358
  }
359

360
  @Post('access-key')
361
  createSignUpKey(@Body() createSignUpKeyDto: CreateUserAccessKeyDto) {
362
    if (createSignUpKeyDto.token !== process.env.SIGN_UP_KEY_TOKEN) {
363
      throw new UnauthorizedException()
364
    }
365
    return this.userService.createUserAccessKey(createSignUpKeyDto)
366
  }
367

368
  @Post('submit-user-access-key')
369
  async submitUserAccessKey(
370
    @UserToken('uid') userId: string,
371
    @Body() submitUserAccessKeyDto: SubmitUserAccessKeyDto
372
  ) {
373
    const key = await this.userService.checkUserAccessKeyExistence(
374
      submitUserAccessKeyDto.key
375
    )
376
    if (key) {
377
      await this.userService.addUserPremiumAccess(
378
        userId,
379
        key.premiumAccess as PREMIUM_ACCESS
380
      )
381
      await this.userService.setUserAccessKeyAsUsed(key.id, userId)
382
    } else {
383
      throw new UnauthorizedException(
384
        "We're sorry, but that key doesn't exist or it's been used"
385
      )
386
    }
387
  }
388

389
  /** @description Removes an RPM url from readyPlayerMeAvatarUrls in Mongo */
390
  @Delete('rpm-avatar-url')
391
  public removeRpmAvatarUrl(
392
    @UserToken('uid') id: string,
393
    @Body() dto: RemoveRpmAvatarUrlDto
394
  ) {
395
    return this.userService.removeRpmAvatarUrl(id, dto)
396
  }
397

398
  @Get('sidebar-tags')
399
  @FirebaseTokenAuthGuard()
400
  public async getUserSidebarTags(@UserToken('user_id') userId: UserId) {
401
    return await this.userService.getUserSidebarTags(userId)
402
  }
403

404
  @Post('sidebar-tags')
405
  @FirebaseTokenAuthGuard()
406
  public async addUserSidebarTag(
407
    @UserToken('user_id') userId: UserId,
408
    @Body() addUserSidebarTagDto: AddUserSidebarTagDto
409
  ) {
410
    return await this.userService.addUserSidebarTag(
411
      userId,
412
      addUserSidebarTagDto
413
    )
414
  }
415

416
  @Patch('sidebar-tags')
417
  @FirebaseTokenAuthGuard()
418
  public async updateUserSidebarTags(
419
    @UserToken('user_id') userId: UserId,
420
    @Body() updateUserSidebarTagsDto: UpdateUserSidebarTagsDto
421
  ) {
422
    return await this.userService.updateUserSidebarTags(
423
      userId,
424
      updateUserSidebarTagsDto.sidebarTags
425
    )
426
  }
427

428
  @Delete('sidebar-tags/:sidebarTag')
429
  @ApiParam({ name: 'sidebarTag', type: 'string', required: true })
430
  @FirebaseTokenAuthGuard()
431
  public async deleteUserSidebarTag(
432
    @UserToken('user_id') userId: UserId,
433
    @Param('sidebarTag') sidebarTag: string
434
  ) {
435
    return await this.userService.deleteUserSidebarTag(userId, sidebarTag)
436
  }
437
}
438

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.