Skip to content
Open
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
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.env

/venv

#Ignoring git and cache folders
.git
.cache

.gitignore

#Ignoring all the markdown and class files
*.md

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,7 @@ cython_debug/
# keys
*.key
*.jwk.json

#envfiles
.env
.envrc
15 changes: 11 additions & 4 deletions Config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# TODO Add the right values
from tempfile import mkdtemp
from decouple import config

config = {
"DEBUG": True,
DOMAIN = config('DOMAIN', default='0.0.0.0')
PORT = config('PORT', default='5000')
tool_config = {
"DEBUG": config('DEBUG', default=True, cast=bool),
"ENV": "production",
"CACHE_TYPE": "simple",
"CACHE_DEFAULT_TIMEOUT": 600,
Expand All @@ -14,6 +17,10 @@
"SESSION_COOKIE_SECURE": True, # should be True in case of HTTPS usage (production)
"SESSION_COOKIE_SAMESITE": "None", # should be 'None' in case of HTTPS usage (production)
"DEBUG_TB_INTERCEPT_REDIRECTS": False,
"SERVER_NAME": "127.0.0.1:5000",
"LEARN_REST_KEY" : "somekey"
"SERVER_NAME": DOMAIN + (':' + PORT) if PORT != '80' else '',
"LEARN_REST_KEY" : "somekey",
"LEARN_REST_SECRET" : "somekey",
"LEARN_REST_HOST" : "somekey",
"APP_URL" : "somekey",
"VERIFY_CERTS" : 'True'
}
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM python:3.9.2

RUN apt-get update || : && apt-get install python -y
RUN apt-get install -y python-dev

# If running in Docker you will need to tell Flask what domain and port you are connecting with
#ENV DOMAIN=<myngrok>.ngrok.io
#ENV PORT=443

#ENV DOMAIN=localhost
#ENV PORT=5000

RUN mkdir /app
WORKDIR /app
COPY . .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN python /app/keys/build_config.py
ENV PYTHONPATH "${PYTHONPATH}:./app"
EXPOSE 5000

ENTRYPOINT ["/app/scripts/entrypoint.sh"]
ENTRYPOINT ["gunicorn", "--config", "gunicorn_config.py", "wsgi:application"]
52 changes: 50 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,56 @@
# BBDN-Workshop-Tool-Python

# Setup
## HOW TO

### Install

```
python -m venv <path to project>/BBDN-Workshop-Tool-Python/venv

pip install -r requirements.txt
```

### Setup
```
source venv/bin/activate

export PYTHONPATH='<path to project>/BBDN-Workshop-Tool-Python/app'
```

Build keys
```bash
python keys/build_config.py
```
```

### Configuration
Edit the `lti.json` file in the root folder to configure your Client ID, devportal, and Deployment ID.

### Run

```
python app.py
```

### Configuration

If you want to modify your configuration it's best to create a `.env` file. These are the possible values you can change:

```
PORT='5000'
DOMAIN='localhost'
FRONTEND_URL='http://localhost:3000'
```














12 changes: 6 additions & 6 deletions RestAuthContoller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,31 @@
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Import Config
import Config
import Config as config


class RestAuthController():
target_url = ''

def __init__(self, authcode):

self.KEY = Config.config['learn_rest_key']
self.SECRET = Config.config['learn_rest_secret']
self.KEY = config.tool_config['LEARN_REST_KEY']
self.SECRET = config.tool_config['LEARN_REST_SECRET']

self.CREDENTIALS = 'authorization_code'
self.PAYLOAD = {
'grant_type': 'authorization_code'
}
self.TOKEN = None
self.target_url = Config.config['learn_rest_url']
self.target_url = config.tool_config['LEARN_REST_URL']

self.app_url = Config.config['app_url']
self.app_url = config.tool_config['APP_URL']

self.authcode = authcode

self.EXPIRES_AT = ''

if Config.config['verify_certs'] == 'True':
if config.tool_config['VERIFY_CERTS'] == 'True':
self.verify_certs = True
else:
self.verify_certs = False
Expand Down
23 changes: 13 additions & 10 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
import uuid
from tempfile import mkdtemp

from flask import Flask, render_template
from flask import Flask, render_template, jsonify
from flask import redirect, request
from flask_caching import Cache
from flask_login import login_required
#from flask_login import login_required
from pylti1p3.contrib.flask import FlaskMessageLaunch, FlaskOIDCLogin, FlaskRequest, FlaskCacheDataStorage
from pylti1p3.tool_config import ToolConfJsonFile

import Config
import Config as config
from RestAuthContoller import RestAuthController

## TODO

PAGE_TITLE = 'Title'


Expand All @@ -34,13 +33,12 @@ def __call__(self, environ, start_response):

app.wsgi_app = ReverseProxied(app.wsgi_app)

app.config.from_mapping(Config.config)
app.config.from_mapping(config.tool_config)

cache = Cache(app)


@app.route('/', methods=['GET', 'POST'])
@login_required
def index():
return render_template('index.html')

Expand Down Expand Up @@ -115,9 +113,9 @@ def launch():

# Add the one_time_session_cookie to the query parameters to send to the Authorization Code endpoint
params = {
'redirect_uri': Config.config['SERVER_NAME'] + '/authcode/',
'redirect_uri': config.tool_config['SERVER_NAME'] + '/authcode/',
'response_type': 'code',
'client_id': Config.config['LEARN_REST_KEY'],
'client_id': config.tool_config['LEARN_REST_KEY'],
'one_time_session_token': one_time_session_token,
'scope': '*',
'state': str(uuid.uuid4())
Expand All @@ -143,16 +141,21 @@ def authcode():
token = restAuthController.getToken()
uuid = restAuthController.getUuid()


# TODO Implement REST call to get course created date, add it and data from launch to kwargs


tp_kwargs = {
'title': PAGE_TITLE,
}

return render_template('index.html', **tp_kwargs)


@app.route('/jwks/', methods=['GET'])
def get_jwks():
tool_conf = ToolConfJsonFile(get_lti_config_path())
return jsonify({'keys': tool_conf.get_jwks()})


if __name__ == '__main__':
restAuthController = None
app.run(host='0.0.0.0', port=5000)
4 changes: 4 additions & 0 deletions gunicorn_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bind = "0.0.0.0:5000"
workers = 4
threads = 4
timeout = 120
4 changes: 3 additions & 1 deletion requirements.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
pip-tools
flask
pylti1p3
gunicorn
flask_caching
flask_login
cachetools
pycryptodome
jwcrypto
jwcrypto
python-decouple
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ flask-caching==1.10.1
# via -r requirements.in
flask-login==0.5.0
# via -r requirements.in
gunicorn==20.1.0
# via -r requirements.in
idna==3.2
# via requests
itsdangerous==2.0.1
Expand All @@ -53,6 +55,8 @@ pyjwt==2.1.0
# via pylti1p3
pylti1p3==1.9.1
# via -r requirements.in
python-decouple==3.4
# via -r requirements.in
requests==2.26.0
# via pylti1p3
tomli==1.2.1
Expand Down
4 changes: 4 additions & 0 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#! /bin/sh

if [ "${LOCALDOMAIN}" != "" ]; then echo "search ${LOCALDOMAIN}" >> /etc/resolv.conf; fi
exec "$@"
46 changes: 46 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>

</head>
<body>
Thank you, I'm finally a free LTI tool
<br/>
<b> Here is some basic information for you</b>
<table>
<tr>
<th><b>Key</b></th>
<th><b>Value</b></th>
</tr>
<tr>
<td>Username</td>
<td>{{ username }}</td>
</tr>
<tr>
<td>User UUID</td>
<td>{{ user_uuid }}</td>
</tr>
<tr>
<td>User BatchUID</td>
<td>{{ user_batch_uid }}</td>
</tr>
<tr>
<td>Course ID</td>
<td>{{ course_id }}</td>
</tr>
<tr>
<td>Course Title</td>
<td>{{ course_title }}</td>
</tr>
<tr>
<td>Course UUID</td>
<td>{{ course_uuid }}</td>
</tr>
<tr>
<td>Course BatchUID</td>
<td>{{ course_batch_uid }}</td>
</tr>
</table>

</body>
</html>
4 changes: 4 additions & 0 deletions wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from app import app

application = app