Understanding Permissions for Various APIs in Open Event API Server
Since the Open Event Server has various elements, a proper permissions system is essential. This huge list of permissions is well compiled in the developer handbook which can be found here. In this blogpost, permissions listed in the developer handbook are discussed. Let’s start with what we wish to achieve, that is, how to make sense of these permissions and where does each clause fit in the API Server’s codebase.
For example, Sponsors API has the following permissions.
List |
View |
Create |
Update |
Delete |
|
Superadmin/admin |
✓ |
✓ |
✓ |
✓ |
✓ |
Event organizer |
✓ [1] |
✓ [1] |
✓ [1] |
✓ [1] |
✓ [1] |
Registered User |
✓ [3] |
✓ [3] |
✓ [4] |
✓ [3] |
✓ [3] |
Everyone else |
✓ [2][4] |
✓ [2][4] |
- Only self-owned events
- Only sessions with state approved or accepted
- Only self-submitted sessions
- Only to events with state published.
Based on flask-rest-jsonapi resource manager, we get list create under ResourceList through ResourceList’s GET and POST methods, whereas View, Update, Delete work on single objects and hence are provided by ResourceDetail’s GET, PATCH and DELETE respectively. Each function of the permission manager has a jwt_required decorator.
@jwt_required def is_super_admin(view, view_args, view_kwargs, *args, **kwargs): @jwt_required def is_session_self_submitted(view, view_args, view_kwargs, *args, **kwargs):
This ensures that whenever a check for access control is made to the permission manager, the user is signed in to Open Event. Additionally, the permissions are written in a hierarchical way such that for every permission, first the useris checked for admin or super admin, then for other accesses. Similar hierarchy is kept for organizer accesses like track organizer, registrar, staff or organizer and co–organizer.
Some APIs resources require no authentication for List. To do this we need to add a check for Authentication token in the headers. Since each of the functions of permission manager have jwt_required as decorator, it is important to checkfor the presence of JWT token in request headers, because we can proceed to check for specific permissions in that case only.
if 'Authorization' in request.headers: _jwt_required(current_app.config['JWT_DEFAULT_REALM'])
Since the resources are created by endpoints of the form : ‘/v1/<resource>/` , this is derived from the separate ResourceListPost class. This class is POST only and has a before_create object method where the required relationships and permissions are checked before inserting the data in the tables. In the before_create method, let’s say that event is a required relationship, which will be defined by the ResourceRelationRequired , then we use our custom method
def require_relationship(resource_list, data): for resource in resource_list: if resource not in data: raise UnprocessableEntity({'pointer': '/data/relationships/{}'.format(resource)}, "A valid relationship with {} resource is required".format(resource))
to check if the required relationships are present in the data. The event_id here can also be used to check for organizer or co-organizer access in the permissions manager for a particular event.
Here’s another permissions structure for a different API – Settings.
List |
View |
Create |
Update |
Delete |
|
Superadmin/admin |
✓ |
✓ |
|||
Everyone else |
✓ [1] |
- Only app_name, tagline, analytics_key, stripe_publishable_key, google_url, github_url, twitter_url, support_url, facebook_url, youtube_url, android_app_url, web_app_url fields .
This API does not allow access to the complete object, but to only some fields which are listed above. The complete details can be checked here.
Resources