Skip to content

Commit

Permalink
docs(api): Add swagger docs of User Controller (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
rajdip-b authored Mar 11, 2024
1 parent 48294c9 commit fd59522
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 4 deletions.
12 changes: 9 additions & 3 deletions apps/api/src/auth/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ import {
import { AuthService } from '../service/auth.service'
import { UserAuthenticatedResponse } from '../auth.types'
import { Public } from '../../decorators/public.decorator'
import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'
import {
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
ApiTags
} from '@nestjs/swagger'
import { AuthGuard } from '@nestjs/passport'
import { GithubOAuthStrategyFactory } from '../../config/factory/github/github-strategy.factory'
import { GoogleOAuthStrategyFactory } from '../../config/factory/google/google-strategy.factory'
Expand Down Expand Up @@ -62,12 +68,12 @@ export class AuthController {
description:
'This endpoint validates OTPs. If the OTP is valid, it returns a valid token along with the user details'
})
@ApiParam({
@ApiQuery({
name: 'email',
description: 'Email to send OTP',
required: true
})
@ApiParam({
@ApiQuery({
name: 'otp',
description: 'OTP to validate',
required: true
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/common/static.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const invalidAuthenticationResponse = {
description: 'Invalid authentication header or API key'
}
6 changes: 6 additions & 0 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ async function initializeNestApp() {
.setTitle('keyshade')
.setDescription('The keyshade API description')
.setVersion('1.0')
.addBearerAuth({ type: 'http', scheme: 'bearer', bearerFormat: 'JWT' })
.addSecurity('api_key', {
type: 'apiKey',
in: 'header',
name: 'x-keyshade-token'
})
.build()
const document = SwaggerModule.createDocument(app, swaggerConfig)
SwaggerModule.setup('docs', app, document)
Expand Down
50 changes: 50 additions & 0 deletions apps/api/src/user/controller/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,70 @@ import { UpdateUserDto } from '../dto/update.user/update.user'
import { AdminGuard } from '../../auth/guard/admin/admin.guard'
import { CreateUserDto } from '../dto/create.user/create.user'
import {
ApiBearerAuth,
ApiCreatedResponse,
ApiForbiddenResponse,
ApiNoContentResponse,
ApiOkResponse,
ApiOperation,
ApiSecurity,
ApiTags
} from '@nestjs/swagger'
import { BypassOnboarding } from '../../decorators/bypass-onboarding.decorator'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { ForbidApiKey } from '../../decorators/forbid-api-key.decorator'
import { invalidAuthenticationResponse } from '../../common/static'

const userSchema = {
type: 'object',
properties: {
id: { type: 'string' },
email: { type: 'string' },
name: { type: 'string' },
profilePictureUrl: { type: 'string' },
isAdmin: { type: 'boolean' },
isActive: { type: 'boolean' },
isOnboardingFinished: { type: 'boolean' }
}
}

@ApiTags('User Controller')
@Controller('user')
@ApiBearerAuth()
@ApiSecurity('api_key')
export class UserController {
constructor(private readonly userService: UserService) {}

@Get()
@BypassOnboarding()
@RequiredApiKeyAuthorities(Authority.READ_SELF)
@ApiOperation({
summary: 'Get current user',
description:
'This endpoint returns the details of the currently logged in user'
})
@ApiOkResponse({
description: 'User details',
schema: userSchema
})
@ApiForbiddenResponse(invalidAuthenticationResponse)
async getCurrentUser(@CurrentUser() user: User) {
return this.userService.getSelf(user)
}

@Put()
@BypassOnboarding()
@RequiredApiKeyAuthorities(Authority.UPDATE_SELF)
@ApiOperation({
summary: 'Update current user',
description:
'This endpoint updates the details of the currently logged in user'
})
@ApiOkResponse({
description: 'Updated user details',
schema: userSchema
})
@ApiForbiddenResponse(invalidAuthenticationResponse)
async updateSelf(@CurrentUser() user: User, @Body() dto: UpdateUserDto) {
return await this.userService.updateSelf(user, dto)
}
Expand All @@ -48,6 +89,15 @@ export class UserController {
@ApiNoContentResponse()
@HttpCode(204)
@ForbidApiKey()
@ApiOperation({
summary: 'Delete current user',
description:
'This endpoint deletes the details of the currently logged in user'
})
@ApiForbiddenResponse(invalidAuthenticationResponse)
@ApiNoContentResponse({
description: 'User deleted successfully'
})
async deleteSelf(@CurrentUser() user: User) {
await this.userService.deleteSelf(user)
}
Expand Down
58 changes: 57 additions & 1 deletion apps/api/src/user/dto/create.user/create.user.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,77 @@
import { IsBoolean, IsOptional, IsString } from 'class-validator'
import { ApiProperty } from '@nestjs/swagger'
import { IsBoolean, IsEmail, IsOptional, IsString } from 'class-validator'

export class CreateUserDto {
@IsString()
@IsOptional()
@ApiProperty({
name: 'name',
description: 'Full name of the user',
required: false,
type: String,
example: 'John Doe',
default: null
})
name: string

@IsString()
@IsEmail()
@ApiProperty({
name: 'email',
description: 'Email of the user',
required: true,
type: String,
example: '[email protected]',
format: 'email',
uniqueItems: true
})
email: string

@IsString()
@IsOptional()
@ApiProperty({
name: 'profilePictureUrl',
description: 'URL of the user profile picture',
required: false,
type: String,
example: 'https://example.com/profile.jpg',
default: null
})
profilePictureUrl: string

@IsBoolean()
@IsOptional()
@ApiProperty({
name: 'isActive',
description: 'Is the user active',
required: false,
type: Boolean,
example: true,
default: true
})
isActive: boolean

@IsBoolean()
@IsOptional()
@ApiProperty({
name: 'isOnboardingFinished',
description: 'Is the user onboarding finished',
required: false,
type: Boolean,
example: true,
default: false
})
isOnboardingFinished: boolean

@IsBoolean()
@IsOptional()
@ApiProperty({
name: 'isAdmin',
description: 'Is the user an admin',
required: false,
type: Boolean,
example: false,
default: false
})
isAdmin: boolean
}

0 comments on commit fd59522

Please sign in to comment.