Skip to content
Snippets Groups Projects
Commit 6359499c authored by Roman Karwacik's avatar Roman Karwacik
Browse files

Merge branch 'moodle-integration' into 'master'

Moodle Authentication

See merge request videoaginfra/website!29
parents 5ec5c2e2 2637db42
No related branches found
No related tags found
No related merge requests found
...@@ -3,12 +3,18 @@ import requests ...@@ -3,12 +3,18 @@ import requests
L2P_BASE = 'https://www3.elearning.rwth-aachen.de/_vti_bin/l2pservices/api.svc/v1/' L2P_BASE = 'https://www3.elearning.rwth-aachen.de/_vti_bin/l2pservices/api.svc/v1/'
OAUTH_BASE = 'https://oauth.campus.rwth-aachen.de/oauth2waitress/oauth2.svc/' OAUTH_BASE = 'https://oauth.campus.rwth-aachen.de/oauth2waitress/oauth2.svc/'
MOODLE_BASE = 'https://moped.ecampus.rwth-aachen.de/proxy/api/v2/eLearning/Moodle/'
def l2pget(endpoint, token, **args): def l2pget(endpoint, token, **args):
args['accessToken'] = token args['accessToken'] = token
r = requests.request('GET', L2P_BASE+endpoint, params=args) r = requests.request('GET', L2P_BASE+endpoint, params=args)
return r.json() return r.json()
def moodleget(endpoint, token, **args):
args['token'] = token
r = requests.request('GET', MOODLE_BASE+endpoint, params=args)
return r.json()
def oauthget(endpoint, **args): def oauthget(endpoint, **args):
args['client_id'] = config['L2P_APIKEY'] args['client_id'] = config['L2P_APIKEY']
r = requests.request('POST', OAUTH_BASE+endpoint, data=args) r = requests.request('POST', OAUTH_BASE+endpoint, data=args)
...@@ -23,6 +29,15 @@ def start_l2pauth(): ...@@ -23,6 +29,15 @@ def start_l2pauth():
session['oauthscope'] = 'l2p' session['oauthscope'] = 'l2p'
return redirect(code['verification_url']+'?q=verify&d='+code['user_code']) return redirect(code['verification_url']+'?q=verify&d='+code['user_code'])
@app.route('/internal/moodleauth')
def start_moodleauth():
if 'L2P_APIKEY' not in config:
return render_template("500.html"), 500
code = oauthget('code', scope='moodle.rwth')
session['oauthcode'] = code['device_code']
session['oauthscope'] = 'moodle'
return redirect(code['verification_url']+'?q=verify&d='+code['user_code'])
@app.route('/internal/rwthauth') @app.route('/internal/rwthauth')
def start_rwthauth(): def start_rwthauth():
if 'L2P_APIKEY' not in config: if 'L2P_APIKEY' not in config:
...@@ -42,12 +57,16 @@ def finish_oauth(): ...@@ -42,12 +57,16 @@ def finish_oauth():
if token.get('status') != 'ok': if token.get('status') != 'ok':
return return
del session['oauthcode'] del session['oauthcode']
if session['oauthscope'] not in ['l2p', 'rwth']: if session['oauthscope'] not in ['l2p', 'rwth', 'moodle']:
return return
session['rwthintern'] = True session['rwthintern'] = True
if session['oauthscope'] == 'l2p': if session['oauthscope'] == 'l2p':
session['l2p_courses'] = [] session['l2p_courses'] = []
for course in l2pget('viewAllCourseInfo', token['access_token'])['dataSet']: for course in l2pget('viewAllCourseInfo', token['access_token'])['dataSet']:
session['l2p_courses'].append(course['uniqueid']) session['l2p_courses'].append(course['uniqueid'])
elif session['oauthscope'] == 'moodle':
session['moodle_courses'] = []
for course in moodleget('getmyenrolledcourses', token['access_token'])['Data']:
session['moodle_courses'].append(str(course['id']))
del session['oauthscope'] del session['oauthscope']
oauthget('token', refresh_token=token['refresh_token'], grant_type='invalidate') oauthget('token', refresh_token=token['refresh_token'], grant_type='invalidate')
...@@ -332,6 +332,11 @@ def lecture(id, course=None, courseid=None): ...@@ -332,6 +332,11 @@ def lecture(id, course=None, courseid=None):
flash(text+'. Du bist kein Teilnehmer des L2P-Kurses! <a target="_blank" class="reloadonclose" href="'+url_for('start_l2pauth')+'">Kurse aktualisieren</a>.', category='player') flash(text+'. Du bist kein Teilnehmer des L2P-Kurses! <a target="_blank" class="reloadonclose" href="'+url_for('start_l2pauth')+'">Kurse aktualisieren</a>.', category='player')
else: else:
flash(text+'. <a target="_blank" class="reloadonclose" href="'+url_for('start_l2pauth')+'">Hier authorisieren</a>.', category='player') flash(text+'. <a target="_blank" class="reloadonclose" href="'+url_for('start_l2pauth')+'">Hier authorisieren</a>.', category='player')
elif mode == 'moodle':
if 'moodle_courses' in session:
flash(text+'. Du bist kein Teilnehmer des Moodle-Kurses! <a target="_blank" class="reloadonclose" href="'+url_for('start_moodleauth')+'">Kurse aktualisieren</a>.', category='player')
else:
flash(text+'. <a target="_blank" class="reloadonclose" href="'+url_for('start_moodleauth')+'">Hier authorisieren</a>.', category='player')
else: else:
flash(text+'.', category='player') flash(text+'.', category='player')
return render_template('embed.html' if request.endpoint == 'embed' else 'lecture.html', course=courses[0], lecture=lecture, videos=videos, chapters=chapters, seek=request.args.get('t')) return render_template('embed.html' if request.endpoint == 'embed' else 'lecture.html', course=courses[0], lecture=lecture, videos=videos, chapters=chapters, seek=request.args.get('t'))
......
...@@ -197,6 +197,9 @@ var moderator = { ...@@ -197,6 +197,9 @@ var moderator = {
case 'l2p': case 'l2p':
permstring = '(' + perm.param1 + ')' permstring = '(' + perm.param1 + ')'
break; break;
case 'moodle':
permstring = '(' + perm.param1 + ')'
break;
} }
html += '<option data-id="'+perm.id+'" data-type="'+perm.type+'" data-param1="'+perm.param1+'" data-param2="'+perm.param2+'">#'+perm.id+' '+perm.type+' '+ permstring +'</option>'; html += '<option data-id="'+perm.id+'" data-type="'+perm.type+'" data-param1="'+perm.param1+'" data-param2="'+perm.param2+'">#'+perm.id+' '+perm.type+' '+ permstring +'</option>';
} }
...@@ -220,6 +223,9 @@ var moderator = { ...@@ -220,6 +223,9 @@ var moderator = {
case 'l2p': case 'l2p':
$(".authl2p", container).val(perm.param1); $(".authl2p", container).val(perm.param1);
break break
case 'moodle':
$(".authmoodle", container).val(perm.param1);
break
} }
$(".authtype option[value="+perm.type+"]").prop("selected", true); $(".authtype option[value="+perm.type+"]").prop("selected", true);
}, },
...@@ -266,6 +272,9 @@ var moderator = { ...@@ -266,6 +272,9 @@ var moderator = {
case 'l2p': case 'l2p':
perm.param1 = $(".authl2p", container).val(); perm.param1 = $(".authl2p", container).val();
break break
case 'moodle':
perm.param1 = $(".authmoodle", container).val();
break
} }
return perm; return perm;
}, },
...@@ -277,18 +286,27 @@ var moderator = { ...@@ -277,18 +286,27 @@ var moderator = {
$(".authuser", container).val(''); $(".authuser", container).val('');
$(".authpassword", container).val(''); $(".authpassword", container).val('');
$(".authl2p", container).val(''); $(".authl2p", container).val('');
$(".authmoodle", container).val('');
switch (type) { switch (type) {
case 'password': case 'password':
$(".passwordinput",container).show(); $(".passwordinput",container).show();
$(".authl2p",container).hide(); $(".authl2p",container).hide();
$(".authmoodle",container).hide();
break; break;
case 'l2p': case 'l2p':
$(".passwordinput",container).hide(); $(".passwordinput",container).hide();
$(".authl2p",container).show(); $(".authl2p",container).show();
$(".authmoodle",container).hide();
break;
case 'moodle':
$(".passwordinput",container).hide();
$(".authl2p",container).hide();
$(".authmoodle",container).show();
break; break;
default: default:
$(".passwordinput",container).hide(); $(".passwordinput",container).hide();
$(".authl2p",container).hide(); $(".authl2p",container).hide();
$(".authmoodle",container).hide();
break; break;
} }
}, },
......
static/moodle.png

1.29 KiB

...@@ -91,6 +91,9 @@ def checkperm(perms, username=None, password=None): ...@@ -91,6 +91,9 @@ def checkperm(perms, username=None, password=None):
elif perm['type'] == 'l2p': elif perm['type'] == 'l2p':
if perm['param1'] in session.get('l2p_courses', []): if perm['param1'] in session.get('l2p_courses', []):
return True return True
elif perm['type'] == 'moodle':
if perm['param1'] in session.get('moodle_courses', []):
return True
elif perm['type'] == 'rwth': elif perm['type'] == 'rwth':
if session.get('rwthintern', False): if session.get('rwthintern', False):
return True return True
...@@ -108,6 +111,7 @@ def permdescr(perms): ...@@ -108,6 +111,7 @@ def permdescr(perms):
public = False public = False
password = False password = False
l2p_courses = [] l2p_courses = []
moodle_courses = []
rwth_intern = False rwth_intern = False
fsmpi_intern = False fsmpi_intern = False
for perm in perms: for perm in perms:
...@@ -117,6 +121,8 @@ def permdescr(perms): ...@@ -117,6 +121,8 @@ def permdescr(perms):
password = True password = True
elif perm['type'] == 'l2p': elif perm['type'] == 'l2p':
l2p_courses.append(perm['param1']) l2p_courses.append(perm['param1'])
elif perm['type'] == 'moodle':
moodle_courses.append(perm['param1'])
elif perm['type'] == 'rwth': elif perm['type'] == 'rwth':
rwth_intern = True rwth_intern = True
elif perm['type'] == 'fsmpi': elif perm['type'] == 'fsmpi':
...@@ -133,6 +139,10 @@ def permdescr(perms): ...@@ -133,6 +139,10 @@ def permdescr(perms):
if password: if password:
return 'l2p', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar' return 'l2p', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
return 'l2p', 'Nur für Teilnehmer der Veranstaltung verfügbar' return 'l2p', 'Nur für Teilnehmer der Veranstaltung verfügbar'
if moodle_courses:
if password:
return 'moodle', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
return 'moodle', 'Nur für Teilnehmer der Veranstaltung verfügbar'
if password: if password:
return 'password', 'Nur für Nutzer mit Passwort verfügbar' return 'password', 'Nur für Nutzer mit Passwort verfügbar'
return 'none', 'Nicht verfügbar' return 'none', 'Nicht verfügbar'
......
...@@ -126,12 +126,14 @@ ...@@ -126,12 +126,14 @@
<option value="rwth">RWTH intern</option> <option value="rwth">RWTH intern</option>
<option value="fsmpi">FSMPI intern</option> <option value="fsmpi">FSMPI intern</option>
<option value="l2p">L2P Lernraum</option> <option value="l2p">L2P Lernraum</option>
<option value="moodle">Moodle Lernraum</option>
<option value="none">Kein Zugriff</option> <option value="none">Kein Zugriff</option>
</select> </select>
<input class="col-xs-12 passwordinput authuser" type="text" placeholder="Benutzername"> <input class="col-xs-12 passwordinput authuser" type="text" placeholder="Benutzername">
<input class="col-xs-10 passwordinput authpassword" type="text" placeholder="Passwort"> <input class="col-xs-10 passwordinput authpassword" type="text" placeholder="Passwort">
<button class="col-xs-2 passwordinput authpgen" type="button" onclick="$('.authpassword',this.parentNode).val(moderator.permissioneditor.randompw());"><span class="fa fa-refresh" aria-hidden="true"></span></button> <button class="col-xs-2 passwordinput authpgen" type="button" onclick="$('.authpassword',this.parentNode).val(moderator.permissioneditor.randompw());"><span class="fa fa-refresh" aria-hidden="true"></span></button>
<input class="col-xs-12 authl2p" type="text" placeholder="Lernraum" style="display: none;"> <input class="col-xs-12 authl2p" type="text" placeholder="Lernraum" style="display: none;">
<input class="col-xs-12 authmoodle" type="text" placeholder="Lernraum" style="display: none;">
<button class="col-xs-4" onclick="moderator.permissioneditor.addbtnclick(this)">Add</button> <button class="col-xs-4" onclick="moderator.permissioneditor.addbtnclick(this)">Add</button>
<button class="col-xs-4" onclick="moderator.permissioneditor.updatebtnclick(this)">Update</button> <button class="col-xs-4" onclick="moderator.permissioneditor.updatebtnclick(this)">Update</button>
<button class="col-xs-4" onclick="moderator.permissioneditor.delbtnclick(this)">Delete</button> <button class="col-xs-4" onclick="moderator.permissioneditor.delbtnclick(this)">Delete</button>
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
<ul> <ul>
<li><strong>Öffentliche</strong> Videos (<span class="fa fa-globe-asia"></span>) können von jedem abgespielt werden.</li> <li><strong>Öffentliche</strong> Videos (<span class="fa fa-globe-asia"></span>) können von jedem abgespielt werden.</li>
<li><strong>RWTH-interne</strong> Videos (<span class="fa" style="width: 25px; height: 17px; background-size: cover; background-image: url('/static/rwth.png');"></span>) sind nur für RWTH-Angehörige verfügbar. Zum Anschauen ist eine Authentifizierung über das RWTH-Single-Sign-On nötig.</li> <li><strong>RWTH-interne</strong> Videos (<span class="fa" style="width: 25px; height: 17px; background-size: cover; background-image: url('/static/rwth.png');"></span>) sind nur für RWTH-Angehörige verfügbar. Zum Anschauen ist eine Authentifizierung über das RWTH-Single-Sign-On nötig.</li>
<li><strong>Lernraum-interne</strong> Videos (<span class="fa" style="width: 12px; height: 14px; background-size: cover; background-image: url('/static/l2p-logo.gif');"></span>) sind nur für Teilnehmer eines bestimmten L2P-Lernraums zugänglich. Wir überprüfen dies, indem du uns kurzzeitig Zugriff auf deinen L2P-Account gibst, aus dem wir die Liste deiner Lernräume auslesen. Solltest du eine Vorlesung hören, dem zugehörigen Lernraum aber nicht hinzugefügt worden sein, melde dich bitte beim entsprechenden Dozenten.</li> <li><strong>Lernraum-interne</strong> Videos (<span class="fa" style="width: 12px; height: 14px; background-size: cover; background-image: url('/static/l2p-logo.gif');"></span> oder <span class="fa" style="width: 12px; height: 14px; background-size: cover; background-image: url('/static/moodle.png');"></span>) sind nur für Teilnehmer eines bestimmten L2P- oder Moodle-Lernraums zugänglich. Wir überprüfen dies, indem du uns kurzzeitig Zugriff auf deinen L2P- oder Moodle-Account gibst, aus dem wir die Liste deiner Lernräume auslesen. Solltest du eine Vorlesung hören, dem zugehörigen Lernraum aber nicht hinzugefügt worden sein, melde dich bitte beim entsprechenden Dozenten.</li>
<li><strong>Passwort-geschützte</strong> Videos (<span class="fa fa-lock"></span>) sind nur nach Eingabe eines Passworts verfügbar, welches jedem zur Verfügung gestellt wurde, der Zugriff haben sollte. In der Regel gibt es gute Gründe, warum dieser Zugriffsschutz gewählt wurde.</li> <li><strong>Passwort-geschützte</strong> Videos (<span class="fa fa-lock"></span>) sind nur nach Eingabe eines Passworts verfügbar, welches jedem zur Verfügung gestellt wurde, der Zugriff haben sollte. In der Regel gibt es gute Gründe, warum dieser Zugriffsschutz gewählt wurde.</li>
</ul> </ul>
<p>Falls du keinen Zugriff auf ein Video hast, wird dies auf der Player-Seite angezeigt und ggf. auf die weiteren Schritte zur Authentifizierung verwiesen. Die erläuterten Möglichkeiten decken nicht jeden denkbaren Fall ab. Solltest du Zugriff auf eine Veranstaltung benötigen, aber aus irgendwelchen Gründen nicht haben, schreib uns eine Mail.</p> <p>Falls du keinen Zugriff auf ein Video hast, wird dies auf der Player-Seite angezeigt und ggf. auf die weiteren Schritte zur Authentifizierung verwiesen. Die erläuterten Möglichkeiten decken nicht jeden denkbaren Fall ab. Solltest du Zugriff auf eine Veranstaltung benötigen, aber aus irgendwelchen Gründen nicht haben, schreib uns eine Mail.</p>
...@@ -66,15 +66,15 @@ ...@@ -66,15 +66,15 @@
{% endcall %} {% endcall %}
<div class="faqHeader">Technisches</div> <div class="faqHeader">Technisches</div>
{% call faqentry("l2prights", "Warum benötigt ihr lesenden und schreibenden Zugriff auf meine L2P-Lernräume?") %} {% call faqentry("l2prights", "Warum benötigt ihr lesenden und schreibenden Zugriff auf meine L2P oder Moodle-Lernräume?") %}
<p>Auf vielfachen Wunsch unserer Dozenten haben wir die Möglichkeit umgesetzt, Videos nur für Teilnehmer eines bestimmten L2P-Lernraums zugänglich zu machen. <p>Auf vielfachen Wunsch unserer Dozenten haben wir die Möglichkeit umgesetzt, Videos nur für Teilnehmer eines bestimmten L2P- oder Moodle-Lernraums zugänglich zu machen.
Um dies umzusetzen benötigen wir die Liste der Lernräume eines Nutzers, und damit Zugriff auf den L2P-Account. Um dies umzusetzen benötigen wir die Liste der Lernräume eines Nutzers, und damit Zugriff auf den L2P- oder Moodle-Account.
Leider erlaubt uns das L2P nur entweder keinen oder vollen (also lesenden und schreibenden) Zugriff, sodass du uns zur Authentifizierung für Lernraum-interne Videos mehr Zugriffsrechte geben musst, als theoretisch nötig.</p> Leider erlaubt uns das L2P sowie Moodle nur entweder keinen oder vollen (also lesenden und schreibenden) Zugriff, sodass du uns zur Authentifizierung für Lernraum-interne Videos mehr Zugriffsrechte geben musst, als theoretisch nötig.</p>
<p>Um die Missbrauchsgefahr zu minimieren, widerrufen wir die Zugriffsrechte auf deine Lernräume, sobald wir die Liste der Lernräume abgerufen haben. <p>Um die Missbrauchsgefahr zu minimieren, widerrufen wir die Zugriffsrechte auf deine Lernräume, sobald wir die Liste der Lernräume abgerufen haben.
Du kannst dies <a href="https://oauth.campus.rwth-aachen.de/manage/">hier</a> überprüfen. Du kannst dies <a href="https://oauth.campus.rwth-aachen.de/manage/">hier</a> überprüfen.
Außerdem speichern wir keine Authentifikationsdaten auf unserem Server. Außerdem speichern wir keine Authentifikationsdaten auf unserem Server.
</p> </p>
<p>Details zu der dafür verwendeten Schnittstelle findest du in der <a href="https://www3.elearning.rwth-aachen.de/_vti_bin/L2PServices/api.svc/v1/Documentation">L2P-API-Dokumentation</a>.</p> <p>Details zu der dafür verwendeten Schnittstelle findest du in der <a href="https://www3.elearning.rwth-aachen.de/_vti_bin/L2PServices/api.svc/v1/Documentation">L2P-API-Dokumentation</a> und der <a href="https://moped.ecampus.rwth-aachen.de/proxy/api/v2/documentation">Moodle-API-Dokumentation</a>.</p>
{% endcall %} {% endcall %}
{% call faqentry("cookies", "Welche Cookies werden gesetzt und wofür?") %} {% call faqentry("cookies", "Welche Cookies werden gesetzt und wofür?") %}
<p>Beim reinen Betrachten der Seite setzen wir überhaupt keine Cookies. Einzig beim Abruf oder Abspielen von Videodateien und bei der Authentifizierung für RWTH- oder Lernraum-interne Videos werden Cookies gesetzt.</p> <p>Beim reinen Betrachten der Seite setzen wir überhaupt keine Cookies. Einzig beim Abruf oder Abspielen von Videodateien und bei der Authentifizierung für RWTH- oder Lernraum-interne Videos werden Cookies gesetzt.</p>
......
...@@ -377,6 +377,9 @@ $('#embedcodebtn').popover( ...@@ -377,6 +377,9 @@ $('#embedcodebtn').popover(
{% if permdescription[0] == 'l2p' %} {% if permdescription[0] == 'l2p' %}
{% set permlogos = '<span class="fa" aria-hidden="true" style="width: 12px; height: 14px; background-size: cover; background-image: url(\'/static/l2p-logo.gif\');"></span>' %} {% set permlogos = '<span class="fa" aria-hidden="true" style="width: 12px; height: 14px; background-size: cover; background-image: url(\'/static/l2p-logo.gif\');"></span>' %}
{% endif %} {% endif %}
{% if permdescription[0] == 'moodle' %}
{% set permlogos = '<span class="fa" aria-hidden="true" style="width: 12px; height: 14px; background-size: cover; background-image: url(\'/static/moodle.png\');"></span>' %}
{% endif %}
{% if permdescription[0] == 'rwth' %} {% if permdescription[0] == 'rwth' %}
{% set permlogos = '<span class="fa" aria-hidden="true" style="width: 25px; height: 20px; background-size: cover; background-image: url(\'/static/rwth.png\');"></span>' %} {% set permlogos = '<span class="fa" aria-hidden="true" style="width: 25px; height: 20px; background-size: cover; background-image: url(\'/static/rwth.png\');"></span>' %}
{% endif %} {% endif %}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment