question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature request: Promises in ability conditions

See original GitHub issue

Abilities allow using functions in the conditions of abilities, such as:

can('update', 'Post', { userId: function(id) { return id === 5 } });

Would it be possible to extend this API to also support promises? This would be handy for cases like querying databases, which return a promise.

Test example:

class Post {
    constructor(props) {
        Object.assign(this, props)
    }
}
function standardUser()
{
    return AbilityBuilder.define(
        (can, cannot) =>
        {
            can('update', 'Post', { userId: Promise.resolve(true) });
        }
    );
}

const abilities = standardUser();

console.log(abilities.can('update', new Post({userId: 5})));

Right now this evaluates to false because it doesn’t recognize promises.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
RedShift1commented, Feb 19, 2019

Let’s say you have users and devices, and users have access to one or more devices. The relationship between users and their devices is stored in a table in a database. You have some data about those devices stored in Redis and want to protect this function:

function doRead(data) // data is user input
{
    return redis.get(`somekey:${data.device}`);
}

It would work as follows (pseudo code):

const ability = AbilityBuilder.define(
    (can, cannot) =>
    {
        can('read', 'SomekeyRequest',
            {
                device: function(device) // Function that returns a Promise
                    {
                        return db.query(`SELECT COUNT(*) AS cnt FROM userDevices WHERE deviceId = ${device}`)
                            .then(resultSet => resultSet.cnt > 0);
                    }
            }
        );
    }
);
function doRead(data)
{
    return ability.can('read', data)
        .then(
            (authz) =>
            {
                if(!authz)
                    throw 'Unauthorized';
                else
                    return redis.get(`somekey:${data.device}`);
            }
        );
}
3reactions
JaneJeoncommented, Oct 28, 2019

I would REALLY like to see this idea dropped.

For reference, I built https://github.com/JaneJeon/objection-authorize which is built on top of a competing access control library, https://github.com/tensult/role-acl.

The developer of role-acl suddenly one day “added” the ability to have an async function in conditions, and that meant literally every method had to be changed to async.

And that broke everything needlessly. And that’s actually the main reason why I’m looking to migrate my library to using casl instead.

I feel that you SHOULDN’T have async conditions to “query the database”. If you need something async, you should put it OUTSIDE the actual ability condition checks - provide all of the information necessary to make a decision to the ability builder in forms of context objects. In addition, you almost always want the frontend to share the same ability class that’s used in the backend so you can limit the UI based on the ACL, but if you’re “querying the database” from the frontend, you’re literally BEGGING to be hacked.

You don’t need async conditions, so the benefits are nil to begin with, and if you do “add” this “feature”, it will break everyone’s code. BAD IDEA.

@stainly I hope to dear god that you don’t consider this. It’s far more changes than you’d think for basically no benefit.

Read more comments on GitHub >

github_iconTop Results From Across the Web

10 Tips for Responding Graciously to Customer Feature ...
10 Tips for Responding Graciously to Customer Feature Requests · 1. Be open and honest · 2. Be grateful for their effort ·...
Read more >
Promise - JavaScript - MDN Web Docs
The termination condition of a promise determines the "settled" state of the next promise in the chain. A "fulfilled" state indicates a ...
Read more >
How to Handle Feature Requests - Tips and Scripts from 5 ...
It's best to over-deliver (or surprise them) rather than promise a specific date and fail to meet it, which is why a more...
Read more >
JavaScript Promise Tutorial: Resolve, Reject, and Chaining in ...
Creating and Using A Promise Step by Step​​ Firstly, we use a constructor to create a Promise object: const myPromise = new Promise();...
Read more >
Asynchronous JavaScript: Advanced Promises with Node.js
Learn how to use advanced features of JavaScript Promises using Node.js with this ... or rejected because of an error or other condition....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found