====== Desired API calls for Workplace Fabric ====== ===== User registration ===== ==== Request ==== API call POST https://apiserver/freespace/users Body { "name": "Melania Carmella", "email": "m.carmella@ramseytech.co.uk" } ==== What the server does between request and response ==== - Check that m.carmella@ramseytech.co.uk is not already registered. If so, the workflow stops and there is a 409 response (see desired responses below). - Create a record for Melania Carmella. Also generate a primary key (user ID) and confirmation token for her. This token is preferably a UUID. The token is saved against the record. - Using the token a hyperlink is created. See the next API User confirmation for what the URL of this hyperlink is. - This hyperlink is mailed to Melania as part of her confirmation email. - The server returns 201 response for the request. - If at any stage, there are exceptions/errors, a 500 response is returned. ==== Response on success ==== Headers HTTP/1.1 201 USER-CREATED Body: None ==== Response if user already exists ==== Headers HTTP/1.1 409 USER-EXISTS Body: None ==== Response for other errors (e.g. exceptions, connection failures, etc) ==== Headers HTTP/1.1 500 ERROR Content-Type: text/plain Body This is an example error message ===== User confirmation ===== This particular URL is not an API call done via AJAX, but it appears inside the body of the confirmation email after he registers. Naturally, clicking on the link inside the email will trigger this script to execute. ==== Request ==== URL https://apiserver/freeserver/actions/confirm?token=token-generated-for-melania's-confirmation ==== What the server does between request and response ==== - The token field in the querystring is checked against Melania's database record. - If the token is invalid, then a 307 response is returned as described. This takes Melania's browser to page that says that her token is invalid (invalid-token.html). - For a valid token, this token is discarded immediately and a new token, called the provisional token, is generated so that Melania can set her password. - The provisional token and Melania's primary key (user ID) are appended to the URL where Melania should be redirected for setting her password (set-password.html) - A 302 response is sent so that Melania can set her password. - An exception or other unexpected errors lead to a 500 response and should redirect the browser to a sorry page (unexpected-error.html) ==== Response for a valid confirmation token ==== Headers HTTP/1.1 302 VALID-TOKEN Location: https://apiserver/freeserver/set-password.html?userid=primary-key-for-melania&token=a-uuid-provisional-token-to-set-password Body: None ==== Response for an invalid confirmation token ==== Headers HTTP/1.1 307 INVALID-TOKEN Location: https://apiserver/freespace/invalid-confirmation-token.html Body: None ==== Response for other errors (e.g. exceptions) ==== Headers HTTP/1.1 500 ERROR Location: https://apiserver/freespace/unexpected-error.html ===== Set password ===== ==== Request ==== API call PATCH https://apiserver/freespace/users/melania's-user-id Headers Content-Type: application/json Authorization: Bearer provisional-token-for-melania Body { password: melania's-new-password } ==== What the server does between request and response ==== - First, the server checks if the user ID passed in the URL is in the database. If no such user ID exists, a 404 error is returned. - Next, once the server finds that the ID belongs to Melania, it extracts the passed provisional token which is part of Authorization header in the request. - If the passed token does not match the one in the database, then a 401 response is returned. - If the tokens match, then a 200 response is returned. - For any exceptions along the way, a 500 response is returned. ==== Response if the password was set successfully ==== Headers HTTP/1.1 204 DONE Body: None ==== Response if the user ID is non-existent ==== Headers HTTP/1.1 404 USER-NOT-FOUND Body: None ==== Response if the provisional token is invalid ==== Headers HTTP/1.1 401 INVALID-TOKEN Body: None ==== Response if there was an exception / error along the way ==== Headers HTTP/1.1 500 ERROR Content-Type: text/plain Body This is a sample error message ===== Login ===== ==== Request ==== API call POST https://apiserver/freespace/oauth/token Headers Content-Type: application/json Authorization: Basic meliania's-username-and-password-in-base64 Please note that in //Basic// authorization mechanism, the username and password are appended with a colon (:) in between. This string is then converted to Base64 encoding. For instance, let's assume that Melania's password is m3l@n1@.\\ First, we'd form a string combining the username, colon and password, i.e. m.carmella@ramseytech.co.uk:m3l@n1@\\ This string is then converted into Base64, which would be bS5jYXJtZWxsYUByYW1zZXl0ZWNoLmNvLnVrOm0zbEBuMUA=. This strange-looking string is what is sent in the Authorization header after the world //Basic//. Body { "grant_type": "client_credentials", "scope": "all:all" } ==== What the server does between request and response ==== - The server checks if the email address is among the list of users registered. If not so, then a 404 is sent. - Next, the server checks if the password entered by the user matches the one in the database. If not so, then a 401 is returned. - If the credentials match, then the server generates a UUID-based token. This token is returned to the client. This token identifies the user in all further communication. - The token request and exchange follow the OAuth 2.0 protocol, using the [[https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/|client credentials]] method. ==== Response for a successful login ==== Headers HTTP/1.1 200 OK Content-Type: application/json Body { "access_token": "access-token-for-melania", "token_type": "bearer", "scope": "all:all" } ==== Response for an invalid username ==== HTTP/1.1 404 USER-NOT-FOUND Body: None ==== Response for an invalid password ==== HTTP/1.1 401 INVALID-PASSWORD Body: None ===== Reset password ===== ==== Request ==== API call https://apiserver/freespace/recovery-requests Headers Content-Type: application/json Body { "email": "m.carmella@ramseytech.co.uk" } ==== What the server does between request and response ==== - The server checks if the email address, for which the password is being reset, exists. If not so, then a 404 is returned. - The server generates a provisional token using which the user can reset the password. - A recovery URL is sent to the user. This URL embeds the token. The recovery endpoint is the same as the confirmation URL sent during registration. - Further workflow is the same as the //User confirmation// workflow. ==== Response if the request is successful ==== Headers HTTP/1.1 204 DONE Body: None There is no body in the response, but an email is sent with the recovery URL. ==== Response if the email address does not exist ==== Headers HTTP/1.1 404 USER-NOT-FOUND Body: None ==== Other errors / exceptions ==== Headers HTTP/1.1 500 ERROR Content-Type: text/plain Body This is a sample error message. ===== Get profile ===== ==== Request ==== API call GET https://apiserver/freespace/users/me Headers Authorization: Bearer access-token-of-the-user Body: none ==== What the server does between request and response ==== - The server examines the token. If no token is passed, then a 401 is returned. - The server fetches the profile from the database based on the user ID. - The server returns the profile along with a 200. - If any errors / exceptions occur, then 500 is returned. ==== Response if request is successful ==== Headers Content-Type: application/json Body { "id": "melania's-uuid-user-id" "name": "Melania Carmella", "email": "m.carmella@ramseytech.co.uk", "phone": "+44 20 7946 0292", "city": { "id": "uuid-based-city-id-for-london", "name": "London" }, "preferredBuilding": { "id": "uuid-based-building-id-for-high-holborn", "name": "High Holborn" }, "preferredFloor": { "id": "uuid-based-floor-id-for-first-floor-of-high-holborn", "name": "1st" }, "preferredDepartment": { "id": "uuid-based-dept-id-for-r&d-1st-floor-high-holborn", "name": "Research and Development" } } ==== Response if token is missing or invalid ==== Headers HTTP/1.1 401 INVALID-TOKEN Body: none ==== Response if some other error / exception occurs ==== Headers HTTP/1.1 500 ERROR Content-Type: text/plain Body This is a sample error message. ===== Get space hierarchy ===== ==== Request ==== API call GET https://apiserver/freespace/cities//spaces Headers Authorization: Bearer access-token-for-the-user ==== What the server does between request and response ==== - The server checks for the validity of the access token. If the token is not found in the server's records, then a 401 is returned. - The server checks if the city ID exists in the server's records. If not so, then a 404 is returned. - The server checks for buildings in the city. If none exist, a 204 is returned. - The server fetches the buildings, floors, departments and space availability in each floor. All the data is combined into a hierarchy and returned along with a 200 response. - If there are errors at any stage, a 500 is returned. ==== Response if the request is successful ==== Headers HTTP/1.1 200 OK Content-Type: application/json Body: [ { "id": "uuid-of-the-building", "name": "Willis Towers", "address": "22, Lewis Street, London", "floors": [ { "id": "uuid-of-the-floor", "name": "1st", "spaces": [ { "id": "uuid-of-the-space", "name": "Task desk", "available": 32 }, ... more spaces.. ] }, ... more floors ... ] }, ... more buildings ... ] ==== Response if the token is invalid ==== Header HTTP/1.1 401 INVALID-TOKEN Body: none ==== Response if the city ID does not exist ==== Header HTTP/1.1 404 CITY-NOT-FOUND Body: none ==== Response if there are no buildings in the city ==== Header HTTP/1.1 204 NONE Body: none ==== Response for other errors / exceptions ==== Header HTTP/1.1 500 ERROR Content-Type: text/plain Body This is a sample error message. ===== Get floor map ===== ==== Request ==== API call GET https://apiserver/freespace/buildings/uuid-for-building/floors/uuid-for-floor/floor-map Headers Authorization: Bearer access-token-of-user ==== What the server does between request and response ==== - The server checks if the access token is that of a valid user. If not so, a 401 is returned. - The server then fetches the floor based on building ID and floor ID. If not found, a 404 is returned. - The server fetches the following from the database - The image of the floor's schematic - List of departments and their central co-ordinate - List of working spaces: their type, X co-ordinate and Y co-ordinate - The above is returned with a 200 status. - If there is an error at any point, a 500 is returned. ==== Response if the request is successful ==== Headers HTTP/1.1 200 OK Content-Type: application/json Body { "id": "uuid-of-the-floor", "schematic": "https://path/to/schematic/diagram/image.png-or-jpg", "departments": [ { "id": "uuid-of-the-department", "name": "Information Technology", "x": X co-ordinate of the centre of the department, "y": Y co-ordinate of the centre of the department, }, ... more departments ... ], "spaces": [ { "id": "uuid-of-the-individual-space", "categoryId": "uuid-of-the-space-category", "x": X co-ordinate of the workspace, "y": Y co-ordinate of the workspace, } ... more spaces ... ] } ==== Response if access token is invalid ==== Headers HTTP/1.1 401 INVALID-TOKEN Body: none ==== Response if building is not found ==== Headers HTTP/1.1 404 BUILDING-NOT-FOUND Body: none ==== Response if floor is not found ==== Headers HTTP/1.1 404 FLOOR-NOT-FOUND Body: none ==== Response for any other error / exception ==== Headers HTTP/1.1 500 ERROR Content-Type: text/plain Body This is a sample error message. ===== Update user profile ===== ==== Request ==== API call PATCH https://apiserver/freespace/users/me Headers Authorization: Bearer Content-Type: application/json Body { "phone": "phone-number", "city": "city-uuid-of-executive's-city", "preferredBuildingId": "uuid-of-preferred-building", "preferredFloor": "uuid-of-preferredFloor", "preferredDepartment": "uuid-of-preferred-department" } ==== What the server does between request and response ==== - The server checks if the access token is valid for the requesting user. If it's not, then 401 is returned. - A 404 is returned if any of the requested city, building, floor or department are not found. - Next, the server updates the changes in profile in the record in database. A 204 is returned. - If there are errors / exceptions on the way, 500 is returned. ==== Response if the updation is successful ==== Headers HTTP/1.1 204 DONE Body: none ==== Response if access token is invalid ==== Headers HTTP/1.1 401 INVALID-TOKEN Body: none ==== Response if city / building / floor / department does not exist ==== Headers HTTP/1.1 404 CITY-NOT-FOUND or HTTP/1.1 404 BUILDING-NOT-FOUND or HTTP/1.1 404 FLOOR-NOT-FOUND or HTTP/1.1 404 DEPARTMENT-NOT-FOUND Body: none ==== Response for some other error / exception ==== Headers HTTP/1.1 500 ERROR Body This is a sample error message. ===== Log out ===== ==== Request ==== API call POST https://apiserver/freespace/oauth/revoke Headers Authorization: Bearer access-token-for-melania Body: none ==== What the server does between request and response ==== The server looks up the bearer token in the database and deletes it, so that the token is invalid from the next time and the user is always redirected to the login page. The response always leads to a 204 response. ==== Response ==== Headers HTTP/1.1 204 DONE ===== Live occupancy update ===== ==== Connection ==== URL ws://apiserver:8000/live-occupancy ==== Client to server data stream ==== None ==== Server to client data stream ==== { "spaceId": "uuid-of-the-room/space-that-is-occupied-or-released", "departmentId": "uuid-of-the-department-where-the-space-is", "floorId": "uuid-of-the-floor-where-the-space-is", "buildingId": "uuid-of-the-building-where-the-space-is", "isOccupied": true if occupied, false if release }