Skip to content

Commit d4a719b

Browse files
committed
Restored all my existing work
1 parent 39efe97 commit d4a719b

File tree

7 files changed

+415
-72
lines changed

7 files changed

+415
-72
lines changed

conditional/blueprints/major_project_submission.py

Lines changed: 139 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
import json
2+
import os
23
import requests
34

5+
import requests
6+
import boto3
7+
8+
from config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
49
from flask import Blueprint
510
from flask import request
611
from flask import jsonify
712
from flask import redirect
813

9-
from sqlalchemy import desc
14+
from sqlalchemy import func, desc
1015

1116
import structlog
17+
from werkzeug.utils import secure_filename
1218

1319
from conditional.util.context_processors import get_member_name
1420

15-
from conditional.models.models import MajorProject
21+
from conditional.models.models import MajorProject, MajorProjectSkill
1622

1723
from conditional.util.ldap import ldap_is_eval_director
1824
from conditional.util.ldap import ldap_get_member
@@ -32,19 +38,39 @@ def display_major_project(user_dict=None):
3238
log = logger.new(request=request, auth_dict=user_dict)
3339
log.info("Display Major Project Page")
3440

41+
# There is probably a better way to do this, but it does work
42+
43+
proj_list = db.session.query(
44+
MajorProject.id,
45+
MajorProject.date,
46+
MajorProject.uid,
47+
MajorProject.name,
48+
MajorProject.tldr,
49+
MajorProject.timeSpent,
50+
MajorProject.description,
51+
MajorProject.status,
52+
func.array_agg(MajorProjectSkill.skill).label("skills")
53+
).outerjoin(MajorProjectSkill,
54+
MajorProject.id == MajorProjectSkill.project_id
55+
).group_by(MajorProject.id
56+
).where(MajorProject.date >= start_of_year()
57+
).order_by(desc(MajorProject.date))
58+
3559
major_projects = [
3660
{
61+
"id": p.id,
62+
"date": p.date,
3763
"username": p.uid,
3864
"name": ldap_get_member(p.uid).cn,
3965
"proj_name": p.name,
66+
"tldr": p.tldr,
67+
"time_spent": p.timeSpent,
68+
"skills": p.skills,
69+
"desc": p.description,
4070
"status": p.status,
41-
"description": p.description,
42-
"id": p.id,
43-
"is_owner": bool(user_dict["username"] == p.uid),
71+
"is_owner": bool(user_dict["username"] == p.uid)
4472
}
45-
for p in MajorProject.query.filter(
46-
MajorProject.date > start_of_year()
47-
).order_by(desc(MajorProject.id))
73+
for p in proj_list
4874
]
4975

5076
major_projects_len = len(major_projects)
@@ -53,8 +79,32 @@ def display_major_project(user_dict=None):
5379
"major_project_submission.html",
5480
major_projects=major_projects,
5581
major_projects_len=major_projects_len,
56-
username=user_dict["username"],
57-
)
82+
username=user_dict["username"])
83+
84+
@major_project_bp.route("/major_project/upload", methods=["POST"])
85+
@auth.oidc_auth("default")
86+
@get_user
87+
def upload_major_project_files(user_dict=None):
88+
log = logger.new(request=request, auth_dict=user_dict)
89+
log.info('Uploading Major Project File(s)')
90+
91+
log.info(f"user_dict: {user_dict}")
92+
93+
if len(list(request.files.keys())) <1:
94+
return "No file", 400
95+
96+
# Temporarily save files to a place, to be uploaded on submit
97+
98+
for _, file in request.files.lists():
99+
file = file[0]
100+
safe_name = secure_filename(file.filename)
101+
filename = f"/tmp/{user_dict['username']}/{safe_name}"
102+
103+
os.makedirs(os.path.dirname(filename), exist_ok=True)
104+
file.save(filename)
105+
106+
return jsonify({"success": True}), 200
107+
58108

59109

60110
@major_project_bp.route("/major_project/submit", methods=["POST"])
@@ -65,27 +115,88 @@ def submit_major_project(user_dict=None):
65115
log.info("Submit Major Project")
66116

67117
post_data = request.get_json()
118+
119+
print(f"Post Data: {post_data}") # TODO: Remove this later
120+
68121
name = post_data["projectName"]
122+
tldr = post_data['projectTldr']
123+
time_spent = post_data['projectTimeSpent']
124+
skills = post_data['projectSkills']
69125
description = post_data["projectDescription"]
70126

