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.

Expose List GET API creation

See original GitHub issue

I want to make the logic used to create the new GET List endpoint (#1544) available to be used in custom routes, similar to the way getUpdateHandler works.

For security, we’d need the ability to white or blacklist fields, and the fields should be used not just for generating JSON but also limit search / filtering functionality as well (so that nobody can query your data on fields they shouldn’t be able to).

I haven’t finalised the API for it yet, suggestions are welcome. I’ll write up the final API here when I’m about to start coding it. If anyone else wants to take this on, please let me know.

It would look something like this:

List.getAPI(type, options)

Type is for use later, so we can add more endpoint types:

  • list returns items
  • get returns a single item by ID
  • update updates a single item by ID
  • delete deletes a single item by ID

Example:

List.getAPI('list', {
    fields: 'name, email', // only name and email fields are available
    excludeFields: 'password', // alternatively, include all fields except password
    filters: 'name, email', // available fields to filter, defaults to the fields option
    excludeFilters: 'password', // as above, allow filtering on all fields except password
    filterValues: { isAdmin: false }, // always includes these filters
    defaultLimit: 500, // alternatively, overrides default limit of 100
    limit: 50, // sets limit to this value (otherwise can be specified in query)
    defaultSort: 'name', // overrides List defaultSort
    sort: 'email' // alternatively, hard-code the sort path
});

Returns a function that can be bound to an Express route:

function (req, res, next) {
   // similar to admin/api/list/get.js
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:12 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
celiaocommented, Oct 9, 2015

For Level 0, exposeAPI() would be more clear.

On Fri, Oct 9, 2015 at 12:23 AM, creynders notifications@github.com wrote:

So, after some input from other people I’m now leaning towards this API:

Level 0

  • expose: starts of route configuration, for a specific collection. I like it better than createAPI, since it communicates better what you’re doing. Maybe it should be exposeAPI?

Level 1

see above

Level 2

  • pre and post as above

    new: query, accepts a function with mquery, req, res signature.

    Article.expose() .retrieve() .query(function(mquery, req, res){ mquery.populate(‘author’, name); return mquery; });

    With mquery being the mongoose query relevant to the method (in this case retrieve, e.g. Article.findById(articleId)) This allows you to leverage mongoose’s powerful and versatile query language.

    Some food for thought: In all you can declare stuff that needs to be applied to all methods (except when overridden) exposing the mongoose query will make this pretty hard, since the mongoose query system has an incremental API, with no means to decrement. E.g. if you declare a populate: ‘author’ in all you can’t unpopulate this in a specific method. I think?

  • sort, filter and populate become wrappers to the mongoose query methods.

  • Not too fond about show the more I think of it. Need to come up with something better.

In general:

all methods accept functions as input, which will be called at the appropriate time to configure the query, e.g.

Article.expose() .retrieve(function(user){ var fields = ‘name author’; user.isAdmin && fields += ’ email’; return fields; });

If you prefer to use a configuration object instead of the fluent API, that’s possible too:

Article.expose({ retrieve: { show: ‘name’, populate: [‘author’, ‘name’] }, list: { sort: ‘-createdAt’, query: function(mquery, req, res){ if(!req.user.isAdmin){ mquery = mquery.where({state: ‘published’}); } return mquery; } } });

Some more food for thought: error handling and data massaging. Maybe it’s a good idea to allow the use of a promise-like API to handle both e.g.:

Article.expose() .retrieve(‘name’) .populate(‘createdBy’) .then(function(user, req, res){ user.author = user.createdBy; delete user.createdBy; return user; }) .catch(function(err, req, res){ // a bit convoluted, I know if(res.locals.status===403){ res.locals.status=404; res.locals.body=‘Not found’; } return err; });

— Reply to this email directly or view it on GitHub https://github.com/keystonejs/keystone/issues/1585#issuecomment-146777390 .

1reaction
creynderscommented, Oct 9, 2015

So, after some input from other people I’m now leaning towards this API:

Level 0

  • expose: starts of route configuration, for a specific collection. I like it better than createAPI, since it communicates better what you’re doing. Maybe it should be exposeAPI?

Level 1

see above

Level 2

  • pre and post as above

  • new: query, accepts a function with mquery, req, res signature.

    Article.expose()
        .retrieve()
            .query(function(mquery, req, res){
                mquery.populate('author', name);
                return mquery;
            });
    

    With mquery being the mongoose query relevant to the method (in this case retrieve, e.g. Article.findById(articleId)) This allows you to leverage mongoose’s powerful and versatile query language.

    Some food for thought: In all you can declare stuff that needs to be applied to all methods (except when overridden) exposing the mongoose query will make this pretty hard, since the mongoose query system has an incremental API, with no means to decrement. E.g. if you declare a populate: 'author' in all you can’t unpopulate this in a specific method. I think?

  • sort, filter and populate become wrappers to the mongoose query methods.

  • Not too fond about show the more I think of it. Need to come up with something better.

In general:

  • all methods accept functions as input, which will be called at the appropriate time to configure the query, e.g.

    Article.expose()
        .retrieve(function(user){
            var fields = 'name author';
            user.isAdmin && fields += ' email';
            return fields;
        });
    
  • If you prefer to use a configuration object instead of the fluent API, that’s possible too:

    Article.expose({
        retrieve: {
            show: 'name',
            populate: ['author', 'name']
        },
        list: {
            sort: '-createdAt',
            query: function(mquery, req, res){
                if(!req.user.isAdmin){
                    mquery = mquery.where({state: 'published'});
                }
                return mquery;
            }
        }
    });
    
  • Some more food for thought: error handling and data massaging. Maybe it’s a good idea to allow the use of a promise-like API to handle both e.g.:

    Article.expose()
        .retrieve('name')
        .populate('createdBy')
        .then(function(user, req, res){
            user.author = user.createdBy;
            delete user.createdBy;
            return user;
        })
        .catch(function(err, req, res){
            // a bit convoluted, I know
            if(res.locals.status===403){
                res.locals.status=404;
                res.locals.body='Not found';
            }
            return err;
        });
    
Read more comments on GitHub >

github_iconTop Results From Across the Web

Expose a REST API - OutSystems 11 Documentation
Create the REST API Method · Right-click your REST API and choose Add REST API Method. · Set the name of your REST...
Read more >
Expose Your Application With a REST API - RapidAPI
This tutorial is a concise introduction to exposing an application's API using REST It is programming language agnostic and focuses on the ...
Read more >
How to Create an API in Three Steps - Stoplight Blog
The first step in creating an API is designing the API. ... To retrieve a list of people, you could use the GET...
Read more >
Expose a REST API in 10 minutes with OutSystems - YouTube
In this episode, OutSystems Developer Advocate Cristiana Umbelino shows us how you can quickly implement a REST API to offer to your ...
Read more >
How-to Create a Rest API - Part 3: Add a GET Method - YouTube
... to expose the REST API to consumers, specifically the GET method. ... video we'll go through creating a GET method that returns...
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