From a7a6ebde8ef99f258171908204b923bee21e764f Mon Sep 17 00:00:00 2001
From: Julian Rother <julianr@fsmpi.rwth-aachen.de>
Date: Wed, 12 Apr 2017 00:33:14 +0200
Subject: [PATCH] Changed url scheme, all non-stable paths are prefixed by
 /internal

---
 feeds.py               |  4 ++--
 importer.py            |  4 ++--
 jobs.py                | 10 +++++-----
 l2pauth.py             |  4 ++--
 server.py              | 42 +++++++++++++++++++++++++-----------------
 sorter.py              |  4 ++--
 static/moderator.js    |  4 ++--
 stats.py               | 10 +++++-----
 templates/embed.html   |  2 --
 templates/feed.atom    |  2 +-
 templates/lecture.html |  2 +-
 templates/macros.html  |  8 ++++----
 timetable.py           |  2 +-
 13 files changed, 52 insertions(+), 46 deletions(-)

diff --git a/feeds.py b/feeds.py
index 7b7767d..702c575 100644
--- a/feeds.py
+++ b/feeds.py
@@ -9,7 +9,7 @@ def fixdate(d):
 	return d
 
 @app.route('/feed')
-@app.route('/course/<handle>/feed')
+@app.route('/<handle>/feed')
 @handle_errors(None, 'Diese Veranstaltung existiert nicht!', 400, IndexError)
 def feed(handle=None):
 	id = None
@@ -40,7 +40,7 @@ def feed(handle=None):
 	course['updated'] = updated
 	return Response(render_template('feed.atom', course=course, entries=entries), 200, {'Content-Type': 'application/atom+xml'})
 
-@app.route('/course/feed')
+@app.route('/courses/feed')
 def courses_feed():
 	courses = query('SELECT * FROM courses WHERE visible AND listed ORDER BY time_created DESC LIMIT 100')
 	atomid = gen_atomid('Video AG, courses')
diff --git a/importer.py b/importer.py
index ded1e96..b3d3bd3 100644
--- a/importer.py
+++ b/importer.py
@@ -1,6 +1,6 @@
 from server import *
 
-@app.route('/import/<int:id>', methods=['GET', 'POST'])
+@app.route('/internal/import/<int:id>', methods=['GET', 'POST'])
 @mod_required
 def list_import_sources(id):
 	courses = query('SELECT * FROM courses WHERE id = ?', id)[0]
@@ -25,7 +25,7 @@ def list_import_sources(id):
 
 	return render_template('import_campus.html', course=courses, import_campus=import_campus, events=[])
 
-@app.route('/import/<int:id>/now', methods=['GET', 'POST'])
+@app.route('/internal/import/<int:id>/now', methods=['GET', 'POST'])
 @mod_required
 def import_from(id):
 
diff --git a/jobs.py b/jobs.py
index 909aab3..440f958 100644
--- a/jobs.py
+++ b/jobs.py
@@ -3,7 +3,7 @@ import traceback
 import json
 import random
 
-@app.route('/jobs/overview')
+@app.route('/internal/jobs/overview')
 @register_navbar('Jobs', iconlib='fa',  icon='suitcase')
 @mod_required
 def jobs_overview():
@@ -47,13 +47,13 @@ def jobs_catch_broken():
 	except:
 		pass
 
-@app.route('/jobs/api/worker/<hostname>/ping', methods=['GET', 'POST'])
+@app.route('/internal/jobs/api/worker/<hostname>/ping', methods=['GET', 'POST'])
 @jobs_api_token_required
 def jobs_worker_ping(hostname):
 	query('INSERT OR REPLACE INTO worker (hostname, last_ping) values (?, ?)', hostname, datetime.now())
 	return 'OK',200
 
-@app.route('/jobs/api/job/<int:id>/ping', methods=['GET', 'POST'])
+@app.route('/internal/jobs/api/job/<int:id>/ping', methods=['GET', 'POST'])
 @jobs_api_token_required
 def jobs_ping(id):
 	hostname = request.values['host']
@@ -62,7 +62,7 @@ def jobs_ping(id):
 	query('UPDATE jobs SET worker = ?, last_ping = ?, status = ?, state = ? where id = ?', hostname, datetime.now(), status, state, id)
 	return 'OK',200
 
-@app.route('/jobs/api/job/<int:id>/finished', methods=['GET', 'POST'])
+@app.route('/internal/jobs/api/job/<int:id>/finished', methods=['GET', 'POST'])
 @jobs_api_token_required
 def jobs_finished(id):
 	if 'status' in request.values:
@@ -72,7 +72,7 @@ def jobs_finished(id):
 	query('UPDATE jobs SET time_finished = ?, status = ?, state = "finished" where id = ?', datetime.now(), status, id)
 	return 'OK',200
 
-@app.route('/jobs/api/worker/<hostname>/schedule', methods=['POST'])
+@app.route('/internal/jobs/api/worker/<hostname>/schedule', methods=['POST'])
 @jobs_api_token_required
 def jobs_schedule(hostname):
 	hostdata =  request.get_json()
diff --git a/l2pauth.py b/l2pauth.py
index d658ee4..3c971e7 100644
--- a/l2pauth.py
+++ b/l2pauth.py
@@ -14,7 +14,7 @@ def oauthget(endpoint, **args):
 	r = requests.request('POST', OAUTH_BASE+endpoint, data=args)
 	return r.json()
 
-@app.route('/l2pauth')
+@app.route('/internal/l2pauth')
 def start_l2pauth():
 	if 'L2P_APIKEY' not in config:
 		return render_template("500.html"), 500
@@ -23,7 +23,7 @@ def start_l2pauth():
 	session['oauthscope'] = 'l2p'
 	return redirect(code['verification_url']+'?q=verify&d='+code['user_code'])
 
-@app.route('/rwthauth')
+@app.route('/internal/rwthauth')
 def start_rwthauth():
 	if 'L2P_APIKEY' not in config:
 		return render_template("500.html"), 500
diff --git a/server.py b/server.py
index 55aa88c..fcdf465 100644
--- a/server.py
+++ b/server.py
@@ -299,7 +299,10 @@ def index():
 		return redirect(url_for('course', handle=request.args['course']),code=302)
 	if 'view' in request.args:
 		if (request.args['view'] == 'player') and ('lectureid' in request.args) :
-			return redirect(url_for('lecture', id=request.args['lectureid']),code=302)
+			courses = query('SELECT courses.handle FROM courses JOIN lectures ON courses.id = lectures.course_id WHERE lectures.id = ?', request.args['lectureid'])
+			if not courses:
+				return "Not found", 404
+			return redirect(url_for('lecture', course=courses[0]['handle'], id=request.args['lectureid']),code=302)
 
 	start = date.today() - timedelta(days=1)
 	end = start + timedelta(days=7)
@@ -335,7 +338,7 @@ def index():
 			item['courses'] = query('SELECT * FROM courses WHERE (visible AND listed) AND `%s` = ? ORDER BY `%s`'%(item['param'], item['param']), item['param2'])
 	return render_template('index.html', latestvideos=livestreams+latestvideos, upcomming=upcomming, featured=featured)
 
-@app.route('/course')
+@app.route('/courses')
 @register_navbar('Videos', icon='film')
 def courses():
 	courses = query('SELECT * FROM courses WHERE (? OR (visible AND listed)) ORDER BY title', ismod())
@@ -355,8 +358,8 @@ def genlive(streams):
 		stream['file_size'] = 0
 	return streams
 
-@app.route('/course/<handle>')
-@app.route('/course/<int:id>')
+@app.route('/<handle>')
+@app.route('/<int:id>')
 @handle_errors('courses', 'Diese Veranstaltung existiert nicht!', 404, IndexError)
 def course(id=None, handle=None):
 	if id:
@@ -396,10 +399,12 @@ def course(id=None, handle=None):
 def faq():
 	return render_template('faq.html')
 
-@app.route('/play/<int:id>')
-@app.route('/embed/<int:id>', endpoint='embed')
+@app.route('/<course>/<int:id>')
+@app.route('/<int:courseid>/<int:id>')
+@app.route('/<course>/<int:id>/embed', endpoint='embed')
+@app.route('/<int:courseid>/<int:id>/embed', endpoint='embed')
 @handle_errors('course', 'Diese Vorlesung existiert nicht!', 404, IndexError)
