예제 #1
0
    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'
예제 #2
0
    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")
예제 #3
0
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')))
예제 #4
0
    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
예제 #5
0
    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"]
예제 #6
0
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)
    )
예제 #7
0
    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"
            )