71-
if name == "" or description == "":
127+
user_id = user_dict['username']
128+
129+
log.info(user_id)
130+
131+
# All fields are required in order to be able to submit the form
132+
# TODO: Do we want any of the fields to have enforced min or max lengths?
133+
if name == "" or tldr == "" or time_spent == "" or skills == "" or description == "":
72134
return jsonify({"success": False}), 400
73-
project = MajorProject(user_dict["username"], name, description)
135+
136+
# TODO: Ensure all the information is being passed to the object
137+
project = MajorProject(user_id, name, tldr, time_spent, description)
74138

75-
# Don't you dare try pinging @channel
139+
# Save the info to the database
140+
db.session.add(project)
141+
db.session.commit()
142+
143+
144+
project = MajorProject.query.filter(
145+
MajorProject.name == name and MajorProject.uid == user_id
146+
).first()
147+
148+
skills_list = filter(lambda x: x != 'None', skills)
149+
print(f"Skills: {list(skills_list)}")
150+
151+
for skill in skills_list:
152+
skill = skill.strip()
153+
154+
if skill != "" and skill != 'None':
155+
mp_skill = MajorProjectSkill(project.id, skill)
156+
db.session.add(mp_skill)
157+
158+
db.session.commit()
159+
160+
# Fail if attempting to retreive non-existent project
161+
if project is None:
162+
return jsonify({"success": False}), 500
163+
164+
# Sanitize input so that the Slackbot cannot ping @channel
76165
name = name.replace("<!", "<! ")
77166

78-
username = user_dict["username"]
79-
send_slack_ping(
80-
{
81-
"text": f"<!subteam^S5XENJJAH> *{get_member_name(username)}* ({username})"
82-
f" submitted their major project, *{name}*! Please be sure to reach out"
83-
f" to E-Board members to answer any questions they may have regarding"
84-
f" your project!"
85-
}
167+
# Connect to S3 bucket
168+
s3 = boto3.resource(
169+
"s3",
170+
endpoint_url="https://s3.csh.rit.edu",
171+
aws_access_key_id=AWS_ACCESS_KEY_ID,
172+
aws_secret_access_key=AWS_SECRET_ACCESS_KEY
86173
)
87-
db.session.add(project)
88-
db.session.commit()
174+
175+
bucket = s3.create_bucket(Bucket="major-project-media")
176+
177+
# Collect all the locally cached files and put them in the bucket
178+
for file in os.listdir(f"/tmp/{user_id}"):
179+
filepath = f"/tmp/{user_id}/{file}"
180+
181+
# TODO: Remove this later
182+
print(f"Filepath in S3: {filepath}")
183+
184+
bucket.upload_file(filepath, f"{project.id}--{file}")
185+
os.remove(filepath)
186+
187+
# Delete the temp directory once all the files have been stored in S3
188+
os.rmdir(f"/tmp/{user_id}")
189+
190+
191+
# Send the slack ping only after we know that the data was properly saved to the DB
192+
# TODO: Maybe add more info to the slack ping?
193+
# send_slack_ping(
194+
# {
195+
# "text": f"<!subteam^S5XENJJAH> *{get_member_name(user_id)}* ({user_id})"
196+
# f" submitted their major project, *{name}*!"
197+
# }
198+
# )
199+
89200
return jsonify({"success": True}), 200
90201

91202

@@ -106,8 +217,10 @@ def major_project_review(user_dict=None):
106217

107218
print(post_data)
108219
MajorProject.query.filter(MajorProject.id == pid).update({"status": status})
220+
109221
db.session.flush()
110222
db.session.commit()
223+
111224
return jsonify({"success": True}), 200
112225

113226

@@ -123,12 +236,14 @@ def major_project_delete(pid, user_dict=None):
123236

124237
if creator == user_dict["username"] or ldap_is_eval_director(user_dict["account"]):
125238
MajorProject.query.filter(MajorProject.id == pid).delete()
239+
126240
db.session.flush()
127241
db.session.commit()
242+
128243
return jsonify({"success": True}), 200
129244

130245
return "Must be project owner to delete!", 401
131246

132247

133248
def send_slack_ping(payload):
134-
requests.post(app.config["WEBHOOK_URL"], json.dumps(payload), timeout=120)
249+
requests.post(app.config["WEBHOOK_URL"], json.dumps(payload), timeout=120)

0 commit comments

Comments
 (0)