Skip to content
Snippets Groups Projects
Commit a49329a9 authored by Andreas Valder's avatar Andreas Valder
Browse files

Merge branch 'master' of git.fsmpi.rwth-aachen.de:julianundandyfrickelnkram/videoagwebsite

parents e36154b5 d5189334
Branches
No related tags found
No related merge requests found
from server import * from server import *
import sqlite3 import sqlite3
import re import re
import datetime
if config['DB_ENGINE'] == 'sqlite': if config['DB_ENGINE'] == 'sqlite':
created = not os.path.exists(config['SQLITE_DB']) created = not os.path.exists(config['SQLITE_DB'])
...@@ -23,6 +24,25 @@ def dict_factory(cursor, row): ...@@ -23,6 +24,25 @@ def dict_factory(cursor, row):
d[col[0].split('.')[-1]] = row[idx] d[col[0].split('.')[-1]] = row[idx]
return d return d
# From sqlite3 module, but with error catching
def sqlite_convert_timestamp(val):
try:
datepart, timepart = val.split(b" ")
year, month, day = map(int, datepart.split(b"-"))
timepart_full = timepart.split(b".")
hours, minutes, seconds = map(int, timepart_full[0].split(b":"))
if len(timepart_full) == 2:
microseconds = int('{:0<6.6}'.format(timepart_full[1].decode()))
else:
microseconds = 0
val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
except:
val = None
return val
sqlite3.register_converter('datetime', sqlite_convert_timestamp)
sqlite3.register_converter('timestamp', sqlite_convert_timestamp)
def query(operation, *params): def query(operation, *params):
if config['DB_ENGINE'] == 'mysql': if config['DB_ENGINE'] == 'mysql':
import mysql.connector import mysql.connector
...@@ -33,7 +53,7 @@ def query(operation, *params): ...@@ -33,7 +53,7 @@ def query(operation, *params):
request.db.execute(operation.replace('?', '%s'), params) request.db.execute(operation.replace('?', '%s'), params)
elif config['DB_ENGINE'] == 'sqlite': elif config['DB_ENGINE'] == 'sqlite':
if 'db' not in g: if 'db' not in g:
g.db = sqlite3.connect(config['SQLITE_DB']) g.db = sqlite3.connect(config['SQLITE_DB'], detect_types=sqlite3.PARSE_DECLTYPES)
g.db.row_factory = dict_factory g.db.row_factory = dict_factory
g.db.isolation_level = None g.db.isolation_level = None
if not hasattr(request, 'db'): if not hasattr(request, 'db'):
...@@ -99,6 +119,8 @@ def ldapget(user): ...@@ -99,6 +119,8 @@ def ldapget(user):
conn = ldap3.Connection('ldaps://rumo.fsmpi.rwth-aachen.de', auto_bind=True) conn = ldap3.Connection('ldaps://rumo.fsmpi.rwth-aachen.de', auto_bind=True)
conn.search("ou=users,dc=fsmpi,dc=rwth-aachen,dc=de", "(uid=%s)"%user, conn.search("ou=users,dc=fsmpi,dc=rwth-aachen,dc=de", "(uid=%s)"%user,
attributes=ldap3.ALL_ATTRIBUTES) attributes=ldap3.ALL_ATTRIBUTES)
if not conn.entries:
return {}
e = conn.entries[0] e = conn.entries[0]
return {'uid': user, 'givenName': e.givenName.value, 'sn':e.sn.value} return {'uid': user, 'givenName': e.givenName.value, 'sn':e.sn.value}
else: else:
......
#!/bin/python #!/bin/python
from flask import Flask, g, request, url_for, redirect, session, render_template, flash from flask import Flask, g, request, url_for, redirect, session, render_template, flash
from werkzeug.routing import Rule
from functools import wraps from functools import wraps
from datetime import date, timedelta, datetime, time from datetime import date, timedelta, datetime, time
import threading
import os import os
app = Flask(__name__) app = Flask(__name__)
def timer_func():
with app.test_request_context():
pass # do something
timer = threading.Timer(60*60, timer_func)
timer.start()
timer = threading.Timer(0, timer_func)
timer.daemon = True
timer.start()
config = app.config config = app.config
config['DB_SCHEMA'] = 'db_schema.sql' config['DB_SCHEMA'] = 'db_schema.sql'
config['DB_DATA'] = 'db_example.sql' config['DB_DATA'] = 'db_example.sql'
...@@ -22,14 +34,12 @@ config.from_pyfile('config.py', silent=True) ...@@ -22,14 +34,12 @@ config.from_pyfile('config.py', silent=True)
from db import query, searchquery, ldapauth, ldapget from db import query, searchquery, ldapauth, ldapget
app.jinja_env.globals['videoprefix'] = config['VIDEOPREFIX']
mod_endpoints = [] mod_endpoints = []
@app.template_global()
def ismod(*args): def ismod(*args):
return ('user' in session) return ('user' in session)
app.jinja_env.globals['ismod'] = ismod
def mod_required(func): def mod_required(func):
mod_endpoints.append(func.__name__) mod_endpoints.append(func.__name__)
@wraps(func) @wraps(func)
...@@ -50,6 +60,28 @@ def register_navbar(name, icon=None): ...@@ -50,6 +60,28 @@ def register_navbar(name, icon=None):
return func return func
return wrapper return wrapper
def render_endpoint(endpoint, flashtext=None, **kargs):
if flashtext:
flash(flashtext)
# request.endpoint is used for navbar highlighting
request.url_rule = Rule(request.path, endpoint=endpoint)
return app.view_functions[endpoint](**kargs)
def handle_errors(endpoint, text, code, *errors, **epargs):
def wrapper(func):
@wraps(func)
def decorator(*args, **kwargs):
try:
return func(*args, **kwargs)
except errors:
return render_endpoint(endpoint, text, **epargs), code
return decorator
return wrapper
@app.errorhandler(404)
def handle_not_found(e):
return render_endpoint('index', 'Diese Seite existiert nicht!'), 404
@app.route('/') @app.route('/')
@register_navbar('Home', icon='home') @register_navbar('Home', icon='home')
def index(): def index():
...@@ -77,11 +109,13 @@ def course(): ...@@ -77,11 +109,13 @@ def course():
return render_template('course.html', courses=courses, groupedby=groupedby) return render_template('course.html', courses=courses, groupedby=groupedby)
@app.route('/course/<id>') @app.route('/course/<id>')
def course_id(id): @app.route('/course/<int:numid>')
courses = query('SELECT * FROM courses WHERE ((handle = ?) or id = ?) AND (? OR visible)', id, id, ismod()) @handle_errors('course', 'Diese Veranstaltung existiert nicht!', 404, IndexError)
if not courses: def course_id(numid=None, id=None):
flash('Diese Veranstaltung existiert nicht!') if numid:
return app.view_functions['course'](), 404 courses = query('SELECT * FROM courses WHERE id = ? AND (? OR visible)', numid, ismod())
else:
courses = query('SELECT * FROM courses WHERE handle = ? AND (? OR visible)', id, ismod())
lectures = query('SELECT * FROM lectures WHERE course_id = ? AND (? OR visible)', courses[0]['id'], ismod()) lectures = query('SELECT * FROM lectures WHERE course_id = ? AND (? OR visible)', courses[0]['id'], ismod())
videos = query(''' videos = query('''
SELECT videos.*, (videos.downloadable AND courses.downloadable) as downloadable, formats.description AS format_description SELECT videos.*, (videos.downloadable AND courses.downloadable) as downloadable, formats.description AS format_description
...@@ -100,18 +134,15 @@ def faq(): ...@@ -100,18 +134,15 @@ def faq():
return render_template('faq.html') return render_template('faq.html')
@app.route('/play/<int:id>') @app.route('/play/<int:id>')
@handle_errors('course', 'Diese Vorlesung existiert nicht!', 404, IndexError)
def play(id): def play(id):
lectures = query('SELECT * FROM lectures WHERE id = ? AND (? OR visible)', id, ismod()) lectures = query('SELECT * FROM lectures WHERE id = ? AND (? OR visible)', id, ismod())
videos = query('SELECT * FROM videos WHERE lecture_id = ? AND (? OR visible)', id, ismod()) videos = query('SELECT * FROM videos WHERE lecture_id = ? AND (? OR visible)', id, ismod())
if not lectures:
flash('Diese Vorlesung existiert nicht!')
return app.view_functions['course'](), 404
if not videos: if not videos:
flash('Zu dieser Vorlesung wurden noch keine Videos veröffentlicht!') flash('Zu dieser Vorlesung wurden noch keine Videos veröffentlicht!')
courses = query('SELECT * FROM courses WHERE id = ? AND (? OR (visible AND listed))', lectures[0]['course_id'], ismod()) courses = query('SELECT * FROM courses WHERE id = ? AND (? OR (visible AND listed))', lectures[0]['course_id'], ismod())
if not courses: if not courses:
flash('Diese Veranstaltung existiert nicht!') return render_endpoint('course', 'Diese Veranstaltung existiert nicht!'), 404
return app.view_functions['course'](), 404
return render_template('play.html', course=courses[0], lecture=lectures[0], videos=videos) return render_template('play.html', course=courses[0], lecture=lectures[0], videos=videos)
@app.route('/search') @app.route('/search')
...@@ -132,10 +163,15 @@ def login(): ...@@ -132,10 +163,15 @@ def login():
if request.method == 'GET': if request.method == 'GET':
return render_template('login.html') return render_template('login.html')
user, groups = ldapauth(request.form.get('user'), request.form.get('password')) user, groups = ldapauth(request.form.get('user'), request.form.get('password'))
if user and 'users' in groups: if not user or not 'users' in groups:
session['user'] = ldapget(user)
else:
flash('Login fehlgeschlagen!') flash('Login fehlgeschlagen!')
return render_template('login.html')
session['user'] = ldapget(user)
dbuser = query('SELECT * FROM users WHERE name = ?', user)
if not dbuser:
query('INSERT INTO users (name, realname, fsacc, level, calendar_key, rfc6238) VALUES (?, ?, ?, 1, "", "")', user, session['user']['givenName'], user)
dbuser = query('SELECT * FROM users WHERE name = ?', user)
session['user']['dbid'] = dbuser[0]['id']
return redirect(request.values.get('ref', url_for('index'))) return redirect(request.values.get('ref', url_for('index')))
@app.route('/logout', methods=['GET', 'POST']) @app.route('/logout', methods=['GET', 'POST'])
...@@ -165,8 +201,7 @@ def edit(): ...@@ -165,8 +201,7 @@ def edit():
assert table in tabs assert table in tabs
assert column in tabs[table][2] assert column in tabs[table][2]
query('INSERT INTO changelog ("table",id_value,id_key,field,value_new,value_old,"when",who,executed) VALUES (?,?,?,?,?,(SELECT %s FROM %s WHERE %s = ?),?,?,1)'%(column,tabs[table][0],tabs[table][1]),table,id,tabs[table][1],column,val,id,datetime.now(),session['user']['givenName']) query('INSERT INTO changelog ("table",id_value,id_key,field,value_new,value_old,"when",who,executed) VALUES (?,?,?,?,?,(SELECT %s FROM %s WHERE %s = ?),?,?,1)'%(column,tabs[table][0],tabs[table][1]),table,id,tabs[table][1],column,val,id,datetime.now(),session['user']['givenName'])
query('UPDATE %s SET %s = ? WHERE %s = ?'%(tabs[table][0], column, query('UPDATE %s SET %s = ? WHERE %s = ?'%(tabs[table][0], column,tabs[table][1]), val, id)
tabs[table][1]), val, id)
query('COMMIT') query('COMMIT')
return "OK", 200 return "OK", 200
...@@ -224,10 +259,9 @@ def schedule(): ...@@ -224,10 +259,9 @@ def schedule():
curcol=0; curcol=0;
freecol=[]; freecol=[];
for l in i['lectures']: for l in i['lectures']:
l['time_asdate'] = datetime.strptime(l['time'],'%Y-%m-%d %H:%M:%S')
# who the hell inserts lectures with zero length?!?!? # who the hell inserts lectures with zero length?!?!?
l['end_asdate'] = l['time_asdate']+timedelta(minutes=max(l['duration'],1)) l['time_end'] = l['time']+timedelta(minutes=max(l['duration'],1))
for l in sorted([(l['time_asdate'],True,l) for l in i['lectures']] + [(l['end_asdate'],False,l) for l in i['lectures']],key=lambda t:(t[0],t[1])): for l in sorted([(l['time'],True,l) for l in i['lectures']] + [(l['time_end'],False,l) for l in i['lectures']],key=lambda t:(t[0],t[1])):
if l[1]: if l[1]:
curcol += 1 curcol += 1
if curcol > maxcol: if curcol > maxcol:
...@@ -262,4 +296,5 @@ def stats(): ...@@ -262,4 +296,5 @@ def stats():
@register_navbar('Changelog', 'book') @register_navbar('Changelog', 'book')
@mod_required @mod_required
def log(): def log():
return render_template('log.html', changelog=query('SELECT *, ( "table" || "." || id_value || "." ||field) as path FROM changelog ORDER BY "when" DESC LIMIT 50')) changelog = query('SELECT *, ( "table" || "." || id_value || "." ||field) as path FROM changelog LEFT JOIN users ON (changelog.who = users.id) ORDER BY "when" DESC LIMIT 50')
return render_template('log.html', changelog=changelog)
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
{% for endpoint, caption, gly, visible in navbar %} {% for endpoint, caption, gly, visible in navbar %}
{% if visible or ismod() %} {% if visible or ismod() %}
<li{% if endpoint == request.endpoint %} class="active"{% endif %}> <li{% if endpoint == request.endpoint %} class="active"{% endif %}>
<a href="{{ url_for(endpoint)|e }}">{% if gly != '' %}<span class="glyphicon glyphicon-{{ gly }}"></span> {% endif %}{{ caption }}</a> <a href="{{ url_for(endpoint) }}">{% if gly != '' %}<span class="glyphicon glyphicon-{{ gly }}"></span> {% endif %}{{ caption }}</a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
...@@ -63,12 +63,12 @@ ...@@ -63,12 +63,12 @@
{ {
html:true, html:true,
title:'Login für Moderatoren', title:'Login für Moderatoren',
content:'<form method="post" action="{{url_for('login')}}"><input placeholder="User" name="user" type="text"><br><input placeholder="Password" name="password" type="password"><br><input type="hidden" name="ref" value="{{ request.url|e }}"><input type="submit" value="Login"></form>' content:'<form method="post" action="{{url_for('login', ref=request.url)}}"><input placeholder="User" name="user" type="text"><br><input placeholder="Password" name="password" type="password"><br><input type="submit" value="Login"></form>'
} }
) )
</script> </script>
{% else %} {% else %}
<a href="{{url_for('logout')}}?ref={{ request.url|urlencode }}"> <a href="{{url_for('logout', ref=request.url)}}">
{{ session.user.givenName }} {{ session.user.givenName }}
<span class="glyphicon glyphicon-log-out"></span> <span class="glyphicon glyphicon-log-out"></span>
</a> </a>
......
...@@ -19,7 +19,11 @@ ...@@ -19,7 +19,11 @@
{% for i in changelog %} {% for i in changelog %}
<tr> <tr>
<td>{{i.when}}</td> <td>{{i.when}}</td>
{% if i.realname %}
<td>{{i.realname}} ({{i.who}})</td>
{% else %}
<td>{{i.who}}</td> <td>{{i.who}}</td>
{% endif %}
<td>{{i.path}}</td> <td>{{i.path}}</td>
<td>"{{i.value_old}}"</td> <td>"{{i.value_old}}"</td>
<td>"{{i.value_new}}"</td> <td>"{{i.value_new}}"</td>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<li class="list-group-item"> <li class="list-group-item">
<a class="hidden-xs" href="{{url_for('play', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}"> <a class="hidden-xs" href="{{url_for('play', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}">
<div class="row"> <div class="row">
<img class="col-xs-4" src="{{ videoprefix }}/{{ lecture['titlefile'] }}" alt="Vorschaubild"> <img class="col-xs-4" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild">
<div class="col-xs-4"> <div class="col-xs-4">
<span style="color: #000;"><strong>{{ lecture['short'] }}</strong></span><br> <span style="color: #000;"><strong>{{ lecture['short'] }}</strong></span><br>
<span style="color: #000;">{{ lecture['time'] }}</span> <span style="color: #000;">{{ lecture['time'] }}</span>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</a> </a>
<a class="visible-xs" href="{{url_for('play', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}"> <a class="visible-xs" href="{{url_for('play', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}">
<div class="row"> <div class="row">
<img class="col-xs-12" src="{{ videoprefix }}/{{ lecture['titlefile'] }}" alt="Vorschaubild"> <img class="col-xs-12" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild">
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
<link rel="stylesheet" href="{{url_for('static', filename='mediaelementjs/mediaelementplayer.css')}}" /> <link rel="stylesheet" href="{{url_for('static', filename='mediaelementjs/mediaelementplayer.css')}}" />
<video class="mejs-player" width="640" height="360" style="width: 100%; height: 100%;"> <video class="mejs-player" width="640" height="360" style="width: 100%; height: 100%;">
{% for v in videos %} {% for v in videos %}
<source type="video/mp4" src="{{ videoprefix }}/{{ v.path }}" /> <source type="video/mp4" src="{{ config.VIDEOPREFIX }}/{{ v.path }}" />
{% endfor %} {% endfor %}
</video> </video>
<script> <script>
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
{% macro course_list_item(course,show_semester=False) %} {% macro course_list_item(course,show_semester=False) %}
<li class="list-group-item {% if (not course.visible) or (not course.listed) %}list-group-item-danger{% endif %}"> <li class="list-group-item {% if (not course.visible) or (not course.listed) %}list-group-item-danger{% endif %}">
<div class="row"> <div class="row">
<a href="{{url_for('course_id', id=course.handle)}}"> <a href="{{url_for('course_id', numid=course.id)}}">
{% if show_semester %} {% if show_semester %}
<span class="col-xs-1"> <span class="col-xs-1">
{{ course.semester }} {{ course.semester }}
...@@ -93,13 +93,13 @@ ...@@ -93,13 +93,13 @@
<button class="btn btn-primary dropdown-toggle {% if videos|length is equalto 0 %}disabled{% endif %}" type="button" data-toggle="dropdown">Download <span class="caret"></span></button> <button class="btn btn-primary dropdown-toggle {% if videos|length is equalto 0 %}disabled{% endif %}" type="button" data-toggle="dropdown">Download <span class="caret"></span></button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% for v in videos %} {% for v in videos %}
{% if v.downloadable %} <li><a href="{{ videoprefix }}/{{v.path}}">{{ valuecheckbox(['videos',v.id,'visible'], v.visible) }} {{v.format_description}} ({{v.file_size|filesizeformat(true)}})</a></li>{% endif %} {% if v.downloadable %} <li><a href="{{ config.VIDEOPREFIX }}/{{v.path}}">{{ valuecheckbox(['videos',v.id,'visible'], v.visible) }} {{v.format_description}} ({{v.file_size|filesizeformat(true)}})</a></li>{% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
<noscript> <noscript>
<ul class="pull-right list-unstyled" style="margin-left:10px;"> <ul class="pull-right list-unstyled" style="margin-left:10px;">
{% for v in videos %} {% for v in videos %}
<li><a href="{{ videoprefix }}/{{v.path}}">{{v.format_description}} ({{v.file_size|filesizeformat(true)}})</a></li> <li><a href="{{ config.VIDEOPREFIX }}/{{v.path}}">{{v.format_description}} ({{v.file_size|filesizeformat(true)}})</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</noscript> </noscript>
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p class="col-xs-12" style="padding: 0px;"> <p class="col-xs-12" style="padding: 0px;">
<span><a href="{{url_for('course_id', id=course.handle)}}" class="btn btn-default" >Zur Veranstaltungsseite</a><span> <span><a href="{{url_for('course_id', numid=course.id)}}#lecture-{{lecture.id}}" class="btn btn-default" >Zur Veranstaltungsseite</a><span>
<span class="pull-right"> <span class="pull-right">
<span>{{ video_embed_btn(lecture.id) }}</span> <span>{{ video_embed_btn(lecture.id) }}</span>
<span>{{ video_download_btn(videos) }}</span> <span>{{ video_download_btn(videos) }}</span>
......
...@@ -21,15 +21,15 @@ ...@@ -21,15 +21,15 @@
{% if ((loop.index - 1) is divisibleby 4) %} <td rowspan="4" style="vertical-align: top;">{{ t.strftime("%H:%M") }}</td> {% endif %} {% if ((loop.index - 1) is divisibleby 4) %} <td rowspan="4" style="vertical-align: top;">{{ t.strftime("%H:%M") }}</td> {% endif %}
{% for d in days if (d.index < 5) or (d.lectures|length) > 0 %} {% for d in days if (d.index < 5) or (d.lectures|length) > 0 %}
{% for i in range(1,d.maxcol+1) %} {% for i in range(1,d.maxcol+1) %}
{% for l in d.lectures|selectattr('schedule_col','equalto',i) if (((l.time_asdate.time() > t) and (l.time_asdate.time() < times[time_loop.index+1])) != (l.time_asdate.time() == t ) ) %} {% for l in d.lectures|selectattr('schedule_col','equalto',i) if (((l.time.time() > t) and (l.time.time() < times[time_loop.index+1])) != (l.time.time() == t ) ) %}
<td rowspan="{{l.duration / 15}}" style="background: lightgrey;"> <td rowspan="{{l.duration / 15}}" style="background: lightgrey;">
<p class="small"> <p class="small">
<strong><a href="{{url_for('course_id', id=l['course_id'])}}#lecture-{{l.id}}">{{l.short}}</a></strong><br> <strong><a href="{{url_for('course_id', numid=l['course_id'])}}#lecture-{{l.id}}">{{l.short}}</a></strong><br>
{{l.time_asdate.strftime("%H:%M")}} - {{l.end_asdate.strftime("%H:%M")}}<br> {{l.time.strftime("%H:%M")}} - {{l.time_end.strftime("%H:%M")}}<br>
{{l.place}}</p> {{l.place}}</p>
</td> </td>
{% else %} {% else %}
{% for l in d.lectures|selectattr('schedule_col','equalto',i) if (l.time_asdate.time() < t) and (l.end_asdate.time() > t) %} {% for l in d.lectures|selectattr('schedule_col','equalto',i) if (l.time.time() < t) and (l.time_end.time() > t) %}
{% else %} {% else %}
<td></td> <td></td>
{% endfor %} {% endfor %}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment