restful api implementation - tharindu326/PWP GitHub Wiki

Important information for Deadline 3

‼️  This chapter should be completed by Deadline 3 (see course information at Lovelace)


📑  Chapter summary In this section you must implement a RESTful API. The minimum requirements are summarized in the Minimum Requirements section of the Project Work Assignment. If you do not meet the minimum requirements this section WILL NOT be evaluated.

CHAPTER GOALS

  • Implement a RESTful API
  • Write tests for the API

✔️     Chapter evaluation (max 20 points) You can get a maximum of 20 points after completing this section. More detailed evaluation is provided in the evaluation sheet in Lovelace.

RESTful API implementation

List of implemented resources

📑  Content that must be included in the section A list of all resourcess. Each resource should include its URL, a short description and supported methods. You should mark also which is the name of the class implementing the resource (if you have implemented such resource) Consider that you do not need to implement every resource you initially planned.   The minimum requirements are summarized in the Minimum requirements section from the Project work assignment.

✏️ List your resources here. You can use the table below for listing resources. You can also list unimplemented resources if you think they are worth mentioning

Resource Name Resource URL Resource Description Supported Methods Implemented
Register Identity /identities Register a new identity with image, permissions, and name POST Yes
Get Identity Profile /identities/<int:user_id> Retrieve an identity's profile information GET Yes
Update Identity /identities/<int:user_id> Update identity details, permissions, or images PUT Yes
Handle Access Request /identities/access-request Process an access request with image and permissions POST Yes
Get Identities by Name /identities/name/<name:user_name> Retrieve identities by name GET Yes
Identity Deletion /identities/<int:user_id> Delete an identity's profile and associated data DELETE Yes
Access Log Retrieval /identities/<int:user_id>/access-logs Retrieve access logs for a specific identity GET Yes
Retrieve Access Requests /identities/<int:user_id>/requests Retrieve access requests for a specific identity GET Yes
Retrieve Permissions /identities/<int:user_id>/permissions Retrieve permissions for a specific identity GET Yes
Get Access Log /access-log/<int:log_id> Retrieve a specific access log GET Yes
Get Access Logs by Request /access-request/<int:access_request_id> Retrieve access logs for a specific access request GET Yes
Terms of Service /face_pass/tos Render the terms of service page GET Yes
Link Relations /face_pass/link-relations Render the link relations page GET Yes
Profile Page /face_pass/profile Render the profile page GET Yes

Basic implementation

💻     TODO: SOFTWARE TO DELIVER IN THIS SECTION The code repository must contain:
  1. The source code for the RESTful API 
  2. The external libraries that you have used
  3. We recommend to include a set of scripts to setup and run your server
  4. A database file or the necessary files and scripts to automatically populate your database.
  5. A README.md file containing:
    • Dependencies (external libraries)
    • How to setup the framework.
    • How to populate and setup the database.
    • How to setup (e.g. modifying any configuration files) and run your RESTful API.
    • The URL to access your API (usually nameofapplication/api/version/)=> the path to your application.
Do not forget to include in the README.md file which is the path to access to your application remotely.

NOTE: Your code MUST be clearly documented. For each public method/function you must provide: a short description of the method, input parameters, output parameters, exceptions (when the application can fail and how to handle such fail).  In addition should be clear which is the code you have implemented yourself and which is the code that you have borrowed from other sources. Always provide a link to the original source. This includes links to the course material.


✏️ You do not need to write anything in this section, just complete the implementation.


RESTful API testing

💻     TODO: SOFTWARE TO DELIVER IN THIS SECTION The code repository must contain:
  1. The code to test your RESTful API (Functional test)
    • The code of the test MUST be commented indicating what you are going to test in each test case.
    • The test must include values that force error messages
  2. The external libraries that you have used
  3. We recommend to include a set of scripts to execute your tests.
  4. A database file or the necessary files and scripts to automatically populate your database.
  5. A README.md file containing:
    • Dependencies (external libraries)
    • Instructions on how to run the different tests for your application.
