Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packet/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ def get_rit_image(username: str) -> str:
for addr in addresses:
url = 'https://gravatar.com/avatar/' + hashlib.md5(addr.encode('utf8')).hexdigest() + '.jpg?d=404&s=250'
try:
gravatar = urllib.request.urlopen(url)
if gravatar.getcode() == 200:
return url
with urllib.request.urlopen(url) as gravatar:
if gravatar.getcode() == 200:
return url
except:
continue
return 'https://www.gravatar.com/avatar/freshmen?d=mp&f=y'
Expand Down
8 changes: 6 additions & 2 deletions packet/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@

class MockMember:

def __init__(self, uid: str, groups: list = None, cn: str = None, room_number: int = None):
def __init__(self,
uid: str,
groups: Optional[list] = None,
cn: Optional[str] = None,
room_number: Optional[int] = None):
self.uid = uid
self.groups = groups if groups else list()
if room_number:
Expand All @@ -37,7 +41,7 @@ def __repr__(self) -> str:

class LDAPWrapper:

def __init__(self, cshldap: CSHLDAP = None, mock_members: list[MockMember] = None):
def __init__(self, cshldap: Optional[CSHLDAP] = None, mock_members: Optional[list[MockMember]] = None):
self.ldap = cshldap
self.mock_members = cast(list[MockMember], mock_members)
if self.ldap:
Expand Down
8 changes: 4 additions & 4 deletions packet/mail.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TypedDict
from typing import TypedDict, List, Union, cast

from flask import render_template
from flask_mail import Mail, Message
Expand All @@ -15,10 +15,10 @@ class ReportForm(TypedDict):

def send_start_packet_mail(packet: Packet) -> None:
if app.config['MAIL_PROD']:
recipients = ['<' + packet.freshman.rit_username + '@rit.edu>']
recipients = ['<' + str(packet.freshman.rit_username) + '@rit.edu>']
msg = Message(subject='CSH Packet Starts ' + packet.start.strftime('%A, %B %-d'),
sender=app.config.get('MAIL_USERNAME'),
recipients=recipients)
recipients=cast(List[Union[str, tuple[str, str]]], recipients))

template = 'mail/packet_start'
msg.body = render_template(template + '.txt', packet=packet)
Expand All @@ -31,7 +31,7 @@ def send_report_mail(form_results: ReportForm, reporter: str) -> None:
recipients = ['<[email protected]>']
msg = Message(subject='Packet Report',
sender=app.config.get('MAIL_USERNAME'),
recipients=recipients)
recipients=cast(List[Union[str, tuple[str, str]]], recipients))

person = form_results['person']
report = form_results['report']
Expand Down
5 changes: 3 additions & 2 deletions packet/routes/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Dict, Any
from flask import render_template

from packet import app
Expand All @@ -13,7 +14,7 @@
@admin_auth
@before_request
@log_time
def admin_packets(info=None):
def admin_packets(info: Dict[str, Any]) -> str:
open_packets = Packet.open_packets()

# Pre-calculate and store the return values of did_sign(), signatures_received(), and signatures_required()
Expand All @@ -35,7 +36,7 @@ def admin_packets(info=None):
@admin_auth
@before_request
@log_time
def admin_freshmen(info=None):
def admin_freshmen(info: Dict[str, Any]) -> str:
all_freshmen = Freshman.get_all()

return render_template('admin_freshmen.html',
Expand Down
72 changes: 39 additions & 33 deletions packet/routes/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""
Shared API endpoints
"""
from datetime import datetime
from datetime import datetime, date
from json import dumps
from typing import Dict, Any, Union, Tuple

from flask import session, request

Expand All @@ -18,15 +19,15 @@


class POSTFreshman:
def __init__(self, freshman):
self.name = freshman['name'].strip()
self.rit_username = freshman['rit_username'].strip()
self.onfloor = freshman['onfloor'].strip() == 'TRUE'
def __init__(self, freshman: Dict[str, Any]) -> None:
self.name: str = freshman['name'].strip()
self.rit_username: str = freshman['rit_username'].strip()
self.onfloor: bool = freshman['onfloor'].strip() == 'TRUE'


@app.route('/api/v1/freshmen', methods=['POST'])
@packet_auth
def sync_freshman():
def sync_freshman() -> Tuple[str, int]:
"""
Create or update freshmen entries from a list

Expand All @@ -40,19 +41,21 @@ def sync_freshman():
"""

# Only allow evals to create new frosh
username = str(session['userinfo'].get('preferred_username', ''))
username: str = str(session['userinfo'].get('preferred_username', ''))
if not ldap.is_evals(ldap.get_member(username)):
return 'Forbidden: not Evaluations Director', 403

freshmen_in_post = {freshman.rit_username: freshman for freshman in map(POSTFreshman, request.json)}
freshmen_in_post: Dict[str, POSTFreshman] = {
freshman.rit_username: freshman for freshman in map(POSTFreshman, request.json)
}
sync_freshman_list(freshmen_in_post)
return dumps('Done'), 200


@app.route('/api/v1/packets', methods=['POST'])
@packet_auth
@log_time
def create_packet():
def create_packet() -> Tuple[str, int]:
"""
Create a new packet.

Expand All @@ -69,13 +72,15 @@ def create_packet():
"""

# Only allow evals to create new packets
username = str(session['userinfo'].get('preferred_username', ''))
username: str = str(session['userinfo'].get('preferred_username', ''))
if not ldap.is_evals(ldap.get_member(username)):
return 'Forbidden: not Evaluations Director', 403

base_date = datetime.strptime(request.json['start_date'], '%m/%d/%Y').date()
base_date: date = datetime.strptime(request.json['start_date'], '%m/%d/%Y').date()

freshmen_in_post = {freshman.rit_username: freshman for freshman in map(POSTFreshman, request.json['freshmen'])}
freshmen_in_post: Dict[str, POSTFreshman] = {
freshman.rit_username: freshman for freshman in map(POSTFreshman, request.json['freshmen'])
}

create_new_packets(base_date, freshmen_in_post)

Expand All @@ -85,9 +90,9 @@ def create_packet():
@app.route('/api/v1/sync', methods=['POST'])
@packet_auth
@log_time
def sync_ldap():
def sync_ldap() -> Tuple[str, int]:
# Only allow evals to sync ldap
username = str(session['userinfo'].get('preferred_username', ''))
username: str = str(session['userinfo'].get('preferred_username', ''))
if not ldap.is_evals(ldap.get_member(username)):
return 'Forbidden: not Evaluations Director', 403
sync_with_ldap()
Expand All @@ -97,14 +102,14 @@ def sync_ldap():
@app.route('/api/v1/packets/<username>', methods=['GET'])
@packet_auth
@before_request
def get_packets_by_user(username: str, info=None) -> dict:
def get_packets_by_user(username: str, info: Dict[str, Any]) -> Union[Dict[int, Dict[str, Any]], Tuple[str, int]]:
"""
Return a dictionary of packets for a freshman by username, giving packet start and end date by packet id
"""

if info['ritdn'] != username:
return 'Forbidden - not your packet', 403
frosh = Freshman.by_username(username)
frosh: Freshman = Freshman.by_username(username)

return {packet.id: {
'start': packet.start,
Expand All @@ -115,17 +120,17 @@ def get_packets_by_user(username: str, info=None) -> dict:
@app.route('/api/v1/packets/<username>/newest', methods=['GET'])
@packet_auth
@before_request
def get_newest_packet_by_user(username: str, info=None) -> dict:
def get_newest_packet_by_user(username: str, info: Dict[str, Any]) -> Union[Dict[int, Dict[str, Any]], Tuple[str, int]]:
"""
Return a user's newest packet
"""

if not info['is_upper'] and info['ritdn'] != username:
return 'Forbidden - not your packet', 403

frosh = Freshman.by_username(username)
frosh: Freshman = Freshman.by_username(username)

packet = frosh.packets[-1]
packet: Packet = frosh.packets[-1]

return {
packet.id: {
Expand All @@ -137,15 +142,15 @@ def get_newest_packet_by_user(username: str, info=None) -> dict:
}


@app.route('/api/v1/packet/<packet_id>', methods=['GET'])
@app.route('/api/v1/packet/<int:packet_id>', methods=['GET'])
@packet_auth
@before_request
def get_packet_by_id(packet_id: int, info=None) -> dict:
def get_packet_by_id(packet_id: int, info: Dict[str, Any]) -> Union[Dict[str, Dict[str, Any]], Tuple[str, int]]:
"""
Return the scores of the packet in question
"""

packet = Packet.by_id(packet_id)
packet: Packet = Packet.by_id(packet_id)

if not info['is_upper'] and info['ritdn'] != packet.freshman.rit_username:
return 'Forbidden - not your packet', 403
Expand All @@ -156,14 +161,14 @@ def get_packet_by_id(packet_id: int, info=None) -> dict:
}


@app.route('/api/v1/sign/<packet_id>/', methods=['POST'])
@app.route('/api/v1/sign/<int:packet_id>/', methods=['POST'])
@packet_auth
@before_request
def sign(packet_id, info):
packet = Packet.by_id(packet_id)
def sign(packet_id: int, info: Dict[str, Any]) -> str:
packet: Packet = Packet.by_id(packet_id)

if packet is not None and packet.is_open():
was_100 = packet.is_100()
was_100: bool = packet.is_100()
if app.config['REALM'] == 'csh':
# Check if the CSHer is an upperclassman and if so, sign that row
for sig in filter(lambda sig: sig.member == info['uid'], packet.upper_signatures):
Expand All @@ -189,8 +194,9 @@ def sign(packet_id, info):
@app.route('/api/v1/subscribe/', methods=['POST'])
@packet_auth
@before_request
def subscribe(info):
def subscribe(info: Dict[str, Any]) -> str:
data = request.form
subscription: NotificationSubscription
if app.config['REALM'] == 'csh':
subscription = NotificationSubscription(token=data['token'], member=info['uid'])
else:
Expand All @@ -203,16 +209,16 @@ def subscribe(info):
@app.route('/api/v1/report/', methods=['POST'])
@packet_auth
@before_request
def report(info):
def report(info: Dict[str, Any]) -> str:
form_results = request.form
send_report_mail(form_results, get_rit_name(info['uid']))
return 'Success: ' + get_rit_name(info['uid']) + ' sent a report'


@app.route('/api/v1/stats/packet/<packet_id>')
@app.route('/api/v1/stats/packet/<int:packet_id>')
@packet_auth
@before_request
def packet_stats(packet_id, info=None):
def packet_stats(packet_id: int, info: Dict[str, Any]) -> Union[stats.PacketStats, Tuple[str, int]]:
if not info['is_upper'] and info['ritdn'] != Packet.by_id(packet_id).freshman.rit_username:
return 'Forbidden - not your packet', 403
return stats.packet_stats(packet_id)
Expand All @@ -221,20 +227,20 @@ def packet_stats(packet_id, info=None):
@app.route('/api/v1/stats/upperclassman/<uid>')
@packet_auth
@before_request
def upperclassman_stats(uid, info=None):
def upperclassman_stats(uid: str, info: Dict[str, Any]) -> Union[stats.UpperStats, Tuple[str, int]]:
if not info['is_upper']:
return 'Forbidden', 403

return stats.upperclassman_stats(uid)


@app.route('/readiness')
def readiness() -> tuple[str, int]:
def readiness() -> Tuple[str, int]:
"""A basic healthcheck. Returns 200 to indicate flask is running"""
return 'ready', 200


def commit_sig(packet, was_100, uid):
def commit_sig(packet: Packet, was_100: bool, uid: str) -> str:
packet_signed_notification(packet, uid)
db.session.commit()
if not was_100 and packet.is_100():
Expand Down
10 changes: 7 additions & 3 deletions packet/routes/freshmen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
Routes available to freshmen only
"""

from flask import redirect, url_for
from typing import Any
from flask import Response, redirect, url_for

from packet import app
from packet.models import Packet
Expand All @@ -12,8 +13,11 @@
@app.route('/')
@packet_auth
@before_request
def index(info=None):
most_recent_packet = Packet.query.filter_by(freshman_username=info['uid']).order_by(Packet.id.desc()).first()
def index(info: dict[str, Any]) -> Response:
most_recent_packet = (Packet.query
.filter_by(freshman_username=info['uid'])
.order_by(Packet.id.desc()) # type: ignore
.first())

if most_recent_packet is not None:
return redirect(url_for('freshman_packet', packet_id=most_recent_packet.id), 302)
Expand Down
Loading