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

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

parents d7de1784 07638a3d
No related branches found
No related tags found
No related merge requests found
# Defaults for development ,do not use in production! # Defaults for development ,do not use in production!
DEBUG = True DEBUG = False
VIDEOPREFIX = 'https://videoag.fsmpi.rwth-aachen.de' VIDEOPREFIX = 'https://videoag.fsmpi.rwth-aachen.de'
VIDEOMOUNT = 'files/' VIDEOMOUNT = 'files/'
#SECRET_KEY = 'something random' #SECRET_KEY = 'something random'
...@@ -16,6 +16,6 @@ DB_DATA = 'db_example.sql' ...@@ -16,6 +16,6 @@ DB_DATA = 'db_example.sql'
DB_ENGINE = 'sqlite' DB_ENGINE = 'sqlite'
SQLITE_DB = 'db.sqlite' SQLITE_DB = 'db.sqlite'
SQLITE_INIT_SCHEMA = True SQLITE_INIT_SCHEMA = True
SQLITE_INIT_DATA = True SQLITE_INIT_DATA = False
#LDAP_HOST = 'ldaps://rumo.fsmpi.rwth-aachen.de' #LDAP_HOST = 'ldaps://rumo.fsmpi.rwth-aachen.de'
...@@ -42,26 +42,26 @@ CREATE TABLE IF NOT EXISTS `chapters` ( ...@@ -42,26 +42,26 @@ CREATE TABLE IF NOT EXISTS `chapters` (
); );
CREATE TABLE IF NOT EXISTS `courses_data` ( CREATE TABLE IF NOT EXISTS `courses_data` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`visible` INTEGER NOT NULL, `visible` INTEGER NOT NULL DEFAULT '0',
`listed` INTEGER NOT NULL DEFAULT '1', `listed` INTEGER NOT NULL DEFAULT '1',
`deleted` INTEGER NOT NULL DEFAULT '0', `deleted` INTEGER NOT NULL DEFAULT '0',
`title` text NOT NULL, `title` text NOT NULL DEFAULT '',
`short` varchar(32) NOT NULL, `short` varchar(32) NOT NULL DEFAULT '',
`handle` varchar(32) NOT NULL, `handle` varchar(32) NOT NULL DEFAULT '',
`organizer` text NOT NULL, `organizer` text NOT NULL DEFAULT '',
`subject` varchar(32) NOT NULL, `subject` varchar(32) NOT NULL DEFAULT '',
`credits` INTEGER NOT NULL DEFAULT '0', `credits` INTEGER NOT NULL DEFAULT '0',
`created_by` INTEGER DEFAULT NULL, `created_by` INTEGER DEFAULT NULL,
`time_created` datetime NOT NULL, `time_created` datetime NOT NULL,
`time_updated` datetime NOT NULL, `time_updated` datetime NOT NULL,
`semester` char(6) NOT NULL, `semester` char(6) NOT NULL DEFAULT '',
`settings` text NOT NULL, `settings` text NOT NULL DEFAULT '',
`downloadable` INTEGER NOT NULL DEFAULT '1', `downloadable` INTEGER NOT NULL DEFAULT '1',
`embedinvisible` INTEGER NOT NULL DEFAULT '0', `embedinvisible` INTEGER NOT NULL DEFAULT '0',
`description` text NOT NULL, `description` text NOT NULL DEFAULT '',
`internal` text NOT NULL, `internal` text NOT NULL DEFAULT '',
`responsible` text NOT NULL, `responsible` text NOT NULL DEFAULT '',
`feed_url` text NOT NULL `feed_url` text NOT NULL DEFAULT ''
); );
CREATE TABLE IF NOT EXISTS `filesizes` ( CREATE TABLE IF NOT EXISTS `filesizes` (
`path` varchar(255) NOT NULL PRIMARY KEY, `path` varchar(255) NOT NULL PRIMARY KEY,
...@@ -185,18 +185,19 @@ CREATE TABLE IF NOT EXISTS `videos_data` ( ...@@ -185,18 +185,19 @@ CREATE TABLE IF NOT EXISTS `videos_data` (
); );
CREATE TABLE IF NOT EXISTS `announcements` ( CREATE TABLE IF NOT EXISTS `announcements` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`text` text NOT NULL, `text` text NOT NULL DEFAULT '',
`internal` text NOT NULL,
`level` INTEGER NOT NULL DEFAULT 0, `level` INTEGER NOT NULL DEFAULT 0,
`visible` INTEGER NOT NULL DEFAULT 0, `visible` INTEGER NOT NULL DEFAULT 0,
`deleted` INTEGER NOT NULL DEFAULT 0, `deleted` INTEGER NOT NULL DEFAULT 0,
`time_publish` datetime DEFAULT "",
`time_expire` datetime DEFAULT "",
`time_created` datetime NOT NULL, `time_created` datetime NOT NULL,
`time_updated` datetime NOT NULL, `time_updated` datetime NOT NULL,
`created_by` INTEGER NOT NULL `created_by` INTEGER NOT NULL
); );
CREATE TABLE IF NOT EXISTS `featured` ( CREATE TABLE IF NOT EXISTS `featured` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`title` text NOT NULL DEFAULT "Neuer Artikel", `title` text NOT NULL DEFAULT '',
`text` text NOT NULL DEFAULT "", `text` text NOT NULL DEFAULT "",
`internal` text NOT NULL DEFAULT "", `internal` text NOT NULL DEFAULT "",
`visible` INTEGER NOT NULL DEFAULT 0, `visible` INTEGER NOT NULL DEFAULT 0,
......
importer.py 100755 → 100644
File mode changed from 100755 to 100644
schedule.py 100755 → 100644
File mode changed from 100755 to 100644
server.py 100755 → 100644
...@@ -12,6 +12,9 @@ app = Flask(__name__) ...@@ -12,6 +12,9 @@ app = Flask(__name__)
app.jinja_env.trim_blocks = True app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True app.jinja_env.lstrip_blocks = True
app.add_template_global(random.randint, name='randint')
app.add_template_global(datetime, name='datetime')
app.add_template_global(timedelta, name='timedelta')
def timer_func(): def timer_func():
with app.test_request_context(): with app.test_request_context():
...@@ -25,9 +28,9 @@ timer.start() ...@@ -25,9 +28,9 @@ timer.start()
config = app.config config = app.config
config.from_pyfile('config.py.example', silent=True) config.from_pyfile('config.py.example', silent=True)
if not sys.argv[0].endswith('run.py'): if sys.argv[0].endswith('run.py'):
config['SQLITE_INIT_DATA'] = False config['SQLITE_INIT_DATA'] = True
config['DEBUG'] = False config['DEBUG'] = True
config.from_pyfile('config.py', silent=True) config.from_pyfile('config.py', silent=True)
if config['DEBUG']: if config['DEBUG']:
app.jinja_env.auto_reload = True app.jinja_env.auto_reload = True
...@@ -120,7 +123,10 @@ def rfc3339(d): ...@@ -120,7 +123,10 @@ def rfc3339(d):
@app.template_global() @app.template_global()
def get_announcements(minlevel=0): def get_announcements(minlevel=0):
return query('SELECT * FROM announcements WHERE NOT deleted AND (? OR visible) AND level >= ? ORDER BY level DESC', ismod(), minlevel) offset = timedelta()
if ismod():
offset = timedelta(hours=24)
return query('SELECT * FROM announcements WHERE NOT deleted AND (time_expire ISNULL OR time_expire > ?) AND (? OR (visible AND time_publish < ?)) AND level >= ? ORDER BY level DESC', datetime.now()-offset, ismod(), datetime.now(), minlevel)
@app.template_filter() @app.template_filter()
def fixnl(s): def fixnl(s):
...@@ -248,10 +254,6 @@ def logout(): ...@@ -248,10 +254,6 @@ def logout():
session.pop('user') session.pop('user')
return redirect(request.values.get('ref', url_for('index'))) return redirect(request.values.get('ref', url_for('index')))
@app.route('/edit', methods=['GET', 'POST'])
@mod_required
def edit(prefix="", ignore=[]):
# All editable tables are expected to have a 'time_updated' field
tabs = { tabs = {
'courses': ('courses_data', 'id', ['visible', 'listed', 'title', 'short', 'courses': ('courses_data', 'id', ['visible', 'listed', 'title', 'short',
'handle', 'organizer', 'subject', 'semester', 'downloadable', 'handle', 'organizer', 'subject', 'semester', 'downloadable',
...@@ -260,14 +262,24 @@ def edit(prefix="", ignore=[]): ...@@ -260,14 +262,24 @@ def edit(prefix="", ignore=[]):
'internal', 'speaker', 'place', 'time', 'duration', 'jumplist','deleted']), 'internal', 'speaker', 'place', 'time', 'duration', 'jumplist','deleted']),
'videos': ('videos_data', 'id', ['visible','deleted']), 'videos': ('videos_data', 'id', ['visible','deleted']),
'chapters': ('chapters', 'id', ['time', 'text', 'visible', 'deleted']), 'chapters': ('chapters', 'id', ['time', 'text', 'visible', 'deleted']),
'announcements': ('announcements', 'id', ['text', 'internal', 'level', 'visible', 'deleted']), 'announcements': ('announcements', 'id', ['text', 'level', 'visible', 'deleted', 'time_publish', 'time_expire']),
'featured': ('featured', 'id', ['text', 'title', 'visible', 'deleted']) 'featured': ('featured', 'id', ['title', 'text', 'internal', 'visible', 'deleted'])
} }
@app.route('/edit', methods=['GET', 'POST'])
@mod_required
def edit(prefix='', ignore=[]):
# All editable tables are expected to have a 'time_updated' field
ignore.append('ref')
ignore.append('prefix')
if not prefix and 'prefix' in request.args:
prefix = request.args['prefix']
modify('BEGIN') modify('BEGIN')
if request.is_json: if request.is_json:
changes = request.get_json().items() changes = request.get_json().items()
else: else:
changes = request.args.items() changes = request.args.items()
created = {}
for key, val in changes: for key, val in changes:
if key in ignore: if key in ignore:
continue continue
...@@ -275,22 +287,21 @@ def edit(prefix="", ignore=[]): ...@@ -275,22 +287,21 @@ def edit(prefix="", ignore=[]):
table, id, column = key.split('.', 2) table, id, column = key.split('.', 2)
assert table in tabs assert table in tabs
assert column in tabs[table][2] assert column in tabs[table][2]
modify('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']) modify('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']['dbid'])
modify('UPDATE %s SET %s = ?, time_updated = ? WHERE %s = ?'%(tabs[table][0], column, tabs[table][1]), val, datetime.now(), id) modify('UPDATE %s SET %s = ?, time_updated = ? WHERE %s = ?'%(tabs[table][0], column, tabs[table][1]), val, datetime.now(), id)
modify('COMMIT') modify('COMMIT')
if 'ref' in request.values:
return redirect(request.values['ref'])
return "OK", 200 return "OK", 200
@app.route('/newcourse', methods=['GET', 'POST']) @app.route('/new/<table>', methods=['GET', 'POST'])
@mod_required @mod_required
def new_course(): def create(table):
id = modify(''' assert table in tabs
INSERT INTO courses_data id = modify('INSERT INTO %s (created_by, time_created, time_updated) VALUES (?, ?, ?)'%tabs[table][0],
(visible, title, short, handle, organizer, subject, created_by, time_created, session['user']['dbid'], datetime.now(), datetime.now())
time_updated, semester, settings, description, internal, responsible, feed_url) edit(prefix=table+'.'+str(id)+'.')
VALUES (0, "Neue Veranstaltung", "Neu", ?, "", "", ?, ?, ?, "", "", "", "", ?, "")
''', 'new'+str(random.randint(0,1000)), session['user']['dbid'], datetime.now(), datetime.now(),
session['user']['givenName'])
edit(prefix='courses.'+str(id)+'.', ignore=['ref'])
if 'ref' in request.values: if 'ref' in request.values:
return redirect(request.values['ref']) return redirect(request.values['ref'])
return str(id), 200 return str(id), 200
...@@ -361,7 +372,9 @@ def stats(): ...@@ -361,7 +372,9 @@ def stats():
@register_navbar('Changelog', icon='book') @register_navbar('Changelog', icon='book')
@mod_required @mod_required
def changelog(): def changelog():
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') changelog = query('SELECT * FROM changelog LEFT JOIN users ON (changelog.who = users.id) ORDER BY `when` DESC LIMIT 50')
for entry in changelog:
entry['path'] = '.'.join([entry['table'], entry['id_value'], entry['field']])
return render_template('changelog.html', changelog=changelog) return render_template('changelog.html', changelog=changelog)
@app.route('/files/<filename>') @app.route('/files/<filename>')
...@@ -383,24 +396,6 @@ def suggest_chapter(lectureid): ...@@ -383,24 +396,6 @@ def suggest_chapter(lectureid):
return redirect(request.values['ref']) return redirect(request.values['ref'])
return 'OK', 200 return 'OK', 200
@app.route('/newpsa', methods=['POST', 'GET'])
@mod_required
def new_announcement():
id = modify('INSERT INTO announcements (text, internal, time_created, time_updated, created_by) VALUES ("Neue Ankündigung", "", ?, ?, ?)',
datetime.now(), datetime.now(), session.get('user', {'dbid':None})['dbid'])
if 'ref' in request.values:
return redirect(request.values['ref'])
return id, 200
@app.route('/newfeatured', methods=['POST', 'GET'])
@mod_required
def new_featured():
id = modify('INSERT INTO featured (time_created, time_updated, created_by) VALUES (?, ?, ?)',
datetime.now(), datetime.now(), session.get('user', {'dbid':None})['dbid'])
if 'ref' in request.values:
return redirect(request.values['ref'])
return id, 200
@app.route('/sitemap.xml') @app.route('/sitemap.xml')
def sitemap(): def sitemap():
pages=[] pages=[]
......
{% set page_border = page_border|default(1) %} {% set page_border = page_border|default(1) %}
{% set min_announcement_level = min_announcement_level|default(1) %} {% set min_announcement_level = min_announcement_level|default(1) %}
{% set announcement_levels = {0: 'info', 1: 'info', 2: 'warning', 3: 'danger'} %} {% set levels = {0: ('info', 'Nur auf Hauptseite sichtbar'), 1: ('info', 'Überall sichtbar (Hinweis)'), 2: ('warning', 'Überall sichtbar (Warnung)'), 3: ('danger', 'Überall sichtbar (Wichtig)')} %}
{% from 'macros.html' import valueeditor, valuecheckbox, valuedeletebtn %} {% from 'macros.html' import valueeditor, valuecheckbox, valuedeletebtn %}
<!DOCTYPE html> <!DOCTYPE html>
...@@ -100,20 +100,10 @@ ...@@ -100,20 +100,10 @@
{% for msg in get_flashed_messages() %} {% for msg in get_flashed_messages() %}
<div class="alert alert-danger" role="alert">{{ msg }}</div> <div class="alert alert-danger" role="alert">{{ msg }}</div>
{% endfor %} {% endfor %}
{% for msg in get_announcements(min_announcement_level) if (not request.cookies['alert-info-'+msg.id|string]) or ismod() %} {% for msg in get_announcements(min_announcement_level) if (not request.cookies['alert-info-'+msg.id|string]) %}
<div class="alert alert-{{announcement_levels.get(msg.level, 'info')}}" role="alert"> <div class="alert alert-{{levels.get(msg.level, ('info', ''))[0]}}" role="alert">
{% if not ismod() %}
<a href="#" class="close" data-dismiss="alert" aria-label="close" onclick="Cookies.set('alert-info-{{msg.id}}', '1');">&times;</a> <a href="#" class="close" data-dismiss="alert" aria-label="close" onclick="Cookies.set('alert-info-{{msg.id}}', '1');">&times;</a>
{% endif %} {{ msg.text|safe }}
<ul class="list-unstyled">
<li>{{ valueeditor(('announcements',msg.id,'text'), msg.text|safe) }}</li>
<li class="pull-right">{{ valuedeletebtn(('announcements',msg.id,'deleted')) }}</li>
{% if ismod() %}
<li>{{ valueeditor(('announcements',msg.id,'internal'), msg.internal) }}</li>
<li class="pull-right">Sichtbar: {{ valuecheckbox(('announcements',msg.id,'visible'),msg.visible) }}</li>
<li>Level: {{ valueeditor(('announcements',msg.id,'level'), msg.level) }}</li>
{% endif %}
</ul>
</div> </div>
{% endfor %} {% endfor %}
{% block content %} {% block content %}
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
</li> </li>
{% if ismod() %} {% if ismod() %}
<li> <li>
<a class="btn btn-default" href="{{ url_for('new_course', ref=request.url) }}">Neue Veranstaltung</a> <a class="btn btn-default" href="{{ url_for('create', table='courses', handle='new'+(randint(0,1000)|string), title='Neue Veranstaltung', responsible=session.user.givenName, ref=request.url) }}">Neue Veranstaltung</a>
</li> </li>
{% endif %} {% endif %}
<li class="dropdown" style="padding-right: 0px"> <li class="dropdown" style="padding-right: 0px">
......
{% from 'macros.html' import preview %} {% from 'macros.html' import preview %}
{% extends "base.html" %} {% extends "base.html" %}
{% set page_border = 0 %} {% set page_border = 0 %}
{% if ismod() %}
{# Little hack to not show annoucements twice #}
{% set min_announcement_level = 999 %}
{% else %}
{% set min_announcement_level = 0 %} {% set min_announcement_level = 0 %}
{% endif %}
{% block content %} {% block content %}
{% if ismod() %}
<div class="row">
<div class="col-xs-12">
{% for msg in get_announcements() %}
<div class="alert alert-{{levels.get(msg.level, ('info', ''))[0]}}" role="alert">
<ul class="list-unstyled">
<li>{{ valueeditor(('announcements',msg.id,'text'), msg.text|safe) }}</li>
<li class="pull-right">{{ valuedeletebtn(('announcements',msg.id,'deleted')) }}</li>
<li class="pull-right" style="padding-right: 5px;">
{% if not msg.visible %}
<a href="{{ url_for('edit', prefix='announcements.'+str(msg.id|string)+'.', ref=request.url, visible=1) }}" class="btn btn-primary">Veröffentlichen</a>
{% elif msg.time_expire and msg.time_expire < datetime.now() %}
<a href="#" class="btn btn-danger disabled">Abgelaufen</a>
{% elif msg.time_publish and msg.time_publish > datetime.now() %}
<a href="#" class="btn btn-default disabled">Geplant</a>
{% else %}
<a href="#" class="btn btn-success disabled">Öffentlich</a>
{% endif %}
</li>
<li class="dropdown pull-right" style="padding-right: 5px;">
<span class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">{{levels.get(msg.level, ('', 'Unbekannt'))[1]}} <span class="caret"></span></span>
<ul class="dropdown-menu">
{% for level, descr in levels.items() %}
<li><a href="{{ url_for('edit', prefix='announcements.'+(msg.id|string)+'.', ref=request.url, level=level) }}">{{ descr[1] }}</a></li>
{% endfor %}
</ul>
</li>
<li>
Aktiv von {{ valueeditor(('announcements',msg.id,'time_publish'), msg.time_publish) }}
bis {{ valueeditor(('announcements',msg.id,'time_expire'), msg.time_expire) }}
</li>
</ul>
</div>
{% endfor %}
</div>
</div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<ul class="list-inline pull-right"> <ul class="list-inline pull-right">
{% if ismod() %}
<li style="padding-right: 0px;"> <li style="padding-right: 0px;">
<a class="btn btn-default" href="{{ url_for('new_announcement', ref=request.url) }}">Neue Ankündigung</a> <a class="btn btn-default" href="{{ url_for('create', table='announcements', text='Neue Ankündigung', time_publish=datetime.now().replace(hour=0, minute=0, second=0, microsecond=0), time_expire=datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)+timedelta(days=7), ref=request.url) }}">Neue Ankündigung</a>
</li> </li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>
{% endif %}
<div class="row"> <div class="row">
<div class="col-md-6 panel-group"> <div class="col-md-6 panel-group">
<div class="panel panel-default"> <div class="panel panel-default">
...@@ -35,7 +75,7 @@ ...@@ -35,7 +75,7 @@
<div class="panel-heading"> <div class="panel-heading">
<h1 class="panel-title">Featured <h1 class="panel-title">Featured
{% if ismod() %} {% if ismod() %}
<a class="btn btn-default" href="{{ url_for('new_featured', ref=request.url) }}">Neue Empfehlung</a> <a class="btn btn-default" href="{{ url_for('create', table='featured', title='Neuer Artikel', ref=request.url) }}">Neue Empfehlung</a>
{% endif %} {% endif %}
</h1> </h1>
</div> </div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment