Skip to content

Commit

Permalink
feat: add missing abilities (#354)
Browse files Browse the repository at this point in the history
feat: add all missing abilities rules on resolvers
  • Loading branch information
magrinj authored Jun 22, 2023
1 parent 4a2797c commit c4ad017
Show file tree
Hide file tree
Showing 21 changed files with 461 additions and 104 deletions.
5 changes: 5 additions & 0 deletions server/src/ability/ability.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export class AbilityFactory {
);

// User
can(AbilityAction.Read, 'User', {
workspaceMember: {
workspaceId: workspace.id,
},
});
can(AbilityAction.Update, 'User', { id: user.id });
cannot(AbilityAction.Delete, 'User');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@ import { PrismaService } from 'src/database/prisma.service';
import { AbilityAction } from '../ability.action';
import { AppAbility } from '../ability.factory';
import { IAbilityHandler } from '../interfaces/ability-handler.interface';
import { Injectable } from '@nestjs/common';
import {
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { CommentThreadTargetWhereInput } from 'src/core/@generated/comment-thread-target/comment-thread-target-where.input';
import { GqlExecutionContext } from '@nestjs/graphql';
import { assert } from 'src/utils/assert';
import { subject } from '@casl/ability';

class CommentThreadTargetArgs {
where?: CommentThreadTargetWhereInput;
}

@Injectable()
export class ManageCommentThreadTargetAbilityHandler
implements IAbilityHandler
{
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility) {
return ability.can(AbilityAction.Manage, 'CommentThreadTarget');
}
Expand All @@ -35,16 +45,42 @@ export class CreateCommentThreadTargetAbilityHandler
export class UpdateCommentThreadTargetAbilityHandler
implements IAbilityHandler
{
handle(ability: AppAbility) {
return ability.can(AbilityAction.Update, 'CommentThreadTarget');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentThreadTargetArgs>();
const commentThreadTarget =
await this.prismaService.commentThreadTarget.findFirst({
where: args.where,
});
assert(commentThreadTarget, '', NotFoundException);

return ability.can(
AbilityAction.Update,
subject('CommentThreadTarget', commentThreadTarget),
);
}
}

@Injectable()
export class DeleteCommentThreadTargetAbilityHandler
implements IAbilityHandler
{
handle(ability: AppAbility) {
return ability.can(AbilityAction.Delete, 'CommentThreadTarget');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentThreadTargetArgs>();
const commentThreadTarget =
await this.prismaService.commentThreadTarget.findFirst({
where: args.where,
});
assert(commentThreadTarget, '', NotFoundException);

return ability.can(
AbilityAction.Delete,
subject('CommentThreadTarget', commentThreadTarget),
);
}
}
48 changes: 41 additions & 7 deletions server/src/ability/handlers/comment-thread.ability-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { PrismaService } from 'src/database/prisma.service';
import { AbilityAction } from '../ability.action';
import { AppAbility } from '../ability.factory';
import { IAbilityHandler } from '../interfaces/ability-handler.interface';
import { Injectable } from '@nestjs/common';
import {
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { CommentThreadWhereInput } from 'src/core/@generated/comment-thread/comment-thread-where.input';
import { assert } from 'src/utils/assert';
import { subject } from '@casl/ability';

class CommentThreadArgs {
where?: CommentThreadWhereInput;
}

@Injectable()
export class ManageCommentThreadAbilityHandler implements IAbilityHandler {
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility) {
return ability.can(AbilityAction.Manage, 'CommentThread');
}
Expand All @@ -29,14 +39,38 @@ export class CreateCommentThreadAbilityHandler implements IAbilityHandler {

@Injectable()
export class UpdateCommentThreadAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Update, 'CommentThread');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentThreadArgs>();
const commentThread = await this.prismaService.commentThread.findFirst({
where: args.where,
});
assert(commentThread, '', NotFoundException);

return ability.can(
AbilityAction.Update,
subject('CommentThread', commentThread),
);
}
}

@Injectable()
export class DeleteCommentThreadAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Delete, 'CommentThread');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentThreadArgs>();
const commentThread = await this.prismaService.commentThread.findFirst({
where: args.where,
});
assert(commentThread, '', NotFoundException);

