def test_signal_when_feature_is_missing(self): expected_feature = 'newfeature' @feature_flags.missing_feature.connect def signal_handler(obj, feature): app.config[FLAG_CONFIG][feature] = True assert feature == expected_feature, u'Signal received wrong feature %s' % feature with self.app.test_request_context('/'): feature_flags.is_active(expected_feature) assert app.config[FLAG_CONFIG][expected_feature], u'Missing feature handler was not called'
def test_signal_when_feature_is_missing(self): expected_feature = 'newfeature' @feature_flags.missing_feature.connect def signal_handler(obj, feature): app.config[FLAG_CONFIG][feature] = True assert feature == expected_feature, u'Signal received wrong feature %s' % feature with self.app.test_request_context('/'): feature_flags.is_active(expected_feature) assert app.config[FLAG_CONFIG][ expected_feature], u'Missing feature handler was not called'
def test_deferred_initialization_works(self): test_app = Flask(__name__) test_app.config[FLAG_CONFIG] = {FEATURE_NAME: True} feature_flagger = feature_flags.FeatureFlag() feature_flagger.init_app(test_app) with test_app.test_request_context("/"): # Test a couple basic cases to make sure we're actually exercising the code # when we make these calls self.assertTrue(feature_flags.is_active(FEATURE_NAME)) self.assertFalse(feature_flags.is_active("DOES_NOT_EXIST"))
def _record_audit_information(response): """Update the audit db table to record the current request. :param response: the response to modify, of type response_class() :return: the same response, unmodified. """ if not audit_method.is_active(request.method): current_app.logger.debug("Skipping audit record for method '%s'" % request.method) return response else: current_app.logger.debug("Filling audit record for method '%s'" % request.method) from app import db try: record = Auditing() # Add any exception that may have occurred. record.exception_msg = str(flask_g.get("exception_msg")) # Add the correlation ID. record.correlation_id = get_correlation_id() # Add referring service record.referring_service = flask_g.get("referring_service") # Add request data to the record _fill_in_request(record) # Add response data to the record _fill_in_response(record, response) # The current session (db.session) may be in a broken state, so we're better off # creating a new session. Luckily, sessions carry their factory around. session = db.session.session_factory() session.add(record) session.commit() except Exception: current_app.logger.exception("Failed to record auditing information") return response
def test_buyer_pages_ok_if_logged_in_as_buyer(self, render_component): props = { "team": { "currentUserName": "******", "teamName": "My Team name", "members": [], "teamBriefs": { "all": [], "draft": [], "live": [], "closed": [] }, "briefs": { "all": [], "draft": [], "live": [], "closed": [] } } } render_component.return_value.get_props.return_value = props with self.app.app_context(): self.login_as_buyer() res = self.client.get(self.expand_path('/buyers')) page_text = res.get_data(as_text=True) assert res.status_code == 200 assert 'private' in res.headers['Cache-Control'] if feature.is_active('TEAM_VIEW'): assert 'My Team' in page_text assert 'My Team name' in page_text
def run_async(function, deamon=True, **kwargs): app = current_app._get_current_object() if feature.is_active(FEATURE_MULTITHREADING): kwargs = copy(kwargs) kwargs["app"] = app threading.Thread(target=function, kwargs=kwargs, daemon=deamon).start() else: function(app=app, **kwargs)
def run(self, threshold=0.4): self.log.info(f'Starting new voting. vacancies = {self.vacancies}') self.log.debug( f'candidates = {sorted(self.candidates, key=attrgetter("id"))}') if feature.is_active(FEATURE_STV_REJECTION): self.reject_candidates(threshold) while len(self.candidates) > 0 and len(self.elected) < self.vacancies: self.round() results = { candidate: candidate.score[-1][0] for candidate in self.candidates } self.discarded += [ candidate for candidate in sorted(results, key=results.get) ] self.log.info(f'Voting finished') self.log.info(f'elected = {self.elected}') self.log.info(f'discarded = {self.discarded}') if feature.is_active(FEATURE_STV_REJECTION): self.log.info(f'rejected = {self.rejected}') return self.elected, self.discarded, self.rejected
def get_role_types(): logger = logging.getLogger(__name__) conn = connect.get_connection() cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) cur.execute("SELECT displayname, id " "FROM codesystems " "WHERE name = 'OrganisationRole' " "ORDER BY displayname;") rows = cur.fetchall() result = [] for row in rows: role_code = row['id'] role_display_name = row['displayname'] link_self_href = str.format('{0}/role-types/{1}', app.config['APP_HOSTNAME'], role_code) link_search_primary_role_code_href = str.format('{0}/organisations?primaryRoleCode={1}', app.config['APP_HOSTNAME'], role_code) link_search_role_code_href = str.format('{0}/organisations?roleCode={1}', app.config['APP_HOSTNAME'], role_code) result_data = { 'name': role_display_name, 'code': role_code, 'links': [{ 'rel': 'self', 'href': link_self_href }, { 'rel': 'organisations.searchByRoleCode', 'href': link_search_role_code_href }] } if not feature.is_active('SuppressPrimaryRoleSearchLink'): result_data['links'].append({ 'rel': 'organisations.searchByPrimaryRoleCode', 'href': link_search_primary_role_code_href }) result.append(result_data) logger.debug("Returning: {result}".format(result=result)) return result
def get_briefs(self): if not self.validate(): raise ValueError("Invalid form") statuses = self.status.data or tuple(id for id, label in self.status.choices) lots = self.lot.data or tuple(id for id, label in self.lot.choices) # disable framework filtering when digital marketplace framework is live kwargs = {} if flask_featureflags.is_active('DM_FRAMEWORK') else {"framework": self._framework_slug} return self._data_api_client.find_briefs( status=",".join(statuses), lot=",".join(lots), page=self.page.data, per_page=75, human=True, **kwargs )
def updateGlobalSession(): ''' updates the Marvin config with the global Flask session ''' # check if mpl versions in session if 'versions' not in current_session: setGlobalSession() elif 'drpver' not in current_session or \ 'dapver' not in current_session: set_session_versions(config.release) elif 'release' not in current_session: current_session['release'] = config.release elif 'release' in current_session: if current_session['release'] not in config._allowed_releases: current_session['release'] = config.release # reset the session versions if on public site if feature.is_active('public'): current_session['versions'] = update_allowed()
def get_briefs(self): if not self.validate(): raise ValueError("Invalid form") statuses = self.status.data or tuple( id for id, label in self.status.choices) lots = self.lot.data or tuple(id for id, label in self.lot.choices) # disable framework filtering when digital marketplace framework is live kwargs = {} if flask_featureflags.is_active('DM_FRAMEWORK') else { "framework": self._framework_slug } return self._data_api_client.find_briefs(status=",".join(statuses), lot=",".join(lots), page=self.page.data, per_page=75, human=True, **kwargs)
def get_role_type_by_id(role_id): sql = "SELECT displayname, id " \ "FROM codesystems " \ "WHERE name = 'OrganisationRole' " \ "AND id = UPPER(%s);" data = (role_id,) cur = connect.get_cursor() cur.execute(sql, data) returned_row = cur.fetchone() role_code = returned_row['id'] role_display_name = returned_row['displayname'] link_self_href = str.format('{0}/role-types/{1}', app.config['APP_HOSTNAME'], role_code) link_search_primary_role_code_href = str.format('{0}/organisations?primaryRoleCode={1}', app.config['APP_HOSTNAME'], role_code) link_search_role_code_href = str.format('{0}/organisations?roleCode={1}', app.config['APP_HOSTNAME'], role_code) result = { 'name': role_display_name, 'code': role_code, 'links': [{ 'rel': 'self', 'href': link_self_href }, { 'rel': 'searchOrganisationsWithThisRole', 'href': link_search_role_code_href }] } if not feature.is_active('SuppressPrimaryRoleSearchLink'): result['links'].append({ 'rel': 'organisations.searchByPrimaryRoleCode', 'href': link_search_primary_role_code_href }) return result
def redirect_logged_in_user(next_url=None): site_url_prefix = current_app.config['URL_PREFIX'] if not site_url_prefix: site_url_prefix = '/' if current_user.is_authenticated: if next_url and next_url.startswith(site_url_prefix): return redirect(next_url) if current_user.role == 'buyer': return redirect(url_for('buyers.buyer_dashboard')) if current_user.role == 'supplier': if feature.is_active('DM_FRAMEWORK'): return redirect(url_for('.list_opportunities', framework_slug='digital-marketplace')) return redirect(url_for('.list_opportunities', framework_slug='digital-service-professionals')) if current_user.role == 'applicant': return redirect('/sellers/application') return redirect(url_for('.index'))
def decorated(*args, **kwargs): try: return f(*args, **kwargs) except Exception as ex: flask_g.exception_msg = traceback.format_exc() current_app.logger.exception(ex) if isinstance(ex, NotFound): return {'Error': ex.args[0]}, 404 if isinstance(ex, BadRequest): return {'Error': ex.description}, 400 return { 'Error': ex.args[0] if feature.is_active('propagates_exception') else 'Internal Server Error' }, 500
def register(): if current_user.is_authenticated: return redirect(url_for('base.index')) form = RegisterForm() if form.validate_on_submit(): fellow = lada.fellow.register(email=form.email.data, password=form.password.data, name=form.name.data, surname=form.surname.data, studentid=form.studentid.data, newsletter=news_flags[NEWS_ALL]) log.info(f"New fellow registered: {fellow}") if feature.is_active(FEATURE_EMAIL_VERIFICATION): send_verification_email(fellow) flash( 'Registration successful. Please check your e-mail, including SPAM, for verification e-mail.' ) else: fellow.set_verified(True) flash('Registration successful.') return redirect(url_for('fellow.login')) return render_template('fellow/register.html', form=form)
def buyer_overview(): email_domain = current_user.email_address.split('@')[-1] teammembers_response = data_api_client.req.teammembers(email_domain).get() teammembers = list(sorted(teammembers_response['teammembers'], key=lambda tm: tm['name'])) rendered_component = render_component( 'bundles/BuyerDashboard/BuyerDashboardWidget.js', { 'teammembers': teammembers, 'meta': { 'domain': email_domain, 'teamname': teammembers_response['teamname'] }, 'flag': feature.is_active('TEAM_VIEW') } ) return render_template( '_react.html', page_title="Dashboard", component=rendered_component, )
def test_flag_inactive(self): self.assertFalse(feature_flags.is_active("INACTIVE"))
def test_flag_not_found(self): self.assertFalse(feature_flags.is_active("NOT_FOUND"))
def view_based_feature_flag(): if feature_flags.is_active(FEATURE_NAME): return FEATURE_IS_ON else: return FEATURE_IS_OFF
def test_flags(self): with self.flask.app_context(): assert flask_featureflags.is_active('YES') assert not flask_featureflags.is_active('NO')
def test_checking_is_active_outside_request_context_returns_false(self): self.assertFalse(feature_flags.is_active("BOGUS_FEATURE_FLAG"))
def test_flag_not_found(self): self.assertFalse(feature_flags.is_active('not_found'))
def test_flag_active(self): self.assertTrue(feature_flags.is_active("ACTIVE"))
def buyer_dashboard(view=None): if feature.is_active('TEAM_VIEW'): current_user_name = current_user.name email_domain = current_user.email_address.split('@')[-1] teammembers_response = data_api_client.req.teammembers(email_domain).get() teamname = teammembers_response['teamname'] teammembers = list(sorted(teammembers_response['teammembers'], key=lambda tm: tm['name'])) team_briefs = data_api_client.req.briefs().teammembers(email_domain).get() # team_draft_briefs = add_unanswered_counts_to_briefs( # [brief for brief in team_briefs if brief['status'] == 'draft'], content_loader) team_draft_briefs = [] team_live_briefs = [brief for brief in team_briefs if brief['status'] == 'live'] team_closed_briefs = [brief for brief in team_briefs if brief['status'] == 'closed'] user_briefs = data_api_client.find_briefs(current_user.id).get('briefs', []) draft_briefs = add_unanswered_counts_to_briefs( [brief for brief in user_briefs if brief['status'] == 'draft'], content_loader) live_briefs = [brief for brief in user_briefs if brief['status'] == 'live'] closed_briefs = [brief for brief in user_briefs if brief['status'] == 'closed'] props = { "flag": feature.is_active('TEAM_VIEW'), "team": { "currentUserName": current_user_name, "teamName": teamname, "members": teammembers, "teamBriefs": { "draft": team_draft_briefs, "live": team_live_briefs, "closed": team_closed_briefs }, "briefs": { "draft": draft_briefs, "live": live_briefs, "closed": closed_briefs } } } rendered_component = render_component( 'bundles/BuyerDashboard/BuyerDashboardWidget.js', props ) return render_template( '_react.html', page_title="Dashboard", component=rendered_component, ) else: def get_teamname(): email_domain = current_user.email_address.split('@')[-1] teammembers_response = data_api_client.req.teammembers(email_domain).get() teammembers = list(sorted(teammembers_response['teammembers'], key=lambda tm: tm['name'])) return teammembers_response['teamname'] user_briefs = data_api_client.find_briefs(current_user.id).get('briefs', []) draft_briefs = add_unanswered_counts_to_briefs([brief for brief in user_briefs if brief['status'] == 'draft'], content_loader) live_briefs = [brief for brief in user_briefs if brief['status'] == 'live'] closed_briefs = [brief for brief in user_briefs if brief['status'] == 'closed'] return render_template( 'buyers/dashboard-briefs.html', draft_briefs=draft_briefs, live_briefs=live_briefs, closed_briefs=closed_briefs, teamname=get_teamname() )
def test_flag_active(self): self.assertTrue(feature_flags.is_active('active'))
def contract_review(framework_slug, agreement_id): framework = get_framework(data_api_client, framework_slug, allowed_statuses=['standstill', 'live']) # if there's no frameworkAgreementVersion key it means we're pre-G-Cloud 8 and shouldn't be using this route if not framework.get('frameworkAgreementVersion'): abort(404) supplier_framework = return_supplier_framework_info_if_on_framework_or_abort( data_api_client, framework_slug) agreement = data_api_client.get_framework_agreement( agreement_id)['agreement'] check_agreement_is_related_to_supplier_framework_or_abort( agreement, supplier_framework) # if framework agreement doesn't have a name or a role or the agreement file, then 404 if not (agreement.get('signedAgreementDetails') and agreement['signedAgreementDetails'].get('signerName') and agreement['signedAgreementDetails'].get('signerRole') and agreement.get('signedAgreementPath')): abort(404) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) signature_page = agreements_bucket.get_key( agreement['signedAgreementPath']) form = ContractReviewForm() form_errors = None if request.method == 'POST': if form.validate_on_submit(): data_api_client.sign_framework_agreement( agreement_id, current_user.email_address, {'uploaderUserId': current_user.id}) try: email_body = render_template( 'emails/framework_agreement_with_framework_version_returned.html', framework_name=framework['name'], framework_slug=framework['slug'], framework_live_date=content_loader.get_message( framework_slug, 'dates')['framework_live_date'], # noqa ) send_email( returned_agreement_email_recipients(supplier_framework), email_body, current_app.config['DM_MANDRILL_API_KEY'], 'Your {} signature page has been received'.format( framework['name']), current_app.config["DM_GENERIC_NOREPLY_EMAIL"], current_app.config["FRAMEWORK_AGREEMENT_RETURNED_NAME"], ['{}-framework-agreement'.format(framework_slug)], ) except MandrillException as e: current_app.logger.error( "Framework agreement email failed to send. " "error {error} supplier_id {supplier_id} email_hash {email_hash}", extra={ 'error': six.text_type(e), 'supplier_id': current_user.supplier_id, 'email_hash': hash_email(current_user.email_address) }) abort(503, "Framework agreement email failed to send") session.pop('signature_page', None) flash( 'Your framework agreement has been returned to the Crown Commercial Service to be countersigned.', 'success') if feature.is_active('CONTRACT_VARIATION'): # Redirect to contract variation if it has not been signed if (framework.get('variations') and not supplier_framework['agreedVariations']): variation_slug = list(framework['variations'].keys())[0] return redirect( url_for('.view_contract_variation', framework_slug=framework_slug, variation_slug=variation_slug)) return redirect( url_for(".framework_dashboard", framework_slug=framework_slug)) else: form_errors = [{ 'question': form['authorisation'].label.text, 'input_name': 'authorisation' }] form.authorisation.description = u"I have the authority to return this agreement on behalf of {}.".format( supplier_framework['declaration']['nameOfOrganisation']) return render_template( "frameworks/contract_review.html", agreement=agreement, form=form, form_errors=form_errors, framework=framework, signature_page=signature_page, supplier_framework=supplier_framework, ), 400 if form_errors else 200
def test_flag_inactive(self): self.assertFalse(feature_flags.is_active('inactive'))