Пример #1
0
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"))
Пример #2
0
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']]
        },
    ]
Пример #3
0
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"]],
        },
    ]
Пример #4
0
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)
Пример #6
0
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}
Пример #8
0
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'
Пример #9
0
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'
Пример #10
0
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'))
Пример #11
0
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
Пример #12
0
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
Пример #13
0
    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)
                )
Пример #14
0
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'))
Пример #16
0
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)
Пример #17
0
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
Пример #18
0
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"
Пример #19
0
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)
Пример #20
0
    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)
Пример #21
0
 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
Пример #22
0
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",
    ]
Пример #23
0
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')
Пример #24
0
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
    }
Пример #25
0
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"
Пример #26
0
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
Пример #27
0
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,
            }
Пример #28
0
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,
    )
Пример #29
0
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"]],
        },
    ]
Пример #30
0
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