Coverage for app/controllers/main/routes.py: 24%

356 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2025-03-12 21:45 +0000

1import json 

2import datetime 

3from peewee import JOIN 

4from http import cookies 

5from playhouse.shortcuts import model_to_dict 

6from flask import request, render_template, jsonify, g, abort, flash, redirect, url_for, make_response, session, request 

7 

8from app.controllers.main import main_bp 

9from app import app 

10from app.models.term import Term 

11from app.models.user import User 

12from app.models.note import Note 

13from app.models.event import Event 

14from app.models.program import Program 

15from app.models.interest import Interest 

16from app.models.eventRsvp import EventRsvp 

17from app.models.celtsLabor import CeltsLabor 

18from app.models.programBan import ProgramBan 

19from app.models.profileNote import ProfileNote 

20from app.models.insuranceInfo import InsuranceInfo 

21from app.models.certification import Certification 

22from app.models.programManager import ProgramManager 

23from app.models.backgroundCheck import BackgroundCheck 

24from app.models.emergencyContact import EmergencyContact 

25from app.models.eventParticipant import EventParticipant 

26from app.models.courseInstructor import CourseInstructor 

27from app.models.backgroundCheckType import BackgroundCheckType 

28 

29from app.logic.events import getUpcomingEventsForUser, getParticipatedEventsForUser, getTrainingEvents, getEventRsvpCountsForTerm, getUpcomingStudentLedCount, getStudentLedEvents, getBonnerEvents, getOtherEvents, getEngagementEvents 

30from app.logic.transcript import * 

31from app.logic.loginManager import logout 

32from app.logic.searchUsers import searchUsers 

33from app.logic.utils import selectSurroundingTerms 

34from app.logic.celtsLabor import getCeltsLaborHistory 

35from app.logic.createLogs import createRsvpLog, createActivityLog 

36from app.logic.certification import getCertRequirementsWithCompletion 

37from app.logic.landingPage import getManagerProgramDict, getActiveEventTab 

38from app.logic.minor import toggleMinorInterest, getCommunityEngagementByTerm, getEngagementTotal 

39from app.logic.participants import unattendedRequiredEvents, trainedParticipants, getParticipationStatusForTrainings, checkUserRsvp, addPersonToEvent 

40from app.logic.users import addUserInterest, removeUserInterest, banUser, unbanUser, isEligibleForProgram, getUserBGCheckHistory, addProfileNote, deleteProfileNote, updateDietInfo 

41 

42@main_bp.route('/logout', methods=['GET']) 

43def redirectToLogout(): 

44 return redirect(logout()) 

45 

46@main_bp.route('/', methods=['GET']) 

47def landingPage(): 

48 

49 managerProgramDict = getManagerProgramDict(g.current_user) 

50 # Optimize the query to fetch programs with non-canceled, non-past events in the current term 

51 

52 programsWithEventsList = list(Program.select(Program, Event) 

53 .join(Event) 

54 .where((Event.term == g.current_term) & (Event.isCanceled == False)) 

55 .distinct() 

56 .execute()) # Ensure only unique programs are included 

57 # Limit returned list to events in the future 

58 futureEvents = [p for p in programsWithEventsList if not p.event.isPastEnd] 

59 

60 return render_template("/main/landingPage.html", 

61 managerProgramDict=managerProgramDict, 

62 term=g.current_term, 

63 programsWithEventsList = futureEvents) 

64 

65 

66 

67 

68@main_bp.route('/goToEventsList/<programID>', methods=['GET']) 

69def goToEventsList(programID): 

70 return {"activeTab": getActiveEventTab(programID)} 

71 

72@main_bp.route('/eventsList/<selectedTerm>', methods=['GET'], defaults={'activeTab': "studentLedEvents", 'programID': 0}) 

73@main_bp.route('/eventsList/<selectedTerm>/<activeTab>', methods=['GET'], defaults={'programID': 0}) 

74@main_bp.route('/eventsList/<selectedTerm>/<activeTab>/<programID>', methods=['GET']) 

75def events(selectedTerm, activeTab, programID): 

76 currentTerm = g.current_term 

77 if selectedTerm: 

78 currentTerm = selectedTerm 

79 

80 currentTime = datetime.datetime.now() 

81 listOfTerms = Term.select().order_by(Term.termOrder) 

82 participantRSVP = EventRsvp.select(EventRsvp, Event).join(Event).where(EventRsvp.user == g.current_user) 

83 rsvpedEventsID = [event.event.id for event in participantRSVP] 

84 

85 term: Term = Term.get_by_id(currentTerm) 

86 

87 currentEventRsvpAmount = getEventRsvpCountsForTerm(term) 

88 studentLedEvents = getStudentLedEvents(term) 

89 countUpcomingStudentLedEvents = getUpcomingStudentLedCount(term, currentTime) 

90 trainingEvents = getTrainingEvents(term, g.current_user) 

91 engagementEvents = getEngagementEvents(term) 

92 bonnerEvents = getBonnerEvents(term) 

93 otherEvents = getOtherEvents(term) 

94 

95 managersProgramDict = getManagerProgramDict(g.current_user) 

96 

97 # Fetch toggle state from session  

98 toggleState = request.args.get('toggleState', 'unchecked') 

99 

100 # compile all student led events into one list 

101 studentEvents = [] 

102 for studentEvent in studentLedEvents.values(): 

103 studentEvents += studentEvent # add all contents of studentEvent to the studentEvents list 

104 

105 # Get the count of all term events for each category to display in the event list page. 

106 studentLedEventsCount: int = len(studentEvents) 

107 trainingEventsCount: int = len(trainingEvents) 

108 engagementEventsCount: int = len(engagementEvents) 

109 bonnerEventsCount: int = len(bonnerEvents) 

110 otherEventsCount: int = len(otherEvents) 

111 

112 # gets only upcoming events to display in indicators 

113 if (toggleState == 'unchecked'): 

114 studentLedEventsCount: int = sum(list(countUpcomingStudentLedEvents.values())) 

115 for event in trainingEvents: 

116 if event.isPastEnd: 

117 trainingEventsCount -= 1 

118 for event in engagementEvents: 

119 if event.isPastEnd: 

120 engagementEventsCount -= 1 

121 for event in bonnerEvents: 

122 if event.isPastEnd: 

123 bonnerEventsCount -= 1 

124 for event in otherEvents: 

125 if event.isPastEnd: 

126 otherEventsCount -= 1 

127 

128 # Handle ajax request for Event category header number notifiers and toggle 

129 if request.headers.get('X-Requested-With') == 'XMLHttpRequest': 

130 return jsonify({ 

131 "studentLedEventsCount": studentLedEventsCount, 

132 "trainingEventsCount": trainingEventsCount, 

133 "engagementEventsCount": engagementEventsCount, 

134 "bonnerEventsCount": bonnerEventsCount, 

135 "otherEventsCount": otherEventsCount, 

136 "toggleStatus": toggleState 

137 }) 

138 

139 return render_template("/events/eventList.html", 

140 selectedTerm = term, 

141 studentLedEvents = studentLedEvents, 

142 trainingEvents = trainingEvents, 

143 engagementEvents = engagementEvents, 

144 bonnerEvents = bonnerEvents, 

145 otherEvents = otherEvents, 

146 listOfTerms = listOfTerms, 

147 rsvpedEventsID = rsvpedEventsID, 

148 currentEventRsvpAmount = currentEventRsvpAmount, 

149 currentTime = currentTime, 

150 user = g.current_user, 

151 activeTab = activeTab, 

152 programID = int(programID), 

153 managersProgramDict = managersProgramDict, 

154 countUpcomingStudentLedEvents = countUpcomingStudentLedEvents, 

155 toggleState = toggleState, 

156 ) 

157 

158@main_bp.route('/profile/<username>', methods=['GET']) 

159def viewUsersProfile(username): 

160 """ 

161 This function displays the information of a volunteer to the user 

162 """ 

163 try: 

164 volunteer = User.get(User.username == username) 

165 except Exception as e: 

166 if g.current_user.isAdmin: 

167 flash(f"{username} does not exist! ", category='danger') 

168 return redirect(url_for('admin.studentSearchPage')) 

169 else: 

170 abort(403) # Error 403 if non admin/student-staff user trys to access via url 

171 

172 if (g.current_user == volunteer) or g.current_user.isAdmin: 

173 upcomingEvents = getUpcomingEventsForUser(volunteer) 

174 participatedEvents = getParticipatedEventsForUser(volunteer) 

175 programs = Program.select() 

176 if not g.current_user.isBonnerScholar and not g.current_user.isAdmin: 

177 programs = programs.where(Program.isBonnerScholars == False) 

178 interests = Interest.select(Interest, Program).join(Program).where(Interest.user == volunteer) 

