1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-09-20 03:11:04 +00:00

Web UI: reworked how data is passed to templates

Logged user is pushed in request data
No more 'username' session key
Small fixes along the way
This commit is contained in:
spl0k 2017-11-22 21:59:32 +01:00
parent 9a58d067ab
commit b998bb0684
13 changed files with 134 additions and 115 deletions

View File

@ -9,12 +9,11 @@
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
from flask import session from flask import session, request, redirect, url_for
from supysonic.web import app, store from supysonic.web import app, store
from supysonic.db import Artist, Album, Track from supysonic.db import Artist, Album, Track
from supysonic.managers.user import UserManager from supysonic.managers.user import UserManager
from functools import wraps
app.add_template_filter(str)
@app.before_request @app.before_request
def login_check(): def login_check():
@ -24,18 +23,17 @@ def login_check():
if request.path.startswith('/static/'): if request.path.startswith('/static/'):
return return
if request.endpoint != 'login': request.user = None
should_login = True
if session.get('userid'):
code, user = UserManager.get(store, session.get('userid'))
if code != UserManager.SUCCESS:
session.clear()
else:
request.user = user
should_login = False should_login = False
if not session.get('userid'):
should_login = True
elif UserManager.get(store, session.get('userid'))[0] != UserManager.SUCCESS:
session.clear()
should_login = True
elif UserManager.get(store, session.get('userid'))[1].name != session.get('username'):
session.clear()
should_login = True
if should_login: if should_login and request.endpoint != 'login':
flash('Please login') flash('Please login')
return redirect(url_for('login', returnUrl = request.script_root + request.url[len(request.url_root)-1:])) return redirect(url_for('login', returnUrl = request.script_root + request.url[len(request.url_root)-1:]))
@ -48,6 +46,14 @@ def index():
} }
return render_template('home.html', stats = stats, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('home.html', stats = stats, admin = UserManager.get(store, session.get('userid'))[1].admin)
def admin_only(f):
@wraps(f)
def decorated_func(*args, **kwargs):
if not request.user or not request.user.admin:
return redirect(url_for('index'))
return f(*args, **kwargs)
return decorated_func
from .user import * from .user import *
from .folder import * from .folder import *
from .playlist import * from .playlist import *

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic. # This file is part of Supysonic.
# #
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# Copyright (C) 2013 Alban 'spl0k' Féron # Copyright (C) 2013-2017 Alban 'spl0k' Féron
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by # it under the terms of the GNU Affero General Public License as published by
@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from flask import request, flash, render_template, redirect, url_for, session from flask import request, flash, render_template, redirect, url_for
import os.path import os.path
import uuid import uuid
@ -28,23 +28,21 @@ from supysonic.scanner import Scanner
from supysonic.managers.user import UserManager from supysonic.managers.user import UserManager
from supysonic.managers.folder import FolderManager from supysonic.managers.folder import FolderManager
@app.before_request from . import admin_only
def check_admin():
if not request.path.startswith('/folder'):
return
if not UserManager.get(store, session.get('userid'))[1].admin:
return redirect(url_for('index'))
@app.route('/folder') @app.route('/folder')
@admin_only
def folder_index(): def folder_index():
return render_template('folders.html', folders = store.find(Folder, Folder.root == True), admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('folders.html', folders = store.find(Folder, Folder.root == True))
@app.route('/folder/add', methods = [ 'GET', 'POST' ]) @app.route('/folder/add')
def add_folder(): @admin_only
if request.method == 'GET': def add_folder_form():
return render_template('addfolder.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('addfolder.html')
@app.route('/folder/add', methods = [ 'POST' ])
@admin_only
def add_folder_post():
error = False error = False
(name, path) = map(request.form.get, [ 'name', 'path' ]) (name, path) = map(request.form.get, [ 'name', 'path' ])
if name in (None, ''): if name in (None, ''):
@ -54,18 +52,19 @@ def add_folder():
flash('The path is required.') flash('The path is required.')
error = True error = True
if error: if error:
return render_template('addfolder.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('addfolder.html')
ret = FolderManager.add(store, name, path) ret = FolderManager.add(store, name, path)
if ret != FolderManager.SUCCESS: if ret != FolderManager.SUCCESS:
flash(FolderManager.error_str(ret)) flash(FolderManager.error_str(ret))
return render_template('addfolder.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('addfolder.html')
flash("Folder '%s' created. You should now run a scan" % name) flash("Folder '%s' created. You should now run a scan" % name)
return redirect(url_for('folder_index')) return redirect(url_for('folder_index'))
@app.route('/folder/del/<id>') @app.route('/folder/del/<id>')
@admin_only
def del_folder(id): def del_folder(id):
try: try:
idid = uuid.UUID(id) idid = uuid.UUID(id)
@ -83,6 +82,7 @@ def del_folder(id):
@app.route('/folder/scan') @app.route('/folder/scan')
@app.route('/folder/scan/<id>') @app.route('/folder/scan/<id>')
@admin_only
def scan_folder(id = None): def scan_folder(id = None):
scanner = Scanner(store) scanner = Scanner(store)
if id is None: if id is None:

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic. # This file is part of Supysonic.
# #
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# Copyright (C) 2013 Alban 'spl0k' Féron # Copyright (C) 2013-2017 Alban 'spl0k' Féron
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by # it under the terms of the GNU Affero General Public License as published by
@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from flask import request, session, flash, render_template, redirect, url_for from flask import request, flash, render_template, redirect, url_for
import uuid import uuid
from supysonic.web import app, store from supysonic.web import app, store
from supysonic.db import Playlist from supysonic.db import Playlist
@ -26,9 +26,9 @@ from supysonic.managers.user import UserManager
@app.route('/playlist') @app.route('/playlist')
def playlist_index(): def playlist_index():
return render_template('playlists.html', mine = store.find(Playlist, Playlist.user_id == uuid.UUID(session.get('userid'))), return render_template('playlists.html',
others = store.find(Playlist, Playlist.user_id != uuid.UUID(session.get('userid')), Playlist.public == True), mine = store.find(Playlist, Playlist.user_id == request.user.id),
admin = UserManager.get(store, session.get('userid'))[1].admin) others = store.find(Playlist, Playlist.user_id != request.user.id, Playlist.public == True))
@app.route('/playlist/<uid>') @app.route('/playlist/<uid>')
def playlist_details(uid): def playlist_details(uid):
@ -43,7 +43,7 @@ def playlist_details(uid):
flash('Unknown playlist') flash('Unknown playlist')
return redirect(url_for('playlist_index')) return redirect(url_for('playlist_index'))
return render_template('playlist.html', playlist = playlist, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('playlist.html', playlist = playlist)
@app.route('/playlist/<uid>', methods = [ 'POST' ]) @app.route('/playlist/<uid>', methods = [ 'POST' ])
def playlist_update(uid): def playlist_update(uid):
@ -58,7 +58,7 @@ def playlist_update(uid):
flash('Unknown playlist') flash('Unknown playlist')
return redirect(url_for('playlist_index')) return redirect(url_for('playlist_index'))
if str(playlist.user_id) != session.get('userid'): if playlist.user_id != request.user.id:
flash("You're not allowed to edit this playlist") flash("You're not allowed to edit this playlist")
elif not request.form.get('name'): elif not request.form.get('name'):
flash('Missing playlist name') flash('Missing playlist name')
@ -81,7 +81,7 @@ def playlist_delete(uid):
playlist = store.get(Playlist, uid) playlist = store.get(Playlist, uid)
if not playlist: if not playlist:
flash('Unknown playlist') flash('Unknown playlist')
elif str(playlist.user_id) != session.get('userid'): elif playlist.user_id != request.user.id:
flash("You're not allowed to delete this playlist") flash("You're not allowed to delete this playlist")
else: else:
store.remove(playlist) store.remove(playlist)

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic. # This file is part of Supysonic.
# #
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# Copyright (C) 2013 Alban 'spl0k' Féron # Copyright (C) 2013-2017 Alban 'spl0k' Féron
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by # it under the terms of the GNU Affero General Public License as published by
@ -27,28 +27,27 @@ import uuid, csv
from supysonic import config from supysonic import config
from supysonic.lastfm import LastFm from supysonic.lastfm import LastFm
@app.before_request from . import admin_only
def check_admin():
if not request.path.startswith('/user'):
return
if request.endpoint in ('user_index', 'add_user', 'del_user', 'export_users', 'import_users', 'do_user_import') and not UserManager.get(store, session.get('userid'))[1].admin:
return redirect(url_for('index'))
@app.route('/user') @app.route('/user')
@admin_only
def user_index(): def user_index():
return render_template('users.html', users = store.find(User), admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('users.html', users = store.find(User))
@app.route('/user/<uid>') @app.route('/user/<uid>')
def user_profile(uid): def user_profile(uid):
if uid == 'me': if uid == 'me':
prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(session.get('userid'))) user = request.user
return render_template('profile.html', user = UserManager.get(store, session.get('userid'))[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin) elif not request.user.admin:
else:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(uid)) else:
return render_template('profile.html', user = UserManager.get(store, uid)[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin) code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
flash(UserManager.error_str(code))
return redirect(url_for('index'))
prefs = store.find(ClientPrefs, ClientPrefs.user_id == user.id)
return render_template('profile.html', user = user, has_lastfm = config.get('lastfm', 'api_key') != None, clients = prefs)
@app.route('/user/<uid>', methods = [ 'POST' ]) @app.route('/user/<uid>', methods = [ 'POST' ])
def update_clients(uid): def update_clients(uid):
@ -58,9 +57,9 @@ def update_clients(uid):
app.logger.debug(clients_opts) app.logger.debug(clients_opts)
if uid == 'me': if uid == 'me':
userid = uuid.UUID(session.get('userid')) userid = request.user.id
else: else:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS: if not request.user.admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
userid = uuid.UUID(uid) userid = uuid.UUID(uid)
@ -78,20 +77,22 @@ def update_clients(uid):
return user_profile(uid) return user_profile(uid)
@app.route('/user/<uid>/changeusername', methods = [ 'GET', 'POST' ]) @app.route('/user/<uid>/changeusername', methods = [ 'GET', 'POST' ])
@admin_only
def change_username(uid): def change_username(uid):
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS: code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
user = UserManager.get(store, uid)[1]
if request.method == 'POST': if request.method == 'POST':
username = request.form.get('user') username = request.form.get('user')
if username in ('', None): if username in ('', None):
flash('The username is required') flash('The username is required')
return render_template('change_username.html', user = user, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('change_username.html', user = user)
if request.form.get('admin') is None: if request.form.get('admin') is None:
admin = False admin = False
else: else:
admin = True admin = True
changed = False
if user.name != username or user.admin != admin: if user.name != username or user.admin != admin:
user.name = username user.name = username
user.admin = admin user.admin = admin
@ -102,16 +103,19 @@ def change_username(uid):
flash("No changes for '%s'." % username) flash("No changes for '%s'." % username)
return redirect(url_for('user_profile', uid = uid)) return redirect(url_for('user_profile', uid = uid))
return render_template('change_username.html', user = user, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('change_username.html', user = user)
@app.route('/user/<uid>/changemail', methods = [ 'GET', 'POST' ]) @app.route('/user/<uid>/changemail', methods = [ 'GET', 'POST' ])
def change_mail(uid): def change_mail(uid):
if uid == 'me': if uid == 'me':
user = UserManager.get(store, session.get('userid'))[1] user = request.user
else: elif not request.user.admin:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
user = UserManager.get(store, uid)[1] else:
code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
return redirect(url_for('index'))
if request.method == 'POST': if request.method == 'POST':
mail = request.form.get('mail') mail = request.form.get('mail')
# No validation, lol. # No validation, lol.
@ -119,25 +123,29 @@ def change_mail(uid):
store.commit() store.commit()
return redirect(url_for('user_profile', uid = uid)) return redirect(url_for('user_profile', uid = uid))
return render_template('change_mail.html', user = user, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('change_mail.html', user = user)
@app.route('/user/<uid>/changepass', methods = [ 'GET', 'POST' ]) @app.route('/user/<uid>/changepass', methods = [ 'GET', 'POST' ])
def change_password(uid): def change_password(uid):
if uid == 'me': if uid == 'me':
user = UserManager.get(store, session.get('userid'))[1].name user = request.user
else: elif not request.user.admin:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
user = UserManager.get(store, uid)[1].name else:
code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
return redirect(url_for('index'))
if request.method == 'POST': if request.method == 'POST':
error = False error = False
if uid == 'me' or uid == session.get('userid'): if uid == 'me' or uid == str(request.user.id):
current, new, confirm = map(request.form.get, [ 'current', 'new', 'confirm' ]) current, new, confirm = map(request.form.get, [ 'current', 'new', 'confirm' ])
if current in ('', None): if current in ('', None):
flash('The current password is required') flash('The current password is required')
error = True error = True
else: else:
new, confirm = map(request.form.get, [ 'new', 'confirm' ]) new, confirm = map(request.form.get, [ 'new', 'confirm' ])
if new in ('', None): if new in ('', None):
flash('The new password is required') flash('The new password is required')
error = True error = True
@ -146,22 +154,24 @@ def change_password(uid):
error = True error = True
if not error: if not error:
if uid == 'me' or uid == session.get('userid'): if uid == 'me' or uid == str(request.user.id):
status = UserManager.change_password(store, session.get('userid'), current, new) status = UserManager.change_password(store, user.id, current, new)
else: else:
status = UserManager.change_password2(store, UserManager.get(store, uid)[1].name, new) status = UserManager.change_password2(store, user.name, new)
if status != UserManager.SUCCESS: if status != UserManager.SUCCESS:
flash(UserManager.error_str(status)) flash(UserManager.error_str(status))
else: else:
flash('Password changed') flash('Password changed')
return redirect(url_for('user_profile', uid = uid)) return redirect(url_for('user_profile', uid = uid))
return render_template('change_pass.html', user = user, admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('change_pass.html', user = user)
@app.route('/user/add', methods = [ 'GET', 'POST' ]) @app.route('/user/add', methods = [ 'GET', 'POST' ])
@admin_only
def add_user(): def add_user():
if request.method == 'GET': if request.method == 'GET':
return render_template('adduser.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('adduser.html')
error = False error = False
(name, passwd, passwd_confirm, mail, admin) = map(request.form.get, [ 'user', 'passwd', 'passwd_confirm', 'mail', 'admin' ]) (name, passwd, passwd_confirm, mail, admin) = map(request.form.get, [ 'user', 'passwd', 'passwd_confirm', 'mail', 'admin' ])
@ -188,9 +198,10 @@ def add_user():
else: else:
flash(UserManager.error_str(status)) flash(UserManager.error_str(status))
return render_template('adduser.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('adduser.html')
@app.route('/user/del/<uid>') @app.route('/user/del/<uid>')
@admin_only
def del_user(uid): def del_user(uid):
status = UserManager.delete(store, uid) status = UserManager.delete(store, uid)
if status == UserManager.SUCCESS: if status == UserManager.SUCCESS:
@ -201,6 +212,7 @@ def del_user(uid):
return redirect(url_for('user_index')) return redirect(url_for('user_index'))
@app.route('/user/export') @app.route('/user/export')
@admin_only
def export_users(): def export_users():
resp = make_response('\n'.join([ '%s,%s,%s,%s,"%s",%s,%s,%s' % (u.id, u.name, u.mail, u.password, u.salt, u.admin, u.lastfm_session, u.lastfm_status) resp = make_response('\n'.join([ '%s,%s,%s,%s,"%s",%s,%s,%s' % (u.id, u.name, u.mail, u.password, u.salt, u.admin, u.lastfm_session, u.lastfm_status)
for u in store.find(User) ])) for u in store.find(User) ]))
@ -209,13 +221,15 @@ def export_users():
return resp return resp
@app.route('/user/import') @app.route('/user/import')
@admin_only
def import_users(): def import_users():
return render_template('importusers.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('importusers.html')
@app.route('/user/import', methods = [ 'POST' ]) @app.route('/user/import', methods = [ 'POST' ])
@admin_only
def do_user_import(): def do_user_import():
if not request.files['file']: if not request.files['file']:
return render_template('importusers.html', admin = UserManager.get(store, session.get('userid'))[1].admin) return render_template('importusers.html')
users = [] users = []
reader = csv.reader(request.files['file']) reader = csv.reader(request.files['file'])
@ -251,11 +265,15 @@ def lastfm_reg(uid):
return redirect(url_for('user_profile', uid = uid)) return redirect(url_for('user_profile', uid = uid))
if uid == 'me': if uid == 'me':
lfm = LastFm(UserManager.get(store, session.get('userid'))[1], app.logger) user = request.user
else: elif not request.user.admin:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
lfm = LastFm(UserManager.get(store, uid)[1], app.logger) else:
code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
return redirect(url_for('index'))
lfm = LastFm(user, app.logger)
status, error = lfm.link_account(token) status, error = lfm.link_account(token)
store.commit() store.commit()
flash(error if not status else 'Successfully linked LastFM account') flash(error if not status else 'Successfully linked LastFM account')
@ -265,11 +283,15 @@ def lastfm_reg(uid):
@app.route('/user/<uid>/lastfm/unlink') @app.route('/user/<uid>/lastfm/unlink')
def lastfm_unreg(uid): def lastfm_unreg(uid):
if uid == 'me': if uid == 'me':
lfm = LastFm(UserManager.get(store, session.get('userid'))[1], app.logger) user = request.user
else: elif not request.user.admin:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index')) return redirect(url_for('index'))
lfm = LastFm(UserManager.get(store, uid)[1], app.logger) else:
code, user = UserManager.get(store, uid)
if code != UserManager.SUCCESS:
return redirect(url_for('index'))
lfm = LastFm(user, app.logger)
lfm.unlink_account() lfm.unlink_account()
store.commit() store.commit()
flash('Unliked LastFM account') flash('Unliked LastFM account')
@ -278,7 +300,7 @@ def lastfm_unreg(uid):
@app.route('/user/login', methods = [ 'GET', 'POST']) @app.route('/user/login', methods = [ 'GET', 'POST'])
def login(): def login():
return_url = request.args.get('returnUrl') or url_for('index') return_url = request.args.get('returnUrl') or url_for('index')
if session.get('userid'): if request.user:
flash('Already logged in') flash('Already logged in')
return redirect(return_url) return redirect(return_url)
@ -298,7 +320,6 @@ def login():
status, user = UserManager.try_auth(store, name, password) status, user = UserManager.try_auth(store, name, password)
if status == UserManager.SUCCESS: if status == UserManager.SUCCESS:
session['userid'] = str(user.id) session['userid'] = str(user.id)
session['username'] = user.name
flash('Logged in!') flash('Logged in!')
return redirect(return_url) return redirect(return_url)
else: else:

View File

@ -9,7 +9,7 @@
-#} -#}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block navbar_users %} {% block navbar_users %}
{% if session.username != user.name %} {% if request.user.id != user.id %}
<li class="active"><a href="{{ url_for('user_index') }}">Users <span <li class="active"><a href="{{ url_for('user_index') }}">Users <span
class="sr-only">(current)</span></a></li> class="sr-only">(current)</span></a></li>
{% else %} {% else %}
@ -17,8 +17,8 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block navbar_profile %} {% block navbar_profile %}
{% if session.username == user.name %} {% if request.user.id == user.id %}
<li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ session.username }} <span class="sr-only">(current)</span></a></li> <li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ request.user.name }} <span class="sr-only">(current)</span></a></li>
{% else %} {% else %}
{{ super() }} {{ super() }}
{% endif %} {% endif %}

View File

@ -9,7 +9,7 @@
-#} -#}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block navbar_users %} {% block navbar_users %}
{% if session.username != user %} {% if request.user.id != user.id %}
<li class="active"><a href="{{ url_for('user_index') }}">Users <span <li class="active"><a href="{{ url_for('user_index') }}">Users <span
class="sr-only">(current)</span></a></li> class="sr-only">(current)</span></a></li>
{% else %} {% else %}
@ -17,8 +17,8 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block navbar_profile %} {% block navbar_profile %}
{% if session.username == user %} {% if request.user.id == user.id %}
<li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ session.username }} <span class="sr-only">(current)</span></a></li> <li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ request.user.name }} <span class="sr-only">(current)</span></a></li>
{% else %} {% else %}
{{ super() }} {{ super() }}
{% endif %} {% endif %}
@ -28,7 +28,7 @@
<h2>{{ user }}</h2> <h2>{{ user }}</h2>
</div> </div>
<form method="post"> <form method="post">
{% if session.username == user %} {% if request.user.id == user.id %}
<div class="form-group"> <div class="form-group">
<label class="sr-only" for="current">Current password</label> <label class="sr-only" for="current">Current password</label>
<div class="input-group"> <div class="input-group">

View File

@ -33,7 +33,7 @@
</tbody> </tbody>
</table> </table>
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<a href="{{ url_for('add_folder') }}" class="btn btn-default">Add</a> <a href="{{ url_for('add_folder_form') }}" class="btn btn-default">Add</a>
<a href="{{ url_for('scan_folder') }}" class="btn btn-default">Scan all</a> <a href="{{ url_for('scan_folder') }}" class="btn btn-default">Scan all</a>
</div> </div>
<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog"> <div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog">

View File

@ -56,7 +56,7 @@
{% block navbar_playlists %} {% block navbar_playlists %}
<li><a href="{{ url_for('playlist_index') }}">Playlists</a></li> <li><a href="{{ url_for('playlist_index') }}">Playlists</a></li>
{% endblock %} {% endblock %}
{% if admin %} {% if request.user.admin %}
{% block navbar_users %} {% block navbar_users %}
<li><a href="{{ url_for('user_index') }}">Users</a></li> <li><a href="{{ url_for('user_index') }}">Users</a></li>
{% endblock %} {% endblock %}
@ -65,7 +65,7 @@
{% endblock %} {% endblock %}
{% endif %} {% endif %}
{% block navbar_profile %} {% block navbar_profile %}
<li><a href="{{ url_for('user_profile', uid = 'me')}}">{{ session.username }}</a></li> <li><a href="{{ url_for('user_profile', uid = 'me')}}">{{ request.user.name }}</a></li>
{% endblock %} {% endblock %}
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">

View File

@ -16,7 +16,7 @@
<div class="page-header first-header"> <div class="page-header first-header">
<h2>Playlist "{{ playlist.name }}"</h2> <h2>Playlist "{{ playlist.name }}"</h2>
</div> </div>
{% if playlist.user_id|str == session.get('userid') %} {% if playlist.user_id == request.user.id %}
<h3>Edit</h3> <h3>Edit</h3>
<form method="post"> <form method="post">
<table id="playlist" class="table"> <table id="playlist" class="table">

View File

@ -9,7 +9,7 @@
-#} -#}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block navbar_users %} {% block navbar_users %}
{% if session.username != user.name %} {% if request.user.id != user.id %}
<li class="active"><a href="{{ url_for('user_index') }}">Users <span <li class="active"><a href="{{ url_for('user_index') }}">Users <span
class="sr-only">(current)</span></a></li> class="sr-only">(current)</span></a></li>
{% else %} {% else %}
@ -17,8 +17,8 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block navbar_profile %} {% block navbar_profile %}
{% if session.username == user.name %} {% if request.user.id == user.id %}
<li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ session.username }} <span class="sr-only">(current)</span></a></li> <li class="active"><a href="{{ url_for('user_profile', uid = 'me') }}">{{ request.user.name }} <span class="sr-only">(current)</span></a></li>
{% else %} {% else %}
{{ super() }} {{ super() }}
{% endif %} {% endif %}
@ -27,7 +27,7 @@
<div class="page-header first-header"> <div class="page-header first-header">
<h2>{{ user.name }}{% if user.admin %} <small><span class="glyphicon <h2>{{ user.name }}{% if user.admin %} <small><span class="glyphicon
glyphicon-certificate" data-toggle="tooltip" data-placement="right" glyphicon-certificate" data-toggle="tooltip" data-placement="right"
title="{% if session.username == user.name %}You're an admin!{% else %}The user is an admin!{% endif %}"></span></small>{% endif %}</h2> title="{% if request.user.id == user.id %}You're an admin!{% else %}The user is an admin!{% endif %}"></span></small>{% endif %}</h2>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
@ -38,7 +38,7 @@
<div class="input-group-addon">User eMail</div> <div class="input-group-addon">User eMail</div>
<input type="text" class="form-control" id="email" placeholder="{{ user.mail }}" readonly> <input type="text" class="form-control" id="email" placeholder="{{ user.mail }}" readonly>
<div class="input-group-btn"> <div class="input-group-btn">
{% if session.username == user.name %} {% if request.user.id == user.id %}
<a href="{{ url_for('change_mail', uid = 'me') }}" class="btn btn-default">Change eMail</a> <a href="{{ url_for('change_mail', uid = 'me') }}" class="btn btn-default">Change eMail</a>
{% else %} {% else %}
<a href="{{ url_for('change_mail', uid = user.id) }}" class="btn btn-default">Change eMail</a> <a href="{{ url_for('change_mail', uid = user.id) }}" class="btn btn-default">Change eMail</a>
@ -54,11 +54,11 @@
<label class="sr-only" for="lastfm">LastFM status</label> <label class="sr-only" for="lastfm">LastFM status</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">LastFM status</div> <div class="input-group-addon">LastFM status</div>
{% if api_key %} {% if has_lastfm %}
{% if user.lastfm_session %} {% if user.lastfm_session %}
<input type="text" class="form-control" id="lastfm" placeholder="{% if user.lastfm_status %}Linked{% else %}Invalid session{% endif %}" readonly> <input type="text" class="form-control" id="lastfm" placeholder="{% if user.lastfm_status %}Linked{% else %}Invalid session{% endif %}" readonly>
<div class="input-group-btn"> <div class="input-group-btn">
{% if session.username == user.name %} {% if request.user.id == user.id %}
<a href="{{ url_for('lastfm_unreg', uid = 'me') }}" class="btn btn-default">Unlink</a> <a href="{{ url_for('lastfm_unreg', uid = 'me') }}" class="btn btn-default">Unlink</a>
{% else %} {% else %}
<a href="{{ url_for('lastfm_unreg', uid = user.id) }}" class="btn btn-default">Unlink</a> <a href="{{ url_for('lastfm_unreg', uid = user.id) }}" class="btn btn-default">Unlink</a>
@ -67,7 +67,7 @@
{% else %} {% else %}
<input type="text" class="form-control" id="lastfm" placeholder="Unlinked" readonly> <input type="text" class="form-control" id="lastfm" placeholder="Unlinked" readonly>
<div class="input-group-btn"> <div class="input-group-btn">
{% if session.username == user.name %} {% if request.user.id == user.id %}
<a href="http://www.last.fm/api/auth/?api_key={{ api_key }}&cb={{ request.url_root[:-(request.script_root|length+1)] + url_for('lastfm_reg', uid = 'me') }}" class="btn btn-default">Link</a> <a href="http://www.last.fm/api/auth/?api_key={{ api_key }}&cb={{ request.url_root[:-(request.script_root|length+1)] + url_for('lastfm_reg', uid = 'me') }}" class="btn btn-default">Link</a>
{% else %} {% else %}
<a href="http://www.last.fm/api/auth/?api_key={{ api_key }}&cb={{ request.url_root[:-(request.script_root|length+1)] + url_for('lastfm_reg', uid = user.id) }}" class="btn btn-default">Link</a> <a href="http://www.last.fm/api/auth/?api_key={{ api_key }}&cb={{ request.url_root[:-(request.script_root|length+1)] + url_for('lastfm_reg', uid = user.id) }}" class="btn btn-default">Link</a>
@ -82,7 +82,7 @@
</form> </form>
</div> </div>
</div> </div>
{% if session.username == user.name %} {% if request.user.id == user.id %}
<a href="{{ url_for('change_password', uid = 'me') }}" class="btn btn-default">Change password</a></li> <a href="{{ url_for('change_password', uid = 'me') }}" class="btn btn-default">Change password</a></li>
{% else %} {% else %}
<a href="{{ url_for('change_username', uid = user.id) }}" class="btn btn-default">Change username or admin status</a></li> <a href="{{ url_for('change_username', uid = user.id) }}" class="btn btn-default">Change username or admin status</a></li>

View File

@ -23,10 +23,10 @@
<tbody> <tbody>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td>{% if session.username == user.name %}{{ user.name }}{% else %} <td>{% if request.user.id == user.id %}{{ user.name }}{% else %}
<a href="{{ url_for('user_profile', uid = user.id) }}">{{ user.name }}</a>{% endif %}</td> <a href="{{ url_for('user_profile', uid = user.id) }}">{{ user.name }}</a>{% endif %}</td>
<td>{{ user.mail }}</td><td>{{ user.admin }}</td><td>{{ user.last_play_date }}</td><td> <td>{{ user.mail }}</td><td>{{ user.admin }}</td><td>{{ user.last_play_date }}</td><td>
{% if session.username != user.name %}<button class="btn btn-danger btn-xs" data-href="{{ url_for('del_user', uid = user.id) }}" data-toggle="modal" data-target="#confirm-delete" aria-label="Delete user"> {% if request.user.id != user.id %}<button class="btn btn-danger btn-xs" data-href="{{ url_for('del_user', uid = user.id) }}" data-toggle="modal" data-target="#confirm-delete" aria-label="Delete user">
<span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete user"></span></button>{% endif %}</td></tr> <span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete user"></span></button>{% endif %}</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -33,7 +33,7 @@ class FolderTestCase(FrontendTestBase):
self._login('bob', 'B0b') self._login('bob', 'B0b')
rv = self.client.get('/folder/add', follow_redirects = True) rv = self.client.get('/folder/add', follow_redirects = True)
self.assertIn('There\'s nothing much to see', rv.data) self.assertIn('There\'s nothing much to see', rv.data)
self.assertNotIn('Add folder', rv.data) self.assertNotIn('Add Folder', rv.data)
self._logout() self._logout()
self._login('alice', 'Alic3') self._login('alice', 'Alic3')

View File

@ -54,7 +54,6 @@ class LoginTestCase(FrontendTestBase):
# Root with valid session # Root with valid session
with self.client.session_transaction() as sess: with self.client.session_transaction() as sess:
sess['userid'] = self.store.find(User, User.name == 'alice').one().id sess['userid'] = self.store.find(User, User.name == 'alice').one().id
sess['username'] = 'alice'
rv = self.client.get('/', follow_redirects=True) rv = self.client.get('/', follow_redirects=True)
self.assertIn('alice', rv.data) self.assertIn('alice', rv.data)
self.assertIn('Log out', rv.data) self.assertIn('Log out', rv.data)
@ -64,13 +63,6 @@ class LoginTestCase(FrontendTestBase):
# Root with a no-valid session # Root with a no-valid session
with self.client.session_transaction() as sess: with self.client.session_transaction() as sess:
sess['userid'] = uuid.uuid4() sess['userid'] = uuid.uuid4()
sess['username'] = 'alice'
rv = self.client.get('/', follow_redirects=True)
self.assertIn('Please login', rv.data)
# Root with a no-valid user
with self.client.session_transaction() as sess:
sess['userid'] = self.store.find(User, User.name == 'alice').one().id
sess['username'] = 'nonexistent'
rv = self.client.get('/', follow_redirects=True) rv = self.client.get('/', follow_redirects=True)
self.assertIn('Please login', rv.data) self.assertIn('Please login', rv.data)