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))
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.disable() self.session.commit() AuditLog.log(self.session, self.current_user.id, "disable_group", "Disabled group.", on_group_id=group.id) if group.audit: # complete the audit group.audit.complete = True self.session.commit() AuditLog.log( self.session, self.current_user.id, "complete_audit", "Disabling group completes group audit.", on_group_id=group.id, ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
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, "ssh") assert "team-sre" in [g[0] for g in permission.get_mapped_groups()] group.disable() assert "team-sre" not in [g[0] for g in permission.get_mapped_groups()]
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 = 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)) group.groupname = form.data["groupname"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] 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 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'
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)
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() members = group.my_members() if not self.current_user.my_role(members): return self.forbidden() return self.render( "group-leave.html", group=group )
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"], )
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)
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)
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))
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))
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() is_owner = self.current_user.my_role_index(members) in OWNER_ROLE_INDICES # 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, is_owner=is_owner, permission_requests_pending=permission_requests_pending )
def sync_db_command(args): 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!" admin_group.grant_permission(permission) session.commit()
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, )
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 )
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) self.render( "group-requests.html", group=group, requests=requests, members=members, status=status, statuses=REQUEST_STATUS_CHOICES, offset=offset, limit=limit, total=total )
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()
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.models import AuditLog, Group, OBJ_TYPES_IDX, 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, )
def post(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(self.request.arguments) form.permission.choices = [["", "(select one)"]] for perm in grantable: grantable_str = "{} ({})".format(perm[0].name, perm[1]) form.permission.choices.append([perm[0].name, grantable_str]) if not form.validate(): return self.render( "permission-grant.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) permission = Permission.get(self.session, form.data["permission"]) if not permission: return self.notfound() # Shouldn't happen. allowed = False for perm in grantable: if perm[0].name == permission.name: if matches_glob(perm[1], form.data["argument"]): allowed = True if not allowed: form.argument.errors.append("You do not have grant authority over that permission/argument combination.") return self.render( "permission-grant.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) # If the permission is audited, then see if the subtree meets auditing requirements. if permission.audited: fail_message = ( "Permission is audited and this group (or a subgroup) contains " + "owners, np-owners, or managers who have not received audit training." ) try: permission_ok = assert_controllers_are_auditors(group) except UserNotAuditor as e: permission_ok = False fail_message = e if not permission_ok: form.permission.errors.append(fail_message) return self.render( "permission-grant.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) try: group.grant_permission(permission, argument=form.data["argument"]) except IntegrityError: form.argument.errors.append("Permission and Argument already mapped to this group.") return self.render( "permission-grant.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) self.session.commit() AuditLog.log( self.session, self.current_user.id, "grant_permission", "Granted permission with argument: {}".format(form.data["argument"]), on_permission_id=permission.id, on_group_id=group.id, ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() # only owner of group can request permissions for that group role_index = self.current_user.my_role_index(group.my_members()) if role_index not in OWNER_ROLE_INDICES: return self.forbidden() # check inputs args_by_perm = get_grantable_permissions(self.session, settings.restricted_ownership_permissions) dropdown_form, text_form = GroupPermissionRequest._get_forms(args_by_perm, self.request.arguments) argument_type = self.request.arguments.get("argument_type") if argument_type and argument_type[0] == "text": form = text_form elif argument_type and argument_type[0] == "dropdown": form = dropdown_form form.argument.choices = [(a, a) for a in args_by_perm[form.permission_name.data]] else: # someone messing with the form self.log_message("unknown argument type", group_name=group.name, argument_type=argument_type) return self.forbidden() if not form.validate(): return 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), alerts=self.get_form_alerts(form.errors), dropdown_help=settings.permission_request_dropdown_help, text_help=settings.permission_request_text_help, ) permission = Permission.get(self.session, form.permission_name.data) assert permission is not None, "our prefilled permission should exist or we have problems" # save off request try: permissions.create_request(self.session, self.current_user, group, permission, form.argument.data, form.reason.data) except permissions.RequestAlreadyGranted: alerts = [Alert("danger", "This group already has this permission and argument.")] except permissions.RequestAlreadyExists: alerts = [Alert("danger", "Request for permission and argument already exists, please wait patiently.")] except permissions.NoOwnersAvailable: self.log_message("prefilled perm+arg have no owner", group_name=group.name, permission_name=permission.name, argument=form.argument.data) alerts = [Alert("danger", "No owners available for requested permission and argument." " If this error persists please contact an adminstrator.")] else: alerts = None if alerts: return 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), alerts=alerts, ) else: return self.redirect("/groups/{}".format(group.name))
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 = 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() 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() if form.data['status'] == 'actioned': send_email( self.session, [request.requester.name], 'Added to group: {}'.format(group.groupname), 'request_actioned', settings, { 'group': 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': 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))
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() form = GroupJoinForm(self.request.arguments) form.member.choices = self._get_choices(group) if not form.validate(): return self.render( "group-join.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) member = self._get_member(form.data["member"]) 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: return self.render( "group-join.html", form=form, group=group, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ] ) if group.canjoin == "nobody": fail_message = 'This group cannot be joined at this time.' return self.render( "group-join.html", form=form, group=group, alerts=[ Alert('danger', fail_message) ] ) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") group.add_member( requester=self.current_user, user_or_group=member, reason=form.data["reason"], status=GROUP_JOIN_CHOICES[group.canjoin], expiration=expiration, role=form.data["role"] ) self.session.commit() if group.canjoin == 'canask': AuditLog.log(self.session, self.current_user.id, 'join_group', '{} requested to join with role: {}'.format( member.name, form.data["role"]), on_group_id=group.id) mail_to = [ user.name for user in group.my_users() if GROUP_EDGE_ROLES[user.role] in ('manager', 'owner', 'np-owner') ] email_context = { "requester": member.name, "requested_by": self.current_user.name, "requested": group.name, "reason": form.data["reason"], "expiration": expiration, "role": form.data["role"], } send_email(self.session, mail_to, 'Request to join: {}'.format(group.name), 'pending_request', settings, email_context) elif group.canjoin == 'canjoin': AuditLog.log(self.session, self.current_user.id, 'join_group', '{} auto-approved to join with role: {}'.format( member.name, form.data["role"]), on_group_id=group.id) else: raise Exception('Need to update the GroupJoin.post audit logging') return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self): form = AuditCreateForm(self.request.arguments) if not form.validate(): return self.render( "audit-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) user = self.get_current_user() if not user.has_permission(AUDIT_MANAGER): return self.forbidden() # Step 1, detect if there are non-completed audits and fail if so. open_audits = self.session.query(Audit).filter( Audit.complete == False).all() if open_audits: raise Exception("Sorry, there are audits in progress.") ends_at = datetime.strptime(form.data["ends_at"], "%m/%d/%Y") # Step 2, find all audited groups and schedule audits for each. audited_groups = [] for groupname in self.graph.groups: if not self.graph.get_group_details(groupname)["audited"]: continue group = Group.get(self.session, name=groupname) audit = Audit( group_id=group.id, ends_at=ends_at, ) try: audit.add(self.session) self.session.flush() except IntegrityError: self.session.rollback() raise Exception("Failed to start the audit. Please try again.") # Update group with new audit audited_groups.append(group) group.audit_id = audit.id # Step 3, now get all members of this group and set up audit rows for those edges. for member in group.my_members().values(): auditmember = AuditMember( audit_id=audit.id, edge_id=member.edge_id ) try: auditmember.add(self.session) except IntegrityError: self.session.rollback() raise Exception("Failed to start the audit. Please try again.") self.session.commit() AuditLog.log(self.session, self.current_user.id, 'start_audit', 'Started global audit.', category=AuditLogCategory.audit) # Calculate schedule of emails, basically we send emails at various periods in advance # of the end of the audit period. schedule_times = [] not_before = datetime.utcnow() + timedelta(1) for days_prior in (28, 21, 14, 7, 3, 1): email_time = ends_at - timedelta(days_prior) email_time.replace(hour=17, minute=0, second=0) if email_time > not_before: schedule_times.append((days_prior, email_time)) # Now send some emails. We do this separately/later to ensure that the audits are all # created. Email notifications are sent multiple times if group audits are still # outstanding. for group in audited_groups: mail_to = [ member.name for member in group.my_users() if GROUP_EDGE_ROLES[member.role] in ('owner', 'np-owner') ] send_email(self.session, mail_to, 'Group Audit: {}'.format(group.name), 'audit_notice', settings, {"group": group.name, "ends_at": ends_at}) for days_prior, email_time in schedule_times: send_async_email( self.session, mail_to, 'Group Audit: {} - {} day(s) left'.format(group.name, days_prior), 'audit_notice_reminder', settings, { "group": group.name, "ends_at": ends_at, "days_left": days_prior, }, email_time, async_key='audit-{}'.format(group.id), ) return self.redirect("/audits")
def post(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() if member.type == "Group": user_or_group = Group.get(self.session, member.id) else: user_or_group = User.get(self.session, member.id) if not user_or_group: 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"]) if not form.validate(): return self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, alerts=self.get_form_alerts(form.errors), ) fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(group, user_or_group, role=form.data["role"]) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: return self.render( "group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ] ) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") group.edit_member(self.current_user, user_or_group, form.data["reason"], role=form.data["role"], expiration=expiration) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def _load_permissions_by_group_name(session, group_name): group = Group.get(session, name=group_name) return [name for _, name, _, _, _ in group.my_permissions()]