Skip to content

cmmasaba/studious-couscous

Repository files navigation

SIMPLE REST API SERVICE

Table of Contents

  1. Description
  2. Database models and design
  3. REST API
  4. Authentication and Authorization
  5. SMS Notifications
  6. Tests
  7. API Documentation
  8. Contributions and License

1. Description

This project is about building a Python REST API service with very minimalistic databases for customers and users.
The REST API implementation uses the awesome Django REST framework. It should support CRUD operations on the database models instances.
Authentication and authorization of users is done using OpenID Connect.

2. Database Models and Design



The underlying database server used for this service is PostgreSQL. The database models are designed to be very simple.

2.1 Customers model

The customers have very few details.

  • first_name: customer's first name.
  • second_name: customer's second name.
  • code: a 5-digit alphanumeric code unique to each customer.
  • phone: customer's phone number, which is used for sending updates when an order is placed in their name. Phone number should be entered in international format, e.g. +254712345678
  • id: autogenerated and used as the Primary Key.

2.2 Orders model

Similarly the orders model is kept simple.

  • item: name of the item to be bought. An order can only have one item in it.
  • quantity: the number of units of the item being bought.
  • price_per_unit: the price of each unit of the item.
  • status: the status of the order. This is an enum with the following values; Pending, Closed, Cancelled. The default is Pending.
  • customer_code: the code of the customer to whom the order belongs. The code is used internally for bookkeeping practices like relating an order to a customer.
  • time_placed: hold the time the order was placed. It is autofilled when an order is created.
  • customer: a Foreign Key that associates a specific customer to an order instance. The relationship between an order and a customer is many-to-one. Many orders can belong to a single customer.
  • id: autogenrated and used as Primary Key
Items

This was supposed to be a model for items that can be ordered. Out of the interes of time I did not pursue this idea for long. In due time I will revisit it. The idea is that there should be a dropdown field of items for a user to select from when placing an order.

3. REST API

The API serive is built using Django REST framework.
The browsable API can be accessed here.
For detailed description of supported HTTP methods, how to invoke them, and expected responses, check out the API docs.

3.1 Endpoints

3.1.1 Api root

  • /api/v1/: the API root, has links to the customers and orders endpoints.

3.1.2 Customers endpoint

  • /api/v1/customers/: list all customer instances belonging to the user.
  • /api/v1/customers/: create a new customer instance.
  • /api/v1/customers/<pk>/: perform an action on the specified customer instance.

3.1.3 Orders endpoint

  • /api/v1/orders/: list all order instances belonging to the user.
  • /api/v1/orders/: create a new order instance.
  • /api/v1/orders/<pk>/: perform an action on the specified order instance

3.1.4 Authentication endpoint

  • /api/v1/api-auth/authenticate/: login to the API using OpenID Connect and go to the home page.
  • /api/v1/api-auth/logout/: logout from the API and return to the home page.

3.1.5 Documentation and Schema endpoint

  • /api/schema/: download the schema.
  • /api/v1/docs/: view the redoc.
  • /api/v1/swagger-docs/: view the Swagger formatted docs.

4. Authentication and Authorization

OpenID Connect is used to provide authentication to API. The OpenID Connect provider used is Google.
To implement this feature I used a third party library, Mozilla OIDC, which makes the task remarkably easy.
To enforce authorization, I used the permission_classes of Django REST to ensure only authenticated users can create, read, update or delete the models.

Warning

Having the IsAuthenticated as the only permission class is security flaw. That means any authenticated user can perform any kind of operation on the customer/order instances even if they did not create them. This will be problematic in a setting where the API is used by many parties.
I implemented the object level permissions, but there is a subtle bug that is causing that mechanism to fail. And so I cannot use it yet in production but the code is there. Until I figure out where the bug is, let's assume the API will be used by only one person.

5. SMS Notifications

When an order is placed, an SMS notification is sent to the related customer using the Africa's Talking gateway.
For testing purposes I am using the Sandbox app, therefore the messages are delivered to the sandbox app.
The screenshot below shows it works as expected.

6. Tests

Unittests followed the usual Django testing procedures. For coverage tests I used the coverage module in combination with django-coverage-plugin.

7. API Documentation

This API's schema and documentation has been generated in accordance to the OpenAPI specifications.
Please visit these links for in-depth details:

8. Contributions and License

This work was done as part of the screening test for the backend developer role at Savannah Informatics, and is protected by the MIT License, all rights reserved.