Do not forget to include in the README.md the instructions on how to run your tests. Discuss briefly which were the main errors that you detected thanks to the functional testing.

Remember that you MUST implement a functional testing suite. A detailed description of the input / output in the a REST client plugin.

In this section it is your responsibility that your API handles requests correctly. All of the supported methods for each resource should work. You also need to show that invalid requests are properly handled, and that the response codes are correct in each situation.


✏️ Most important part of this section is completing the implementation. Write down here a short reflection on which are the main errors you have solved thanks to the functional tests.

  • Encountered an OSError related to a small paging file size when trying to import torch. This issue involves the failure to load a specific DLL file due to insufficient paging file size. The issues were fixed using following resources:

    PyTorch discussion forum post: WinError 1455: The paging file is too small for this operation to complete

    StackOverflow question: How to efficiently run multiple PyTorch processes/models at once? Functions were used incorrectly in the application.

  • Payload parameters were misinterpreted. For example, permissions was used instead of permission in the payload of the http://127.0.0.1:8080/register endpoint.

  • Error handling was not implemented adequately throughout the application. So have to update the APIs with proper error handeling.

  • Permission validation was lacking, allowing any permission type, defined or undefined, to proceed without indicating the absence of the specified correct permission. A permission validator was introduced to address this issue.

  • When there is a single identity in the system, we cannot use the classifier to train a model. So we have to handle that manually

  • Permissions were not validated as a list, leading to issues in permission handling when non-list values passed in payload.

  • Input parameters were not validated at the outset of the process in the identities/register endpoint. For instance, if an image with an unsupported extension is encountered after partial data updates, an error occurs, but the updates made prior to the error remain in place.

  • The identities/update API did not manage scenarios where no data was submitted for updates (empty payload). It is designed to update existing data with provided information.

  • When the system doesn't locate an existing face embedding file, it automatically regenerates this file without first verifying if there are new faces in the system to generate embeddings for. To address this, a check was implemented to consult the database for the presence of new faces before proceeding with the generation of the embedding file.


REST conformance

📑  Content that must be included in the section Explain briefly how your API meets REST principles. Focus specially in these three principles: Addressability, Uniform interface, Statelessness. Provide examples (e.g. how does each HTTP method work in your API). Note that Connectedness will be addressed in more depth in Deadline 4.

✏️ Our APIs demonstrate adherence to the REST principles, particularly focusing on Addressability, Uniform Interface, and Statelessness. Below are some examples how these principles are embodied in your API with examples:

  1. Addressability Addressability is the principle that every resource should have a unique URI. It ensures resources can be found and interacted with over the network.

Example:

/identities/register for registering a new identity. /identities/int:user_id/profile for retrieving the profile of a specific user. /identities/int:user_id/update for updating user details. /identities/int:user_id/delete for deleting a user. /access-log/int:user_id for retrieving access logs for a specific identity. Each of these endpoints uniquely addresses a resource or a set of resources, making them accessible via specific URIs.

  1. Uniform Interface Uniform Interface is about interacting with resources through a standardized interface, typically HTTP methods (GET, POST, PUT, DELETE, etc.).

Example:

POST /identities/register: Creates a new user. The POST method indicates the creation of a resource. GET /identities/int:user_id/profile: Retrieves a user's profile. The GET method is used for reading resources. PUT /identities/int:user_id/update: Updates user details. The PUT method indicates an update operation on a resource. DELETE /identities/int:user_id/delete: Deletes a user. The DELETE method is used for removing resources. GET /access-log/int:user_id: Retrieves access logs for a user, using GET to read these log resources. These examples illustrate how HTTP methods provide a uniform way to interact with the resources, fulfilling different roles like creation, reading, updating, and deletion.

  1. Statelessness Statelessness is referred as each request from a client to a server must contain all the information the server needs to understand and fulfill the request. The server does not store any session state about the client.

Example: Each API request to your endpoints includes all necessary data within the request itself. For example:

When registering a user with POST /identities/register, the request includes all user details (name, permissions, facial image) and authentication information (API key) needed to process the request. The server does not rely on any previous interaction to understand and complete this request. For GET /identities/int:user_id/profile, the request must include the user ID and the API key for authorization. The server uses only the information provided in the request to retrieve and return the user's profile. This approach ensures that the API does not need to maintain any client session state, adhering to the statelessness principle of RESTful design.

By adhering to these REST principles, these APIs ensure they are scalable, flexible, and easy to integrate with, following best practices for web service design.


Extras

📑  Details on extra features This section lists the additional features that will be graded as part of the API but are not required. In addition to implementing the feature you are also asked to write a short description for each.

URL Converters

📑  Fill this section if you used URL converters Write a short rationale of how URL converters are used, including your thoughts on the possible trade-offs. Go through all URL parameters in your API and describe whether they use a converter, what property is used for converting, or why it's not using a converter.

✏️ **

Endpoint Converter Property for Converting Description
/identities None N/A This endpoint registers a new user by uploading an image and assigning permissions. The endpoint processes form data and file uploads, necessitating manual validation steps within the request processing.
/identities/<int:user_id> int Integer values This endpoint retrieves the profile of an existing user by their ID, ensuring the ID is always an integer, simplifying error handling and data processing.
/identities/<int:user_id> int Integer values This endpoint updates the details of an existing user by their ID, ensuring the ID is always an integer. It processes optional form data and file uploads.
/identities/<int:user_id> int Integer values This endpoint deletes an existing user by their ID, ensuring the ID is always an integer.
/identities/access-request None N/A This endpoint handles an access request by verifying the user identity and permissions. It primarily involves form data and file uploads, requiring manual validation within the request processing.
/identities/name/<name:user_name> NameConverter String format without numbers/special characters, capitalized parts The NameConverter ensures that names in URLs are properly formatted and free from unwanted characters, enhancing data consistency and user experience.
/identities/<int:user_id>/access-logs int Integer values This endpoint retrieves access logs for a specific user by their ID, ensuring the ID is always an integer, which simplifies retrieving and processing access logs associated with the user.
/identities/<int:user_id>/requests int Integer values This endpoint retrieves access requests for a specific user by their ID, ensuring the ID is always an integer, facilitating the retrieval and processing of access requests for the user.
/identities/<int:user_id>/permissions int Integer values This endpoint retrieves permissions for a specific user by their ID, ensuring the ID is always an integer, making it easier to manage and validate permissions associated with the user.
/access-log/<int:log_id> int Integer values This endpoint retrieves a specific access log by its ID, ensuring the log ID is always an integer, simplifying the retrieval and processing of specific access logs.
/access-request/<int:access_request_id> int Integer values This endpoint retrieves access logs for a specific access request by its ID, ensuring the access request ID is always an integer, facilitating the accurate retrieval and processing of specific access requests.

Schema Validation

📑  Fill this section if you used JSON schema validation Write a short description of your JSON schemas, including key decision making for choosing how to validate each field.

✏️ **

1. /identities/register (POST)

  • Fields:
    • name: String, required, must exclude numbers and special characters. Validates user names to maintain consistency.
    • image: File, required, must be of allowed types (png, jpg, jpeg). Ensures that only valid image files are processed for facial recognition.
    • permission: Array of strings, required, must match predefined permission levels. Validates user permissions against a controlled list to enforce security constraints.

2. /identities/<int:user_id>/profile (GET)

  • No JSON body but uses URL parameter user_id validated as an integer. This simplicity avoids the need for JSON validation but ensures the identifier is numeric.

3. /identities/<int:user_id>/update (PUT)

  • No JSON body but uses URL parameter user_id validated as an integer. The function checks for the presence and validity of three key pieces of information: the user's name, their permissions, and an image file. For the name, it validates that the field is a string and does not contain numbers or special characters, formatting it correctly if it passes the check. For permissions, it ensures that the provided list contains valid permission levels as defined in the configuration. For images, it checks that files are provided and that their types are among the allowed formats (png, jpg, jpeg).

