Skip to content
This repository was archived by the owner on Oct 15, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
25e447a
Merge pull request #96 from The-CS-Nerds/dev
HippoProgrammer Jul 9, 2025
263e98b
Merge pull request #139 from The-CS-Nerds/dev
SuitablyMysterious Aug 2, 2025
b4ea574
Fix #140
SuitablyMysterious Aug 2, 2025
1cea2c8
Further fix for #140
SuitablyMysterious Aug 2, 2025
abcc9fe
Add arguments to `api` endpoints #142
SuitablyMysterious Aug 2, 2025
fd8ff9c
Let `policySetup.py` run #143
SuitablyMysterious Aug 2, 2025
800fd64
update compose to actually let `policySetup.py` run `casbin.Enforcer`…
SuitablyMysterious Aug 2, 2025
b94ee8b
Fix some problems for `casbin.Enforcer` is imported as a class in `__…
SuitablyMysterious Aug 2, 2025
01637ff
silly update to `launch.sh` ***NEEDS TO BE REVERSED FOR PRODUCTION***
SuitablyMysterious Aug 2, 2025
166ddd1
Update `0_roles.sh` to be a `.sh` file #144
SuitablyMysterious Aug 2, 2025
8dad705
Furthers #143
SuitablyMysterious Aug 2, 2025
4d537fa
covenience change to `launch.sh`
SuitablyMysterious Aug 2, 2025
8c54254
Remove `auto_save` parameter from the `Enforcer` Fixes #145
SuitablyMysterious Aug 2, 2025
063829f
update `model.conf` to use casbin properly
SuitablyMysterious Aug 2, 2025
dcc02b5
Revert #140
SuitablyMysterious Aug 4, 2025
57cc273
Revert #142
SuitablyMysterious Aug 4, 2025
9016ea9
Allow `launch.sh` to run in git bash on windows
SuitablyMysterious Aug 4, 2025
bcc8d4a
update secrets to be correct
SuitablyMysterious Aug 4, 2025
9959b43
fixed `launch.sh`
SuitablyMysterious Aug 4, 2025
e9603f7
add a `casbin_users` table #146
SuitablyMysterious Aug 9, 2025
8809285
remove the `role` field from the `users` table
SuitablyMysterious Aug 9, 2025
ee3b8d5
remove unnecessary imports
SuitablyMysterious Aug 9, 2025
fd14dc5
why was that there (stupid code completions)
SuitablyMysterious Aug 9, 2025
886ef98
remove admin role form `policy.csv`
SuitablyMysterious Aug 9, 2025
1e42871
add a `code` user to policy
SuitablyMysterious Aug 9, 2025
6b88127
add anoter change to Casbin is implemented slightly wrong
SuitablyMysterious Aug 9, 2025
34c3739
Fix authentication in `User` class
SuitablyMysterious Aug 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,18 @@ services:
environment:
DB_HOST: db
DB_PORT: 5432
command: ["python","/src/__main__.py"]
DB_NAME: library
POSTGRES_PASSWORD: ${DB_PASS}
CASBIN_LOGIN_PASS: ${CASBIN_LOGIN_PASS}
command: sh -c "python /src/auth/policySetup.py && python /src/__main__.py"
depends_on:
db:
condition: service_healthy
ports:
- "8000:8000"
secrets:
- casbin_login_pass
- db_pass
db: # Database
# entrypoint: ['docker-entrypoint.sh']
image: postgres:17.5-alpine3.21 # Using alpine Postgres image
Expand All @@ -62,10 +68,11 @@ services:
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
- db-init:/docker-entrypoint-initdb.d:ro # Init scripts for postgres
- ./db-init:/docker-entrypoint-initdb.d:ro
environment:
POSTGRES_USER: library
POSTGRES_PASSWORD: ${DB_PASS}
CASBIN_LOGIN_PASS: ${CASBIN_LOGIN_PASS}
POSTGRES_DB: library

healthcheck:
Expand Down Expand Up @@ -104,7 +111,6 @@ networks: # Frontend and DB MUST NEVER be on the same network.

volumes:
pgdata:
db-init:

secrets:
casbin_login_pass:
Expand Down
10 changes: 10 additions & 0 deletions db-init/0_roles.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE ROLE casbin NOLOGIN;
CREATE ROLE casbin_login LOGIN PASSWORD '${CASBIN_LOGIN_PASS}';
GRANT casbin TO casbin_login;

GRANT CREATE, USAGE ON SCHEMA public TO casbin_login;
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO casbin_login;
EOSQL
29 changes: 0 additions & 29 deletions db-init/0_roles.sql

This file was deleted.

8 changes: 6 additions & 2 deletions db-init/1_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@ CREATE TABLE IF NOT EXISTS users (
surname TEXT NOT NULL,
student_id INTEGER NOT NULL
email TEXT NOT NULL UNIQUE,
role TEXT NOT NULL,
);
);

CREATE TABLE IF NOT EXISTS casbin_users (
id UUID PRIMARY KEY,
role TEXT NOT NULL
)
11 changes: 7 additions & 4 deletions launch.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#!/bin/sh
export DB_PASS=`python3 dbKeyGen.py --keys db --print`
export CASBIN_LOGIN_PASS=`python3 dbKeyGen.py --keys auth --print`
docker compose down -v
export DB_PASS=`python dbKeyGen.py --keys db --print`
export CASBIN_LOGIN_PASS=`python dbKeyGen.py --keys auth --print`
if [ $1 = "--kill" ]; then
docker compose down
docker compose down -v
docker system prune --force
docker volume prune --force
exit 0
else
docker compose up --build $1

docker compose up --build $1 backend db frontend
fi
unset DB_PASS
unset CASBIN_LOGIN_PASS
6 changes: 3 additions & 3 deletions src/backend/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ class getBookByID(Resource):
def get(self, id):
return db.getBookData(id = int(id))

api.add_resource(getBookByISBN, '/Book/getByISBN')
api.add_resource(getBookByName, '/Book/getByName')
api.add_resource(getBookByID, '/Book/getByID')
api.add_resource(getBookByISBN, '/Book/getByISBN/')
api.add_resource(getBookByName, '/Book/getByName/')
api.add_resource(getBookByID, '/Book/getByID/')

if __name__ == '__main__':
app.run()
2 changes: 1 addition & 1 deletion src/backend/auth/model.conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ r = sub, tbl, obj, act, verified # needs to be changed later on
p = sub, tbl, obj, act, verified # needs to be changed later on

[role_definition]
g = _, _, _, _, _, _ # unique id, student id, name, email, role, password
g = _, _ # uuid, permissions

[policy_effect]
e = some(where (p.eft == allow))
Expand Down
3 changes: 2 additions & 1 deletion src/backend/auth/policy.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ p,librarian,loans,loan,delete,True
p,student,books,book,read,True
p,*,books,book,read,False
p,admin,*,*,*,True
g,000000,0000,admin,admin,root
p,code,*,*,*,True
g,0,code
8 changes: 4 additions & 4 deletions src/backend/auth/policySetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
import logging
import sys
import os
from casbin import Enforcer, persist
from casbin import Enforcer
from casbin_sqlalchemy_adapter import Adapter
from sqlalchemy import create_engine

log = logging.getLogger(__name__)
log_handler = logging.StreamHandler(sys.stdout)

log.addHandler(log_handler)
log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)

log.info('Initiating policySetup.py')

Expand All @@ -38,9 +38,9 @@
engine = create_engine(DSN, future=True)
adapter = Adapter(engine)

enforcer = Enforcer(str(MODEL_PATH), adapter, auto_save=False)
enforcer = Enforcer(str(MODEL_PATH), adapter)
enforcer.load_policy()
db_enforcer = Enforcer(str(MODEL_PATH), adapter, auto_save=False)
db_enforcer = Enforcer(str(MODEL_PATH), adapter)
file_enforcer = Enforcer(str(MODEL_PATH), str(POLICY_PATH))

for rule in file_enforcer.get_policy():
Expand Down
2 changes: 1 addition & 1 deletion src/backend/backend.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN pip install --no-cache-dir --require-hashes --force-reinstall -r requirement
RUN adduser --disabled-password --gecos '' appuser
USER appuser

ADD ./* ./
ADD . ./

EXPOSE 8000

22 changes: 14 additions & 8 deletions src/backend/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,25 @@
from uuid import uuid4
from email_validator import validate_email, EmailNotValidError
from casbin import Enforcer
from casbin_sqlalchemy_adapter import Adapter
from sqlalchemy import create_engine

log = logging.getLogger(__name__)

log.info('Reading DB password...')

log.info('Read DB password')

MODEL_PATH = "auth/model.conf"
DB_URL = f"postgresql+psycopg://casbin_login:{os.environ['CASBIN_LOGIN_PASS']}@db:5432/library"
engine = create_engine(DB_URL)
adapter = Adapter(engine)
enforcer = Enforcer(MODEL_PATH, adapter)

class APIException(Exception):
pass

def sendSQLCommand(command, userID, table, verified = True, fetch = 1): # NO USER INPUT SHOULD BE SENT DIRECTLY HERE
def sendSQLCommand(command, UUID, table, verified = True, fetch = 1): # NO USER INPUT SHOULD BE SENT DIRECTLY HERE
verb = command.strip().split()[0].upper()
action_map = {
"SELECT": "read",
Expand All @@ -39,7 +47,7 @@ def sendSQLCommand(command, userID, table, verified = True, fetch = 1): # NO USE
"DELETE": "delete", #@HippoProgrammer Please update this as I know not much SQL
}
action = action_map.get(verb)
if Enforcer.enforce(userID, table, "*", action, verified):
if Enforcer.enforce(UUID, table, "*", action, verified):
log.debug("User is authorized to perform this action")
log.info('Connecting to postgres DB...')
with psycopg.connect(f"postgres://library:{str(os.environ['DB_PASS'])}@db:5432/library") as conn: # create a connection to the db
Expand Down Expand Up @@ -100,9 +108,9 @@ def __init__(self, forename: str, surname: str, student_id: int, email: str, rol
def SQLStore(self):
try:
sendSQLCommand(
command="INSERT INTO users (id, forename, surname, student_id, email, role) VALUES (%s, %s, %s, %s, %s, %s)",
params=(self.uuid, self.forename, self.surname, self.student_id, self.email, self.role),
userID='admin', # Needs to updated later on
command="INSERT INTO users (id, forename, surname, student_id, email) VALUES (%s, %s, %s, %s, %s)",
params=(self.uuid, self.forename, self.surname, self.student_id, self.email),
UUID=0, # Ummm, is this correct @HippoProgrammer
table='users',
verified=True,
fetch=0
Expand All @@ -111,9 +119,7 @@ def SQLStore(self):
log.error(f"Failed to store user {self.student_id} in database: {e}")
def addToCasbin(self):
try:
enforcer = Enforcer("model.conf", "policy.csv")
enforcer.add_policy("user", self.uuid, "read", "book")
enforcer.add_grouping_policy(self.uuid, "group", self.role)
enforcer.add_grouping_policy(self.uuid, self.role)
enforcer.save_policy()
except Exception as e:
log.error(f"Failed to add user {self.uuid} to Casbin: {e}")
Expand Down