Implementing Permissions for Orders API in Open Event API Server

Open Event API Server Orders API is one of the core APIs. The permissions in Orders API are robust and secure enough to ensure no leak on payment and ticketing.The permission manager provides the permissions framework to implement the permissions and proper access controls based on the dev handbook. The following table is the permissions in the developer handbook.   List View Create Update Delete Superadmin/admin ✓ ✓ ✓ ✓ ✓ Event organizer ✓ [1] ✓ [1] ✓ [1] ✓ [1][2] ✓ [1][3] Registered user ✓ [4] Everyone else Only self-owned events Can only change order status A refund will also be initiated if paid ticket Only if order placed by self Super Admins and admins are allowed to create any order with any amount but any coupon they apply is not consumed on creating order. They can update almost every field of the order and can provide any custom status to the order. Permissions are applied with the help of Permission Manager which takes care the authorization roles. For example, if a permission is set based on admin access then it is automatically set for super admin as well i.e., to the people with higher rank. Self-owned events This allows the event admins, Organizer and Co-Organizer to manage the orders of the event they own. This allows then to view all orders and create orders with or without discount coupon with any custom price and update status of orders. Event admins can provide specific status while others cannot if not has_access('is_coorganizer', event_id=data['event']): data['status'] = 'pending' And Listing requires Co-Organizer access elif not has_access('is_coorganizer', event_id=kwargs['event_id']): raise ForbiddenException({'source': ''}, "Co-Organizer Access Required") Can only change order status The organizer cannot change the order fields except the status of the order. Only Server Admin and Super Admins are allowed to update any field of the order. if not has_access('is_admin'): for element in data: if element != 'status': setattr(data, element, getattr(order, element)) And Delete access is prohibited to event admins thus only Server admins can delete orders by providing a cancelling note which will be provided to the Attendee/Buyer. def before_delete_object(self, order, view_kwargs): if not has_access('is_coorganizer', event_id=order.event.id): raise ForbiddenException({'source': ''}, 'Access Forbidden') Registered User A registered user can create order with basic details like the attendees' records and payment method with fields like country and city. They are not allowed to provide any custom status to the order they are creating. All orders will be set by default to “pending” Also, they are not allowed to update any field in their order. Any status update will be done internally thus maintaining the security of Order System. Although they are allowed to view their place orders. This is done by comparing their logged in user id with the user id of the purchaser. if not has_access('is_coorganizer_or_user_itself', event_id=order.event_id, user_id=order.user_id): return ForbiddenException({'source': ''}, 'Access Forbidden') Event Admins The event admins have one more restriction, as an event admin, you cannot provide discount coupon and even if you do it will be ignored. # Apply discount only…

Continue ReadingImplementing Permissions for Orders API in Open Event API Server

Managing Related Endpoints in Permission Manager of Open Event API Server

Open Event API Server has its permission manager to manage all permission to different endpoints and some of the left gaps were filled by new helper method has_access. The next challenge for permission manager was to incorporate a feature many related endpoints points to the same resource. Example: /users-events-roles/<int:users_events_role_id>/user or /event-invoices/<int:event_invoice_id>/user Both endpoints point to Users API where they are fetching the record of a single user and for this, we apply the permission “is_user_itself”. This permission ensures that the logged in user is the same user whose record is asked through the API and for this we need the “user_id” as the “id” in the permission function, “is_user_itself” Thus there is need to add the ability in permission manager to fetch this user_id from different models for different endpoints. For example, if we consider above endpoints then we need the ability to get user_id from UsersEventsRole and EventInvoice models and pass it to permission function so that it can use it for the check. Adding support To add support for multiple keys, we have to look for two things. fetch_key_url model These two are key attributes to add this feature, fetch_key_url will take the comma separated list which will be matched with view_kwargs and model receives the array of the Model Classes which will be used to fetch the related records from the model This snippet provides the main logic for this: for index, mod in enumerate(model): if is_multiple(fetch_key_url): f_url = fetch_key_url[index] else: f_url = fetch_key_url try: data = mod.query.filter(getattr(mod, fetch_key_model) == view_kwargs[f_url]).one() except NoResultFound, e: pass else: found = True if not found: return NotFoundError({'source': ''}, 'Object not found.').respond() From the above snippet we are: We iterate through the models list Check if fetch_key_url has multiple keys or not Get the key from fetch_key_url on the basis of multiple keys or single key in it. We try to attempt to get object from model for the respective iteration If there is any record/object in the database then it’s our data. Skipping further process Else continue iteration till we get the object or to the end. To use multiple mode Instead of providing the single model to the model option of permission manager, provide an array of models. Also, it is optional to provide comma separated values to fetch_key_url Now there can be scenario where you want to fetch resource from database model using different keys present on your view_kwargs for example, consider these endpoints `/notifications/<notification_id>/event` `/orders/<order_id>/event` Since they point to same resource and if you want to ensure that logged in user is organizer then you can use these two things as: fetch_key_url="notification_id, order_id" model=[Notification, Order] Permission manager will always match indexes in both options, the first key of fetch_key_url will be only used for the first key of the model and so on. Also, fetch_key_url is an optional parameter and even in multiple mode you can provide a single value as well.  But if you provide multiple commas separated values make sure you provide all values such…

Continue ReadingManaging Related Endpoints in Permission Manager of Open Event API Server