|
1 | 1 | import json |
2 | | -import os |
3 | | - |
4 | 2 | import requests |
5 | | -import boto3 |
6 | 3 |
|
7 | 4 | from flask import Blueprint |
8 | 5 | from flask import request |
|
12 | 9 | from sqlalchemy import desc |
13 | 10 |
|
14 | 11 | import structlog |
15 | | -from werkzeug.utils import secure_filename |
16 | 12 |
|
17 | 13 | from conditional.util.context_processors import get_member_name |
18 | 14 |
|
|
26 | 22 |
|
27 | 23 | logger = structlog.get_logger() |
28 | 24 |
|
29 | | -major_project_bp = Blueprint('major_project_bp', __name__) |
| 25 | +major_project_bp = Blueprint("major_project_bp", __name__) |
30 | 26 |
|
31 | 27 |
|
32 | | -@major_project_bp.route('/major_project/') |
| 28 | +@major_project_bp.route("/major_project/") |
33 | 29 | @auth.oidc_auth("default") |
34 | 30 | @get_user |
35 | 31 | def display_major_project(user_dict=None): |
36 | 32 | log = logger.new(request=request, auth_dict=user_dict) |
37 | | - log.info('Display Major Project Page') |
| 33 | + log.info("Display Major Project Page") |
38 | 34 |
|
39 | 35 | major_projects = [ |
40 | 36 | { |
41 | | - 'username': p.uid, |
42 | | - 'name': ldap_get_member(p.uid).cn, |
43 | | - 'proj_name': p.name, |
44 | | - 'status': p.status, |
45 | | - 'description': p.description, |
46 | | - 'id': p.id, |
47 | | - 'is_owner': bool(user_dict['username'] == p.uid) |
48 | | - } for p in |
49 | | - MajorProject.query.filter( |
50 | | - MajorProject.date > start_of_year()).order_by( |
51 | | - desc(MajorProject.id))] |
| 37 | + "username": p.uid, |
| 38 | + "name": ldap_get_member(p.uid).cn, |
| 39 | + "proj_name": p.name, |
| 40 | + "status": p.status, |
| 41 | + "description": p.description, |
| 42 | + "id": p.id, |
| 43 | + "is_owner": bool(user_dict["username"] == p.uid), |
| 44 | + } |
| 45 | + for p in MajorProject.query.filter( |
| 46 | + MajorProject.date > start_of_year() |
| 47 | + ).order_by(desc(MajorProject.id)) |
| 48 | + ] |
52 | 49 |
|
53 | 50 | major_projects_len = len(major_projects) |
54 | 51 | # return names in 'first last (username)' format |
55 | | - return render_template('major_project_submission.html', |
56 | | - major_projects=major_projects, |
57 | | - major_projects_len=major_projects_len, |
58 | | - username=user_dict['username']) |
59 | | - |
60 | | -@major_project_bp.route('/major_project/upload', methods=['POST']) |
61 | | -@auth.oidc_auth("default") |
62 | | -@get_user |
63 | | -def upload_major_project_files(user_dict=None): |
64 | | - log = logger.new(request=request, auth_dict=user_dict) |
65 | | - log.info('Uploading Major Project File(s)') |
66 | | - |
| 52 | + return render_template( |
| 53 | + "major_project_submission.html", |
| 54 | + major_projects=major_projects, |
| 55 | + major_projects_len=major_projects_len, |
| 56 | + username=user_dict["username"], |
| 57 | + ) |
67 | 58 |
|
68 | | - if len(list(request.files.keys())) < 1: |
69 | | - return "No file", 400 |
70 | | - |
71 | | - # Temporarily save files to a place, to be uploaded on submit |
72 | | - |
73 | | - for _, file in request.files.lists(): |
74 | | - file = file[0] # remove it from the list because this is not the best |
75 | | - safe_name = secure_filename(file.filename) |
76 | | - filename = f"/tmp/{user_dict['username']}/{safe_name}" |
77 | | - |
78 | | - os.makedirs(os.path.dirname(filename), exist_ok=True) |
79 | | - file.save(filename) |
80 | | - |
81 | | - return jsonify({"success": True}), 200 |
82 | 59 |
|
83 | | - |
84 | | - |
85 | | -@major_project_bp.route('/major_project/submit', methods=['POST']) |
| 60 | +@major_project_bp.route("/major_project/submit", methods=["POST"]) |
86 | 61 | @auth.oidc_auth("default") |
87 | 62 | @get_user |
88 | 63 | def submit_major_project(user_dict=None): |
89 | 64 | log = logger.new(request=request, auth_dict=user_dict) |
90 | | - log.info('Submit Major Project') |
| 65 | + log.info("Submit Major Project") |
91 | 66 |
|
92 | 67 | post_data = request.get_json() |
93 | | - print(post_data) |
94 | | - name = post_data['projectName'] |
95 | | - tldr = post_data['projectTldr'] |
96 | | - time_spent = post_data['projectTimeSpent'] |
97 | | - skills = post_data['projectSkills'] |
98 | | - description = post_data['projectDescription'] |
99 | | - |
100 | | - user_id = user_dict['username'] |
101 | | - |
102 | | - print(skills) |
| 68 | + name = post_data["projectName"] |
| 69 | + description = post_data["projectDescription"] |
103 | 70 |
|
104 | | - if name == "" or len(description.strip().split()) < 50: # check for 50 word minimum |
| 71 | + if name == "" or description == "": |
105 | 72 | return jsonify({"success": False}), 400 |
106 | | - project = MajorProject(user_id, name, tldr, time_spent, description) |
| 73 | + project = MajorProject(user_dict["username"], name, description) |
107 | 74 |
|
| 75 | + username = user_dict["username"] |
| 76 | + send_slack_ping( |
| 77 | + { |
| 78 | + "text": f"<!subteam^S5XENJJAH> *{get_member_name(username)}* ({username})" |
| 79 | + f" submitted their major project, *{name}*!" |
| 80 | + } |
| 81 | + ) |
108 | 82 | db.session.add(project) |
109 | 83 | db.session.commit() |
110 | | - |
111 | | - # This allows us to get a project with a database ID |
112 | | - project = MajorProject.query.filter( |
113 | | - MajorProject.name == name and MajorProject.uid == user_id |
114 | | - ).first() |
115 | | - |
116 | | - if project is None: |
117 | | - return jsonify({"success": False}), 500 |
118 | | - |
119 | | - # Don't send slack ping until after we are sure the DB worked fine |
120 | | - send_slack_ping({"text":f"<!subteam^S5XENJJAH> *{get_member_name(user_id)}* ({user_id})" |
121 | | - f" submitted their major project, *{name}*!"}) |
122 | | - |
123 | | - # Acquire S3 Bucket instance |
124 | | - s3 = boto3.resource("s3", endpoint_url="https://s3.csh.rit.edu") |
125 | | - bucket = s3.create_bucket(Bucket="major-project-media") |
126 | | - # Collect all the locally cached files and put them in the bucket |
127 | | - for file in os.listdir(f"/tmp/{user_id}"): |
128 | | - filepath = f"/tmp/{user_id}/{file}" |
129 | | - print(filepath) |
130 | | - bucket.upload_file(filepath, f"{project.id}-{file}") |
131 | | - os.remove(filepath) |
132 | | - os.rmdir(f"/tmp/{user_id}") |
133 | | - |
134 | 84 | return jsonify({"success": True}), 200 |
135 | 85 |
|
136 | 86 |
|
137 | | -@major_project_bp.route('/major_project/review', methods=['POST']) |
| 87 | +@major_project_bp.route("/major_project/review", methods=["POST"]) |
138 | 88 | @auth.oidc_auth("default") |
139 | 89 | @get_user |
140 | 90 | def major_project_review(user_dict=None): |
141 | 91 | log = logger.new(request=request, auth_dict=user_dict) |
142 | 92 |
|
143 | | - if not ldap_is_eval_director(user_dict['account']): |
| 93 | + if not ldap_is_eval_director(user_dict["account"]): |
144 | 94 | return redirect("/dashboard", code=302) |
145 | 95 |
|
146 | 96 | post_data = request.get_json() |
147 | | - pid = post_data['id'] |
148 | | - status = post_data['status'] |
| 97 | + pid = post_data["id"] |
| 98 | + status = post_data["status"] |
149 | 99 |
|
150 | | - log.info(f'{status} Major Project ID: {pid}') |
| 100 | + log.info(f"{status} Major Project ID: {pid}") |
151 | 101 |
|
152 | 102 | print(post_data) |
153 | | - MajorProject.query.filter( |
154 | | - MajorProject.id == pid). \ |
155 | | - update( |
156 | | - { |
157 | | - 'status': status |
158 | | - }) |
| 103 | + MajorProject.query.filter(MajorProject.id == pid).update({"status": status}) |
159 | 104 | db.session.flush() |
160 | 105 | db.session.commit() |
161 | 106 | return jsonify({"success": True}), 200 |
162 | 107 |
|
163 | 108 |
|
164 | | -@major_project_bp.route('/major_project/delete/<pid>', methods=['DELETE']) |
| 109 | +@major_project_bp.route("/major_project/delete/<pid>", methods=["DELETE"]) |
165 | 110 | @auth.oidc_auth("default") |
166 | 111 | @get_user |
167 | 112 | def major_project_delete(pid, user_dict=None): |
168 | 113 | log = logger.new(request=request, auth_dict=user_dict) |
169 | | - log.info(f'Delete Major Project ID: {pid}') |
| 114 | + log.info(f"Delete Major Project ID: {pid}") |
170 | 115 |
|
171 | | - major_project = MajorProject.query.filter( |
172 | | - MajorProject.id == pid |
173 | | - ).first() |
| 116 | + major_project = MajorProject.query.filter(MajorProject.id == pid).first() |
174 | 117 | creator = major_project.uid |
175 | 118 |
|
176 | | - if creator == user_dict['username'] or ldap_is_eval_director(user_dict['account']): |
177 | | - MajorProject.query.filter( |
178 | | - MajorProject.id == pid |
179 | | - ).delete() |
| 119 | + if creator == user_dict["username"] or ldap_is_eval_director(user_dict["account"]): |
| 120 | + MajorProject.query.filter(MajorProject.id == pid).delete() |
180 | 121 | db.session.flush() |
181 | 122 | db.session.commit() |
182 | 123 | return jsonify({"success": True}), 200 |
183 | 124 |
|
184 | 125 | return "Must be project owner to delete!", 401 |
185 | 126 |
|
| 127 | + |
186 | 128 | def send_slack_ping(payload): |
187 | | - requests.post(app.config['WEBHOOK_URL'], json.dumps(payload), timeout=120) |
| 129 | + requests.post(app.config["WEBHOOK_URL"], json.dumps(payload), timeout=120) |
0 commit comments