Skip to content

Commit

Permalink
Throw error on user delete when owner of organization
Browse files Browse the repository at this point in the history
  • Loading branch information
MrBartusek committed Jun 3, 2024
1 parent eb19d87 commit 1ad58a7
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 3 deletions.
2 changes: 2 additions & 0 deletions apps/api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { UpdateEmailDto } from './dto/update-email.dto';
import { UserRegisterDto } from './dto/user-register.dto';
import { AuthGuard } from './guards/auth.guard';
import { LocalAuthGuard } from './guards/local-auth.guard';
import { NotOrgOwnerGuard } from '../models/users/guards/org-owner.guard';

@Controller('auth')
@ApiTags('auth')
Expand Down Expand Up @@ -105,6 +106,7 @@ export class AuthController {
@Delete('delete')
@UseGuards(AuthGuard)
@UseGuards(NotDemoGuard)
@UseGuards(NotOrgOwnerGuard)
async deleteAccount(@Req() request: Request, @Body() dto: DeleteAccountDto) {
const userId = new Types.ObjectId(request.user.id);
const user = await this.authService.validateUserByUserId(userId, dto.password);
Expand Down
4 changes: 3 additions & 1 deletion apps/api/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import { SessionSerializer } from './session.serializer';
import { LocalStrategy } from './strategies/local.strategy';
import { BearerStrategy } from './strategies/bearer.strategy';
import { ApiKeysModule } from '../api-keys/api-keys.module';
import { OrganizationsModule } from '../models/organizations/organizations.module';

@Module({
imports: [
PassportModule.register({ session: true }),
ApiKeysModule,
UsersModule,
forwardRef(() => UsersModule),
forwardRef(() => AuthEmailsModule),
forwardRef(() => OrganizationsModule),
],
controllers: [AuthController],
providers: [
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/models/inventory/inventory.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { InventoryItem, InventoryItemSchema } from './schemas/inventory-item.sch
imports: [
MongooseModuleHelper.forFeature(InventoryItem, InventoryItemSchema),
forwardRef(() => OrganizationResolverModule),
SecurityModule,
forwardRef(() => SecurityModule),
],
controllers: [InventoryController],
providers: [
Expand Down
11 changes: 11 additions & 0 deletions apps/api/src/models/organizations/organizations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { OrganizationUpdatedEvent } from './events/organization-updated.event';
import { OrganizationRepository } from './organizations.repository';
import { OrgSettingsDocument } from './schemas/org-settings';
import { OrganizationDocument } from './schemas/organization.schema';
import { OrganizationSecurityRole } from 'shared-types';

@Injectable()
export class OrganizationsService {
Expand Down Expand Up @@ -66,6 +67,16 @@ export class OrganizationsService {
return this.organizationRepository.find({ 'acls.user': id });
}

/**
* Check if specified user is owner of any organization
*/
async isUserOwnerOfAny(id: Types.ObjectId): Promise<boolean> {
return this.organizationRepository.exist({
'acls.user': id,
'acls.role': OrganizationSecurityRole.OWNER,
});
}

async paginateAllForUser(id: Types.ObjectId, pageQueryDto: PageQueryDto) {
return this.organizationRepository.paginate({ 'acls.user': id }, pageQueryDto);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/models/products/products.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Product, ProductSchema } from './schemas/product.schema';
imports: [
MongooseModuleHelper.forFeature(Product, ProductSchema),
forwardRef(() => OrganizationResolverModule),
SecurityModule,
forwardRef(() => SecurityModule),
ImagesModule,
],
controllers: [ProductsController],
Expand Down
25 changes: 25 additions & 0 deletions apps/api/src/models/users/guards/org-owner.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { BadRequestException, CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Request } from 'express';
import { Types } from 'mongoose';
import { OrganizationsService } from '../../organizations/organizations.service';

@Injectable()
export class NotOrgOwnerGuard implements CanActivate {
constructor(private readonly organizationsService: OrganizationsService) {}

async canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest<Request>();
const user = new Types.ObjectId(request.user.id);

const isOwner = await this.organizationsService.isUserOwnerOfAny(user);

if (isOwner) {
throw new BadRequestException(
'In order to delete account you must first transfer ownership of ' +
'all organizations that you own.',
);
}

return true;
}
}

0 comments on commit 1ad58a7

Please sign in to comment.