175 lines
6.8 KiB
Python
175 lines
6.8 KiB
Python
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
from .exceptions import ExceptionHandlerRoute
|
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from sqlalchemy.orm import Session
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
from .models import Users
|
|
from .db.db import engine
|
|
from .db.config import settings
|
|
from .middlewares import app_middleware
|
|
from .auth.views import get_password_hash
|
|
from .routes import routers, docs
|
|
|
|
|
|
@asynccontextmanager
|
|
async def init_db(app: FastAPI):
|
|
with Session(engine) as session:
|
|
from sqlalchemy import select, insert
|
|
user = session.execute(select(Users).where(Users.username == settings.FIRST_SUPERUSER)).first()
|
|
if not user:
|
|
session.execute(insert(Users).values(
|
|
username = settings.FIRST_SUPERUSER,
|
|
hashed_password = get_password_hash(settings.FIRST_SUPERUSER_PASSWORD),
|
|
full_name = "admin",
|
|
type = 'ADMIN',
|
|
email = settings.FIRST_SUPERUSER_EMAIL
|
|
))
|
|
session.commit()
|
|
yield
|
|
|
|
description = """
|
|
# Description
|
|
This part of the documentation includes overview of the backend, backend internals and common attributes shared by all the apis.
|
|
|
|
The backend is written using [FastAPI](https://fastapi.tiangolo.com/), [SQLAlchemy](https://www.sqlalchemy.org/) and [Postgresql](https://www.postgresql.org/).
|
|
|
|
## Documentation
|
|
Redoc with openapi will serve as primary documentation, which will be available publicly in development and staging environment and not for production evnrionment for security reasons.
|
|
|
|
## Authorization
|
|
Authorization is implemended using OAuth2 using password and username, logging with external providers like google, github etc. is not supported.
|
|
|
|
Each type of user i.e. doctor, patient, staff is required to create their own username and password while registering, so that will be able to login to the system.
|
|
|
|
The auth token expiry duration is 120 minutes currently
|
|
|
|
|
|
## Common columns
|
|
All tables in the backend shares some common columns, these columns will be described here and not in the respective API as it has the same meaning everywhere.
|
|
|
|
|
|
1. __created_at, updated_at__ : represents the datetime when the row was added, updated respectively
|
|
|
|
2. __create_by_id, updated_by_id__ : foreign key to user's id, it's extracted from the logged in user who created or updated the row.
|
|
|
|
3. __is_archived__ : It represents if the row is deleted, allows us to implement soft delete.
|
|
|
|
|
|
## Audit
|
|
|
|
Each table on the backend has it's respective audit table with suffix ___audit__. i.e __appointment__ table has __appointment_audit__.
|
|
It stores all the changes done in each row including which operation it was, which columns were changed and what's it's old and new values.
|
|
|
|
APIs will be created to access the audit for each table.
|
|
|
|
It's implemented using sqlalchemy_declarative_extention library
|
|
|
|
## Internals
|
|
|
|
### Primary, Foreign Key
|
|
|
|
All primary keys are [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), which makes it possible to avoid alot of security risks and implement dynamic features.
|
|
Due to this all the foreign keys are also UUIDs
|
|
UUIDs can be generated in postgres or in python easy and fast
|
|
|
|
## Errors
|
|
|
|
Errors are implemented using [RFC9457](https://www.rfc-editor.org/rfc/rfc9457.html) with some slight modification. Here is a sample error response.
|
|
|
|
```json
|
|
{
|
|
"type": "UNIQUE_VALIDATION",
|
|
"status": 422,
|
|
"detail": "Key (username)=(banana) already exists.",
|
|
"title": "Unique violation"
|
|
}
|
|
```
|
|
|
|
The type will always be a standard enum value. the status will always be the http status code.
|
|
The type, status, title and detail will __always__ exist,
|
|
|
|
For now in case of pydantic validation error, the raw pydantic message will be set in details
|
|
|
|
In case of internal server error the type will be 'INTERNAL_SERVER_ERROR' and it's detail will contain the error message.
|
|
|
|
In this way all the errors will be well documented and handled in a central module, It will also make writing automated tests easier.
|
|
|
|
|
|
# Testing
|
|
This section covers the steps for testing and guidelines for reporting and verifying bugs for backend api.
|
|
In the future the manual for QA for frontend will also be included here.
|
|
|
|
|
|
## Automated testing
|
|
Automated testing is done using fastapi's testclient, pytest and faker
|
|
This test creates new database on startup, runs the tests and deletes everything, so the errors i can be reproduceable and deterministic.
|
|
The test interacts to the backend only thru API
|
|
|
|
### Prerequisites
|
|
1. Python
|
|
2. Postgresql server with a clean database (You can avoid it by using test database on the server)
|
|
|
|
### Steps
|
|
1. Clone the [repository](https://git.aayutech.dev/fourleaf/backend)
|
|
2. Create .env file using .env.example as reference
|
|
3. Create virtual environment and install packages from requirements.txt
|
|
4. Run tests using pytest (lookup pytest's documentation for more information)
|
|
5. Create a test inside the tests folder
|
|
|
|
|
|
## Manual testing
|
|
Manual testing is done using postman or similar api client.
|
|
Url for testing in dev environment is `https://api-dev.aayutech.dev`
|
|
|
|
|
|
### Steps
|
|
1. Download postmand collection from the git server (optional)
|
|
2. Create and run requests from postman
|
|
|
|
## Reporting bug
|
|
All the bug reporting will be done using kanban `https://project.aayutech.dev`
|
|
|
|
### Bug criteria
|
|
1. All __INTERNAL_SERVER_ERROR__
|
|
2. All about:none errors
|
|
3. All errors that consists of raw sql messages
|
|
4. Errors that doesn't match the description of the api
|
|
5. Bug should be able to be reproduced
|
|
|
|
### Bug reporting steps
|
|
1. Create new task in the `Bug Report` column in kanboard
|
|
2. Write short description about the bug and how it can be reproduced
|
|
3. Optionally take screenshot of postman or terminal where the bug can be seen
|
|
4. Add related user as assigne
|
|
|
|
### Bug resolve steps
|
|
1. After a bug is reported a QA or Developer will approve the bug and put it in the `BUG` column.
|
|
2. After the bug is verified, the respective developer will fix the bug and put it in the `Read for QA` column.
|
|
3. A QA will reverify the bug and put it in the `DONE` column.
|
|
|
|
"""
|
|
|
|
app = FastAPI(
|
|
version = "0.0.1",
|
|
lifespan = init_db,
|
|
title = "Fastapi template",
|
|
openapi_tags = docs,
|
|
description = description
|
|
)
|
|
|
|
for router in routers: app.include_router(router)
|
|
|
|
app.middleware('http')(app_middleware)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware
|
|
,allow_origins=["*"]
|
|
,allow_credentials=True # Set to True if you need to support cookies/authorization headers
|
|
,allow_methods=["*"] # Allows all methods (GET, POST, PUT, DELETE, OPTIONS, etc.)
|
|
,allow_headers=["*"] # Allows all headers
|
|
)
|
|
|