diff --git a/config.py.example b/config.py.example index 6dc234e3c34afdfbf50fb23bea26e140ee158129..186b638439da3da382799862eb27ab9d449e4038 100644 --- a/config.py.example +++ b/config.py.example @@ -25,6 +25,7 @@ SQLITE_INIT_DATA = True #LDAP_HOST = 'rumo.fsmpi.rwth-aachen.de' LDAP_PORT = 636 +LDAP_GROUPS = ['users'] #ICAL_URL = 'https://user:password@mail.fsmpi.rwth-aachen.de/SOGo/....ics' ERROR_PAGE = 'static/500.html' RWTH_IP_RANGES = ['134.130.0.0/16', '137.226.0.0/16', '134.61.0.0/16', '192.35.229.0/24', '2a00:8a60::/32'] diff --git a/db.py b/db.py index a4cac848bd6421e307d0b408f1039191a03b4a70..866d3d1d77e280931912085d680c9f39954a6c39 100644 --- a/db.py +++ b/db.py @@ -152,24 +152,14 @@ if 'LDAP_HOST' in config: def ldapauth(user, password): user = LDAP_USERRE.sub(r'', user.lower()) try: - conn = ldap3.Connection(ldap3.Server(config['LDAP_HOST'], port=config['LDAP_PORT'], use_ssl=True), 'uid=%s,ou=users,dc=fsmpi,dc=rwth-aachen,dc=de'%user, password, auto_bind=True) - groups = [] - if conn.search("ou=groups,dc=fsmpi,dc=rwth-aachen,dc=de", "(&(cn=*)(memberUid=%s))"%user, attributes=['cn']): - groups = [e['attributes']['cn'][0] for e in conn.response] - conn.unbind() - return user, groups - except ldap3.core.exceptions.LDAPExceptionError: - return None, [] - - def ldapget(user): - user = LDAP_USERRE.sub(r'', user.lower()) - conn = ldap3.Connection(ldap3.Server(config['LDAP_HOST'], port=config['LDAP_PORT'], use_ssl=True), auto_bind=True) - conn.search("ou=users,dc=fsmpi,dc=rwth-aachen,dc=de", "(uid=%s)"%user, - attributes=ldap3.ALL_ATTRIBUTES) - if not conn.response: - return {} - e = conn.response[0] - return {'uid': user, 'givenName': e['attributes']['givenName'][0], 'sn':e['attributes']['sn'][0]} + conn = ldap3.Connection(ldap3.Server(config['LDAP_HOST'], port=config['LDAP_PORT'], use_ssl=True), 'fsmpi\\%s'%user, password, auto_bind=True, check_names=False) + except ldap3.core.exceptions.LDAPBindError: + return {}, [] + conn.search("cn=users,dc=fsmpi,dc=rwth-aachen,dc=de", "(cn=%s)"%user, attributes=['memberOf', 'givenName', 'sn']) + info = {'uid': user, 'givenName': conn.response[0]['attributes']['givenName'][0], 'sn': conn.response[0]['attributes']['sn'][0]} + groups = [g.split(',')[0].split('=')[-1] for g in conn.response[0]['attributes']['memberOf']] + conn.unbind() + return info, groups else: notldap = { @@ -180,9 +170,5 @@ else: def ldapauth(user, password): user = LDAP_USERRE.sub(r'', user.lower()) if config.get('DEBUG') and user in notldap and password == notldap[user][0]: - return user, notldap[user][1] - return None, [] - - def ldapget(user): - user = LDAP_USERRE.sub(r'', user.lower()) - return notldap[user][2] + return notldap[user][2], notldap[user][1] + return {}, [] diff --git a/icalexport.py b/icalexport.py index 9f360f623d721b65e5e8fd857d60309efa95e73a..8ab175842f0ccc80c3464213a34ff817aeb88027 100644 --- a/icalexport.py +++ b/icalexport.py @@ -7,28 +7,24 @@ def export_lectures(lectures, name): cal = icalendar.Calendar() cal.add('prodid', '-//Video AG//rwth.video//') cal.add('version', '1.0') - - courses = {}; for l in lectures: event = icalendar.Event() - if not l['course_id'] in courses: - courses[l['course_id']] = query('SELECT * from courses WHERE id = ?',l['course_id'])[0] - c = courses[l['course_id']] - - event.add('summary', c['short']+' : '+l['title']) - event.add('description', l['internal']) - event.add('uid', 'lecture_'+str(l['id'])+'@rwth.video') - event.add('comment', l['comment']) + event.add('summary', l['course']['short']+': '+l['title']) + event.add('description', '\n\n'.join([s for s in [ + l['comment'], + l['internal'], + 'Zuständig: '+l['course']['responsible'] if l['course']['responsible'] else '' + ] if s])) + event.add('uid', '%i@rwth.video'%l['id']) event.add('dtstamp', datetime.utcnow()) - event.add('categories', c['short']) + event.add('categories', l['course']['short']) event.add('dtstart', l['time']) event.add('location', l['place']) event.add('dtend', l['time'] + timedelta(minutes=l['duration'])) cal.add_component(event) - - H = Headers() - H.add_header("Content-Disposition", "inline", filename=name) - return Response(cal.to_ical(), mimetype="text/calendar", headers=H) + h = Headers() + h.add_header("Content-Disposition", "inline", filename=name) + return Response(cal.to_ical(), mimetype="text/calendar", headers=h) def calperm(func): @wraps(func) @@ -46,21 +42,16 @@ def calperm(func): return redirect(url_for('index')) return decorator -@app.route('/internal/ical/semester/<semester>') -@calperm -def ical_semester(semester): - if semester == 'zeitlos': - semester_q = '' - else: - semester_q = semester - return export_lectures(query('SELECT lectures.* FROM lectures JOIN courses ON courses.id = lectures.course_id WHERE courses.semester = ? AND lectures.visible = 1', semester_q),'videoag_semester_'+semester+'.ics') - @app.route('/internal/ical/all') @calperm def ical_all(): - return export_lectures(query('SELECT lectures.* FROM lectures WHERE lectures.visible = 1'),'videoag_all.ics') + return export_lectures(query('''SELECT lectures.*, "course" AS sep, courses.* + FROM lectures JOIN courses ON courses.id = lectures.course_id + WHERE NOT norecording AND NOT external ORDER BY time DESC LIMIT 1000'''),'videoag_all.ics') @app.route('/internal/ical/course/<course>') @calperm def ical_course(course): - return export_lectures(query('SELECT lectures.* FROM lectures JOIN courses ON courses.id = lectures.course_id WHERE courses.handle = ? AND lectures.visible = 1', course),'videoag_course_'+course+'.ics') + return export_lectures(query('''SELECT lectures.*, "course" AS sep, courses.* + FROM lectures JOIN courses ON courses.id = lectures.course_id + WHERE courses.handle = ? AND NOT norecording AND NOT external ORDER BY time DESC''', course),'videoag_course_'+course+'.ics') diff --git a/server.py b/server.py index 860e9699c7aa99e88f8ed93f99e006a0431c4954..1631071f941a81499b1444d25fe8ccda7d9f8d9f 100644 --- a/server.py +++ b/server.py @@ -72,7 +72,7 @@ app.jinja_env.globals['gitversion'] = { 'hash': output[1], 'longhash': output[0] if not config.get('SECRET_KEY', None): config['SECRET_KEY'] = os.urandom(24) -from db import query, modify, show, searchquery, ldapauth, ldapget +from db import query, modify, show, searchquery, ldapauth mod_endpoints = [] @@ -502,17 +502,23 @@ def search(): return render_template('search.html', searchtext=request.args['q'], courses=courses, lectures=lectures) def check_mod(user, groups): - return user and 'users' in groups + if not user: + return False + for group in config['LDAP_GROUPS']: + if group in groups: + return True + return False @app.route('/internal/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html') - user, groups = ldapauth(request.form.get('user'), request.form.get('password')) + userinfo, groups = ldapauth(request.form.get('user'), request.form.get('password')) + user = userinfo.get('uid') if not check_mod(user, groups): flash('Login fehlgeschlagen!') return render_template('login.html') - session['user'] = ldapget(user) + session['user'] = userinfo dbuser = query('SELECT * FROM users WHERE name = ?', user) if not dbuser: modify('INSERT INTO users (name, realname, fsacc, level, calendar_key, rfc6238) VALUES (?, ?, ?, 1, "", "")', user, session['user']['givenName'], user) diff --git a/static/style.css b/static/style.css index 870481be8d90ca6103f983ccc4c05f8197dc46c1..d7b4089a70c19f615ef90f4666da3e88ba0ca501 100644 --- a/static/style.css +++ b/static/style.css @@ -74,6 +74,10 @@ } } +.footer { + z-index: 100; +} + .plot-view { height: 600px; } diff --git a/templates/macros.html b/templates/macros.html index 0c87bac504b0d0ac2b792a8206679fec194c28aa..432956f9b084bcbe18b77d9f269b4622873a6b1b 100644 --- a/templates/macros.html +++ b/templates/macros.html @@ -52,7 +52,6 @@ <video id="videoplayer" style="width: 100%" class="video-js vjs-default-skin vjs-big-play-centered" width="640" height="320" controls data-wasnotplayed="1" data-setup='{ "language":"de", "plugins" : {"hotkeys": {"seekStep": 15, "enableVolumeScroll": false, "alwaysCaptureHotkeys": true}, "videoJsResolutionSwitcher": { "ui": true, "default": "720p", "dynamicLabel": false } }, "customControlsOnMobile": true, "playbackRates": [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4] }'> {% for v in videos|sort(attribute='formats.player_prio', reverse=True) %} <source type="{{ v.formats.mimetype }}" src="{{ config.VIDEOPREFIX }}/{{ v.path }}" data-label="{{ v.formats.description }}" data-res="{{v.formats.resolution}}" data-aspect="{{v.formats.aspect}}" data-player_prio="{{v.formats.player_prio}}"/> - {{ v|safe }} {% endfor %} <track srclang="de" kind="chapters" src="{{ url_for('chapters',lectureid=lecture.id) }}" /> </video>