Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6cd8171
fix: change session ID to be generated from 32 bytes of entropy
jbriones1 Jul 1, 2026
8edfeda
fix: remove site profile pics
jbriones1 Jul 1, 2026
10b88a4
feat: rewrite login
jbriones1 Jul 1, 2026
add95fb
feat: environment variable support
jbriones1 Jul 1, 2026
b85e9de
fix: make logout idempotent
jbriones1 Jul 1, 2026
b47e819
refactor: change the variables of create_user_session
jbriones1 Jul 1, 2026
d882d0f
feat: creating a user session now uses upserts
jbriones1 Jul 1, 2026
1586c88
fix: cookie wouldn't be delete if the domain was set
jbriones1 Jul 1, 2026
b8caf2a
feat: improve auth login handling
jbriones1 Jul 1, 2026
de0d450
fix: let client handle post authentication
jbriones1 Jul 1, 2026
55607ac
fix: status codes in auth module
jbriones1 Jul 1, 2026
3c8c895
fix: no session provided still deleted the cookie
jbriones1 Jul 1, 2026
44dd222
feat(cookie): add MAX-AGE of 2 hours
jbriones1 Jul 2, 2026
33e8112
fix: removed unused import
jbriones1 Jul 2, 2026
ad11d75
fix: made session expiration consistently 2 hours
jbriones1 Jul 2, 2026
97d85e2
feat: remove 401 from logout if user is missing the session cookie
jbriones1 Jul 2, 2026
6a4fa59
fix: expired sessions were still usable
jbriones1 Jul 2, 2026
f14fc84
fix: added the missing status code to /auth/login
jbriones1 Jul 2, 2026
a14534d
fix: frontend origin removed from /auth/login
jbriones1 Jul 2, 2026
2bc4a56
chore: move .env to root
jbriones1 Jul 2, 2026
a4d1c54
chore: removed some dead code
jbriones1 Jul 2, 2026
f74b369
feat: add auth tests and update pytest config
jbriones1 Jul 2, 2026
8b84bc1
ci: update workflows to use uv and fix env vars
jbriones1 Jul 2, 2026
f6ff060
fix: `.env` in root can be in sub-directories
jbriones1 Jul 3, 2026
7e84d34
fix: test runner failure due to date difference
jbriones1 Jul 3, 2026
a3e35fa
fix: database setup does not respect the app settings
jbriones1 Jul 3, 2026
961f907
feat: update alembic heads
jbriones1 Jul 29, 2026
d6353a1
feat: moved database connection step outside the main file
jbriones1 Jul 29, 2026
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
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Required
# Supports `dev`, `prod`, or `test`
ENVIRONMENT=dev
DB_PORT=5444

# Authentication
COOKIE_SECURE=false
AUTH_URL=https://cas.sfu.ca/cas/serviceValidate

# Redirect after authentication
FRONTEND_ORIGIN=http://localhost:8080
32 changes: 18 additions & 14 deletions .github/workflows/alembic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ on: pull_request
jobs:
alembic_upgrade_head:
runs-on: ubuntu-latest
env:
ENVIRONMENT: dev
DB_PORT: "5432"
COOKIE_SECURE: "false"
FRONTEND_ORIGIN: http://localhost:8080

services:
postgres:
Expand Down Expand Up @@ -32,19 +37,18 @@ jobs:
sleep 1
done

- uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Install Python
run: uv python install 3.13

- name: Install dependencies
run: |
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.13 python3.13-venv
python3.13 -m pip install --upgrade pip
python3.13 -m venv venv
source ./venv/bin/activate
pip install .

# This will fail if there are divergent heads and alembic gets confused;
# e.g., un-sanitarily merging main into a dev branch.
run: uv sync --locked

# This will fail if there are divergent heads and alembic gets confused
# e.g. merging into main without passing this check
- name: Run alembic upgrade head
run: |
source ./venv/bin/activate
cd src
alembic upgrade head
working-directory: src
run: uv run alembic upgrade head
11 changes: 7 additions & 4 deletions .github/workflows/pytest_unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ jobs:
unit_tests:
runs-on: ubuntu-latest
timeout-minutes: 5
env:
ENVIRONMENT: test
COOKIE_SECURE: "false"
FRONTEND_ORIGIN: http://localhost:8080

steps:
- uses: actions/checkout@v6

- uses: actions/setup-python@v6
with:
python-version: '3.13'

- uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Install Python
run: uv python install 3.13

- name: Install dependencies
run: uv sync --extra test --locked

Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/ruff-action@v3

- uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Install Python
run: uv python install 3.13

- name: Install dependencies
run: uv sync --extra dev --locked

- name: Run Ruff
run: uv run ruff check .
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,27 @@ pip install ".[dev, test]" # or: uv sync --all-extras
```

5. Follow the database setup instructions on the [wiki](https://github.com/CSSS/csss-site-backend/wiki/1.-Local-Setup#database-setup). The recommended way is to do it through Docker, but both should work.
6. You will need to set the following environment variables
6. You will need to set the following environment variables set
```bash
export DB_PORT=5444 # If you're using Docker
export LOCAL=true # Should be true if you're running this locally
DB_PORT=5444 # If you're using Docker
ENVIRONMENT=dev # Set this to `test` if you want to use the test database instead
```
You can also create a `.env` file and set those in there. See `.env.example` for more information.


## Important Directories

- `config/` configuration files for the server machine
- `src/`
- `alembic` for database migrations
- `access/` for controlling officer access to the google drive, bitwarden, and github. TODO: discord as well?
- `blog/` for running an editable csss-blog
- `dashboard/` for controlling the server, website, jobs, and access to services & stuff.
- `elections/` for the mangement of current elections & past elections
- `jobs/` for cronjobs that run regularly on the server
- `misc/` for anything that can't be easily categorized or is very small
- `officers/` for officer contact information + photos
- `test/` for html pages which interact with the backend's local api
- `alembic` database migrations
- `auth/` controlling authentication and sessions
- `candidates/` management of those who run in large elections
- `elections/` mangement of current elections & past elections
- `event/` management of events
- `nominees/` management of nominees to large elections
- `officers/` management of officer information and terms
- `translink/` management of TransLink REST API
- `test/` unit and integration tests

## Developer Tools

Expand Down
18 changes: 13 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,22 @@ Homepage = "https://api.sfucsss.org/"
# Pytest: Test framework
[tool.pytest.ini_options]
pythonpath = ["src"]
testpaths = ["tests"]
norecursedirs = ["tests/wip"] # Don't test these paths
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
asyncio_default_test_loop_scope = "function"
log_cli = true
log_cli_level = "INFO"
testpaths = [
"tests",
addopts = [
"--strict-markers",
"--strict-config",
"--tb=short"
]
markers = [
"integration: tests that require database or full app setup",
"unit: isolated tests that do not require external services"
]
norecursedirs = "tests/wip"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"

# Ruff: Formatter and linter
[tool.ruff]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""change session ID to be 32 bytes of base64

Revision ID: 060623cf940f
Revises: f0c99d0db277
Create Date: 2026-07-01 01:17:28.430756

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

from constants import SESSION_ID_LEN


# revision identifiers, used by Alembic.
revision: str = '060623cf940f'
down_revision: Union[str, None] = '3c00f28c26e2'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('user_session', 'session_id',
existing_type=sa.VARCHAR(length=512),
type_=sa.String(length=SESSION_ID_LEN),
existing_nullable=False)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('user_session', 'session_id',
existing_type=sa.String(length=SESSION_ID_LEN),
type_=sa.VARCHAR(length=512),
existing_nullable=False)
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""

from collections.abc import Sequence
from typing import Union

import sqlalchemy as sa

Expand Down
30 changes: 30 additions & 0 deletions src/alembic/versions/caa26d56d842_remove_site_profile_pics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""remove site profile pics

Revision ID: caa26d56d842
Revises: 060623cf940f
Create Date: 2026-07-01 02:01:26.412179

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'caa26d56d842'
down_revision: Union[str, None] = '060623cf940f'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("site_user", "profile_picture_url")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("site_user", sa.Column("profile_picture_url", sa.TEXT(), autoincrement=False, nullable=True))
# ### end Alembic commands ###
1 change: 0 additions & 1 deletion src/auth/__init__.py

This file was deleted.

5 changes: 5 additions & 0 deletions src/auth/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from datetime import timedelta

COOKIE_SESSION_KEY = "session_id"
COOKIE_MAX_AGE = 60 * 60 * 2 # 2 hours in seconds
SESSION_MAX_AGE = timedelta(seconds=COOKIE_MAX_AGE)
Loading
Loading