Skip to content

Merge dev#6

Closed
dburcat wants to merge 64 commits intoZCW-Spring26:mainfrom
Circus-Circus-data-7-0:Merge_dev
Closed

Merge dev#6
dburcat wants to merge 64 commits intoZCW-Spring26:mainfrom
Circus-Circus-data-7-0:Merge_dev

Conversation

@dburcat
Copy link
Copy Markdown

@dburcat dburcat commented Apr 10, 2026

merging in reactions, post updates, and simplified config file

Copilot AI review requested due to automatic review settings April 10, 2026 20:20
@dburcat dburcat closed this Apr 10, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges development work that adds reactions, private posts + file uploads, MySQL-oriented configuration/startup, and splits core functionality into additional blueprints/modules.

Changes:

  • Reworked local startup and configuration to default to MySQL (plus added PyMySQL/cryptography dependencies).
  • Added new post features: optional file upload, private posts, and reaction buttons on the post view.
  • Introduced new modules/blueprints for posts, subforums, and reactions; added extensive project documentation.

Reviewed changes

Copilot reviewed 24 out of 25 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
run.sh New bootstrap script (venv creation, dependency install, env defaults, server/dev modes).
requirements.txt Adds MySQL driver and crypto dependency for authentication support.
README.md Adds team startup guidance and MySQL migration link (currently with path issues).
PROJECT_FLOW.md New high-level project/runtime flow documentation.
MYSQL_MIGRATION_GUIDE.md New MySQL migration + startup guide (currently inconsistent with code).
CIRCUSCIRCUS_FULL_CODE_GUIDE.md Large onboarding guide for codebase behavior (currently inconsistent with code).
Procfile Removes old gunicorn Procfile entry.
config.py Switches configuration to build a MySQL SQLAlchemy URI; adds upload config fields.
forum/init.py Registers additional blueprints (posts/subforums/reactions) and adjusts imports.
forum/app.py Adds seeding protections, schema-compat “ALTER TABLE add missing columns”, and startup tweaks.
forum/models.py Updates User column types for MySQL compatibility; leaves other models modularized.
forum/routes.py Keeps auth/login routes; comments out routes moved into other modules.
forum/post.py New Post model + routes for posting, viewing, commenting (as replies), uploads, and privacy checks.
forum/subforum.py New Subforum model + routes for browsing, creating, deleting subforums.
forum/Reactions.py New Reaction model + route to toggle reactions.
forum/ignore.py Adds MySQL bootstrap helper functions (currently incomplete/unimportable).
forum/templates/*.html UI updates for private posts, uploads, reactions, admin controls, and minor HTML improvements.
forum/static/style.css Adds CSS classes to replace repeated inline styles.
Comments suppressed due to low confidence (1)

README.md:58

  • README claims the app appears on port 5000, but run.sh defaults PORT to 8000 and forum/app.py runs on 8000 when executed directly. Update the README to match the actual default port (or change the script default to 5000) to avoid confusion.

python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
./run.sh


and it should appear on port 5000

`http://0.0.0.0:5000`

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread forum/user.py
Comment on lines +5 to +18
# Shared SQLAlchemy object used by the app factory and all models.
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

# Database models
class User(UserMixin, db.Model):
# Store account information and ownership of posts/comments.
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
email = db.Column(db.String(255), unique=True, nullable=False)
admin = db.Column(db.Boolean, default=False)
posts = db.relationship("Post", backref="user")
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module defines a new db = SQLAlchemy() and an ORM User model, but the application’s shared db is already defined in forum/models.py. Having a second SQLAlchemy instance/model registry will cause tables/relationships and queries to bind to different metadata/engines. Remove the local db/ORM model from this file and import db/User from forum.models instead (keeping forum/user.py for validation/query helpers only).

Copilot uses AI. Check for mistakes.
Comment thread forum/user.py
Comment on lines 31 to +70
@@ -23,3 +52,63 @@ def username_taken(username):
return User.query.filter(User.username == username).first()
def email_taken(email):
return User.query.filter(User.email == email).first()


##########################################################################
import hashlib
import hmac
import secrets


class User:
def __init__(self, id, username, password, email,
is_admin=False, permissions=None, privacy="public"):

# --- Core Fields ---
self.id = id # Primary Key
self.username = username
self.password_hash = self._hash_password(password)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User is imported from .models (line 31) and then later redefined as a plain Python class (line 63). This overwrites the ORM model, so username_taken()/email_taken() will start referencing the non-ORM User at runtime and crash (User has no .query). Rename/remove the second User class (or move it to a different module/name) so the ORM User stays in scope.

Copilot uses AI. Check for mistakes.
Comment thread forum/subforum.py
Comment on lines +71 to +73
@login_required
@subforum_rt.route('/createsubforum', methods=['GET', 'POST'])
def create_subforum_page():
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decorator order is reversed here: @login_required is applied after @subforum_rt.route, which means the blueprint registers the unprotected function and the login check won’t run. Swap the decorator order so @subforum_rt.route(...) is outermost and @login_required is directly above the function.

Copilot uses AI. Check for mistakes.
Comment thread forum/subforum.py
Comment on lines +125 to +127
@login_required
@subforum_rt.route('/deletesubforum', methods=['POST'])
def delete_subforum():
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same decorator-order issue as above: with @login_required above @subforum_rt.route, the route is registered without authentication. Swap the decorators so the registered view function is the login_required wrapper.

Copilot uses AI. Check for mistakes.
Comment thread forum/subforum.py
Comment on lines +128 to +131
# Only admins can delete subforums.
if not current_user.admin:
return Subforum.error("Only administrators can delete subforums!")

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subforum.error(...) does not exist (there is no error method on the model), so these branches will raise AttributeError. Use the imported error(...) helper (or return a proper Flask response) instead.

Copilot uses AI. Check for mistakes.
Comment thread forum/post.py
Comment on lines +127 to +132
file = request.files.get('upload_file')
filename = None
if file and file.filename:
filename = secure_filename(file.filename)
file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
post = Post(title=title, content=content, postdate=datetime.datetime.now(), upload_file=filename, private=private)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename)) will fail if the upload directory doesn’t exist. Config.UPLOAD_FOLDER points to forum/static/uploads, but that directory is not present in the repo. Ensure the directory is created on startup (e.g., os.makedirs(..., exist_ok=True)) before saving uploads.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +27
{% if post.upload_file %}
{% if post.upload_file.endswith(('.mp4', 'mov', '.webm')) %}
<video controls>
<source src="/uploads/{{ post.upload_file }}">
</video>
{% else %}
<img src="/uploads/{{ post.upload_file }}">
{% endif %}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new image rendering <img src="/uploads/{{ post.upload_file }}"> is missing an alt attribute, which is important for accessibility/screen readers. Add a meaningful alt text (even a generic one like the filename) when rendering uploaded images.

Copilot uses AI. Check for mistakes.
Comment on lines +615 to +618
- Python imports modules.
- config.py executes top-level code.
- check_mysql_and_setup() runs during import.

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guide states that config.py contains and runs MySQL bootstrap helpers (and that check_mysql_and_setup() runs during config import), but in this PR config.py only defines Config and the bootstrap code appears in forum/ignore.py (which currently isn’t imported and is missing required imports). Please update the guide to match the actual bootstrap location/behavior, or move the bootstrap into config.py as described.

Copilot uses AI. Check for mistakes.
Comment thread MYSQL_MIGRATION_GUIDE.md
Comment on lines +65 to +75
### 4. Startup now tries to prepare MySQL automatically

`config.py` now includes startup helpers that:

- try to connect to MySQL as an admin user on the local machine
- create the `ZipChat` database if it is missing
- create the `zipchat_app` user if it is missing
- grant that user access to the database
- verify that the app credentials can connect

This is a best-effort bootstrap. If MySQL admin access is unavailable on a specific machine, the code prints clear instructions instead of failing silently.
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guide claims config.py includes startup helpers and runs MySQL setup checks, but config.py in this PR only builds the DB URI. Either implement the described bootstrap (DB/user creation + connectivity checks) where documented, or update this guide to reflect the current behavior/location (e.g., forum/ignore.py).

Copilot uses AI. Check for mistakes.
Comment thread MYSQL_MIGRATION_GUIDE.md
Comment on lines +55 to +62
We changed the model fields that need uniqueness or fixed sizes:

- `User.username` became a bounded string
- `User.email` became a bounded string
- `User.password_hash` became a bounded string
- `Post.title` became a bounded string
- `Subforum.title` became a bounded string

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The guide says Post.title became a bounded string for MySQL compatibility, but forum/post.py still defines Post.title as db.Text (line 16). Update the guide or the model so they match (especially if you expect schema compatibility across environments).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants