Skip to content

Commit 797769a

Browse files
Gatekeep fix (#465)
* Fix Gatekeep to constitional requirements * Gatekeep does all constitutional things now * rename variable for legibility * fix json response * lint fix --------- Co-authored-by: Noah Hanford (spaced) <spaced@csh.rit.edu>
1 parent 94a7dc9 commit 797769a

2 files changed

Lines changed: 72 additions & 44 deletions

File tree

conditional/__init__.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def database_processor(logger, log_method, event_dict): # pylint: disable=unuse
108108
# pylint: disable=wrong-import-order
109109
from conditional.util import context_processors
110110
from conditional.util.auth import get_user
111-
from conditional.util.member import gatekeep_status
111+
from conditional.util.member import gatekeep_status, get_voting_members
112112
from .blueprints.dashboard import dashboard_bp # pylint: disable=ungrouped-imports
113113
from .blueprints.attendance import attendance_bp
114114
from .blueprints.major_project_submission import major_project_bp
@@ -167,7 +167,7 @@ def health():
167167

168168

169169
@app.route("/gatekeep/<username>")
170-
def gatekeep(username):
170+
def gatekeep_user(username):
171171
token = request.headers.get("X-VOTE-TOKEN", "")
172172
if token != app.config["VOTE_TOKEN"]:
173173
return "Users cannot access this page", 403
@@ -178,6 +178,13 @@ def gatekeep(username):
178178

179179
return gatekeep_data, 200
180180

181+
@app.route("/gatekeep")
182+
def gatekeep_all():
183+
token = request.headers.get("X-VOTE-TOKEN", "")
184+
if token != app.config["VOTE_TOKEN"]:
185+
return "Users cannot access this page", 403
186+
return list(get_voting_members()), 200
187+
181188

182189
@app.errorhandler(404)
183190
@app.errorhandler(500)

conditional/util/member.py

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from sqlalchemy import func, or_
33

44
from conditional import start_of_year
5-
from conditional.models.models import CommitteeMeeting
5+
from conditional.models.models import CommitteeMeeting, FreshmanAccount
66
from conditional.models.models import CurrentCoops
77
from conditional.models.models import FreshmanEvalData
88
from conditional.models.models import HouseMeeting
@@ -21,6 +21,7 @@
2121
from conditional.util.ldap import ldap_is_intromember
2222
from conditional.util.ldap import ldap_get_member
2323

24+
2425
@service_cache(maxsize=1024)
2526
def get_members_info():
2627
members = ldap_get_current_students()
@@ -57,18 +58,18 @@ def get_freshman_data(user_name):
5758
MemberCommitteeAttendance.query.filter(
5859
MemberCommitteeAttendance.uid == user_name
5960
) if CommitteeMeeting.query.filter(
60-
CommitteeMeeting.id == m.meeting_id).first().approved]
61+
CommitteeMeeting.id == m.meeting_id).first().approved]
6162
freshman['committee_meetings'] = len(c_meetings)
6263
# technical seminar total
6364
t_seminars = [s.seminar_id for s in
6465
MemberSeminarAttendance.query.filter(
6566
MemberSeminarAttendance.uid == user_name
6667
) if TechnicalSeminar.query.filter(
67-
TechnicalSeminar.id == s.seminar_id).first().approved]
68+
TechnicalSeminar.id == s.seminar_id).first().approved]
6869
freshman['ts_total'] = len(t_seminars)
6970
attendance = [m.name for m in TechnicalSeminar.query.filter(
7071
TechnicalSeminar.id.in_(t_seminars)
71-
)]
72+
)]
7273

7374
freshman['ts_list'] = attendance
7475

@@ -114,20 +115,20 @@ def get_cm(member):
114115

115116
def get_hm(member, only_absent=False):
116117
h_meetings = MemberHouseMeetingAttendance.query.outerjoin(
117-
HouseMeeting,
118-
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id).with_entities(
119-
MemberHouseMeetingAttendance.meeting_id,
120-
MemberHouseMeetingAttendance.attendance_status,
121-
HouseMeeting.date).filter(
122-
HouseMeeting.date > start_of_year(),
123-
MemberHouseMeetingAttendance.uid == member.uid)
118+
HouseMeeting,
119+
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id).with_entities(
120+
MemberHouseMeetingAttendance.meeting_id,
121+
MemberHouseMeetingAttendance.attendance_status,
122+
HouseMeeting.date).filter(
123+
HouseMeeting.date > start_of_year(),
124+
MemberHouseMeetingAttendance.uid == member.uid)
124125
if only_absent:
125126
h_meetings = h_meetings.filter(MemberHouseMeetingAttendance.attendance_status == "Absent")
126127
return h_meetings
127128

128129

129130
# @service_cache(maxsize=128)
130-
def req_cm(uid, members_on_coop = None):
131+
def req_cm(uid, members_on_coop=None):
131132
# Get the number of required committee meetings based on if the member
132133
# is going on co-op in the current operating session.
133134
on_coop = False
@@ -143,14 +144,16 @@ def req_cm(uid, members_on_coop = None):
143144
return 15
144145
return 30
145146

147+
146148
@service_cache(maxsize=256)
147149
def get_voting_members():
148-
if datetime.today() < datetime(start_of_year().year, 12, 31):
150+
today = datetime.today()
151+
if today < datetime(start_of_year().year, 12, 31):
149152
semester = "Fall"
150-
semester_start = datetime(start_of_year().year,6,1)
153+
semester_start = datetime(start_of_year().year, 6, 1)
151154
else:
152155
semester = "Spring"
153-
semester_start = datetime(start_of_year().year + 1,1,1)
156+
semester_start = datetime(start_of_year().year + 1, 1, 1)
154157

155158
active_members = set(ldap_get_active_members())
156159
intro_members = set(ldap_get_intro_members())
@@ -169,8 +172,8 @@ def get_voting_members():
169172
coop_members = set(coop_members)
170173

171174
passed_fall_members = FreshmanEvalData.query.filter(
172-
FreshmanEvalData.freshman_eval_result == "Passed",
173-
FreshmanEvalData.eval_date > start_of_year(),
175+
FreshmanEvalData.freshman_eval_result == "Passed",
176+
FreshmanEvalData.eval_date > start_of_year(),
174177
).with_entities(
175178
func.array_agg(FreshmanEvalData.uid)
176179
).scalar()
@@ -185,6 +188,12 @@ def get_voting_members():
185188

186189
elligible_members = (active_not_intro - coop_members) | passed_fall_members
187190

191+
# Check to see if there's an Intro Evals in the future of this semester. If there is, everyone gets to vote!
192+
before_evals_one = len(FreshmanAccount.query.filter(FreshmanAccount.eval_date > today).limit(1).all())
193+
before_evals_two = len(FreshmanEvalData.query.filter(FreshmanEvalData.eval_date > today).limit(1).all())
194+
if before_evals_one > 0 or before_evals_two > 0:
195+
return elligible_members
196+
188197
passing_dm = set(member.uid for member in MemberCommitteeAttendance.query.join(
189198
CommitteeMeeting,
190199
MemberCommitteeAttendance.meeting_id == CommitteeMeeting.id
@@ -200,7 +209,7 @@ def get_voting_members():
200209
).group_by(
201210
MemberCommitteeAttendance.uid
202211
).having(
203-
func.count(MemberCommitteeAttendance.uid) >= 6 #pylint: disable=not-callable
212+
func.count(MemberCommitteeAttendance.uid) >= 6 # pylint: disable=not-callable
204213
).with_entities(
205214
MemberCommitteeAttendance.uid
206215
).all())
@@ -216,58 +225,69 @@ def get_voting_members():
216225
).group_by(
217226
MemberSeminarAttendance.uid
218227
).having(
219-
func.count(MemberSeminarAttendance.uid) >= 2 #pylint: disable=not-callable
228+
func.count(MemberSeminarAttendance.uid) >= 2 # pylint: disable=not-callable
220229
).all())
221230

