Skip to content

Commit

Permalink
feat: dashboard statistics and get all boards with pagination (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
nunocaseiro authored Apr 11, 2022
1 parent bdc35f2 commit 1d569d6
Show file tree
Hide file tree
Showing 21 changed files with 412 additions and 49 deletions.
17 changes: 17 additions & 0 deletions backend/src/infrastructure/config/jwt.register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import {
JWT_ACCESS_TOKEN_SECRET,
JWT_ACCESS_TOKEN_EXPIRATION_TIME,
} from '../../libs/constants/jwt';

export const JwtRegister = JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
secret: configService.get(JWT_ACCESS_TOKEN_SECRET),
signOptions: {
expiresIn: `${configService.get(JWT_ACCESS_TOKEN_EXPIRATION_TIME)}s`,
},
}),
});
16 changes: 16 additions & 0 deletions backend/src/libs/dto/param/pagination.params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IsNumber, Min, IsOptional } from 'class-validator';
import { Type } from 'class-transformer';

export class PaginationParams {
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(0)
page?: number;

@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
size?: number;
}
20 changes: 7 additions & 13 deletions backend/src/modules/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ConfigModule } from '@nestjs/config';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';

import AuthController from './controller/auth.controller';
import UsersModule from '../users/users.module';
import LocalStrategy from './strategy/local.strategy';
Expand All @@ -15,22 +13,18 @@ import {
getTokenAuthApplication,
registerAuthApplication,
} from './auth.providers';
import TeamsModule from '../teams/teams.module';
import BoardsModule from '../boards/boards.module';
import { JwtRegister } from '../../infrastructure/config/jwt.register';

@Module({
imports: [
UsersModule,
TeamsModule,
JwtRegister,
BoardsModule,
PassportModule,
ConfigModule,
JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
secret: configService.get('jwt.accessToken.secret'),
signOptions: {
expiresIn: `${configService.get('jwt.accessToken.expirationTime')}s`,
},
}),
}),
],
providers: [
getTokenAuthService,
Expand Down
23 changes: 22 additions & 1 deletion backend/src/modules/auth/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
BadRequestException,
Param,
} from '@nestjs/common';
import { EmailParam } from '../../../libs/dto/param/email.param';
import LocalAuthGuard from '../../../libs/guards/localAuth.guard';
import RequestWithUser from '../../../libs/interfaces/requestWithUser.interface';
import JwtRefreshGuard from '../../../libs/guards/jwtRefreshAuth.guard';
Expand All @@ -26,7 +25,13 @@ import CreateUserDto from '../../users/dto/create.user.dto';
import { uniqueViolation } from '../../../infrastructure/database/errors/unique.user';
import { signIn } from '../shared/login.auth';
import * as User from '../../users/interfaces/types';
import * as Teams from '../../teams/interfaces/types';
import * as Boards from '../../boards/interfaces/types';
import { EmailParam } from '../../../libs/dto/param/email.param';
import { GetUserApplication } from '../../users/interfaces/applications/get.user.application.interface';
import JwtAuthenticationGuard from '../../../libs/guards/jwtAuth.guard';
import { GetBoardApplicationInterface } from '../../boards/interfaces/applications/get.board.application.interface';
import { GetTeamApplicationInterface } from '../../teams/interfaces/applications/get.team.application.interface';

@Controller('auth')
export default class AuthController {
Expand All @@ -37,6 +42,10 @@ export default class AuthController {
private getTokenAuthApp: GetTokenAuthApplication,
@Inject(User.TYPES.applications.GetUserApplication)
private getUserApp: GetUserApplication,
@Inject(Teams.TYPES.applications.GetTeamApplication)
private getTeamsApp: GetTeamApplicationInterface,
@Inject(Boards.TYPES.applications.GetBoardApplication)
private getBoardApp: GetBoardApplicationInterface,
) {}

@Post('register')
Expand Down Expand Up @@ -78,4 +87,16 @@ export default class AuthController {
checkEmail(@Param() { email }: EmailParam): Promise<boolean> {
return this.getUserApp.getByEmail(email).then((user) => !!user);
}

@UseGuards(JwtAuthenticationGuard)
@Get('/dashboardStatistics')
async getDashboardHeaderInfo(@Req() request: RequestWithUser) {
const { _id: userId } = request.user;
const [usersCount, teamsCount, boardsCount] = await Promise.all([
this.getUserApp.countUsers(),
this.getTeamsApp.countTeams(userId),
this.getBoardApp.countBoards(userId),
]);
return { usersCount, teamsCount, boardsCount };
}
}
2 changes: 2 additions & 0 deletions backend/src/modules/azure/services/auth.azure.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export default class AuthAzureServiceImpl implements AuthAzureService {
const { unique_name, email, given_name, family_name } = <AzureDecodedUser>(
jwt_decode(azureToken)
);
const userExists = await this.checkUserExistsInActiveDirectory(email);
if (!userExists) return null;

const emailOrUniqueName = email ?? unique_name;
const user = await this.getUserService.getByEmail(emailOrUniqueName);
Expand Down
33 changes: 29 additions & 4 deletions backend/src/modules/boards/applications/get.board.application.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
import { Inject, Injectable } from '@nestjs/common';
import { GetBoardApplicationInterface } from '../interfaces/applications/get.board.application.interface';
import { GetBoardService } from '../interfaces/services/get.board.service.interface';
import { BoardsAndPage } from '../interfaces/boards-page.interface';
import { GetBoardServiceInterface } from '../interfaces/services/get.board.service.interface';
import { TYPES } from '../interfaces/types';

@Injectable()
export class GetBoardApplication implements GetBoardApplicationInterface {
constructor(
@Inject(TYPES.services.GetBoardService)
private getBoardService: GetBoardService,
private getBoardService: GetBoardServiceInterface,
) {}

getAllBoards(userId: string) {
return this.getBoardService.getAllBoards(userId);
getUserBoardsOfLast3Months(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null> {
return this.getBoardService.getUserBoardsOfLast3Months(userId, page, size);
}

getSuperAdminBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null> {
return this.getBoardService.getSuperAdminBoards(userId, page, size);
}

getUsersBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null> {
return this.getBoardService.getUsersBoards(userId, page, size);
}

getBoard(boardId: string, userId: string) {
return this.getBoardService.getBoard(boardId, userId);
}

countBoards(userId: string) {
return this.getBoardService.countBoards(userId);
}
}
10 changes: 8 additions & 2 deletions backend/src/modules/boards/boards.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ import {
mongooseBoardModule,
mongooseBoardUserModule,
} from '../../infrastructure/database/mongoose.module';
import TeamsModule from '../teams/teams.module';

@Module({
imports: [UsersModule, mongooseBoardModule, mongooseBoardUserModule],
imports: [
UsersModule,
TeamsModule,
mongooseBoardModule,
mongooseBoardUserModule,
],
providers: [
createBoardService,
updateBoardService,
Expand All @@ -29,6 +35,6 @@ import {
getBoardApplication,
],
controllers: [BoardsController],
exports: [],
exports: [getBoardApplication],
})
export default class BoardsModule {}
28 changes: 25 additions & 3 deletions backend/src/modules/boards/controller/boards.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
Param,
Post,
Put,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import { BaseParam } from '../../../libs/dto/param/base.param';
import BoardDto from '../dto/board.dto';
import JwtAuthenticationGuard from '../../../libs/guards/jwtAuth.guard';
import RequestWithUser from '../../../libs/interfaces/requestWithUser.interface';
Expand All @@ -27,6 +27,8 @@ import {
INSERT_FAILED,
UPDATE_FAILED,
} from '../../../libs/exceptions/messages';
import { BaseParam } from '../../../libs/dto/param/base.param';
import { PaginationParams } from '../../../libs/dto/param/pagination.params';

@Controller('boards')
export default class BoardsController {
Expand All @@ -53,10 +55,30 @@ export default class BoardsController {
return board;
}

@UseGuards(JwtAuthenticationGuard)
@Get('/dashboard')
getDashboardBoards(
@Req() request: RequestWithUser,
@Query() { page, size }: PaginationParams,
) {
return this.getBoardApp.getUserBoardsOfLast3Months(
request.user._id,
page,
size,
);
}

@UseGuards(JwtAuthenticationGuard)
@Get()
boards(@Req() request: RequestWithUser) {
return this.getBoardApp.getAllBoards(request.user._id);
getAllBoards(
@Req() request: RequestWithUser,
@Query() { page, size }: PaginationParams,
) {
const { _id: userId, isSAdmin } = request.user;
if (isSAdmin) {
return this.getBoardApp.getSuperAdminBoards(userId, page, size);
}
return this.getBoardApp.getUsersBoards(userId, page, size);
}

@UseGuards(JwtAuthenticationGuard)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import { LeanDocument } from 'mongoose';
import { BoardDocument } from '../../schemas/board.schema';
import { BoardsAndPage } from '../boards-page.interface';

export interface GetBoardApplicationInterface {
getAllBoards(userId: string): Promise<LeanDocument<BoardDocument>[] | null>;
getUserBoardsOfLast3Months(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getSuperAdminBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getUsersBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getBoard(
boardId: string,
userId: string,
): Promise<LeanDocument<BoardDocument> | null>;
countBoards(userId: string): Promise<number>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { LeanDocument } from 'mongoose';
import { BoardDocument } from '../schemas/board.schema';

export interface BoardsAndPage {
boards: LeanDocument<BoardDocument>[];
hasNextPage: boolean;
page: number;
}
33 changes: 33 additions & 0 deletions backend/src/modules/boards/interfaces/findQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { LeanDocument } from 'mongoose';
import { TeamUserDocument } from '../../teams/schemas/team.user.schema';

export type QueryType = {
$and: (
| {
isSubBoard: boolean;
updatedAt?: {
$gte: number;
};
$or?: undefined;
}
| {
$or: (
| {
_id: {
$in: LeanDocument<any>[];
};
team?: undefined;
}
| {
team: {
$in?: LeanDocument<TeamUserDocument>[];
$ne?: undefined | null;
};
_id?: undefined;
}
)[];
isSubBoard?: undefined;
updatedAt?: undefined;
}
)[];
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { LeanDocument } from 'mongoose';
import { BoardDocument } from '../../schemas/board.schema';
import { BoardsAndPage } from '../boards-page.interface';

export interface GetBoardService {
getAllBoards(userId: string): Promise<LeanDocument<BoardDocument>[] | null>;
export interface GetBoardServiceInterface {
getUserBoardsOfLast3Months(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getSuperAdminBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getUsersBoards(
userId: string,
page?: number,
size?: number,
): Promise<BoardsAndPage | null>;
getBoardFromRepo(
boardId: string,
): Promise<LeanDocument<BoardDocument> | null>;
getBoard(
boardId: string,
userId: string,
): Promise<LeanDocument<BoardDocument> | null>;
countBoards(userId: string): Promise<number>;
}
3 changes: 0 additions & 3 deletions backend/src/modules/boards/schemas/board.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ export type BoardDocument = Board & Document;

@Schema({
timestamps: true,
toJSON: {
virtuals: true,
},
})
export default class Board {
@Prop({ nullable: false })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export default class CreateBoardServiceImpl implements CreateBoardService {
...boardData,
createdBy: userId,
dividedBoards: await this.createDividedBoards(dividedBoards, userId),
isSubBoard: isEmpty(dividedBoards),
});
}

Expand Down
Loading

0 comments on commit 1d569d6

Please sign in to comment.