-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
38 changed files
with
2,043 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) [2021] [Bunyamin Sani] | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# FastAPI Project Template | ||
|
||
Generate a FastAPI application backend with Role Based Access Control(RBAC) using Python, including interactive API documentation. | ||
|
||
## Features | ||
|
||
* **Production ready** Python web server using Uvicorn and Gunicorn. | ||
* Everything that comes with [FastAPI](https://fastapi.tiangolo.com/features/) | ||
* **Fast:** Very high performance, on par with NodeJS and Go (thanks to Starlette and Pydantic). | ||
* **Intuitive:** Great editor support. Completion everywhere. Less time debugging. | ||
* **Easy:** Designed to be easy to use and learn. Less time reading docs. | ||
* **Short:** Minimize code duplication. Multiple features from each parameter declaration. | ||
* **Robust:** Get production-ready code. With automatic interactive documentation. | ||
* **Standards-based:** Based on (and fully compatible with) the open standards for APIs: OpenAPI and JSON Schema. | ||
* Many other features including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc. | ||
* **RBAC:** Role Based Access Control | ||
* **Secure password** hashing by default. | ||
* **JWT** token authentication. | ||
* **SQLAlchemy** models. | ||
* **Alembic** migrations. | ||
* **CORS** (Cross Origin Resource Sharing). | ||
* Browse API docs offline | ||
* Basic starting models for users (modify and remove as you need). | ||
* Dependencies to check permission | ||
* Initial data for admin User, permissions , roles, and group | ||
* Dummy email for development | ||
|
||
## How to use it | ||
|
||
Go to the directory where you want to create your project and run: | ||
|
||
```bash | ||
pip install cookiecutter | ||
cookiecutter https://github.com/Bexils/fastapi-project-template | ||
``` | ||
|
||
### Generate passwords | ||
|
||
You will be asked to provide secret key whic will be used for password hashing. Open another terminal and run: | ||
|
||
```bash | ||
openssl rand -hex 32 | ||
# Outputs something like: f5e601cffde98e116dab4e31c50764006c765295732d40a57dbebc02e273eeb1 | ||
``` | ||
|
||
If you're on Windows, run the command above on a WSL terminal or git bash. | ||
Copy the contents and use that as password / secret key. And run that again to generate another secure key. | ||
|
||
|
||
### Input variables | ||
|
||
The generator (cookiecutter) will ask you for some data, you might want to have at hand before generating the project. | ||
|
||
The input variables, with their default values (some auto generated) are: | ||
|
||
* `project_name`: The name of the project | ||
* `project_slug`: The development friendly name of the project. By default, based on the project name | ||
* `secret_key`: Backend server secret key. Use the method above to generate it. | ||
* `superuser_email`: The first superuser generated, with it you will be able to create more users, etc. By default, based on the domain. | ||
* `superuser_password`: First superuser password. Use the method above to generate it or set a frendlier one. | ||
* `db_host`: Database server url | ||
* `db_port`: Database server port | ||
* `db_name`: Name of database to use on the database server | ||
* `db_engine`: Database server type, e.g postgres(default), mysql, e.t.c | ||
* `db_user`: Database server user's username | ||
* `db_password`: Database server user's password, use the method above to generate it or set a frendlier one. | ||
|
||
## More details | ||
|
||
After using this generator, your new project (the directory created) will contain an extensive `README.md` with instructions for development, deployment, etc. You can pre-read [the project `README.md` template here too](./{{cookiecutter.project_slug}}/README.md). | ||
|
||
## Won't Do | ||
|
||
This project does not intend to support any other ORM apart from SQLAlchemy unless it works as smoothly with pydantic as SQLAlchemy does. | ||
|
||
## License | ||
|
||
This project is licensed under the terms of the MIT license. | ||
|
||
## Screenshots | ||
|
||
![Screenshot 1](./assets/01.png) | ||
![Screenshot 2](./assets/02.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"project_name": "Base Project", | ||
"project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}", | ||
"secret_key": "change_this", | ||
"superuser_email": "admin@example.com", | ||
"superuser_password": "superadminpassword", | ||
"db_host": "localhost", | ||
"db_port": 5432, | ||
"db_name": "test_db", | ||
"db_engine": "postgres", | ||
"db_user": "user", | ||
"db_password": "password", | ||
"_copy_without_render": [ | ||
"*.js", | ||
"*.ini" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Python compile stuff | ||
__pycache__ | ||
*.pyc | ||
|
||
# Environments | ||
.env | ||
venv/ | ||
|
||
# Editors and IDE | ||
.idea | ||
.vscode/ | ||
|
||
# Mac-Stuff | ||
.DS_Store | ||
cloud_storage_key.json | ||
|
||
# Own directories | ||
emails/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# {{cookiecutter.project_name}} | ||
|
||
This is a backend server application power with Python and [FastAPI](https://fastapi.tiangolo.com). | ||
|
||
## Local Development | ||
|
||
### Install the dependencies | ||
|
||
Create a virtual environment: | ||
```bash | ||
python -m venv venv | ||
``` | ||
|
||
Activate the virtual environment: | ||
```bash | ||
venv/Scripts/activate | ||
``` | ||
Change directory to `app/` folder | ||
```bash | ||
cd app/ | ||
``` | ||
Install dependencies | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
Ensure that your database config in `.env` is correct, then run [alembic](https://alembic.sqlalchemy.org) migrations | ||
```bash | ||
alembic upgrade head | ||
``` | ||
Initialise database with User & RBAC tables and initial entries | ||
```bash | ||
python initial_data.py | ||
``` | ||
|
||
### Start the development server | ||
Run without `--reload` flag if you want to disable hot module reloading (HMR) | ||
```bash | ||
uvicorn main:app --reload | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from sqlalchemy.orm import Session | ||
|
||
from access_control import models, schemas | ||
|
||
|
||
|
||
def create_permission(db: Session, perm_data: schemas.PermissionCreate): | ||
permission = models.Permission(**perm_data.dict(exclude_unset=True)) | ||
permission.name = permission.name.lower() | ||
db.add(permission) | ||
db.commit() | ||
db.refresh(permission) | ||
return permission | ||
|
||
|
||
def get_perm_by_name(db: Session, name: str): | ||
return db.query(models.Permission). \ | ||
filter(models.Permission.name == name.lower()). \ | ||
first() | ||
|
||
|
||
def create_role(db: Session, role_data: schemas.RoleCreate): | ||
role = models.Role(**role_data.dict(exclude_unset=True)) | ||
role.name = role.name.lower() | ||
db.add(role) | ||
db.commit() | ||
db.refresh(role) | ||
return role | ||
|
||
|
||
def get_role_by_name(db: Session, name: str): | ||
return db.query(models.Role). \ | ||
filter(models.Role.name == name.lower()). \ | ||
first() | ||
|
||
|
||
def create_group(db: Session, group_data: schemas.GroupCreate): | ||
group = models.Group(**group_data.dict(exclude_unset=True)) | ||
group.name = group.name.lower() | ||
db.add(group) | ||
db.commit() | ||
db.refresh(group) | ||
return group | ||
|
||
|
||
def get_group_by_name(db: Session, name: str): | ||
return db.query(models.Group). \ | ||
filter(models.Group.name == name.lower()). \ | ||
first() |
29 changes: 29 additions & 0 deletions
29
{{cookiecutter.project_slug}}/app/access_control/models.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from sqlalchemy import Column, ForeignKey, Integer, Table | ||
from sqlalchemy.orm import relationship | ||
|
||
from config.db import Base | ||
from mixins.columns import BaseMixin, BaseUACMixin | ||
|
||
|
||
|
||
# Many to Many associations | ||
permission_role = Table('permission_role', Base.metadata, | ||
Column('permission_id', Integer, ForeignKey('permissions.id')), | ||
Column('role_id', Integer, ForeignKey('roles.id')) | ||
) | ||
role_group = Table('role_group', Base.metadata, | ||
Column('role_id', Integer, ForeignKey('roles.id')), | ||
Column('group_id', Integer, ForeignKey('groups.id')) | ||
) | ||
|
||
|
||
class Permission(BaseUACMixin, Base): | ||
pass | ||
|
||
|
||
class Role(BaseUACMixin, Base): | ||
permissions = relationship("Permission", secondary=permission_role) | ||
|
||
|
||
class Group(BaseUACMixin, Base): | ||
roles = relationship("Role", secondary=role_group) |
Oops, something went wrong.