Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jan 31 2019 22:44
    renovate[bot] edited #154
  • Jan 31 2019 22:17
    riyadshauk starred stalniy/casl
  • Jan 31 2019 21:49
    renovate[bot] commented #154
  • Jan 31 2019 21:49
    renovate[bot] opened #154
  • Jan 31 2019 20:16

    renovate[bot] on typescript-3.x

    chore(deps): update dependency … (compare)

  • Jan 31 2019 17:15
    iamvanja starred stalniy/casl
  • Jan 31 2019 17:13
    RedShift1 commented #153
  • Jan 31 2019 16:35
    stalniy commented #152
  • Jan 31 2019 16:33
    stalniy commented #153
  • Jan 31 2019 15:45
    RedShift1 opened #153
  • Jan 31 2019 11:11
    chrisblakely01 starred stalniy/casl
  • Jan 31 2019 04:58
    l02162010 starred stalniy/casl
  • Jan 31 2019 03:22
    l02162010 commented #150
  • Jan 30 2019 22:58
    ifatihyildirim starred stalniy/casl
  • Jan 30 2019 20:56
    scytherswings starred stalniy/casl
  • Jan 30 2019 19:38
    jmwohl starred stalniy/casl
  • Jan 30 2019 18:55
    mdaronco starred stalniy/casl
  • Jan 30 2019 10:57
    AlexGoranov edited #152
  • Jan 30 2019 10:57
    AlexGoranov edited #152
  • Jan 30 2019 10:57
    AlexGoranov edited #152
Norbert
@norbiu
Hi! I'm trying to implement casl-react using typescript, but I'm getting a TS error when creating the context:
import { Ability, AbilityBuilder } from '@casl/ability';
import { createContextualCan } from '@casl/react';
import { createContext } from 'react';

export const ability = new AbilityBuilder(Ability);

export const AbilityContext = createContext({});

export const Can = createContextualCan(AbilityContext.Consumer);
Argument of type 'Consumer<{}>' is not assignable to parameter of type 'Consumer<AnyAbility>'.
  Type 'ConsumerProps<AnyAbility>' is not assignable to type 'ConsumerProps<{}>'.
    Type '{}' is missing the following properties from type 'AnyAbility': can, relevantRuleFor, cannot, rules, and 7 more.
Sergii Stotskyi
@stalniy
ramk18
@ramk18
Has someone used this in conjunction with aws cognito?
Oskar Yildiz
@oskaryil
Hello,
We are using nestjs in combination with casl and casl-ability. We have run into some issues with understanding how casl's abilities and rules actually work under the hood. Like for example, how does a validation rule passed as a second argument to can match the value against the Model?
In this case as shown in the code below, how does casl actually get the vendor value that it is suppose to check on the ProductCollection?
We are getting a value for vendor in our request body that we want to use as the check in the ability.
      can(Action.Create, ProductCollection, {
        vendor: { $in: user.vendors },
      });
      can(Action.Update, ProductCollection, {
        vendor: { $in: user.vendors },
      });
Sergii Stotskyi
@stalniy
Oskar Yildiz
@oskaryil

Hey @stalniy. Yes, I read about it. The way we're using CASL in our backend is with NestJS Guards. Please see https://docs.nestjs.com/security/authorization#advanced-implementing-a-policiesguard for an example.

With that said, we're doing the ability check on a route level. Like this:

  @Post()
  @UseGuards(PoliciesGuard)
  @CheckPolicies((ability: Ability) =>
    ability.can(Action.Create, ProductCollection),
  )
4 replies
Where ProductCollection in this case is the actual Mongoose/Typegoose Class and not an instance of it.
Does that make sense?
David Waterston
@davidwaterston

Is it possible to give access to a field then remove it in the same set of Abilities? Something like this:

{
    "subject": "Financial",
    "action": "read",
    "fields": [
        "salary",
        "taxcode"
    ]
},
{
    "subject": "Financial",
    "action": "read",
    "inverted": true,
    "fields": [
        “salary"
    ]
}

I have a situation where I have a user who is in a role called ‘HR’. This gives them access to the two fields ‘salary’ and ‘taxcode’ (the first ability in my example). But a particular person also has user-specific Abilities which remove the read access to ‘salary’. I had hoped that by appending the user abilities to the role abilities in the way I have done above this user would only have read access to ‘taxcode’ but using ‘can’ tells me the user can still read both fields.
Is there a way to achieve this?

5 replies
OLAWOYE OMOTAYO
@TayoDavid
Hello every. Please I'm running into the logic problem using casl with my vue app
The CASL-Vue Can component hides components for both authorized and unauthorized user
Here's my ability.js

import {Ability, AbilityBuilder} from "@casl/ability";

export default function defineAbilityFor(hasRole) {
const { can, cannot, build } = new AbilityBuilder(Ability)
can('read', 'all')
if (hasRole === undefined) {
cannot('create', 'all')
} else {
console.log(hasRole)
can('create', 'all')
}

return build()

}

21 replies
I'm checking if the user hasRole which returns an object or undefined if the user has permission or not
Gabriel
@th3rius
is there an easy way of detecting the subject type of mongoose documents? should I use the model as the type?
Sergii Stotskyi
@stalniy
@th3rius if you wanna use models as subject types you will need to provide custom detectSubjectType function. I haven't tried to do this but very likely it will be the same as for regular classes (after all Model is a function constructor)
janek
@janek:matrix.org
[m]

Hello,

Is there a recommended way of checking permissions in backend before "creating" something?

e.g:

Roles: ADMIN, USER
Subjects: post

ADMIN:

can('manage', 'post')

USER:

can('create', 'post', { ownerId: user.id })

Now in by create post controller, I get POST data/dto with new post. Admins can create posts for other users, so "ownerId" can be provided by ADMINs. In case of USER create post as other user should be forbidden (according to casl ability).

To archive this I'm using something like this:

function createPost(postData: CreatePostDto) {
   const data = { ownerId: currentUser.id, ...postData }
   if (auth.cannot('create', subject('post', data as any)) {
     throw ForbiddenError()
   }
   return service.create(data)
}

as casl is expecting a full-blown "post" object in it's helpers, I have to do a as any or as POST cast which seems kind of ugly to me.
But maybe my approach is not really as it's intended by the library authors in the first place.

Does anyone have any ideas/examples on how to check abilities with CASL in a case like this?

OLAWOYE OMOTAYO
@TayoDavid
Please When I user "ProvideAbility" in a Casl-Vue, how do i inject it into a child component. The documentation describe how to add the provideability hook. How can i use the provided ability in the child component.
OLAWOYE OMOTAYO
@TayoDavid
I found I could use inject from the documentation but i always have to reload the page before the boolean component is made visible or hidden.
Ferid Zuber
@Ferido07
I'm just learning about CASL and I found that I can write the rules in JSON so I can retrieve them from database, this way it would be flexible enough to change the rules. I know that when building the rules using AbilityBuilder I can use if statements to create the rules based on the users attributes. I can also use the attributes of the user in the condition argument to match with the Subject. But what I couldn't find info on is how can I use the attributes of the user in the condition argument if I'm retrieving the rules from a database using JSON? Or more broadly how can I define and get other information(For example, the time, the location, the IP or other relevant environment information) to be accessible in the condition object when defining rules in JSON.
Ferid Zuber
@Ferido07
@stalniy
Ferid Zuber
@Ferido07
No problem found the answer https://casl.js.org/v5/en/cookbook/roles-with-persisted-permissions/ I didn't know I could do interpolation. I could definitely use other variables and interpolate them in as well. This is very great library. I've checked Casbin and I was inclined to it because it allows changing policy but now after discovering this CASL is definitely way easier to understand and use. Thanks for making it.
Sergii Stotskyi
@stalniy
Happy that you find it useful @Ferido07 :)
Forloski
@Forloski
Hey, ins CASL documentation with TypeScript it shows the use of Strings as subjects, but then i try to use them it does not work. The only way to make it work is using the entity class as subject.
can(Action.Update, Relationship) //this works
can(Action.Update, 'Relationship') //this does not
I'm doing something wrong or its intended?
Sergii Stotskyi
@stalniy
Hey @Forloski it depends on several configuration factors
  1. ts generics specified
  1. detectSubjectType option
Jon Bloom
@jonbloom
Hi all, I'm using @casl/vue@1.x and am having some issues with updating my ability instance stored in my Vuex store. I have a defineAbilityFor(user) function defined, which checks a users permission level and conditionally applies different rules appropriately. For example I have something similar to if (user.isAdmin) {can('read', 'shipments')}. Later, when actually checking, all $can or $ability.can checks return false. running $ability.relevantRuleFor('read', 'shipments') returns null every time. Where should I be looking?
I'm using Vue 2, with some relevant snippets below:
// ability/index.js
import { AbilityBuilder, Ability } from "@casl/ability";
import { UserPermissionsLevel } from "@/constants";

export default (user) => {
  const { can, build } = new AbilityBuilder(Ability);

  if (user) {
    can("read", "system");
    can("read", "shipment");

    if (user.permission_level == UserPermissionsLevel.Admin) {
      can("update", "system");
      can("update", "shipment");
    }
  }
  return build();
};
//main.js
Vue.use(abilitiesPlugin, store.getters.ability, {
  useGlobalProperties: true,
});
//store/plugins/ability.js
import { USER_PROFILE_SUCCESS } from "@/store/actions/user";
import defineAbilityFor from "@/ability";

export default (store) => {
  const ability = store.getters.ability;

  // ability.update(store.state.rules);

  return store.subscribe((mutation) => {
    switch (mutation.type) {
      case USER_PROFILE_SUCCESS:
        ability.update(defineAbilityFor(mutation.payload));
        break;
    }
  });
};
Jon Bloom
@jonbloom
...I figured it out. I was passing the entire Ability instance from defineAbilityFor into the update() call, not the actual rules to update it with.
nzaouesgi
@nzaouesgi

Hello everyone, i just had this error while building my app:

node_modules/@casl/ability/dist/types/matchers/conditions.d.ts:26:5 - error TS2502: 'produce' is referenced directly or indirectly in its own type annotation.

26     produce: MongoQuery<this[0]>;

My Typescript version is 4.3.2
Install casl is 5.3.1

any ideas ?

Sergii Stotskyi
@stalniy

Hello,

Hmm.... it may be an issue related to changes in TS 4.3, they did changes into generics handling. I got similar issues in other places. Could you please check with TS 4.2.x and let me know whether it works there?

nzaouesgi
@nzaouesgi
yeah i'm gonna try it out
it's so weird. sometimes it works (build success) and sometimes it does not. i'm using the exact same command line which is tsc --p tsconfig.build.json.
i'm very confused. i'm going to downgrade version and see if the error disappears completetly
nzaouesgi
@nzaouesgi
@stalniy i can confirm that build works when using typescript version 4.2.4
Bryan Van Horn
@bryan-vh

Hello @stalniy ,

Currently I am trying to utilize CASL for generating permissions based on dynamic data that I am retrieving from a database. In my case I have 3 tables: Posts, Relationships, and Users. One of the core issues that I'm struggling to figure out how to implement is making a post viewable given a privacy setting. In this case, a post can either be public or private. If the post is public anybody can read it, but if private, then the current user needs to be friends with the post's author, which requires a read from the Relationships table. I know this is a high level overview, but I was just wondering if there's any insight you'd possibly be able to give as to how I should approach this. Thank you for any feedback and for this amazing library!

nzaouesgi
@nzaouesgi
@bryan-vh i don't think there's many options here. you need to load the current user friends list before creating the ability object since permissions will be based on this list.
Bryan Van Horn
@bryan-vh
@nzaouesgi so i would have to make a db query before being able to check the permission, correct?
nzaouesgi
@nzaouesgi
@bryan-vh well, i guess you already make a query to fetch your user before creating your ability object, you could join/select the friend list data as well (maybe only friend IDs so that you only load what's necessary)
nzaouesgi
@nzaouesgi
it could be very consuming in terms of database querying, i know. what you could try to do is lazy-creating rules for your ability object according to what the user wants to do.
for exemple, if he wants to read only his data, no need to create abilities that concern his friends' data. otherwise, you could lazy load the friend list and assign new rules on the ability object (using ability.update)
i think this could be a way to do it
Forloski
@Forloski
Hello, i'm following CASL NestJS instructions and when i use
 @UseGuards(PoliciesGuard)
  @CheckPolicies((ability: AppAbility) => ability.can(Action.READ, Relationship))
it does not check conditions, what i'm doing wrong?
Bryan Van Horn
@bryan-vh
@nzaouesgi what if i were to create the ability only when needed for the request (i guess lazy loading) and create it specifically for only the access control needed for that endpoint? I feel like this will save resources overall as I won't have to load all of the needed rules every time, only depends on the endpoint being requested