diff --git a/frontend/scss/components/buttons.scss b/frontend/scss/components/buttons.scss index 2f2ff5fd..596ce6cc 100644 --- a/frontend/scss/components/buttons.scss +++ b/frontend/scss/components/buttons.scss @@ -1,4 +1,8 @@ .sign-packet { float: right; text-align: right; -} \ No newline at end of file +} + +.sign-button { + float: right; +} diff --git a/frontend/scss/components/signatures.scss b/frontend/scss/components/signatures.scss new file mode 100644 index 00000000..db44a89a --- /dev/null +++ b/frontend/scss/components/signatures.scss @@ -0,0 +1,3 @@ +.signature-count { + float: right; +} diff --git a/frontend/scss/packet.scss b/frontend/scss/packet.scss index 068124ca..d5f8d6fa 100644 --- a/frontend/scss/packet.scss +++ b/frontend/scss/packet.scss @@ -5,3 +5,4 @@ $csh-pink: #b0197e; @import "components/switches"; @import "components/datatables"; @import "components/buttons"; +@import "components/signatures"; diff --git a/package.json b/package.json index d3cc2504..76697313 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "CSH Packet", "name": "csh-packet", - "version": "3.0.0", + "version": "3.0.1", "description": "A webpacket for CSH", "bugs": { "url": "https://github.com/ComputerScienceHouse/packet/issues", diff --git a/packet/__init__.py b/packet/__init__.py index 06656faa..1047c375 100644 --- a/packet/__init__.py +++ b/packet/__init__.py @@ -10,6 +10,8 @@ from flask_pyoidc.flask_pyoidc import OIDCAuthentication from flask_sqlalchemy import SQLAlchemy +from ._version import __version__ + app = Flask(__name__) # Load default configuration and any environment variable overrides @@ -19,6 +21,8 @@ if os.path.exists(os.path.join(os.getcwd(), "config.py")): app.config.from_pyfile(os.path.join(os.getcwd(), "config.py")) +app.config["VERSION"] = __version__ + # Initialize the extensions db = SQLAlchemy(app) migrate = Migrate(app, db) diff --git a/packet/_version.py b/packet/_version.py new file mode 100644 index 00000000..05527687 --- /dev/null +++ b/packet/_version.py @@ -0,0 +1 @@ +__version__ = "3.0.1" diff --git a/packet/ldap.py b/packet/ldap.py index 65639621..1e4f153a 100644 --- a/packet/ldap.py +++ b/packet/ldap.py @@ -1,14 +1,14 @@ from functools import lru_cache -import ldap - from packet import _ldap +@lru_cache(maxsize=1024) def _ldap_get_group_members(group): return _ldap.get_group(group).get_members() +@lru_cache(maxsize=2048) def _ldap_is_member_of_group(member, group): group_list = member.get("memberOf") for group_dn in group_list: @@ -48,16 +48,6 @@ def ldap_get_onfloor_members(): return _ldap_get_group_members("onfloor") -@lru_cache(maxsize=1024) -def ldap_get_current_students(): - return _ldap_get_group_members("current_student") - - -@lru_cache(maxsize=1024) -def ldap_get_all_members(): - return _ldap_get_group_members("member") - - @lru_cache(maxsize=1024) def ldap_get_groups(account): group_list = account.get("memberOf") @@ -68,17 +58,6 @@ def ldap_get_groups(account): return groups -@lru_cache(maxsize=1024) -def ldap_get_group_desc(group): - con = _ldap.get_con() - results = con.search_s( - "cn=groups,cn=accounts,dc=csh,dc=rit,dc=edu", - ldap.SCOPE_SUBTREE, - "(cn=%s)" % group, - ['description']) - return results[0][1]['description'][0].decode('utf-8') - - @lru_cache(maxsize=1024) def ldap_get_eboard(): members = _ldap_get_group_members("eboard-chairman") + _ldap_get_group_members("eboard-evaluations" @@ -90,6 +69,7 @@ def ldap_get_eboard(): return members +@lru_cache(maxsize=2048) def ldap_get_live_onfloor(): """ :return: All upperclassmen who live on floor and are not eboard @@ -101,67 +81,51 @@ def ldap_get_live_onfloor(): members.append(member) return members + # Status checkers +@lru_cache(maxsize=1024) +def ldap_is_eval_director(account): + return _ldap_is_member_of_directorship(account, 'evaluations') + + +@lru_cache(maxsize=1024) def ldap_is_active(account): return _ldap_is_member_of_group(account, 'active') +@lru_cache(maxsize=1024) def ldap_is_alumni(account): # If the user is not active, they are an alumni. return not _ldap_is_member_of_group(account, 'active') +@lru_cache(maxsize=1024) def ldap_is_eboard(account): return _ldap_is_member_of_group(account, 'eboard') +@lru_cache(maxsize=1024) def ldap_is_rtp(account): return _ldap_is_member_of_group(account, 'rtp') +@lru_cache(maxsize=1024) def ldap_is_intromember(account): return _ldap_is_member_of_group(account, 'intromembers') +@lru_cache(maxsize=1024) def ldap_is_onfloor(account): return _ldap_is_member_of_group(account, 'onfloor') +@lru_cache(maxsize=1024) def ldap_is_current_student(account): return _ldap_is_member_of_group(account, 'current_student') -# Directorships - -def ldap_is_financial_director(account): - return _ldap_is_member_of_directorship(account, 'financial') - - -def ldap_is_eval_director(account): - return _ldap_is_member_of_directorship(account, 'evaluations') - - -def ldap_is_chairman(account): - return _ldap_is_member_of_directorship(account, 'chairman') - - -def ldap_is_history(account): - return _ldap_is_member_of_directorship(account, 'history') - - -def ldap_is_imps(account): - return _ldap_is_member_of_directorship(account, 'imps') - - -def ldap_is_social(account): - return _ldap_is_member_of_directorship(account, 'Social') - - -def ldap_is_rd(account): - return _ldap_is_member_of_directorship(account, 'research') - - +@lru_cache(maxsize=1024) def ldap_get_roomnumber(account): try: return account.roomNumber diff --git a/packet/member.py b/packet/member.py index a4544ac4..9e4a75b6 100644 --- a/packet/member.py +++ b/packet/member.py @@ -2,10 +2,10 @@ def signed_packets(member): - is_freshman = Freshman.query.filter_by(rit_username=member).first() is not None - if is_freshman: + # Checks whether or not member is a freshman + if Freshman.query.filter_by(rit_username=member).first() is not None: return FreshSignature.query.filter_by(freshman_username=member, signed=True).all() - is_upper = UpperSignature.query.filter_by(member=member).first() is not None - if is_upper: + # Checks whether or not member is an upperclassman + if UpperSignature.query.filter_by(member=member).first() is not None: return UpperSignature.query.filter_by(member=member, signed=True).all() return MiscSignature.query.filter_by(member=member).all() diff --git a/packet/models.py b/packet/models.py index 5bd3f0a5..62f07de2 100644 --- a/packet/models.py +++ b/packet/models.py @@ -3,6 +3,8 @@ """ from datetime import datetime +from functools import lru_cache + from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, Boolean from sqlalchemy.orm import relationship @@ -47,6 +49,7 @@ class Packet(db.Model): def is_open(self): return self.start < datetime.now() < self.end + @lru_cache(maxsize=1024) def signatures_required(self): eboard = UpperSignature.query.filter_by(eboard=True).count() return {'eboard': eboard, diff --git a/packet/packet.py b/packet/packet.py index ecafe10d..a0827237 100644 --- a/packet/packet.py +++ b/packet/packet.py @@ -1,3 +1,7 @@ +import copy +from functools import lru_cache + +from packet.ldap import ldap_get_member, ldap_is_intromember from .models import Freshman, UpperSignature, FreshSignature, MiscSignature, db @@ -9,33 +13,37 @@ def sign(signer_username, freshman_username): if freshman_signed is None: return False packet = freshman_signed.current_packet() - if packet is None: - return False - if not packet.is_open(): + if packet is None or not packet.is_open(): return False - # Make sure only on floor freshmen can sign packets - freshman_signer = Freshman.query.filter_by(rit_username=signer_username).first() - if freshman_signer: - if not freshman_signer.onfloor: - return False - upper_signature = UpperSignature.query.filter(UpperSignature.member == signer_username, UpperSignature.packet == packet).first() fresh_signature = FreshSignature.query.filter(FreshSignature.freshman_username == signer_username, FreshSignature.packet == packet).first() if upper_signature: + if ldap_is_intromember(ldap_get_member(signer_username)): + return False upper_signature.signed = True elif fresh_signature: + # Make sure only on floor freshmen can sign packets + freshman_signer = Freshman.query.filter_by(rit_username=signer_username).first() + if freshman_signer and not freshman_signer.onfloor: + return False fresh_signature.signed = True else: db.session.add(MiscSignature(packet=packet, member=signer_username)) db.session.commit() + # Clear functions that read signatures cache + get_number_signed.cache_clear() + get_signatures.cache_clear() + get_upperclassmen_percent.cache_clear() + return True +@lru_cache(maxsize=2048) def get_signatures(freshman_username): packet = Freshman.query.filter_by(rit_username=freshman_username).first().current_packet() eboard = UpperSignature.query.filter_by(packet_id=packet.id, eboard=True).order_by(UpperSignature.signed.desc()) @@ -49,9 +57,24 @@ def get_signatures(freshman_username): 'misc': misc_signatures} +@lru_cache(maxsize=2048) def get_number_signed(freshman_username): return Freshman.query.filter_by(rit_username=freshman_username).first().current_packet().signatures_received() +@lru_cache(maxsize=4096) def get_number_required(freshman_username): return Freshman.query.filter_by(rit_username=freshman_username).first().current_packet().signatures_required() + + +@lru_cache(maxsize=2048) +def get_upperclassmen_percent(uid): + upperclassmen_required = copy.deepcopy(get_number_required(uid)) + del upperclassmen_required['freshmen'] + upperclassmen_required = sum(upperclassmen_required.values()) + + upperclassmen_signature = copy.deepcopy(get_number_signed(uid)) + del upperclassmen_signature['freshmen'] + upperclassmen_signature = sum(upperclassmen_signature.values()) + + return upperclassmen_signature / upperclassmen_required * 100 diff --git a/packet/routes/shared.py b/packet/routes/shared.py index 983936f1..e89401ea 100644 --- a/packet/routes/shared.py +++ b/packet/routes/shared.py @@ -1,10 +1,11 @@ -from flask import render_template from datetime import datetime from itertools import chain +from flask import render_template + from packet import auth, app from packet.models import Freshman, Packet -from packet.packet import get_signatures, get_number_required, get_number_signed +from packet.packet import get_signatures, get_number_required, get_number_signed, get_upperclassmen_percent from packet.utils import before_request, signed_packet @@ -13,35 +14,28 @@ @before_request def freshman_packet(uid, info=None): freshman = Freshman.query.filter_by(rit_username=uid).first() + upperclassmen_percent = get_upperclassmen_percent(uid) signatures = get_signatures(uid) + signed_dict = get_number_signed(uid) required = sum(get_number_required(uid).values()) - signed = sum(get_number_signed(uid).values()) - - upperclassmen_required = get_number_required(uid) - del upperclassmen_required['freshmen'] - upperclassmen_required = sum(upperclassmen_required.values()) - - upperclassmen_signature = get_number_signed(uid) - del upperclassmen_signature['freshmen'] - upperclassmen_signature = sum(upperclassmen_signature.values()) - - upperclassmen_percent = upperclassmen_signature / upperclassmen_required * 100 + signed = sum(signed_dict.values()) packet_signed = signed_packet(info['uid'], uid) return render_template("packet.html", info=info, signatures=signatures, uid=uid, required=required, signed=signed, - freshman=freshman, packet_signed=packet_signed, upperclassmen_percent=upperclassmen_percent) + freshman=freshman, packet_signed=packet_signed, upperclassmen_percent=upperclassmen_percent, + signed_dict=signed_dict) @app.route("/packets") @auth.oidc_auth @before_request def packets(info=None): - packets = Packet.query.filter(Packet.end > datetime.now()).filter(Packet.start < datetime.now()).all() + open_packets = Packet.query.filter(Packet.end > datetime.now()).filter(Packet.start < datetime.now()).all() # Add the did_sign flag if app.config["REALM"] == "csh": # User is an upperclassman - for packet in packets: + for packet in open_packets: packet.did_sign = False packet.total_signatures = sum(packet.signatures_received().values()) packet.required_signatures = sum(packet.signatures_required().values()) @@ -52,7 +46,7 @@ def packets(info=None): break else: # User is a freshman - for packet in packets: + for packet in open_packets: packet.did_sign = False packet.total_signatures = sum(packet.signatures_received().values()) packet.required_signatures = sum(packet.signatures_required().values()) @@ -62,7 +56,7 @@ def packets(info=None): packet.did_sign = True break - packets.sort(key=lambda x: sum(x.signatures_received().values()), reverse=True) - packets.sort(key=lambda x: x.did_sign, reverse=True) + open_packets.sort(key=lambda x: sum(x.signatures_received().values()), reverse=True) + open_packets.sort(key=lambda x: x.did_sign, reverse=True) - return render_template("active_packets.html", info=info, packets=packets) + return render_template("active_packets.html", info=info, packets=open_packets) diff --git a/packet/templates/active_packets.html b/packet/templates/active_packets.html index a8cf1c7d..103cd11d 100644 --- a/packet/templates/active_packets.html +++ b/packet/templates/active_packets.html @@ -31,13 +31,17 @@
Name | -Signature | -|||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+ |
{% if m.signed %}
{% else %}
@@ -96,18 +94,13 @@ Upperclassmen Score
On-Floor Upperclassmen Signatures
+ {{ signed_dict.upperclassmen }}/{{ signatures.upperclassmen.count() }}
|