Skip to content

Commit 54c27fb

Browse files
Merge pull request #169 from devinmatte/oidc
Adding Flask_pyoidc and Updating to Python 3.6
2 parents b579158 + da9a8fe commit 54c27fb

21 files changed

+484
-520
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
language: python
22
python:
3-
- "3.3"
3+
- "3.6"
44

55
install:
66
- "pip install -r requirements.txt"

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,24 @@ Then, install the pipeline and frontend dependencies:
3131
npm install
3232
```
3333

34+
### Config
35+
3436
You must create `config.py` in the top-level directory with the appropriate credentials for the application to run. See `config.sample.py` for an example.
3537

38+
#### Add OIDC Config
39+
Reach out to an RTP to get OIDC credentials that will allow you to develop locally behind OIDC auth
40+
```
41+
# OIDC Config
42+
OIDC_ISSUER = "https://sso.csh.rit.edu/auth/realms/csh"
43+
OIDC_CLIENT_CONFIG = {
44+
'client_id': '',
45+
'client_secret': '',
46+
'post_logout_redirect_uris': ['http://0.0.0.0:6969/logout']
47+
}
48+
```
49+
50+
### Run
51+
3652
Once you have all of the dependencies installed, simply run:
3753

3854
```

conditional/__init__.py

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import os
22
import subprocess
33
from datetime import datetime
4-
from flask import Flask, redirect, request, render_template, g
5-
from flask_sqlalchemy import SQLAlchemy
6-
from flask_migrate import Migrate
4+
5+
import structlog
76
from csh_ldap import CSHLDAP
8-
from raven import fetch_git_sha
7+
from flask import Flask, redirect, render_template, g
8+
from flask_migrate import Migrate
9+
from flask_pyoidc.flask_pyoidc import OIDCAuthentication
10+
from flask_sqlalchemy import SQLAlchemy
911
from raven.contrib.flask import Sentry
10-
from raven.exceptions import InvalidGitRepository
11-
import structlog
1212

1313
app = Flask(__name__)
1414

@@ -22,7 +22,6 @@
2222
'--short',
2323
'HEAD']).decode('utf-8').rstrip()
2424

25-
2625
db = SQLAlchemy(app)
2726
migrate = Migrate(app, db)
2827
sentry = Sentry(app)
@@ -31,17 +30,24 @@
3130
app.config['LDAP_BIND_PW'],
3231
ro=app.config['LDAP_RO'])
3332

33+
auth = OIDCAuthentication(app, issuer=app.config["OIDC_ISSUER"],
34+
client_registration_info=app.config["OIDC_CLIENT_CONFIG"])
35+
36+
app.secret_key = app.config["SECRET_KEY"]
37+
3438
def start_of_year():
3539
start = datetime(datetime.today().year, 6, 1)
3640
if datetime.today() < start:
37-
start = datetime(datetime.today().year-1, 6, 1)
41+
start = datetime(datetime.today().year - 1, 6, 1)
3842
return start
3943

44+
4045
# pylint: disable=C0413
4146
from conditional.models.models import UserLog
4247

48+
4349
# Configure Logging
44-
def request_processor(logger, log_method, event_dict): # pylint: disable=unused-argument, redefined-outer-name
50+
def request_processor(logger, log_method, event_dict): # pylint: disable=unused-argument, redefined-outer-name
4551
if 'request' in event_dict:
4652
flask_request = event_dict['request']
4753
event_dict['user'] = flask_request.headers.get("x-webauth-user")
@@ -52,7 +58,7 @@ def request_processor(logger, log_method, event_dict): # pylint: disable=unused-
5258
return event_dict
5359

5460

55-
def database_processor(logger, log_method, event_dict): # pylint: disable=unused-argument, redefined-outer-name
61+
def database_processor(logger, log_method, event_dict): # pylint: disable=unused-argument, redefined-outer-name
5662
if 'request' in event_dict:
5763
if event_dict['method'] != 'GET':
5864
log = UserLog(
@@ -62,23 +68,25 @@ def database_processor(logger, log_method, event_dict): # pylint: disable=unused
6268
blueprint=event_dict['blueprint'],
6369
path=event_dict['path'],
6470
description=event_dict['event']
65-
)
71+
)
6672
db.session.add(log)
6773
db.session.flush()
6874
db.session.commit()
6975
del event_dict['request']
7076
return event_dict
7177

78+
7279
structlog.configure(processors=[
7380
request_processor,
7481
database_processor,
7582
structlog.processors.KeyValueRenderer()
76-
])
83+
])
7784

7885
logger = structlog.get_logger()
7986

87+
from conditional.util.auth import get_user
8088

81-
from conditional.blueprints.dashboard import dashboard_bp # pylint: disable=ungrouped-imports
89+
from conditional.blueprints.dashboard import dashboard_bp # pylint: disable=ungrouped-imports
8290
from conditional.blueprints.attendance import attendance_bp
8391
from conditional.blueprints.major_project_submission import major_project_bp
8492
from conditional.blueprints.intro_evals import intro_evals_bp
@@ -108,27 +116,36 @@ def database_processor(logger, log_method, event_dict): # pylint: disable=unused
108116

109117
from conditional.util.ldap import ldap_get_member
110118

119+
111120
@app.route('/<path:path>')
112121
def static_proxy(path):
113122
# send_static_file will guess the correct MIME type
114123
return app.send_static_file(path)
115124

116125

117126
@app.route('/')
127+
@auth.oidc_auth
118128
def default_route():
119129
return redirect('/dashboard')
120130

131+
132+
@app.route("/logout")
133+
@auth.oidc_logout
134+
def logout():
135+
return redirect("/", 302)
136+
137+
121138
@app.errorhandler(404)
122139
@app.errorhandler(500)
123-
def route_errors(error):
140+
@auth.oidc_auth
141+
@get_user
142+
def route_errors(error, user_dict=None):
124143
data = dict()
125-
username = request.headers.get('x-webauth-user')
126144

127145
# Handle the case where the header isn't present
128-
if username is not None:
129-
member = ldap_get_member(username)
130-
data['username'] = member.uid
131-
data['name'] = member.cn
146+
if user_dict['username'] is not None:
147+
data['username'] = user_dict['account'].uid
148+
data['name'] = user_dict['account'].cn
132149
else:
133150
data['username'] = "unknown"
134151
data['name'] = "Unknown"
@@ -149,15 +166,17 @@ def route_errors(error):
149166
error_desc = type(error).__name__
150167

151168
return render_template('errors.html',
152-
error=error_desc,
153-
error_code=code,
154-
event_id=g.sentry_event_id,
155-
public_dsn=sentry.client.get_public_dsn('https'),
156-
**data), int(code)
169+
error=error_desc,
170+
error_code=code,
171+
event_id=g.sentry_event_id,
172+
public_dsn=sentry.client.get_public_dsn('https'),
173+
**data), int(code)
174+
157175

158176
@app.cli.command()
159177
def zoo():
160178
from conditional.models.migrate import free_the_zoo
161179
free_the_zoo(app.config['ZOO_DATABASE_URI'])
162180

181+
163182
logger.info('conditional started')

0 commit comments

Comments
 (0)