diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index f8ae97f..980b1ab 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - python-version: [3.8, 3.9] + python-version: [3.12] steps: - name: Install ldap dependencies diff --git a/.pylintrc b/.pylintrc index 407369b..22e31bc 100644 --- a/.pylintrc +++ b/.pylintrc @@ -9,7 +9,6 @@ disable = duplicate-code, no-member, parse-error, - bad-continuation, too-few-public-methods, global-statement, cyclic-import, diff --git a/Dockerfile b/Dockerfile index 3148d47..5fa9b20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/python:3.8-buster +FROM docker.io/python:3.12-bookworm MAINTAINER Computer Science House RUN mkdir /opt/conditional @@ -8,7 +8,7 @@ ADD requirements.txt /opt/conditional WORKDIR /opt/conditional RUN apt-get -yq update && \ - apt-get -yq install libsasl2-dev libldap2-dev libssl-dev gcc g++ make && \ + apt-get -yq install libsasl2-dev libldap2-dev libldap-common libssl-dev gcc g++ make && \ pip install -r requirements.txt && \ apt-get -yq clean all diff --git a/conditional/__init__.py b/conditional/__init__.py index 041218a..1c2f5ee 100644 --- a/conditional/__init__.py +++ b/conditional/__init__.py @@ -7,6 +7,7 @@ from flask_migrate import Migrate from flask_gzip import Gzip from flask_pyoidc.flask_pyoidc import OIDCAuthentication +from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata from flask_sqlalchemy import SQLAlchemy import sentry_sdk @@ -39,8 +40,10 @@ app.config['LDAP_BIND_PW'], ro=app.config['LDAP_RO']) -auth = OIDCAuthentication(app, issuer=app.config["OIDC_ISSUER"], - client_registration_info=app.config["OIDC_CLIENT_CONFIG"]) +client_metadata = ClientMetadata(app.config["OIDC_CLIENT_CONFIG"]) +provider_config = ProviderConfiguration(issuer=app.config["OIDC_ISSUER"], client_registration_info=client_metadata) + +auth = OIDCAuthentication({'default': provider_config}, app) app.secret_key = app.config["SECRET_KEY"] @@ -137,7 +140,7 @@ def static_proxy(path): @app.route('/') -@auth.oidc_auth +@auth.oidc_auth("default") def default_route(): return redirect('/dashboard') @@ -158,10 +161,10 @@ def health(): @app.errorhandler(404) @app.errorhandler(500) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def route_errors(error, user_dict=None): - data = dict() + data = {} # Handle the case where the header isn't present if user_dict['username'] is not None: diff --git a/conditional/blueprints/attendance.py b/conditional/blueprints/attendance.py index 7adbf99..2247570 100644 --- a/conditional/blueprints/attendance.py +++ b/conditional/blueprints/attendance.py @@ -29,7 +29,7 @@ @attendance_bp.route('/attendance/ts_members') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_all_members(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -57,7 +57,7 @@ def get_all_members(user_dict=None): @attendance_bp.route('/attendance/hm_members') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_non_alumni_non_coop(internal=False, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -102,7 +102,7 @@ def get_non_alumni_non_coop(internal=False, user_dict=None): @attendance_bp.route('/attendance/cm_members') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_non_alumni(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -130,7 +130,7 @@ def get_non_alumni(user_dict=None): @attendance_bp.route('/attendance_cm') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_attendance_cm(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -142,7 +142,7 @@ def display_attendance_cm(user_dict=None): @attendance_bp.route('/attendance_ts') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_attendance_ts(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -154,7 +154,7 @@ def display_attendance_ts(user_dict=None): @attendance_bp.route('/attendance_hm') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_attendance_hm(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -170,7 +170,7 @@ def display_attendance_hm(user_dict=None): @attendance_bp.route('/attendance/submit/cm', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_committee_attendance(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -183,7 +183,7 @@ def submit_committee_attendance(user_dict=None): f_attendees = post_data['freshmen'] timestamp = post_data['timestamp'] - log.info('Submit {} Meeting Attendance'.format(committee)) + log.info(f'Submit {committee} Meeting Attendance') timestamp = datetime.strptime(timestamp, "%Y-%m-%d") meeting = CommitteeMeeting(committee, timestamp, approved) @@ -193,11 +193,11 @@ def submit_committee_attendance(user_dict=None): db.session.refresh(meeting) for m in m_attendees: - log.info('Gave Attendance to {} for {}'.format(m, committee)) + log.info(f'Gave Attendance to {m} for {committee}') db.session.add(MemberCommitteeAttendance(m, meeting.id)) for f in f_attendees: - log.info('Gave Attendance to freshman-{} for {}'.format(f, committee)) + log.info(f'Gave Attendance to freshman-{f} for {committee}') db.session.add(FreshmanCommitteeAttendance(f, meeting.id)) db.session.commit() @@ -205,7 +205,7 @@ def submit_committee_attendance(user_dict=None): @attendance_bp.route('/attendance/submit/ts', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_seminar_attendance(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -228,11 +228,11 @@ def submit_seminar_attendance(user_dict=None): db.session.refresh(seminar) for m in m_attendees: - log.info('Gave Attendance to {} for {}'.format(m, seminar_name)) + log.info(f'Gave Attendance to {m} for {seminar_name}') db.session.add(MemberSeminarAttendance(m, seminar.id)) for f in f_attendees: - log.info('Gave Attendance to freshman-{} for {}'.format(f, seminar_name)) + log.info(f'Gave Attendance to freshman-{f} for {seminar_name}') db.session.add(FreshmanSeminarAttendance(f, seminar.id)) db.session.commit() @@ -240,7 +240,7 @@ def submit_seminar_attendance(user_dict=None): @attendance_bp.route('/attendance/submit/hm', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_house_attendance(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -263,10 +263,7 @@ def submit_house_attendance(user_dict=None): if "members" in post_data: for m in post_data['members']: - log.info('Marked {} {} for House Meeting on {}'.format( - m['uid'], - m['status'], - timestamp.strftime("%Y-%m-%d"))) + log.info(f'Marked {m['uid']} {m['status']} for House Meeting on {timestamp.strftime("%Y-%m-%d")}') db.session.add(MemberHouseMeetingAttendance( m['uid'], meeting.id, @@ -275,10 +272,7 @@ def submit_house_attendance(user_dict=None): if "freshmen" in post_data: for f in post_data['freshmen']: - log.info('Marked freshman-{} {} for House Meeting on {}'.format( - f['id'], - f['status'], - timestamp.strftime("%Y-%m-%d"))) + log.info(f'Marked freshman-{f['id']} {f['status']} for House Meeting on {timestamp.strftime("%Y-%m-%d")}') db.session.add(FreshmanHouseMeetingAttendance( f['id'], meeting.id, @@ -290,7 +284,7 @@ def submit_house_attendance(user_dict=None): @attendance_bp.route('/attendance/alter/hm//', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def alter_house_attendance(uid, hid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -299,7 +293,7 @@ def alter_house_attendance(uid, hid, user_dict=None): return "must be evals", 403 if not uid.isdigit(): - log.info('Mark {} Present for House Meeting ID: {}'.format(uid, hid)) + log.info(f'Mark {uid} Present for House Meeting ID: {hid}') member_meeting = MemberHouseMeetingAttendance.query.filter( MemberHouseMeetingAttendance.uid == uid, MemberHouseMeetingAttendance.meeting_id == hid @@ -308,7 +302,7 @@ def alter_house_attendance(uid, hid, user_dict=None): db.session.commit() return jsonify({"success": True}), 200 - log.info('Mark freshman-{} Present for House Meeting ID: {}'.format(uid, hid)) + log.info(f'Mark freshman-{uid} Present for House Meeting ID: {hid}') freshman_meeting = FreshmanHouseMeetingAttendance.query.filter( FreshmanHouseMeetingAttendance.fid == uid, FreshmanHouseMeetingAttendance.meeting_id == hid @@ -320,7 +314,7 @@ def alter_house_attendance(uid, hid, user_dict=None): @attendance_bp.route('/attendance/alter/hm//', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def alter_house_excuse(uid, hid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -333,7 +327,7 @@ def alter_house_excuse(uid, hid, user_dict=None): hm_excuse = post_data['excuse'] if not uid.isdigit(): - log.info('Mark {} as {} for HM ID: {}'.format(uid, hm_status, hid)) + log.info(f'Mark {uid} as {hm_status} for HM ID: {hid}') MemberHouseMeetingAttendance.query.filter( MemberHouseMeetingAttendance.uid == uid, MemberHouseMeetingAttendance.meeting_id == hid @@ -342,7 +336,7 @@ def alter_house_excuse(uid, hid, user_dict=None): 'attendance_status': hm_status }) else: - log.info('Mark {} as {} for HM ID: {}'.format(uid, hm_status, hid)) + log.info(f'Mark {uid} as {hm_status} for HM ID: {hid}') FreshmanHouseMeetingAttendance.query.filter( FreshmanHouseMeetingAttendance.fid == uid, FreshmanHouseMeetingAttendance.meeting_id == hid @@ -357,7 +351,7 @@ def alter_house_excuse(uid, hid, user_dict=None): @attendance_bp.route('/attendance/history', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def attendance_history(user_dict=None): @@ -431,9 +425,9 @@ def get_seminar_attendees(meeting_id): TechnicalSeminar.approved == False).all()] # pylint: disable=singleton-comparison all_meetings = sorted((all_cm + all_ts), key=lambda k: k['dt_obj'], reverse=True)[offset:limit] if len(all_cm) % 10 != 0: - total_pages = (int(len(all_cm) / 10) + 1) + total_pages = int(len(all_cm) / 10) + 1 else: - total_pages = (int(len(all_cm) / 10)) + total_pages = int(len(all_cm) / 10) return render_template('attendance_history.html', username=user_dict['username'], history=all_meetings, @@ -444,7 +438,7 @@ def get_seminar_attendees(meeting_id): @attendance_bp.route('/attendance/alter/cm/', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def alter_committee_attendance(cid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -476,7 +470,7 @@ def alter_committee_attendance(cid, user_dict=None): @attendance_bp.route('/attendance/alter/ts/', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def alter_seminar_attendance(sid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -508,7 +502,7 @@ def alter_seminar_attendance(sid, user_dict=None): @attendance_bp.route('/attendance/ts/', methods=['GET', 'DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_cm_attendees(sid, user_dict=None): if request.method == 'GET': @@ -526,7 +520,7 @@ def get_cm_attendees(sid, user_dict=None): return jsonify({"attendees": attendees}), 200 log = logger.new(request=request, auth_dict=user_dict) - log.info('Delete Technical Seminar {}'.format(sid)) + log.info(f'Delete Technical Seminar {sid}') if not ldap_is_eboard(user_dict['account']): return jsonify({"success": False, "error": "Not EBoard"}), 403 @@ -545,7 +539,7 @@ def get_cm_attendees(sid, user_dict=None): @attendance_bp.route('/attendance/cm/', methods=['GET', 'DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_ts_attendees(cid, user_dict=None): if request.method == 'GET': @@ -563,7 +557,7 @@ def get_ts_attendees(cid, user_dict=None): return jsonify({"attendees": attendees}), 200 log = logger.new(request=request, auth_dict=user_dict) - log.info('Delete Committee Meeting {}'.format(cid)) + log.info(f'Delete Committee Meeting {cid}') if not ldap_is_eboard(user_dict['account']): return jsonify({"success": False, "error": "Not EBoard"}), 403 @@ -582,11 +576,11 @@ def get_ts_attendees(cid, user_dict=None): @attendance_bp.route('/attendance/cm//approve', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def approve_cm(cid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Approve Committee Meeting {} Attendance'.format(cid)) + log.info(f'Approve Committee Meeting {cid} Attendance') if not ldap_is_eboard(user_dict['account']): return jsonify({"success": False, "error": "Not EBoard"}), 403 @@ -600,11 +594,11 @@ def approve_cm(cid, user_dict=None): @attendance_bp.route('/attendance/ts//approve', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def approve_ts(sid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Approve Technical Seminar {} Attendance'.format(sid)) + log.info(f'Approve Technical Seminar {sid} Attendance') if not ldap_is_eboard(user_dict['account']): return jsonify({"success": False, "error": "Not EBoard"}), 403 diff --git a/conditional/blueprints/cache_management.py b/conditional/blueprints/cache_management.py index fc4a186..14290a5 100644 --- a/conditional/blueprints/cache_management.py +++ b/conditional/blueprints/cache_management.py @@ -21,7 +21,7 @@ @cache_bp.route('/restart') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def restart_app(user_dict=None): if not ldap_is_rtp(user_dict['account']): @@ -34,7 +34,7 @@ def restart_app(user_dict=None): @cache_bp.route('/clearcache') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def clear_cache(user_dict=None): if not ldap_is_eval_director(user_dict['account']) and not ldap_is_rtp(user_dict['account']): diff --git a/conditional/blueprints/co_op.py b/conditional/blueprints/co_op.py index 27b86dc..94bf107 100644 --- a/conditional/blueprints/co_op.py +++ b/conditional/blueprints/co_op.py @@ -17,7 +17,7 @@ @co_op_bp.route('/co_op/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_co_op_form(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -33,7 +33,7 @@ def display_co_op_form(user_dict=None): @co_op_bp.route('/co_op/submit', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_co_op_form(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -46,7 +46,7 @@ def submit_co_op_form(user_dict=None): if not ldap_is_current_student(user_dict['account']): return "Must be current student", 403 - log.info('Submit {} Co-Op'.format(semester)) + log.info(f'Submit {semester} Co-Op') if CurrentCoops.query.filter(CurrentCoops.uid == user_dict['username'], CurrentCoops.date_created > start_of_year()).first(): @@ -65,7 +65,7 @@ def submit_co_op_form(user_dict=None): @co_op_bp.route('/co_op/', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def delete_co_op(uid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -73,7 +73,7 @@ def delete_co_op(uid, user_dict=None): if not ldap_is_eval_director(user_dict['account']): return "must be eval director", 403 - log.info('Delete {}\'s Co-Op'.format(uid)) + log.info(f'Delete {uid}\'s Co-Op') # Remove from corresponding co-op ldap group if ldap_is_member_of_group(user_dict['account'], 'fall_coop'): @@ -91,7 +91,7 @@ def delete_co_op(uid, user_dict=None): @co_op_bp.route('/co_op/manage') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_co_op_management(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/blueprints/conditional.py b/conditional/blueprints/conditional.py index a5bd005..1082ca4 100644 --- a/conditional/blueprints/conditional.py +++ b/conditional/blueprints/conditional.py @@ -15,7 +15,7 @@ @conditionals_bp.route('/conditionals/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_conditionals(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -39,7 +39,7 @@ def display_conditionals(user_dict=None): @conditionals_bp.route('/conditionals/create', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def create_conditional(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -52,7 +52,7 @@ def create_conditional(user_dict=None): uid = post_data['uid'] description = post_data['description'] due_date = datetime.strptime(post_data['dueDate'], "%Y-%m-%d") - log.info('Create a new conditional for {}'.format(uid)) + log.info(f'Create a new conditional for {uid}') if post_data['evaluation'] == 'spring': current_eval = SpringEval.query.filter(SpringEval.status == "Pending", SpringEval.uid == uid, @@ -76,7 +76,7 @@ def create_conditional(user_dict=None): @conditionals_bp.route('/conditionals/review', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def conditional_review(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -88,7 +88,7 @@ def conditional_review(user_dict=None): cid = post_data['id'] status = post_data['status'] - log.info('Updated conditional-{} to {}'.format(cid, status)) + log.info(f'Updated conditional-{cid} to {status}') conditional = Conditional.query.filter(Conditional.id == cid) cond_obj = conditional.first() @@ -113,11 +113,11 @@ def conditional_review(user_dict=None): @conditionals_bp.route('/conditionals/delete/', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def conditional_delete(cid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Delete conditional-{}'.format(cid)) + log.info(f'Delete conditional-{cid}') if ldap_is_eval_director(user_dict['account']): Conditional.query.filter( diff --git a/conditional/blueprints/dashboard.py b/conditional/blueprints/dashboard.py index 6028c45..527e8dd 100644 --- a/conditional/blueprints/dashboard.py +++ b/conditional/blueprints/dashboard.py @@ -29,7 +29,7 @@ def is_seminar_attendance_valid(attendance): # pylint: disable=too-many-statements @dashboard_bp.route('/dashboard/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_dashboard(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -38,7 +38,7 @@ def display_dashboard(user_dict=None): # Get the list of voting members. can_vote = get_voting_members() - data = dict() + data = {} data['username'] = user_dict['account'].uid data['active'] = ldap_is_active(user_dict['account']) data['bad_standing'] = ldap_is_bad_standing(user_dict['account']) @@ -71,7 +71,7 @@ def display_dashboard(user_dict=None): # only show housing if member has onfloor status if ldap_is_onfloor(user_dict['account']): - housing = dict() + housing = {} housing['points'] = user_dict['account'].housingPoints housing['room'] = user_dict['account'].roomNumber housing['queue_pos'] = get_queue_position(user_dict['account'].uid) diff --git a/conditional/blueprints/housing.py b/conditional/blueprints/housing.py index b4ea546..45e29f9 100644 --- a/conditional/blueprints/housing.py +++ b/conditional/blueprints/housing.py @@ -20,7 +20,7 @@ @housing_bp.route('/housing') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_housing(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -62,7 +62,7 @@ def display_housing(user_dict=None): @housing_bp.route('/housing/in_queue', methods=['PUT']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def change_queue_state(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -75,11 +75,11 @@ def change_queue_state(user_dict=None): if uid: if post_data.get('inQueue', False): - log.info('Add {} to Housing Queue'.format(uid)) + log.info(f'Add {uid} to Housing Queue') queue_obj = InHousingQueue(uid=uid) db.session.add(queue_obj) else: - log.info('Remove {} from Housing Queue'.format(uid)) + log.info(f'Remove {uid} from Housing Queue') InHousingQueue.query.filter_by(uid=uid).delete() db.session.flush() @@ -88,7 +88,7 @@ def change_queue_state(user_dict=None): @housing_bp.route('/housing/update/', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def change_room_numbers(rmnumber, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -107,21 +107,21 @@ def change_room_numbers(rmnumber, user_dict=None): if occupant != "": account = ldap_get_member(occupant) account.roomNumber = rmnumber - log.info('{} assigned to room {}'.format(occupant, rmnumber)) + log.info(f'{occupant} assigned to room {rmnumber}') ldap_set_active(account) - log.info('{} marked as active because of room assignment'.format(occupant)) + log.info(f'{occupant} marked as active because of room assignment') # Delete any old occupants that are no longer in room. for old_occupant in [account for account in current_students if ldap_get_roomnumber(account) == str(rmnumber) and account.uid not in update["occupants"]]: - log.info('{} removed from room {}'.format(old_occupant.uid, old_occupant.roomNumber)) + log.info(f'{old_occupant.uid} removed from room {old_occupant.roomNumber}') old_occupant.roomNumber = None return jsonify({"success": True}), 200 @housing_bp.route('/housing/room/', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") def get_occupants(rmnumber): # Get the current list of people living on-floor. @@ -134,7 +134,7 @@ def get_occupants(rmnumber): @housing_bp.route('/housing', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def clear_all_rooms(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -146,6 +146,6 @@ def clear_all_rooms(user_dict=None): # Find the current occupants and clear them. for occupant in current_students: - log.info('{} removed from room {}'.format(occupant.uid, occupant.roomNumber)) + log.info(f'{occupant.uid} removed from room {occupant.roomNumber}') occupant.roomNumber = None return jsonify({"success": True}), 200 diff --git a/conditional/blueprints/intro_evals.py b/conditional/blueprints/intro_evals.py index 7cd276b..3349bcb 100644 --- a/conditional/blueprints/intro_evals.py +++ b/conditional/blueprints/intro_evals.py @@ -25,7 +25,7 @@ @intro_evals_bp.route('/intro_evals/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_intro_evals(internal=False, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/blueprints/intro_evals_form.py b/conditional/blueprints/intro_evals_form.py index 94efa60..d90f161 100644 --- a/conditional/blueprints/intro_evals_form.py +++ b/conditional/blueprints/intro_evals_form.py @@ -15,7 +15,7 @@ @intro_evals_form_bp.route('/intro_evals_form/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_intro_evals_form(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -36,7 +36,7 @@ def display_intro_evals_form(user_dict=None): @intro_evals_form_bp.route('/intro_evals/submit', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_intro_evals(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/blueprints/logs.py b/conditional/blueprints/logs.py index 1e78fc1..92b671b 100644 --- a/conditional/blueprints/logs.py +++ b/conditional/blueprints/logs.py @@ -14,7 +14,7 @@ @log_bp.route('/logs') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_logs(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/blueprints/major_project_submission.py b/conditional/blueprints/major_project_submission.py index dfe8de0..6fb9649 100644 --- a/conditional/blueprints/major_project_submission.py +++ b/conditional/blueprints/major_project_submission.py @@ -3,7 +3,6 @@ import requests import boto3 -from botocore.exceptions import ClientError from flask import Blueprint from flask import request @@ -31,7 +30,7 @@ @major_project_bp.route('/major_project/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_major_project(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -59,12 +58,13 @@ def display_major_project(user_dict=None): username=user_dict['username']) @major_project_bp.route('/major_project/upload', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def upload_major_project_files(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) log.info('Uploading Major Project File(s)') + if len(list(request.files.keys())) < 1: return "No file", 400 @@ -83,7 +83,7 @@ def upload_major_project_files(user_dict=None): @major_project_bp.route('/major_project/submit', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def submit_major_project(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -135,7 +135,7 @@ def submit_major_project(user_dict=None): @major_project_bp.route('/major_project/review', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def major_project_review(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -147,7 +147,7 @@ def major_project_review(user_dict=None): pid = post_data['id'] status = post_data['status'] - log.info('{} Major Project ID: {}'.format(status, pid)) + log.info(f'{status} Major Project ID: {pid}') print(post_data) MajorProject.query.filter( @@ -162,11 +162,11 @@ def major_project_review(user_dict=None): @major_project_bp.route('/major_project/delete/', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def major_project_delete(pid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Delete Major Project ID: {}'.format(pid)) + log.info(f'Delete Major Project ID: {pid}') major_project = MajorProject.query.filter( MajorProject.id == pid @@ -184,4 +184,4 @@ def major_project_delete(pid, user_dict=None): return "Must be project owner to delete!", 401 def send_slack_ping(payload): - requests.post(app.config['WEBHOOK_URL'], json.dumps(payload)) + requests.post(app.config['WEBHOOK_URL'], json.dumps(payload), timeout=120) diff --git a/conditional/blueprints/member_management.py b/conditional/blueprints/member_management.py index 3f5d3d9..1927e44 100644 --- a/conditional/blueprints/member_management.py +++ b/conditional/blueprints/member_management.py @@ -1,7 +1,7 @@ import csv import io from datetime import datetime -from distutils.util import strtobool # pylint: disable=no-name-in-module,import-error +from distutils.util import strtobool # pylint: disable=no-name-in-module,import-error,deprecated-module import structlog from flask import Blueprint, request, jsonify, make_response @@ -52,7 +52,7 @@ @member_management_bp.route('/manage') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_member_management(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -100,7 +100,7 @@ def display_member_management(user_dict=None): @member_management_bp.route('/manage/settings', methods=['PUT']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_eval(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -111,14 +111,14 @@ def member_management_eval(user_dict=None): post_data = request.get_json() if 'siteLockdown' in post_data: - log.info('Changed Site Lockdown: {}'.format(post_data['siteLockdown'])) + log.info(f'Changed Site Lockdown: {post_data['siteLockdown']}') EvalSettings.query.update( { 'site_lockdown': post_data['siteLockdown'] }) if 'introForm' in post_data: - log.info('Changed Intro Form: {}'.format(post_data['introForm'])) + log.info(f'Changed Intro Form: {post_data['introForm']}') EvalSettings.query.update( { 'intro_form_active': post_data['introForm'] @@ -130,7 +130,7 @@ def member_management_eval(user_dict=None): @member_management_bp.route('/manage/accept_dues_until', methods=['PUT']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_financial(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -142,7 +142,7 @@ def member_management_financial(user_dict=None): if 'acceptDuesUntil' in post_data: date = datetime.strptime(post_data['acceptDuesUntil'], "%Y-%m-%d") - log.info('Changed Dues Accepted Until: {}'.format(date)) + log.info(f'Changed Dues Accepted Until: {date}') EvalSettings.query.update( { 'accept_dues_until': date @@ -154,7 +154,7 @@ def member_management_financial(user_dict=None): @member_management_bp.route('/manage/user', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_adduser(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -167,7 +167,7 @@ def member_management_adduser(user_dict=None): name = post_data['name'] onfloor_status = post_data['onfloor'] room_number = post_data['roomNumber'] - log.info('Create Freshman Account for {}'.format(name)) + log.info(f'Create Freshman Account for {name}') # empty room numbers should be NULL if room_number == "": @@ -180,7 +180,7 @@ def member_management_adduser(user_dict=None): @member_management_bp.route('/manage/user/upload', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_uploaduser(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -210,7 +210,7 @@ def member_management_uploaduser(user_dict=None): else: rit_username = None - log.info('Create Freshman Account for {} via CSV Upload'.format(name)) + log.info(f'Create Freshman Account for {name} via CSV Upload') db.session.add(FreshmanAccount(name, onfloor_status, room_number, None, rit_username)) db.session.flush() @@ -221,7 +221,7 @@ def member_management_uploaduser(user_dict=None): @member_management_bp.route('/manage/user/', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_edituser(uid, user_dict=None): if not ldap_is_eval_director(user_dict['account']) and not ldap_is_financial_director(user_dict['account']): @@ -248,11 +248,7 @@ def edit_uid(uid, flask_request, username): room_number = post_data['roomNumber'] onfloor_status = post_data['onfloorStatus'] housing_points = post_data['housingPoints'] - log.info('Edit {} - Room: {} On-Floor: {} Points: {}'.format( - uid, - post_data['roomNumber'], - post_data['onfloorStatus'], - post_data['housingPoints'])) + log.info(f'Edit {uid} - Room: {post_data['roomNumber']} On-Floor: {post_data['onfloorStatus']} Points: {post_data['housingPoints']}') #pylint: disable=line-too-long ldap_set_roomnumber(account, room_number) if onfloor_status: @@ -271,7 +267,7 @@ def edit_uid(uid, flask_request, username): ldap_set_housingpoints(account, housing_points) # Only update if there's a diff - log.info('Set {} Active: {}'.format(uid, active_member)) + log.info(f'Set {uid} Active: {active_member}') if ldap_is_active(account) != active_member: if active_member: ldap_set_active(account) @@ -293,12 +289,9 @@ def edit_uid(uid, flask_request, username): def edit_fid(uid, flask_request): log = logger.new(request=flask_request, auth_dict={'username': uid}) post_data = flask_request.get_json() - log.info('Edit freshman-{} - Room: {} On-Floor: {} Eval: {} SigMiss: {}'.format( - uid, - post_data['roomNumber'], - post_data['onfloorStatus'], - post_data['evalDate'], - post_data['sigMissed'])) + + log.info(f'Edit freshman-{uid} - Room: {post_data['roomNumber']} On-Floor: {post_data['onfloorStatus']} Eval: {post_data['evalDate']} SigMiss: {post_data['sigMissed']}') #pylint: disable=line-too-long + name = post_data['name'] @@ -325,11 +318,11 @@ def edit_fid(uid, flask_request): @member_management_bp.route('/manage/user/', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_getuserinfo(uid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Get {}\'s Information'.format(uid)) + log.info(f'Get {uid}\'s Information') if not ldap_is_eval_director(user_dict['account']) and not ldap_is_financial_director(user_dict['account']): return "must be eval or financial director", 403 @@ -410,11 +403,11 @@ def get_hm_date(hm_id): @member_management_bp.route('/manage/user/', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_deleteuser(fid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Delete freshman-{}'.format(fid)) + log.info(f'Delete freshman-{fid}') if not ldap_is_eval_director(user_dict['account']): return "must be eval director", 403 @@ -422,7 +415,7 @@ def member_management_deleteuser(fid, user_dict=None): if not fid.isdigit(): return "can only delete freshman accounts", 400 - log.info('backend', action="delete freshman account %s" % fid) + log.info('backend', action=f"delete freshman account {fid}") for fca in FreshmanCommitteeAttendance.query.filter(FreshmanCommitteeAttendance.fid == fid): db.session.delete(fca) @@ -444,7 +437,7 @@ def member_management_deleteuser(fid, user_dict=None): # user creation script. There's no reason that the evals director should ever # manually need to do this @member_management_bp.route('/manage/upgrade_user', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_upgrade_user(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -458,7 +451,7 @@ def member_management_upgrade_user(user_dict=None): uid = post_data['uid'] signatures_missed = post_data['sigsMissed'] - log.info('Upgrade freshman-{} to Account: {}'.format(fid, uid)) + log.info(f'Upgrade freshman-{fid} to Account: {uid}') acct = FreshmanAccount.query.filter( FreshmanAccount.id == fid).first() @@ -483,10 +476,7 @@ def member_management_upgrade_user(user_dict=None): db.session.add(MemberHouseMeetingAttendance( uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status)) else: - log.info('Duplicate house meeting attendance! fid: {}, uid: {}, id: {}'.format( - fid, - uid, - fhm.meeting_id)) + log.info(f'Duplicate house meeting attendance! fid: {fid}, uid: {uid}, id: {fhm.meeting_id}') db.session.delete(fhm) new_account = ldap_get_member(uid) @@ -508,7 +498,7 @@ def member_management_upgrade_user(user_dict=None): @member_management_bp.route('/manage/make_user_active', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def member_management_make_user_active(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -519,18 +509,18 @@ def member_management_make_user_active(user_dict=None): return "must be current student, not in bad standing and not active", 403 ldap_set_active(user_dict['account']) - log.info("Make user {} active".format(user_dict['username'])) + log.info(f"Make user {user_dict['username']} active") clear_members_cache() return jsonify({"success": True}), 200 @member_management_bp.route('/member/', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def get_member(uid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) - log.info('Get {}\'s Information'.format(uid)) + log.info(f'Get {uid}\'s Information') if not ldap_is_eval_director(user_dict['account']): return "must be eval director", 403 @@ -546,7 +536,7 @@ def get_member(uid, user_dict=None): @member_management_bp.route('/manage/active', methods=['DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def clear_active_members(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -559,7 +549,7 @@ def clear_active_members(user_dict=None): # Clear the active group. for account in members: if account.uid != user_dict['username']: - log.info('Remove {} from Active Status'.format(account.uid)) + log.info(f'Remove {account.uid} from Active Status') ldap_set_inactive(account) return jsonify({"success": True}), 200 @@ -592,7 +582,7 @@ def export_active_list(): @member_management_bp.route('/manage/current/', methods=['POST', 'DELETE']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def remove_current_student(uid, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -602,16 +592,16 @@ def remove_current_student(uid, user_dict=None): member = ldap_get_member(uid) if request.method == 'DELETE': - log.info('Remove {} from Current Student'.format(uid)) + log.info(f'Remove {uid} from Current Student') ldap_set_non_current_student(member) elif request.method == 'POST': - log.info('Add {} to Current Students'.format(uid)) + log.info(f'Add {uid} to Current Students') ldap_set_current_student(member) return jsonify({"success": True}), 200 @member_management_bp.route('/manage/new', methods=['GET']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def new_year(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/blueprints/slideshow.py b/conditional/blueprints/slideshow.py index c745e24..1ea953d 100644 --- a/conditional/blueprints/slideshow.py +++ b/conditional/blueprints/slideshow.py @@ -20,7 +20,7 @@ @slideshow_bp.route('/slideshow/intro') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_intro_display(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -36,7 +36,7 @@ def slideshow_intro_display(user_dict=None): @slideshow_bp.route('/slideshow/intro/members') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_intro_members(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -49,7 +49,7 @@ def slideshow_intro_members(user_dict=None): @slideshow_bp.route('/slideshow/intro/review', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_intro_review(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -61,7 +61,7 @@ def slideshow_intro_review(user_dict=None): uid = post_data['uid'] status = post_data['status'] - log.info('Intro Eval for {}: {}'.format(uid, status)) + log.info(f'Intro Eval for {uid}: {status}') FreshmanEvalData.query.filter( FreshmanEvalData.uid == uid and FreshmanEvalData.active). \ @@ -76,7 +76,7 @@ def slideshow_intro_review(user_dict=None): @slideshow_bp.route('/slideshow/spring') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_spring_display(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -92,7 +92,7 @@ def slideshow_spring_display(user_dict=None): @slideshow_bp.route('/slideshow/spring/members') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_spring_members(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -105,7 +105,7 @@ def slideshow_spring_members(user_dict=None): @slideshow_bp.route('/slideshow/spring/review', methods=['POST']) -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def slideshow_spring_review(user_dict=None): log = logger.new(request=request, auth_dict=user_dict) @@ -117,7 +117,7 @@ def slideshow_spring_review(user_dict=None): uid = post_data['uid'] status = post_data['status'] - log.info('Spring Eval for {}: {}'.format(uid, status)) + log.info(f'Spring Eval for {uid}: {status}') SpringEval.query.filter( SpringEval.uid == uid and diff --git a/conditional/blueprints/spring_evals.py b/conditional/blueprints/spring_evals.py index e8c6e1d..212ca88 100644 --- a/conditional/blueprints/spring_evals.py +++ b/conditional/blueprints/spring_evals.py @@ -17,7 +17,7 @@ @spring_evals_bp.route('/spring_evals/') -@auth.oidc_auth +@auth.oidc_auth("default") @get_user def display_spring_evals(internal=False, user_dict=None): log = logger.new(request=request, auth_dict=user_dict) diff --git a/conditional/models/models.py b/conditional/models/models.py index fec3036..423795e 100644 --- a/conditional/models/models.py +++ b/conditional/models/models.py @@ -18,7 +18,7 @@ class FreshmanAccount(db.Model): signatures_missed = Column(Integer) rit_username = Column(String(10), nullable=True) - def __init__(self, name, onfloor, room=None, missed=None, rit_username=None): + def __init__(self, name, onfloor, room=None, missed=None, rit_username=None): # pylint: disable=too-many-positional-arguments self.name = name today = date.fromtimestamp(time.time()) self.eval_date = today + timedelta(weeks=6) @@ -32,8 +32,7 @@ class FreshmanEvalData(db.Model): __tablename__ = 'freshman_eval_data' id = Column(Integer, primary_key=True) uid = Column(String(32), nullable=False) - freshman_project = Column(Enum('Pending', 'Passed', 'Failed', - name="freshman_project_enum"), nullable=True) + freshman_project = Column(Enum('Pending', 'Passed', 'Failed', name="freshman_project_enum"), nullable=True) eval_date = Column(DateTime, nullable=False) signatures_missed = Column(Integer, nullable=False) social_events = Column(Text) @@ -143,7 +142,7 @@ class MajorProject(db.Model): name="major_project_enum"), nullable=False) - def __init__(self, uid, name, tldr, time, desc): + def __init__(self, uid, name, tldr, time, desc): # pylint: disable=too-many-positional-arguments,redefined-outer-name self.uid = uid self.date = datetime.now() self.name = name @@ -233,7 +232,7 @@ class Conditional(db.Model): s_evaluation = Column(ForeignKey('spring_evals.id')) i_evaluation = Column(ForeignKey('freshman_eval_data.id')) - def __init__(self, uid, description, due, s_eval=None, i_eval=None): + def __init__(self, uid, description, due, s_eval=None, i_eval=None): # pylint: disable=too-many-positional-arguments self.uid = uid self.description = description self.date_due = due @@ -293,7 +292,7 @@ class UserLog(db.Model): path = Column(String(128), nullable=False) description = Column(String(128), nullable=False) - def __init__(self, ipaddr, user, method, blueprint, path, description): + def __init__(self, ipaddr, user, method, blueprint, path, description): # pylint: disable=too-many-positional-arguments self.ipaddr = ipaddr self.timestamp = datetime.now() self.uid = user diff --git a/conditional/util/context_processors.py b/conditional/util/context_processors.py index feecb10..766e4d8 100644 --- a/conditional/util/context_processors.py +++ b/conditional/util/context_processors.py @@ -33,7 +33,9 @@ def check_current_student(username): @app.context_processor def utility_processor(): - return dict( - get_csh_name=get_csh_name, get_freshman_name=get_freshman_name, get_member_name=get_member_name, - check_current_student=check_current_student - ) + return { + "get_csh_name": get_csh_name, + "get_freshman_name": get_freshman_name, + "get_member_name": get_member_name, + "check_current_student": check_current_student + } diff --git a/requirements.in b/requirements.in index 5636cd6..2526aaf 100644 --- a/requirements.in +++ b/requirements.in @@ -1,33 +1,33 @@ -alembic~=0.9.8 -astroid~=2.4.0 +alembic~=1.15.1 +astroid~=3.3.9 blinker~=1.4 boto3==1.35.13 botocore==1.35.13 -click~=7.1 +click~=8.1.8 csh_ldap>=2.3.1 -ddtrace~=1.1.4 -Flask~=1.1.4 +ddtrace~=3.3.1 +Flask~=3.1.0 Flask-Migrate~=2.1.1 Flask-Gzip~=0.2 -Flask-pyoidc~=1.3.0 -Flask-SQLAlchemy~=2.3.2 +Flask-pyoidc~=3.14.3 +Flask-SQLAlchemy~=3.1.1 gunicorn~=20.1.0 isort~=4.3.4 -itsdangerous~=0.24 -Jinja2~=2.10 +itsdangerous~=2.2.0 +Jinja2~=3.1.6 lazy-object-proxy~=1.4.0 Mako~=1.0.7 -MarkupSafe~=1.0 +MarkupSafe~=3.0.2 mccabe~=0.6.1 -oic~=0.11.0 -pip-tools~=6.6.2 +oic~=1.6.1 +pip-tools~=7.4.1 psycopg2-binary~=2.9.3 -pylint~=2.6.0 +pylint~=3.3.6 python-dateutil~=2.6.1 python-editor~=1.0.3 -sentry-sdk[flask]~=0.19.5 -six~=1.12.0 -SQLAlchemy~=1.3.22 +sentry-sdk[flask]~=2.24.1 +six~=1.17.0 +SQLAlchemy~=2.0.40 structlog~=18.1.0 -Werkzeug~=0.15.3 +Werkzeug~=3.1.3 wrapt~=1.11.0 diff --git a/requirements.txt b/requirements.txt index 3bc182c..6ff2705 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,29 +1,35 @@ # -# This file is autogenerated by pip-compile with python 3.8 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.13 +# by the following command: # # pip-compile requirements.in # -alabaster==0.7.12 - # via oic -alembic==0.9.10 +alembic==1.15.1 # via # -r requirements.in # flask-migrate -astroid==2.4.2 +annotated-types==0.7.0 + # via pydantic +astroid==3.3.9 # via # -r requirements.in # pylint -attrs==21.4.0 - # via ddtrace -beaker==1.11.0 - # via oic -blinker==1.4 +blinker==1.9.0 # via # -r requirements.in + # flask # sentry-sdk boto3==1.35.13 + # via -r requirements.in botocore==1.35.13 + # via + # -r requirements.in + # boto3 + # s3transfer +build==1.2.2.post1 + # via pip-tools +bytecode==0.16.1 + # via ddtrace certifi==2022.5.18.1 # via # requests @@ -32,22 +38,28 @@ cffi==1.15.0 # via cryptography charset-normalizer==2.0.12 # via requests -click==7.1.2 +click==8.1.8 # via # -r requirements.in # flask # pip-tools cryptography==37.0.2 - # via pyopenssl + # via oic csh-ldap==2.3.1 # via -r requirements.in -ddsketch==2.0.3 - # via ddtrace -ddtrace==1.1.4 +ddtrace==3.3.1 # via -r requirements.in +defusedxml==0.7.1 + # via oic +deprecated==1.2.18 + # via opentelemetry-api +dill==0.3.9 + # via pylint dnspython==2.2.1 # via srvlookup -flask==1.1.4 +envier==0.6.1 + # via ddtrace +flask==3.1.0 # via # -r requirements.in # flask-gzip @@ -59,64 +71,74 @@ flask-gzip==0.2 # via -r requirements.in flask-migrate==2.1.1 # via -r requirements.in -flask-pyoidc==1.3.0 +flask-pyoidc==3.14.3 # via -r requirements.in -flask-sqlalchemy==2.3.2 +flask-sqlalchemy==3.1.1 # via # -r requirements.in # flask-migrate future==0.18.2 - # via - # oic - # pyjwkest + # via pyjwkest +greenlet==3.1.1 + # via sqlalchemy gunicorn==20.1.0 # via -r requirements.in idna==3.3 # via requests +importlib-metadata==8.6.1 + # via opentelemetry-api +importlib-resources==6.5.2 + # via flask-pyoidc isort==4.3.21 # via # -r requirements.in # pylint -itsdangerous==0.24 +itsdangerous==2.2.0 # via # -r requirements.in # flask -jinja2==2.11.3 +jinja2==3.1.6 # via # -r requirements.in # flask -lazy-object-proxy==1.4.3 +jmespath==1.0.1 # via - # -r requirements.in - # astroid + # boto3 + # botocore +lazy-object-proxy==1.4.3 + # via -r requirements.in +legacy-cgi==2.6.3 + # via ddtrace mako==1.0.14 # via # -r requirements.in # alembic # oic -markupsafe==1.1.1 +markupsafe==3.0.2 # via # -r requirements.in # jinja2 # mako + # sentry-sdk + # werkzeug mccabe==0.6.1 # via # -r requirements.in # pylint -oic==0.11.0.1 +oic==1.6.1 # via # -r requirements.in # flask-pyoidc -packaging==21.3 +opentelemetry-api==1.31.1 # via ddtrace -pep517==0.12.0 - # via pip-tools -pip-tools==6.6.2 +packaging==24.2 + # via build +pip-tools==7.4.1 # via -r requirements.in +platformdirs==4.3.7 + # via pylint protobuf==3.20.1 - # via - # ddsketch - # ddtrace + # via ddtrace psycopg2-binary==2.9.3 # via -r requirements.in pyasn1==0.4.8 @@ -131,41 +153,46 @@ pycryptodomex==3.14.1 # via # oic # pyjwkest +pydantic==2.11.0 + # via pydantic-settings +pydantic-core==2.33.0 + # via pydantic +pydantic-settings==2.8.1 + # via oic pyjwkest==1.4.2 # via oic -pylint==2.6.2 +pylint==3.3.6 # via -r requirements.in -pyopenssl==22.0.0 - # via oic -pyparsing==3.0.9 - # via packaging +pyproject-hooks==1.2.0 + # via + # build + # pip-tools python-dateutil==2.6.1 # via # -r requirements.in - # alembic + # botocore +python-dotenv==1.1.0 + # via pydantic-settings python-editor==1.0.4 - # via - # -r requirements.in - # alembic + # via -r requirements.in python-ldap==3.0.0 # via csh-ldap requests==2.27.1 # via + # flask-pyoidc # oic # pyjwkest -sentry-sdk[flask]==0.19.5 +s3transfer==0.10.4 + # via boto3 +sentry-sdk[flask]==2.24.1 # via -r requirements.in -six==1.12.0 +six==1.17.0 # via # -r requirements.in - # astroid - # ddsketch - # ddtrace - # oic # pyjwkest # python-dateutil # structlog -sqlalchemy==1.3.24 +sqlalchemy==2.0.40 # via # -r requirements.in # alembic @@ -174,17 +201,24 @@ srvlookup==2.0.0 # via csh-ldap structlog==18.1.0 # via -r requirements.in -tenacity==8.0.1 - # via ddtrace -toml==0.10.2 +tomlkit==0.13.2 # via pylint -tomli==2.0.1 - # via pep517 -urllib3==1.26.9 +typing-extensions==4.13.0 # via + # alembic + # ddtrace + # pydantic + # pydantic-core + # sqlalchemy + # typing-inspection +typing-inspection==0.4.0 + # via pydantic +urllib3==1.26.20 + # via + # botocore # requests # sentry-sdk -werkzeug==0.15.6 +werkzeug==3.1.3 # via # -r requirements.in # flask @@ -193,7 +227,12 @@ wheel==0.37.1 wrapt==1.11.2 # via # -r requirements.in - # astroid + # ddtrace + # deprecated +xmltodict==0.14.2 + # via ddtrace +zipp==3.21.0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip