Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional context to directives #145

Open
mfrieling opened this issue Aug 6, 2020 · 5 comments
Open

Add optional context to directives #145

mfrieling opened this issue Aug 6, 2020 · 5 comments

Comments

@mfrieling
Copy link

#2 I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[ ] Documentation issue or request

Current behavior

Currently using the ngxPermissionsOnly and ngxPermissionsExcept we can pass one or more permission or role names as string and basically it checks whether the current user has that/one of them or not. The permission/role itself can provide a validator function which is able to perform simple validations like in the roles example checking the session state.

Expected behavior

What in many cases would be helpful is to validate permissions or roles with a given context. For example within a list of objects where each object has actions like view/edit/delete we not only need to check if user X can view/edit/delete objects of that type but for example if he can view/edit/delete that specific object.In my actual use case the action is editing permissions of contacts. But the contact can either be a "simple" data item or connected with an user account which can login or not. So user X editing (assigning) permissions to contact A only makes sense if user X has the permission "edit contact permissions¨ and contact A is able to login.

This could be solved by providing an optional context to the validator function via the directives, pipes and maybe also the routes (the question is how to define what to pass from routing).

Directives:

<ul>
<li *ngFor="let item of items">
<a href="#" *ngxPermissionsOnly="['changeSomething']" [ngxPermissionsContext]="item">
    Visible if user has permission and item fullfils specific criteria
</a>

Pipes:
(example from #124 adapted)

<button [disabled]="'changeSomething' | ngxPermission(something)">Change</button>

Permission/role validator function:

# Current validator functions:
function(): boolean|Promise<boolean>
function(permissionName: string, permissionObject: object): boolean|Promise<boolean>

# New validator functions:
function(context?: any): boolean|Promise<boolean>
function(context?: any, permissionName: string, permissionObject: object): boolean|Promise<boolean>

# Examples:
this.permissionsService.addPermission('changeSomething', (context) => {
        return typeof context === User && user.canLogin;
    })


this.permissionsService.addPermission('changeSomething', (context, permissionName, permissionsObject) => {
        return !!permissionsObject[permissionName] && typeof context === User && user.canLogin;
    })

Environment


Angular version: 9.1.8
ngx-permissions version: 8.0.0


Browser:
- [x] Chrome (desktop) version 83
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
@paolosanchi
Copy link

paolosanchi commented Aug 11, 2020

I need this too, if anyone is already on it, I'm going with the implementation.

however, probably the best for routing is doing like this:


let routes = [
  { path: '', 
    canActivate: [AuthGuard],
    children: [
      {path: 'component', 
      component: ComponentName, 
      canActivate: [NgxPermissionsGuard],
      data: {
         permissions: {
           only: ['ADMIN', 'MODERATOR'],
           redirectTo: 'another-route'
           context: {
               [...things...]
           }
         }
       }}
    ]
  }
]

@paolosanchi
Copy link

As I expected the issue is that the validation function is defined as this:

export declare type ValidationFn = ((name?: string, store?: any) => Promise<void | string | boolean> | boolean | string[]);

it means that if we set the context as the first parameter it would break every compatibility, unless we do something like this:

export declare type ValidationFn = ((name?: string | object, store?: any) => Promise<void | string | boolean> | boolean | string[]);

and the validation caller would pass the context instead of the name when specified, but this behaviour could result confusing.

the easiest way would be obviously this:

export declare type ValidationFn = ((name?: string, store?: any, context: object) => Promise<void | string | boolean> | boolean | string[]);

Any other ideas?

@paolosanchi
Copy link

I made the changes to do this, and it was almost easy, you can check it out here (I'll provide some examples soon):
https://github.com/paolosanchi/ngx-permissions/tree/addContextToValidationFunction

The router part is not completed yet, but I'm almost there.

I've an issue with the build, @AlexKhymenko what is the command to run? When I import the dist folder to my test project I got errors,
Angular core has no exported member ɵɵFactoryDef
or
No provider for ViewContainerRef (or something similar, I don't remember)

@GasyTek
Copy link

GasyTek commented Feb 10, 2021

Need this feature too, @paolosanchi have you managed to make it work ?

@paolosanchi
Copy link

paolosanchi commented Feb 26, 2021

I'm sorry, but I moved to https://github.com/stalniy/casl and I'm sticking with it. It has this feature and many more.
I can't remember where I got with this issue. You can check the changes I made at the time, anyway:
#146

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants