From 825467c3c6f4b7ad78fd329e7f59a30e265b4a8d Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 12:20:27 -0400 Subject: [PATCH 01/11] Update requirements --- requirements.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9628066..dcfad91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,14 @@ -Babel~=2.6.0 -Flask~=1.1.1 -flask_httpauth~=3.3.0 -Flask_limiter~=1.1.0 -Flask-SQLAlchemy~=2.3.2 -google-api-python-client>=1.7.11 -google-auth-httplib2~=0.0.3 -google-auth-oauthlib~=0.4.1 -gunicorn~=19.9.0 +Babel~=2.17.0 +Flask~=3.1.2 +flask_httpauth~=4.8.0 +Flask_limiter~=3.13 +Flask-SQLAlchemy~=3.1.1 +google-api-python-client>=2.181 +google-auth-httplib2~=0.2.0 +google-auth-oauthlib~=1.2.2 +gunicorn~=23.0.0 oauth2client~=4.1.3 -profanityfilter~=2.0.4 +profanityfilter~=2.1.0 python-dateutil~=2.6.1 -sentry-sdk[flask]~=0.13.2 -SQLAlchemy~=1.3.7 \ No newline at end of file +sentry-sdk[flask]~=2.38.0 +SQLAlchemy~=2.0.43 \ No newline at end of file From f1063b9b6f9ecd3cc3e14915cdccfda4c1df7419 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 12:21:49 -0400 Subject: [PATCH 02/11] Make app run with updated dependencies --- jumpstart/__init__.py | 64 ++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/jumpstart/__init__.py b/jumpstart/__init__.py index 64ce147..ae016a1 100644 --- a/jumpstart/__init__.py +++ b/jumpstart/__init__.py @@ -39,34 +39,41 @@ integrations = [FlaskIntegration()] ) -App = Flask(__name__) +app = Flask(__name__) auth = HTTPTokenAuth(scheme='Token') api_keys = os.environ.get('JUMPSTART_API_KEYS') tokens = api_keys.split(',') if api_keys else [] -App.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True -App.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' -db = SQLAlchemy(App) + +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' + +db = SQLAlchemy(app) from jumpstart.models import File, Ann if not os.path.exists(os.path.join(os.getcwd(), "site.db")): - db.create_all() - -# Initializes the database for Files -file = File(title="Jumpstart.exe") -db.session.query(File).delete() -db.session.commit() -db.session.add(file) -db.session.commit() - -# Initializes the database for Announcements -ann = Ann(title="Have a great day!") -db.session.query(Ann).delete() -db.session.commit() -db.session.add(ann) -db.session.commit() + with app.app_context(): + db.create_all() + +# Prepare database +# geese: If the database is cleared every boot, +# why can't it just be a damn variable? +with app.app_context(): + # Initializes the database for Files + file = File(title="Jumpstart.exe") + db.session.query(File).delete() + db.session.commit() + db.session.add(file) + db.session.commit() + + # Initializes the database for Announcements + ann = Ann(title="Have a great day!") + db.session.query(Ann).delete() + db.session.commit() + db.session.add(ann) + db.session.commit() @auth.verify_token def verify_token(token): @@ -77,8 +84,8 @@ def verify_token(token): limiter = Limiter( - App, - key_func=get_remote_address, + get_remote_address, + app=app, default_limits=["13 per minute", "1 per second"], ) @@ -86,11 +93,12 @@ def verify_token(token): def ip_whitelist(): return request.remote_addr == "127.0.0.1" -@App.route('/') + +@app.route('/') def index(): return render_template('index.html') -@App.route('/calendar', methods=['GET']) +@app.route('/calendar', methods=['GET']) @limiter.limit("3/minute") @limiter.limit("1/second") def calendar(): @@ -136,7 +144,7 @@ def calendar(): event_list = {'data': final_events} return jsonify(event_list) -@App.route('/get-announcement', methods=['GET']) +@app.route('/get-announcement', methods=['GET']) @limiter.limit("13/minute") @limiter.limit("1/second") def get_announcement(): @@ -144,7 +152,7 @@ def get_announcement(): announcement_post = {'data' : str(ann)} return jsonify(announcement_post) -@App.route("/update-announcement", methods=["POST"]) +@app.route("/update-announcement", methods=["POST"]) @auth.login_required @limiter.limit("3/hour") @limiter.limit("2/minute") @@ -157,7 +165,7 @@ def update_announcement(): db.session.commit() return "Announcement Updated" -@App.route('/get-harold', methods=['GET']) +@app.route('/get-harold', methods=['GET']) @limiter.limit("13/minute") @limiter.limit("1/second") def get_harold(): @@ -165,7 +173,7 @@ def get_harold(): filename = {'data': str(file)} return jsonify(filename) -@App.route("/update-harold", methods=["POST"]) +@app.route("/update-harold", methods=["POST"]) @auth.login_required def update_harold(): req_data = request.get_json() @@ -178,7 +186,7 @@ def update_harold(): if __name__ == '__main__': App.run(debug=True) -@App.route('/showerthoughts', methods=['GET']) +@app.route('/showerthoughts', methods=['GET']) @limiter.limit("3/minute") @limiter.limit("1/second") def showerthoughts(): From 6c5725c90f8078ef8ac930c1dbc6bb3eaa3045b7 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 12:49:29 -0400 Subject: [PATCH 03/11] update readme --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8a4f4a5..538f23f 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,15 @@ A graphical interface that runs on a RPI in the lobby of my dorm. This project uses [Python](http://nodejs.org), [Flask](https://npmjs.com), SQL, HTML/CSS, and Javascript. 1. Download the zip file and open the code. -2. Navigate into the folder. +2. Navigate into the root folder. 3. Run `pip install -r requirements.txt` -4. Run `flask run` -5. DM @drno in CSH slack, or email for secrets package +4. Navigate into `jumpstart` folder. +6. Ask opcomm for secrets - The secrets package follows the directory structure: - src/ + jumpstart/ secrets/ client_secrets.json +5. Run `flask --app . run` 6. Results ## Usage From 0ef5c47820ede713625b27a87c9ee2e8befe8346 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 12:53:22 -0400 Subject: [PATCH 04/11] Add env variables --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 538f23f..bd74764 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,14 @@ This project uses [Python](http://nodejs.org), [Flask](https://npmjs.com), SQL, 5. Run `flask --app . run` 6. Results +Jumpstart expects the following environment variables to be defined: +``` +FLASK_APP=jumpstart:App +JUMPSTART_API_KEYS=KEYS +TZ=TIMEZONE +SENTRY_DSN=LINK +``` + ## Usage Go [here](https://jumpstart.csh.rit.edu) From 04fb015ca856feb8824549c5837ce74f080ff9d6 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 13:43:05 -0400 Subject: [PATCH 05/11] docker --- dockerfile | 15 ++++++ dockerignore | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 dockerfile create mode 100644 dockerignore diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..2f35b21 --- /dev/null +++ b/dockerfile @@ -0,0 +1,15 @@ +FROM python:3.13 +WORKDIR /usr/local/jumpstart + +COPY . . +RUN pip install --no-cache-dir -r requirements.txt + +EXPOSE 5000 + +RUN useradd jumpstart +RUN chown jumpstart /usr/local/jumpstart +RUN mkdir -p /usr/local/var +RUN chown jumpstart:jumpstart /usr/local/var +USER jumpstart + +CMD ["flask", "--app", "jumpstart", "run"] \ No newline at end of file diff --git a/dockerignore b/dockerignore new file mode 100644 index 0000000..34e7ff6 --- /dev/null +++ b/dockerignore @@ -0,0 +1,141 @@ +# Created by https://www.gitignore.io/api/macos,python +# Edit at https://www.gitignore.io/?templates=macos,python + +# APPLICATION +site.db +/secrets + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# End of https://www.gitignore.io/api/macos,python From ab87ddd24b2adf7f33e9b60f231466655214581d Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 13:43:30 -0400 Subject: [PATCH 06/11] correct filename --- dockerignore => .dockerignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dockerignore => .dockerignore (100%) diff --git a/dockerignore b/.dockerignore similarity index 100% rename from dockerignore rename to .dockerignore From e4fc366d105b1608eabd859f6ceac8371f56431d Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 13:51:27 -0400 Subject: [PATCH 07/11] update dateutil --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index dcfad91..b66216e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ google-auth-oauthlib~=1.2.2 gunicorn~=23.0.0 oauth2client~=4.1.3 profanityfilter~=2.1.0 -python-dateutil~=2.6.1 +python-dateutil~=2.9.0.post0 sentry-sdk[flask]~=2.38.0 -SQLAlchemy~=2.0.43 \ No newline at end of file +SQLAlchemy~=2.0.43 +pytz~=2025.2 \ No newline at end of file From 5c352dfe5455c04f072615ed90208b1ecd1dfe8c Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 13:55:32 -0400 Subject: [PATCH 08/11] add docker docs --- README.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bd74764..c4fd63b 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,14 @@ A graphical interface that runs on a RPI in the lobby of my dorm. This project uses [Python](http://nodejs.org), [Flask](https://npmjs.com), SQL, HTML/CSS, and Javascript. 1. Download the zip file and open the code. -2. Navigate into the root folder. +2. Navigate into the project's folder. 3. Run `pip install -r requirements.txt` -4. Navigate into `jumpstart` folder. 6. Ask opcomm for secrets - The secrets package follows the directory structure: - jumpstart/ + src/ secrets/ client_secrets.json -5. Run `flask --app . run` +5. Run `flask --app jumpstart run` 6. Results Jumpstart expects the following environment variables to be defined: @@ -28,6 +27,22 @@ JUMPSTART_API_KEYS=KEYS TZ=TIMEZONE SENTRY_DSN=LINK ``` +## Docker + +1. Ensure you are in the project root, then build the image locally with `docker built -t jumpstart .` +2. Run with the following: (Be sure to update env variables) +``` +docker run \ + -e FLASK_RUN_HOST=0.0.0.0 \ + -e FLASK_APP=jumpstart:App \ + -e JUMPSTART_API_KEYS=KEYS \ + -e TZ=America/New_York \ + -e SENTRY_DSN=LINK \ + -v ./secrets:/usr/local/jumpstart/secrets \ + -p 5000:5000 \ + jumpstart +``` + ## Usage From dca2274a7415bdfeb817581b333af2dc4ee56bc7 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 14:31:46 -0400 Subject: [PATCH 09/11] Only copy needed files, remove dockerignore --- .dockerignore | 141 -------------------------------------------------- dockerfile | 4 +- 2 files changed, 3 insertions(+), 142 deletions(-) delete mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 34e7ff6..0000000 --- a/.dockerignore +++ /dev/null @@ -1,141 +0,0 @@ -# Created by https://www.gitignore.io/api/macos,python -# Edit at https://www.gitignore.io/?templates=macos,python - -# APPLICATION -site.db -/secrets - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# End of https://www.gitignore.io/api/macos,python diff --git a/dockerfile b/dockerfile index 2f35b21..251cbaf 100644 --- a/dockerfile +++ b/dockerfile @@ -1,9 +1,11 @@ FROM python:3.13 WORKDIR /usr/local/jumpstart -COPY . . +COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt +COPY jumpstart jumpstart + EXPOSE 5000 RUN useradd jumpstart From 440fdadc354908999c5641a9359c428d8270cbf2 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 14:36:25 -0400 Subject: [PATCH 10/11] Clarify install instructions --- README.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c4fd63b..80bd18f 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,22 @@ # Jumpstart -## Author: Beckett Jenen -[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) +A graphical interface that displays important information at the entrance of CSH. -A graphical interface that runs on a RPI in the lobby of my dorm. +See it live [here](https://jumpstart.csh.rit.edu)! ## Install This project uses [Python](http://nodejs.org), [Flask](https://npmjs.com), SQL, HTML/CSS, and Javascript. -1. Download the zip file and open the code. -2. Navigate into the project's folder. -3. Run `pip install -r requirements.txt` -6. Ask opcomm for secrets +1. Clone and cd into the repo: `git clone https://github.com/ComputerScienceHouse/Jumpstart` +2. Run `pip install -r requirements.txt` +3. Ask opcomm for secrets - The secrets package follows the directory structure: src/ secrets/ client_secrets.json -5. Run `flask --app jumpstart run` -6. Results +4. Run `flask --app jumpstart run` +5. Results Jumpstart expects the following environment variables to be defined: ``` @@ -41,9 +39,4 @@ docker run \ -v ./secrets:/usr/local/jumpstart/secrets \ -p 5000:5000 \ jumpstart -``` - - -## Usage - -Go [here](https://jumpstart.csh.rit.edu) +``` \ No newline at end of file From b8705632ea76867d5523134def54abe0e4716d23 Mon Sep 17 00:00:00 2001 From: goosenotduck Date: Tue, 16 Sep 2025 16:57:39 -0400 Subject: [PATCH 11/11] Make dockerfile production ready --- README.md | 1 + dockerfile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 80bd18f..7a86370 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ docker run \ -e JUMPSTART_API_KEYS=KEYS \ -e TZ=America/New_York \ -e SENTRY_DSN=LINK \ + -e GUNICORN_CMD_ARGS="-b=0.0.0.0:5000" \ -v ./secrets:/usr/local/jumpstart/secrets \ -p 5000:5000 \ jumpstart diff --git a/dockerfile b/dockerfile index 251cbaf..5174dad 100644 --- a/dockerfile +++ b/dockerfile @@ -14,4 +14,4 @@ RUN mkdir -p /usr/local/var RUN chown jumpstart:jumpstart /usr/local/var USER jumpstart -CMD ["flask", "--app", "jumpstart", "run"] \ No newline at end of file +CMD ["gunicorn", "jumpstart:app"] \ No newline at end of file