def _handle_patch_request(field: str): try: logging.info(f"User requested [{field}] change") if not _required_params(field): return make_response("Invalid parameter(s)", 406) if field=='votes': update_value='votes + 1' else: update_value = request.args.get('update') song_name = request.args.get('song_name') artist = request.args.get('artist') template = load_db_template(defaults.update_songs_column) query = template.render(field=field, update_value=update_value, song_name=song_name, artist=artist) connect_execute_query(query) logging.info(f"[{field}] successfully changed to {update_value}.") return make_response(f"Successfully changed [{field}] field.", 200) except Exception as e: logging.error(f"Unexpected error happened: {e}") return make_response("Unprocessable entity", 430)
def charts(): if request.method =='GET': select_query="SELECT * from songs order by votes desc limit 10" songs=connect_execute_query(select_query) if not songs: logging.info("Couldn't get results") return render_template('charts.html') return render_template('charts.html',songs=songs) genre=request.form['genre'] if 'all' in genre: select_query="SELECT * from songs order by votes desc limit 10" songs=connect_execute_query(select_query) if not songs: logging.info("Coudln't get results") return render_template('charts.html') return render_template('charts.html',songs=songs) select_query=f"SELECT * from songs where genre='{genre}' order by votes desc limit 10" songs=connect_execute_query(select_query) if not songs: logging.info("You have selected invalid genre, please try again") return render_template('charts.html') return render_template('charts.html',songs=songs)
def _song_in_db(song_name: str, artist: str) -> bool: query = f"SELECT song_name from songs where song_name='{song_name}' and artist ='{artist}'" found = connect_execute_query(query) if not found: logging.info("Song is not in the database.") return False return True
def decor(*args, **kwargs): secret = os.getenv('SECRET_KEY') if 'Authorization' not in request.headers: return make_response("Token auth is required for this endpoint.", 403) auth_header = request.headers.get('Authorization') auth_token = auth_header.split(" ")[1] if auth_header else "" if not all(param in request.args for param in ['song_name', 'artist']): return make_response("Invalid parameter(s)", 406) song_name = request.args.get('song_name') artist = request.args.get('artist') try: token = jwt.decode(auth_token, secret, algorithms=["HS256"])['token'] token_query = f"SELECT token FROM songs WHERE song_name='{song_name}' AND artist='{artist}'" token_result = connect_execute_query(token_query) if not token_result: return make_response("Invalid token.", 405) if token_result[0][0] != token: return make_response("Invalid permissions for this song", 403) logging.info(f"User is authenticated to use this API Endpoint") return func(*args, **kwargs) except Exception as e: logging.error(f"Error happened during authentication: [{e}]") return make_response("Invalid token.", 405)
def decor(*args, **kwargs): secret = os.getenv('SECRET_KEY') if 'Authorization' not in request.headers: return make_response("Token auth is required for this endpoint.", 403) auth_header = request.headers.get('Authorization') auth_token = auth_header.split(" ")[1] if auth_header else "" try: token = jwt.decode(auth_token, secret, algorithms=["HS256"])['token'] token_query = f"SELECT * FROM users WHERE token='{token}'" result = connect_execute_query(token_query) if not result: return make_response("Invalid token.", 405) logging.info( f"User [{result[0][1]}] is authenticated to use this API Endpoint" ) return func(*args, **kwargs) except Exception as e: logging.error(f"Error happened during authentication: [{e}]") return make_response("Invalid token.", 405)
def songs(): if request.method =='GET': return render_template('songs.html') song_name = request.form.get('song') username = request.form.get('user') artist = request.form.get('artist') genre = request.form.get('genre') yt_link = request.form.get('yt_link') token = request.form.get('token') try: token = jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['token'] token_query = f"SELECT * FROM users WHERE token='{token}'" result = connect_execute_query(token_query) if not result: flash("Token is not valid,please try again", category='error') return render_template('songs.html') logging.info(f"User [{result[0][1]}] is authenticated to use this API Endpoint") except Exception as e: logging.error(f"Error happened during authentication: [{e}]") flash(str(e), category='error') return render_template('songs.html') song = Song(artist,genre,song_name,yt_link,token) success = song.input_song() if not success: flash("Song already exists!", category='error') return render_template("songs.html") return render_template('added_song.html',name=song.song_name)
def input_song(self) -> bool: if self.check_if_song_exists(): logging.info( f"Adding [{self.artist.upper()}:{self.song_name}] song into db." ) template = load_db_template(defaults.song_insert) insert_query = template.render(song_name=self.song_name, artist=self.artist, genre=self.genre, yt_link=self.yt_link, token=self.token) connect_execute_query(insert_query) return True return False
def validate_user(self) -> bool: query = f"SELECT user FROM users WHERE user=\'{self.name}\'" result = connect_execute_query(query) if result: logging.warning(f"User by the name {result[0][0]} already exists.") return False else: logging.info(f"User with name {self.name} is valid.") return True
def check_if_song_exists(self) -> bool: query = f"SELECT * FROM songs WHERE UPPER(artist)=\'{self.artist.upper()}\' AND UPPER(song_name)=\'{self.song_name.upper()}\'" result = connect_execute_query(query) if result: logging.warning( f"Song [{self.artist}:{self.song_name}] you wanted to add already exists." ) return False else: return True
def _handle_request(wanted_params: list, endpoint: str, top_count: int = 0): logging.info(f"User requested list of {endpoint}.") try: if invalid_parameters(wanted_params): logging.info("Bad parameter added to request.") return make_response(f"Bad parameter", 420) if invalid_param_value(): logging.info("Bad parameter values added to request.") return make_response("Bad parameter value", 421) where_query = '' for param in wanted_params: if param == 'sort': continue if param in request.args: logging.info( f"User requested {param} to be {request.args.get(param)}.") where_query += f"{' AND' if where_query else ''} {param}='{request.args.get(param)}'" where_query = f" WHERE{where_query}" if where_query else '' values = [param for param in wanted_params if param != 'sort'] values_str = ','.join(values) query = f"SELECT {values_str} FROM songs{where_query}" songs = connect_execute_query(query) response = [dict(zip(values, song)) for song in songs] sort_desc = 'sort' in request.args and request.args.get( 'sort') == 'desc' if 'votes' in endpoint: logging.info( f"Results will be sorted in {'descending' if sort_desc else 'ascending'} order" ) response = sorted(response, key=lambda k: k['votes'], reverse=sort_desc) if top_count != 0: logging.info(f"User requested first {top_count} results.") response = response[:top_count] if sort_desc else response[ -top_count:] return jsonify(response) except Exception as e: logging.error( f"Error happened while using /api/{endpoint} endpoint: {e}") return make_response('Could not get the results. Please try later.', 430)
def _handle_delete_request(song_name: str, artist: str): try: logging.info(f"User requested delete of {song_name}.") if not _song_in_db(song_name, artist): return make_response("Bad song_name value", 405) query = f"DELETE FROM songs where song_name='{song_name}' and artist='{artist}'" songs = connect_execute_query(query) return make_response("Song is successfully deleted from database.") except Exception as e: logging.error(f"Error happened while using /api/songs endpoint: {e}") return make_response('Could not get the results. Please try later.', 430)
def get_encoded_token(self) -> str: try: query = f"SELECT token FROM users WHERE user='******'" result = connect_execute_query(query) if result: token = result[0][0] return str( jwt.encode({'token': token}, os.getenv('SECRET_KEY'), algorithm="HS256")) else: logging.warning( f"User [{self.name}] is missing from DB. Trying to add him." ) user_added = self.input_user() if not user_added: logging.critical( f"User [{self.name}] failed to be added to the DB.") return None logging.info( "User successfully added to the DB, acquiring token.") result = connect_execute_query(query) if not result: return None return str( jwt.encode({'token': result[0][0]}, os.getenv('SECRET_KEY'), algorithm="HS256")) except Exception as e: logging.error(f"Error happened while acquiring token: {e}") return None
def input_user(self) -> bool: if len(self.name) <= 3: logging.info("Username must have more than 3 characters.") return False if len(self.password) <= 4: logging.info("Password must have more than 4 characters.") return False if self.validate_user(): logging.info(f"Adding {self.name} user into db.") token = str(uuid.uuid4()) template = load_db_template(defaults.user_insert) insert_query = template.render(user=self.name, password=generate_hash( self.password), token=token) connect_execute_query(insert_query) return True return False