Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM mcr.microsoft.com/vscode/devcontainers/universal:1-linux

USER root

# Add LDAP and python dependency build deps
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
apt-get -yq --no-install-recommends install gcc curl libsasl2-dev libldap2-dev libssl-dev python3-dev

USER codespace
58 changes: 58 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Update the VARIANT arg in docker-compose.yml to pick a Python version: 3, 3.8, 3.7, 3.6
{
"name": "Packet Codespace (python and postgres)",
"dockerComposeFile": "docker-compose.yaml",
"service": "app",

// Set *default* container specific settings.json values on container create.
"settings": {
"sqltools.connections": [{
"name": "Container database",
"driver": "PostgreSQL",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"database": "postgres",
"username": "postgres",
"password": "mysecretpassword"
}],
"terminal.integrated.shell.linux": "/bin/bash",
"python.pythonPath": "/opt/python/latest/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"python.testing.pytestPath": "/usr/local/py-utils/bin/pytest"
},
"remoteUser": "codespace",
"overrideCommand": false,
"workspaceMount": "source=${localWorkspaceFolder},target=/home/codespace/workspace,type=bind,consistency=cached",
"workspaceFolder": "/home/codespace/workspace",
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--privileged", "--init" ],

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"GitHub.vscode-pull-request-github",
"ms-python.python",
"mtxr.sqltools",
"mtxr.sqltools-driver-pg"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [5000, 5432],

// Use 'postCreateCommand' to run commands after the container is created.
// "oryx build" will automatically install your dependencies and attempt to build your project
"postCreateCommand": [
"pip install --progress-bar=off install -r requirements.txt;",
"yarn install && `yarn bin gulp production`;",
"/home/codespace/.local/bin/flask db upgrade;"
]
}
41 changes: 41 additions & 0 deletions .devcontainer/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
version: '3'

services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
NODE_VERSION: "10"

volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ..:/workspace:cached

# Overrides default command so things don't shut down after the process ends.
command: sleep infinity

# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db

# Uncomment the next line to use a non-root user for all processes.
user: codespace

# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)

db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: mysecretpassword

# Add "forwardPorts": ["5432"] to **devcontainer.json** to forward MongoDB locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)

volumes:
postgres-data:
4 changes: 2 additions & 2 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:

strategy:
matrix:
python-version: [3.7, 3.8]
python-version: [3.9]

steps:
- name: Install ldap dependencies
run: sudo apt-get install libldap2-dev libsasl2-dev
run: sudo apt-get update && sudo apt-get install libldap2-dev libsasl2-dev
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
Expand Down
1 change: 1 addition & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[MASTER]
ignore = ,input
persistent = yes
load-plugins = pylint_quotes

[MESSAGES CONTROL]
disable =
Expand Down
11 changes: 8 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
FROM python:3.7-slim-buster
FROM python:3.9-slim-buster
MAINTAINER Devin Matte <[email protected]>

ENV DD_LOGS_INJECTION=true

RUN apt-get -yq update && \
apt-get -yq --no-install-recommends install gcc curl libsasl2-dev libldap2-dev libssl-dev gnupg2 && \
apt-get -yq --no-install-recommends install gcc curl libsasl2-dev libldap2-dev libssl-dev gnupg2 git && \
apt-get -yq clean all

RUN mkdir /opt/packet
Expand Down Expand Up @@ -30,4 +32,7 @@ RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && \

RUN ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime

CMD ["gunicorn", "packet:app", "--bind=0.0.0.0:8080", "--access-logfile=-", "--timeout=600"]
# Set version for apm
RUN echo "export DD_VERSION=$(python3 packet/git.py)" >> /tmp/version

CMD ["/bin/bash", "-c", "source /tmp/version && ddtrace-run gunicorn packet:app --bind=0.0.0.0:8080 --access-logfile=- --timeout=600"]
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# CSH Web Packet

[![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://www.python.org/downloads/release/python-370/)
[![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/release/python-390/)
[![Build Status](https://travis-ci.com/ComputerScienceHouse/packet.svg?branch=develop)](https://travis-ci.com/ComputerScienceHouse/packet)

Packet is used by CSH to facilitate the freshmen packet portion of our introductory member evaluation process. This is
the second major iteration of packet on the web. The first version was
[Tal packet](https://github.com/TalCohen/CSHWebPacket).

## Setup
**Requires Python 3.7 or newer.**
**Requires Python 3.9 or newer.**

To get the server working you'll just need the Python dependencies and some secrets. There will be some UI issues due
to missing assets though. To solve that you'll want to set up the front end dependencies or download a copy of the
Expand Down Expand Up @@ -115,12 +115,12 @@ All DB commands are from the `Flask-Migrate` library and are used to configure D
docs [here](https://flask-migrate.readthedocs.io/en/latest/) for details.

## Code standards
This project is configured to use Pylint. Commits will be pylinted by Travis CI and if the score drops your build will
This project is configured to use Pylint. Commits will be pylinted by GitHub actions and if the score drops your build will
fail blocking you from merging. To make your life easier just run it before making a PR.

To run pylint use this command:
```bash
pylint --load-plugins pylint_quotes packet/routes packet
pylint packet/routes packet
```

All python files should have a top-level docstring explaining the contents of the file and complex functions should
Expand Down
6 changes: 5 additions & 1 deletion config.env.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

# Logging config
LOG_LEVEL = environ.get("PACKET_LOG_LEVEL", "INFO")
ANALYTICS_ID = environ.get("ANALYTICS_ID", "UA-420696-9")

# OpenID Connect SSO config
REALM = environ.get("PACKET_REALM", "csh")
Expand Down Expand Up @@ -68,3 +67,8 @@
# Packet Config
PACKET_UPPER = environ.get("PACKET_UPPER", "packet.csh.rit.edu")
PACKET_INTRO = environ.get("PACKET_INTRO", "freshmen-packet.csh.rit.edu")

# RUM
RUM_APP_ID = environ.get("PACKET_RUM_APP_ID", "")
RUM_CLIENT_TOKEN = environ.get("PACKET_RUM_CLIENT_TOKEN","")
DD_ENV = environ.get("DD_ENV", "local-dev")
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "CSH Packet",
"name": "csh-packet",
"version": "3.5.2",
"version": "3.5.3",
"description": "A web app implementation of the CSH introductory packet.",
"bugs": {
"url": "https://github.com/ComputerScienceHouse/packet/issues",
Expand Down
7 changes: 4 additions & 3 deletions packet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from sentry_sdk.integrations.flask import FlaskIntegration
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration

from .git import get_version

app = Flask(__name__)
gzip = Gzip(app)

Expand All @@ -31,9 +33,8 @@
if os.path.exists(_pyfile_config):
app.config.from_pyfile(_pyfile_config)

# Fetch the version number from the npm package file
with open(os.path.join(_root_dir, 'package.json')) as package_file:
app.config['VERSION'] = json.load(package_file)['version']
# Fetch the version number
app.config['VERSION'] = get_version()

# Logger configuration
logging.getLogger().setLevel(app.config['LOG_LEVEL'])
Expand Down
49 changes: 49 additions & 0 deletions packet/git.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import json
import os
import subprocess

def get_short_sha(commit_ish: str = 'HEAD'):
"""
Get the short hash of a commit-ish
Returns '' if unfound
"""

try:
rev_parse = subprocess.run(f'git rev-parse --short {commit_ish}'.split(), capture_output=True, check=True)
return rev_parse.stdout.decode('utf-8').strip()
except subprocess.CalledProcessError:
return ''

def get_tag(commit_ish: str = 'HEAD'):
"""
Get the name of the tag at a given commit-ish
Returns '' if untagged
"""

try:
describe = subprocess.run(f'git describe --exact-match {commit_ish}'.split(), capture_output=True, check=True)
return describe.stdout.decode('utf-8').strip()
except subprocess.CalledProcessError:
return ''

def get_version(commit_ish: str = 'HEAD'):
"""
Get the version string of a commit-ish

If we have a commit and the commit is tagged, version is `tag (commit-sha)`
If we have a commit but not a tag, version is `commit-sha`
If we have neither, version is the version field of package.json
"""

if sha := get_short_sha(commit_ish):
if tag := get_tag(commit_ish):
return f'{tag} ({sha})'
else:
return sha
else:
root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
with open(os.path.join(root_dir, 'package.json')) as package_file:
return json.load(package_file)['version']

if __name__ == '__main__':
print(get_version())
18 changes: 18 additions & 0 deletions packet/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ def _is_member_of_group(self, member, group):
else:
return group in member.groups

def get_groups(self, member):
if self.ldap:
return list(
map(
lambda g: g[0][3:],
filter(
lambda d: d[1] == 'cn=groups',
map(
lambda group_dn: group_dn.split(','),
member.get('memberOf')
)
)
)
)
else:
return member.groups



# Getters

Expand Down
17 changes: 9 additions & 8 deletions packet/routes/upperclassmen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
"""
import json

from itertools import chain
from operator import itemgetter
from flask import redirect, render_template, url_for

from packet import app
from packet.models import Packet, MiscSignature
from packet.models import Packet
from packet.utils import before_request, packet_auth
from packet.log_utils import log_cache, log_time
from packet.stats import packet_stats
Expand Down Expand Up @@ -51,18 +50,20 @@ def upperclassmen_total(info=None):

# Sum up the signed packets per upperclassman
upperclassmen = dict()
misc = dict()
for packet in open_packets:
for sig in chain(packet.upper_signatures, packet.misc_signatures):
for sig in packet.upper_signatures:
if sig.member not in upperclassmen:
upperclassmen[sig.member] = 0

if isinstance(sig, MiscSignature):
upperclassmen[sig.member] += 1
elif sig.signed:
upperclassmen[sig.member] += 1
if sig.signed:
upperclassmen[sig.member] += 1
for sig in packet.misc_signatures:
misc[sig.member] = 1 + misc.get(sig.member, 0)

return render_template('upperclassmen_totals.html', info=info, num_open_packets=len(open_packets),
upperclassmen=sorted(upperclassmen.items(), key=itemgetter(1), reverse=True))
upperclassmen=sorted(upperclassmen.items(), key=itemgetter(1), reverse=True),
misc=sorted(misc.items(), key=itemgetter(1), reverse=True))


@app.route('/stats/packet/<packet_id>')
Expand Down
Loading