Skip to content

Commit 84a21f1

Browse files
committed
Enhance Docker configurations and add setup scripts
- Updated `docker-compose-dev.yml` to include a sleep command before database migrations and added makemigrations step. - Modified `docker-compose-prod.yml` to use environment variables for Traefik configuration and updated container names for versioning. - Added a new `setup.sh` script for easier environment setup and management. - Updated `README.md` to include prerequisites and setup instructions. - Introduced new JSON example files for RADIUSdesk and smart contracts. - Added management commands for creating users and smart contracts from JSON files. - Implemented TimescaleDB checks and continuous aggregate refresh commands. - Enhanced serializers and views for better data handling and pagination in the API.
1 parent f6f8be3 commit 84a21f1

38 files changed

Lines changed: 3054 additions & 411 deletions

README.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ The backend for the bespoke iNethi system.
44

55
## Commands
66

7+
### Prerequisites
8+
9+
Read the [docs](./docs/README.md) for details of the set up and requirements.
10+
711
### Running the Code
812

913
Look at [.env.example](.env.example) and create a `.env` file with all the variables listed in this file. See
@@ -55,12 +59,3 @@ print(f"Your encryption key: {encryption_key.decode()}")
5559
from django.core.management.utils import get_random_secret_key
5660
print(get_random_secret_key())
5761
```
58-
59-
## Contributing
60-
61-
Pull requests and issues are welcome! Please open an issue to discuss major changes or new features.
62-
63-
## License
64-
65-
> [!WARNING]
66-
> Closed-source commercial usage of this code is not permitted with the GPL-3.0. If that license is not compatible with your use case, please contact [email protected] for queries.

docker-compose-dev.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ services:
1313
volumes:
1414
- ./inethi:/inethi
1515
command: >
16-
sh -c "python manage.py wait_for_db &&
16+
sh -c "sleep 10 &&
17+
python manage.py wait_for_db &&
18+
python manage.py makemigrations &&
1719
python manage.py migrate &&
1820
python manage.py runserver 0.0.0.0:8000"
1921
environment:
@@ -37,6 +39,7 @@ services:
3739
- POSTGRES_DB=${DB_NAME:-devdb}
3840
- POSTGRES_USER=${DB_USER:-devuser}
3941
- POSTGRES_PASSWORD=${DB_PASS:-devpass}
42+
command: postgres -c shared_preload_libraries=timescaledb
4043

4144
keycloak:
4245
image: quay.io/keycloak/keycloak:25.0.6

docker-compose-prod.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
app:
3-
container_name: inethi-backend
3+
container_name: inethi-backend-v1
44
restart: unless-stopped
55
env_file:
66
- ./.env
@@ -25,29 +25,30 @@ services:
2525
- db
2626
labels:
2727
- "traefik.enable=true"
28-
- "traefik.http.routers.backend.rule=Host(`backend.inethicloud.net`)"
29-
- "traefik.http.routers.backend.entrypoints=websecure"
28+
- "traefik.http.routers.backend.rule=Host(`${TRAEFIK_BACKEND_HOST:-backend.inethicloud.net}`)"
29+
- "traefik.http.routers.backend.entrypoints=${TRAEFIK_ENTRYPOINTS:-websecure}"
3030
- "traefik.http.services.backend.loadbalancer.server.port=8000"
31+
- "traefik.http.routers.backend.tls.certresolver=${TRAEFIK_CERTRESOLVER:-letsencrypt}"
3132

3233
db:
3334
image: timescale/timescaledb:latest-pg17
3435
restart: unless-stopped
35-
container_name: inethi-backend-db-timescale
36+
container_name: inethi-backend-db-timescale-v1
3637
env_file:
3738
- ./.env
3839
volumes:
39-
- prod-db-data-timescale:/var/lib/postgresql/data
40+
- prod-db-data-timescale-v1:/var/lib/postgresql/data
4041
environment:
4142
- POSTGRES_DB=${DB_NAME:-devdb}
4243
- POSTGRES_USER=${DB_USER:-devuser}
4344
- POSTGRES_PASSWORD=${DB_PASS:-devpass}
4445
labels:
4546
- "traefik.enable=true"
46-
- "traefik.http.routers.backenddb.entrypoints=websecure"
47+
- "traefik.http.routers.backenddbv1.entrypoints=${TRAEFIK_ENTRYPOINTS:-websecure}"
4748

4849
redis:
4950
image: redis:alpine
50-
container_name: inethi-backend-celery-redis
51+
container_name: inethi-backend-celery-redis-v1
5152

5253
celery:
5354
build:
@@ -61,7 +62,7 @@ services:
6162
environment:
6263
- CELERY_BROKER=redis://redis:6379/0
6364
- CELERY_BACKEND=redis://redis:6379/0
64-
container_name: inethi-backend-celery
65+
container_name: inethi-backend-celery-v1
6566
depends_on:
6667
- redis
6768
- db
@@ -76,16 +77,15 @@ services:
7677
environment:
7778
- CELERY_BROKER=redis://redis:6379/0
7879
- CELERY_BACKEND=redis://redis:6379/0
79-
container_name: inethi-backend-celery-beat
80+
container_name: inethi-backend-celery-beat-v1
8081
depends_on:
8182
- redis
8283
- db
8384

84-
8585
networks:
8686
default:
8787
external:
88-
name: "inethi-bridge-traefik"
88+
name: "${TRAEFIK_NETWORK_BRIDGE:-inethi-bridge-traefik}"
8989

9090
volumes:
91-
prod-db-data-timescale:
91+
prod-db-data-timescale-v1:

docs/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Setting Up The System
2+
3+
1. Populate a `.env` file.
4+
2. If you don't have keycloak and radiusdesk you need to set these up. The details for Keycloak can be found [here](./keycloak/README.md).
5+
3. Run the compose file of your choosing then run `docker exec inethi-backend python manage.py create_superuser`.
6+
4. Create json files and place them in the [inethi dir](../inethi/) for your NETWORK admin user(s), RADIUSDesk instance(s) and smart contract(s) commands, see the [users example](./examples/users.json), [RADIUSDesk example](./examples/sample_radiusdesk_config.json) and the contracts [example](./examples/smart_contracts.json) then run the following:
7+
8+
```
9+
docker exec -it inethi-backend sh
10+
python manage.py create_users_from_json user.json
11+
python manage.py create_smart_contracts_from_json smart_contracts.json
12+
python manage.py create_radiusdesk_from_json sample_radiusdesk_config.json
13+
```
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
[
2+
{
3+
"name": "Main RADIUSdesk Instance",
4+
"base_url": "https://radiusdesk.example.com",
5+
"username": "admin",
6+
"password": "admin_password",
7+
"accepts_crypto": true,
8+
"administrators": ["devuser", "network_admin"],
9+
"clouds": [
10+
{
11+
"name": "Main Cloud",
12+
"radius_desk_id": 1,
13+
"realms": [
14+
{
15+
"name": "Default Realm",
16+
"radius_desk_id": 1,
17+
"profiles": [
18+
{
19+
"name": "Basic Plan",
20+
"radius_desk_id": 1,
21+
"data_limit_enabled": true,
22+
"data_limit_gb": 5.0,
23+
"data_limit_reset": "monthly",
24+
"speed_limit_enabled": true,
25+
"speed_limit_mbs": 10.0,
26+
"limit_session_enabled": false,
27+
"session_limit": 0,
28+
"cost": 0.0
29+
},
30+
{
31+
"name": "Premium Plan",
32+
"radius_desk_id": 2,
33+
"data_limit_enabled": true,
34+
"data_limit_gb": 20.0,
35+
"data_limit_reset": "monthly",
36+
"speed_limit_enabled": true,
37+
"speed_limit_mbs": 50.0,
38+
"limit_session_enabled": false,
39+
"session_limit": 0,
40+
"cost": 10.0
41+
},
42+
{
43+
"name": "Unlimited Plan",
44+
"radius_desk_id": 3,
45+
"data_limit_enabled": false,
46+
"data_limit_gb": 0,
47+
"data_limit_reset": "never",
48+
"speed_limit_enabled": true,
49+
"speed_limit_mbs": 100.0,
50+
"limit_session_enabled": true,
51+
"session_limit": 1,
52+
"cost": 25.0
53+
}
54+
]
55+
},
56+
{
57+
"name": "Guest Realm",
58+
"radius_desk_id": 2,
59+
"profiles": [
60+
{
61+
"name": "Guest Access",
62+
"radius_desk_id": 4,
63+
"data_limit_enabled": true,
64+
"data_limit_gb": 1.0,
65+
"data_limit_reset": "daily",
66+
"speed_limit_enabled": true,
67+
"speed_limit_mbs": 5.0,
68+
"limit_session_enabled": true,
69+
"session_limit": 2,
70+
"cost": 0.0
71+
}
72+
]
73+
}
74+
]
75+
},
76+
{
77+
"name": "Secondary Cloud",
78+
"radius_desk_id": 2,
79+
"realms": [
80+
{
81+
"name": "Business Realm",
82+
"radius_desk_id": 3,
83+
"profiles": [
84+
{
85+
"name": "Business Basic",
86+
"radius_desk_id": 5,
87+
"data_limit_enabled": true,
88+
"data_limit_gb": 50.0,
89+
"data_limit_reset": "monthly",
90+
"speed_limit_enabled": true,
91+
"speed_limit_mbs": 25.0,
92+
"limit_session_enabled": false,
93+
"session_limit": 0,
94+
"cost": 15.0
95+
},
96+
{
97+
"name": "Business Pro",
98+
"radius_desk_id": 6,
99+
"data_limit_enabled": true,
100+
"data_limit_gb": 100.0,
101+
"data_limit_reset": "monthly",
102+
"speed_limit_enabled": true,
103+
"speed_limit_mbs": 100.0,
104+
"limit_session_enabled": true,
105+
"session_limit": 5,
106+
"cost": 35.0
107+
}
108+
]
109+
}
110+
]
111+
}
112+
]
113+
},
114+
{
115+
"name": "Test RADIUSdesk Instance",
116+
"base_url": "https://test-radiusdesk.example.com",
117+
"username": "test_admin",
118+
"password": "test_password",
119+
"accepts_crypto": false,
120+
"administrators": ["devuser"],
121+
"clouds": [
122+
{
123+
"name": "Test Cloud",
124+
"radius_desk_id": 1,
125+
"realms": [
126+
{
127+
"name": "Test Realm",
128+
"radius_desk_id": 1,
129+
"profiles": [
130+
{
131+
"name": "Test Profile",
132+
"radius_desk_id": 1,
133+
"data_limit_enabled": false,
134+
"data_limit_gb": 0,
135+
"data_limit_reset": "never",
136+
"speed_limit_enabled": false,
137+
"speed_limit_mbs": 0,
138+
"limit_session_enabled": false,
139+
"session_limit": 0,
140+
"cost": 0.0
141+
}
142+
]
143+
}
144+
]
145+
}
146+
]
147+
}
148+
]

docs/examples/smart_contracts.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[
2+
{
3+
"name": "iNethi Registry",
4+
"address": "0x9b1a3F8FadD0dc86FBae5Cf66Fa682fDcd84a9b0",
5+
"contract_type": "account index",
6+
"description": "iNethi account registry for celo eth faucet",
7+
"write_access": false,
8+
"read_access": false,
9+
"user_name": "inethiofficial"
10+
},
11+
{
12+
"name": "iNethi Faucet",
13+
"address": "0xB821E49ADB53F0AbeD834278d5dFc57901c30Eea",
14+
"contract_type": "eth faucet",
15+
"description": "iNethi faucet for celo",
16+
"write_access": false,
17+
"read_access": false,
18+
"user_name": "inethiofficial"
19+
}
20+
]

docs/examples/users.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"username": "network_admin_1",
4+
"password": "password1",
5+
"email": "[email protected]"
6+
},
7+
{
8+
"username": "network_admin_2",
9+
"password": "password2",
10+
"email": "[email protected]"
11+
}
12+
]

docs/keycloak/README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Keycloak Integration with iNethi Backend
2+
3+
## Set Up
4+
5+
To get auth working for the UI and App you need to set up your keycloak instance. Navigate to your keycloak URL. If you use the dev compose file then navigate to [http://localhost:8080/](http://localhost:8080/).
6+
7+
### Configuration
8+
9+
These steps will use the following env variables. Repalce them with your own where neccessary:
10+
11+
```
12+
KEYCLOAK_MASTER_ADMIN="devuser"
13+
KEYCLOAK_MASTER_ADMIN_PASSWORD="devpass"
14+
KEYCLOAK_ADMIN="inethi"
15+
KEYCLOAK_ADMIN_PASSWORD="iNethi2023#"
16+
KEYCLOAK_URL="http://192.168.0.1:8080"
17+
KEYCLOAK_REALM="inethi-services"
18+
KEYCLOAK_BACKEND_CLIENT_ID="inethi-backend-client"
19+
KEYCLOAK_CLIENT_SECRET="oq3BKpcKtiVyNXatzaelqW2QV2zji7YG"
20+
```
21+
22+
These will be used in the [settings.py file](../../inethi/inethi/settings.py) to generate the `KEYCLOAK_OPENID`:
23+
24+
```
25+
KEYCLOAK_OPENID = KeycloakOpenID(
26+
server_url=env("KEYCLOAK_URL"),
27+
client_id=env("KEYCLOAK_BACKEND_CLIENT_ID"),
28+
realm_name=env("KEYCLOAK_REALM"),
29+
client_secret_key=env("KEYCLOAK_CLIENT_SECRET"),
30+
)
31+
```
32+
33+
1. Create a new realm called `inethi-services`.
34+
35+
2. Ensure you are in this realm and then create a user with the username of `inethi` and password of `iNethi2023#`. Ensure email verification is set to on.
36+
37+
3. Navigate to `Role mapping` and assign the inethi user these roles:
38+
39+
- `realm-management` create-client
40+
- `realm-management` manage-clients
41+
- `realm-management` view-clients
42+
- `realm-management` manage-users
43+
44+
4. Navigate to clients and create a client with the following details:
45+
46+
- Type: `OpenID Connect`
47+
- Client ID: `inethi-backend-client`
48+
- Name: `inethi-backend-client`
49+
- Client authentication: `on`
50+
- Authorization: `on`
51+
- AUthentication flow: `standard flow, direct access grants, service account roles`
52+
- Home URL: (enter your backend's URL): `http://localhost:8000`
53+
- Valid redirect URIs: `http://localhost:8000/*`
54+
- Valid post logout redirect URIs: `+`
55+
- Web origins: `+`
56+
57+
5. Navigate to Credentials on the client and copy the `Client Secret` into your `.env` file and replace the default value for `KEYCLOAK_CLIENT_SECRET`. Then restart your backend docker containers:
58+
59+
```
60+
docker compose -f docker-compose-dev.yml down
61+
docker compose -f docker-compose-dev.yml build
62+
docker compose -f docker-compose-dev.yml up -d
63+
```

inethi/api_key/migrations/0001_initial.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.1 on 2025-02-03 09:30
1+
# Generated by Django 5.1 on 2025-08-08 14:01
22

33
import django.db.models.deletion
44
from django.conf import settings
@@ -18,9 +18,9 @@ class Migration(migrations.Migration):
1818
name='APIKey',
1919
fields=[
2020
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21-
('key', models.CharField(db_index=True, max_length=255, unique=True)),
22-
('created_at', models.DateTimeField(auto_now_add=True)),
21+
('key', models.CharField(blank=True, max_length=255, unique=True)),
2322
('is_active', models.BooleanField(default=True)),
23+
('created_at', models.DateTimeField(auto_now_add=True)),
2424
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='api_keys', to=settings.AUTH_USER_MODEL)),
2525
],
2626
),

0 commit comments

Comments
 (0)