Middlewares
If you plan on writing extra endpoints for oms-events, consider using the middlewares that are present. Currently, those are available:
- authenticateUser
- fetchUserDetails
- fetchSingleEvent
- checkPermissions
authenticateUser
Checks the user token by querying the core for some user data. It will either send back a 400 - Forbidden or add basic user data to req.user.basic.
"basic": { "id": 1, "internal_email": "No internal email assigned!", "contact_email": "flaviu@glitch.ro", "first_name": "Flaviu", "last_name": "Porutiu", "date_of_birth": "1994-01-24 00:00:00", "gender": 1, "antenna_id": 1, "university": "UBB Cluj", "studies_type_id": 1, "studies_field_id": 1, "phone": null, "address": null, "city": "Cluj", "zipcode": null, "other": null, "is_superadmin": 1, "is_suspended": null, "department_id": null, "created_at": "2017-03-15 10:59:28", "updated_at": "2017-03-15 10:59:28", "activated_at": "2017-03-15 10:59:28", "suspended_reason": null, "seo_url": "glitch", "email_hash": null, "antenna": "Global antenna", "antenna_name": "Global antenna" }
fetchUserDetails
Gets additional information about the user. It uses the core api/getUserProfile request, as that is the one providing the most information. It outfits the req.user with those fields:
"details": { "id": 1, "fullname": "Flaviu Porutiu", "antenna": "Global antenna", "antenna_city": "Cluj-Napoca", "country": "Afghanistan", "department": "-", "date_of_birth": "1994-01-24", "gender": "Male", "university": "UBB Cluj", "studies": "Agriculture (Bachelor)", "city": "Cluj", "bio": "No bio available", "rank": "Super Admin", "email": "flaviu@glitch.ro", "activated_at": "2017-03-15", "status": "Active", "suspended_for": null, "is_boardmember": 1 } "workingGroups": [], "board_positions": [], "roles": [], "fees_paid": []
In addition it adds user-constant special roles. See checkPermissions for a small explanation of the permission management in oms-events
"special": [ "Public", "Superadmin" ]
fetchSingleEvent
Returns a single event based on the id or url in the endpoint parameters (/api/single/:event_id). You can pass either the id or the url and the service will try to find the event based on both database fields and add it to req.event. Bear in mind that it will return it as a mongoose object, if you want to tinker around with the object, use .toObject() first. Also userdata will not be complete after this stage. If you need more information about the users, have a look at populateUsers in users.js and how it is used in the event.js - eventDetails handler.
{ "success": true, "data": { "_id": "58da349b45e3a800140c4000", "url": "58da349b45e3a800140c4000", "updatedAt": "2017-03-28T10:02:03.486Z", "createdAt": "2017-03-28T10:02:03.486Z", "lifecycle": "58da348645e3a800140c3fff", "status": { "_id": "58da348645e3a800140c3ffd", "__v": 0, "name": "Default name 1", "visibility": { "special": [ "Public" ], "bodies": [], "roles": [], "users": [] } }, "name": "asdasd", "starts": "2017-03-28T22:10:00.000Z", "ends": "2017-04-08T12:10:00.000Z", "__v": 0, "organizers": [ { "foreign_id": "1", "_id": "58da349b45e3a800140c4001", "roles": [ { "_id": "58bfac6e0223b6002b88266c", "cfg_id": "6", "name": "Creator", "description": "The user who created the event, automatically assigned", "__v": 0 } ], "data": { "first_name": "Flaviu", "last_name": "Porutiu", "antenna_name": "Global antenna" } } ], "application_fields": [], "application_status": "closed", "max_participants": 0, "type": "Default event type", "organizing_locals": [ { "name": "Global antenna", "foreign_id": "1", "_id": "58da349b45e3a800140c4002" } ], "description": "asdas", "head_image": { "url": "" }, "id": "58da349b45e3a800140c4000" } }
checkPermissions
This one is actually the most interesting one, and I will add a small explanation of the whole permission system with it. But at first, what this request adds is req.user.permissions:
"permissions": { "is": { "superadmin": true, "boardmember": false, "organizer": true, "participant": false, "accepted_participant": false, "own_antenna": true }, "can": { "view_local_involved_events": true, "edit_organizers": true, "edit_details": true, "delete": true, "edit_application_status": true, "approve": true, "edit": true, "apply": false, "approve_participants": true, "view_applications": true } }
This is all the permission logic we have, and it is split in "is" and "can". In your own handler you should never do any permission checks other than if(req.user.permissions.can.<something>). If you need more complicated logic, please consider extending the checkPermissions middleware. Those permissions are also sent to the frontend, so it can adapt and change the layout. To intruduce this middleware has the idea of keeping it all in one place and being able to update frontend and backend at the same time, when a permission logic changes.
If you are actually at the point of wanting to do that, a short thing about the permission objects. In the microservice admin in the frontend, you can edit permissions based on roles, users, bodies and special roles. The first three are fetched from the core backend, but the last one is added dynamically in the fetchUserDetails and fetchSingleEvent middlewares, it looks like this:
"special": [ "Public", "Superadmin", "Organizing Local Member", "Creator" ]
Those special roles consist of hardcoded roles (see config/pseudo.json) and dynamically added roles based on the role of the user in the event (see config/eventroles.json). You can use these to dynamically determine "is" states that are not included in the above listing.