return ability.can(
AbilityAction.Delete,
subject('CommentThread', commentThread),
);
}
}
42 changes: 35 additions & 7 deletions server/src/ability/handlers/comment.ability-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { PrismaService } from 'src/database/prisma.service';
import { AbilityAction } from '../ability.action';
import { AppAbility } from '../ability.factory';
import { IAbilityHandler } from '../interfaces/ability-handler.interface';
import { Injectable } from '@nestjs/common';
import {
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { subject } from '@casl/ability';
import { CommentWhereInput } from 'src/core/@generated/comment/comment-where.input';
import { GqlExecutionContext } from '@nestjs/graphql';
import { assert } from 'src/utils/assert';

class CommentArgs {
where?: CommentWhereInput;
}

@Injectable()
export class ManageCommentAbilityHandler implements IAbilityHandler {
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility) {
return ability.can(AbilityAction.Manage, 'Comment');
}
Expand All @@ -29,14 +39,32 @@ export class CreateCommentAbilityHandler implements IAbilityHandler {

@Injectable()
export class UpdateCommentAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Update, 'Comment');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentArgs>();
const comment = await this.prismaService.comment.findFirst({
where: args.where,
});
assert(comment, '', NotFoundException);

return ability.can(AbilityAction.Update, subject('Comment', comment));
}
}

@Injectable()
export class DeleteCommentAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Delete, 'Comment');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CommentArgs>();
const comment = await this.prismaService.comment.findFirst({
where: args.where,
});
assert(comment, '', NotFoundException);

return ability.can(AbilityAction.Delete, subject('Comment', comment));
}
}
42 changes: 35 additions & 7 deletions server/src/ability/handlers/company.ability-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { PrismaService } from 'src/database/prisma.service';
import { AbilityAction } from '../ability.action';
import { AppAbility } from '../ability.factory';
import { IAbilityHandler } from '../interfaces/ability-handler.interface';
import { Injectable } from '@nestjs/common';
import {
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { CompanyWhereInput } from 'src/core/@generated/company/company-where.input';
import { GqlExecutionContext } from '@nestjs/graphql';
import { assert } from 'src/utils/assert';
import { subject } from '@casl/ability';

class CompanyArgs {
where?: CompanyWhereInput;
}

@Injectable()
export class ManageCompanyAbilityHandler implements IAbilityHandler {
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility) {
return ability.can(AbilityAction.Manage, 'Company');
}
Expand All @@ -29,14 +39,32 @@ export class CreateCompanyAbilityHandler implements IAbilityHandler {

@Injectable()
export class UpdateCompanyAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Update, 'Company');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CompanyArgs>();
const company = await this.prismaService.company.findFirst({
where: args.where,
});
assert(company, '', NotFoundException);

return ability.can(AbilityAction.Update, subject('Company', company));
}
}

@Injectable()
export class DeleteCompanyAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Delete, 'Company');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<CompanyArgs>();
const company = await this.prismaService.company.findFirst({
where: args.where,
});
assert(company, '', NotFoundException);

return ability.can(AbilityAction.Delete, subject('Company', company));
}
}
42 changes: 35 additions & 7 deletions server/src/ability/handlers/person.ability-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { PrismaService } from 'src/database/prisma.service';
import { AbilityAction } from '../ability.action';
import { AppAbility } from '../ability.factory';
import { IAbilityHandler } from '../interfaces/ability-handler.interface';
import { Injectable } from '@nestjs/common';
import {
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { PersonWhereInput } from 'src/core/@generated/person/person-where.input';
import { GqlExecutionContext } from '@nestjs/graphql';
import { assert } from 'src/utils/assert';
import { subject } from '@casl/ability';

class PersonArgs {
where?: PersonWhereInput;
}

@Injectable()
export class ManagePersonAbilityHandler implements IAbilityHandler {
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility) {
return ability.can(AbilityAction.Manage, 'Person');
}
Expand All @@ -29,14 +39,32 @@ export class CreatePersonAbilityHandler implements IAbilityHandler {

@Injectable()
export class UpdatePersonAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Update, 'Person');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<PersonArgs>();
const person = await this.prismaService.person.findFirst({
where: args.where,
});
assert(person, '', NotFoundException);

return ability.can(AbilityAction.Update, subject('Person', person));
}
}

@Injectable()
export class DeletePersonAbilityHandler implements IAbilityHandler {
handle(ability: AppAbility) {
return ability.can(AbilityAction.Delete, 'Person');
constructor(private readonly prismaService: PrismaService) {}

async handle(ability: AppAbility, context: ExecutionContext) {
const gqlContext = GqlExecutionContext.create(context);
const args = gqlContext.getArgs<PersonArgs>();
const person = await this.prismaService.person.findFirst({
where: args.where,
});
assert(person, '', NotFoundException);

return ability.can(AbilityAction.Delete, subject('Person', person));
}
}
Loading

0 comments on commit c4ad017

Please sign in to comment.