Skip to content

Commit

Permalink
Merge pull request #131 from codeforjapan/yash/paginate
Browse files Browse the repository at this point in the history
Add pagination support for admin list
  • Loading branch information
DaisukeHirata authored May 13, 2020
2 parents 42cc9bc + 74eb725 commit f8f0dc6
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 10 deletions.
14 changes: 14 additions & 0 deletions firebase.firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{
"indexes": [
{
"collectionGroup": "admins",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "accessControlList",
"arrayConfig": "CONTAINS"
},
{
"fieldPath": "email",
"order": "ASCENDING"
}
]
},
{
"collectionGroup": "prefectures",
"queryScope": "COLLECTION",
Expand Down
8 changes: 6 additions & 2 deletions src/admins/admins.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HttpCode,
Param,
Delete,
Query,
} from '@nestjs/common'
import {
ApiOperation,
Expand All @@ -29,6 +30,7 @@ import { Admin } from './classes/admin.class'
import { NoResponseBodyInterceptor } from '../shared/interceptors/no-response-body.interceptor'
import { NoResponseBody } from '../shared/classes/no-response-body.class'
import { RequestAdminUser } from '../shared/interfaces'
import { PaginationParamsDto } from '../shared/classes/pagination-params.class'

@ApiTags('admin')
@ApiBearerAuth()
Expand All @@ -40,11 +42,13 @@ export class AdminsController {
constructor(private adminsService: AdminsService) {}

// TODO @yashmurty : Investigate pagination for this later.
@UsePipes(new ValidationPipe(VALIDATION_PIPE_OPTIONS))
@ApiOperation({ summary: 'Get all admin users' })
@ApiOkResponse({ type: [Admin] })
@Get('/users')
async getAdminUsers(): Promise<Admin[]> {
return this.adminsService.findAllAdminUsers()
async getAdminUsers(@Request() req, @Query() query: PaginationParamsDto): Promise<Admin[]> {
const requestAdminUser: RequestAdminUser = req.user
return this.adminsService.findAllAdminUsers(requestAdminUser, query.limit, query.offset)
}

@UsePipes(new ValidationPipe(VALIDATION_PIPE_OPTIONS))
Expand Down
11 changes: 9 additions & 2 deletions src/admins/admins.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,19 @@ export class AdminsRepository {
return admin
}

async findAll(): Promise<Admin[] | undefined> {
async findAll(
userAccessKey: string,
limit: number,
offset: number
): Promise<Admin[] | undefined> {
const adminsArray: Admin[] = []

const adminsRef = (await this.firestoreDB).collection('admins')
await adminsRef
.limit(100)
.orderBy('email')
.where('accessControlList', 'array-contains', userAccessKey)
.limit(limit)
.offset(offset)
.get()
.then((snapshot) => {
if (snapshot.empty) {
Expand Down
13 changes: 7 additions & 6 deletions src/admins/admins.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,16 @@ export class AdminsService {
return this.adminsRepository.findOneById(adminId)
}

async findAllAdminUsers(): Promise<Admin[]> {
// TODO @yashmurty :
// Fetch resource and perform ACL check.

return this.adminsRepository.findAll()
async findAllAdminUsers(
requestAdminUser: RequestAdminUser,
limit: number,
offset: number
): Promise<Admin[]> {
// ACL check is automatically performed in the repository function.
return this.adminsRepository.findAll(requestAdminUser.userAccessKey, limit, offset)
}

async deleteOneAdminById(requestAdminUser: RequestAdminUser, adminId: string): Promise<void> {
// TODO @yashmurty :
// Fetch resource and perform ACL check. Check performed within the called function.
await this.getOneAdminById(requestAdminUser, adminId)

Expand Down
23 changes: 23 additions & 0 deletions src/shared/classes/pagination-params.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IsNumber, IsOptional } from 'class-validator'
import { Transform } from 'class-transformer'
import { ApiPropertyOptional } from '@nestjs/swagger'

export class PaginationParamsDto {
@ApiPropertyOptional({
description: 'Optional, defaults to 100',
type: Number,
})
@IsNumber()
@IsOptional()
@Transform((value) => parseInt(value, 10), { toClassOnly: true })
limit = 100

@ApiPropertyOptional({
description: 'Optional, defaults to 0',
type: Number,
})
@IsNumber()
@IsOptional()
@Transform((value) => parseInt(value, 10), { toClassOnly: true })
offset = 0
}

0 comments on commit f8f0dc6

Please sign in to comment.