diff --git a/music/api/admin.py b/music/api/admin.py index 7ab575a..6d72935 100644 --- a/music/api/admin.py +++ b/music/api/admin.py @@ -5,7 +5,7 @@ from datetime import datetime from google.cloud import tasks_v2 -from music.api.decorators import login_or_jwt, admin_required +from music.api.decorators import login_or_jwt, admin_required, no_locked_users blueprint = Blueprint('admin-api', __name__) @@ -18,6 +18,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/tasks', methods=['GET']) @login_or_jwt @admin_required +@no_locked_users def get_tasks(auth=None, user=None): tasks = list(tasker.list_tasks(parent=task_path)) diff --git a/music/api/api.py b/music/api/api.py index 889aaa7..8d00d94 100644 --- a/music/api/api.py +++ b/music/api/api.py @@ -8,7 +8,7 @@ import logging from datetime import datetime from music.api.decorators import login_or_jwt, login_required, login_or_jwt, \ - admin_required, cloud_task, validate_json, validate_args, spotify_link_required + admin_required, cloud_task, validate_json, validate_args, spotify_link_required, no_locked_users from music.cloud import queue_run_user_playlist, offload_or_run_user_playlist from music.cloud.tasks import update_all_user_playlists, update_playlists @@ -29,6 +29,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/playlists', methods=['GET']) @login_or_jwt +@no_locked_users def all_playlists_route(auth=None, user=None): """Retrieve all playlists for a given user @@ -47,6 +48,7 @@ def all_playlists_route(auth=None, user=None): @blueprint.route('/playlist', methods=['GET', 'DELETE']) @login_or_jwt +@no_locked_users @validate_args(('name', str)) def playlist_get_delete_route(auth=None,user=None): @@ -65,6 +67,7 @@ def playlist_get_delete_route(auth=None,user=None): @blueprint.route('/playlist', methods=['POST', 'PUT']) @login_or_jwt +@no_locked_users @validate_json(('name', str)) def playlist_post_put_route(auth=None, user=None): @@ -162,6 +165,7 @@ def playlist_post_put_route(auth=None, user=None): @blueprint.route('/user', methods=['GET', 'POST']) @login_or_jwt +@no_locked_users def user_route(auth=None, user=None): assert user is not None @@ -220,6 +224,7 @@ def user_delete_route(auth=None, user=None): @blueprint.route('/users', methods=['GET']) @login_or_jwt @admin_required +@no_locked_users def all_users_route(auth=None, user=None): return jsonify({ 'accounts': [i.to_dict() for i in User.collection.fetch()] @@ -228,6 +233,7 @@ def all_users_route(auth=None, user=None): @blueprint.route('/user/password', methods=['POST']) @login_required +@no_locked_users @validate_json(('new_password', str), ('current_password', str)) def change_password(user=None): request_json = request.get_json() @@ -251,6 +257,7 @@ def change_password(user=None): @blueprint.route('/playlist/run', methods=['GET']) @login_or_jwt +@no_locked_users @validate_args(('name', str)) def run_playlist(auth=None, user=None): @@ -281,6 +288,7 @@ def run_playlist_task(): # receives cloud tasks request for update @blueprint.route('/playlist/run/user', methods=['GET']) @login_or_jwt +@no_locked_users def run_user(auth=None, user=None): if user.type == 'admin': @@ -306,6 +314,7 @@ def run_user_task(): @blueprint.route('/playlist/run/users', methods=['GET']) @login_or_jwt @admin_required +@no_locked_users def run_users(auth=None, user=None): update_all_user_playlists() @@ -315,6 +324,7 @@ def run_users(auth=None, user=None): @blueprint.route('/playlist/image', methods=['GET']) @login_or_jwt @spotify_link_required +@no_locked_users @validate_args(('name', str)) def image(auth=None, user=None): diff --git a/music/api/decorators.py b/music/api/decorators.py index 5fac078..016b135 100644 --- a/music/api/decorators.py +++ b/music/api/decorators.py @@ -132,6 +132,22 @@ def admin_required(func): return admin_required_wrapper +def no_locked_users(func): + @functools.wraps(func) + def no_locked_users_wrapper(*args, **kwargs): + db_user = kwargs.get('user') + + if db_user is not None: + if not db_user.locked: + return func(*args, **kwargs) + else: + logger.warning('user locked') + return jsonify({'status': 'error', 'message': 'user locked'}), 401 + else: + logger.warning('user not logged in') + return jsonify({'error': 'not logged in'}), 401 + + return no_locked_users_wrapper def spotify_link_required(func): @functools.wraps(func) diff --git a/music/api/fm.py b/music/api/fm.py index 6f41bdf..f7d13c7 100644 --- a/music/api/fm.py +++ b/music/api/fm.py @@ -2,7 +2,7 @@ from flask import Blueprint, jsonify from datetime import date import logging -from music.api.decorators import login_or_jwt, lastfm_username_required +from music.api.decorators import login_or_jwt, lastfm_username_required, no_locked_users import music.db.database as database @@ -12,6 +12,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/today', methods=['GET']) @login_or_jwt +@no_locked_users @lastfm_username_required def daily_scrobbles(auth=None, user=None): diff --git a/music/api/player.py b/music/api/player.py index 54f8bbd..cc50894 100644 --- a/music/api/player.py +++ b/music/api/player.py @@ -2,7 +2,7 @@ from flask import Blueprint, request, jsonify import logging -from music.api.decorators import login_or_jwt, spotify_link_required, validate_json +from music.api.decorators import login_or_jwt, spotify_link_required, validate_json, no_locked_users import music.db.database as database from spotframework.net.network import SpotifyNetworkException @@ -18,6 +18,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/play', methods=['POST']) @login_or_jwt @spotify_link_required +@no_locked_users def play(auth=None, user=None): request_json = request.get_json() @@ -80,6 +81,7 @@ def play(auth=None, user=None): @blueprint.route('/next', methods=['POST']) @login_or_jwt @spotify_link_required +@no_locked_users def next_track(auth=None, user=None): net = database.get_authed_spotify_network(user) player = Player(net) @@ -91,6 +93,7 @@ def next_track(auth=None, user=None): @blueprint.route('/shuffle', methods=['POST']) @login_or_jwt @spotify_link_required +@no_locked_users @validate_json(('state', bool)) def shuffle(auth=None, user=None): request_json = request.get_json() @@ -105,6 +108,7 @@ def shuffle(auth=None, user=None): @blueprint.route('/volume', methods=['POST']) @login_or_jwt @spotify_link_required +@no_locked_users @validate_json(('volume', int)) def volume(auth=None, user=None): request_json = request.get_json() diff --git a/music/api/spotfm.py b/music/api/spotfm.py index 0ca1948..3ad25e5 100644 --- a/music/api/spotfm.py +++ b/music/api/spotfm.py @@ -4,7 +4,7 @@ import json import os from music.api.decorators import admin_required, login_or_jwt, lastfm_username_required, \ - spotify_link_required, cloud_task, validate_args + spotify_link_required, cloud_task, validate_args, no_locked_users import music.db.database as database from music.cloud.tasks import refresh_all_user_playlist_stats, refresh_user_playlist_stats, refresh_playlist_task from music.tasks.refresh_lastfm_stats import refresh_lastfm_track_stats, \ @@ -23,6 +23,7 @@ logger = logging.getLogger(__name__) @login_or_jwt @spotify_link_required @lastfm_username_required +@no_locked_users def count(auth=None, user=None): uri = request.args.get('uri', None) @@ -72,6 +73,7 @@ def count(auth=None, user=None): @login_or_jwt @spotify_link_required @lastfm_username_required +@no_locked_users @validate_args(('name', str)) def playlist_refresh(auth=None, user=None): @@ -135,6 +137,7 @@ def run_playlist_artist_task(): @blueprint.route('/playlist/refresh/users', methods=['GET']) @login_or_jwt @admin_required +@no_locked_users def run_users(auth=None, user=None): refresh_all_user_playlist_stats() return jsonify({'message': 'executed all users', 'status': 'success'}), 200 @@ -142,6 +145,7 @@ def run_users(auth=None, user=None): @blueprint.route('/playlist/refresh/user', methods=['GET']) @login_or_jwt +@no_locked_users def run_user(auth=None, user=None): if user.type == 'admin': diff --git a/music/api/spotify.py b/music/api/spotify.py index 20f497d..6008822 100644 --- a/music/api/spotify.py +++ b/music/api/spotify.py @@ -1,7 +1,7 @@ from flask import Blueprint, request, jsonify import logging -from music.api.decorators import login_or_jwt, spotify_link_required +from music.api.decorators import login_or_jwt, spotify_link_required, no_locked_users import music.db.database as database from spotframework.engine.playlistengine import PlaylistEngine @@ -14,6 +14,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/sort', methods=['POST']) @login_or_jwt @spotify_link_required +@no_locked_users def sort(auth=None, user=None): request_json = request.get_json() diff --git a/music/api/tag.py b/music/api/tag.py index b8f9aa4..9d583e3 100644 --- a/music/api/tag.py +++ b/music/api/tag.py @@ -4,7 +4,7 @@ import logging import os import json -from music.api.decorators import login_or_jwt, cloud_task +from music.api.decorators import login_or_jwt, cloud_task, no_locked_users from music.cloud.function import update_tag as serverless_update_tag from music.tasks.update_tag import update_tag @@ -16,6 +16,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/tag', methods=['GET']) @login_or_jwt +@no_locked_users def tags(auth=None, user=None): logger.info(f'retrieving tags for {user.username}') return jsonify({ @@ -25,6 +26,7 @@ def tags(auth=None, user=None): @blueprint.route('/tag/', methods=['GET', 'PUT', 'POST', "DELETE"]) @login_or_jwt +@no_locked_users def tag_route(tag_id, auth=None, user=None): if request.method == 'GET': return get_tag(tag_id, user) @@ -127,6 +129,7 @@ def delete_tag(tag_id, user): @blueprint.route('/tag//update', methods=['GET']) @login_or_jwt +@no_locked_users def tag_refresh(tag_id, auth=None, user=None): logger.info(f'updating {tag_id} tag for {user.username}')