-def lecture(id):
+def lecture(id, course=None, courseid=None):
 	lecture = query('SELECT * FROM lectures WHERE id = ? AND (? OR visible)', id, ismod())[0]
 	videos = query('''
 			SELECT videos.*, (videos.downloadable AND courses.downloadable) as downloadable, formats.description AS format_description, formats.player_prio, formats.prio, formats.mimetype
@@ -463,7 +468,7 @@ def search():
 def check_mod(user, groups):
 	return user and 'users' in groups
 
-@app.route('/login', methods=['GET', 'POST'])
+@app.route('/internal/login', methods=['GET', 'POST'])
 def login():
 	if request.method == 'GET':
 		return render_template('login.html')
@@ -480,7 +485,7 @@ def login():
 	session['_csrf_token'] = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(128))
 	return redirect(request.values.get('ref', url_for('index')))
 
-@app.route('/logout', methods=['GET', 'POST'])
+@app.route('/internal/logout', methods=['GET', 'POST'])
 def logout():
 	session.pop('user')
 	return redirect(request.values.get('ref', url_for('index')))
@@ -509,7 +514,7 @@ tabs = {
 			['time_created', 'time_updated'])
 }
 
-@app.route('/edit', methods=['GET', 'POST'])
+@app.route('/internal/edit', methods=['GET', 'POST'])
 @mod_required
 @csrf_protect
 def edit(prefix='', ignore=[]):
@@ -536,7 +541,7 @@ def edit(prefix='', ignore=[]):
 		return redirect(request.values['ref'])
 	return "OK", 200
 
-@app.route('/new/<table>', methods=['GET', 'POST'])
+@app.route('/internal/new/<table>', methods=['GET', 'POST'])
 @mod_required
 @csrf_protect
 def create(table):
@@ -564,7 +569,7 @@ def create(table):
 		return redirect(request.values['ref'])
 	return str(id), 200
 
-@app.route('/auth')
+@app.route('/internal/auth')
 def auth(): # For use with nginx auth_request
 	if 'X-Original-Uri' not in request.headers:
 		return 'Internal Server Error', 500
@@ -625,7 +630,7 @@ def auth(): # For use with nginx auth_request
 		return Response("Login required", 401, {'WWW-Authenticate': 'Basic realm="Login Required"'})
 	return "Not allowed", 403
 
-@app.route('/changelog')
+@app.route('/internal/changelog')
 @register_navbar('Changelog', icon='book')
 @mod_required
 def changelog():
@@ -638,7 +643,7 @@ def changelog():
 def files(filename):
 	return redirect(config['VIDEOPREFIX']+'/'+filename)
 
-@app.route('/newchapter/<int:lectureid>', methods=['POST', 'GET'])
+@app.route('/internal/newchapter/<int:lectureid>', methods=['POST', 'GET'])
 def suggest_chapter(lectureid):
 	time = request.values['time']
 	text = request.values['text']
@@ -659,7 +664,7 @@ def suggest_chapter(lectureid):
 		return redirect(request.values['ref'])
 	return 'OK',  200
 
-@app.route('/chapters/<int:lectureid>')
+@app.route('/internal/chapters/<int:lectureid>')
 def chapters(lectureid):
 	chapters = query("SELECT * FROM chapters WHERE lecture_id = ? AND NOT deleted AND (visible OR ?) ORDER BY time DESC", lectureid, ismod())
 	if not chapters:
@@ -682,7 +687,7 @@ def sitemap():
 	for i in query('select * from courses where visible and listed'):
 		pages.append([url_for('course',handle=i['handle'])])
 		for j in query('select * from lectures where (course_id = ? and visible)',i['id']):
-			pages.append([url_for('lecture',id=j['id'])])
+			pages.append([url_for('lecture',course=i['handle'],id=j['id'])])
 
 
 	return Response(render_template('sitemap.xml', pages=pages), 200, {'Content-Type': 'application/atom+xml'} )
@@ -692,7 +697,10 @@ def sitemap():
 @app.route('/site/<string:phpfile>')
 def legacy(phpfile=None):
 	if phpfile=='embed.php' and ('lecture' in request.args):
-		return redirect(url_for('embed', id=request.args['lecture']),code=302)
+		courses = query('SELECT courses.handle FROM courses JOIN lectures ON courses.id = lectures.course_id WHERE lectures.id = ?', request.args['lecture'])
+		if not courses:
+			return render_endpoint('index', 'Diese Seite existiert nicht!'), 404
+		return redirect(url_for('embed', course=courses[0]['handle'], id=request.args['lecture']),code=302)
 	if phpfile=='feed.php' and ('all' in request.args):
 		return redirect(url_for('feed'),code=302)
 	if phpfile=='feed.php' and ('newcourses' in request.args):
diff --git a/sorter.py b/sorter.py
index 72c338e..1e0f80b 100644
--- a/sorter.py
+++ b/sorter.py
@@ -1,7 +1,7 @@
 from server import *
 import traceback
 
-@app.route('/sort/log')
+@app.route('/internal/sort/log')
 @register_navbar('Sortierlog', icon='sort-by-attributes-alt')
 @mod_required
 def sort_log():
@@ -53,7 +53,7 @@ def schedule_thumbnail(lectureid):
 	data = '{"lectureid": "'+str(lectureid)+'", "path": "'+path+'"}'
 	query('INSERT INTO jobs (type, data, time_created) VALUES ("thumbnail", ?, ?)', data, datetime.now());
 
-@app.route('/sort/now')
+@app.route('/internal/sort/now')
 @mod_required
 @sched_func(600)
 def sort_now():
diff --git a/static/moderator.js b/static/moderator.js
index 858b5f5..ca809f1 100644
--- a/static/moderator.js
+++ b/static/moderator.js
@@ -13,7 +13,7 @@ var moderator = {
 			dict['_csrf_token'] = moderator.api.csrf_token;
 			$.ajax({
 				method: "POST",
-				url: "/edit",
+				url: "/internal/edit",
 				dataType: "text",
 				contentType: "application/json",
 				data: JSON.stringify(dict),
@@ -29,7 +29,7 @@ var moderator = {
 			value['_csrf_token'] = moderator.api.csrf_token;
 			$.ajax({
 				method: "POST",
-				url: "/new/"+type,
+				url: "/internal/new/"+type,
 				dataType: "text",
 				contentType: "application/json",
 				data: JSON.stringify(value),
diff --git a/stats.py b/stats.py
index b0be43c..8ef3166 100644
--- a/stats.py
+++ b/stats.py
@@ -3,7 +3,7 @@ import json
 from jobs import date_json_handler
 from hashlib import md5
 
-@app.route('/stats')
+@app.route('/internal/stats')
 @register_navbar('Statistiken', icon='stats')
 @mod_required
 def stats():
@@ -22,8 +22,8 @@ statsqueries['live_views'] = "SELECT hlslog.segment AS x, COUNT(DISTINCT hlslog.
 def plotly_date_handler(obj):
 	return obj.strftime("%Y-%m-%d %H:%M:%S")
 
-@app.route('/stats/generic/<req>')
-@app.route('/stats/generic/<req>/<param>')
+@app.route('/internal/stats/generic/<req>')
+@app.route('/internal/stats/generic/<req>/<param>')
 @mod_required
 def stats_generic(req, param=None):
 	if req not in statsqueries:
@@ -37,8 +37,8 @@ def stats_generic(req, param=None):
 			res[key].append(val)
 	return Response(json.dumps([res], default=plotly_date_handler),  mimetype='application/json')
 
-@app.route('/stats/viewsperday/<req>')
-@app.route('/stats/viewsperday/<req>/<param>')
+@app.route('/internal/stats/viewsperday/<req>')
+@app.route('/internal/stats/viewsperday/<req>/<param>')
 @mod_required
 def stats_viewsperday(req, param=""):
 	update_expr = 'INSERT INTO logcache (req, param, trace, date, value) SELECT "%s", ?, trace, date, y FROM (%s) AS cachetmp WHERE date < ?'
diff --git a/templates/embed.html b/templates/embed.html
index 2c5a2ee..0871ece 100644
--- a/templates/embed.html
+++ b/templates/embed.html
@@ -1,6 +1,4 @@
 {% from 'macros.html' import player %}
-{% from 'macros.html' import video_download_btn %}
-{% from 'macros.html' import video_embed_btn %}
 {% set page_border = 0 -%}
 
 {% extends "base.html" %}
diff --git a/templates/feed.atom b/templates/feed.atom
index 0144dd0..e24ad94 100644
--- a/templates/feed.atom
+++ b/templates/feed.atom
@@ -53,7 +53,7 @@ Veranstalter: {{ course.organizer }}<br>
 			<name>{{ entry.speaker }}</name>
 		</author>
 		{% endif %}
-		<link rel="alternate" href="{{ url_for('lecture', id=entry.id, _external=True) }}"/>
+		<link rel="alternate" href="{{ url_for('lecture', course=entry.course.handle, id=entry.id, _external=True) }}"/>
 		<link rel="enclosure" href="{{ url_for('files', filename=entry.video.path, _external=True)}}" length="{{ entry.video.file_size }}"/>
 		<id>{{ entry.atomid }}</id>
 		<updated>{{ entry.updated|rfc3339 }}</updated>
diff --git a/templates/lecture.html b/templates/lecture.html
index 96ca158..71c4b12 100644
--- a/templates/lecture.html
+++ b/templates/lecture.html
@@ -27,7 +27,7 @@
 				<a href="{{url_for('course', handle=course.handle)}}#lecture-{{lecture.id}}" class="btn btn-default" >Zur Veranstaltungsseite</a>
 				<ul class="list-inline pull-right">
 					<li><button class="btn btn-default" id="hintnewchapter">Kapitelmarker vorschlagen</button></li>
-					<li>{{ video_embed_btn(lecture.id) }}</li>
+					<li>{{ video_embed_btn(lecture.id, course=course.handle) }}</li>
 					<li class="dropdown">{{ video_download_btn(videos) }}</li>
 				</ul>
 			</div>
diff --git a/templates/macros.html b/templates/macros.html
index 07313d7..9395650 100644
--- a/templates/macros.html
+++ b/templates/macros.html
@@ -1,6 +1,6 @@
 {% macro preview(lecture) %}
 <li class="list-group-item">
-	<a href="{{url_for('lecture', id=lecture['id'])}}" title="{{ lecture.course.title }}" style="color: #000">
+	<a href="{{url_for('lecture', course=lecture.course.handle, id=lecture['id'])}}" title="{{ lecture.course.title }}" style="color: #000">
 		<div class="hidden-xs">
 			<div class="row">
 				<img class="col-xs-4" style="max-height: 120px; height: auto; width:170px" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
@@ -144,12 +144,12 @@ $(function() {
 {% endif %}
 {% endmacro %}
 
-{%macro video_embed_btn(lectureid) %}
+{%macro video_embed_btn(lectureid, course=None) %}
 <a class="btn btn-default" id="embedcodebtn" data-container="body" data-toggle="popover" data-placement="bottom">
 	<span>Einbetten</span>
 </a>
 <script>
-{% set embedcode = '<iframe width="700" height="394" src="'+url_for('embed', id=lectureid, _external=True)+'" frameborder="0" allowfullscreen="true"></iframe>' %}
+{% set embedcode = '<iframe width="700" height="394" src="'+url_for('embed', course=course, id=lectureid, _external=True)+'" frameborder="0" allowfullscreen="true"></iframe>' %}
 $('#embedcodebtn').popover(
 		{
 			html:true,
@@ -165,7 +165,7 @@ $('#embedcodebtn').popover(
 	<div class="row">
 		<div style="background-image: url('{% if not lecture.titlefile %}{{url_for('static',filename='no-thumbnail.png')}}{% else %}{{ config.VIDEOPREFIX }}/{{lecture.titlefile}}'){% endif %}" class="col-sm-2 col-xs-12 thumbnailimg">
 		{% if not videos|length is equalto 0 %}
-			<a href="{{url_for('lecture', id=lecture.id)}}">
+			<a href="{{url_for('lecture', course=lecture.course.handle, id=lecture.id)}}">
 				<span class="glyphicon glyphicon-play-circle playpreviewbtn"></span>
 			</a>
 		{% endif %}
diff --git a/timetable.py b/timetable.py
index a8e18be..2ccb548 100644
--- a/timetable.py
+++ b/timetable.py
@@ -1,6 +1,6 @@
 from server import *
 
-@app.route('/timetable')
+@app.route('/internal/timetable')
 @register_navbar('Drehplan', icon='calendar')
 @mod_required
 def timetable():
-- 
GitLab