Skip to content

Commit

Permalink
fix: redirect guest user on public board (#1304)
Browse files Browse the repository at this point in the history
  • Loading branch information
CatiaAntunes96 authored Mar 24, 2023
1 parent 2061c92 commit b3f2516
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ export class GetBoardApplication implements GetBoardApplicationInterface {
getAllBoardIdsAndTeamIdsOfUser(userId: string) {
return this.getBoardService.getAllBoardIdsAndTeamIdsOfUser(userId);
}

isBoardPublic(boardId: string) {
return this.getBoardService.isBoardPublic(boardId);
}
}
3 changes: 2 additions & 1 deletion backend/src/modules/boards/boards.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
} from './boards.providers';
import BoardsController from './controller/boards.controller';
import TeamUsersModule from 'src/modules/teamUsers/teamusers.module';
import PublicBoardsController from './controller/publicBoards.controller';

@Module({
imports: [
Expand Down Expand Up @@ -76,7 +77,7 @@ import TeamUsersModule from 'src/modules/teamUsers/teamusers.module';
afterUserRequestedTimerStateSubscriber,
boardRepository
],
controllers: [BoardsController],
controllers: [BoardsController, PublicBoardsController],
exports: [
getBoardApplication,
createBoardService,
Expand Down
43 changes: 43 additions & 0 deletions backend/src/modules/boards/controller/publicBoards.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { BaseParam } from 'src/libs/dto/param/base.param';
import { BadRequestResponse } from 'src/libs/swagger/errors/bad-request.swagger';
import { InternalServerErrorResponse } from 'src/libs/swagger/errors/internal-server-error.swagger';
import { NotFoundResponse } from 'src/libs/swagger/errors/not-found.swagger';
import { Controller, Get, Inject, Param } from '@nestjs/common';
import {
ApiBadRequestResponse,
ApiInternalServerErrorResponse,
ApiNotFoundResponse,
ApiOperation,
ApiParam,
ApiTags
} from '@nestjs/swagger';
import { GetBoardApplicationInterface } from '../interfaces/applications/get.board.application.interface';
import { TYPES } from '../interfaces/types';

@ApiTags('PublicBoards')
@Controller('publicBoards')
export default class PublicBoardsController {
constructor(
@Inject(TYPES.applications.GetBoardApplication)
private getBoardApp: GetBoardApplicationInterface
) {}

@ApiOperation({ summary: 'Check if board is public' })
@ApiParam({ type: String, name: 'boardId', required: true })
@ApiBadRequestResponse({
description: 'Bad Request',
type: BadRequestResponse
})
@ApiNotFoundResponse({
type: NotFoundResponse,
description: 'Board not found!'
})
@ApiInternalServerErrorResponse({
description: 'Internal Server Error',
type: InternalServerErrorResponse
})
@Get(':boardId/isPublic')
getBoard(@Param() { boardId }: BaseParam) {
return this.getBoardApp.isBoardPublic(boardId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@ export interface GetBoardApplicationInterface {
getAllBoardIdsAndTeamIdsOfUser(
userId: string
): Promise<{ boardIds: LeanDocument<unknown>[]; teamIds: unknown[] }>;

isBoardPublic(boardId: string);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ export interface GetBoardServiceInterface {
getBoardUser(board: string, user: string): Promise<BoardUser>;

getAllMainBoards(): Promise<Board[]>;

isBoardPublic(boardId: string);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DeleteResult } from 'mongodb';

export interface BoardRepositoryInterface extends BaseInterfaceRepository<Board> {
getBoard(boardId: string): Promise<Board>;
isBoardPublic(boardId: string): Promise<Board>;
getBoardsByBoardIdsList(boardIds: string[]): Promise<Board[]>;
getBoardPopulated(boardId: string): Promise<Board>;
getMainBoard(boardId: string): Promise<Board>;
Expand Down
4 changes: 4 additions & 0 deletions backend/src/modules/boards/repositories/board.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class BoardRepository
return this.findOneById(boardId);
}

isBoardPublic(boardId: string): Promise<Board> {
return this.findOneById(boardId, 'isPublic');
}

getBoardsByBoardIdsList(boardIds: string[]): Promise<Board[]> {
return this.findAllWithQuery({
_id: { $in: boardIds }
Expand Down
23 changes: 23 additions & 0 deletions backend/src/modules/boards/services/get.board.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import Column from 'src/modules/columns/entities/column.schema';
import { UserDtoFactory } from 'src/libs/test-utils/mocks/factories/dto/userDto-factory.mock';
import { BadRequestException, NotFoundException } from '@nestjs/common';

const board = BoardFactory.create();

const hideVotesFromColumns = (columns: Column[], userId: string) => {
return columns.map((column) => {
column.cards.forEach((card) => {
Expand Down Expand Up @@ -558,4 +560,25 @@ describe('GetBoardService', () => {
expect(result).toEqual(countResult);
});
});

describe('isBoardPublic', () => {
it('should return the isPublic status of a board', async () => {
board.isPublic = true;

boardRepositoryMock.isBoardPublic.mockResolvedValue(board);

const result = await boardService.isBoardPublic(board._id);

expect(boardRepositoryMock.isBoardPublic).toBeCalledTimes(1);
expect(result).toEqual(true);
});

it('should throw an error if board is not found', async () => {
boardRepositoryMock.isBoardPublic.mockResolvedValue(null);

expect(async () => await boardService.isBoardPublic(board._id)).rejects.toThrow(
NotFoundException
);
});
});
});
12 changes: 11 additions & 1 deletion backend/src/modules/boards/services/get.board.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
NotFoundException,
forwardRef
} from '@nestjs/common';
import { BOARD_USER_NOT_FOUND, NOT_FOUND } from 'src/libs/exceptions/messages';
import { BOARD_NOT_FOUND, BOARD_USER_NOT_FOUND, NOT_FOUND } from 'src/libs/exceptions/messages';
import { GetTeamServiceInterface } from 'src/modules/teams/interfaces/services/get.team.service.interface';
import * as Teams from 'src/modules/teams/interfaces/types';
import * as Users from 'src/modules/users/interfaces/types';
Expand Down Expand Up @@ -159,6 +159,16 @@ export default class GetBoardService implements GetBoardServiceInterface {
return this.boardRepository.getAllMainBoards();
}

async isBoardPublic(boardId: string) {
const board = await this.boardRepository.isBoardPublic(boardId);

if (!board) {
throw new NotFoundException(BOARD_NOT_FOUND);
}

return board.isPublic;
}

/* --------------- HELPERS --------------- */

private async getBoards(allBoards: boolean, query: QueryType, page = 0, size = 10) {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/boardService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const getPublicStatusRequest = (
boardId: string,
context?: GetServerSidePropsContext,
): Promise<boolean> =>
fetchData<boolean>(`/publicBoards/${boardId}/publicStatus`, {
fetchData<boolean>(`/publicBoards/${boardId}/isPublic`, {
context,
serverSide: !!context,
isPublicRequest: true,
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/pages/boards/[boardId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getSession, useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react';
import { useRecoilState, useSetRecoilState } from 'recoil';
import { getBoardRequest } from '@/api/boardService';
import { getBoardRequest, getPublicStatusRequest } from '@/api/boardService';
import DragDropArea from '@/components/Board/DragDropArea';
import RegularBoard from '@/components/Board/RegularBoard';
import { BoardSettings } from '@/components/Board/Settings';
Expand Down Expand Up @@ -49,8 +49,10 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
props: {},
};

// if board is public and no session
if (!session) {
const boardIsPublic = await getPublicStatusRequest(boardId, context);

// if board is public and user has no session
if (boardIsPublic && !session) {
// check if there are guest user cookies
const cookiesGuestUser: GuestUser | { user: string } = getGuestUserCookies({ req, res }, true);
// if there isn´t cookies, the guest user is not registered
Expand Down

0 comments on commit b3f2516

Please sign in to comment.