Beispiel #1
0
def test_add_service_account(session, users, http_client, base_url):
    user = users['*****@*****.**']

    # Add account
    fe_url = url(base_url, '/service/create')
    resp = yield http_client.fetch(fe_url, method="POST",
            body=urlencode({'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin"}),
            headers={'X-Grouper-User': user.username})
    assert resp.code == 200

    assert User.get(session, name="*****@*****.**") is None
    assert Group.get(session, name="*****@*****.**") is None

    # Add account
    fe_url = url(base_url, '/service/create')
    resp = yield http_client.fetch(fe_url, method="POST",
            body=urlencode({'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin"}),
            headers={'X-Grouper-User': user.username})
    assert resp.code == 200

    u = User.get(session, name="*****@*****.**")
    g = Group.get(session, name="*****@*****.**")

    assert u is not None
    assert g is not None
    assert is_service_account(session, user=u)
    assert is_service_account(session, group=g)
    assert get_service_account(session, user=u).group.id == g.id
    assert get_service_account(session, group=g).user.id == u.id
    assert not is_service_account(session, user=user)
    assert not is_service_account(session, group=Group.get(session, name="team-sre"))
Beispiel #2
0
def test_add_service_account(session, users, http_client, base_url):
    user = users['*****@*****.**']

    # Add account
    fe_url = url(base_url, '/service/create')
    resp = yield http_client.fetch(fe_url, method="POST",
            body=urlencode({'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin"}),
            headers={'X-Grouper-User': user.username})
    assert resp.code == 200

    assert User.get(session, name="*****@*****.**") is None
    assert Group.get(session, name="*****@*****.**") is None

    # Add account
    fe_url = url(base_url, '/service/create')
    resp = yield http_client.fetch(fe_url, method="POST",
            body=urlencode({'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin"}),
            headers={'X-Grouper-User': user.username})
    assert resp.code == 200

    u = User.get(session, name="*****@*****.**")
    g = Group.get(session, name="*****@*****.**")

    assert u is not None
    assert g is not None
    assert is_service_account(session, user=u)
    assert is_service_account(session, group=g)
    assert get_service_account(session, user=u).group.id == g.id
    assert get_service_account(session, group=g).user.id == u.id
    assert not is_service_account(session, user=user)
    assert not is_service_account(session, group=Group.get(session, name="team-sre"))
Beispiel #3
0
def test_oneoff(mock_make_session, mock_annex, mock_load_plugins, session):
    mock_make_session.return_value = session
    username = '******'
    other_username = '******'
    groupname = 'fake_group'

    class FakeOneOff(object):
        def configure(self, service_name):
            pass

        def run(self, session, **kwargs):
            if kwargs.get('group'):
                Group.get_or_create(session, groupname=groupname)
                session.commit()
            elif kwargs.get('key') == 'valuewith=':
                User.get_or_create(session, username=other_username)
                session.commit()
            else:
                User.get_or_create(session, username=username)
                session.commit()

    mock_annex.return_value = [FakeOneOff()]

    # dry_run
    call_main('oneoff', 'run', 'FakeOneOff')
    assert User.get(session,
                    name=username) is None, 'default dry_run means no writes'
    assert User.get(session,
                    name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(
        session,
        name=groupname) is None, '"group" not in arg so no group created'

    # not dry_run, create a user
    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff')
    assert User.get(session,
                    name=username) is not None, 'dry_run off means writes'
    assert User.get(session,
                    name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(
        session,
        name=groupname) is None, '"group" not in arg so no group created'

    # not dry_run, use kwarg to create a group
    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'group=1')
    assert User.get(session,
                    name=username) is not None, 'dry_run off means writes'
    assert User.get(session,
                    name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(
        session, name=groupname) is not None, '"group" in arg so group created'

    # invalid format for argument should result in premature system exit
    with pytest.raises(SystemExit):
        call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'bad_arg')

    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'key=valuewith=')
    assert User.get(
        session,
        name=other_username) is not None, '"valuewith= in arg, create user2'
Beispiel #4
0
def test_group_disable(session, groups, http_client, base_url):
    # create global audit
    fe_url = url(base_url, '/audits/create')
    ends_at = date.today() + timedelta(days=7)
    resp = yield http_client.fetch(fe_url, method="POST",
            headers={"X-Grouper-User": "******"},
            body=urlencode({"ends_at": ends_at.strftime("%m/%d/%Y")}))
    assert resp.code == 200

    serving_team, just_created = Group.get_or_create(session, groupname="serving-team")
    assert not just_created
    assert serving_team.audit
    assert not serving_team.audit.complete

    # disable with insufficient permissions
    fe_url = url(base_url, '/groups/serving-team/disable')
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(fe_url, method="POST",
                headers={"X-Grouper-User": "******"}, body=urlencode({"name": "serving-team"}))

    # disable
    fe_url = url(base_url, '/groups/serving-team/disable')
    resp = yield http_client.fetch(fe_url, method="POST",
            headers={"X-Grouper-User": "******"}, body=urlencode({"name": "serving-team"}))
    assert resp.code == 200

    serving_team, just_created = Group.get_or_create(session, groupname="serving-team")
    assert not just_created
    assert serving_team.audit
    assert serving_team.audit.complete, "disabling group should complete any outstanding audit"
Beispiel #5
0
 def run(self, session, **kwargs):
     if kwargs.get('group'):
         Group.get_or_create(session, groupname=groupname)
         session.commit()
     elif kwargs.get('key') == 'valuewith=':
         User.get_or_create(session, username=other_username)
         session.commit()
     else:
         User.get_or_create(session, username=username)
         session.commit()
Beispiel #6
0
 def run(self, session, **kwargs):
     if kwargs.get('group'):
         Group.get_or_create(session, groupname=groupname)
         session.commit()
     elif kwargs.get('key') == 'valuewith=':
         User.get_or_create(session, username=other_username)
         session.commit()
     else:
         User.get_or_create(session, username=username)
         session.commit()
Beispiel #7
0
def create_service_account(session, actor, name, description, canjoin):
    # type (Session, User, str, str, str) -> None
    """Creates a service account with the given name, description, and canjoin status

    Args:
        session: the database session
        actor: the user creating the service account
        name: the name of the service account
        description: description of the service account
        canjoin: the canjoin status for management of the service account

    Throws:
        IntegrityError: if a user or group with the given name already exists
    """
    user = User(username=name, role_user=True)
    group = Group(groupname=name, description=description, canjoin=canjoin)

    user.add(session)
    group.add(session)

    group.add_member(actor, actor, "Group Creator", "actioned", None,
                     "np-owner")
    group.add_member(actor, user, "Service Account", "actioned", None,
                     "member")
    session.commit()

    AuditLog.log(session,
                 actor.id,
                 'create_service_account',
                 'Created new service account.',
                 on_group_id=group.id,
                 on_user_id=user.id)
Beispiel #8
0
def get_service_account(session, user=None, group=None):
    # type: (Session, User, Group) -> ServiceAccount
    """
    Takes in a User or a Group and returns a dictionary that contains
    all of the service account components for the service account that
    the user/group is part of.

    Args:
        session: the database session
        user: a User object to check
        group: a Group object to check

    Throws:
        ServiceAccountNotFound: if the user or group is not part of a
            service account

    Returns:
        a dictionary with all components of the service account of the
            user or group passed in
    """
    if not is_service_account(session, user, group):
        raise ServiceAccountNotFound()

    name = user.name if user else group.name
    return ServiceAccount(User.get(session, name=name), Group.get(session, name=name))
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not self.current_user.can_manage(group):
            return self.forbidden()

        form = GroupRemoveForm(self.request.arguments)
        if not form.validate():
            return self.send_error(status_code=400)

        member_type, member_name = form.data["member_type"], form.data["member"]

        members = group.my_members()
        if not members.get((member_type.capitalize(), member_name), None):
            return self.notfound()

        removed_member = get_user_or_group(self.session, member_name, user_or_group=member_type)

        if self.current_user == removed_member:
            return self.send_error(
                status_code=400,
                reason="Can't remove yourself. Leave group instead."
            )

        group.revoke_member(self.current_user, removed_member, "Removed by owner/np-owner/manager")
        AuditLog.log(self.session, self.current_user.id, 'remove_from_group',
                     '{} was removed from the group.'.format(removed_member.name),
                     on_group_id=group.id, on_user_id=removed_member.id)
        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #10
0
    def get(self, request_id, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        my_role = user_role(self.current_user, members)
        if my_role not in ("manager", "owner", "np-owner"):
            return self.forbidden()

        request = self.session.query(Request).filter_by(id=request_id).scalar()
        if not request:
            return self.notfound()

        form = GroupRequestModifyForm(self.request.arguments)
        form.status.choices = self._get_choices(request.status)

        updates = request.my_status_updates()

        self.render("group-request-update.html",
                    group=group,
                    request=request,
                    members=members,
                    form=form,
                    statuses=REQUEST_STATUS_CHOICES,
                    updates=updates)
Beispiel #11
0
def get_service_account(session, user=None, group=None):
    # type: (Session, User, Group) -> ServiceAccount
    """
    Takes in a User or a Group and returns a dictionary that contains
    all of the service account components for the service account that
    the user/group is part of.

    Args:
        session: the database session
        user: a User object to check
        group: a Group object to check

    Throws:
        ServiceAccountNotFound: if the user or group is not part of a
            service account

    Returns:
        a dictionary with all components of the service account of the
            user or group passed in
    """
    if not is_service_account(session, user, group):
        raise ServiceAccountNotFound()

    name = user.name if user else group.name
    return ServiceAccount(User.get(session, name=name),
                          Group.get(session, name=name))
Beispiel #12
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        status = self.get_argument("status", None)
        offset = int(self.get_argument("offset", 0))
        limit = int(self.get_argument("limit", 100))
        if limit > 9000:
            limit = 9000

        requests = group.my_requests(status).order_by(
            Request.requested_at.desc()
        )
        members = group.my_members()

        total = requests.count()
        requests = requests.offset(offset).limit(limit)

        current_user_role = {
            'is_owner': user_role_index(self.current_user, members) in OWNER_ROLE_INDICES,
            'is_approver': user_role_index(self.current_user, members) in APPROVER_ROLE_INDICIES,
            'is_manager': user_role(self.current_user, members) == "manager",
            'role': user_role(self.current_user, members),
             }

        self.render(
            "group-requests.html", group=group, requests=requests,
            members=members, status=status, statuses=REQUEST_STATUS_CHOICES,
            offset=offset, limit=limit, total=total, current_user_role=current_user_role,
        )
Beispiel #13
0
def test_permission_exclude_inactive(session, standard_graph):
    """Ensure disabled groups are excluded from permission data."""
    group = Group.get(session, name="team-sre")
    permission = Permission.get(session, name="ssh")
    assert "team-sre" in [g[0] for g in get_groups_by_permission(session, permission)]
    group.disable()
    assert "team-sre" not in [g[0] for g in get_groups_by_permission(session, permission)]
Beispiel #14
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not user_role(self.current_user, members) in ("owner", "np-owner"):
            return self.forbidden()

        # Enabling and disabling service accounts via the group endpoints is forbidden
        # because we need the preserve_membership data that is only available via the
        # UserEnable form.
        if is_service_account(self.session, group=group):
            return self.forbidden()

        group.enable()

        self.session.commit()

        AuditLog.log(self.session,
                     self.current_user.id,
                     'enable_group',
                     'Enabled group.',
                     on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #15
0
def test_oneoff(mock_make_session, mock_annex, session):
    mock_make_session.return_value = session
    username = '******'
    other_username = '******'
    groupname = 'fake_group'

    class FakeOneOff(object):
        def configure(self, service_name):
            pass

        def run(self, session, **kwargs):
            if kwargs.get('group'):
                Group.get_or_create(session, groupname=groupname)
                session.commit()
            elif kwargs.get('key') == 'valuewith=':
                User.get_or_create(session, username=other_username)
                session.commit()
            else:
                User.get_or_create(session, username=username)
                session.commit()

    mock_annex.return_value = [FakeOneOff()]

    # dry_run
    call_main('oneoff', 'run', 'FakeOneOff')
    assert User.get(session, name=username) is None, 'default dry_run means no writes'
    assert User.get(session, name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(session, name=groupname) is None, '"group" not in arg so no group created'

    # not dry_run, create a user
    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff')
    assert User.get(session, name=username) is not None, 'dry_run off means writes'
    assert User.get(session, name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(session, name=groupname) is None, '"group" not in arg so no group created'

    # not dry_run, use kwarg to create a group
    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'group=1')
    assert User.get(session, name=username) is not None, 'dry_run off means writes'
    assert User.get(session, name=other_username) is None, '"valuewith= not in arg'
    assert Group.get(session, name=groupname) is not None, '"group" in arg so group created'

    # invalid format for argument should result in premature system exit
    with pytest.raises(SystemExit):
        call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'bad_arg')

    call_main('oneoff', 'run', '--no-dry_run', 'FakeOneOff', 'key=valuewith=')
    assert User.get(session, name=other_username) is not None, '"valuewith= in arg, create user2'
Beispiel #16
0
def sync_db_command(args):
    # Models not implicitly or explictly imported above are explicitly imported
    # here:
    from grouper.models.perf_profile import PerfProfile  # noqa

    db_engine = get_db_engine(get_database_url(settings))
    Model.metadata.create_all(db_engine)

    # Add some basic database structures we know we will need if they don't exist.
    session = make_session()

    for name, description in SYSTEM_PERMISSIONS:
        test = Permission.get(session, name)
        if test:
            continue
        permission = Permission(name=name, description=description)
        try:
            permission.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception('Failed to create permission: %s' % (name, ))
        session.commit()

    # This group is needed to bootstrap a Grouper installation.
    admin_group = Group.get(session, name="grouper-administrators")
    if not admin_group:
        admin_group = Group(
            groupname="grouper-administrators",
            description="Administrators of the Grouper system.",
            canjoin="nobody",
        )

        try:
            admin_group.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception('Failed to create group: grouper-administrators')

        for permission_name in (GROUP_ADMIN, PERMISSION_ADMIN, USER_ADMIN):
            permission = Permission.get(session, permission_name)
            assert permission, "Permission should have been created earlier!"
            grant_permission(session, admin_group.id, permission.id)

        session.commit()
Beispiel #17
0
def groups(session):
    groups = {
        groupname: Group.get_or_create(session, groupname=groupname)[0]
        for groupname in ("team-sre", "tech-ops", "team-infra", "all-teams", "serving-team",
                          "security-team", "auditors", "sad-team", "audited-team")
    }
    session.commit()
    return groups
Beispiel #18
0
def sync_db_command(args):
    # Models not implicitly or explictly imported above are explicitly imported
    # here:
    from grouper.models.perf_profile import PerfProfile  # noqa

    db_engine = get_db_engine(get_database_url(settings))
    Model.metadata.create_all(db_engine)

    # Add some basic database structures we know we will need if they don't exist.
    session = make_session()

    for name, description in SYSTEM_PERMISSIONS:
        test = Permission.get(session, name)
        if test:
            continue
        permission = Permission(name=name, description=description)
        try:
            permission.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception('Failed to create permission: %s' % (name, ))
        session.commit()

    # This group is needed to bootstrap a Grouper installation.
    admin_group = Group.get(session, name="grouper-administrators")
    if not admin_group:
        admin_group = Group(
                groupname="grouper-administrators",
                description="Administrators of the Grouper system.",
                canjoin="nobody",
        )

        try:
            admin_group.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception('Failed to create group: grouper-administrators')

        for permission_name in (GROUP_ADMIN, PERMISSION_ADMIN, USER_ADMIN):
            permission = Permission.get(session, permission_name)
            assert permission, "Permission should have been created earlier!"
            grant_permission(session, admin_group.id, permission.id)

        session.commit()
def test_grant_and_revoke(session, standard_graph, graph, groups, permissions,
        http_client, base_url):
    """Test that permission grant and revokes are reflected correctly."""
    group_name = "team-sre"
    permission_name = "sudo"
    user_name = "*****@*****.**"

    def _check_graph_for_perm(graph):
        return any(map(lambda x: x.permission == permission_name,
                graph.permission_metadata[group_name]))

    # make some permission admins
    perm_admin, _ = Permission.get_or_create(session, name=PERMISSION_ADMIN, description="")
    session.commit()
    grant_permission(groups["security-team"], perm_admin)

    # grant attempt by non-permission admin
    fe_url = url(base_url, "/permissions/grant/{}".format(group_name))
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url, method="POST",
                body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
                headers={'X-Grouper-User': "******"})

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "no permissions granted"

    # grant by permission admin
    resp = yield http_client.fetch(fe_url, method="POST",
            body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
            headers={'X-Grouper-User': user_name})
    assert resp.code == 200

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions granted, successfully"

    # figure out mapping_id of grant
    permission_id = Permission.get(session, name=permission_name).id
    group_id = Group.get(session, name=group_name).id
    mapping = session.query(PermissionMap).filter(
            PermissionMap.permission_id == permission_id,
            PermissionMap.group_id == group_id).first()

    # revoke permission by non-admin
    fe_url = url(base_url, "/permissions/{}/revoke/{}".format(permission_name, mapping.id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url, method="POST", body=urlencode({}),
                headers={'X-Grouper-User': "******"})

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions not revoked"

    # revoke permission for realz
    resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({}),
            headers={'X-Grouper-User': user_name})
    assert resp.code == 200

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "permissions revoked successfully"
Beispiel #20
0
def create_service_account(session, actor, name, description, canjoin):
    # type (Session, User, str, str, str) -> None
    """Creates a service account with the given name, description, and canjoin status

    Args:
        session: the database session
        actor: the user creating the service account
        name: the name of the service account
        description: description of the service account
        canjoin: the canjoin status for management of the service account

    Throws:
        IntegrityError: if a user or group with the given name already exists
    """
    user = User(username=name, role_user=True)
    group = Group(groupname=name, description=description, canjoin=canjoin)

    user.add(session)
    group.add(session)

    group.add_member(actor, actor, "Group Creator", "actioned", None, "np-owner")
    group.add_member(actor, user, "Service Account", "actioned", None, "member")
    session.commit()

    AuditLog.log(session, actor.id, 'create_service_account', 'Created new service account.',
                 on_group_id=group.id, on_user_id=user.id)
Beispiel #21
0
def groups(session):
    groups = {
        groupname: Group.get_or_create(session, groupname=groupname)[0]
        for groupname in ("team-sre", "tech-ops", "team-infra", "all-teams",
                          "serving-team", "security-team", "auditors",
                          "sad-team", "audited-team", "user-admins")
    }
    session.commit()
    return groups
Beispiel #22
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        group_md = self.graph.get_group_details(group.name)

        form = GroupJoinForm()
        form.member.choices = self._get_choices(group)
        return self.render("group-join.html", form=form, group=group, audited=group_md["audited"])
Beispiel #23
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not user_role(self.current_user, members):
            return self.forbidden()

        return self.render("group-leave.html", group=group)
Beispiel #24
0
def test_permission_exclude_inactive(session, standard_graph):
    """Ensure disabled groups are excluded from permission data."""
    group = Group.get(session, name="team-sre")
    permission = Permission.get(session, name="ssh")
    assert "team-sre" in [
        g[0] for g in get_groups_by_permission(session, permission)
    ]
    group.disable()
    assert "team-sre" not in [
        g[0] for g in get_groups_by_permission(session, permission)
    ]
Beispiel #25
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        form = GroupEditForm(obj=group)

        self.render("group-edit.html", group=group, form=form)
Beispiel #26
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not self.current_user.can_manage(group):
            return self.forbidden()

        form = GroupEditForm(obj=group)

        self.render("group-edit.html", group=group, form=form)
Beispiel #27
0
def test_sync_db_default_group(make_session, session, users, groups):
    make_session.return_value = session

    call_main('sync_db')
    admin_group = Group.get(session, name="grouper-administrators")
    assert admin_group, "Group should have been autocreated"

    admin_group_permission_names = [perm[1] for perm in admin_group.my_permissions()]
    for permission in (GROUP_ADMIN, PERMISSION_ADMIN, USER_ADMIN):
        assert permission in admin_group_permission_names, \
                "Expected permission missing: %s" % permission
Beispiel #28
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not self.current_user.my_role(members):
            return self.forbidden()

        return self.render(
            "group-leave.html", group=group
        )
Beispiel #29
0
def test_group_disable(session, groups, http_client, base_url):
    # create global audit
    fe_url = url(base_url, '/audits/create')
    ends_at = date.today() + timedelta(days=7)
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": "******"},
        body=urlencode({"ends_at": ends_at.strftime("%m/%d/%Y")}))
    assert resp.code == 200

    serving_team, just_created = Group.get_or_create(session,
                                                     groupname="serving-team")
    assert not just_created
    assert serving_team.audit
    assert not serving_team.audit.complete

    # disable with insufficient permissions
    fe_url = url(base_url, '/groups/serving-team/disable')
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(fe_url,
                                       method="POST",
                                       headers={"X-Grouper-User": "******"},
                                       body=urlencode({"name":
                                                       "serving-team"}))

    # disable
    fe_url = url(base_url, '/groups/serving-team/disable')
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": "******"},
                                   body=urlencode({"name": "serving-team"}))
    assert resp.code == 200

    serving_team, just_created = Group.get_or_create(session,
                                                     groupname="serving-team")
    assert not just_created
    assert serving_team.audit
    assert serving_team.audit.complete, "disabling group should complete any outstanding audit"
Beispiel #30
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        members = group.my_members()
        my_role = user_role(self.current_user, members)
        return self.render(
            "group-add.html", form=self.get_form(role=my_role), group=group
        )
Beispiel #31
0
    def get(self, group_id=None, name=None):
        self.handle_refresh()
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if is_service_account(self.session, group=group):
            return self.redirect("/service/{}".format(group.groupname))

        self.render(
            "group.html", group=group,
            **get_group_view_template_vars(self.session, self.current_user, group, self.graph)
        )
Beispiel #32
0
def test_sync_db_default_group(make_session, session, users, groups):
    make_session.return_value = session

    call_main('sync_db')
    admin_group = Group.get(session, name="grouper-administrators")
    assert admin_group, "Group should have been autocreated"

    admin_group_permission_names = [
        perm[1] for perm in admin_group.my_permissions()
    ]
    for permission in (GROUP_ADMIN, PERMISSION_ADMIN, USER_ADMIN):
        assert permission in admin_group_permission_names, \
                "Expected permission missing: %s" % permission
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        args_by_perm = get_grantable_permissions(self.session,
                settings.restricted_ownership_permissions)
        dropdown_form, text_form = GroupPermissionRequest._get_forms(args_by_perm, None)

        self.render("group-permission-request.html", dropdown_form=dropdown_form,
                text_form=text_form, group=group, args_by_perm_json=json.dumps(args_by_perm),
                dropdown_help=settings.permission_request_dropdown_help,
                text_help=settings.permission_request_text_help)
Beispiel #34
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not self.current_user.can_manage(group):
            return self.forbidden()

        members = group.my_members()
        my_role = self.current_user.my_role(members)
        return self.render(
            "group-add.html", form=self.get_form(role=my_role), group=group
        )
Beispiel #35
0
    def get(self, group_id=None, name=None):
        self.handle_refresh()
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if is_service_account(self.session, group=group):
            return self.redirect("/service/{}".format(group.groupname))

        self.render("group.html",
                    group=group,
                    **get_group_view_template_vars(self.session,
                                                   self.current_user, group,
                                                   self.graph))
Beispiel #36
0
    def get(self, group_id=None, name=None):
        self.handle_refresh()
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        grantable = self.current_user.my_grantable_permissions()

        try:
            group_md = self.graph.get_group_details(group.name)
        except NoSuchGroup:
            # Very new group with no metadata yet, or it has been disabled and
            # excluded from in-memory cache.
            group_md = {}

        members = group.my_members()
        groups = group.my_groups()
        permissions = group_md.get('permissions', [])
        permission_requests_pending = get_pending_request_by_group(self.session, group)
        audited = group_md.get('audited', False)
        log_entries = group.my_log_entries()
        num_pending = group.my_requests("pending").count()
        current_user_role = {
                'is_owner': self.current_user.my_role_index(members) in OWNER_ROLE_INDICES,
                'is_approver': self.current_user.my_role_index(members) in APPROVER_ROLE_INDICIES,
                'is_manager': self.current_user.my_role(members) == "manager",
                }

        # Add mapping_id to permissions structure
        my_permissions = group.my_permissions()
        for perm_up in permissions:
            for perm_direct in my_permissions:
                if (perm_up['permission'] == perm_direct.name and
                        perm_up['argument'] == perm_direct.argument):
                    perm_up['mapping_id'] = perm_direct.mapping_id
                    break

        alerts = []
        self_pending = group.my_requests("pending", user=self.current_user).count()
        if self_pending:
            alerts.append(Alert('info', 'You have a pending request to join this group.', None))

        self.render(
            "group.html", group=group, members=members, groups=groups,
            num_pending=num_pending, alerts=alerts, permissions=permissions,
            log_entries=log_entries, grantable=grantable, audited=audited,
            statuses=AUDIT_STATUS_CHOICES, current_user_role=current_user_role,
            permission_requests_pending=permission_requests_pending
        )
Beispiel #37
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        form = GroupEditForm(self.request.arguments, obj=group)
        if not form.validate():
            return self.render("group-edit.html",
                               group=group,
                               form=form,
                               alerts=self.get_form_alerts(form.errors))

        if (group.groupname != form.data["groupname"]
                and is_service_account(self.session, group=group)):
            form.groupname.errors.append(
                "You cannot change the name of service account groups")
            return self.render("group-edit.html",
                               group=group,
                               form=form,
                               alerts=self.get_form_alerts(form.errors))

        group.groupname = form.data["groupname"]
        group.email_address = form.data["email_address"]
        group.description = form.data["description"]
        group.canjoin = form.data["canjoin"]
        group.auto_expire = form.data["auto_expire"]
        Counter.incr(self.session, "updates")

        try:
            self.session.commit()
        except IntegrityError:
            self.session.rollback()
            form.groupname.errors.append("{} already exists".format(
                form.data["groupname"]))
            return self.render("group-edit.html",
                               group=group,
                               form=form,
                               alerts=self.get_form_alerts(form.errors))

        AuditLog.log(self.session,
                     self.current_user.id,
                     'edit_group',
                     'Edited group.',
                     on_group_id=group.id)

        return self.redirect("/groups/{}".format(group.name))
Beispiel #38
0
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        group_md = self.graph.get_group_details(group.name)

        form = GroupJoinForm()
        form.member.choices = self._get_choices(group)
        return self.render(
            "group-join.html",
            form=form,
            group=group,
            audited=group_md["audited"],
        )
Beispiel #39
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not self.current_user.my_role(members) in ("owner", "np-owner"):
            return self.forbidden()

        group.enable()
        self.session.commit()

        AuditLog.log(self.session, self.current_user.id, 'enable_group',
                     'Enabled group.', on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #40
0
    def get(self, user_id=None, name=None):
        self.handle_refresh()
        user = User.get(self.session, user_id, name)

        if not user or not user.role_user:
            return self.notfound()

        group = Group.get(self.session, name=name)
        actor = self.current_user
        graph = self.graph
        session = self.session
        self.render("service.html",
                    user=user,
                    group=group,
                    **get_service_account_view_template_vars(session, actor, user, group, graph)
                    )
Beispiel #41
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not self.current_user.my_role(members):
            return self.forbidden()

        group.revoke_member(self.current_user, self.current_user, "User self-revoked.")

        AuditLog.log(self.session, self.current_user.id, 'leave_group',
                     '{} left the group.'.format(self.current_user.name),
                     on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #42
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        form = GroupEditForm(self.request.arguments, obj=group)
        if not form.validate():
            return self.render(
                "group-edit.html", group=group, form=form,
                alerts=self.get_form_alerts(form.errors)
            )

        if (group.groupname != form.data["groupname"] and
                is_service_account(self.session, group=group)):
            form.groupname.errors.append("You cannot change the name of service account groups")
            return self.render(
                "group-edit.html", group=group, form=form,
                alerts=self.get_form_alerts(form.errors)
            )

        group.groupname = form.data["groupname"]
        group.description = form.data["description"]
        group.canjoin = form.data["canjoin"]
        group.auto_expire = form.data["auto_expire"]
        Counter.incr(self.session, "updates")

        try:
            self.session.commit()
        except IntegrityError:
            self.session.rollback()
            form.groupname.errors.append(
                "{} already exists".format(form.data["groupname"])
            )
            return self.render(
                "group-edit.html", group=group, form=form,
                alerts=self.get_form_alerts(form.errors)
            )

        AuditLog.log(self.session, self.current_user.id, 'edit_group',
                     'Edited group.', on_group_id=group.id)

        return self.redirect("/groups/{}".format(group.name))
    def get(self, name=None):
        grantable = self.current_user.my_grantable_permissions()
        if not grantable:
            return self.forbidden()

        group = Group.get(self.session, None, name)
        if not group:
            return self.notfound()

        form = PermissionGrantForm()
        form.permission.choices = [["", "(select one)"]]
        for perm in grantable:
            grantable = "{} ({})".format(perm[0].name, perm[1])
            form.permission.choices.append([perm[0].name, grantable])

        return self.render(
            "permission-grant.html", form=form, group=group,
        )
Beispiel #44
0
    def get(self, group_id=None, name=None, name2=None, member_type=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if self.current_user.name == name2:
            return self.forbidden()

        members = group.my_members()
        my_role = user_role(self.current_user, members)
        if my_role not in ("manager", "owner", "np-owner"):
            return self.forbidden()

        member = members.get((member_type.capitalize(), name2), None)
        if not member:
            return self.notfound()

        edge = GroupEdge.get(
            self.session,
            group_id=group.id,
            member_type=OBJ_TYPES[member.type],
            member_pk=member.id,
        )
        if not edge:
            return self.notfound()

        form = GroupEditMemberForm(self.request.arguments)
        form.role.choices = [["member", "Member"]]
        if my_role in ("owner", "np-owner"):
            form.role.choices.append(["manager", "Manager"])
            form.role.choices.append(["owner", "Owner"])
            form.role.choices.append(["np-owner", "No-Permissions Owner"])

        form.role.data = edge.role
        form.expiration.data = edge.expiration.strftime(
            "%m/%d/%Y") if edge.expiration else None

        self.render(
            "group-edit-member.html",
            group=group,
            member=member,
            edge=edge,
            form=form,
        )
Beispiel #45
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not user_role(self.current_user, members):
            return self.forbidden()

        group.revoke_member(self.current_user, self.current_user,
                            "User self-revoked.")

        AuditLog.log(self.session,
                     self.current_user.id,
                     'leave_group',
                     '{} left the group.'.format(self.current_user.name),
                     on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #46
0
    def get(self, name=None):
        grantable = user_grantable_permissions(self.session, self.current_user)
        if not grantable:
            return self.forbidden()

        group = Group.get(self.session, None, name)
        if not group:
            return self.notfound()

        form = PermissionGrantForm()
        form.permission.choices = [["", "(select one)"]]
        for perm in grantable:
            grantable = "{} ({})".format(perm[0].name, perm[1])
            form.permission.choices.append([perm[0].name, grantable])

        return self.render(
            "permission-grant.html",
            form=form,
            group=group,
        )
    def get(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        # Only members can request permissions
        if not self.current_user.is_member(group.my_members()):
            return self.forbidden()

        args_by_perm = get_grantable_permissions(
            self.session, settings.restricted_ownership_permissions)
        dropdown_form, text_form = GroupPermissionRequest._get_forms(
            args_by_perm, None)

        self.render("group-permission-request.html",
                    dropdown_form=dropdown_form,
                    text_form=text_form,
                    group=group,
                    args_by_perm_json=json.dumps(args_by_perm),
                    dropdown_help=settings.permission_request_dropdown_help,
                    text_help=settings.permission_request_text_help)
def test_group_add_remove_member(make_session, session, users, groups):
    make_session.return_value = session

    username = '******'
    groupname = 'team-sre'

    # add
    assert (u'User', username) not in groups[groupname].my_members()
    call_main('group', 'add_member', '--owner', groupname, username)
    all_members = Group.get(session, name=groupname).my_members()
    assert (u'User', username) in all_members
    _, _, _, role, _, _ = all_members[(u'User', username)]
    assert GROUP_EDGE_ROLES[role] == "owner"

    # remove
    call_main('group', 'remove_member', groupname, username)
    assert (u'User', username) not in Group.get(session,
                                                name=groupname).my_members()

    # bulk add
    usernames = {'*****@*****.**', '*****@*****.**', '*****@*****.**'}
    call_main('group', 'add_member', '--member', groupname, *usernames)
    members = {
        u
        for _, u in Group.get(session, name=groupname).my_members().keys()
    }
    assert usernames.issubset(members)

    # bulk remove
    call_main('group', 'remove_member', groupname, *usernames)
    members = {
        u
        for _, u in Group.get(session, name=groupname).my_members().keys()
    }
    assert not members.intersection(usernames)

    # check user/group name
    call_main('group', 'add_member', '--member', 'invalid group name',
              username)
    assert (u'User', username) not in Group.get(session,
                                                name=groupname).my_members()

    bad_username = '******'
    call_main('group', 'add_member', '--member', groupname, bad_username)
    assert (u'User',
            bad_username) not in Group.get(session,
                                           name=groupname).my_members()
Beispiel #49
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        if not user_role(self.current_user, members) in ("owner", "np-owner"):
            return self.forbidden()

        # Enabling and disabling service accounts via the group endpoints is forbidden
        # because we need the preserve_membership data that is only available via the
        # UserEnable form.
        if is_service_account(self.session, group=group):
            return self.forbidden()

        group.enable()

        self.session.commit()

        AuditLog.log(self.session, self.current_user.id, "enable_group", "Enabled group.", on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
    def get(self, group_id=None, name=None, name2=None, member_type=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if self.current_user.name == name2:
            return self.forbidden()

        members = group.my_members()
        my_role = self.current_user.my_role(members)
        if my_role not in ("manager", "owner", "np-owner"):
            return self.forbidden()

        member = members.get((member_type.capitalize(), name2), None)
        if not member:
            return self.notfound()

        edge = GroupEdge.get(
            self.session,
            group_id=group.id,
            member_type=OBJ_TYPES[member.type],
            member_pk=member.id,
        )
        if not edge:
            return self.notfound()

        form = GroupEditMemberForm(self.request.arguments)
        form.role.choices = [["member", "Member"]]
        if my_role in ("owner", "np-owner"):
            form.role.choices.append(["manager", "Manager"])
            form.role.choices.append(["owner", "Owner"])
            form.role.choices.append(["np-owner", "No-Permissions Owner"])

        form.role.data = edge.role
        form.expiration.data = edge.expiration.strftime("%m/%d/%Y") if edge.expiration else None

        self.render(
            "group-edit-member.html", group=group, member=member, edge=edge, form=form,
        )
Beispiel #51
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        form = GroupRemoveForm(self.request.arguments)
        if not form.validate():
            return self.send_error(status_code=400)

        member_type, member_name = form.data["member_type"], form.data["member"]

        members = group.my_members()
        if not members.get((member_type.capitalize(), member_name), None):
            return self.notfound()

        removed_member = get_user_or_group(self.session, member_name, user_or_group=member_type)

        if self.current_user == removed_member:
            return self.send_error(
                status_code=400,
                reason="Can't remove yourself. Leave group instead."
            )

        if (is_service_account(self.session, group=group) and
                get_service_account(self.session, group=group).user.name == removed_member.name):
            return self.send_error(
                status_code=400,
                reason="Can't remove a service account user from the service account group."
            )

        group.revoke_member(self.current_user, removed_member, "Removed by owner/np-owner/manager")
        AuditLog.log(self.session, self.current_user.id, 'remove_from_group',
                     '{} was removed from the group.'.format(removed_member.name),
                     on_group_id=group.id, on_user_id=removed_member.id)
        return self.redirect("/groups/{}?refresh=yes".format(group.name))
    def get(self, request_id, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        my_role = self.current_user.my_role(members)
        if my_role not in ("manager", "owner", "np-owner"):
            return self.forbidden()

        request = self.session.query(Request).filter_by(id=request_id).scalar()
        if not request:
            return self.notfound()

        form = GroupRequestModifyForm(self.request.arguments)
        form.status.choices = self._get_choices(request.status)

        updates = request.my_status_updates()

        self.render(
            "group-request-update.html", group=group, request=request,
            members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates
        )
Beispiel #53
0
    def post(self):
        form = GroupCreateForm(self.request.arguments)
        if not form.validate():
            return self.render(
                "group-create.html", form=form,
                alerts=self.get_form_alerts(form.errors)
            )

        user = self.get_current_user()

        group = Group(
            groupname=form.data["groupname"],
            description=form.data["description"],
            canjoin=form.data["canjoin"],
            auto_expire=form.data["auto_expire"],
        )
        try:
            group.add(self.session)
            self.session.flush()
        except IntegrityError:
            self.session.rollback()
            form.groupname.errors.append(
                "{} already exists".format(form.data["groupname"])
            )
            return self.render(
                "group-create.html", form=form,
                alerts=self.get_form_alerts(form.errors)
            )

        group.add_member(user, user, "Group Creator", "actioned", None, form.data["creatorrole"])
        self.session.commit()

        AuditLog.log(self.session, self.current_user.id, 'create_group',
                     'Created new group.', on_group_id=group.id)

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #54
0
def test_group_add_remove_member(make_session, session, users, groups):
    make_session.return_value = session

    username = "******"
    groupname = "team-sre"

    # add
    assert (u"User", username) not in groups[groupname].my_members()
    call_main("group", "add_member", "--owner", groupname, username)
    all_members = Group.get(session, name=groupname).my_members()
    assert (u"User", username) in all_members
    _, _, _, role, _, _ = all_members[(u"User", username)]
    assert GROUP_EDGE_ROLES[role] == "owner"

    # remove
    call_main("group", "remove_member", groupname, username)
    assert (u"User", username) not in Group.get(session, name=groupname).my_members()

    # bulk add
    usernames = {"*****@*****.**", "*****@*****.**", "*****@*****.**"}
    call_main("group", "add_member", "--member", groupname, *usernames)
    members = {u for _, u in Group.get(session, name=groupname).my_members().keys()}
    assert usernames.issubset(members)

    # bulk remove
    call_main("group", "remove_member", groupname, *usernames)
    members = {u for _, u in Group.get(session, name=groupname).my_members().keys()}
    assert not members.intersection(usernames)

    # check user/group name
    call_main("group", "add_member", "--member", "invalid group name", username)
    assert (u"User", username) not in Group.get(session, name=groupname).my_members()

    bad_username = "******"
    call_main("group", "add_member", "--member", groupname, bad_username)
    assert (u"User", bad_username) not in Group.get(session, name=groupname).my_members()
Beispiel #55
0
def notify_edge_expiration(settings, session, edge):
    """Send notification that an edge has expired.

    Handles email notification and audit logging.

    Args:
        settings (Settings): Grouper Settings object for current run.
        session (Session): Object for db session.
        edge (GroupEdge): The expiring edge.
    """
    # TODO(herb): get around circular depdendencies; long term remove call to
    # send_async_email() from grouper.models
    from grouper.model_soup import Group
    from grouper.models.base.constants import OBJ_TYPES_IDX
    from grouper.models.user import User

    # TODO(rra): Arbitrarily use the first listed owner of the group from which membership expired
    # as the actor, since we have to provide an actor and we didn't record who set the expiration on
    # the edge originally.
    actor_id = next(edge.group.my_owners().itervalues()).id

    # Pull data about the edge and the affected user or group.
    group_name = edge.group.name
    if OBJ_TYPES_IDX[edge.member_type] == "User":
        user = User.get(session, pk=edge.member_pk)
        member_name = user.username
        recipients = [member_name]
        member_is_user = True
    else:
        subgroup = Group.get(session, pk=edge.member_pk)
        member_name = subgroup.groupname
        recipients = subgroup.my_owners_as_strings()
        member_is_user = False

    # Log to the audit log.  How depends on whether a user's membership has expired or a group's
    # membership has expired.
    audit_data = {
        "action": "expired_from_group",
        "actor_id": actor_id,
        "description": "{} expired out of the group".format(member_name),
    }
    if member_is_user:
        AuditLog.log(session,
                     on_user_id=user.id,
                     on_group_id=edge.group_id,
                     **audit_data)
    else:
        # Make an audit log entry for both the subgroup and the parent group so that it will show up
        # in the FE view for both groups.
        AuditLog.log(session, on_group_id=edge.group_id, **audit_data)
        AuditLog.log(session, on_group_id=subgroup.id, **audit_data)

    # Send email notification to the affected people.
    email_context = {
        "group_name": group_name,
        "member_name": member_name,
        "member_is_user": member_is_user,
    }
    send_email(
        session=session,
        recipients=recipients,
        subject="Membership in {} expired".format(group_name),
        template="expiration",
        settings=settings,
        context=email_context,
    )
Beispiel #56
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        if not user_can_manage_group(self.session, group, self.current_user):
            return self.forbidden()

        members = group.my_members()
        my_role = user_role(self.current_user, members)
        form = self.get_form(role=my_role)
        if not form.validate():
            return self.render(
                "group-add.html", form=form, group=group,
                alerts=self.get_form_alerts(form.errors)
            )

        member = get_user_or_group(self.session, form.data["member"])
        if member.type == "User" and is_service_account(self.session, member):
            # For service accounts, we want to always add the group to other groups, not the user
            member = get_service_account(self.session, user=member).group
        if not member:
            form.member.errors.append("User or group not found.")
        elif (member.type, member.name) in group.my_members():
            form.member.errors.append("User or group is already a member of this group.")
        elif group.name == member.name:
            form.member.errors.append("By definition, this group is a member of itself already.")

        # Ensure this doesn't violate auditing constraints
        fail_message = 'This join is denied with this role at this time.'
        try:
            user_can_join = assert_can_join(group, member, role=form.data["role"])
        except UserNotAuditor as e:
            user_can_join = False
            fail_message = e
        if not user_can_join:
            form.member.errors.append(fail_message)

        if form.member.errors:
            return self.render(
                "group-add.html", form=form, group=group,
                alerts=self.get_form_alerts(form.errors)
            )

        expiration = None
        if form.data["expiration"]:
            expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y")

        try:
            group.add_member(
                requester=self.current_user,
                user_or_group=member,
                reason=form.data["reason"],
                status='actioned',
                expiration=expiration,
                role=form.data["role"]
            )
        except InvalidRoleForMember as e:
            return self.render(
                "group-add.html", form=form, group=group,
                alerts=[
                    Alert('danger', e.message)
                ]
            )

        self.session.commit()

        AuditLog.log(self.session, self.current_user.id, 'join_group',
                     '{} added to group with role: {}'.format(
                         member.name, form.data["role"]),
                     on_group_id=group.id)

        if member.type == "User":
            send_email(
                self.session,
                [member.name],
                'Added to group: {}'.format(group.name),
                'request_actioned',
                settings,
                {
                    'group_name': group.name,
                    'actioned_by': self.current_user.name,
                    'reason': form.data['reason'],
                    'expiration': expiration,
                    'role': form.data['role'],
                }
            )

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
Beispiel #57
0
    def post(self, request_id, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        members = group.my_members()
        my_role = user_role(self.current_user, members)
        if my_role not in ("manager", "owner", "np-owner"):
            return self.forbidden()

        request = self.session.query(Request).filter_by(id=request_id).scalar()
        if not request:
            return self.notfound()

        form = GroupRequestModifyForm(self.request.arguments)
        form.status.choices = self._get_choices(request.status)

        updates = request.my_status_updates()

        if not form.validate():
            return self.render("group-request-update.html",
                               group=group,
                               request=request,
                               members=members,
                               form=form,
                               alerts=self.get_form_alerts(form.errors),
                               statuses=REQUEST_STATUS_CHOICES,
                               updates=updates)

        # We have to test this here, too, to ensure that someone can't sneak in with a pending
        # request that used to be allowed.
        if form.data["status"] != "cancelled":
            fail_message = 'This join is denied with this role at this time.'
            try:
                user_can_join = assert_can_join(request.requesting,
                                                request.get_on_behalf(),
                                                role=request.edge.role)
            except UserNotAuditor as e:
                user_can_join = False
                fail_message = e
            if not user_can_join:
                return self.render("group-request-update.html",
                                   group=group,
                                   request=request,
                                   members=members,
                                   form=form,
                                   statuses=REQUEST_STATUS_CHOICES,
                                   updates=updates,
                                   alerts=[
                                       Alert('danger', fail_message,
                                             'Audit Policy Enforcement')
                                   ])

        request.update_status(self.current_user, form.data["status"],
                              form.data["reason"])
        self.session.commit()

        AuditLog.log(self.session,
                     self.current_user.id,
                     'update_request',
                     'Updated request to status: {}'.format(
                         form.data["status"]),
                     on_group_id=group.id,
                     on_user_id=request.requester.id)

        edge = self.session.query(GroupEdge).filter_by(
            id=request.edge_id).one()

        approver_mail_to = [
            user.name for user in group.my_approver_users()
            if user.name != self.current_user.name
            and user.name != request.requester.username
        ]

        send_email(
            self.session,
            approver_mail_to,
            "Request to join {} by {} has been {}".format(
                group.groupname, request.requester.name, form.data['status']),
            "approver_request_updated",
            settings,
            {
                'group_name': group.name,
                'requester': request.requester.username,
                'changed_by': self.current_user.name,
                'status': form.data['status'],
                'role': edge.role,
                'reason': form.data['reason'],
            },
        )

        if form.data['status'] == 'actioned':
            send_email(
                self.session, [request.requester.name],
                'Added to group: {}'.format(group.groupname),
                'request_actioned', settings, {
                    'group_name': group.name,
                    'actioned_by': self.current_user.name,
                    'reason': form.data['reason'],
                    'expiration': edge.expiration,
                    'role': edge.role,
                })
        elif form.data['status'] == 'cancelled':
            send_email(
                self.session, [request.requester.name],
                'Request to join cancelled: {}'.format(group.groupname),
                'request_cancelled', settings, {
                    'group_name': group.name,
                    'cancelled_by': self.current_user.name,
                    'reason': form.data['reason'],
                    'expiration': edge.expiration,
                    'role': edge.role,
                })

        # No explicit refresh because handler queries SQL.
        if form.data['redirect_aggregate']:
            return self.redirect("/user/requests")
        else:
            return self.redirect("/groups/{}/requests".format(group.name))