Skip to content

Commit 28d2288

Browse files
Merge pull request #110 from ComputerScienceHouse/develop
Conditional v1.3
2 parents 90e7702 + 7ae0095 commit 28d2288

38 files changed

+1511
-719
lines changed

app.py

-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
import os
21
from conditional import app
3-
from conditional.util.ldap import ldap_init
4-
5-
app.config.from_pyfile(os.path.join(os.getcwd(), "config.py"))
6-
7-
ldap_init(app.config['LDAP_RO'],
8-
app.config['LDAP_URL'],
9-
app.config['LDAP_BIND_DN'],
10-
app.config['LDAP_BIND_PW'],
11-
app.config['LDAP_USER_OU'],
12-
app.config['LDAP_GROUP_OU'],
13-
app.config['LDAP_COMMITTEE_OU'])
142

153
if __name__ == "__main__":
164
app.run(host=app.config['IP'], port=app.config['PORT'])

conditional/__init__.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1+
import os
2+
import subprocess
13
from flask import Flask
24
from flask import redirect
35
from flask_sqlalchemy import SQLAlchemy
46
from flask_migrate import Migrate
7+
from csh_ldap import CSHLDAP
58
import structlog
69

710
app = Flask(__name__)
811

12+
config = os.path.join(os.getcwd(), "config.py")
13+
14+
app.config.from_pyfile(config)
915
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
1016

17+
app.config["GIT_REVISION"] = subprocess.check_output(['git',
18+
'rev-parse',
19+
'--short',
20+
'HEAD']).decode('utf-8').rstrip()
1121
db = SQLAlchemy(app)
1222
migrate = Migrate(app, db)
1323
logger = structlog.get_logger()
1424

25+
ldap = CSHLDAP(app.config['LDAP_BIND_DN'],
26+
app.config['LDAP_BIND_PW'],
27+
ro=app.config['LDAP_RO'])
28+
1529
# pylint: disable=C0413
1630

1731
from conditional.blueprints.dashboard import dashboard_bp
@@ -38,8 +52,6 @@
3852
app.register_blueprint(slideshow_bp)
3953
app.register_blueprint(cache_bp)
4054

41-
logger.info('conditional started')
42-
4355

4456
@app.route('/<path:path>')
4557
def static_proxy(path):
@@ -56,3 +68,5 @@ def default_route():
5668
def zoo():
5769
from conditional.models.migrate import free_the_zoo
5870
free_the_zoo(app.config['ZOO_DATABASE_URI'])
71+
72+
logger.info('conditional started')

conditional/blueprints/attendance.py

+151-45
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
from flask import Blueprint, jsonify, redirect, request
77

88
from conditional.util.ldap import ldap_get_current_students
9-
from conditional.util.ldap import ldap_is_eboard
10-
from conditional.util.ldap import ldap_is_eval_director
119
from conditional.util.ldap import ldap_get_active_members
10+
from conditional.util.ldap import ldap_is_eval_director
11+
from conditional.util.ldap import ldap_is_eboard
12+
from conditional.util.ldap import ldap_get_member
1213

1314
from conditional.models.models import CurrentCoops
1415
from conditional.models.models import CommitteeMeeting
@@ -31,10 +32,6 @@
3132
attendance_bp = Blueprint('attendance_bp', __name__)
3233

3334

34-
def get_name(m):
35-
return m['cn'][0].decode('utf-8')
36-
37-
3835
@attendance_bp.route('/attendance/ts_members')
3936
def get_all_members():
4037
log = logger.new(user_name=request.headers.get("x-webauth-user"),
@@ -51,14 +48,11 @@ def get_all_members():
5148
} for f in FreshmanAccount.query.filter(
5249
FreshmanAccount.eval_date > datetime.now())]
5350

54-
for m in members:
55-
uid = m['uid'][0].decode('utf-8')
56-
name = "{name} ({uid})".format(name=get_name(m), uid=uid)
57-
51+
for account in members:
5852
named_members.append(
5953
{
60-
'display': name,
61-
'value': uid,
54+
'display': account.displayName,
55+
'value': account.uid,
6256
'freshman': False
6357
})
6458

@@ -71,37 +65,34 @@ def get_non_alumni_non_coop(internal=False):
7165
request_id=str(uuid.uuid4()))
7266
log.info('api', action='retrieve house meeting attendance list')
7367

74-
# Only Members Who Have Paid Dues Are Required to
75-
# go to house meetings
76-
non_alumni_members = ldap_get_active_members()
68+
# Get all active members as a base house meeting attendance.
69+
active_members = ldap_get_active_members()
7770
coop_members = [u.uid for u in CurrentCoops.query.all()]
7871

79-
named_members = [
72+
eligible_members = [
8073
{
8174
'display': f.name,
8275
'value': f.id,
8376
'freshman': True
8477
} for f in FreshmanAccount.query.filter(
8578
FreshmanAccount.eval_date > datetime.now())]
8679

87-
for m in non_alumni_members:
88-
uid = m['uid'][0].decode('utf-8')
89-
90-
if uid in coop_members:
91-
continue
92-
name = "{name} ({uid})".format(name=get_name(m), uid=uid)
80+
for account in active_members:
81+
if account.uid in coop_members:
82+
# Members who are on co-op don't need to go to house meeting.
83+
pass
9384

94-
named_members.append(
85+
eligible_members.append(
9586
{
96-
'display': name,
97-
'value': uid,
87+
'display': account.displayName,
88+
'value': account.uid,
9889
'freshman': False
9990
})
10091

10192
if internal:
102-
return named_members
93+
return eligible_members
10394
else:
104-
return jsonify({'members': named_members}), 200
95+
return jsonify({'members': eligible_members}), 200
10596

10697

10798
@attendance_bp.route('/attendance/cm_members')
@@ -110,27 +101,25 @@ def get_non_alumni():
110101
request_id=str(uuid.uuid4()))
111102
log.info('api', action='retrieve committee meeting attendance list')
112103

113-
non_alumni_members = ldap_get_current_students()
104+
current_students = ldap_get_current_students()
114105

115-
named_members = [
106+
eligible_members = [
116107
{
117108
'display': f.name,
118109
'value': f.id,
119110
'freshman': True
120111
} for f in FreshmanAccount.query.filter(
121112
FreshmanAccount.eval_date > datetime.now())]
122-
for m in non_alumni_members:
123-
uid = m['uid'][0].decode('utf-8')
124-
name = "{name} ({uid})".format(name=get_name(m), uid=uid)
125113

126-
named_members.append(
114+
for account in current_students:
115+
eligible_members.append(
127116
{
128-
'display': name,
129-
'value': uid,
117+
'display': account.displayName,
118+
'value': account.uid,
130119
'freshman': False
131120
})
132121

133-
return jsonify({'members': named_members}), 200
122+
return jsonify({'members': eligible_members}), 200
134123

135124

136125
@attendance_bp.route('/attendance_cm')
@@ -140,7 +129,8 @@ def display_attendance_cm():
140129
log.info('frontend', action='display committee meeting attendance page')
141130

142131
user_name = request.headers.get('x-webauth-user')
143-
if not ldap_is_eboard(user_name):
132+
account = ldap_get_member(user_name)
133+
if not ldap_is_eboard(account):
144134
return redirect("/dashboard")
145135

146136
return render_template(request,
@@ -156,7 +146,8 @@ def display_attendance_ts():
156146
log.info('frontend', action='display technical seminar attendance page')
157147

158148
user_name = request.headers.get('x-webauth-user')
159-
if not ldap_is_eboard(user_name):
149+
account = ldap_get_member(user_name)
150+
if not ldap_is_eboard(account):
160151
return redirect("/dashboard")
161152

162153
return render_template(request,
@@ -172,7 +163,8 @@ def display_attendance_hm():
172163
log.info('frontend', action='display house meeting attendance page')
173164

174165
user_name = request.headers.get('x-webauth-user')
175-
if not ldap_is_eval_director(user_name):
166+
account = ldap_get_member(user_name)
167+
if not ldap_is_eval_director(account):
176168
return redirect("/dashboard")
177169

178170
return render_template(request,
@@ -189,8 +181,8 @@ def submit_committee_attendance():
189181
log.info('api', action='submit committee meeting attendance')
190182

191183
user_name = request.headers.get('x-webauth-user')
192-
193-
if not ldap_is_eboard(user_name):
184+
account = ldap_get_member(user_name)
185+
if not ldap_is_eboard(account):
194186
return "must be eboard", 403
195187

196188
post_data = request.get_json()
@@ -232,7 +224,8 @@ def submit_seminar_attendance():
232224

233225
user_name = request.headers.get('x-webauth-user')
234226

235-
if not ldap_is_eboard(user_name):
227+
account = ldap_get_member(user_name)
228+
if not ldap_is_eboard(account):
236229
return "must be eboard", 403
237230

238231
post_data = request.get_json()
@@ -275,7 +268,8 @@ def submit_house_attendance():
275268

276269
user_name = request.headers.get('x-webauth-user')
277270

278-
if not ldap_is_eval_director(user_name):
271+
account = ldap_get_member(user_name)
272+
if not ldap_is_eval_director(account):
279273
return "must be evals", 403
280274

281275
post_data = request.get_json()
@@ -321,7 +315,8 @@ def submit_house_attendance():
321315
def alter_house_attendance(uid, hid):
322316
user_name = request.headers.get('x-webauth-user')
323317

324-
if not ldap_is_eval_director(user_name):
318+
account = ldap_get_member(user_name)
319+
if not ldap_is_eval_director(account):
325320
return "must be evals", 403
326321

327322
if not uid.isdigit():
@@ -351,7 +346,8 @@ def alter_house_excuse(uid, hid):
351346

352347
user_name = request.headers.get('x-webauth-user')
353348

354-
if not ldap_is_eval_director(user_name):
349+
account = ldap_get_member(user_name)
350+
if not ldap_is_eval_director(account):
355351
return "must be eval director", 403
356352

357353
post_data = request.get_json()
@@ -381,3 +377,113 @@ def alter_house_excuse(uid, hid):
381377
db.session.flush()
382378
db.session.commit()
383379
return jsonify({"success": True}), 200
380+
381+
382+
@attendance_bp.route('/attendance/history', methods=['GET'])
383+
def attendance_history():
384+
385+
386+
def get_meeting_attendees(meeting_id):
387+
attendees = [ldap_get_member(a.uid).displayName for a in
388+
MemberCommitteeAttendance.query.filter(
389+
MemberCommitteeAttendance.meeting_id == meeting_id).all()]
390+
391+
for freshman in [a.fid for a in
392+
FreshmanCommitteeAttendance.query.filter(
393+
FreshmanCommitteeAttendance.meeting_id == meeting_id).all()]:
394+
attendees.append(FreshmanAccount.query.filter(
395+
FreshmanAccount.id == freshman).first().name)
396+
return attendees
397+
398+
log = logger.new(user_name=request.headers.get("x-webauth-user"),
399+
request_id=str(uuid.uuid4()))
400+
401+
user_name = request.headers.get('x-webauth-user')
402+
account = ldap_get_member(user_name)
403+
if not ldap_is_eboard(account):
404+
return "must be eboard", 403
405+
406+
if request.method == 'GET':
407+
page = request.args.get('page', 1)
408+
log.info('api', action='view past attendance submitions')
409+
offset = 0 if int(page) == 1 else ((int(page)-1)*10)
410+
limit = int(page)*10
411+
all_cm = [{"id": m.id,
412+
"directorship": m.committee,
413+
"dt_obj": m.timestamp,
414+
"date": m.timestamp.strftime("%a %m/%d/%Y"),
415+
"attendees": get_meeting_attendees(m.id)
416+
} for m in CommitteeMeeting.query.all()]
417+
c_meetings = sorted(all_cm, key=lambda k: k['dt_obj'], reverse=True)[offset:limit]
418+
if len(all_cm) % 10 != 0:
419+
total_pages = (int(len(all_cm) / 10) + 1)
420+
else:
421+
total_pages = (int(len(all_cm) / 10))
422+
return render_template(request,
423+
'attendance_history.html',
424+
username=user_name,
425+
history=c_meetings,
426+
num_pages=total_pages,
427+
current_page=int(page))
428+
429+
@attendance_bp.route('/attendance/alter/cm/<cid>', methods=['POST'])
430+
def alter_committee_attendance(cid):
431+
log = logger.new(user_name=request.headers.get("x-webauth-user"),
432+
request_id=str(uuid.uuid4()))
433+
log.info('api', action='edit committee meeting attendance')
434+
435+
user_name = request.headers.get('x-webauth-user')
436+
437+
account = ldap_get_member(user_name)
438+
if not ldap_is_eboard(account):
439+
return "must be eboard", 403
440+
441+
post_data = request.get_json()
442+
meeting_id = cid
443+
m_attendees = post_data['members']
444+
f_attendees = post_data['freshmen']
445+
446+
FreshmanCommitteeAttendance.query.filter(
447+
FreshmanCommitteeAttendance.meeting_id == meeting_id).delete()
448+
449+
MemberCommitteeAttendance.query.filter(
450+
MemberCommitteeAttendance.meeting_id == meeting_id).delete()
451+
452+
for m in m_attendees:
453+
db.session.add(MemberCommitteeAttendance(m, meeting_id))
454+
455+
for f in f_attendees:
456+
db.session.add(FreshmanCommitteeAttendance(f, meeting_id))
457+
458+
db.session.flush()
459+
db.session.commit()
460+
return jsonify({"success": True}), 200
461+
462+
@attendance_bp.route('/attendance/cm/<cid>', methods=['GET', 'DELETE'])
463+
def get_cm_attendees(cid):
464+
if request.method == 'GET':
465+
attendees = [{"value": a.uid,
466+
"display": ldap_get_member(a.uid).displayName
467+
} for a in
468+
MemberCommitteeAttendance.query.filter(
469+
MemberCommitteeAttendance.meeting_id == cid).all()]
470+
471+
for freshman in [{"value": a.fid,
472+
"display": FreshmanAccount.query.filter(FreshmanAccount.id == a.fid).first().name
473+
} for a in FreshmanCommitteeAttendance.query.filter(
474+
FreshmanCommitteeAttendance.meeting_id == cid).all()]:
475+
attendees.append(freshman)
476+
return jsonify({"attendees": attendees}), 200
477+
478+
elif request.method == 'DELETE':
479+
FreshmanCommitteeAttendance.query.filter(
480+
FreshmanCommitteeAttendance.meeting_id == cid).delete()
481+
MemberCommitteeAttendance.query.filter(
482+
MemberCommitteeAttendance.meeting_id == cid).delete()
483+
CommitteeMeeting.query.filter(
484+
CommitteeMeeting.id == cid).delete()
485+
486+
db.session.flush()
487+
db.session.commit()
488+
489+
return jsonify({"success": True}), 200

0 commit comments

Comments
 (0)