Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[flake8]
max-line-length = 88
# E203/W503 — conflicts with black's formatting style
# E501 — line length enforced by black instead
# E266 — block comment style (## allowed)
# F841 — local variable assigned but never used
extend-ignore = E203, W503, E501, E266, F841
exclude =
.git,
__pycache__,
migrations,
venv,
staticfiles,
.pre-commit-config.yaml
71 changes: 71 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: CI

on:
push:
branches: ["**"]
pull_request:
branches: ["**"]

jobs:
pre-commit:
name: pre-commit checks
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Cache pre-commit environments
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}

- name: Install pre-commit
run: pip install pre-commit

- name: Run pre-commit
run: pre-commit run --all-files

test:
name: Django tests
runs-on: ubuntu-latest

env:
SECRET_KEY: ci-secret-key-not-for-production
DEBUG: "True"
EMAIL_BACKEND: django.core.mail.backends.console.EmailBackend
EMAIL_HOST: localhost
EMAIL_PORT: "25"
EMAIL_USE_TLS: "False"
EMAIL_HOST_USER: ""
EMAIL_HOST_PASSWORD: ""
EMAIL_FROM_ADDRESS: ci@example.com

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ hashFiles('requirements.txt') }}
restore-keys: pip-

- name: Install dependencies
run: pip install -r requirements.txt

- name: Run migrations
run: python manage.py migrate --no-input

- name: Run tests
run: python manage.py test --verbosity=2
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
repos:
- repo: https://github.com/psf/black
rev: 22.12.0
hooks:
- id: black
language_version: python3

- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile", "black"]

- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
2 changes: 2 additions & 0 deletions Procfile.tailwind
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
django: python manage.py runserver
tailwind: python manage.py tailwind start
97 changes: 0 additions & 97 deletions README.md

This file was deleted.

31 changes: 0 additions & 31 deletions TODO.md

This file was deleted.

3 changes: 2 additions & 1 deletion accounts/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib import admin
from .models import User, Student, Parent

from .models import Parent, Student, User


class UserAdmin(admin.ModelAdmin):
Expand Down
1 change: 1 addition & 0 deletions accounts/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class AccountsConfig(AppConfig):

def ready(self) -> None:
from django.db.models.signals import post_save

from .models import User
from .signals import post_save_account_receiver

Expand Down
29 changes: 29 additions & 0 deletions accounts/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Custom JWT authentication using httpOnly cookies for better security
"""
from django.conf import settings
from rest_framework_simplejwt.authentication import JWTAuthentication


class JWTCookieAuthentication(JWTAuthentication):
"""
Custom authentication class that reads JWT from httpOnly cookies
instead of Authorization header
"""

def authenticate(self, request):
# Try to get token from cookie first
raw_token = request.COOKIES.get(settings.SIMPLE_JWT_COOKIE_NAME)

# If no cookie, fall back to header (for backwards compatibility during migration)
if raw_token is None:
header = self.get_header(request)
if header is None:
return None
raw_token = self.get_raw_token(header)

if raw_token is None:
return None

validated_token = self.get_validated_token(raw_token)
return self.get_user(validated_token), validated_token
5 changes: 3 additions & 2 deletions accounts/filters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db.models import Q
import django_filters
from .models import User, Student
from django.db.models import Q

from .models import Student, User


class LecturerFilter(django_filters.FilterSet):
Expand Down
11 changes: 6 additions & 5 deletions accounts/forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from course.models import Program
from django import forms
from django.db import transaction
from django.contrib.auth.forms import (
UserCreationForm,
PasswordResetForm,
UserChangeForm,
UserCreationForm,
)
from django.contrib.auth.forms import PasswordResetForm
from course.models import Program
from .models import User, Student, Parent, RELATION_SHIP, LEVEL, GENDERS
from django.db import transaction

from .models import GENDERS, LEVEL, RELATION_SHIP, Parent, Student, User


class StaffAddForm(UserCreationForm):
Expand Down
Loading