def accept_invite(token): try: invited_user = InvitedUser.from_token(token) except InviteTokenError as exception: flash(_(str(exception))) return redirect(url_for("main.sign_in")) if not current_user.is_anonymous and current_user.email_address.lower() != invited_user.email_address.lower(): message = Markup( _( "You’re signed in as %(email)s. This invite is for another email address. " + "<a href=%(href)s>Sign out</a> and click the link again to accept this invite.", email=current_user.email_address, href=url_for("main.sign_out", _external=True), ) ) flash(message=message) abort(403) if invited_user.status == "cancelled": service = Service.from_id(invited_user.service) return render_template( "views/cancelled-invitation.html", from_user=invited_user.from_user.name, service_name=service.name, ) if invited_user.status == "accepted": session.pop("invited_user", None) return redirect(url_for("main.service_dashboard", service_id=invited_user.service)) session["invited_user"] = invited_user.serialize() existing_user = User.from_email_address_or_none(invited_user.email_address) if existing_user: invited_user.accept_invite() if existing_user in Users(invited_user.service): return redirect(url_for("main.service_dashboard", service_id=invited_user.service)) else: service = Service.from_id(invited_user.service) # if the service you're being added to can modify auth type, then check if this is relevant if service.has_permission("email_auth") and ( # they have a phone number, we want them to start using it. if they dont have a mobile we just # ignore that option of the invite (existing_user.mobile_number and invited_user.auth_type == "sms_auth") or # we want them to start sending emails. it's always valid, so lets always update invited_user.auth_type == "email_auth" ): existing_user.update(auth_type=invited_user.auth_type) existing_user.add_to_service( service_id=invited_user.service, permissions=invited_user.permissions, folder_permissions=invited_user.folder_permissions, ) return redirect(url_for("main.service_dashboard", service_id=service.id)) else: return redirect(url_for("main.register_from_invite"))
def test_get_template_folders_shows_user_folders_when_user_id_passed_in( app_, mock_get_template_folders, service_one, active_user_with_permissions, mocker ): mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions) service = Service(service_one) result = service.get_template_folders(user=User(active_user_with_permissions)) assert result == [ { 'name': ["Parent 1 - invisible", "1's Visible child"], 'id': mocker.ANY, 'parent_id': None, 'users_with_permission': [active_user_with_permissions['id']] }, { 'name': ["Parent 1 - invisible", ["1's Invisible child", "1's Visible grandchild"]], 'id': mocker.ANY, 'parent_id': None, 'users_with_permission': [active_user_with_permissions['id']] }, { 'name': "Parent 2 - visible", 'id': VIS_PARENT_FOLDER_ID, 'parent_id': None, 'users_with_permission': [active_user_with_permissions['id']] }, ]
def test_get_template_folders_shows_all_folders_when_user_id_not_passed_in( mock_get_template_folders, service_one, active_user_with_permissions, mocker ): mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions) service = Service(service_one) result = service.get_template_folders() assert result == [ { "name": "Invisible folder", "id": mocker.ANY, "parent_id": None, "users_with_permission": [], }, { "name": "Parent 1 - invisible", "id": INV_PARENT_FOLDER_ID, "parent_id": None, "users_with_permission": [], }, { "name": "Parent 2 - visible", "id": VIS_PARENT_FOLDER_ID, "parent_id": None, "users_with_permission": [active_user_with_permissions["id"]], }, ]
def test_get_template_folders_shows_all_folders_when_user_id_not_passed_in( mock_get_template_folders, service_one, active_user_with_permissions, mocker ): mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions) service = Service(service_one) result = service.get_template_folders() assert result == [ { 'name': "Invisible folder", 'id': mocker.ANY, 'parent_id': None, 'users_with_permission': [] }, { 'name': "Parent 1 - invisible", 'id': INV_PARENT_FOLDER_ID, 'parent_id': None, 'users_with_permission': [] }, { 'name': "Parent 2 - visible", 'id': VIS_PARENT_FOLDER_ID, 'parent_id': None, 'users_with_permission': [active_user_with_permissions['id']], } ]
def create(current_user, workspaceId, projectId): """ Create a service. Reuires login """ if request.content_type == 'application/json': post_data = request.get_json(force=True) required_keys = ['serviceType', 'serviceMeta'] if all(name in post_data for name in required_keys): service = Service(serviceType=post_data.get('serviceType'), serviceMeta=post_data.get('serviceMeta'), projectId=projectId, createdBy=current_user.email_id) service.create() # add to project project = Project.get_by_id(projectId) project.services.append(service._id) project.save() # Replcing _id with id service_obj = json.loads(service.to_json()) service_obj['id'] = service_obj['_id'] service_obj.pop('_id', None) return response_with_obj('success', 'Service created successfully', service_obj, 200) else: return response('failed', 'Required data not found in POST body.', 402) return response('failed', 'Content-type must be json', 402)
def choose_template_to_copy( service_id, from_service=None, from_folder=None, ): if from_service: current_user.belongs_to_service_or_403(from_service) service = Service(service_api_client.get_service(from_service)['data']) return render_template( 'views/templates/copy.html', services_templates_and_folders=TemplateList( service, template_folder_id=from_folder, user=current_user), template_folder_path=service.get_template_folder_path(from_folder), from_service=service, search_form=SearchByNameForm(), ) else: return render_template( 'views/templates/copy.html', services_templates_and_folders=TemplateLists(current_user), search_form=SearchByNameForm(), )
def get(current_user, workspaceId, projectId): """ Get a service by service id or project id :return: Http Json response """ serviceId = request.args.get('serviceId') if serviceId: # Get by Service ID service = Service.get_by_id(serviceId) if service: return { 'serviceType': service.serviceType, 'id': service._id, 'createdBy': service.createdBy, 'createdOn': service.createdOn, 'isActive': service.isActive, 'serviceMeta': service.serviceMeta } else: return response('failed', 'service not found', 404) else: # Get by Project ID project = Project.get_by_id(projectId) services = project.services payload = [] for service_id in services: service = Service.get_by_id(service_id) payload.append({"id": service_id, "serviceType": service.serviceType, "isActive": service.isActive, "serviceMeta": service.serviceMeta}) return {'services': payload}
def test_organisation_type_when_services_organisation_has_no_org_type(mocker, service_one): service = Service(service_one) service._dict['organisation_id'] = ORGANISATION_ID org = organisation_json(organisation_type=None) mocker.patch('app.organisations_client.get_organisation', return_value=org) assert not org['organisation_type'] assert service.organisation_type == 'central'
def test_organisation_type_when_service_and_its_org_both_have_an_org_type(mocker, service_one): # service_one has an organisation_type of 'central' service = Service(service_one) service._dict['organisation'] = ORGANISATION_ID org = organisation_json(organisation_type='local') mocker.patch('app.organisations_client.get_organisation', return_value=org) assert service.organisation_type == 'local'
def accept_invite(token): invited_user = InvitedUser.from_token(token) if not current_user.is_anonymous and current_user.email_address.lower( ) != invited_user.email_address.lower(): message = Markup(""" You’re signed in as {}. This invite is for another email address. <a href={} class="govuk-link govuk-link--no-visited-state">Sign out</a> and click the link again to accept this invite. """.format(current_user.email_address, url_for("main.sign_out", _external=True))) flash(message=message) abort(403) if invited_user.status == 'cancelled': service = Service.from_id(invited_user.service) return render_template('views/cancelled-invitation.html', from_user=invited_user.from_user.name, service_name=service.name) if invited_user.status == 'accepted': session.pop('invited_user', None) return redirect( url_for('main.service_dashboard', service_id=invited_user.service)) session['invited_user'] = invited_user.serialize() existing_user = User.from_email_address_or_none(invited_user.email_address) if existing_user: invited_user.accept_invite() if existing_user in Users(invited_user.service): return redirect( url_for('main.service_dashboard', service_id=invited_user.service)) else: service = Service.from_id(invited_user.service) # if the service you're being added to can modify auth type, then check if this is relevant if service.has_permission('email_auth') and ( # they have a phone number, we want them to start using it. if they dont have a mobile we just # ignore that option of the invite (existing_user.mobile_number and invited_user.auth_type == 'sms_auth') or # we want them to start sending emails. it's always valid, so lets always update invited_user.auth_type == 'email_auth'): existing_user.update(auth_type=invited_user.auth_type) existing_user.add_to_service( service_id=invited_user.service, permissions=invited_user.permissions, folder_permissions=invited_user.folder_permissions, ) return redirect( url_for('main.service_dashboard', service_id=service.id)) else: return redirect(url_for('main.register_from_invite'))
def test_organisation_name_comes_from_cache(mocker, service_one): mock_redis_get = mocker.patch( 'app.extensions.RedisClient.get', return_value=b'"Borchester Council"', ) mock_get_organisation = mocker.patch('app.organisations_client.get_organisation') service = Service(service_one) service._dict['organisation'] = ORGANISATION_ID assert service.organisation_name == 'Borchester Council' mock_redis_get.assert_called_once_with(f'organisation-{ORGANISATION_ID}-name') assert mock_get_organisation.called is False
def test_service_without_organisation_doesnt_need_org_api(mocker, service_one): mock_redis_get = mocker.patch('app.extensions.RedisClient.get') mock_get_organisation = mocker.patch('app.organisations_client.get_organisation') service = Service(service_one) service._dict['organisation'] = None assert service.organisation_id is None assert service.organisation_name is None assert isinstance(service.organisation, Organisation) assert mock_redis_get.called is False assert mock_get_organisation.called is False
def __init__(self, app): self.app = app self.services_cfg_file_path = None self.services = {} # Find the services yaml file self.__find_services_yml_file_path() # Read the services param file with open(self.services_cfg_file_path, "r", encoding='utf8') as stream: try: services_dict = yaml.safe_load(stream) for k, v in list(services_dict.items()): v["cfg_file_path"] = self.services_cfg_file_path v["name"] = k s = Service(**v) self.services[k] = s self.app.init_success = True except yaml.YAMLError as e: self.app.logger.exception(e) self.app.logger.critical( "The app config file is not correctly formed. The initialization porcess will stop." "The following configuration file must be fixed before the application is restarted : " "{}".format(self.services_cfg_file_path) )
def load_service_before_request(): if "/static/" in request.url: _request_ctx_stack.top.service = None _request_ctx_stack.top.organisation = None # added to init None to ensure request context has None or something return if _request_ctx_stack.top is not None: _request_ctx_stack.top.service = None _request_ctx_stack.top.organisation = None # added to init None to ensure request context has None or something if request.view_args: service_id = request.view_args.get("service_id", session.get("service_id")) else: service_id = session.get("service_id") if service_id: try: _request_ctx_stack.top.service = Service( service_api_client.get_service(service_id)["data"]) except HTTPError as exc: # if service id isn't real, then 404 rather than 500ing later because we expect service to be set if exc.status_code == 404: abort(404) else: raise
def activate_user(user_id): user = User.from_id(user_id) # the user will have a new current_session_id set by the API - store it in the cookie for future requests session['current_session_id'] = user.current_session_id organisation_id = session.get('organisation_id') activated_user = user.activate() activated_user.login() invited_user = InvitedUser.from_session() if invited_user: service_id = _add_invited_user_to_service(invited_user) service = Service.from_id(service_id) if service.has_permission('broadcast'): return redirect( url_for('main.broadcast_tour', service_id=service.id, step_index=1)) return redirect( url_for('main.service_dashboard', service_id=service_id)) invited_org_user = InvitedOrgUser.from_session() if invited_org_user: user_api_client.add_user_to_organisation(invited_org_user.organisation, session['user_details']['id']) if organisation_id: return redirect( url_for('main.organisation_dashboard', org_id=organisation_id)) else: return redirect(url_for('main.add_service', first='first'))
def get(current_user, workspaceId, projectId): """ Get a project by project id :return: Http Json response """ project = Project.get_by_id(projectId) if project: services = project.services srv_payload = [] for sid in services: srv = Service.get_by_id(sid) if srv: srv_obj = { 'id': srv._id, 'serviceType': srv.serviceType, 'serviceMeta': srv.serviceMeta, 'isActive': srv.isActive } srv_payload.append(srv_obj) return { 'name': project.name, 'id': project._id, 'createdBy': project.createdBy, 'createdOn': project.createdOn, 'isActive': project.isActive, 'services': srv_payload, 'timezone': project.timezone } else: return response('failed', 'project not found', 404)
def test_go_live_checklist( mocker, service_one, has_submitted_use_case, has_templates, has_team_members_status, has_accepted_tos, expected_completed, app_, ): for prop in [ "has_submitted_use_case", "has_templates", "has_team_members_status", "has_accepted_tos", ]: mocker.patch( f"app.models.service.Service.{prop}", new_callable=PropertyMock, return_value=locals()[prop], ) with app_.test_request_context(): checklist = Service(service_one).go_live_checklist assert len(checklist) == 4 assert checklist[0].keys() == set(["text", "status", "endpoint", "completed"]) assert { "text": "Add a team member who can manage settings", "status": has_team_members_status, "endpoint": "main.manage_users", "completed": expected_completed, } in checklist
def test_organisation_type_when_service_and_its_org_both_have_an_org_type(mocker, service_one): # service_one has an organisation_type of 'central' service = Service(service_one) org = organisation_json(organisation_type="local") mocker.patch("app.organisations_client.get_service_organisation", return_value=org) assert service.organisation_type == "local"
def deactivate(current_user, workspaceId, projectId): """ Deactivate a service Service ID Is mandatory :return: Http Json response """ if request.content_type == 'application/json': serviceId = request.get_json(force=True).get('serviceId') if serviceId: service = Service.get_by_id(serviceId) if service: service.deactivate() res_payload = { 'serviceType': service.serviceType, 'id': service._id, 'createdBy': service.createdBy, 'createdOn': service.createdOn, 'isActive': service.isActive, 'serviceMeta': service.serviceMeta } return response_with_obj('success', 'Service deactivated successfully', res_payload, 200) else: return response('failed', 'service not found', 404) else: return response('failed', 'Service ID is required in the request payload.', 402) else: return response('failed', 'Content-type must be json', 402)
def has_permissions(self, *permissions, restrict_admin_usage=False, allow_org_user=False): unknown_permissions = set(permissions) - all_permissions if unknown_permissions: raise TypeError("{} are not valid permissions".format(list(unknown_permissions))) # Service id is always set on the request for service specific views. service_id = _get_service_id_from_view_args() org_id = _get_org_id_from_view_args() if not service_id and not org_id: # we shouldn't have any pages that require permissions, but don't specify a service or organisation. # use @user_is_platform_admin for platform admin only pages return False # platform admins should be able to do most things (except eg send messages, or create api keys) if self.platform_admin and not restrict_admin_usage: return True if org_id: return self.belongs_to_organisation(org_id) if not permissions and self.belongs_to_service(service_id): return True if any(self.has_permission_for_service(service_id, permission) for permission in permissions): return True from app.models.service import Service return allow_org_user and self.belongs_to_organisation(Service.from_id(service_id).organisation_id)
def add_service(self, name, repository, tag): try: service = Service(name=name, repository=repository, tag=tag) db.session.add(service) db.session.commit() return service except IntegrityError: db.session.rollback() return None
def test_get_status_filters_in_right_order(client): ret = get_status_filters(Service({"id": "foo"}), "sms", STATISTICS) assert [label for label, _option, _link, _count in ret] == [ "total", "sending", "delivered", "failed", ]
def create_service(name, repository, tag): service = Service(name=name, repository=repository, tag=tag) db.session.add(service) try: db.session.commit() print('Successfully created service', name) except IntegrityError: db.session.rollback() print('Service already exists')
def test_get_status_filters_calculates_stats(client): ret = get_status_filters(Service({'id': 'foo'}), 'sms', STATISTICS) assert {label: count for label, _option, _link, count in ret} == { 'total': 6, 'sending': 3, 'failed': 2, 'delivered': 1 }
def test_organisation_type_when_services_organisation_has_no_org_type(mocker, service_one, organisation_one): service = Service(service_one) mocker.patch( "app.organisations_client.get_service_organisation", return_value=organisation_one, ) assert not organisation_one["organisation_type"] assert service.organisation_type == "central"
def test_has_team_members_status_no_invited_users( service_one, mock_get_invites_without_manage_permission, mock_get_users_by_service ): # 1 active with "manage_service", 1 invited without "manage_service" service = Service(service_one) assert len(service.team_members) == 2 assert len(service.invited_users) == 1 assert service.has_team_members_status is False
def test_get_status_filters_calculates_stats(client): ret = get_status_filters(Service({"id": "foo"}), "sms", STATISTICS) assert {label: count for label, _option, _link, count in ret} == { "total": 6, "sending": 3, "failed": 2, "delivered": 1, }
def test_organisation_name_goes_into_cache(mocker, service_one): mocker.patch( 'app.extensions.RedisClient.get', return_value=None, ) mock_redis_set = mocker.patch('app.extensions.RedisClient.set', ) mocker.patch( 'app.organisations_client.get_organisation', return_value=organisation_json(), ) service = Service(service_one) service._dict['organisation'] = ORGANISATION_ID assert service.organisation_name == 'Test Organisation' mock_redis_set.assert_called_once_with( f'organisation-{ORGANISATION_ID}-name', '"Test Organisation"', ex=604800, )
def test_get_user_template_folders_only_returns_folders_visible_to_user( app_, mock_get_template_folders, service_one, active_user_with_permissions, mocker ): mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions) service = Service(service_one) result = service.get_user_template_folders(User(active_user_with_permissions)) assert result == [ { "name": ["Parent 1 - invisible", "1's Visible child"], "id": mocker.ANY, "parent_id": None, "users_with_permission": [active_user_with_permissions["id"]], }, { "name": [ "Parent 1 - invisible", ["1's Invisible child", "1's Visible grandchild"], ], "id": mocker.ANY, "parent_id": None, "users_with_permission": [active_user_with_permissions["id"]], }, { "name": "2's Visible child", "id": mocker.ANY, "parent_id": VIS_PARENT_FOLDER_ID, "users_with_permission": [active_user_with_permissions["id"]], }, { "name": ["2's Invisible child", "2's Visible grandchild"], "id": mocker.ANY, "parent_id": VIS_PARENT_FOLDER_ID, "users_with_permission": [active_user_with_permissions["id"]], }, { "name": "Parent 2 - visible", "id": VIS_PARENT_FOLDER_ID, "parent_id": None, "users_with_permission": [active_user_with_permissions["id"]], }, ]
def create_service_info(): with open('service-info.json') as service_info_json: data = json.load(service_info_json) service_info = Service(**data) service_info.contactUrl = SERVICE_INFO_CONTACTURL service_info.environment = SERVICE_INFO_ENVIRONMENT service_info.version = SERVICE_INFO_VERSION service_info.createdAt = SERVICE_INFO_CREATEDAT service_info.updatedAt = datetime.now().strftime("%d-%m-%y") serviceInfo.service = service_info