179 programsInterested = [interest.program for interest in interests] 

180 

181 rsvpedEventsList = EventRsvp.select(EventRsvp, Event).join(Event).where(EventRsvp.user == volunteer) 

182 rsvpedEvents = [event.event.id for event in rsvpedEventsList] 

183 

184 programManagerPrograms = ProgramManager.select(ProgramManager, Program).join(Program).where(ProgramManager.user == volunteer) 

185 permissionPrograms = [entry.program.id for entry in programManagerPrograms] 

186 

187 allBackgroundHistory = getUserBGCheckHistory(volunteer) 

188 backgroundTypes = list(BackgroundCheckType.select()) 

189 

190 

191 

192 eligibilityTable = [] 

193 

194 for program in programs: 

195 banNotes = list(ProgramBan.select(ProgramBan, Note) 

196 .join(Note, on=(ProgramBan.banNote == Note.id)) 

197 .where(ProgramBan.user == volunteer, 

198 ProgramBan.program == program, 

199 ProgramBan.endDate > datetime.datetime.now()).execute()) 

200 onTranscriptQuery = list(ProgramBan.select(ProgramBan) 

201 .where(ProgramBan.user == volunteer, 

202 ProgramBan.program == program, 

203 ProgramBan.unbanNote.is_null(), 

204 ProgramBan.removeFromTranscript == 0)) 

205 

206 onTranscript = True if len(onTranscriptQuery) > 0 else False 

207 userParticipatedTrainingEvents = getParticipationStatusForTrainings(program, [volunteer], g.current_term) 

208 try: 

209 allTrainingsComplete = False not in [attended for event, attended in userParticipatedTrainingEvents[username]] # Did volunteer attend all events 

210 except KeyError: 

211 allTrainingsComplete = False 

212 noteForDict = banNotes[-1].banNote.noteContent if banNotes else "" 

213 eligibilityTable.append({"program": program, 

214 "completedTraining": allTrainingsComplete, 

215 "trainingList": userParticipatedTrainingEvents, 

216 "isNotBanned": (not banNotes), 

217 "banNote": noteForDict, 

218 "onTranscript": onTranscript}), 

219 

220 profileNotes = ProfileNote.select().where(ProfileNote.user == volunteer) 

221 

222 bonnerRequirements = getCertRequirementsWithCompletion(certification=Certification.BONNER, username=volunteer) 

223 

224 managersProgramDict = getManagerProgramDict(g.current_user) 

225 managersList = [id[1] for id in managersProgramDict.items()] 

226 totalSustainedEngagements = getEngagementTotal(getCommunityEngagementByTerm(volunteer)) 

227 

228 return render_template ("/main/userProfile.html", 

229 programs = programs, 

230 programsInterested = programsInterested, 

231 upcomingEvents = upcomingEvents, 

232 participatedEvents = participatedEvents, 

233 rsvpedEvents = rsvpedEvents, 

234 permissionPrograms = permissionPrograms, 

235 eligibilityTable = eligibilityTable, 

236 volunteer = volunteer, 

237 backgroundTypes = backgroundTypes, 

238 allBackgroundHistory = allBackgroundHistory, 

239 currentDateTime = datetime.datetime.now(), 

240 profileNotes = profileNotes, 

241 bonnerRequirements = bonnerRequirements, 

242 managersList = managersList, 

243 participatedInLabor = getCeltsLaborHistory(volunteer), 

244 totalSustainedEngagements = totalSustainedEngagements, 

245 ) 

246 abort(403) 

247 

248@main_bp.route('/profile/<username>/emergencyContact', methods=['GET', 'POST']) 

249def emergencyContactInfo(username): 

250 """ 

251 This loads the Emergency Contact Page 

252 """ 

253 if not (g.current_user.username == username or g.current_user.isCeltsAdmin): 

254 abort(403) 

255 

256 user = User.get(User.username == username) 

257 

258 if request.method == 'GET': 

259 readOnly = g.current_user.username != username 

260 contactInfo = EmergencyContact.get_or_none(EmergencyContact.user_id == username) 

261 return render_template ("/main/emergencyContactInfo.html", 

262 username=username, 

263 contactInfo=contactInfo, 

264 readOnly=readOnly 

265 ) 

266 

267 elif request.method == 'POST': 

268 if g.current_user.username != username: 

269 abort(403) 

270 

271 rowsUpdated = EmergencyContact.update(**request.form).where(EmergencyContact.user == username).execute() 

272 if not rowsUpdated: 

273 EmergencyContact.create(user = username, **request.form) 

274 

275 createActivityLog(f"{g.current_user.fullName} updated {user.fullName}'s emergency contact information.") 

276 flash('Emergency contact information saved successfully!', 'success') 

277 

278 if request.args.get('action') == 'exit': 

279 return redirect (f"/profile/{username}") 

280 else: 

281 return redirect (f"/profile/{username}/insuranceInfo") 

282 

283@main_bp.route('/profile/<username>/insuranceInfo', methods=['GET', 'POST']) 

284def insuranceInfo(username): 

285 """ 

286 This loads the Insurance Information Page 

287 """ 

288 if not (g.current_user.username == username or g.current_user.isCeltsAdmin): 

289 abort(403) 

290 

291 user = User.get(User.username == username) 

292 

293 if request.method == 'GET': 

294 readOnly = g.current_user.username != username 

295 userInsuranceInfo = InsuranceInfo.get_or_none(InsuranceInfo.user == username) 

296 return render_template ("/main/insuranceInfo.html", 

297 username=username, 

298 userInsuranceInfo=userInsuranceInfo, 

299 readOnly=readOnly 

300 ) 

301 

302 # Save the form data 

303 elif request.method == 'POST': 

304 if g.current_user.username != username: 

305 abort(403) 

306 

307 rowsUpdated = InsuranceInfo.update(**request.form).where(InsuranceInfo.user == username).execute() 

308 if not rowsUpdated: 

309 InsuranceInfo.create(user = username, **request.form) 

310 

311 createActivityLog(f"{g.current_user.fullName} updated {user.fullName}'s insurance information.") 

312 flash('Insurance information saved successfully!', 'success') 

313 

314 if request.args.get('action') == 'exit': 

315 return redirect (f"/profile/{username}") 

316 else: 

317 return redirect (f"/profile/{username}/emergencyContact") 

318 

319@main_bp.route('/profile/<username>/travelForm', methods=['GET', 'POST']) 

320def travelForm(username): 

321 if not (g.current_user.username == username or g.current_user.isCeltsAdmin): 

322 abort(403) 

323 

324 user = (User.select(User, EmergencyContact, InsuranceInfo) 

325 .join(EmergencyContact, JOIN.LEFT_OUTER).switch() 

326 .join(InsuranceInfo, JOIN.LEFT_OUTER) 

327 .where(User.username == username).limit(1)) 

328 if not list(user): 

329 abort(404) 

330 userData = list(user.dicts())[0] 

331 userData = {key: value if value else '' for (key, value) in userData.items()} 

332 

333 return render_template ('/main/travelForm.html', 

334 userData = userData 

335 ) 

336 

337 

338@main_bp.route('/profile/addNote', methods=['POST']) 

339def addNote(): 

340 """ 

341 This function adds a note to the user's profile. 

342 """ 

343 postData = request.form 

344 try: 

345 note = addProfileNote(postData["visibility"], postData["bonner"] == "yes", postData["noteTextbox"], postData["username"]) 

346 flash("Successfully added profile note", "success") 

347 return redirect(url_for("main.viewUsersProfile", username=postData["username"])) 

348 except Exception as e: 

349 print("Error adding note", e) 

350 flash("Failed to add profile note", "danger") 

351 return "Failed to add profile note", 500 

352 

353@main_bp.route('/<username>/deleteNote', methods=['POST']) 

354def deleteNote(username): 

355 """ 

356 This function deletes a note from the user's profile. 

357 """ 

358 try: 

359 deleteProfileNote(request.form["id"]) 

360 flash("Successfully deleted profile note", "success") 

361 except Exception as e: 

362 print("Error deleting note", e) 

363 flash("Failed to delete profile note", "danger") 

364 return "success" 

365 

366# ===========================Ban=============================================== 

367@main_bp.route('/<username>/ban/<program_id>', methods=['POST']) 

368def ban(program_id, username): 

369 """ 

370 This function updates the ban status of a username either when they are banned from a program. 

371 program_id: the primary id of the program the student is being banned from 

372 username: unique value of a user to correctly identify them 

373 """ 

374 postData = request.form 

375 banNote = postData["note"] # This contains the note left about the change 

376 banEndDate = postData["endDate"] # Contains the date the ban will no longer be effective 

377 

378 try: 

379 banUser(program_id, username, banNote, banEndDate, g.current_user) 

380 programInfo = Program.get(int(program_id)) 

381 flash("Successfully banned the volunteer", "success") 

382 createActivityLog(f'Banned {username} from {programInfo.programName} until {banEndDate}.') 

383 return "Successfully banned the volunteer." 

384 except Exception as e: 

385 print("Error while updating ban", e) 

386 flash("Failed to ban the volunteer", "danger") 

387 return "Failed to ban the volunteer", 500 

388 

389# ===========================Unban=============================================== 

390@main_bp.route('/<username>/unban/<program_id>', methods=['POST']) 

391def unban(program_id, username): 

392 """ 

393 This function updates the ban status of a username either when they are unbanned from a program. 

394 program_id: the primary id of the program the student is being unbanned from 

395 username: unique value of a user to correctly identify them 

396 """ 

397 postData = request.form 

398 unbanNote = postData["note"] # This contains the note left about the change 

399 try: 

400 unbanUser(program_id, username, unbanNote, g.current_user) 

401 programInfo = Program.get(int(program_id)) 

402 createActivityLog(f'Unbanned {username} from {programInfo.programName}.') 

403 flash("Successfully unbanned the volunteer", "success") 

404 return "Successfully unbanned the volunteer" 

405 

406 except Exception as e: 

407 print("Error while updating Unban", e) 

408 flash("Failed to unban the volunteer", "danger") 

409 return "Failed to unban the volunteer", 500 

410 

411 

412@main_bp.route('/<username>/addInterest/<program_id>', methods=['POST']) 

413def addInterest(program_id, username): 

414 """ 

415 This function adds a program to the list of programs a user interested in 

416 program_id: the primary id of the program the student is adding interest of 

417 username: unique value of a user to correctly identify them 

418 """ 

419 try: 

420 success = addUserInterest(program_id, username) 

421 if success: 

422 flash("Successfully added " + Program.get_by_id(program_id).programName + " as an interest", "success") 

423 return "" 

424 else: 

425 flash("Was unable to remove " + Program.get_by_id(program_id).programName + " as an interest.", "danger") 

426 

427 except Exception as e: 

428 print(e) 

429 return "Error Updating Interest", 500 

430 

431@main_bp.route('/<username>/removeInterest/<program_id>', methods=['POST']) 

432def removeInterest(program_id, username): 

433 """ 

434 This function removes a program to the list of programs a user interested in 

435 program_id: the primary id of the program the student is adding interest of 

436 username: unique value of a user to correctly identify them 

437 """ 

438 try: 

439 removed = removeUserInterest(program_id, username) 

440 if removed: 

441 flash("Successfully removed " + Program.get_by_id(program_id).programName + " as an interest.", "success") 

442 return "" 

443 else: 

444 flash("Was unable to remove " + Program.get_by_id(program_id).programName + " as an interest.", "danger") 

445 except Exception as e: 

446 print(e) 

447 return "Error Updating Interest", 500 

448 

449@main_bp.route('/rsvpForEvent', methods = ['POST']) 

450def volunteerRegister(): 

451 """ 

452 This function selects the user ID and event ID and registers the user 

453 for the event they have clicked register for. 

454 """ 

455 event = Event.get_by_id(request.form['id']) 

456 program = event.program 

457 user = g.current_user 

458 

459 isAdded = checkUserRsvp(user, event) 

460 isEligible = isEligibleForProgram(program, user) 

461 listOfRequirements = unattendedRequiredEvents(program, user) 

462 

463 personAdded = False 

464 if isEligible: 

465 personAdded = addPersonToEvent(user, event) 

466 if personAdded and listOfRequirements: 

467 reqListToString = ', '.join(listOfRequirements) 

468 flash(f"{user.firstName} {user.lastName} successfully registered. However, the following training may be required: {reqListToString}.", "success") 

469 elif personAdded: 

470 flash("Successfully registered for event!","success") 

471 else: 

472 flash(f"RSVP Failed due to an unknown error.", "danger") 

473 else: 

474 flash(f"Cannot RSVP. Contact CELTS administrators: {app.config['celts_admin_contact']}.", "danger") 

475 

476 

477 if 'from' in request.form: 

478 if request.form['from'] == 'ajax': 

479 return '' 

480 return redirect(url_for("admin.eventDisplay", eventId=event.id)) 

481 

482@main_bp.route('/rsvpRemove', methods = ['POST']) 

483def RemoveRSVP(): 

