def test_generate_change_token_ok(self) -> None: """ Test the function that generates a change token, with a success case for DELETION. """ # The expected result expected_expiration_date = datetime.datetime.today().replace( microsecond=0) + datetime.timedelta(days=5) expected_type = 'DELETION' # Prepare the mocks configuration.DELETION_TOKEN_VALIDITY_DAYS = 5 # Call the function actual_result = authentication.generate_change_token( 123, authentication.TokenType.DELETION, {'extra_key': 'extra_value'}) # Verify the result self.assertIsNotNone(actual_result) db_calls_mock.register_token.assert_not_called() # Verify the date actual_expiration_date = datetime.datetime.fromtimestamp( authentication.get_token_field(actual_result, 'exp')) self.assertEqual(expected_expiration_date, actual_expiration_date) # Verify the other fields exist self.assertEqual(expected_type, authentication.get_token_field(actual_result, 'type')) self.assertEqual(123, authentication.get_token_field(actual_result, 'user')) self.assertEqual( 'extra_value', authentication.get_token_field(actual_result, 'extra_key'))
def test_generate_token_ok_01(self) -> None: """ Test the function that generates a token, with a success case for REFRESH. """ # The expected result expected_expiration_date = datetime.datetime.today().replace( microsecond=0) + datetime.timedelta(days=5) expected_type = 'REFRESH' # Prepare the mocks token_payload = {'key': 'value'} token = jwt.encode(token_payload, 'secret key', algorithm='HS256') configuration.REFRESH_TOKEN_VALIDITY_DAYS = 5 db_calls_mock.register_token.return_value = models.Token( token, expected_expiration_date.date()) # Call the function actual_result = authentication.generate_token( 1, authentication.TokenType.REFRESH, unittest.mock.MagicMock()) # Verify the result self.assertIsNotNone(actual_result) db_calls_mock.register_token.assert_called() # Verify the date actual_expiration_date = datetime.datetime.fromtimestamp( authentication.get_token_field(actual_result, 'exp')) self.assertEqual(expected_expiration_date, actual_expiration_date) # Verify the other fields exist self.assertEqual(expected_type, authentication.get_token_field(actual_result, 'type')) self.assertEqual(1, authentication.get_token_field(actual_result, 'user'))
def post(self, args): """Send settings email.""" with session_scope() as session: token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] email_type = args['type'] # Get the user id from the token user_id = authentication.get_token_field(token.encode(), 'user') # If it is a user's deletion email request if email_type == SendEmailEP.EmailType.DELETION.name: if processing.send_deletion_email(session, user_id): return flask.make_response('', 200) else: return flask.make_response('', 400) # If it is an email change email request elif email_type == SendEmailEP.EmailType.CHANGE_OLD.name: if processing.send_change_email_old(session, user_id): return flask.make_response('', 200) else: return flask.make_response('', 400) # If something else is sent else: return flask.make_response('', 400)
def put(self, args): """Update a reminder.""" reminder_id = args['reminder_id'] anticipation_minutes = args['anticipation_minutes'] with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') success, msg = reminders.update_reminder(session, reminder_id, anticipation_minutes, user_id) if success: return flask.make_response( flask.jsonify({ 'reminder_list': auxiliary.list_to_json( reminders.get_reminders(session, user_id)) }), 201) else: if msg == 'Not found': return flask.make_response('', 404) else: return flask.make_response(msg, 400)
def test_get_token_field_error_01(self) -> None: """ Test the function that returns a field in the payload of a token, with an error due to invalid token. """ # The expected result expected_result = None # Call the function token = 'secret string'.encode() actual_result = authentication.get_token_field(token, 'key') # Verify the result self.assertEqual(expected_result, actual_result)
def post(self, args): """Register an alarm.""" show_name = args['show_name'] is_movie = args['is_movie'] alarm_type = args['type'] trakt_id = None show_season = None show_episode = None for k, v in args.items(): if v is None: continue if k == 'show_season': show_season = v elif k == 'show_episode': show_episode = v elif k == 'trakt_id': trakt_id = v with session_scope() as session: try: alarm_type = AlarmType[alarm_type] except KeyError: return flask.make_response('Invalid Alarm Type', 400) # Alarms for Listings are no longer valid if alarm_type == AlarmType.LISTINGS: return flask.make_response('Invalid Alarm Type', 400) if alarm_type == AlarmType.DB and trakt_id is None: return flask.make_response('Missing Trakt Id', 400) if not is_movie and (show_season is None or show_episode is None): return flask.make_response('Missing Season Episode', 400) # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') if db_calls.register_alarm(session, show_name, trakt_id, is_movie, alarm_type, show_season, show_episode, user_id) is not None: return flask.make_response( flask.jsonify({ 'alarm_list': auxiliary.list_to_json( processing.get_alarms(session, user_id)) }), 201) else: return flask.make_response('Alarm Already Exists', 400)
def get(self): """Get the list of alarms of the user.""" with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') alarms = processing.get_alarms(session, user_id) return flask.make_response( flask.jsonify({'alarm_list': auxiliary.list_to_json(alarms)}), 200)
def put(self, args): """Change user's settings, that don't require anything.""" include_adult_channels = None language = None excluded_channel_list = None for k, v in args.items(): if v is None: continue if k == 'include_adult_channels': include_adult_channels = v elif k == 'language': language = v elif k == 'excluded_channel_list': excluded_channel_list = v with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') changes = {} # Update include_adult_channels if include_adult_channels is not None: changes[ChangeType.INCLUDE_ADULT_CHANNELS. value] = include_adult_channels # Update language if language is not None and language in configuration.AVAILABLE_LANGUAGES: changes[ChangeType.LANGUAGE.value] = language # Update excluded channel list if excluded_channel_list is not None: changes[ ChangeType.EXCLUDED_CHANNELS.value] = excluded_channel_list # If there are changes to be made if changes != {}: if processing.change_user_settings(session, changes, user_id): return flask.make_response( flask.jsonify(processing.get_settings( session, user_id)), 200) else: return flask.make_response('', 400) # If there are no changes to be made else: return flask.make_response('Invalid Parameters', 400)
def get(self): """Get the user's settings, that don't require anything.""" with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') settings = processing.get_settings(session, user_id) if settings != {}: return flask.make_response(flask.jsonify(settings), 200) else: return flask.make_response('', 404)
def test_get_token_field_error_02(self) -> None: """ Test the function that returns a field in the payload of a token, with an error due to invalid field. """ # The expected result expected_result = None # Call the function token_payload = {'key': 'value'} token = jwt.encode(token_payload, 'secret key', algorithm='HS256') actual_result = authentication.get_token_field(token, 'invalid key') # Verify the result self.assertEqual(expected_result, actual_result)
def test_generate_access_token_ok(self) -> None: """ Test the function that generates an access token, with a success case. """ # The expected result expected_expiration_date = datetime.datetime.today().replace( microsecond=0) + datetime.timedelta(hours=10) expected_type = 'ACCESS' # Prepare the mocks configuration.REFRESH_TOKEN_VALIDITY_DAYS = 5 configuration.ACCESS_TOKEN_VALIDITY_HOURS = 10 refresh_token = authentication.generate_token( 123, authentication.TokenType.REFRESH, unittest.mock.MagicMock()) db_calls_mock.register_token.return_value = models.Token( refresh_token, expected_expiration_date.date()) # Call the function actual_result, actual_token = authentication.generate_access_token( unittest.mock.MagicMock(), refresh_token) # Verify the result self.assertTrue(actual_result) self.assertIsNotNone(actual_token) # Verify the date actual_expiration_date = datetime.datetime.fromtimestamp( authentication.get_token_field(actual_token, 'exp')) self.assertEqual(expected_expiration_date, actual_expiration_date) # Verify the other fields exist self.assertEqual(expected_type, authentication.get_token_field(actual_token, 'type')) self.assertEqual(123, authentication.get_token_field(actual_token, 'user'))
def get(self, args): """Get search results for the search_text, using the Trakt API.""" search_text = args['search_text'] language = args['language'] is_movie = None for k, v in args.items(): if v is None: continue if k == 'is_movie': is_movie = v if len(search_text) < 2: return flask.make_response('Search Text Too Small', 400) with session_scope() as session: search_adult = False # Get the user settings of whether it should look in channels with adult content or not if 'HTTP_AUTHORIZATION' in flask.request.headers.environ: token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field( token.encode(), 'user') user = db_calls.get_user_id(session, user_id) search_adult = user.show_adult if user is not None else False if search_text[0] == '"' and search_text[-1] == '"': search_text = search_text[1:-1] exact_name = True else: exact_name = False more_results, shows = processing.search_show_information( session, search_text, is_movie, language, search_adult, exact_name) response_dict = {'show_list': shows} # Add a remark when there are more results than those on the response if more_results and not exact_name: response_dict['remark'] = 'Incomplete List' return flask.make_response(flask.jsonify(response_dict), 200)
def delete(self, args): """Delete a alarm.""" alarm_id = args['alarm_id'] with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') processing.remove_alarm(session, alarm_id, user_id) return flask.make_response( flask.jsonify({ 'alarm_list': auxiliary.list_to_json( processing.get_alarms(session, user_id)) }), 200)
def send_change_email_new(session, change_token_old: str, new_email: str) -> (bool, bool): """ Send a 'Change Email' email to the new email address. :param session: the db session. :param change_token_old: the change token from the old email address. :param new_email: the new email. :return: a pair of booleans: the first is the success of the operation and the second is if the motif of the failure is that the new email is already at use. """ # Validate the change token from the old email address valid, user_id = authentication.validate_token( change_token_old.encode(), authentication.TokenType.CHANGE_EMAIL_OLD) if not valid: return False, False # Get the user id from the token user_id = authentication.get_token_field(change_token_old.encode(), 'user') # Get user user = session.query(models.User).filter(models.User.id == user_id).first() if user is None: return False, False # Check if the new email is valid new_email_user = session.query( models.User).filter(models.User.email == new_email).first() if new_email_user is not None: return False, True changes = {ChangeType.NEW_EMAIL.value: new_email} change_email_new_token = authentication.generate_change_token( user.id, authentication.TokenType.CHANGE_EMAIL_NEW, changes).decode() process_emails.set_language(user.language) return process_emails.send_change_email_new(new_email, change_email_new_token, user.email), True
def put(self, args): """Change user's settings, that require the password to be sent.""" password = args['password'] new_password = None for k, v in args.items(): if v is None: continue if k == 'new_password': new_password = v with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') user = db_calls.get_user_id(session, user_id) # Check if the password is valid valid = verify_login_credentials(user.email, password) if not valid: return flask.make_response('Unauthorized Access', 403) # Should be 503 # Update new_password if new_password is not None: if password == new_password: return flask.make_response('Same Password', 400) if processing.change_user_settings( session, {ChangeType.NEW_PASSWORD.value: new_password}, user_id): return flask.make_response('', 200) else: return flask.make_response('', 400) # No parameters else: return flask.make_response('Missing Parameter', 400)
def delete(self, args): """Delete a reminder.""" reminder_id = args['reminder_id'] with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') if db_calls.delete_reminder(session, reminder_id, user_id): return flask.make_response( flask.jsonify({ 'reminder_list': auxiliary.list_to_json( reminders.get_reminders(session, user_id)) }), 200) else: return flask.make_response('', 404)
def put(self, args): """Update an alarm.""" alarm_id = args['alarm_id'] show_season = args['show_season'] show_episode = args['show_episode'] with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') if processing.update_alarm(session, alarm_id, show_season, show_episode, user_id): return flask.make_response( flask.jsonify({ 'alarm_list': auxiliary.list_to_json( processing.get_alarms(session, user_id)) }), 201) else: return flask.make_response('', 404)
def post(self, args): """Register a reminder.""" show_session_id = args['show_session_id'] anticipation_minutes = args['anticipation_minutes'] with session_scope() as session: # Get the user id from the token token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field(token.encode(), 'user') if reminders.register_reminder(session, show_session_id, anticipation_minutes, user_id) is not None: return flask.make_response( flask.jsonify({ 'reminder_list': auxiliary.list_to_json( reminders.get_reminders(session, user_id)) }), 201) else: return flask.make_response('Invalid reminder', 400)
def get(self, args): """Get search results for the search_text or the show_id, in the listings and streaming services.""" search_text = None show_id = None is_movie = None for k, v in args.items(): if v is None: continue if k == 'search_text': search_text = v.strip() if k == 'show_id': show_id = v if k == 'is_movie': is_movie = v if search_text is None and show_id is None: return flask.make_response('Invalid request', 400) with session_scope() as session: search_adult = False # Get the user settings of whether it should look in channels with adult content or not if 'HTTP_AUTHORIZATION' in flask.request.headers.environ: token = flask.request.headers.environ['HTTP_AUTHORIZATION'][7:] user_id = authentication.get_token_field( token.encode(), 'user') user = db_calls.get_user_id(session, user_id) search_adult = user.show_adult if user is not None else False # Check whether it is a request by id or by text if show_id is not None: if is_movie is None: return flask.make_response('Invalid request', 400) titles = processing.get_show_titles(session, show_id, is_movie) db_shows = processing.search_sessions_db_with_tmdb_id( session, show_id, is_movie) else: if len(search_text) < 2: return flask.make_response('Search Text Too Small', 400) titles = [search_text] db_shows = [] # If it is a search with id # - we only want exact title matches # - for those results that don't have a TMDB id complete_title = show_id is not None ignore_with_tmdb_id = show_id is not None # db_shows += processing.search_streaming_services_shows_db(session, titles, is_movie=is_movie, # complete_title=complete_title, # search_adult=search_adult, # ignore_with_tmdb_id=ignore_with_tmdb_id) db_shows += processing.search_sessions_db( session, titles, is_movie=is_movie, complete_title=complete_title, search_adult=search_adult, ignore_with_tmdb_id=ignore_with_tmdb_id) response_dict = {'show_list': auxiliary.list_to_json(db_shows)} show_dict = {} # If it is a search by id, add information on the premiere of the show if show_id is not None: show = db_calls.get_show_data_by_tmdb_id( session, show_id, is_movie) if show is not None: if show.premiere_date is not None: show_dict['premiere_date'] = show.premiere_date if show.season_premiere is not None: show_dict['season_premiere'] = show.season_premiere response_dict['show'] = show_dict return flask.make_response(flask.jsonify(response_dict), 200)