Skip to content

Commit 822a75d

Browse files
authored
Merge pull request #139 from ComputerScienceHouse/develop
Version 3.2
2 parents 3c92f55 + 353d8fb commit 822a75d

29 files changed

+1103
-422
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ ENV/
106106
# Configurations
107107
config.py
108108

109+
# Setup
110+
node_modules
111+
109112
# Generated Assets
110113
packet/static/css/packet.css
111114
*.min.css
@@ -124,3 +127,4 @@ packet/static/mstile-70x70.png
124127
packet/static/safari-pinned-tab.svg
125128
packet/static/site.webmanifest
126129
faviconData.json
130+

.nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
6

.pylintrc

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ disable =
1515
cyclic-import,
1616
locally-disabled,
1717
file-ignored,
18-
no-else-return
18+
no-else-return,
19+
unnecessary-lambda
1920

2021
[REPORTS]
2122
output-format = text

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ python:
55
install:
66
- "pip install -r requirements.txt"
77
script:
8-
- "pylint packet"
8+
- "pylint packet/routes packet"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# CSH Web Packet
22

33
[![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-360/)
4-
[![Build Status](https://travis-ci.org/ComputerScienceHouse/packet.svg?branch=develop)](https://travis-ci.org/ComputerScienceHouse/packet)
4+
[![Build Status](https://travis-ci.com/ComputerScienceHouse/packet.svg?branch=develop)](https://travis-ci.com/ComputerScienceHouse/packet)
55

66
Packet is used by CSH to facilitate the freshmen packet portion of our introductory member evaluation process. This is
77
the second major iteration of packet on the web. The first version was

config.env.py

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
# Logging config
1616
LOG_LEVEL = environ.get("PACKET_LOG_LEVEL", "INFO")
17+
ANALYTICS_ID = environ.get("ANALYTICS_ID", "UA-420696-9")
1718

1819
# OpenID Connect SSO config
1920
REALM = environ.get("PACKET_REALM", "csh")

frontend/scss/components/badges.scss

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
span {
2+
&.badge {
3+
font-size: 80%;
4+
}
5+
&.badge-eboard {
6+
color: #fff;
7+
background-color: #4CAF50;
8+
}
9+
10+
&.badge-rtp {
11+
color: #fff;
12+
background-color: #ff9800;
13+
}
14+
15+
&.badge-three_da {
16+
color: #fff;
17+
background-color: #e83e8c;
18+
}
19+
20+
&.badge-webmaster {
21+
color: #fff;
22+
background-color: #2196F3;
23+
}
24+
25+
&.badge-cm {
26+
color: #fff;
27+
background-color: #e51c23;
28+
}
29+
30+
&.badge-drink {
31+
color: #fff;
32+
background-color: #b0197e;
33+
}
34+
}

frontend/scss/packet.scss

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ $csh-pink: #b0197e;
66
@import "components/datatables";
77
@import "components/buttons";
88
@import "components/signatures";
9+
@import "components/badges";

frontend/scss/partials/_base.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
body {
2-
padding-top: 50px;
2+
padding-top: 40px;
33
}
44

55
.main {
6-
margin-top: 50px;
6+
margin-top: 40px;
77
}
88

99
@import "global";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""Demote Eboard Deluxe
2+
3+
Revision ID: eecf30892d0e
4+
Revises: fe83600ef3fa
5+
Create Date: 2019-02-14 17:41:18.469840
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = 'eecf30892d0e'
14+
down_revision = 'fe83600ef3fa'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column('signature_upper', sa.Column('active_rtp', sa.Boolean(), nullable=False, server_default='f'))
22+
op.add_column('signature_upper', sa.Column('c_m', sa.Boolean(), nullable=False, server_default='f'))
23+
op.add_column('signature_upper', sa.Column('drink_admin', sa.Boolean(), nullable=False, server_default='f'))
24+
op.add_column('signature_upper', sa.Column('three_da', sa.Boolean(), nullable=False, server_default='f'))
25+
op.add_column('signature_upper', sa.Column('webmaster', sa.Boolean(), nullable=False, server_default='f'))
26+
op.alter_column('signature_upper', 'eboard',
27+
existing_type=sa.BOOLEAN(),
28+
type_=sa.String(length=12),
29+
nullable=True)
30+
# ### end Alembic commands ###
31+
32+
33+
def downgrade():
34+
# ### commands auto generated by Alembic - please adjust! ###
35+
op.alter_column('signature_upper', 'eboard',
36+
existing_type=sa.String(length=12),
37+
type_=sa.BOOLEAN(),
38+
nullable=False)
39+
op.drop_column('signature_upper', 'webmaster')
40+
op.drop_column('signature_upper', 'three_da')
41+
op.drop_column('signature_upper', 'drink_admin')
42+
op.drop_column('signature_upper', 'c_m')
43+
op.drop_column('signature_upper', 'active_rtp')
44+
# ### end Alembic commands ###

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "CSH Packet",
33
"name": "csh-packet",
4-
"version": "3.1.1",
4+
"version": "3.2",
55
"description": "A web app implementation of the CSH introductory packet.",
66
"bugs": {
77
"url": "https://github.com/ComputerScienceHouse/packet/issues",

packet/__init__.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from flask import Flask
1111
from flask_migrate import Migrate
1212
from flask_pyoidc.flask_pyoidc import OIDCAuthentication
13+
from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata
1314
from flask_sqlalchemy import SQLAlchemy
1415

1516
app = Flask(__name__)
@@ -37,11 +38,11 @@
3738
migrate = Migrate(app, db)
3839
app.logger.info("SQLAlchemy pointed at " + repr(db.engine.url))
3940

40-
auth = OIDCAuthentication(app, issuer=app.config["OIDC_ISSUER"], client_registration_info={
41-
"client_id": app.config["OIDC_CLIENT_ID"],
42-
"client_secret": app.config["OIDC_CLIENT_SECRET"],
43-
"post_logout_redirect_uris": "/logout/"
44-
})
41+
APP_CONFIG = ProviderConfiguration(issuer=app.config["OIDC_ISSUER"],
42+
client_metadata=ClientMetadata(app.config["OIDC_CLIENT_ID"],
43+
app.config["OIDC_CLIENT_SECRET"]))
44+
45+
auth = OIDCAuthentication({'app': APP_CONFIG}, app)
4546

4647
# LDAP
4748
_ldap = csh_ldap.CSHLDAP(app.config["LDAP_BIND_DN"], app.config["LDAP_BIND_PASS"])

packet/commands.py

+52-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
from . import app, db
1111
from .models import Freshman, Packet, FreshSignature, UpperSignature, MiscSignature
12-
from .ldap import ldap_get_active_members, ldap_is_eboard, ldap_is_intromember
12+
from .ldap import ldap_get_eboard_role, ldap_get_active_rtps, ldap_get_3das, ldap_get_webmasters, \
13+
ldap_get_drink_admins, ldap_get_constitutional_maintainers, ldap_is_intromember, ldap_get_active_members, \
14+
ldap_is_on_coop
1315

1416

1517
@app.cli.command("create-secret")
@@ -113,7 +115,14 @@ def create_packets(freshmen_csv):
113115
end = datetime.combine(base_date, packet_end_time) + timedelta(days=14)
114116

115117
print("Fetching data from LDAP...")
116-
all_upper = list(filter(lambda member: not ldap_is_intromember(member), ldap_get_active_members()))
118+
all_upper = list(filter(
119+
lambda member: not ldap_is_intromember(member) and not ldap_is_on_coop(member), ldap_get_active_members()))
120+
121+
rtp = ldap_get_active_rtps()
122+
three_da = ldap_get_3das()
123+
webmaster = ldap_get_webmasters()
124+
c_m = ldap_get_constitutional_maintainers()
125+
drink = ldap_get_drink_admins()
117126

118127
# Create the new packets and the signatures for each freshman in the given CSV
119128
freshmen_in_csv = parse_csv(freshmen_csv)
@@ -123,7 +132,14 @@ def create_packets(freshmen_csv):
123132
db.session.add(packet)
124133

125134
for member in all_upper:
126-
db.session.add(UpperSignature(packet=packet, member=member.uid, eboard=ldap_is_eboard(member)))
135+
sig = UpperSignature(packet=packet, member=member.uid)
136+
sig.eboard = ldap_get_eboard_role(member)
137+
sig.active_rtp = member.uid in rtp
138+
sig.three_da = member.uid in three_da
139+
sig.webmaster = member.uid in webmaster
140+
sig.c_m = member.uid in c_m
141+
sig.drink_admin = member.uid in drink
142+
db.session.add(sig)
127143

128144
for onfloor_freshman in Freshman.query.filter_by(onfloor=True).filter(Freshman.rit_username !=
129145
freshman.rit_username).all():
@@ -139,32 +155,57 @@ def ldap_sync():
139155
Updates the upper and misc sigs in the DB to match ldap.
140156
"""
141157
print("Fetching data from LDAP...")
142-
all_upper = {member.uid: member for member in filter(lambda member: not ldap_is_intromember(member),
143-
ldap_get_active_members())}
158+
all_upper = {member.uid: member for member in filter(
159+
lambda member: not ldap_is_intromember(member) and not ldap_is_on_coop(member), ldap_get_active_members())}
160+
161+
rtp = ldap_get_active_rtps()
162+
three_da = ldap_get_3das()
163+
webmaster = ldap_get_webmasters()
164+
c_m = ldap_get_constitutional_maintainers()
165+
drink = ldap_get_drink_admins()
144166

145167
print("Applying updates to the DB...")
146168
for packet in Packet.query.filter(Packet.end > datetime.now()).all():
147-
# Update the eboard state of all UpperSignatures
169+
# Update the role state of all UpperSignatures
148170
for sig in filter(lambda sig: sig.member in all_upper, packet.upper_signatures):
149-
sig.eboard = ldap_is_eboard(all_upper[sig.member])
171+
sig.eboard = ldap_get_eboard_role(all_upper[sig.member])
172+
sig.active_rtp = sig.member in rtp
173+
sig.three_da = sig.member in three_da
174+
sig.webmaster = sig.member in webmaster
175+
sig.c_m = sig.member in c_m
176+
sig.drink_admin = sig.member in drink
150177

151178
# Migrate UpperSignatures that are from accounts that are not active anymore
152179
for sig in filter(lambda sig: sig.member not in all_upper, packet.upper_signatures):
153180
UpperSignature.query.filter_by(packet_id=packet.id, member=sig.member).delete()
154181
if sig.signed:
155-
db.session.add(MiscSignature(packet=packet, member=sig.member))
182+
sig = MiscSignature(packet=packet, member=sig.member)
183+
db.session.add(sig)
156184

157185
# Migrate MiscSignatures that are from accounts that are now active members
158186
for sig in filter(lambda sig: sig.member in all_upper, packet.misc_signatures):
159187
MiscSignature.query.filter_by(packet_id=packet.id, member=sig.member).delete()
160-
db.session.add(UpperSignature(packet=packet, member=sig.member,
161-
eboard=ldap_is_eboard(all_upper[sig.member]), signed=True))
188+
sig = UpperSignature(packet=packet, member=sig.member, signed=True)
189+
sig.eboard = ldap_get_eboard_role(all_upper[sig.member])
190+
sig.active_rtp = sig.member in rtp
191+
sig.three_da = sig.member in three_da
192+
sig.webmaster = sig.member in webmaster
193+
sig.c_m = sig.member in c_m
194+
sig.drink_admin = sig.member in drink
195+
db.session.add(sig)
162196

163197
# Create UpperSignatures for any new active members
164198
# pylint: disable=cell-var-from-loop
165199
upper_sigs = set(map(lambda sig: sig.member, packet.upper_signatures))
166200
for member in filter(lambda member: member not in upper_sigs, all_upper):
167-
db.session.add(UpperSignature(packet=packet, member=member, eboard=ldap_is_eboard(all_upper[member])))
201+
UpperSignature(packet=packet, member=member)
202+
sig.eboard = ldap_get_eboard_role(all_upper[sig.member])
203+
sig.active_rtp = sig.member in rtp
204+
sig.three_da = sig.member in three_da
205+
sig.webmaster = sig.member in webmaster
206+
sig.c_m = sig.member in c_m
207+
sig.drink_admin = sig.member in drink
208+
db.session.add(sig)
168209

169210
db.session.commit()
170211
print("Done!")
@@ -190,7 +231,6 @@ def fetch_results():
190231
print("\tTotal score: {:0.2f}%".format(received.total / required.total * 100))
191232
print()
192233

193-
print("\tEboard: {}/{}".format(received.eboard, required.eboard))
194234
print("\tUpperclassmen: {}/{}".format(received.upper, required.upper))
195235
print("\tFreshmen: {}/{}".format(received.fresh, required.fresh))
196236
print("\tMiscellaneous: {}/{}".format(received.misc, required.misc))

packet/context_processors.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ def get_csh_name(username):
1818
except:
1919
return username
2020

21+
def get_roles(sig):
22+
"""
23+
Converts a signature's role fields to a dict for ease of access.
24+
:return: A dictionary of role short names to role long names
25+
"""
26+
out = {}
27+
if sig.eboard:
28+
out["eboard"] = sig.eboard
29+
if sig.active_rtp:
30+
out["rtp"] = "RTP"
31+
if sig.three_da:
32+
out["three_da"] = "3DA"
33+
if sig.webmaster:
34+
out["webmaster"] = "Webmaster"
35+
if sig.c_m:
36+
out["cm"] = "Constitutional Maintainer"
37+
if sig.drink_admin:
38+
out["drink"] = "Drink Admin"
39+
return out
40+
2141

2242
# pylint: disable=bare-except
2343
@lru_cache(maxsize=128)
@@ -38,4 +58,4 @@ def log_time(label):
3858

3959
@app.context_processor
4060
def utility_processor():
41-
return dict(get_csh_name=get_csh_name, get_rit_name=get_rit_name, log_time=log_time)
61+
return dict(get_csh_name=get_csh_name, get_rit_name=get_rit_name, log_time=log_time, get_roles=get_roles)

0 commit comments

Comments
 (0)