computer-science-club

computer-science-club
git clone https://git.prime8.dev/computer-science-club.git
Log | Files | Refs | README | LICENSE

commit e3b4fbdebec9462f7f468c876f7502c0de2b56b2
parent aafc0a115249f47840e276f853454d13bb0cf467
Author: Damian Myrda <damian@prime8.dev>
Date:   Wed, 18 Feb 2026 14:42:48 -0600

Fix critical bugs and security issues

- Fix Python 3 relative imports in models/__init__.py
- Fix Jinja2 macro call in events.html template
- Fix authors parsing in add_project route (comma-separated)
- Replace insecure pickle with JSON in database
- Use secure random SECRET_KEY instead of DOMAIN
- Only allow insecure OAuth transport in development mode
- Update README with new environment variables

Diffstat:
MREADME.md | 16+++++++++-------
Mdatabase.py | 6+++---
Mmain.py | 13+++++++------
Mmodels/__init__.py | 12++++++------
Mtemplates/elements/events.html | 2+-
5 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md @@ -10,13 +10,15 @@ A website for Computer Science Club made during a mini-hackathon. The following environment variables are required: -| Variable | Description | -|----------|-------------| -| `DOMAIN` | The URL where this app is hosted | -| `GROUP_ID` | Schoology group ID (found in the URL after `/group/`) | -| `SCHOOLOGY_DOMAIN` | Your Schoology instance domain (e.g., `schoology.example.com`) | -| `SCHOOLOGY_API_KEY` | Schoology API key | -| `SCHOOLOGY_API_SECRET` | Schoology API secret | +| Variable | Description | Required | +|----------|-------------|----------| +| `DOMAIN` | The URL where this app is hosted | Yes | +| `SECRET_KEY` | Flask session secret key (auto-generated if not set) | No | +| `GROUP_ID` | Schoology group ID (found in the URL after `/group/`) | Yes | +| `SCHOOLOGY_DOMAIN` | Your Schoology instance domain (e.g., `schoology.example.com`) | Yes | +| `SCHOOLOGY_API_KEY` | Schoology API key | Yes | +| `SCHOOLOGY_API_SECRET` | Schoology API secret | Yes | +| `FLASK_ENV` | Set to `development` to allow HTTP OAuth (insecure) | No | ### Schoology diff --git a/database.py b/database.py @@ -1,6 +1,6 @@ from models import Project import sqlite3 -import pickle +import json class Database: @@ -29,7 +29,7 @@ class Database: for data in self.cursor.fetchall(): name = data[0] description = data[1] - authors = pickle.loads(data[2]) + authors = json.loads(data[2]) source = data[3] project = Project(name, description, authors, source) self.projects.append(project) @@ -43,7 +43,7 @@ class Database: data = ( project.name, project.description, - pickle.dumps(project.authors), + json.dumps(project.authors), project.source, ) self.cursor.execute("INSERT INTO projects VALUES (?, ?, ?, ?)", data) diff --git a/main.py b/main.py @@ -12,8 +12,10 @@ from schoology import group from flask import Flask, request, redirect, abort, render_template, session from cachecontrol import CacheControl +import secrets + app = Flask(__name__) -app.secret_key = DOMAIN +app.secret_key = os.environ.get("SECRET_KEY", secrets.token_hex(32)) @app.route("/") @@ -53,13 +55,11 @@ def add_project(): description = request.form["description"].rstrip() if description == "": description = None - authors = request.form["authors"] - for author in authors: - author = author.rstrip() + authors = [a.strip() for a in request.form["authors"].split(",") if a.strip()] source = request.form["source"].rstrip() if source == "": source = None - project = Project(name, description, [authors], source) + project = Project(name, description, authors, source) database.add(project) return redirect("/projects") return render_template( @@ -88,7 +88,8 @@ GOOGLE_AUTH_SCOPES = [ "https://www.googleapis.com/auth/userinfo.email", "openid", ] -os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" +if os.environ.get("FLASK_ENV") == "development": + os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" flow = Flow.from_client_secrets_file( client_secrets_file=GOOGLE_CLIENT_SECRETS_FILE, diff --git a/models/__init__.py b/models/__init__.py @@ -1,6 +1,6 @@ -from discussion import Discussion -from event import Event -from group import Group -from member import Member -from project import Project -from update import Update +from .discussion import Discussion +from .event import Event +from .group import Group +from .member import Member +from .project import Project +from .update import Update diff --git a/templates/elements/events.html b/templates/elements/events.html @@ -18,6 +18,6 @@ {% macro upcoming(events) -%} {% for event in events %} -<div>view(event)</div> +<div>{{ view(event) }}</div> {% endfor %} {%- endmacro %}