diff --git a/app.py b/app.py index ef670ef9..80621e24 100644 --- a/app.py +++ b/app.py @@ -1,16 +1,4 @@ -import os from conditional import app -from conditional.util.ldap import ldap_init - -app.config.from_pyfile(os.path.join(os.getcwd(), "config.py")) - -ldap_init(app.config['LDAP_RO'], - app.config['LDAP_URL'], - app.config['LDAP_BIND_DN'], - app.config['LDAP_BIND_PW'], - app.config['LDAP_USER_OU'], - app.config['LDAP_GROUP_OU'], - app.config['LDAP_COMMITTEE_OU']) if __name__ == "__main__": app.run(host=app.config['IP'], port=app.config['PORT']) diff --git a/conditional/__init__.py b/conditional/__init__.py index 0a1dcb87..e7c8a44f 100644 --- a/conditional/__init__.py +++ b/conditional/__init__.py @@ -1,17 +1,26 @@ +import os from flask import Flask from flask import redirect from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate +from csh_ldap import CSHLDAP import structlog app = Flask(__name__) +config = os.path.join(os.getcwd(), "config.py") + +app.config.from_pyfile(config) app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db = SQLAlchemy(app) migrate = Migrate(app, db) logger = structlog.get_logger() +ldap = CSHLDAP(app.config['LDAP_BIND_DN'], + app.config['LDAP_BIND_PW'], + ro=app.config['LDAP_RO']) + # pylint: disable=C0413 from conditional.blueprints.dashboard import dashboard_bp @@ -38,8 +47,6 @@ app.register_blueprint(slideshow_bp) app.register_blueprint(cache_bp) -logger.info('conditional started') - @app.route('/') def static_proxy(path): @@ -56,3 +63,5 @@ def default_route(): def zoo(): from conditional.models.migrate import free_the_zoo free_the_zoo(app.config['ZOO_DATABASE_URI']) + +logger.info('conditional started') diff --git a/conditional/blueprints/attendance.py b/conditional/blueprints/attendance.py index 2062f304..da4523d3 100644 --- a/conditional/blueprints/attendance.py +++ b/conditional/blueprints/attendance.py @@ -6,9 +6,10 @@ from flask import Blueprint, jsonify, redirect, request from conditional.util.ldap import ldap_get_current_students -from conditional.util.ldap import ldap_is_eboard -from conditional.util.ldap import ldap_is_eval_director from conditional.util.ldap import ldap_get_active_members +from conditional.util.ldap import ldap_is_eval_director +from conditional.util.ldap import ldap_is_eboard +from conditional.util.ldap import ldap_get_member from conditional.models.models import CurrentCoops from conditional.models.models import CommitteeMeeting @@ -31,10 +32,6 @@ attendance_bp = Blueprint('attendance_bp', __name__) -def get_name(m): - return m['cn'][0].decode('utf-8') - - @attendance_bp.route('/attendance/ts_members') def get_all_members(): log = logger.new(user_name=request.headers.get("x-webauth-user"), @@ -51,14 +48,11 @@ def get_all_members(): } for f in FreshmanAccount.query.filter( FreshmanAccount.eval_date > datetime.now())] - for m in members: - uid = m['uid'][0].decode('utf-8') - name = "{name} ({uid})".format(name=get_name(m), uid=uid) - + for account in members: named_members.append( { - 'display': name, - 'value': uid, + 'display': account.displayName, + 'value': account.uid, 'freshman': False }) @@ -71,12 +65,11 @@ def get_non_alumni_non_coop(internal=False): request_id=str(uuid.uuid4())) log.info('api', action='retrieve house meeting attendance list') - # Only Members Who Have Paid Dues Are Required to - # go to house meetings - non_alumni_members = ldap_get_active_members() + # Get all active members as a base house meeting attendance. + active_members = ldap_get_active_members() coop_members = [u.uid for u in CurrentCoops.query.all()] - named_members = [ + eligible_members = [ { 'display': f.name, 'value': f.id, @@ -84,24 +77,22 @@ def get_non_alumni_non_coop(internal=False): } for f in FreshmanAccount.query.filter( FreshmanAccount.eval_date > datetime.now())] - for m in non_alumni_members: - uid = m['uid'][0].decode('utf-8') - - if uid in coop_members: - continue - name = "{name} ({uid})".format(name=get_name(m), uid=uid) + for account in active_members: + if account.uid in coop_members: + # Members who are on co-op don't need to go to house meeting. + pass - named_members.append( + eligible_members.append( { - 'display': name, - 'value': uid, + 'display': account.displayName, + 'value': account.uid, 'freshman': False }) if internal: - return named_members + return eligible_members else: - return jsonify({'members': named_members}), 200 + return jsonify({'members': eligible_members}), 200 @attendance_bp.route('/attendance/cm_members') @@ -110,27 +101,25 @@ def get_non_alumni(): request_id=str(uuid.uuid4())) log.info('api', action='retrieve committee meeting attendance list') - non_alumni_members = ldap_get_current_students() + current_students = ldap_get_current_students() - named_members = [ + eligible_members = [ { 'display': f.name, 'value': f.id, 'freshman': True } for f in FreshmanAccount.query.filter( FreshmanAccount.eval_date > datetime.now())] - for m in non_alumni_members: - uid = m['uid'][0].decode('utf-8') - name = "{name} ({uid})".format(name=get_name(m), uid=uid) - named_members.append( + for account in current_students: + eligible_members.append( { - 'display': name, - 'value': uid, + 'display': account.displayName, + 'value': account.uid, 'freshman': False }) - return jsonify({'members': named_members}), 200 + return jsonify({'members': eligible_members}), 200 @attendance_bp.route('/attendance_cm') @@ -140,7 +129,8 @@ def display_attendance_cm(): log.info('frontend', action='display committee meeting attendance page') user_name = request.headers.get('x-webauth-user') - if not ldap_is_eboard(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eboard(account): return redirect("/dashboard") return render_template(request, @@ -156,7 +146,8 @@ def display_attendance_ts(): log.info('frontend', action='display technical seminar attendance page') user_name = request.headers.get('x-webauth-user') - if not ldap_is_eboard(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eboard(account): return redirect("/dashboard") return render_template(request, @@ -172,7 +163,8 @@ def display_attendance_hm(): log.info('frontend', action='display house meeting attendance page') user_name = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eval_director(account): return redirect("/dashboard") return render_template(request, @@ -189,8 +181,8 @@ def submit_committee_attendance(): log.info('api', action='submit committee meeting attendance') user_name = request.headers.get('x-webauth-user') - - if not ldap_is_eboard(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eboard(account): return "must be eboard", 403 post_data = request.get_json() @@ -232,7 +224,8 @@ def submit_seminar_attendance(): user_name = request.headers.get('x-webauth-user') - if not ldap_is_eboard(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eboard(account): return "must be eboard", 403 post_data = request.get_json() @@ -275,7 +268,8 @@ def submit_house_attendance(): user_name = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eval_director(account): return "must be evals", 403 post_data = request.get_json() @@ -321,7 +315,8 @@ def submit_house_attendance(): def alter_house_attendance(uid, hid): user_name = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eval_director(account): return "must be evals", 403 if not uid.isdigit(): @@ -351,7 +346,8 @@ def alter_house_excuse(uid, hid): user_name = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + account = ldap_get_member(user_name) + if not ldap_is_eval_director(account): return "must be eval director", 403 post_data = request.get_json() diff --git a/conditional/blueprints/cache_management.py b/conditional/blueprints/cache_management.py index 88754f55..43b4a7ae 100644 --- a/conditional/blueprints/cache_management.py +++ b/conditional/blueprints/cache_management.py @@ -4,19 +4,25 @@ from conditional.util.ldap import ldap_is_eval_director from conditional.util.ldap import ldap_is_rtp -from conditional.util.ldap import ldap_get_housing_points + +from conditional.util.ldap import _ldap_is_member_of_directorship +from conditional.util.ldap import ldap_get_member from conditional.util.ldap import ldap_get_active_members from conditional.util.ldap import ldap_get_intro_members -from conditional.util.ldap import ldap_get_non_alumni_members from conditional.util.ldap import ldap_get_onfloor_members from conditional.util.ldap import ldap_get_current_students -from conditional.util.ldap import ldap_get_name + +from conditional.util.member import get_voting_members +from conditional.util.member import get_members_info +from conditional.util.member import get_onfloor_members + from flask import Blueprint, request, redirect logger = structlog.get_logger() cache_bp = Blueprint('cache_bp', __name__) + @cache_bp.route('/restart') def restart_app(): user_name = request.headers.get('x-webauth-user') @@ -33,44 +39,31 @@ def restart_app(): def clear_cache(): user_name = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name) or ldap_is_rtp(user_name): + if not ldap_is_eval_director(user_name) or not ldap_is_rtp(user_name): return redirect("/dashboard") logger.info('api', action='purge system cache') - ldap_get_housing_points.cache_clear() + _ldap_is_member_of_directorship.cache_clear() + ldap_get_member.cache_clear() ldap_get_active_members.cache_clear() ldap_get_intro_members.cache_clear() - ldap_get_non_alumni_members.cache_clear() ldap_get_onfloor_members.cache_clear() ldap_get_current_students.cache_clear() - ldap_get_name.cache_clear() - return "cache cleared", 200 - -def clear_housing_points_cache(): - ldap_get_housing_points.cache_clear() + get_voting_members.cache_clear() + get_members_info.cache_clear() + get_onfloor_members.cache_clear() + return "cache cleared", 200 -def clear_active_members_cache(): +def clear_members_cache(): + ldap_get_member.cache_clear() ldap_get_active_members.cache_clear() - - -def clear_intro_members_cache(): + ldap_get_current_students.cache_clear() ldap_get_intro_members.cache_clear() - - -def clear_non_alumni_cache(): - ldap_get_non_alumni_members.cache_clear() - - -def clear_onfloor_members_cache(): ldap_get_onfloor_members.cache_clear() -def clear_current_students_cache(): - ldap_get_current_students.cache_clear() - - -def clear_user_cache(username): - ldap_get_name(username).cache_clear() +def clear_committee_cache(): + _ldap_is_member_of_directorship.clear_cache() diff --git a/conditional/blueprints/conditional.py b/conditional/blueprints/conditional.py index 0a78c418..96cc1ac3 100644 --- a/conditional/blueprints/conditional.py +++ b/conditional/blueprints/conditional.py @@ -6,7 +6,7 @@ from flask import Blueprint, request, jsonify, redirect -from conditional.util.ldap import ldap_get_name +from conditional.util.ldap import ldap_get_member from conditional.util.ldap import ldap_is_eval_director from conditional.util.flask import render_template @@ -30,7 +30,7 @@ def display_conditionals(): conditionals = [ { - 'name': ldap_get_name(c.uid), + 'name': ldap_get_member(c.uid).cn, 'date_created': c.date_created, 'date_due': c.date_due, 'description': c.description, diff --git a/conditional/blueprints/dashboard.py b/conditional/blueprints/dashboard.py index 28b9d4d6..7d9815d3 100644 --- a/conditional/blueprints/dashboard.py +++ b/conditional/blueprints/dashboard.py @@ -3,19 +3,12 @@ from flask import Blueprint, request -from conditional.util.ldap import ldap_get_room_number -from conditional.util.ldap import ldap_is_active from conditional.util.ldap import ldap_is_onfloor -from conditional.util.ldap import ldap_get_housing_points +from conditional.util.ldap import ldap_is_active from conditional.util.ldap import ldap_is_intromember -from conditional.util.ldap import ldap_get_name -from conditional.util.ldap import ldap_get_active_members -from conditional.util.ldap import ldap_get_intro_members +from conditional.util.ldap import ldap_get_member -from conditional.models.models import FreshmanEvalData from conditional.models.models import MemberCommitteeAttendance -from conditional.models.models import MemberSeminarAttendance -from conditional.models.models import TechnicalSeminar from conditional.models.models import MemberHouseMeetingAttendance from conditional.models.models import MajorProject from conditional.models.models import Conditional @@ -26,117 +19,62 @@ from conditional.util.housing import get_queue_length, get_queue_position from conditional.util.flask import render_template +from conditional.util.member import get_freshman_data, get_voting_members logger = structlog.get_logger() dashboard_bp = Blueprint('dashboard_bp', __name__) -def get_freshman_data(user_name): - freshman = {} - freshman_data = FreshmanEvalData.query.filter(FreshmanEvalData.uid == user_name).first() - - freshman['status'] = freshman_data.freshman_eval_result - # number of committee meetings attended - c_meetings = [m.meeting_id for m in - MemberCommitteeAttendance.query.filter( - MemberCommitteeAttendance.uid == user_name - )] - freshman['committee_meetings'] = len(c_meetings) - # technical seminar total - t_seminars = [s.seminar_id for s in - MemberSeminarAttendance.query.filter( - MemberSeminarAttendance.uid == user_name - )] - freshman['ts_total'] = len(t_seminars) - attendance = [m.name for m in TechnicalSeminar.query.filter( - TechnicalSeminar.id.in_(t_seminars) - )] - - freshman['ts_list'] = attendance - - h_meetings = [(m.meeting_id, m.attendance_status) for m in - MemberHouseMeetingAttendance.query.filter( - MemberHouseMeetingAttendance.uid == user_name)] - freshman['hm_missed'] = len([h for h in h_meetings if h[1] == "Absent"]) - freshman['social_events'] = freshman_data.social_events - freshman['general_comments'] = freshman_data.other_notes - freshman['fresh_proj'] = freshman_data.freshman_project - freshman['sig_missed'] = freshman_data.signatures_missed - freshman['eval_date'] = freshman_data.eval_date - return freshman - - -def get_voting_members(): - voting_list = [] - active_members = [x['uid'][0].decode('utf-8') for x - in ldap_get_active_members()] - intro_members = [x['uid'][0].decode('utf-8') for x - in ldap_get_intro_members()] - passed_fall = FreshmanEvalData.query.filter( - FreshmanEvalData.freshman_eval_result == "Passed" - ).distinct() - - for intro_member in passed_fall: - voting_list.append(intro_member.uid) - - for active_member in active_members: - if active_member not in intro_members: - voting_list.append(active_member) - - return voting_list - - @dashboard_bp.route('/dashboard/') def display_dashboard(): log = logger.new(user_name=request.headers.get("x-webauth-user"), request_id=str(uuid.uuid4())) log.info('frontend', action='display dashboard') - # get user data - - user_name = request.headers.get('x-webauth-user') + # Get username from headers. + username = request.headers.get('x-webauth-user') + # Get the list of voting members. can_vote = get_voting_members() + + member = ldap_get_member(username) data = dict() - data['username'] = user_name - data['name'] = ldap_get_name(user_name) - # Member Status - data['active'] = ldap_is_active(user_name) - # On-Floor Status - data['onfloor'] = ldap_is_onfloor(user_name) - # Voting Status - data['voting'] = bool(user_name in can_vote) + data['username'] = member.uid + data['name'] = member.cn + data['active'] = ldap_is_active(member) + data['onfloor'] = ldap_is_onfloor(member) + data['voting'] = bool(member.uid in can_vote) active_list = get_members_info()[0] data['voting_count'] = {"Voting Members": len(can_vote), "Active Members": len(active_list)} # freshman shit - if ldap_is_intromember(user_name): - data['freshman'] = get_freshman_data(user_name) + if ldap_is_intromember(member): + data['freshman'] = get_freshman_data(member.uid) else: data['freshman'] = False spring = {} c_meetings = [m.meeting_id for m in MemberCommitteeAttendance.query.filter( - MemberCommitteeAttendance.uid == user_name + MemberCommitteeAttendance.uid == member.uid )] spring['committee_meetings'] = len(c_meetings) h_meetings = [(m.meeting_id, m.attendance_status) for m in MemberHouseMeetingAttendance.query.filter( - MemberHouseMeetingAttendance.uid == user_name)] + MemberHouseMeetingAttendance.uid == member.uid)] spring['hm_missed'] = len([h for h in h_meetings if h[1] == "Absent"]) data['spring'] = spring # only show housing if member has onfloor status - if ldap_is_onfloor(user_name): + if ldap_is_onfloor(member): housing = dict() - housing['points'] = ldap_get_housing_points(user_name) - housing['room'] = ldap_get_room_number(user_name) - if housing['room'] == "N/A": - housing['queue_pos'] = "%s / %s" % (get_queue_position(user_name), get_queue_length()) + housing['points'] = member.housingPoints + housing['room'] = member.roomNumber + if housing['room'] == "": + housing['queue_pos'] = "%s / %s" % (get_queue_position(member.uid), get_queue_length()) else: housing['queue_pos'] = "N/A" else: @@ -151,7 +89,7 @@ def display_dashboard(): 'status': p.status, 'description': p.description } for p in - MajorProject.query.filter(MajorProject.uid == user_name)] + MajorProject.query.filter(MajorProject.uid == member.uid)] data['major_projects_count'] = len(data['major_projects']) @@ -171,7 +109,7 @@ def display_dashboard(): 'description': c.description, 'status': c.status } for c in - Conditional.query.filter(Conditional.uid == user_name)] + Conditional.query.filter(Conditional.uid == member.uid)] data['conditionals'] = conditionals data['conditionals_len'] = len(conditionals) @@ -190,7 +128,7 @@ def display_dashboard(): HouseMeeting.id == m.meeting_id).first().date } for m in MemberHouseMeetingAttendance.query.filter( - MemberHouseMeetingAttendance.uid == user_name + MemberHouseMeetingAttendance.uid == member.uid ).filter(MemberHouseMeetingAttendance.attendance_status == "Absent")] data['cm_attendance'] = cm_attendance diff --git a/conditional/blueprints/housing.py b/conditional/blueprints/housing.py index 02c9e841..6b20a8f3 100644 --- a/conditional/blueprints/housing.py +++ b/conditional/blueprints/housing.py @@ -6,10 +6,10 @@ from conditional.models.models import FreshmanAccount from conditional.util.housing import get_queue_with_points from conditional.util.ldap import ldap_get_onfloor_members -from conditional.util.ldap import ldap_get_room_number -from conditional.util.ldap import ldap_get_name from conditional.util.flask import render_template +from conditional.util.ldap import ldap_get_roomnumber + logger = structlog.get_logger() @@ -27,28 +27,29 @@ def display_housing(): user_name = request.headers.get('x-webauth-user') housing = {} - onfloors = [uids['uid'][0].decode('utf-8') for uids in ldap_get_onfloor_members()] + onfloors = [account for account in ldap_get_onfloor_members()] onfloor_freshmen = FreshmanAccount.query.filter( FreshmanAccount.room_number is not None ) room_list = set() - for m in onfloors: - room = ldap_get_room_number(m) - if room in housing: - housing[room].append(ldap_get_name(m)) - else: - housing[room] = [ldap_get_name(m)] - room_list.add(room) + for member in onfloors: + room = ldap_get_roomnumber(member) + if room in housing and room is not None: + housing[room].append(member.cn) + room_list.add(room) + elif room is not None: + housing[room] = [member.cn] + room_list.add(room) for f in onfloor_freshmen: name = f.name - room = str(f.room_number) - if room in housing and room != "None": + room = f.room_number + if room in housing and room is not None: housing[room].append(name) room_list.add(room) - elif room != "None": + elif room is not None: housing[room] = [name] room_list.add(room) diff --git a/conditional/blueprints/intro_evals.py b/conditional/blueprints/intro_evals.py index fd62981d..38665a6d 100644 --- a/conditional/blueprints/intro_evals.py +++ b/conditional/blueprints/intro_evals.py @@ -5,7 +5,7 @@ from flask import Blueprint, request from conditional.util.ldap import ldap_get_intro_members -from conditional.util.ldap import ldap_get_name + from conditional.models.models import FreshmanCommitteeAttendance from conditional.models.models import MemberCommitteeAttendance @@ -43,7 +43,7 @@ def get_fid_cm_count(member_id): if not internal: user_name = request.headers.get('x-webauth-user') - members = [m['uid'] for m in ldap_get_intro_members()] + members = [account for account in ldap_get_intro_members()] ie_members = [] @@ -100,8 +100,9 @@ def get_fid_cm_count(member_id): ie_members.append(freshman) # freshmen who have accounts - for member_uid in members: - uid = member_uid[0].decode('utf-8') + for member in members: + uid = member.uid + name = member.cn freshman_data = FreshmanEvalData.query.filter( FreshmanEvalData.uid == uid).first() @@ -117,7 +118,7 @@ def get_fid_cm_count(member_id): MemberHouseMeetingAttendance.attendance_status == "Absent" )] member = { - 'name': ldap_get_name(uid), + 'name': name, 'uid': uid, 'eval_date': freshman_data.eval_date.strftime("%Y-%m-%d"), 'signatures_missed': freshman_data.signatures_missed, diff --git a/conditional/blueprints/major_project_submission.py b/conditional/blueprints/major_project_submission.py index debf0fd7..1eebc2b8 100644 --- a/conditional/blueprints/major_project_submission.py +++ b/conditional/blueprints/major_project_submission.py @@ -6,7 +6,7 @@ from conditional.models.models import MajorProject from conditional.util.ldap import ldap_is_eval_director -from conditional.util.ldap import ldap_get_name +from conditional.util.ldap import ldap_get_member from conditional.util.flask import render_template from conditional import db @@ -31,7 +31,7 @@ def display_major_project(): major_projects = [ { 'username': p.uid, - 'name': ldap_get_name(p.uid), + 'name': ldap_get_member(p.uid).cn, 'proj_name': p.name, 'status': p.status, 'description': p.description, diff --git a/conditional/blueprints/member_management.py b/conditional/blueprints/member_management.py index a8d29310..08fd27d4 100644 --- a/conditional/blueprints/member_management.py +++ b/conditional/blueprints/member_management.py @@ -3,7 +3,6 @@ import uuid from datetime import datetime -from functools import lru_cache import structlog @@ -22,29 +21,26 @@ from conditional.models.models import OnFloorStatusAssigned from conditional.models.models import SpringEval -from conditional.blueprints.cache_management import clear_active_members_cache -from conditional.blueprints.cache_management import clear_onfloor_members_cache +from conditional.blueprints.cache_management import clear_members_cache from conditional.blueprints.intro_evals import display_intro_evals from conditional.util.ldap import ldap_is_eval_director from conditional.util.ldap import ldap_is_financial_director +from conditional.util.ldap import ldap_is_active +from conditional.util.ldap import ldap_is_onfloor from conditional.util.ldap import ldap_set_roomnumber from conditional.util.ldap import ldap_set_active from conditional.util.ldap import ldap_set_inactive from conditional.util.ldap import ldap_set_housingpoints -from conditional.util.ldap import ldap_get_room_number -from conditional.util.ldap import ldap_get_housing_points -from conditional.util.ldap import ldap_get_current_students from conditional.util.ldap import ldap_get_active_members -from conditional.util.ldap import ldap_get_name -from conditional.util.ldap import ldap_is_active -from conditional.util.ldap import ldap_is_onfloor +from conditional.util.ldap import ldap_get_member from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group from conditional.util.ldap import _ldap_remove_member_from_group as ldap_remove_member_from_group from conditional.util.ldap import _ldap_is_member_of_group as ldap_is_member_of_group from conditional.util.flask import render_template from conditional.models.models import attendance_enum +from conditional.util.member import get_members_info, get_onfloor_members from conditional import db @@ -53,47 +49,19 @@ member_management_bp = Blueprint('member_management_bp', __name__) -@lru_cache(maxsize=1024) -def get_members_info(): - members = [m['uid'] for m in ldap_get_current_students()] - member_list = [] - number_onfloor = 0 - - for member_uid in members: - uid = member_uid[0].decode('utf-8') - name = ldap_get_name(uid) - active = ldap_is_active(uid) - onfloor = ldap_is_onfloor(uid) - room_number = ldap_get_room_number(uid) - room = room_number if room_number != "N/A" else "" - hp = ldap_get_housing_points(uid) - member_list.append({ - "uid": uid, - "name": name, - "active": active, - "onfloor": onfloor, - "room": room, - "hp": hp - }) - - if onfloor: - number_onfloor += 1 - - return member_list, number_onfloor - - @member_management_bp.route('/manage') def display_member_management(): log = logger.new(user_name=request.headers.get("x-webauth-user"), request_id=str(uuid.uuid4())) log.info('frontend', action='display member management') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name) and not ldap_is_financial_director(user_name): + if not ldap_is_eval_director(username) and not ldap_is_financial_director(username): return "must be eval director", 403 - member_list, onfloor_number = get_members_info() + member_list = get_members_info() + onfloor_list = get_onfloor_members() freshmen = FreshmanAccount.query freshmen_list = [] @@ -116,12 +84,12 @@ def display_member_management(): intro_form = False return render_template(request, "member_management.html", - username=user_name, + username=username, active=member_list, num_current=len(member_list), num_active=len(ldap_get_active_members()), num_fresh=len(freshmen_list), - num_onfloor=onfloor_number, + num_onfloor=len(onfloor_list), freshmen=freshmen_list, site_lockdown=lockdown, intro_form=intro_form) @@ -133,9 +101,9 @@ def member_management_eval(): request_id=str(uuid.uuid4())) log.info('api', action='submit site settings') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 post_data = request.get_json() @@ -165,9 +133,9 @@ def member_management_adduser(): request_id=str(uuid.uuid4())) log.info('api', action='add fid user') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 post_data = request.get_json() @@ -189,9 +157,9 @@ def member_management_adduser(): @member_management_bp.route('/manage/user/upload', methods=['POST']) def member_management_uploaduser(): - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 f = request.files['file'] @@ -226,15 +194,15 @@ def member_management_edituser(uid): request_id=str(uuid.uuid4())) log.info('api', action='edit uid user') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name) and not ldap_is_financial_director(user_name): + if not ldap_is_eval_director(username) and not ldap_is_financial_director(username): return "must be eval director", 403 post_data = request.get_json() if not uid.isdigit(): - edit_uid(uid, user_name, post_data) + edit_uid(uid, username, post_data) else: edit_fid(uid, post_data) @@ -243,40 +211,42 @@ def member_management_edituser(uid): return jsonify({"success": True}), 200 -def edit_uid(uid, user_name, post_data): +def edit_uid(uid, username, post_data): + + account = ldap_get_member(uid) active_member = post_data['activeMember'] + room_number = post_data['roomNumber'] + onfloor_status = post_data['onfloorStatus'] + housing_points = post_data['housingPoints'] - if ldap_is_eval_director(user_name): + if ldap_is_eval_director(username): logger.info('backend', action="edit %s room: %s onfloor: %s housepts %s" % (uid, post_data['roomNumber'], post_data['onfloorStatus'], post_data['housingPoints'])) - room_number = post_data['roomNumber'] - onfloor_status = post_data['onfloorStatus'] - housing_points = post_data['housingPoints'] - ldap_set_roomnumber(uid, room_number) + ldap_set_roomnumber(account, room_number) if onfloor_status: # If a OnFloorStatusAssigned object exists, don't make another - if not ldap_is_member_of_group(uid, "onfloor"): + if not ldap_is_member_of_group(account, "onfloor"): db.session.add(OnFloorStatusAssigned(uid, datetime.now())) - ldap_add_member_to_group(uid, "onfloor") + ldap_add_member_to_group(account, "onfloor") else: for ofs in OnFloorStatusAssigned.query.filter(OnFloorStatusAssigned.uid == uid): db.session.delete(ofs) db.session.flush() db.session.commit() - if ldap_is_member_of_group(uid, "onfloor"): - ldap_remove_member_from_group(uid, "onfloor") - ldap_set_housingpoints(uid, housing_points) + if ldap_is_member_of_group(account, "onfloor"): + ldap_remove_member_from_group(account, "onfloor") + ldap_set_housingpoints(account, housing_points) # Only update if there's a diff logger.info('backend', action="edit %s active: %s" % (uid, active_member)) - if ldap_is_active(uid) != active_member: + if ldap_is_active(account) != active_member: if active_member: - ldap_set_active(uid) + ldap_set_active(account) else: - ldap_set_inactive(uid) + ldap_set_inactive(account) if active_member: db.session.add(SpringEval(uid)) @@ -287,7 +257,7 @@ def edit_uid(uid, user_name, post_data): { 'active': False }) - clear_active_members_cache() + clear_members_cache() def edit_fid(uid, post_data): @@ -325,9 +295,9 @@ def member_management_getuserinfo(uid): request_id=str(uuid.uuid4())) log.info('api', action='retrieve user info') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name) and not ldap_is_financial_director(user_name): + if not ldap_is_eval_director(username) and not ldap_is_financial_director(username): return "must be eval or financial director", 403 acct = None @@ -369,7 +339,9 @@ def get_hm_date(hm_id): 'sig_missed': acct.signatures_missed }), 200 - if ldap_is_eval_director(user_name): + account = ldap_get_member(uid) + + if ldap_is_eval_director(username): missed_hm = [ { 'date': get_hm_date(hma.meeting_id), @@ -386,19 +358,19 @@ def get_hm_date(hm_id): hms_missed.append(hm) return jsonify( { - 'name': ldap_get_name(uid), - 'room_number': ldap_get_room_number(uid), - 'onfloor_status': ldap_is_onfloor(uid), - 'housing_points': ldap_get_housing_points(uid), - 'active_member': ldap_is_active(uid), + 'name': account.cn, + 'room_number': account.roomNumber, + 'onfloor_status': ldap_is_onfloor(account), + 'housing_points': account.housingPoints, + 'active_member': ldap_is_active(account), 'missed_hm': hms_missed, 'user': 'eval' }), 200 else: return jsonify( { - 'name': ldap_get_name(uid), - 'active_member': ldap_is_active(uid), + 'name': account.cn, + 'active_member': ldap_is_active(account), 'user': 'financial' }), 200 @@ -409,15 +381,15 @@ def member_management_deleteuser(fid): request_id=str(uuid.uuid4())) log.info('api', action='edit fid user') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 if not fid.isdigit(): return "can only delete freshman accounts", 400 - logger.info('backend', action="delete freshman account %s" % (fid)) + logger.info('backend', action="delete freshman account %s" % fid) for fca in FreshmanCommitteeAttendance.query.filter(FreshmanCommitteeAttendance.fid == fid): db.session.delete(fca) @@ -444,9 +416,9 @@ def member_management_upgrade_user(): request_id=str(uuid.uuid4())) log.info('api', action='convert fid to uid entry') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 post_data = request.get_json() @@ -495,7 +467,7 @@ def member_management_upgrade_user(): db.session.flush() db.session.commit() - clear_onfloor_members_cache() + clear_members_cache() return jsonify({"success": True}), 200 @@ -506,14 +478,14 @@ def introductory_project(): request_id=str(uuid.uuid4())) log.info('api', action='show introductory project management') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 return render_template(request, 'introductory_project.html', - username=user_name, + username=username, intro_members=display_intro_evals(internal=True)) @@ -523,9 +495,9 @@ def introductory_project_submit(): request_id=str(uuid.uuid4())) log.info('api', action='submit introductory project results') - user_name = request.headers.get('x-webauth-user') + username = request.headers.get('x-webauth-user') - if not ldap_is_eval_director(user_name): + if not ldap_is_eval_director(username): return "must be eval director", 403 post_data = request.get_json() diff --git a/conditional/blueprints/spring_evals.py b/conditional/blueprints/spring_evals.py index c7f04eb1..bc865931 100644 --- a/conditional/blueprints/spring_evals.py +++ b/conditional/blueprints/spring_evals.py @@ -4,7 +4,6 @@ from flask import Blueprint, request from conditional.util.ldap import ldap_get_active_members -from conditional.util.ldap import ldap_get_name from conditional.models.models import MemberCommitteeAttendance from conditional.models.models import MemberHouseMeetingAttendance @@ -35,12 +34,11 @@ def get_cm_count(member_id): if not internal: user_name = request.headers.get('x-webauth-user') - members = [m['uid'] for m in ldap_get_active_members()] + active_members = [account for account in ldap_get_active_members()] sp_members = [] - for member_uid in members: - uid = member_uid[0].decode('utf-8') - print(uid) + for account in active_members: + uid = account.uid spring_entry = SpringEval.query.filter( SpringEval.uid == uid and SpringEval.active).first() @@ -50,8 +48,7 @@ def get_cm_count(member_id): db.session.add(spring_entry) db.session.flush() db.session.commit() - # something bad happened to get here - print("User did not have existing spring eval data") + # something bad happened to get here... elif spring_entry.status != "Pending" and internal: continue @@ -64,7 +61,7 @@ def get_cm_count(member_id): MemberHouseMeetingAttendance.attendance_status == "Absent" )] member = { - 'name': ldap_get_name(uid), + 'name': account.cn, 'uid': uid, 'status': spring_entry.status, 'committee_meetings': get_cm_count(uid), diff --git a/conditional/util/auth.py b/conditional/util/auth.py index bdf89c4b..535a3ab8 100644 --- a/conditional/util/auth.py +++ b/conditional/util/auth.py @@ -2,18 +2,19 @@ from flask import request from conditional.util.ldap import ldap_is_active, ldap_is_alumni, \ ldap_is_eboard, ldap_is_eval_director, \ - ldap_is_financial_director + ldap_is_financial_director, ldap_get_member def webauth_request(func): @wraps(func) def wrapped_func(*args, **kwargs): user_name = request.headers.get('x-webauth-user') - is_active = ldap_is_active(user_name) - is_alumni = ldap_is_alumni(user_name) - is_eboard = ldap_is_eboard(user_name) - is_financial = ldap_is_financial_director(user_name) - is_eval = ldap_is_eval_director(user_name) + account = ldap_get_member(user_name) + is_active = ldap_is_active(account) + is_alumni = ldap_is_alumni(account) + is_eboard = ldap_is_eboard(account) + is_financial = ldap_is_financial_director(account) + is_eval = ldap_is_eval_director(account) return func({"user_name": user_name, "is_active": is_active, diff --git a/conditional/util/flask.py b/conditional/util/flask.py index d223ef83..9f5ea4ab 100644 --- a/conditional/util/flask.py +++ b/conditional/util/flask.py @@ -8,6 +8,7 @@ from conditional.util.ldap import ldap_is_eval_director from conditional.util.ldap import ldap_is_intromember from conditional.util.ldap import ldap_is_rtp +from conditional.util.ldap import ldap_get_member from conditional import db @@ -20,15 +21,15 @@ def render_template(request, template_name, **kwargs): db.session.add(EvalSettings()) db.session.flush() db.session.commit() - + account = ldap_get_member(user_name) lockdown = EvalSettings.query.first().site_lockdown - is_active = ldap_is_active(user_name) - is_alumni = ldap_is_alumni(user_name) - is_eboard = ldap_is_eboard(user_name) - is_financial = ldap_is_financial_director(user_name) - is_eval = ldap_is_eval_director(user_name) - is_intromember = ldap_is_intromember(user_name) - is_rtp = ldap_is_rtp(user_name) + is_active = ldap_is_active(account) + is_alumni = ldap_is_alumni(account) + is_eboard = ldap_is_eboard(account) + is_financial = ldap_is_financial_director(account) + is_eval = ldap_is_eval_director(account) + is_intromember = ldap_is_intromember(account) + is_rtp = ldap_is_rtp(account) if is_eval: lockdown = False diff --git a/conditional/util/housing.py b/conditional/util/housing.py index 102b12db..19268c3a 100644 --- a/conditional/util/housing.py +++ b/conditional/util/housing.py @@ -1,80 +1,16 @@ -from functools import lru_cache -from datetime import datetime -from conditional.util.ldap import ldap_get_housing_points -from conditional.util.ldap import ldap_get_room_number -from conditional.util.ldap import ldap_get_name -from conditional.util.ldap import ldap_is_active -from conditional.util.ldap import ldap_get_onfloor_members -from conditional.util.ldap import ldap_is_current_student - -from conditional.models.models import CurrentCoops -from conditional.models.models import OnFloorStatusAssigned - -@lru_cache(maxsize=1024) -def __get_ofm__(): - - # check that everyone in onfloor has onfloorstatus - onfloors = [uids['uid'][0].decode('utf-8') for uids in ldap_get_onfloor_members()] - - ofm = [ - { - 'uid': m.uid, - 'time': m.onfloor_granted, - 'points': ldap_get_housing_points(m.uid) - } for m in OnFloorStatusAssigned.query.all() - if ldap_is_active(m.uid) - or CurrentCoops.query.filter( - CurrentCoops.uid == m.uid and CurrentCoops.active - ).first() is not None] - - # Add everyone who has a discrepancy in LDAP and OnFloorStatusAssigned - for member in onfloors: - if OnFloorStatusAssigned.query.filter(OnFloorStatusAssigned.uid == member).first() is None: - ofsa = OnFloorStatusAssigned(member, datetime.min) - active = ldap_is_active(ofsa.uid) - coop = CurrentCoops.query.filter(CurrentCoops.uid == ofsa.uid).first() - coop = coop != None and coop.active - - if active or coop: - ofm.append( - { - 'uid': ofsa.uid, - 'time': ofsa.onfloor_granted, - 'points': ldap_get_housing_points(ofsa.uid) - }) - - # sort by housing points then by time in queue - ofm.sort(key=lambda m: m['time']) - ofm.sort(key=lambda m: m['points'], reverse=True) - - return ofm - def get_housing_queue(): - ofm = __get_ofm__() - - queue = [m['uid'] for m in ofm if ldap_get_room_number(m['uid']) == "N/A" and ldap_is_current_student(m['uid'])] - - return queue + return [] def get_queue_with_points(): - ofm = __get_ofm__() - - queue = [ - { - 'name': ldap_get_name(m['uid']), - 'points': m['points'] - } for m in ofm if ldap_get_room_number(m['uid']) == "N/A" and ldap_is_current_student(m['uid'])] - - return queue + return [] def get_queue_length(): - return len(get_housing_queue()) + # TODO: Actually implement queue length. + return 20 def get_queue_position(username): - try: - return get_housing_queue().index(username) - except (IndexError, ValueError): - return "0" + # TODO: Actually implement queue position. + return len(username) diff --git a/conditional/util/ldap.py b/conditional/util/ldap.py index bf2aa984..8fdad08a 100644 --- a/conditional/util/ldap.py +++ b/conditional/util/ldap.py @@ -1,250 +1,118 @@ -import copy -from functools import wraps from functools import lru_cache -import ldap -import ldap.modlist -from ldap.ldapobject import ReconnectLDAPObject - -# Global state is gross. I'm sorry. -ldap_conn = None -user_search_ou = None -committee_search_ou = None -group_search_ou = None -read_only = False - - -class HousingLDAPError(Exception): - pass - - -def ldap_init(ro, ldap_url, bind_dn, bind_pw, user_ou, group_ou, committee_ou): - global user_search_ou, group_search_ou, committee_search_ou, ldap_conn, read_only - read_only = ro - user_search_ou = user_ou - group_search_ou = group_ou - committee_search_ou = committee_ou - ldap_conn = ReconnectLDAPObject(ldap_url) - ldap_conn.simple_bind_s(bind_dn, bind_pw) - - -def ldap_init_required(func): - @wraps(func) - def wrapped_func(*args, **kwargs): - if ldap_conn is not None: - return func(*args, **kwargs) - raise HousingLDAPError("LDAP uninitialized. Did you forget to call ldap_init?") - - return wrapped_func - - -@ldap_init_required -def _ldap_get_field(username, field): - ldap_results = ldap_conn.search_s(user_search_ou, ldap.SCOPE_SUBTREE, "(uid=%s)" - % username) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for username %s." - % username) - if field not in ldap_results[0][1]: - return None - return ldap_results[0][1][field][0] - - -@ldap_init_required -def _ldap_set_field(username, field, new_val): - if read_only: - print('LDAP modification: setting %s on %s to %s' % (field, - username, - new_val)) - return - ldap_results = ldap_conn.search_s(user_search_ou, ldap.SCOPE_SUBTREE, - "(uid=%s)" % username) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for username %s." - % username) - old_result = ldap_results[0][1] - new_result = copy.deepcopy(ldap_results[0][1]) - if new_val is not None: - new_result[field] = [str(new_val).encode('ascii')] - else: - new_result[field] = [None] - ldap_mod_list = ldap.modlist.modifyModlist(old_result, new_result) - userdn = "uid=%s,%s" % (username, user_search_ou) - ldap_conn.modify_s(userdn, ldap_mod_list) - - -@ldap_init_required -def _ldap_get_members(): - return ldap_conn.search_s(user_search_ou, ldap.SCOPE_SUBTREE, - "objectClass=houseMember") - - -@ldap_init_required -def _ldap_is_member_of_group(username, group): - ldap_results = ldap_conn.search_s(group_search_ou, ldap.SCOPE_SUBTREE, - "(cn=%s)" % group) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for group %s." % - group) - return "uid=" + username + "," + user_search_ou in \ - [x.decode('ascii') for x in ldap_results[0][1]['member']] - - -@ldap_init_required -def _ldap_add_member_to_group(username, group): - if read_only: - print("LDAP: Adding user %s to group %s" % (username, group)) - return - if _ldap_is_member_of_group(username, group): - return - ldap_results = ldap_conn.search_s(group_search_ou, ldap.SCOPE_SUBTREE, - "(cn=%s)" % group) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for group %s." % - group) - old_results = ldap_results[0][1] - new_results = copy.deepcopy(ldap_results[0][1]) - new_entry = "uid=%s,%s" % (username, user_search_ou) - new_entry = new_entry.encode('utf-8') - new_results['member'].append(new_entry) - ldap_modlist = ldap.modlist.modifyModlist(old_results, new_results) - groupdn = "cn=%s,%s" % (group, group_search_ou) - ldap_conn.modify_s(groupdn, ldap_modlist) - - -def _ldap_remove_member_from_group(username, group): - if read_only: - print("LDAP: Removing user %s from group %s" % (username, group)) - return - if not _ldap_is_member_of_group(username, group): - return - ldap_results = ldap_conn.search_s(group_search_ou, ldap.SCOPE_SUBTREE, - "(cn=%s)" % group) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for group %s." % - group) - old_results = ldap_results[0][1] - new_results = copy.deepcopy(ldap_results[0][1]) - new_results['member'] = [i for i in old_results['member'] if - i.decode('utf-8') != "uid=%s,%s" % (username, user_search_ou)] - ldap_modlist = ldap.modlist.modifyModlist(old_results, new_results) - groupdn = "cn=%s,%s" % (group, group_search_ou) - ldap_conn.modify_s(groupdn, ldap_modlist) - - -@ldap_init_required -def _ldap_is_member_of_committee(username, committee): - ldap_results = ldap_conn.search_s(committee_search_ou, ldap.SCOPE_SUBTREE, - "(cn=%s)" % committee) - if len(ldap_results) != 1: - raise HousingLDAPError("Wrong number of results found for committee %s." % - committee) - return "uid=" + username + "," + user_search_ou in \ - [x.decode('ascii') for x in ldap_results[0][1]['head']] +from conditional import ldap -@lru_cache(maxsize=1024) -def ldap_get_housing_points(username): - return int(_ldap_get_field(username, 'housingPoints')) +def _ldap_get_group_members(group): + return ldap.get_group(group).get_members() + + +def _ldap_is_member_of_group(member, group): + group_list = member.get("memberOf") + for group_dn in group_list: + if group == group_dn.split(",")[0][3:]: + return True + +def _ldap_add_member_to_group(account, group): + if not _ldap_is_member_of_group(account, group): + ldap.get_group(group).add_member(account, dn=False) -def ldap_get_room_number(username): - roomno = _ldap_get_field(username, 'roomNumber') - if roomno is None: - return "N/A" - return roomno.decode('utf-8') + +def _ldap_remove_member_from_group(account, group): + if _ldap_is_member_of_group(account, group): + ldap.get_group(group).del_member(account, dn=False) @lru_cache(maxsize=1024) -def ldap_get_active_members(): - return [x for x in ldap_get_current_students() - if ldap_is_active(x['uid'][0].decode('utf-8'))] +def _ldap_is_member_of_directorship(account, directorship): + directors = ldap.get_directorship_heads(directorship) + for account in directors: + if account.uid == account.uid: + return True @lru_cache(maxsize=1024) -def ldap_get_intro_members(): - return [x for x in ldap_get_current_students() - if ldap_is_intromember(x['uid'][0].decode('utf-8'))] +def ldap_get_member(username): + return ldap.get_member(username, uid=True) @lru_cache(maxsize=1024) -def ldap_get_non_alumni_members(): - return [x for x in ldap_get_current_students() - if ldap_is_alumni(x['uid'][0].decode('utf-8'))] +def ldap_get_active_members(): + return _ldap_get_group_members("active") + + +@lru_cache(maxsize=1024) +def ldap_get_intro_members(): + return _ldap_get_group_members("intromembers") @lru_cache(maxsize=1024) def ldap_get_onfloor_members(): - return [x for x in ldap_get_current_students() - if ldap_is_onfloor(x['uid'][0].decode('utf-8'))] + return _ldap_get_group_members("onfloor") @lru_cache(maxsize=1024) def ldap_get_current_students(): - return [x[1] - for x in _ldap_get_members()[1:] - if ldap_is_current_student(str(str(x[0]).split(",")[0]).split("=")[1])] + return _ldap_get_group_members("current_student") -def ldap_is_active(username): - return _ldap_is_member_of_group(username, 'active') +def ldap_is_active(account): + return _ldap_is_member_of_group(account, 'active') -def ldap_is_alumni(username): - # When alumni status becomes a group rather than an attribute this will - # change to use _ldap_is_member_of_group. - alum_status = _ldap_get_field(username, 'alumni') - return alum_status is not None and alum_status.decode('utf-8') == '1' +def ldap_is_alumni(account): + # If the user is not active, they are an alumni. + return not _ldap_is_member_of_group(account, 'active') -def ldap_is_eboard(username): - return _ldap_is_member_of_group(username, 'eboard') +def ldap_is_eboard(account): + return _ldap_is_member_of_group(account, 'eboard') -def ldap_is_rtp(username): - return _ldap_is_member_of_group(username, 'rtp') +def ldap_is_rtp(account): + return _ldap_is_member_of_group(account, 'rtp') -def ldap_is_intromember(username): - return _ldap_is_member_of_group(username, 'intromembers') +def ldap_is_intromember(account): + return _ldap_is_member_of_group(account, 'intromembers') -def ldap_is_onfloor(username): - # april 3rd created onfloor group - # onfloor_status = _ldap_get_field(username, 'onfloor') - # return onfloor_status != None and onfloor_status.decode('utf-8') == '1' - return _ldap_is_member_of_group(username, 'onfloor') +def ldap_is_onfloor(account): + return _ldap_is_member_of_group(account, 'onfloor') -def ldap_is_financial_director(username): - return _ldap_is_member_of_committee(username, 'Financial') +def ldap_is_financial_director(account): + return _ldap_is_member_of_directorship(account, 'Financial') -def ldap_is_eval_director(username): +def ldap_is_eval_director(account): # TODO FIXME Evaulations -> Evaluations - return _ldap_is_member_of_committee(username, 'Evaulations') + return _ldap_is_member_of_directorship(account, 'Evaulations') -def ldap_is_current_student(username): - return _ldap_is_member_of_group(username, 'current_student') +def ldap_is_current_student(account): + return _ldap_is_member_of_group(account, 'current_student') -def ldap_set_housingpoints(username, housing_points): - _ldap_set_field(username, 'housingPoints', housing_points) +def ldap_set_housingpoints(account, housing_points): + account.housingPoints = housing_points -def ldap_set_roomnumber(username, room_number): - _ldap_set_field(username, 'roomNumber', room_number) +def ldap_set_roomnumber(account, room_number): + account.roomNumber = room_number -def ldap_set_active(username): - _ldap_add_member_to_group(username, 'active') +def ldap_set_active(account): + _ldap_add_member_to_group(account, 'active') -def ldap_set_inactive(username): - _ldap_remove_member_from_group(username, 'active') +def ldap_set_inactive(account): + _ldap_remove_member_from_group(account, 'active') -@lru_cache(maxsize=1024) -def ldap_get_name(username): - return _ldap_get_field(username, 'cn').decode('utf-8') +def ldap_get_roomnumber(account): + try: + return account.roomNumber + except AttributeError: + return "" diff --git a/conditional/util/member.py b/conditional/util/member.py new file mode 100644 index 00000000..f17ebb37 --- /dev/null +++ b/conditional/util/member.py @@ -0,0 +1,95 @@ +from functools import lru_cache + +from conditional.util.ldap import ldap_get_active_members +from conditional.util.ldap import ldap_get_intro_members +from conditional.util.ldap import ldap_get_current_students +from conditional.util.ldap import ldap_get_roomnumber +from conditional.util.ldap import ldap_get_onfloor_members +from conditional.util.ldap import ldap_is_active +from conditional.util.ldap import ldap_is_onfloor + +from conditional.models.models import FreshmanEvalData +from conditional.models.models import MemberSeminarAttendance +from conditional.models.models import MemberHouseMeetingAttendance +from conditional.models.models import MemberCommitteeAttendance +from conditional.models.models import TechnicalSeminar + + +@lru_cache(maxsize=1024) +def get_voting_members(): + voting_list = [uid for uid in [member.uid for member in ldap_get_active_members()] + if uid not in [member.uid for member in ldap_get_intro_members()]] + + passed_fall = FreshmanEvalData.query.filter( + FreshmanEvalData.freshman_eval_result == "Passed" + ).distinct() + + for intro_member in passed_fall: + voting_list.append(intro_member.uid) + + return voting_list + + +@lru_cache(maxsize=1024) +def get_members_info(): + members = [account for account in ldap_get_current_students()] + member_list = [] + + for account in members: + uid = account.uid + name = account.cn + active = ldap_is_active(account) + onfloor = ldap_is_onfloor(account) + room = ldap_get_roomnumber(account) + hp = account.housingPoints + member_list.append({ + "uid": uid, + "name": name, + "active": active, + "onfloor": onfloor, + "room": room, + "hp": hp + }) + + return member_list + + +def get_freshman_data(user_name): + freshman = {} + freshman_data = FreshmanEvalData.query.filter(FreshmanEvalData.uid == user_name).first() + + freshman['status'] = freshman_data.freshman_eval_result + # number of committee meetings attended + c_meetings = [m.meeting_id for m in + MemberCommitteeAttendance.query.filter( + MemberCommitteeAttendance.uid == user_name + )] + freshman['committee_meetings'] = len(c_meetings) + # technical seminar total + t_seminars = [s.seminar_id for s in + MemberSeminarAttendance.query.filter( + MemberSeminarAttendance.uid == user_name + )] + freshman['ts_total'] = len(t_seminars) + attendance = [m.name for m in TechnicalSeminar.query.filter( + TechnicalSeminar.id.in_(t_seminars) + )] + + freshman['ts_list'] = attendance + + h_meetings = [(m.meeting_id, m.attendance_status) for m in + MemberHouseMeetingAttendance.query.filter( + MemberHouseMeetingAttendance.uid == user_name)] + freshman['hm_missed'] = len([h for h in h_meetings if h[1] == "Absent"]) + freshman['social_events'] = freshman_data.social_events + freshman['general_comments'] = freshman_data.other_notes + freshman['fresh_proj'] = freshman_data.freshman_project + freshman['sig_missed'] = freshman_data.signatures_missed + freshman['eval_date'] = freshman_data.eval_date + return freshman + + +@lru_cache(maxsize=1024) +def get_onfloor_members(): + return [uid for uid in [members.uid for members in ldap_get_active_members()] + if uid in [members.uid for members in ldap_get_onfloor_members()]] diff --git a/config.sample.py b/config.sample.py index f29a317e..2e817008 100644 --- a/config.sample.py +++ b/config.sample.py @@ -9,12 +9,8 @@ # LDAP config LDAP_RO = True -LDAP_URL = 'ldaps://ldap.csh.rit.edu:636/' LDAP_BIND_DN = 'cn=conditional,ou=Apps,dc=csh,dc=rit,dc=edu' LDAP_BIND_PW = '' -LDAP_USER_OU = 'ou=Users,dc=csh,dc=rit,dc=edu' -LDAP_GROUP_OU = 'ou=Groups,dc=csh,dc=rit,dc=edu' -LDAP_COMMITTEE_OU = 'ou=Committees,dc=csh,dc=rit,dc=edu' # Database config SQLALCHEMY_DATABASE_URI = 'sqlite:///{}'.format(os.path.join(os.getcwd(), "data.db")) diff --git a/requirements.txt b/requirements.txt index aeceac1d..c20c4c8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Flask itsdangerous Jinja2 MarkupSafe -pyldap +csh_ldap SQLAlchemy Werkzeug structlog