484 """ 

485 This function deletes the user ID and event ID from database when RemoveRSVP is clicked 

486 """ 

487 eventData = request.form 

488 event = Event.get_by_id(eventData['id']) 

489 

490 currentRsvpParticipant = EventRsvp.get(EventRsvp.user == g.current_user, EventRsvp.event == event) 

491 logBody = "withdrew from the waitlist" if currentRsvpParticipant.rsvpWaitlist else "un-RSVP'd" 

492 currentRsvpParticipant.delete_instance() 

493 createRsvpLog(event.id, f"{g.current_user.fullName} {logBody}.") 

494 flash("Successfully unregistered for event!", "success") 

495 if 'from' in eventData: 

496 if eventData['from'] == 'ajax': 

497 return '' 

498 return redirect(url_for("admin.eventDisplay", eventId=event.id)) 

499 

500@main_bp.route('/profile/<username>/serviceTranscript', methods = ['GET']) 

501def serviceTranscript(username): 

502 user = User.get_or_none(User.username == username) 

503 if user is None: 

504 abort(404) 

505 if user != g.current_user and not g.current_user.isAdmin: 

506 abort(403) 

507 

508 slCourses = getSlCourseTranscript(username) 

509 totalHours = getTotalHours(username) 

510 allEventTranscript = getProgramTranscript(username) 

511 startDate = getStartYear(username) 

512 return render_template('main/serviceTranscript.html', 

513 allEventTranscript = allEventTranscript, 

514 slCourses = slCourses.objects(), 

515 totalHours = totalHours, 

516 startDate = startDate, 

517 userData = user) 

518 

519@main_bp.route('/profile/<username>/updateTranscript/<program_id>', methods=['POST']) 

520def updateTranscript(username, program_id): 

521 # Check user permissions 

522 user = User.get_or_none(User.username == username) 

523 if user is None: 

524 abort(404) 

525 if user != g.current_user and not g.current_user.isAdmin: 

526 abort(403) 

527 

528 # Get the data sent from the client-side JavaScript 

529 data = request.json 

530 

531 # Retrieve removeFromTranscript value from the request data 

532 removeFromTranscript = data.get('removeFromTranscript') 

533 

534 # Update the ProgramBan object matching the program_id and username 

535 try: 

536 bannedProgramForUser = ProgramBan.get((ProgramBan.program == program_id) & (ProgramBan.user == user) & (ProgramBan.unbanNote.is_null())) 

537 bannedProgramForUser.removeFromTranscript = removeFromTranscript 

538 bannedProgramForUser.save() 

539 return jsonify({'status': 'success'}) 

540 except ProgramBan.DoesNotExist: 

541 return jsonify({'status': 'error', 'message': 'ProgramBan not found'}) 

542 

543 

544@main_bp.route('/searchUser/<query>', methods = ['GET']) 

545def searchUser(query): 

546 

547 category= request.args.get("category") 

548 

549 '''Accepts user input and queries the database returning results that matches user search''' 

550 try: 

551 query = query.strip() 

552 search = query.upper() 

553 splitSearch = search.split() 

554 searchResults = searchUsers(query,category) 

555 return searchResults 

556 except Exception as e: 

557 print(e) 

558 return "Error in searching for user", 500 

559 

560@main_bp.route('/contributors',methods = ['GET']) 

561def contributors(): 

562 return render_template("/contributors.html") 

563 

564@main_bp.route('/updateDietInformation', methods = ['GET', 'POST']) 

565def getDietInfo(): 

566 dietaryInfo = request.form 

567 user = dietaryInfo["user"] 

568 dietInfo = dietaryInfo["dietInfo"] 

569 

570 if (g.current_user.username == user) or g.current_user.isAdmin: 

571 updateDietInfo(user, dietInfo) 

572 userInfo = User.get(User.username == user) 

573 if len(dietInfo) > 0: 

574 createActivityLog(f"Updated {userInfo.fullName}'s dietary restrictions to {dietInfo}.") if dietInfo.strip() else None 

575 else: 

576 createActivityLog(f"Deleted all {userInfo.fullName}'s dietary restrictions dietary restrictions.") 

577 

578 

579 return " " 

580 

581@main_bp.route('/profile/<username>/indicateInterest', methods=['POST']) 

582def indicateMinorInterest(username): 

583 if g.current_user.isCeltsAdmin or g.current_user.username == username: 

584 toggleMinorInterest(username) 

585 

586 else: 

587 abort(403) 

588 

589 return ""