222-
passing_hm = set(member.uid for member in MemberHouseMeetingAttendance.query.join(
231+
absent_hm = set(member.uid for member in MemberHouseMeetingAttendance.query.join(
223232
HouseMeeting,
224233
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id
225234
).filter(
226235
HouseMeeting.date >= semester_start, or_(
227-
MemberHouseMeetingAttendance.attendance_status == 'Attended',
228-
# MemberHouseMeetingAttendance.attendance_status == 'Excused'
236+
MemberHouseMeetingAttendance.attendance_status == 'Absent',
229237
)
230238
).with_entities(
231239
MemberHouseMeetingAttendance.uid
232240
).group_by(
233241
MemberHouseMeetingAttendance.uid
234242
).having(
235-
func.count(MemberHouseMeetingAttendance.uid) >= 6 #pylint: disable=not-callable
243+
func.count(MemberHouseMeetingAttendance.uid) > 1 # pylint: disable=not-callable
236244
).all())
237245

238-
passing_reqs = passing_dm & passing_ts & passing_hm
246+
passing_reqs = (passing_dm & passing_ts) - absent_hm
239247

240248
return elligible_members & passing_reqs
241249

250+
242251
def gatekeep_status(username):
243-
if datetime.today() < datetime(start_of_year().year, 12, 31):
252+
today = datetime.today()
253+
# Check to see if there's an Intro Evals in the future of this semester. If there is, everyone gets to vote!
254+
before_evals_one = len(FreshmanAccount.query.filter(FreshmanAccount.eval_date > today).limit(1).all())
255+
before_evals_two = len(FreshmanEvalData.query.filter(FreshmanEvalData.eval_date > today).limit(1).all())
256+
if before_evals_one > 0 or before_evals_two > 0:
257+
return {
258+
"result": True,
259+
"h_meetings_missed": 0,
260+
"c_meetings": 0,
261+
"t_seminars": 0,
262+
}
263+
if today < datetime(start_of_year().year, 12, 31):
244264
semester = "Fall"
245-
semester_start = datetime(start_of_year().year,6,1)
265+
semester_start = datetime(start_of_year().year, 6, 1)
246266
else:
247267
semester = "Spring"
248-
semester_start = datetime(start_of_year().year + 1,1,1)
268+
semester_start = datetime(start_of_year().year + 1, 1, 1)
249269

250270
# groups
251271
ldap_member = ldap_get_member(username)
252272
is_intro_member = ldap_is_intromember(ldap_member)
253273
is_active_member = ldap_is_active(ldap_member) and not is_intro_member
254274

255275
is_on_coop = (
256-
CurrentCoops.query.filter(
257-
CurrentCoops.date_created > start_of_year(),
258-
CurrentCoops.semester == semester,
259-
CurrentCoops.uid == username,
260-
).first()
261-
is not None
276+
CurrentCoops.query.filter(
277+
CurrentCoops.date_created > start_of_year(),
278+
CurrentCoops.semester == semester,
279+
CurrentCoops.uid == username,
280+
).first()
281+
is not None
262282
)
263283

264284
passed_fall = (
265-
FreshmanEvalData.query.filter(
266-
FreshmanEvalData.freshman_eval_result == "Passed",
267-
FreshmanEvalData.eval_date > start_of_year(),
268-
FreshmanEvalData.uid == username,
269-
).first()
270-
is not None
285+
FreshmanEvalData.query.filter(
286+
FreshmanEvalData.freshman_eval_result == "Passed",
287+
FreshmanEvalData.eval_date > start_of_year(),
288+
FreshmanEvalData.uid == username,
289+
).first()
290+
is not None
271291
)
272292
eligibility_of_groups = (is_active_member and not is_on_coop) or passed_fall
273293

@@ -298,22 +318,23 @@ def gatekeep_status(username):
298318
.count()
299319
)
300320
# number of house meetings attended in the current semester
301-
h_meetings = (
321+
h_meetings_missed = (
302322
MemberHouseMeetingAttendance.query.join(
303323
HouseMeeting,
304324
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id,
305325
)
306326
.filter(
327+
MemberHouseMeetingAttendance.attendance_status == 'Absent',
307328
MemberHouseMeetingAttendance.uid == username,
308329
HouseMeeting.date >= semester_start
309330
)
310331
.count()
311332
)
312-
result = eligibility_of_groups and (d_meetings >= 6 and t_seminars >= 2 and h_meetings >= 6)
333+
result = eligibility_of_groups and (d_meetings >= 6 and t_seminars >= 2 and h_meetings_missed < 2) # pylint: disable=chained-comparison
313334

314335
return {
315336
"result": result,
316-
"h_meetings": h_meetings,
337+
"h_meetings_missed": h_meetings_missed,
317338
"c_meetings": d_meetings,
318339
"t_seminars": t_seminars,
319340
}

0 commit comments

Comments
 (0)