Skip to content

Commit

Permalink
fix: invitation list
Browse files Browse the repository at this point in the history
  • Loading branch information
Mefjus committed May 20, 2021
1 parent 6c16559 commit 70c51e0
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 36 deletions.
14 changes: 10 additions & 4 deletions packages/api/src/modules/database/entities/invitation.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ export class InvitationEntity extends BaseEntity {
})
public roles: Array<Role>;

@ManyToOne(() => UserEntity, (user) => user.createdInvitations, { onDelete: 'CASCADE' })
public createdBy: Promise<UserEntity>;
@ManyToOne(() => UserEntity, (user) => user.createdInvitations, {
onDelete: 'CASCADE',
nullable: true,
})
public createdBy?: UserEntity;

@ManyToOne(() => UserEntity, (user) => user.updatedInvitations, { onDelete: 'CASCADE' })
public updatedBy: Promise<UserEntity>;
@ManyToOne(() => UserEntity, (user) => user.updatedInvitations, {
onDelete: 'CASCADE',
nullable: true,
})
public updatedBy?: UserEntity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class InvitationCreatedByNullable1621545394649 implements MigrationInterface {
name = 'InvitationCreatedByNullable1621545394649';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "invitations" DROP CONSTRAINT "FK_d5bc6e2af606d5aaaa4ef4e6be5"`,
);
await queryRunner.query(
`ALTER TABLE "invitations" DROP CONSTRAINT "FK_861bf660a15368ecfaf5d9ef853"`,
);
await queryRunner.query(
`ALTER TABLE "invitations" ADD CONSTRAINT "FK_d5bc6e2af606d5aaaa4ef4e6be5" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "invitations" ADD CONSTRAINT "FK_861bf660a15368ecfaf5d9ef853" FOREIGN KEY ("updatedById") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "invitations" DROP CONSTRAINT "FK_861bf660a15368ecfaf5d9ef853"`,
);
await queryRunner.query(
`ALTER TABLE "invitations" DROP CONSTRAINT "FK_d5bc6e2af606d5aaaa4ef4e6be5"`,
);
await queryRunner.query(
`ALTER TABLE "invitations" ADD CONSTRAINT "FK_861bf660a15368ecfaf5d9ef853" FOREIGN KEY ("updatedById") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "invitations" ADD CONSTRAINT "FK_d5bc6e2af606d5aaaa4ef4e6be5" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
}
}
21 changes: 21 additions & 0 deletions packages/api/src/modules/invitations/dto/invitation-item.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { InvitationStatus } from '../../../enums/invitationStatus.enum';
import { Role } from '../../../enums/role.enum';

export interface InvitationUser {
email: string;
firstName: string;
lastName: string;
roles: Array<Role>;
}

export interface InvitationItemDto {
id: string;
createdAt: number;
updatedAt: number;
email: string;
expirationDate: Date;
status: InvitationStatus;
roles: Array<Role>;
createdBy?: InvitationUser;
updatedBy?: InvitationUser;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsArray } from 'class-validator';

export class RemoveManyInvitationDto {
@IsArray()
ids: Array<string>;
}
18 changes: 12 additions & 6 deletions packages/api/src/modules/invitations/invitations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Auth } from '../auth/decorators/auth.decorator';
import { CookiePayload } from '../auth/decorators/cookiePayload.decorator';
import { UseSentryTransaction } from '../sentry/decorators/use-sentry-transaction.decorator';
import { CreateInvitationDto } from './dto/create-invitation.dto';
import { RemoveManyInvitationDto } from './dto/removeMany-invitation.dto';
import { UpdateInvitationDto } from './dto/update-invitation.dto';
import { InvitationsService } from './invitations.service';

Expand All @@ -25,8 +26,8 @@ export class InvitationsController {
@CookiePayload() { sub }: TokenPayload,
@Body(new ValidationPipe()) createInvitationDto: CreateInvitationDto,
) {
const getCurrentUserPromise = this.authService.getUser(sub);
await this.invitationsService.send(createInvitationDto, getCurrentUserPromise);
const getCurrentUser = await this.authService.getUser(sub);
await this.invitationsService.send(createInvitationDto, getCurrentUser);
}

@Get()
Expand All @@ -40,17 +41,22 @@ export class InvitationsController {
}

@Patch(':id')
update(
async update(
@CookiePayload() { sub }: TokenPayload,
@Param('id') id: string,
@Body() updateUserDto: UpdateInvitationDto,
@Body(new ValidationPipe()) updateUserDto: UpdateInvitationDto,
) {
const getCurrentUserPromise = this.authService.getUser(sub);
return this.invitationsService.update(id, updateUserDto, getCurrentUserPromise);
const getCurrentUser = await this.authService.getUser(sub);
return this.invitationsService.update(id, updateUserDto, getCurrentUser);
}

@Delete(':id')
remove(@Param('id') id: string) {
return this.invitationsService.remove(id);
}

@Post('removeMany')
removeMany(@Body(new ValidationPipe()) { ids }: RemoveManyInvitationDto) {
return this.invitationsService.removeMany(ids);
}
}
82 changes: 57 additions & 25 deletions packages/api/src/modules/invitations/invitations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { InvitationRepository } from '../repository/invitation.repository';
import { UserRepository } from '../repository/user.repository';
import { InvitationsConfigService } from './Config/invitations-config.service';
import { CreateInvitationDto } from './dto/create-invitation.dto';
import { InvitationItemDto } from './dto/invitation-item.dto';
import { UpdateInvitationDto } from './dto/update-invitation.dto';

@Injectable()
Expand All @@ -26,7 +27,7 @@ export class InvitationsService {

async send(
{ email, roles }: CreateInvitationDto,
currentUserPromise?: Promise<UserEntity>,
currentUser?: UserEntity,
): Promise<InvitationEntity> {
const user = await this.userRepository.findOneByEmail(email);
if (user) {
Expand All @@ -38,10 +39,10 @@ export class InvitationsService {
const expirationDate = this.invitationsConfigService.getExpirationDate();

let metaDetails = {};
if (currentUserPromise) {
if (currentUser) {
metaDetails = {
createdBy: currentUserPromise,
updatedBy: currentUserPromise,
createdBy: currentUser,
updatedBy: currentUser,
};
}

Expand All @@ -60,24 +61,52 @@ export class InvitationsService {

await this.mailerService.sendInvitation(email, link);

if (currentUserPromise) {
const {
id: currentUserId,
createdInvitations,
updatedInvitations,
} = await currentUserPromise;
await this.userRepository.update(currentUserId, {
createdInvitations: [...createdInvitations, createdInvitation],
updatedInvitations: [...updatedInvitations, createdInvitation],
});
}

return createdInvitation;
}

async findAll(): Promise<GetList<InvitationEntity>> {
const allInvitations = await this.repository.find();
return { data: allInvitations, total: allInvitations.length };
async findAll(): Promise<GetList<InvitationItemDto>> {
const invitations = await this.repository.find({ relations: ['createdBy', 'updatedBy'] });
const resultInvitation = invitations.map(
({
email,
id,
roles,
expirationDate,
status,
createdBy,
updatedBy,
createdAt,
updatedAt,
}): InvitationItemDto => {
return {
id,
email,
roles,
createdAt,
updatedAt,
expirationDate,
status,
createdBy: createdBy
? {
email: createdBy.email,
roles: createdBy.roles,
firstName: createdBy.firstName,
lastName: createdBy.lastName,
}
: undefined,
updatedBy: updatedBy
? {
email: updatedBy.email,
roles: updatedBy.roles,
firstName: updatedBy.firstName,
lastName: updatedBy.lastName,
}
: undefined,
};
},
);

return { data: resultInvitation, total: resultInvitation.length };
}

async findOne(id: string): Promise<InvitationEntity> {
Expand All @@ -89,7 +118,7 @@ export class InvitationsService {
async update(
id: string,
updateInvitationDto: UpdateInvitationDto,
currentUserPromise?: Promise<UserEntity>,
currentUser?: UserEntity,
): Promise<InvitationEntity | undefined> {
const foundInvitation = await this.findOne(id);

Expand All @@ -101,19 +130,22 @@ export class InvitationsService {
foundInvitation.roles = updateInvitationDto.roles;
}

if (currentUserPromise) {
const currentUser = await currentUserPromise;
const currentUpdatedBy = await foundInvitation.updatedBy;
if (currentUser) {
const currentUpdatedBy = foundInvitation.updatedBy;

if (currentUser.id !== currentUpdatedBy.id) {
foundInvitation.updatedBy = currentUserPromise;
if (currentUser.id !== currentUpdatedBy?.id) {
foundInvitation.updatedBy = currentUser;
}
}

await this.repository.save(foundInvitation);
return foundInvitation;
}

async removeMany(ids: Array<string>) {
await this.repository.delete(ids);
}

async remove(id: string): Promise<true> {
await this.connection
.createQueryBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ const Invitations = () => {
<SendInvitationButtonWithDialog />
<DetailedList resource="invitations" rowStyle={getRowStyle}>
<TextField source="email" />
<TextField source="createdBy" label="invitation.inviter" />
<FunctionField<ApiInvitation>
label="invitation.inviter"
render={({ createdBy }) => (createdBy ? createdBy.email : '-')}
/>
<InvitationStatusField label="Status" noTranslation />
<DateField source="createdAt" label="invitation.sendDate" showTime />
<FunctionField<ApiInvitation>
Expand Down

0 comments on commit 70c51e0

Please sign in to comment.