Skip to content

Commit b74142e

Browse files
authored
Update repo + Docker from @goosenotduck (#23)
2 parents 298f442 + b870563 commit b74142e

File tree

4 files changed

+96
-52
lines changed

4 files changed

+96
-52
lines changed

README.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,43 @@
11
# Jumpstart
2-
## Author: Beckett Jenen
32

4-
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
3+
A graphical interface that displays important information at the entrance of CSH.
54

6-
A graphical interface that runs on a RPI in the lobby of my dorm.
5+
See it live [here](https://jumpstart.csh.rit.edu)!
76

87
## Install
98

109
This project uses [Python](http://nodejs.org), [Flask](https://npmjs.com), SQL, HTML/CSS, and Javascript.
1110

12-
1. Download the zip file and open the code.
13-
2. Navigate into the folder.
14-
3. Run `pip install -r requirements.txt`
15-
4. Run `flask run`
16-
5. DM @drno in CSH slack, or email for secrets package
11+
1. Clone and cd into the repo: `git clone https://github.com/ComputerScienceHouse/Jumpstart`
12+
2. Run `pip install -r requirements.txt`
13+
3. Ask opcomm for secrets
1714
- The secrets package follows the directory structure:
1815
src/
1916
secrets/
2017
client_secrets.json
21-
6. Results
18+
4. Run `flask --app jumpstart run`
19+
5. Results
2220

23-
## Usage
21+
Jumpstart expects the following environment variables to be defined:
22+
```
23+
FLASK_APP=jumpstart:App
24+
JUMPSTART_API_KEYS=KEYS
25+
TZ=TIMEZONE
26+
SENTRY_DSN=LINK
27+
```
28+
## Docker
2429

25-
Go [here](https://jumpstart.csh.rit.edu)
30+
1. Ensure you are in the project root, then build the image locally with `docker built -t jumpstart .`
31+
2. Run with the following: (Be sure to update env variables)
32+
```
33+
docker run \
34+
-e FLASK_RUN_HOST=0.0.0.0 \
35+
-e FLASK_APP=jumpstart:App \
36+
-e JUMPSTART_API_KEYS=KEYS \
37+
-e TZ=America/New_York \
38+
-e SENTRY_DSN=LINK \
39+
-e GUNICORN_CMD_ARGS="-b=0.0.0.0:5000" \
40+
-v ./secrets:/usr/local/jumpstart/secrets \
41+
-p 5000:5000 \
42+
jumpstart
43+
```

dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM python:3.13
2+
WORKDIR /usr/local/jumpstart
3+
4+
COPY requirements.txt .
5+
RUN pip install --no-cache-dir -r requirements.txt
6+
7+
COPY jumpstart jumpstart
8+
9+
EXPOSE 5000
10+
11+
RUN useradd jumpstart
12+
RUN chown jumpstart /usr/local/jumpstart
13+
RUN mkdir -p /usr/local/var
14+
RUN chown jumpstart:jumpstart /usr/local/var
15+
USER jumpstart
16+
17+
CMD ["gunicorn", "jumpstart:app"]

jumpstart/__init__.py

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,41 @@
3939
integrations = [FlaskIntegration()]
4040
)
4141

42-
App = Flask(__name__)
42+
app = Flask(__name__)
4343

4444
auth = HTTPTokenAuth(scheme='Token')
4545
api_keys = os.environ.get('JUMPSTART_API_KEYS')
4646

4747
tokens = api_keys.split(',') if api_keys else []
48-
App.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
49-
App.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
50-
db = SQLAlchemy(App)
48+
49+
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
50+
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
51+
52+
db = SQLAlchemy(app)
5153

5254
from jumpstart.models import File, Ann
5355

5456
if not os.path.exists(os.path.join(os.getcwd(), "site.db")):
55-
db.create_all()
56-
57-
# Initializes the database for Files
58-
file = File(title="Jumpstart.exe")
59-
db.session.query(File).delete()
60-
db.session.commit()
61-
db.session.add(file)
62-
db.session.commit()
63-
64-
# Initializes the database for Announcements
65-
ann = Ann(title="Have a great day!")
66-
db.session.query(Ann).delete()
67-
db.session.commit()
68-
db.session.add(ann)
69-
db.session.commit()
57+
with app.app_context():
58+
db.create_all()
59+
60+
# Prepare database
61+
# geese: If the database is cleared every boot,
62+
# why can't it just be a damn variable?
63+
with app.app_context():
64+
# Initializes the database for Files
65+
file = File(title="Jumpstart.exe")
66+
db.session.query(File).delete()
67+
db.session.commit()
68+
db.session.add(file)
69+
db.session.commit()
70+
71+
# Initializes the database for Announcements
72+
ann = Ann(title="Have a great day!")
73+
db.session.query(Ann).delete()
74+
db.session.commit()
75+
db.session.add(ann)
76+
db.session.commit()
7077

7178
@auth.verify_token
7279
def verify_token(token):
@@ -77,20 +84,21 @@ def verify_token(token):
7784

7885

7986
limiter = Limiter(
80-
App,
81-
key_func=get_remote_address,
87+
get_remote_address,
88+
app=app,
8289
default_limits=["13 per minute", "1 per second"],
8390
)
8491

8592
@limiter.request_filter
8693
def ip_whitelist():
8794
return request.remote_addr == "127.0.0.1"
8895

89-
@App.route('/')
96+
97+
@app.route('/')
9098
def index():
9199
return render_template('index.html')
92100

93-
@App.route('/calendar', methods=['GET'])
101+
@app.route('/calendar', methods=['GET'])
94102
@limiter.limit("3/minute")
95103
@limiter.limit("1/second")
96104
def calendar():
@@ -136,15 +144,15 @@ def calendar():
136144
event_list = {'data': final_events}
137145
return jsonify(event_list)
138146

139-
@App.route('/get-announcement', methods=['GET'])
147+
@app.route('/get-announcement', methods=['GET'])
140148
@limiter.limit("13/minute")
141149
@limiter.limit("1/second")
142150
def get_announcement():
143151
ann = Ann.query.first()
144152
announcement_post = {'data' : str(ann)}
145153
return jsonify(announcement_post)
146154

147-
@App.route("/update-announcement", methods=["POST"])
155+
@app.route("/update-announcement", methods=["POST"])
148156
@auth.login_required
149157
@limiter.limit("3/hour")
150158
@limiter.limit("2/minute")
@@ -157,15 +165,15 @@ def update_announcement():
157165
db.session.commit()
158166
return "Announcement Updated"
159167

160-
@App.route('/get-harold', methods=['GET'])
168+
@app.route('/get-harold', methods=['GET'])
161169
@limiter.limit("13/minute")
162170
@limiter.limit("1/second")
163171
def get_harold():
164172
file = File.query.first()
165173
filename = {'data': str(file)}
166174
return jsonify(filename)
167175

168-
@App.route("/update-harold", methods=["POST"])
176+
@app.route("/update-harold", methods=["POST"])
169177
@auth.login_required
170178
def update_harold():
171179
req_data = request.get_json()
@@ -178,7 +186,7 @@ def update_harold():
178186
if __name__ == '__main__':
179187
App.run(debug=True)
180188

181-
@App.route('/showerthoughts', methods=['GET'])
189+
@app.route('/showerthoughts', methods=['GET'])
182190
@limiter.limit("3/minute")
183191
@limiter.limit("1/second")
184192
def showerthoughts():

requirements.txt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
Babel~=2.6.0
2-
Flask~=1.1.1
3-
flask_httpauth~=3.3.0
4-
Flask_limiter~=1.1.0
5-
Flask-SQLAlchemy~=2.3.2
6-
google-api-python-client>=1.7.11
7-
google-auth-httplib2~=0.0.3
8-
google-auth-oauthlib~=0.4.1
9-
gunicorn~=19.9.0
1+
Babel~=2.17.0
2+
Flask~=3.1.2
3+
flask_httpauth~=4.8.0
4+
Flask_limiter~=3.13
5+
Flask-SQLAlchemy~=3.1.1
6+
google-api-python-client>=2.181
7+
google-auth-httplib2~=0.2.0
8+
google-auth-oauthlib~=1.2.2
9+
gunicorn~=23.0.0
1010
oauth2client~=4.1.3
11-
profanityfilter~=2.0.4
12-
python-dateutil~=2.6.1
13-
sentry-sdk[flask]~=0.13.2
14-
SQLAlchemy~=1.3.7
11+
profanityfilter~=2.1.0
12+
python-dateutil~=2.9.0.post0
13+
sentry-sdk[flask]~=2.38.0
14+
SQLAlchemy~=2.0.43
15+
pytz~=2025.2

0 commit comments

Comments
 (0)