diff --git a/l2pauth.py b/l2pauth.py index 3c971e74733e175fbb170811af10685c954b85d0..49448063e1b6a010ba27ffe22d8aa6462bc5ca44 100644 --- a/l2pauth.py +++ b/l2pauth.py @@ -3,12 +3,18 @@ import requests 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/' +MOODLE_BASE = 'https://moped.ecampus.rwth-aachen.de/proxy/api/v2/eLearning/Moodle/' def l2pget(endpoint, token, **args): args['accessToken'] = token r = requests.request('GET', L2P_BASE+endpoint, params=args) 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): args['client_id'] = config['L2P_APIKEY'] r = requests.request('POST', OAUTH_BASE+endpoint, data=args) @@ -23,6 +29,15 @@ def start_l2pauth(): session['oauthscope'] = 'l2p' 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') def start_rwthauth(): if 'L2P_APIKEY' not in config: @@ -42,12 +57,16 @@ def finish_oauth(): if token.get('status') != 'ok': return del session['oauthcode'] - if session['oauthscope'] not in ['l2p', 'rwth']: + if session['oauthscope'] not in ['l2p', 'rwth', 'moodle']: return session['rwthintern'] = True if session['oauthscope'] == 'l2p': session['l2p_courses'] = [] for course in l2pget('viewAllCourseInfo', token['access_token'])['dataSet']: 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'] oauthget('token', refresh_token=token['refresh_token'], grant_type='invalidate') diff --git a/server.py b/server.py index 4c8ef6970aea90c52774fa160415edd1741f7e59..6e969ee95f51423e13f3a72c5273be5f54d68902 100644 --- a/server.py +++ b/server.py @@ -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') else: 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: 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')) diff --git a/static/moderator.js b/static/moderator.js index 306d1f5e449a857fce89ff846f94d9b8641bbf33..524cc1d0b8e12fa94e2a5d114b934ef2aea2a26a 100644 --- a/static/moderator.js +++ b/static/moderator.js @@ -197,6 +197,9 @@ var moderator = { case 'l2p': permstring = '(' + perm.param1 + ')' 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>'; } @@ -220,6 +223,9 @@ var moderator = { case 'l2p': $(".authl2p", container).val(perm.param1); break + case 'moodle': + $(".authmoodle", container).val(perm.param1); + break } $(".authtype option[value="+perm.type+"]").prop("selected", true); }, @@ -266,6 +272,9 @@ var moderator = { case 'l2p': perm.param1 = $(".authl2p", container).val(); break + case 'moodle': + perm.param1 = $(".authmoodle", container).val(); + break } return perm; }, @@ -277,18 +286,27 @@ var moderator = { $(".authuser", container).val(''); $(".authpassword", container).val(''); $(".authl2p", container).val(''); + $(".authmoodle", container).val(''); switch (type) { case 'password': $(".passwordinput",container).show(); $(".authl2p",container).hide(); + $(".authmoodle",container).hide(); break; case 'l2p': $(".passwordinput",container).hide(); $(".authl2p",container).show(); + $(".authmoodle",container).hide(); + break; + case 'moodle': + $(".passwordinput",container).hide(); + $(".authl2p",container).hide(); + $(".authmoodle",container).show(); break; default: $(".passwordinput",container).hide(); $(".authl2p",container).hide(); + $(".authmoodle",container).hide(); break; } }, diff --git a/static/moodle.png b/static/moodle.png new file mode 100644 index 0000000000000000000000000000000000000000..29ac72931fcf4950b9365bd82ece1cc9025f0e71 Binary files /dev/null and b/static/moodle.png differ diff --git a/template_helper.py b/template_helper.py index 2effb5934f1a06051a1a5cc6b8664a39a00ac9ee..cece6949d9d5d0877e9d2bc088c7fcc2963ff7bd 100644 --- a/template_helper.py +++ b/template_helper.py @@ -91,6 +91,9 @@ def checkperm(perms, username=None, password=None): elif perm['type'] == 'l2p': if perm['param1'] in session.get('l2p_courses', []): return True + elif perm['type'] == 'moodle': + if perm['param1'] in session.get('moodle_courses', []): + return True elif perm['type'] == 'rwth': if session.get('rwthintern', False): return True @@ -108,6 +111,7 @@ def permdescr(perms): public = False password = False l2p_courses = [] + moodle_courses = [] rwth_intern = False fsmpi_intern = False for perm in perms: @@ -117,6 +121,8 @@ def permdescr(perms): password = True elif perm['type'] == 'l2p': l2p_courses.append(perm['param1']) + elif perm['type'] == 'moodle': + moodle_courses.append(perm['param1']) elif perm['type'] == 'rwth': rwth_intern = True elif perm['type'] == 'fsmpi': @@ -133,6 +139,10 @@ def permdescr(perms): if password: return 'l2p', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort 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: return 'password', 'Nur für Nutzer mit Passwort verfügbar' return 'none', 'Nicht verfügbar' diff --git a/templates/course.html b/templates/course.html index 2bd5d92bda3bba7be108690a0d1f082d43148142..a43010e919e27ca53be5c266076f7578890bc45d 100644 --- a/templates/course.html +++ b/templates/course.html @@ -126,12 +126,14 @@ <option value="rwth">RWTH intern</option> <option value="fsmpi">FSMPI intern</option> <option value="l2p">L2P Lernraum</option> + <option value="moodle">Moodle Lernraum</option> <option value="none">Kein Zugriff</option> </select> <input class="col-xs-12 passwordinput authuser" type="text" placeholder="Benutzername"> <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> <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.updatebtnclick(this)">Update</button> <button class="col-xs-4" onclick="moderator.permissioneditor.delbtnclick(this)">Delete</button> diff --git a/templates/faq.html b/templates/faq.html index 698b8fbc3def7eaaba3d4af3f58df96a7729e423..7e2e5d6515be6f5b7e5d1f701dda363f382d2dde 100644 --- a/templates/faq.html +++ b/templates/faq.html @@ -53,7 +53,7 @@ <ul> <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>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> </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> @@ -66,15 +66,15 @@ {% endcall %} <div class="faqHeader">Technisches</div> - {% call faqentry("l2prights", "Warum benötigt ihr lesenden und schreibenden Zugriff auf meine L2P-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. - Um dies umzusetzen benötigen wir die Liste der Lernräume eines Nutzers, und damit Zugriff auf den L2P-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> + {% 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- 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- oder Moodle-Account. + 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. 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. </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 %} {% 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> diff --git a/templates/macros.html b/templates/macros.html index 786fb87a087e6805c83a9affe5069adfdf6a344b..999df29ef9e854fd7d1ab399f1e9ed1bb010e1a6 100644 --- a/templates/macros.html +++ b/templates/macros.html @@ -377,6 +377,9 @@ $('#embedcodebtn').popover( {% 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>' %} {% 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' %} {% set permlogos = '<span class="fa" aria-hidden="true" style="width: 25px; height: 20px; background-size: cover; background-image: url(\'/static/rwth.png\');"></span>' %} {% endif %}