def get_user_view_template_vars(session, actor, user, graph): # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} if user.is_service_account: ret["can_control"] = ( can_manage_service_account(session, user.service_account, actor) or user_is_user_admin(session, actor) ) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner(session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{'name': g.name, 'type': 'Group', 'role': ge._role} for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = ["{} ({})".format(perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key)] ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get('permissions', []) return ret
def post(self, request_id): # check for request existence request = permissions.get_request_by_id(self.session, request_id) if not request: return self.notfound() # check that this user should be actioning this request user_requests, total = permissions.get_requests_by_owner( self.session, self.current_user, status="pending", limit=None, offset=0) user_request_ids = [ur.id for ur in user_requests.requests] if request.id not in user_request_ids: return self.forbidden() form = PermissionRequestUpdateForm(self.request.arguments) form.status.choices = self._get_choices(request.status) if not form.validate(): change_comment_list = [ (sc, user_requests.comment_by_status_change_id[sc.id]) for sc in user_requests.status_change_by_request_id[request.id] ] return self.render("permission-request-update.html", form=form, request=request, change_comment_list=change_comment_list, statuses=REQUEST_STATUS_CHOICES, alerts=self.get_form_alerts(form.errors)) try: permissions.update_request(self.session, request, self.current_user, form.status.data, form.reason.data) except UserNotAuditor as e: alerts = [Alert("danger", str(e))] change_comment_list = [ (sc, user_requests.comment_by_status_change_id[sc.id]) for sc in user_requests.status_change_by_request_id[request.id] ] return self.render("permission-request-update.html", form=form, request=request, change_comment_list=change_comment_list, statuses=REQUEST_STATUS_CHOICES, alerts=alerts) return self.redirect("/permissions/requests?status=pending")
def get_user_view_template_vars(session, actor, user, graph): ret = {} ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate( session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner( session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{ 'name': g.name, 'type': 'Group', 'role': ge._role } for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = [ "{} ({})".format( perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key) ] ret["permissions"] = user_md.get('permissions', []) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens return ret
def get(self, user_id=None, name=None): self.handle_refresh() user = User.get(self.session, user_id, name) if user_id is not None: user = self.session.query(User).filter_by(id=user_id).scalar() else: user = self.session.query(User).filter_by(username=name).scalar() if not user: return self.notfound() can_control = user.name == self.current_user.name or self.current_user.user_admin can_disable = UserDisable.check_access(self.current_user, user) can_enable = UserEnable.check_access(self.current_user, user) if user.id == self.current_user.id: num_pending_group_requests = self.current_user.my_requests_aggregate().count() _, num_pending_perm_requests = get_requests_by_owner(self.session, self.current_user, status='pending', limit=1, offset=0) else: num_pending_group_requests = None num_pending_perm_requests = None try: user_md = self.graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} open_audits = user.my_open_audits() group_edge_list = group_biz.get_groups_by_user(self.session, user) if user.enabled else [] groups = [{'name': g.name, 'type': 'Group', 'role': ge._role} for g, ge in group_edge_list] public_keys = user.my_public_keys() permissions = user_md.get('permissions', []) log_entries = user.my_log_entries() self.render("user.html", user=user, groups=groups, public_keys=public_keys, can_control=can_control, permissions=permissions, can_disable=can_disable, can_enable=can_enable, user_tokens=user.tokens, log_entries=log_entries, num_pending_group_requests=num_pending_group_requests, num_pending_perm_requests=num_pending_perm_requests, open_audits=open_audits, )
def get(self): form = PermissionRequestsForm(self.request.arguments) form.status.choices = [("", "")] + [(k, k) for k in REQUEST_STATUS_CHOICES] if not form.validate(): alerts = self.get_form_alerts(form.errors) request_tuple = None total = 0 else: alerts = [] request_tuple, total = permissions.get_requests_by_owner(self.session, self.current_user, status=form.status.data, limit=form.limit.data, offset=form.offset.data) return self.render("permission-requests.html", form=form, request_tuple=request_tuple, alerts=alerts, total=total, statuses=REQUEST_STATUS_CHOICES)
def get(self, request_id): # check for request existence request = permissions.get_request_by_id(self.session, request_id) if not request: return self.notfound() # check that this user should be actioning this request user_requests, total = permissions.get_requests_by_owner(self.session, self.current_user, status="pending", limit=None, offset=0) user_request_ids = [ur.id for ur in user_requests.requests] if request.id not in user_request_ids: return self.forbidden() form = PermissionRequestUpdateForm(self.request.arguments) form.status.choices = self._get_choices(request.status) # compile list of changes to this request change_comment_list = [(sc, user_requests.comment_by_status_change_id[sc.id]) for sc in user_requests.status_change_by_request_id[request.id]] return self.render("permission-request-update.html", form=form, request=request, change_comment_list=change_comment_list, statuses=REQUEST_STATUS_CHOICES)
def post(self, request_id): # check for request existence request = permissions.get_request_by_id(self.session, request_id) if not request: return self.notfound() # check that this user should be actioning this request user_requests, total = permissions.get_requests_by_owner(self.session, self.current_user, status="pending", limit=None, offset=0) user_request_ids = [ur.id for ur in user_requests.requests] if request.id not in user_request_ids: return self.forbidden() form = PermissionRequestUpdateForm(self.request.arguments) form.status.choices = self._get_choices(request.status) if not form.validate(): change_comment_list = [(sc, user_requests.comment_by_status_change_id[sc.id]) for sc in user_requests.status_change_by_request_id[request.id]] return self.render("permission-request-update.html", form=form, request=request, change_comment_list=change_comment_list, statuses=REQUEST_STATUS_CHOICES, alerts=self.get_form_alerts(form.errors)) try: permissions.update_request(self.session, request, self.current_user, form.status.data, form.reason.data) except UserNotAuditor as e: alerts = [Alert("danger", str(e))] change_comment_list = [(sc, user_requests.comment_by_status_change_id[sc.id]) for sc in user_requests.status_change_by_request_id[request.id]] return self.render("permission-request-update.html", form=form, request=request, change_comment_list=change_comment_list, statuses=REQUEST_STATUS_CHOICES, alerts=alerts) return self.redirect("/permissions/requests?status=pending")
def get(self): form = PermissionRequestsForm(self.request.arguments) form.status.choices = [("", "")] + [(k, k) for k in REQUEST_STATUS_CHOICES] if not form.validate(): alerts = self.get_form_alerts(form.errors) request_tuple = None total = 0 else: alerts = [] request_tuple, total = permissions.get_requests_by_owner( self.session, self.current_user, status=form.status.data, limit=form.limit.data, offset=form.offset.data) return self.render("permission-requests.html", form=form, request_tuple=request_tuple, alerts=alerts, total=total, statuses=REQUEST_STATUS_CHOICES)
def test_permission_request_flow(session, standard_graph, groups, grantable_permissions, http_client, base_url): """Test that a permission request gets into the system correctly and notifications are sent correctly.""" perm_grant, _, perm1, perm2 = grantable_permissions grant_permission(groups["all-teams"], perm_grant, argument="grantable.*") # REQUEST: 'grantable.one', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode( { "permission_name": "grantable.one", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text", } ), headers={"X-Grouper-User": username}, ) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "only one user (and no group) should receive notification for request" perms = _load_permissions_by_group_name(session, "serving-team") assert len(perms) == 1 assert "grantable.one" not in perms, "requested permission shouldn't be granted immediately" user = User.get(session, name="*****@*****.**") request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests) == 0, "random user shouldn't have a request" user = User.get(session, name="*****@*****.**") request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests) == 1, "user in group with grant should have a request" # APPROVE grant: have '*****@*****.**' action this request as owner of # 'all-teams' which has the grant permission for the requested permission request_id = request_tuple.requests[0].id fe_url = url(base_url, "/permissions/requests/{}".format(request_id)) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode({"status": "actioned", "reason": "lgtm"}), headers={"X-Grouper-User": user.name}, ) assert resp.code == 200 perms = _load_permissions_by_group_name(session, "serving-team") assert len(perms) == 2 assert "grantable.one" in perms, "requested permission shouldn't be granted immediately" emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "requester should receive email as well" # (re)REQUEST: 'grantable.one', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode( { "permission_name": "grantable.one", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text", } ), headers={"X-Grouper-User": username}, ) assert resp.code == 200 user = User.get(session, name="*****@*****.**") request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests) == 0, "request for existing perm should fail" # REQUEST: 'grantable.two', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode( { "permission_name": "grantable.two", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text", } ), headers={"X-Grouper-User": username}, ) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "only one user (and no group) should receive notification for request" perms = _load_permissions_by_group_name(session, "serving-team") assert len(perms) == 2 assert "grantable.two" not in perms, "requested permission shouldn't be granted immediately" user = User.get(session, name="*****@*****.**") request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests) == 0, "random user shouldn't have a request" user = User.get(session, name="*****@*****.**") request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests) == 1, "user in group with grant should have a request" # CANCEL request: have '*****@*****.**' cancel this request request_id = request_tuple.requests[0].id fe_url = url(base_url, "/permissions/requests/{}".format(request_id)) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode({"status": "cancelled", "reason": "heck no"}), headers={"X-Grouper-User": user.name}, ) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "rejection email should be sent" perms = _load_permissions_by_group_name(session, "serving-team") assert len(perms) == 2 assert "grantable.two" not in perms, "no new permissions should be granted for this"
def test_permission_request_flow(session, standard_graph, groups, grantable_permissions, http_client, base_url): """Test that a permission request gets into the system correctly and notifications are sent correctly.""" perm_grant, _, perm1, perm2 = grantable_permissions grant_permission(groups["all-teams"], perm_grant, argument="grantable.*") # REQUEST: 'grantable.one', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ "permission_name": "grantable.one", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text" }), headers={'X-Grouper-User': username}) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len( emails ) == 1, "only one user (and no group) should receive notification for request" perms = _load_permissions_by_group_name(session, 'serving-team') assert len(perms) == 1 assert "grantable.one" not in perms, "requested permission shouldn't be granted immediately" user = User.get(session, name='*****@*****.**') request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len( request_tuple.requests) == 0, "random user shouldn't have a request" user = User.get(session, name='*****@*****.**') request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests ) == 1, "user in group with grant should have a request" # APPROVE grant: have '*****@*****.**' action this request as owner of # 'all-teams' which has the grant permission for the requested permission request_id = request_tuple.requests[0].id fe_url = url(base_url, "/permissions/requests/{}".format(request_id)) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ "status": "actioned", "reason": "lgtm" }), headers={'X-Grouper-User': user.name}) assert resp.code == 200 perms = _load_permissions_by_group_name(session, 'serving-team') assert len(perms) == 2 assert "grantable.one" in perms, "requested permission shouldn't be granted immediately" emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "requester should receive email as well" # (re)REQUEST: 'grantable.one', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ "permission_name": "grantable.one", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text" }), headers={'X-Grouper-User': username}) assert resp.code == 200 user = User.get(session, name='*****@*****.**') request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len( request_tuple.requests) == 0, "request for existing perm should fail" # REQUEST: 'grantable.two', 'some argument' for 'serving-team' groupname = "serving-team" username = "******" fe_url = url(base_url, "/groups/{}/permission/request".format(groupname)) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ "permission_name": "grantable.two", "argument": "some argument", "reason": "blah blah black sheep", "argument_type": "text" }), headers={'X-Grouper-User': username}) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len( emails ) == 1, "only one user (and no group) should receive notification for request" perms = _load_permissions_by_group_name(session, 'serving-team') assert len(perms) == 2 assert "grantable.two" not in perms, "requested permission shouldn't be granted immediately" user = User.get(session, name='*****@*****.**') request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len( request_tuple.requests) == 0, "random user shouldn't have a request" user = User.get(session, name='*****@*****.**') request_tuple, total = get_requests_by_owner(session, user, "pending", 10, 0) assert len(request_tuple.requests ) == 1, "user in group with grant should have a request" # CANCEL request: have '*****@*****.**' cancel this request request_id = request_tuple.requests[0].id fe_url = url(base_url, "/permissions/requests/{}".format(request_id)) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ "status": "cancelled", "reason": "heck no" }), headers={'X-Grouper-User': user.name}) assert resp.code == 200 emails = _get_unsent_and_mark_as_sent_emails(session) assert len(emails) == 1, "rejection email should be sent" perms = _load_permissions_by_group_name(session, 'serving-team') assert len(perms) == 2 assert "grantable.two" not in perms, "no new permissions should be granted for this"