4. /identities/access-request (POST)

  • Fields:
    • image: File, required, similar validation as in /identities/register.
    • associated_permission: String, required, must match predefined permission levels. Validates the context of access requests against allowed permissions to ensure authorization integrity.

5. /identities/<name:user_name> (GET)

  • No JSON body; uses URL parameter user_name validated through NameConverter. The converter ensures that the name is appropriately formatted and free from unsupported characters, aligning with the system's naming conventions.

Caching

📑  Fill this section if you implemented server side caching Explain your caching decisions here. Include an explanation for every GET method in your API, explaining what is cached (or why it is not cached), and how long is it cached (and why). If you are using manual cache clearing, also explain when it happens.

✏️ **

Caching User Profiles (get_profile function):

  • User profiles are cached to speed up retrieval.
  • Cached data includes user details like name and permissions.
  • Cache entries are manually cleared using cache.delete() in the update_user function whenever a user's profile is updated, ensuring that subsequent requests pull fresh data.

Caching User Search Results (get_users function):

  • Search results for users by name are cached to avoid repetitive database queries and related processes for similar searches.
  • The cache key is derived from the full request path, allowing for specific caching of different search queries.

Caching has not been applied to other endpoints (such as register_person, handle_access_request, and update_user) because they primarily handle image inputs, which are likely to be unique with each request. This variability renders caching ineffective, as the likelihood of reusing cached data for these operations is minimal.

Cache Configurations:

  • Uses FileSystemCache, which stores cache data in the filesystem (cache_data).
  • By default, cache entries do not expire (CACHE_DEFAULT_TIMEOUT = 0), relying on manual cache management to avoid serving outdated information.

Authentication

📑  Fill this section if you implemented authentication Explain your authentication scheme here. Describe the authentication requirements for each resource in your API, and your reasoning for the decisions. In addition, provide a plan for how API keys will be distributed, even if the distribution is not currently implemented.

✏️ **

The application mainly uses simple, fixed API keys because it's designed also as a microservice and then authentication can be done without the need for session management. So it doesn't use more complex methods like creating tokens each time someone logs in. However, if the system grows (with system Users) or needs more security, we could switch from these fixed keys to creating tokens using JWT. This method gives better control over who gets access and for how long. We could also think about using services like Auth0, which help manage these keys and offer more features, making the whole process easier and safer.

Implementation

Every endpoint in the application requires a valid API key provided in the request headers under 'Authorization'. This ensures a consistent layer of security across all API interactions, preventing unauthorized access to any of the application's functionalities.

The require_api_key decorator is applied to every route, checking the provided API key against a list of valid keys (VALID_API_KEYS) stored in the application's configuration. If the key is missing or invalid, the request is rejected with an appropriate error message and status code.

Also, API key authentication aligns with the stateless nature, ensuring that each request is independently authenticated without the need for session management.

API Key Distribution

In the beginning, API keys are directly provided to a select group of users. This could involve secure email communication or another secure method to ensure the keys are not compromised.

Also, we can set up an online portal for developers and users where they can create an account, log in, and automatically receive an API key. This portal serves as a one-place for API documentation, key management, and support. Through the portal, users can generate new keys, rotate existing keys for security, or deactivate keys if they believe their keys are compromised. Also, implement rate limits based on API key usage, periodic rotation of API keys to minimize the risk of key compromise can be done.

For more extensive systems, integrating with third-party key management services like Auth0 can offer advanced features.


Resources allocation

Task Student Estimated time
implementation of endpoints Tharindu Muthukuda Walawwe ([email protected]) 3h
implementation of face-engine and debugging Tharindu Muthukuda Walawwe ([email protected]) 3h
API testing with postman Tharindu Muthukuda Walawwe ([email protected]) 1h
caching, URL converter adding and Authentication as extras Tharindu Muthukuda Walawwe ([email protected]) 3h
⚠️ **GitHub.com Fallback** ⚠️