def it_does_not_log_in_email_in_wrong_domain(self, client, mocker): mock_oauth2session(mocker, url_for('main.callback'), 'test@invalid_domain.com') session_dict = { 'oauth_state': 'state' } mock_sessions(mocker, session_dict) class MockResponse: status_code = 400 def json(self): return {'message': 'test@invalid_domain.com not in correct domain'} class MockException: response = MockResponse() e = HTTPError.create(MockException()) mocker.patch('app.main.views.os.environ', {}) mocker.patch('app.main.views.api_client.get_user', return_value=None) mocker.patch('app.main.views.api_client.create_user', side_effect=e) response = client.get(url_for( 'main.callback' )) assert response.status_code == 200 page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') err_message = page.select_one('.col-sm') assert err_message.text.strip() == 'test@invalid_domain.com not in correct domain, '\ 'please contact the website administrators to get an email in correct domain'
def request(self, method, url, data=None, params=None): current_app.logger.info("API request {} {}".format(method, url)) if not session.get("access_token"): self.set_access_token() payload = json.dumps(data) url = urljoin(str(self.base_url), str(url)) start_time = time.time() try: response = requests.request(method, url, data=payload, params=params, headers={ 'Authorization': 'Bearer {}'.format( session["access_token"]) }, timeout=30) if response.status_code == 404: current_app.logger.warn('404', response.json()['message']) return if response.status_code == 401 and response.json( )['message'] == "Signature expired": self.set_access_token() response = requests.request(method, url, data=payload, params=params, headers={ 'Authorization': 'Bearer {}'.format( session["access_token"]) }) response.raise_for_status() except requests.RequestException as e: api_error = HTTPError.create(e) current_app.logger.error( "API {} request on {} failed with {} '{}'".format( method, url, api_error.status_code, api_error.message)) raise api_error finally: elapsed_time = time.time() - start_time current_app.logger.debug( "API {} request on {} finished in {}".format( method, url, elapsed_time)) try: if response.status_code == 204: return return response.json() except ValueError: raise InvalidResponse( response, message="No JSON response object could be decoded")
def callback(): os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = current_app.config[ 'OAUTHLIB_INSECURE_TRANSPORT'] google = OAuth2Session( current_app.config['GOOGLE_OAUTH2_CLIENT_ID'], state=session.get('oauth_state'), redirect_uri=current_app.config['GOOGLE_OAUTH2_REDIRECT_URI']) token = google.fetch_token( token_url, client_secret=current_app.config['GOOGLE_OAUTH2_CLIENT_SECRET'], authorization_response=request.url) auth_google = OAuth2Session(current_app.config['GOOGLE_OAUTH2_CLIENT_ID'], token=token) profile = auth_google.get(user_info_url).json() user = api_client.get_user(profile['email']) if not user: try: api_client.create_user(profile) if 'error' in session: error = session.pop('error') raise HTTPError(error) return render_template( 'views/admin/admin_interstitial.html', message="{} has registered as a user, " "please wait until the web administrators setup your permissions" .format(profile['email'])) except HTTPError as e: if 'not in correct domain' in e.message: return render_template( 'views/admin/admin_interstitial.html', message= '{}, please contact the website administrators to get an email in correct domain' .format(e.message)) raise elif not user.get('access_area'): return render_template( 'views/admin/admin_interstitial.html', message= 'Waiting for permissions to be granted for {} by website administrators' .format(profile['email'])) else: session['user'] = user session['oauth_token'] = token # store profile in session to use later session['user_profile'] = profile return redirect(session.pop('target_url', url_for('.admin')))
def set_access_token(self): if not self.base_url: current_app.logger.info("No API URL") return False send_ga_event('frontend', 'visit', request.remote_addr) current_app.logger.info("set access token") auth_payload = { "username": self.client_id, "password": self.secret } auth_url = urljoin(str(self.base_url), "auth/login") try: auth_response = requests.request( "POST", auth_url, data=json.dumps(auth_payload), headers={'Content-Type': 'application/json'}, allow_redirects=False, timeout=60 ) auth_response.raise_for_status() except (requests.RequestException, requests.Timeout) as e: api_error = HTTPError.create(e) current_app.logger.error( "Set access token: {} failed with {} '{}' - '{}'".format( auth_url, api_error.status_code, api_error.message, e.message ) ) # raise api_error session["error"] = u"Error connecting to API: " +\ str(e).replace(current_app.config['API_BASE_URL'], 'https://API') return False session["access_token"] = auth_response.json()["access_token"] return True
def set_access_token(self): current_app.logger.info("set access token") auth_payload = {"username": self.client_id, "password": self.secret} try: auth_url = urljoin(str(self.base_url), "auth/login") auth_response = requests.request( "POST", auth_url, data=json.dumps(auth_payload), headers={'Content-Type': 'application/json'}, allow_redirects=False) auth_response.raise_for_status() except requests.RequestException as e: api_error = HTTPError.create(e) current_app.logger.error( "Set access token: {} failed with {} '{}'".format( auth_url, api_error.status_code, api_error.message)) raise api_error session["access_token"] = auth_response.json()["access_token"]
def admin_events(selected_event_id=None, api_message=None): events = api_client.get_limited_events() event_types = api_client.get_event_types() speakers = api_client.get_speakers() venues = api_client.get_venues() session['events'] = events form = EventForm() temp_event = None errors = reject_reasons = [] form.set_events_form(events, event_types, speakers, venues) if form.validate_on_submit(): if form.image_filename.data: filename = form.image_filename.data.filename else: filename = form.existing_image_filename.data reject_reasons = json.loads(form.reject_reasons_json.data) if form.reject_reason.data: reject_reasons.append( { 'reason': form.reject_reason.data, 'created_by': session['user']['id'] } ) event = { 'event_id': form.events.data, 'event_type_id': form.event_type.data, 'title': form.title.data, 'sub_title': form.sub_title.data, 'description': form.description.data, 'image_filename': filename, 'fee': int(form.fee.data) if form.fee.data else 0, 'conc_fee': int(form.conc_fee.data) if form.conc_fee.data else 0, 'multi_day_fee': int(form.multi_day_fee.data) if form.multi_day_fee.data else 0, 'multi_day_conc_fee': int(form.multi_day_conc_fee.data) if form.multi_day_conc_fee.data else 0, 'venue_id': form.venue.data, 'event_dates': form.event_dates.data, 'start_time': form.start_time.data, 'end_time': form.end_time.data, 'event_state': form.submit_type.data, 'reject_reasons': reject_reasons, 'remote_access': form.remote_access.data, 'remote_pw': form.remote_pw.data, 'show_banner_text': form.show_banner_text.data } adjusted_event = event.copy() from html import escape adjusted_event['description'] = escape(event['description']) adjusted_event['event_dates'] = json.loads(str(event['event_dates'])) file_request = request.files.get('image_filename') if file_request: file_data = file_request.read() file_data_encoded = base64.b64encode(file_data) file_data_encoded = base64.b64encode(file_data_encoded).decode('utf-8') _file_size = size_from_b64(str(file_data_encoded)) if _file_size > current_app.config['MAX_IMAGE_SIZE']: _file_size_mb = round(_file_size/(1024*1024), 1) _max_size_mb = current_app.config['MAX_IMAGE_SIZE']/(1024*1024) errors.append("Image {} file size ({} mb) is larger than max ({} mb)".format( file_request.filename, _file_size_mb, _max_size_mb)) else: adjusted_event['image_data'] = file_data_encoded if not errors: # remove empty values for key, value in event.items(): if value != 0 and not value: del adjusted_event[key] try: message = None if event.get('event_id'): response = api_client.update_event(event['event_id'], adjusted_event) message = 'event updated' if event['event_state'] != "approved" and not form.cache_switch.data: Cache.set_review_entity('get_events_in_future', event.get('event_id')) else: Cache.delete_review_entity('get_events_in_future', event.get('event_id')) update_cache( func=api_client.get_events_in_future_from_db, decorator=only_show_approved_events, approved_only=True) else: # do not need to update the cache here as an event is never in approved state when first created response = api_client.add_event(adjusted_event) if 'error' in session: raise HTTPError(response, message=session.pop('error')) return redirect(url_for('main.admin_events', selected_event_id=response.get('id'), api_message=message)) except HTTPError as e: current_app.logger.error(e) temp_event = json.dumps(event) if "message" in e.message: errors = e.message['message'] else: errors = json.dumps(e.message) return render_template( 'views/admin/events.html', form=form, images_url=current_app.config['IMAGES_URL'], selected_event_id=selected_event_id, message=api_message, temp_event=temp_event, errors=json.dumps(errors) )
def request(self, method, url, data=None, params=None): current_app.logger.info("API request {} {}".format(method, url)) # don't set access token for API call to info set_access_token = url != '' if not self.base_url: current_app.logger.info("No API URL") return [] if set_access_token and "access_token" not in session: if not self.set_access_token(): return [] payload = json.dumps(data) url = urljoin(str(self.base_url), str(url)) start_time = time.time() try: response = requests.request( method, url, data=payload, params=params, headers={'Authorization': 'Bearer {}'.format(session["access_token"])} if set_access_token else {}, timeout=30 ) if response.status_code == 404: current_app.logger.warn('%r: 404 - %r', url, response.json()['message']) session['error'] = { 'code': 404, 'response': {'error': response.json()} } return if response.status_code == 401 and response.json()['message'] == "Signature expired": self.set_access_token() response = requests.request( method, url, data=payload, params=params, headers={'Authorization': 'Bearer {}'.format(session["access_token"])} ) response.raise_for_status() except requests.RequestException as e: api_error = HTTPError.create(e) current_app.logger.error( "API {} request on {} failed with {} '{}'".format( method, url, api_error.status_code, api_error.message ) ) # raise api_error session['error'] = { 'code': api_error.status_code, 'message': api_error.message or response.json() } return [] finally: elapsed_time = time.time() - start_time current_app.logger.debug("API {} request on {} finished in {}".format(method, url, elapsed_time)) try: if response.status_code == 204: return return response.json() except ValueError: raise InvalidResponse( response, message="No JSON response object could be decoded" )