def update_groups(self, ldap_id, groups): """Update users account""" url = '{0}/{1}/users/update_groups'.format(self.url, self.version) headers = { "Content-Type": "application/json", "Accept": "application/json" } data = { 'ldap_id': ldap_id, 'groups': groups } try: response = g.requests.patch(url, json=data, headers=headers, timeout=self.timeout) response.raise_for_status() except requests.exceptions.HTTPError as error: current_app.logger.error('Encountered non 2xx http code from account_api for updating groups') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR", filler=str(error))) except requests.exceptions.ConnectionError as error: current_app.logger.error('Encountered an error connecting to account_api for updating group') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_CONN_ERROR", filler=str(error))) except requests.exceptions.Timeout as error: current_app.logger.error('Encountered a timeout when writing to account_api for updating group') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_TIMEOUT", filler=str(error))) else: app.logger.info("groups updated for user {}".format(ldap_id)) return {'message': 'groups updated'}
def create(self, data): """Activate user.""" url = '{0}/{1}/users'.format(self.url, self.version) headers = { "Content-Type": "application/json", "Accept": "application/json" } payload = _create_user_data(data) try: response = g.requests.post(url, json=payload, headers=headers, timeout=self.timeout) response.raise_for_status() except requests.exceptions.HTTPError as error: current_app.logger.error('Encountered non 2xx http code from account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR", filler=str(error))) except requests.exceptions.ConnectionError as error: current_app.logger.error('Encountered an error connecting to account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_CONN_ERROR", filler=str(error))) except requests.exceptions.Timeout as error: current_app.logger.error('Encountered a timeout when writing to account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_TIMEOUT", filler=str(error))) else: app.logger.info("Created user {}".format(payload['email'])) return response.json()
def get_user_by_key(user_data): if user_data['key'] == 'user_details_id': user = UserDetails.get_user_details_by_id(user_data['value']) elif user_data['key'] == 'email': user = UserDetails.get_user_details_by_email(user_data['value']) elif user_data['key'] == 'api_key': user = UserDetails.get_user_details_by_api_key(user_data['value']) elif user_data['key'] == 'ldap_id': user = UserDetails.get_user_details_by_ldap_id(user_data['value']) else: raise ApplicationError('Incorrect key: {}'.format(user_data['key']), 'E101', http_code=404) if user: user_details = user.as_dict() user_type = get_user_type(user_details['user_type_id']) user_details['user_type'] = user_type contact_preferences = _build_contact_preferences( _extract_rows( Contact.get_contact_preferences_for_user( user_details['user_details_id']))) user_details['contact_preferences'] = contact_preferences user_dict = { 'user_details': user_details, 'datasets': _build_users_datasets(user_details['user_details_id']) } return user_dict else: raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_data['value']), http_code=404)
def delete_user(user_id): try: UserTermsLink.delete_user_by_user_id(user_id) Activity.delete_user_by_user_id(user_id) Contact.delete_contact_preferences_for_user(user_id) user = UserDetails.get_user_details_by_id(user_id) if user: db.session.delete(user) else: app.logger.error("No user: {} found for deletion".format(user_id)) db.session.rollback() db.session.close() raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_id), http_code=404) db.session.commit() return {'user_id': user_id, 'message': 'user deleted'} except Exception as e: db.session.rollback() db.session.close() raise ApplicationError(*errors.get('ulapd_api', 'DELETE_USER_ERROR', filler=e), http_code=400)
def test_update_historical_cache_exception(self, mock_prefixes, mock_s3, *_): mock_s3.return_value = MagicMock() mock_s3.return_value.BUCKET_NAME.return_value = 'bucket' mock_s3.return_value.BUCKET_RESTRICTED.return_value = 'other_bucket' mock_prefixes.return_value = ['ccod/'] mock_s3.return_value.fetch_s3_file.side_effect = ApplicationError( 'Some error', 400) mock_s3.return_value.write_to_s3.side_effect = ApplicationError( 'Some error', 400) result = service.update_historical_cache() self.assertEqual( result, {'result': 'Failed to write cache, please check logs'})
def manage_licence_agreement(data): try: user = UserDetails.get_user_details_by_id(data['user_details_id']) if not user: app.logger.error("No user found for id {}".format( data['user_details_id'])) raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=data['user_details_id']), http_code=404) # check to see if user already has this type of licence ldap_update_needed = True licence_data = _extract_rows( Licence.get_licences_by_dataset_name(data['licence_id'])) for rows in licence_data: user_licence = UserTermsLink.get_user_terms_by_licence_name( user.user_details_id, rows['licence_id']) if user_licence: app.logger.info( 'User {} already has the role {} so not updating ldap...'. format(user.user_details_id, data['licence_id'])) ldap_update_needed = False stored_licence_id = data['licence_id'] if _check_freemium(data['licence_id']): data['licence_id'] += '_direct' licence = UserTermsLink(data) db.session.add(licence) if ldap_update_needed: app.logger.info( 'User {} does not have the role {} so update ldap...'.format( user.user_details_id, stored_licence_id)) _handle_ldap_group(stored_licence_id, user.ldap_id, True) db.session.commit() data['link_id'] = licence.user_terms_link_id return data except Exception as e: app.logger.error( 'Failed to manage licence for user {} with error - {}'.format( data['user_details_id'], str(e))) db.session.rollback() db.session.close() raise ApplicationError(*errors.get('ulapd_api', 'LICENCE_AGREE_ERROR', filler=e), http_code=400)
def get_current_timestamp(): try: conn = psycopg2.connect(current_app.config['SQLALCHEMY_DATABASE_URI']) cur = conn.cursor() cur.execute("SELECT CURRENT_TIMESTAMP;") result = cur.fetchone() cur.close() conn.close() return result[0] except psycopg2.DataError as e: raise ApplicationError( 'Input data error: ' + str(e), 'DB', http_code=400) except (psycopg2.OperationalError, psycopg2.ProgrammingError) as e: raise ApplicationError( 'Database error: ' + str(e), 'DB', http_code=400)
def create_new_user(user_data): try: account = AccountAPI() verification = VerificationAPI() app.logger.info('Creating user in ldap for {}'.format( user_data['email'])) response = account.create(user_data) user_data['ldap_id'] = response['user_id'] user_data = _process_new_user_data(user_data) app.logger.info('Adding user {} to the ulapd database...'.format( user_data['email'])) new_user_details = UserDetails(user_data) db.session.add(new_user_details) db.session.commit() user_data['user_details_id'] = new_user_details.user_details_id if user_data['contactable']: app.logger.info( 'Inserting the contact preferences for {}...'.format( user_data['email'])) for preference in user_data['contact_preferences']: contact = { 'user_details_id': user_data['user_details_id'], 'contact_type': preference } contact_preference = Contact(contact) db.session.add(contact_preference) db.session.commit() app.logger.info( 'Finished adding user {} to the ulapd database...'.format( user_data['email'])) # Add the user details to verification database for DST app.logger.info('Adding user {} to verification db...'.format( user_data['email'])) verification.create(user_data) # Call to account-api to activate or acknowledge user is_uk_org = 'organisation-uk' in user_data['user_type'] if is_uk_org: app.logger.info('Acknowledging user') account.acknowledge(user_data['ldap_id']) else: app.logger.info('Activating user') account.activate(user_data['ldap_id']) db.session.close() return user_data except Exception as e: app.logger.error('Failed to create user with error - {}'.format( str(e))) db.session.rollback() _delete_user_data(account, user_data) db.session.close() raise ApplicationError(*errors.get('ulapd_api', 'CREATE_USER_ERROR', filler=e), http_code=400)
def get_dataset_history(name): dataset = Dataset.get_dataset_by_name(name) if dataset: return _metadata_extend_history(dataset.as_dict()) else: raise ApplicationError(*errors.get('ulapd_api', 'DATASET_NOT_FOUND', filler=name), http_code=404)
def update_api_key(user_id): try: user = UserDetails.get_user_details_by_id(user_id) if user: user.api_key = _create_api_key() db.session.commit() return get_user_details(user_id) else: raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_id), http_code=404) except Exception as e: raise ApplicationError(*errors.get('ulapd_api', 'RESET_API_KEY_ERROR', filler=e), http_code=400)
def get_dataset_activity(user_id): user = UserDetails.get_user_details_by_id(user_id) if user: return _build_user_dataset_activity(user_id) else: app.logger.error("No user found for id {}".format(user_id)) raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_id), http_code=404)
def get(self, ldap_id): url = '{0}/{1}/users?id={2}'.format(self.url, self.version, ldap_id) headers = { "Accept": "application/json" } try: response = g.requests.get(url, headers=headers, timeout=self.timeout) response.raise_for_status() except requests.exceptions.HTTPError as error: current_app.logger.error('Encountered non 2xx http code from account_api for retrieving user details') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR", filler=str(error))) except requests.exceptions.ConnectionError as error: current_app.logger.error('Encountered an error connecting to account_api for retrieving user details') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_CONN_ERROR", filler=str(error))) except requests.exceptions.Timeout as error: current_app.logger.error('Encountered a timeout when writing to account_api for retrieving user details') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_TIMEOUT", filler=str(error))) else: return response.json()
def test_update_groups_for_ldap_error(self, mock_account): error = ApplicationError( *errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR")) mock_account.return_value.update_groups.side_effect = error with app.app_context() as ac: update_groups_retry = current_app.config["UPDATE_GROUPS_RETRY"] ac.g.trace_id = None update_groups_for_ldap('112-122', {'nps': True}) self.assertEqual(mock_account.return_value.update_groups.call_count, int(update_groups_retry))
def test_get_dataset_by_name_error(self, mock_service): mock_service.get_dataset_by_name.side_effect = ApplicationError( 'some error', 500) response = self.app.get('/v1/datasets/test', headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to get dataset: test - error: some error'})
def test_get_activity_error(self, mock_service): mock_service.get_user_activity_list.side_effect = ApplicationError( 'some error', 500) response = self.app.get('/v1/activities/1', headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to get user activity: 1 - error: some error'})
def get_user_details(user_id): user_details = UserDetails.get_user_details_by_id(user_id) if user_details: result = user_details.as_dict() else: app.logger.error("User '{}' not found".format(user_id)) raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_id), http_code=404) return result
def get_user_type(type_id): user_type = UserType.get_user_type_by_id(type_id) if user_type: result = user_type.as_dict() else: app.logger.error("User type '{}' not found".format(type_id)) raise ApplicationError(*errors.get('ulapd_api', 'USER_TYPE_NOT_FOUND', filler=type_id), http_code=404) return result
def test_historical_cache_error(self, mock_service): mock_service.update_historical_cache.side_effect = ApplicationError( 'some error', 500) response = self.app.put('/v1/datasets/historical_cache', headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to update historical cache: some error '})
def test_add_activity_error(self, mock_service): mock_service.create_licence.side_effect = ApplicationError( 'some error', 500) response = self.app.post('/v1/licence', json={"licence_id": "ccod"}, headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to create licence ccod - error: some error'})
def test_create_dataset_error(self, mock_service): mock_service.create_dataset.side_effect = ApplicationError( 'some error', 500) response = self.app.post('/v1/datasets', json={"name": "aaaa"}, headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to create dataset: aaaa - error: some error'})
def test_add_activity_error(self, mock_service): mock_service.add_user_activity.side_effect = ApplicationError( 'some error', 500) response = self.app.post('/v1/activities', json={"foo": "bar"}, headers=self.headers) self.assertEqual(500, response.status_code) response_body = response.get_json() self.assertEqual( response_body, {'error': 'Failed to add activity - error: some error'})
def handle_role(self, data): """Add or remove role for user.""" url = '{0}/{1}/users/handle_role'.format(self.url, self.version) headers = { "Content-Type": "application/json", "Accept": "application/json" } try: response = g.requests.post(url, json=data, headers=headers, timeout=self.timeout) response.raise_for_status() except requests.exceptions.HTTPError as error: current_app.logger.error('Encountered non 2xx http code from account_api for adding a role') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR", filler=str(error))) except requests.exceptions.ConnectionError as error: current_app.logger.error('Encountered an error connecting to account_api for adding a role') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_CONN_ERROR", filler=str(error))) except requests.exceptions.Timeout as error: current_app.logger.error('Encountered a timeout when writing to account_api adding a role') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_TIMEOUT", filler=str(error))) else: app.logger.info("Added role for user {}".format(data['ldap_id'])) return {'message': 'success'}
def activate(self, ldap_id): """Activate user.""" url = '{0}/{1}/users/{2}/activate'.format(self.url, self.version, ldap_id) headers = { "Content-Type": "application/json", "Accept": "application/json" } try: response = g.requests.post(url, headers=headers, timeout=self.timeout) response.raise_for_status() except requests.exceptions.HTTPError as error: current_app.logger.error('Encountered non 2xx http code from account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_HTTP_ERROR", filler=str(error))) except requests.exceptions.ConnectionError as error: current_app.logger.error('Encountered an error connecting to account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_CONN_ERROR", filler=str(error))) except requests.exceptions.Timeout as error: current_app.logger.error('Encountered a timeout when writing to account_api for user activation') raise ApplicationError(*errors.get("ulapd_api", "ACCOUNT_API_TIMEOUT", filler=str(error))) else: app.logger.info("Activated user {}".format(ldap_id)) return {'message': 'activated'}
def run_and_handle(*args, **kwargs): try: return func(*args, **kwargs) except SQLAlchemyError as e: error_code = 500 if is_get else 422 raise ApplicationError(*errors.get('ulapd_api', 'SQLALCHEMY_ERROR', filler=e), http_code=error_code) except ApplicationError as error: raise error finally: if not is_get: db.session.rollback() db.session.close()
def get_users_dataset_access(user_id): user = UserDetails.get_user_details_by_id(user_id) if user: datasets = Dataset.get_all() dataset_access = [] for row in datasets: if row.type != 'open': dataset_dict = { 'id': row.dataset_id, 'name': row.name, 'title': row.title, 'type': row.type } licence_names = _extract_rows( Licence.get_licences_by_dataset_name(row.name)) licence_dict = {} for licence_rows in licence_names: licence = get_licence_agreement(user_id, licence_rows['licence_id']) licence_dict[licence_rows['licence_id']] = { 'title': licence_rows['title'], 'agreed': licence['valid_licence'] } dataset_dict['licences'] = licence_dict dataset_access.append(dataset_dict) dataset_access = _sort_out_sample(dataset_access) licenced_datasets = [ d for d in dataset_access if d['type'] == 'licenced' ] non_licenced_datasets = [ d for d in dataset_access if d['type'] != 'licenced' ] full_access = non_licenced_datasets full_access.append(_sort_out_licenced_datasets(licenced_datasets)) return full_access else: app.logger.error("No user found for id {}".format(user_id)) raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=user_id), http_code=404)
def update_contact_preference(user_data): user = UserDetails.get_user_details_by_id(user_data['user_id']) if user: app.logger.info('Deleting contact preferences for user {}'.format( user_data['user_id'])) Contact.delete_contact_preferences_for_user(user_data['user_id']) for contacts in user_data['contact_preferences']: contact = { 'user_details_id': user_data['user_id'], 'contact_type': contacts } contact_preference = Contact(contact) db.session.add(contact_preference) user.contactable = user_data['contactable'] db.session.commit() user_details = user.as_dict() user_details['contact_preferences'] = user_data['contact_preferences'] return user_details else: raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', user_data['user_id']), http_code=404)
def test_update_groups_app_error(self, mock_account, mock_app): error = ('ulapd_api', 'ACCOUNT_API_HTTP_ERROR') mock_account.side_effect = ApplicationError(*errors.get(*error)) update_groups_for_ldap('112-122', {'nps': True}) mock_app.logger.error.assert_called_once()
def manage_multi_licence_agreement(data): try: user = UserDetails.get_user_details_by_id(data['user_details_id']) if not user: app.logger.error("No user found for id {}".format( data['user_details_id'])) raise ApplicationError(*errors.get('ulapd_api', 'USER_NOT_FOUND', filler=data['user_details_id']), http_code=404) current_licences = _extract_rows( UserTermsLink.get_user_terms_by_user_id(data['user_details_id'])) current_list = [d['licence_id'] for d in current_licences] all_licences = Licence.get_all_licences() licence_dict = {} for rows in all_licences: licence_dict[rows.licence_name] = rows.dataset_name groups = {} for row in data['licences']: if row['licence_id'] not in current_list and row['agreed']: app.logger.info('Adding licence {} to db and ldap'.format( row['licence_id'])) role = licence_dict[row['licence_id']] groups[role] = row['agreed'] new_user_licence = UserTermsLink({ 'user_details_id': user.user_details_id, 'licence_id': row['licence_id'] }) db.session.add(new_user_licence) elif row['licence_id'] in current_list and not row['agreed']: app.logger.info('Removing licence {} from db and ldap'.format( row['licence_id'])) role = licence_dict[row['licence_id']] groups[role] = row['agreed'] UserTermsLink.delete_user_licence_agreement( user.user_details_id, row['licence_id']) else: app.logger.info('There is no change for licence {}'.format( row['licence_id'])) # sort out freemium res_covs = [ d for d in data['licences'] if 'res_cov' in d['licence_id'] ] groups = _handle_ldap_freemium_updates('res_cov', res_covs, groups, current_list) if bool(groups): app.logger.info( 'Sending these groups - {}, for ldap update for user {}'. format(groups, user.user_details_id)) update_groups_for_ldap(user.ldap_id, groups) else: app.logger.info('No groups to update in ldap for user {}'.format( user.user_details_id)) db.session.commit() return groups except Exception as e: app.logger.error( 'Failed to manage multi licences for user {} with error - {}'. format(data['user_details_id'], str(e))) db.session.rollback() db.session.close() raise ApplicationError(*errors.get('ulapd_api', 'LICENCE_AGREE_ERROR', filler=e), http_code=400)