REST Framework Ideas


#1

The Preside REST framework implementation as of now is already really useful. But there are several things that could be added that would make developing APIs within Preside even more powerful.
There are currently 4 open tickets in Jira regarding possible improvements and new features.

https://presidecms.atlassian.net/browse/PRESIDECMS-421 (swagger integration)
https://presidecms.atlassian.net/browse/PRESIDECMS-462 (multilingual requests)
https://presidecms.atlassian.net/browse/PRESIDECMS-463 (security/authentication)
https://presidecms.atlassian.net/browse/PRESIDECMS-464 (scaffolding endpoints)

Please feel free to comment here or on the individual tickets to push this topic forward. Anyone interested in contributing and/or sharing additional ideas is welcome.

Things that have not been covered yet that might be interesting in the future:

  • API monitoring
  • request throttling
  • authorization (specific users/apikeys only allowed for specific endpoints)
  • non-code endpoints (e.g. preside-object itself is annotated as being accessible via REST)
  • system endpoints (e.g. for authentication, system objects like languages, maybe pages, sites, etc.)

If we start scaffolding endpoints we need to come up with some sort of reference implementation. How are validation or other errors reported back to the caller (HTTP response headers, a defined response body format, etc.), which HTTP verb translates to which CRUD action. We should have a common understanding of what we would consider best practice.
A good reading on this topic is Adam Tuttle’s book: http://www.restassuredbook.com

We might also have a look at the implementation of the REST stuff in ACF2016 (how they generate swagger specs, what the API Manager is all about). Anyone played with that already?


#2

Conceptual idea regarding authentication improvements:

Currently the mentioned extension preside-ext-rest-security supports one simple API key authentication. An admin defines one single key in the sys config and that is the only valid one.

To improve this several things can be integrated:

Multiple API keys

  • new preside object rest_api_key
  • ability to give the key a label
  • record last usage and/or count usages
  • possibility to enable/disable a key
  • the api keys could be either managed within the sys config or within the data manager (or both)

Website User Basic Auth

  • Using Basic Auth (ideally over SSL) is a reasonable authentication model for REST APIs
  • if the websiteusers-feature is enabled, basic auth could be enabled for REST via the sys config (yesnoswitch)
  • optionally a specific benefit could be selected in the sys config to restrict access (only users with that specific benefit should have access, others not), if left empty, every active website user has access

Website User API key

  • adding an API key to the website user object
  • obviously only working/valid if the websiteusers-feature is enabled
  • possibility to manage the keys in the admin (not sure if we need a dedicated form for that or just do it in the website user edit form)
  • implementation in the frontend is up to the developer (e.g. having it in a profile page)

I think it makes sense to give developers different options - or a combination of all of the above (if they wish).
The above is implemented fairly easy. We could get more fancy using oauth, etc. but that could come later.

I could go ahead and update the extension’s code. If the stuff gets moved to core later, that would be great.

Does that make sense? Any further ideas?


#3

I implemented a first version of a REST endpoint scaffolding terminal command. For now it is an extension - but could be integrated in the core later:

Try it here: https://www.forgebox.io/view/preside-ext-rest-scaffold

Obviously the whole POST/PATCH/PUT/DELETE part is still missing.

Conceptually I think there are 2 approaches to improve the current concept and extend it with write functionality:

  1. put the whole logic in the endpoints only using built-in services (e.g. PresideObjectService, Validation Framework, etc.)
    This has the advantage of transparency for the developer - easy code customization.
    What is odd is that there is a lot of code redundancy - even more if validation and error handling, etc. is included for write requests.

  2. build something like a RestRequestDataService (or alternatively an abstract rest handler that each endpoint handler extends)
    read/insert/update/delete methods would be called on this one passing in the arguments/parameters of the api call, the object type related args (e.g. which fields to return) as well as the restRequest and restResponse params.
    The service would then do everything (e.g. validation, setting errors in the restResponse, reading/writing data.
    The endpoints themselves would then only be wrapper functions calling a service method and passing in all relevant data.
    This is a clear advantage as there will not be any redundant code (even no try/catch in the endpoints). However it will not be as transparent to the user and furthermore harder to customize or extend.

Any thoughts of in which direction this should go?
Or are there alternatives that combine the best of both worlds? Maybe a custom endpoint-specific service that is scaffolded along with the endpoints which extends an abstract base service (which holds most of the logic) would allow an easier customization.

Feedback is welcome.


#4

I’m not going to get a chance to look at this before PresideCon / CFCamp - but we should catch up about it then :slight_smile: