- Published on
Role Based Access with Django
- Authors
- Name
- Ryan Ashiruma
- @RAshiruma
Role Based Access Control
Provides restrictive access to the users in a system based on their role (User groups) Above implies the entire format will be implemented with group and no granular permissions assigned to the user directly
Explicit Features/Tasks
- User is a member of one group or more groups
- Group contains many users and many permisions
- Each user created will have a group with their username
- Sub users will be registered on parent users group and they will be able to cascade the permisions downstream.
- Adding permission to the role/Group
- Remove permission from the group/role
- Add user to group/role
- Remove user from role/group
- Get all permisions of a role
- Get all users of a role
Features Implemented in the application
- Application/api security (JWT token generation)
- Data normalizations (Database functionlity)
- Auditable data (Timestamps and user profile on any data manupilation done)
- Application testability (Unit tests to achieve coverage greater 90%)
- Application documentation (Feature and code documentation on readme file)
- Code versioning (Git hub)
- Deployment and delivery via Heroku
- Depandencies management and documentation on requirements.txt
- Logging and log management.
Potential challenges
- How to handle deletion of parent sub. so that the other subs remain but permision related to the parent sub are removed. NOTE: Group defines the role of the user in the system
Research material
- user types with django
- role based access control
- designing roles and permissions
- configure role based access control
- api guide permissions
Application setup
Get the application source code from github
git clone https://github.com/ryananyangu/tmpbuupassrepo.git
Change directory into the application directory
cd tmpbuupassrepo
Create virtual environment to host the application dependacies
python3 -m venv env
Activate the virtual environment
source ../env/bin/activate
Install application dependancies into your virtual directory
pip install -r requirements.txt
Add the following enviromental variables to be able to run the application smoothly
# Advisable never to use the default even though it exists esp in prod
export SECRET_KEY={insert your own !}
# Debug only accepts True or False values default is True
export DEBUG=True|False
# Database url if not set defaults to sqlite setup
export DATABASE_URL={insert your own postgresql url}
Making the model migrations and running the generated migrations For both default apps and cordinates app
python3 manage.py makemigrations
python3 manage.py makemigrations cordinates
python3 manage.py migrate
Create a supper user account to be able to access both the apis and admin portal
python3 manage.py createsuperuser
# Follow the prompt instructions recieved
Run the application
python3 manage.py runserver
Production setup is different as it uses
- Whitenoise to server static files and
- Gunicorn for serving the backend api
Following is the variation of production command for running the application Setup for whitenoise for deployment to heroku is already done in the settings.py file
# Collect all the static files to be served with application i.e. admin, rest_api browser etc.
python3 manage.py collectstatic --noinput
# Run the application on production
gunicorn --bind 0.0.0.0:$PORT buupass.wsgi:application --log-file -
Running test and getting the test coverage report.
coverage run --source='.' manage.py test cordinates
coverage report
APIs Implementation and Examples
Login API
Sample request via curl
curl -X POST \
https://ashiruma-buupass.herokuapp.com/api-token-auth/ \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"username": "rashiruma",
"password": "XXXXXXXXX"
}'
Sample response
{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Verify Token API
Sample request
curl -X POST \
https://ashiruma-buupass.herokuapp.com/api-token-refresh/ \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}'
Sample response
{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Refresh token API
Sample request
curl -X POST \
https://ashiruma-buupass.herokuapp.com/api-token-refresh/ \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}'
Sample response with new token
{
"token": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
}
GET Roles of logged in user
curl --location --request GET 'https://ashiruma-buupass.herokuapp.com/user/roles/' \
--header 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
[
{
"id": 1,
"name": "rashiruma",
"admin_id__username": "rashiruma",
"created_at": "2022-01-06T07:08:33.815437Z",
"created_by__username": "rashiruma",
"modified_at": "2022-01-06T07:08:33.832000Z",
"modified_by__username": "rashiruma"
},
{
"id": 3,
"name": "ztech",
"admin_id__username": "ztech",
"created_at": "2022-01-06T10:32:20.586653Z",
"created_by__username": "ztech",
"modified_at": "2022-01-06T10:32:20.587621Z",
"modified_by__username": "ztech"
}
]
Add user to role
curl --location --request POST 'https://ashiruma-buupass.herokuapp.com/user/roles/' \
--header 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXX' \
--header 'Content-Type: application/json' \
--data-raw '{
"role_id":1,
"user_id":3
}'
Sample response
{
"message": "user ranyangu added to role rashiruma successfully"
}
Delete user from role
curl --location --request DELETE 'https://ashiruma-buupass.herokuapp.com/user/roles/1/' \
--header 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
--data-raw ''
Sample response
{
"message": "Role rashiruma removed from user rashiruma profile."
}