Tenho as seguintes habilidades definidas em CaslAbilityFactory
:
if (auth.isAdmin) {
can(Action.Create, User);
can(Action.Read, "all");
can(Action.Manage, User);
can(Action.Update, User, ["email", "firstName", "lastName", "role"]);
can(Action.Delete, User);
cannot(Action.Delete, User, isOwner);
}
if (auth.isUser) {
can([Action.Read, Action.Update], User, isOwner);
}
Então, defini o seguinte resolver:
@Mutation(() => User)
@UseGuards(PoliciesGuard)
@CheckPolicies(ability => ability.can(Action.Update, User))
async updateUser(
@Args("input") input: UpdateUserInput,
@CurrentAuth() auth,
): Promise<User> {
const ability = this.caslAbilityFactory.createForAuth(auth);
if (ability.cannot(Action.Update, { id: input.id }) {
throw new ForbiddenException();
}
return this.usersService.update(input.id, input);
}
O @CheckPolicies
decorador garante corretamente que apenas um usuário com a Update
ação para usuários pode chamá-lo, mas preciso afirmar que para este específico, posso atualizá-lo? Se o solicitante for o proprietário, ele pode. Mas como você verifica isso antes de carregar o usuário?
Uma solução óbvia é carregar o usuário, executar a verificação e, então, executar a atualização. Outra solução mais hackeada seria, de alguma forma, fazer o cast new User({ id })
e executar a verificação.
Existe uma solução melhor para isso?
Obrigado,
Há poucas opções para fazer isso. 2 delas você mencionou. Outra é converter condições casl para consulta de banco de dados e deixar o db verificar as condições.
Isso é possível para casl-prisma. Há também algum trabalho feito nessa direção para outras bibliotecas SQL, mas não foi concluído.
Casting POJO para
User
é a pior opção porque você revela permissões para o controlador. Você sabe que somente os proprietários podem acessar este objeto, é por isso que você codifica o formato do objeto para que o casl retorne o resultado esperado. MAS assim que você altera essas permissões no nível casl, você também precisará atualizar seu formato POJO codificado. Então, basicamente, você perde a flexibilidade que o casl lhe dá - alterando permissões em um único lugar.É por isso que existem apenas duas soluções viáveis a longo prazo: