Пример #1
0
def _create_agency_user_requests(request_id, agency_admins, guid_for_event):
    """
    Creates user_requests entries for agency administrators.
    :param request_id: Request being created
    :param agency_users: List of Users
    :param guid_for_event: guid used to create request events
    :return:
    """

    for admin in agency_admins:
        user_request = UserRequests(
            user_guid=admin.guid,
            request_user_type=user_type_request.AGENCY,
            request_id=request_id,
            permissions=Roles.query.filter_by(
                name=role.AGENCY_ADMIN).first().permissions)
        create_object(user_request)
        create_object(
            Events(request_id,
                   guid_for_event,
                   event_type.USER_ADDED,
                   previous_value=None,
                   new_value=user_request.val_for_events,
                   response_id=None,
                   timestamp=datetime.utcnow()))
Пример #2
0
def create_requests_search_set(requester, other_requester):
    """
    Generate 216 unique requests.
    Every combination of title content, description content, agency description content,
    title privacy, agency description privacy, and requester is guaranteed to be unique.
    """
    agency_eins = [
        ein[0] for ein in Agencies.query.with_entities(Agencies.ein).all()
    ]

    for title_private, agency_request_summary_private, is_requester in product(
            range(2), repeat=3):
        for title, description, agency_request_summary in product(
            ("foo", "bar", "qux"), repeat=3):
            agency_ein = random.choice(agency_eins)
            date_created = get_random_date(datetime(2015, 1, 1),
                                           datetime(2016, 1, 1))
            date_submitted = get_following_date(date_created)
            # TODO: use rf = RequestsFactory()
            request = Requests(generate_request_id(agency_ein),
                               title=title,
                               description=description,
                               agency_ein=agency_ein,
                               date_created=date_created,
                               date_submitted=date_submitted,
                               due_date=get_due_date(date_submitted,
                                                     ACKNOWLEDGMENT_DAYS_DUE,
                                                     'US/Eastern'),
                               submission=submission_methods.DIRECT_INPUT,
                               status=random.choice(
                                   (request_status.OPEN, request_status.CLOSED,
                                    request_status.OVERDUE,
                                    request_status.IN_PROGRESS,
                                    request_status.DUE_SOON)),
                               privacy={
                                   'title':
                                   bool(title_private),
                                   'agency_request_summary':
                                   bool(agency_request_summary_private)
                               })
            request.agency_request_summary = agency_request_summary
            create_object(request)
            user_request = UserRequests(
                user_guid=(requester.guid
                           if is_requester else other_requester.guid),
                auth_user_type=(requester.auth_user_type if is_requester else
                                other_requester.auth_user_type),
                request_id=request.id,
                request_user_type=user_type_request.REQUESTER,
                permissions=11)
            create_object(user_request)
Пример #3
0
 def __init__(self, request_id=None, clean=True):
     """
     :param request_id: request FOIL id
     :param clean: reset data?
     """
     self.clean = clean
     date_created = datetime.utcnow()
     date_submitted = get_following_date(date_created)
     agency_ein = '0860'
     self.request = Requests(
         request_id or generate_request_id(agency_ein),
         title="I would like my vital essence.",
         description="Someone has taken my vital essence "
         "and I would like it back.",
         agency_ein=agency_ein,
         date_created=date_created,
         date_submitted=date_submitted,
         due_date=get_due_date(date_submitted, ACKNOWLEDGMENT_DAYS_DUE),
         submission=submission_methods.DIRECT_INPUT,
         status=request_status.OPEN)
     create_object(self.request)
     self.requester = Users(
         guid=generate_user_guid(user_type_auth.PUBLIC_USER_NYC_ID),
         auth_user_type=user_type_auth.PUBLIC_USER_NYC_ID,
         agency_ein=agency_ein,
         first_name='Jane',
         last_name='Doe',
         email='*****@*****.**',
         email_validated=True,
         terms_of_use_accepted=True,
         title='The Janest')
     create_object(self.requester)
     self.user_request = UserRequests(
         user_guid=self.requester.guid,
         auth_user_type=self.requester.auth_user_type,
         request_id=self.request.id,
         request_user_type=user_type_request.REQUESTER,
         permissions=Roles.query.filter_by(
             name=PUBLIC_REQUESTER).first().permissions)
     create_object(self.user_request)
Пример #4
0
    def add_user(self, user, permissions=None, role=None, agent=None):
        """
        Assign user to request.
        If a role is not supplied, one will be provided and permissions
        will be set based on the user's status:
            anonymous           role_name.ANONYMOUS
            public              role_name.PUBLIC_REQUESTER
            agency admin        role_name.AGENCY_ADMIN
            agency user         role_name.AGENCY_OFFICER
            agency inactive     role_name.AGENCY_HELPER

        :param user: user to add
        :param permissions: permissions to grant to user
        :param role: role from which to retrieve permissions to grant to user
        :param agent: user performing this action
        :return: created UserRequests object
        """
        if role is None and permissions is None:
            if user.auth_user_type == user_type_auth.ANONYMOUS_USER:
                role = role_name.ANONYMOUS
            elif user.auth_user_type in user_type_auth.PUBLIC_USER_TYPES:
                role = role_name.PUBLIC_REQUESTER
            elif user.auth_user_type == user_type_auth.AGENCY_USER:
                if user.is_agency_active:
                    role = role_name.AGENCY_ADMIN if user.is_agency_admin else role_name.AGENCY_OFFICER
                else:
                    role = role_name.AGENCY_HELPER
        permissions = permissions or Roles.query.filter_by(
            name=role).one().permissions
        user_request = UserRequests(
            user_guid=user.guid,
            auth_user_type=user.auth_user_type,
            request_id=self.request.id,
            request_user_type=user_type_request.AGENCY
            if user.is_agency else user_type_request.REQUESTER,
            permissions=permissions)
        create_object(user_request)
        self.__create_event(event_type.USER_ADDED, user_request, agent)
        return user_request
Пример #5
0
def add_user_request(request_id, user_guid, permissions, point_of_contact):
    """
    Create a users permissions entry for a request and notify all agency administrators and the user that the permissions
    have changed.

    :param request_id: FOIL request ID
    :param user_guid: string guid of the user being edited
    :param permissions: Updated permissions values {'permission': true}
    :param point_of_contact: boolean value to set user as point of contact or not
    """
    user_request = UserRequests.query.filter_by(user_guid=user_guid,
                                                request_id=request_id).first()

    agency_name = Requests.query.filter_by(id=request_id).one().agency.name

    if user_request:
        raise UserRequestException(action="create", request_id=request_id, reason="UserRequest entry already exists.")

    user = Users.query.filter_by(guid=user_guid).one()

    agency_admin_emails = get_agency_emails(request_id, admins_only=True)

    added_permissions = []
    for i, val in enumerate(permission.ALL):
        if i in permissions:
            added_permissions.append(val)

    # send email to agency administrators
    safely_send_and_add_email(
        request_id,
        render_template(
            'email_templates/email_user_request_added.html',
            request_id=request_id,
            name=user.name,
            agency_name=agency_name,
            page=urljoin(flask_request.host_url, url_for('request.view', request_id=request_id)),
            added_permissions=[capability.label for capability in added_permissions],
            admin=True),
        'User Added to Request {}'.format(request_id),
        to=agency_admin_emails)

    # send email to user being added
    safely_send_and_add_email(
        request_id,
        render_template(
            'email_templates/email_user_request_added.html',
            request_id=request_id,
            name=user.name,
            agency_name=agency_name,
            page=urljoin(flask_request.host_url, url_for('request.view', request_id=request_id)),
            added_permissions=[capability.label for capability in added_permissions],
        ),
        'User Added to Request {}'.format(request_id),
        to=[user.notification_email or user.email])

    if point_of_contact and has_point_of_contact(request_id):
        remove_point_of_contact(request_id)
    user_request = UserRequests(
        user_guid=user.guid,
        request_id=request_id,
        request_user_type=user_type_request.AGENCY,
        permissions=0,
        point_of_contact=point_of_contact
    )

    create_object(user_request)

    if added_permissions:
        user_request.add_permissions([capability.value for capability in added_permissions])

    user_request.request.es_update()

    create_user_request_event(event_type.USER_ADDED, user_request)
Пример #6
0
def add_user_request(request_id, user_guid, permissions, point_of_contact):
    """
    Create a users permissions entry for a request and notify all agency administrators and the user that the permissions
    have changed.

    :param request_id: FOIL request ID
    :param user_guid: string guid of the user being edited
    :param permissions: Updated permissions values {'permission': true}
    :param point_of_contact: boolean value to set user as point of contact or not
    """
    user_request = UserRequests.query.filter_by(user_guid=user_guid,
                                                request_id=request_id).first()

    agency = Requests.query.filter_by(id=request_id).one().agency

    if user_request:
        raise UserRequestException(action="create",
                                   request_id=request_id,
                                   reason="UserRequest entry already exists.")

    user = Users.query.filter_by(guid=user_guid).one()

    agency_admin_emails = get_agency_admin_emails(agency)

    added_permissions = []
    for i, val in enumerate(permission.ALL):
        if i in permissions:
            added_permissions.append(val)

    # send email to agency administrators
    safely_send_and_add_email(
        request_id,
        render_template(
            'email_templates/email_user_request_added.html',
            request_id=request_id,
            name=user.name,
            agency_name=agency.name,
            page=urljoin(flask_request.host_url,
                         url_for('request.view', request_id=request_id)),
            added_permissions=[
                capability.label for capability in added_permissions
            ],
            admin=True),
        'User Added to Request {}'.format(request_id),
        to=agency_admin_emails)

    # send email to user being added
    safely_send_and_add_email(
        request_id,
        render_template(
            'email_templates/email_user_request_added.html',
            request_id=request_id,
            name=user.name,
            agency_name=agency.name,
            page=urljoin(flask_request.host_url,
                         url_for('request.view', request_id=request_id)),
            added_permissions=[
                capability.label for capability in added_permissions
            ],
        ),
        'User Added to Request {}'.format(request_id),
        to=[user.notification_email or user.email])

    if point_of_contact and has_point_of_contact(request_id):
        remove_point_of_contact(request_id)
    user_request = UserRequests(user_guid=user.guid,
                                request_id=request_id,
                                request_user_type=user_type_request.AGENCY,
                                permissions=0,
                                point_of_contact=point_of_contact)

    create_object(user_request)

    if added_permissions:
        user_request.add_permissions(
            [capability.value for capability in added_permissions])

    user_request.request.es_update()

    create_user_request_event(event_type.USER_ADDED, user_request)
Пример #7
0
def create_request(title,
                   description,
                   category,
                   tz_name,
                   agency_ein=None,
                   first_name=None,
                   last_name=None,
                   submission=DIRECT_INPUT,
                   agency_date_submitted_local=None,
                   email=None,
                   user_title=None,
                   organization=None,
                   phone=None,
                   fax=None,
                   address=None,
                   upload_path=None,
                   custom_metadata=None):
    """
    Creates a new FOIL Request and associated Users, UserRequests, and Events.

    :param title: request title
    :param description: detailed description of the request
    :param tz_name: client's timezone name
    :param agency_ein: agency_ein selected for the request
    :param first_name: first name of the requester
    :param last_name: last name of the requester
    :param submission: request submission method
    :param agency_date_submitted_local: submission date chosen by agency
    :param email: requester's email address
    :param user_title: requester's organizational title
    :param organization: requester's organization
    :param phone: requester's phone number
    :param fax: requester's fax number
    :param address: requester's mailing address
    :param upload_path: file path of the validated upload
    :param custom_metadata: JSON containing all data from custom request forms
    """
    # 1. Generate the request id
    request_id = generate_request_id(agency_ein)

    # 2a. Generate Email Notification Text for Agency
    # agency_email = generate_email_template('agency_acknowledgment.html', request_id=request_id)
    # 2b. Generate Email Notification Text for Requester

    # 3a. Send Email Notification Text for Agency
    # 3b. Send Email Notification Text for Requester

    # 4a. Calculate Request Submitted Date (Round to next business day)
    date_created_local = utc_to_local(datetime.utcnow(), tz_name)
    if current_user.is_agency:
        date_submitted_local = agency_date_submitted_local
    else:
        date_submitted_local = date_created_local

    # 4b. Calculate Request Due Date (month day year but time is always 5PM, 5 Days after submitted date)
    due_date = get_due_date(date_submitted_local, ACKNOWLEDGMENT_PERIOD_LENGTH,
                            tz_name)

    date_created = local_to_utc(date_created_local, tz_name)
    date_submitted = local_to_utc(date_submitted_local, tz_name)

    # 5. Create Request
    request = Requests(id=request_id,
                       title=title,
                       agency_ein=agency_ein,
                       category=category,
                       description=description,
                       date_created=date_created,
                       date_submitted=date_submitted,
                       due_date=due_date,
                       submission=submission,
                       custom_metadata=custom_metadata)
    create_object(request)

    guid_for_event = current_user.guid if not current_user.is_anonymous else None

    # 6. Get or Create User
    if current_user.is_public:
        user = current_user
    else:
        user = Users(guid=generate_guid(),
                     email=email,
                     first_name=first_name,
                     last_name=last_name,
                     title=user_title or None,
                     organization=organization or None,
                     email_validated=False,
                     terms_of_use_accepted=False,
                     phone_number=phone,
                     fax_number=fax,
                     mailing_address=address,
                     is_anonymous_requester=True)
        create_object(user)
        # user created event
        create_object(
            Events(request_id,
                   guid_for_event,
                   event_type.USER_CREATED,
                   previous_value=None,
                   new_value=user.val_for_events,
                   response_id=None,
                   timestamp=datetime.utcnow()))

    if upload_path is not None:
        # 7. Move file to upload directory
        upload_path = _move_validated_upload(request_id, upload_path)
        # 8. Create response object
        filename = os.path.basename(upload_path)
        response = Files(request_id,
                         RELEASE_AND_PRIVATE,
                         filename,
                         filename,
                         fu.get_mime_type(upload_path),
                         fu.getsize(upload_path),
                         fu.get_hash(upload_path),
                         is_editable=False)
        create_object(obj=response)

        # 8. Create upload Event
        upload_event = Events(user_guid=user.guid,
                              response_id=response.id,
                              request_id=request_id,
                              type_=event_type.FILE_ADDED,
                              timestamp=datetime.utcnow(),
                              new_value=response.val_for_events)
        create_object(upload_event)

        # Create response token if requester is anonymous
        if current_user.is_anonymous or current_user.is_agency:
            create_object(ResponseTokens(response.id))

    role_to_user = {
        role.PUBLIC_REQUESTER: user.is_public,
        role.ANONYMOUS: user.is_anonymous_requester,
    }
    role_name = [k for (k, v) in role_to_user.items() if v][0]
    # (key for "truthy" value)

    # 9. Create Event
    timestamp = datetime.utcnow()
    event = Events(user_guid=user.guid
                   if current_user.is_anonymous else current_user.guid,
                   request_id=request_id,
                   type_=event_type.REQ_CREATED,
                   timestamp=timestamp,
                   new_value=request.val_for_events)
    create_object(event)
    if current_user.is_agency:
        agency_event = Events(user_guid=current_user.guid,
                              request_id=request.id,
                              type_=event_type.AGENCY_REQ_CREATED,
                              timestamp=timestamp)
        create_object(agency_event)

    # 10. Create UserRequest for requester
    user_request = UserRequests(
        user_guid=user.guid,
        request_user_type=user_type_request.REQUESTER,
        request_id=request_id,
        permissions=Roles.query.filter_by(name=role_name).first().permissions)
    create_object(user_request)
    create_object(
        Events(request_id,
               guid_for_event,
               event_type.USER_ADDED,
               previous_value=None,
               new_value=user_request.val_for_events,
               response_id=None,
               timestamp=datetime.utcnow()))

    # 11. Create the elasticsearch request doc only if agency has been onboarded
    agency = Agencies.query.filter_by(ein=agency_ein).one()

    # 12. Add all agency administrators to the request.
    if agency.administrators:
        # b. Store all agency users objects in the UserRequests table as Agency users with Agency Administrator
        # privileges
        _create_agency_user_requests(request_id=request_id,
                                     agency_admins=agency.administrators,
                                     guid_for_event=guid_for_event)

    # 13. Add all parent agency administrators to the request.
    if agency != agency.parent:
        if (agency.parent.agency_features is not None
                and agency_ein in agency.parent.agency_features.get(
                    'monitor_agency_requests', []) and agency.parent.is_active
                and agency.parent.administrators):
            _create_agency_user_requests(
                request_id=request_id,
                agency_admins=agency.parent.administrators,
                guid_for_event=guid_for_event)

    # (Now that we can associate the request with its requester AND agency users.)
    if current_app.config['ELASTICSEARCH_ENABLED'] and agency.is_active:
        request.es_create()

    return request_id
Пример #8
0
def patch(user_id):
    """
    Request Parameters:
    - title
    - organization
    - email
    - phone_number
    - fax_number
    - mailing_address
    - is_super
    - is_agency_active
    - is_agency_admin
    (Mailing Address)
    - zip
    - city
    - state
    - address_one
    - address_two

    Restrictions:
    - Anonymous Users
        - cannot access this endpoint
    - Agency Administrators
        - cannot change their agency status
        - can only update the agency status of users within their agency
        - cannot change any super user status
    - Super Users
        - cannot change their super user status
    - Agency Users
        - cannot change any user except for themselves or
          *anonymous* requesters for requests they are assigned to
        - cannot change super user or agency status
    - Public Users
        - can only update themselves
        - cannot change super user or agency status

    """
    if not current_user.is_anonymous:
        # attempt to parse user_id and find user
        try:
            guid, auth_type = user_id.split(USER_ID_DELIMITER)
            user_ = Users.query.filter_by(guid=guid,
                                          auth_user_type=auth_type).one()
        except (ValueError, NoResultFound, MultipleResultsFound):
            return jsonify({}), 404

        agency_ein = request.form.get('agency_ein', None)
        if agency_ein is None and not (auth_type
                                       == user_type_auth.ANONYMOUS_USER
                                       or 'is_super' in request.form):
            return jsonify({}), 404

        updating_self = current_user == user_
        current_user_is_agency_user = (
            current_user.is_agency and not current_user.is_super
            and not current_user.is_agency_admin(agency_ein)
            and current_user.is_agency_active(agency_ein))
        current_user_is_agency_admin = (
            current_user.is_agency and not current_user.is_super
            and current_user.is_agency_admin(agency_ein)
            and current_user.is_agency_active(agency_ein))
        same_agency = agency_ein in [
            agency.ein for agency in current_user.agencies.all()
        ]
        associated_anonymous_requester = (
            user_.is_anonymous_requester
            and current_user.user_requests.filter_by(
                request_id=user_.anonymous_request.id).first() is None)

        is_agency_admin = request.form.get('is_agency_admin')
        is_agency_active = request.form.get('is_agency_active')
        is_super = request.form.get('is_super')

        changing_status = any((is_agency_active, is_agency_admin, is_super))

        rform_copy = dict(request.form)
        try:
            rform_copy.pop('is_agency_admin')
            rform_copy.pop('is_agency_active')
            rform_copy.pop('agency_ein')
            changing_more_than_agency_status = len(rform_copy) != 0
        except KeyError:
            changing_more_than_agency_status = False

        # VALIDATE
        if ((
                updating_self and
            (
                # super user attempting to change their own super status
                (current_user.is_super and is_super is not None) or
                # agency admin or public user attempting to change their own agency/super status
                (changing_status and
                 (current_user_is_agency_admin or current_user.is_public)))) or
            (not updating_self and (
                # public user attempting to change another user
                current_user.is_public or
                # agency user attempting to change a agency/super status
                (current_user_is_agency_user and changing_status) or
                # agency user attempting to change a user that is not an anonymous requester
                # for a request they are assigned to
                (current_user_is_agency_user and
                 (not user_.is_anonymous_requester
                  or not associated_anonymous_requester)) or
                # agency admin attempting to change another user that is not in the same agency or
                # attempting to change more than just the agency status of a user
                (current_user_is_agency_admin
                 and not (associated_anonymous_requester
                          or user_.is_anonymous_requester) and
                 (not same_agency or changing_more_than_agency_status)) or
                # agency admin attempting to change an anonymous requester for a request
                # they are not assigned to
                (current_user_is_agency_admin
                 and associated_anonymous_requester)))):
            return jsonify({}), 403

        # UPDATE
        user_fields = [
            'email', 'phone_number', 'fax_number', 'title', 'organization'
        ]
        status_fields = ['is_agency_admin', 'is_agency_active', 'is_super']
        address_fields = ['zip', 'city', 'state', 'address_one', 'address_two']

        user_field_val = {
            'email': request.form.get('email'),
            'phone_number': request.form.get('phone'),
            'fax_number': request.form.get('fax'),
            'title': request.form.get('title'),
            'organization': request.form.get('organization'),
        }
        status_field_val = {
            'is_agency_admin': request.form.get('is_agency_admin'),
            'is_agency_active': request.form.get('is_agency_active'),
            'is_super': request.form.get('is_super')
        }
        address_field_val = {
            'address_one': request.form.get('address_one'),
            'address_two': request.form.get('address_two'),
            'zip': request.form.get('zipcode'),
            'city': request.form.get('city'),
            'state': request.form.get('state')
        }

        # check if missing contact information
        if (user_field_val['email'] == ''
                and user_field_val['phone_number'] == ''
                and user_field_val['fax_number'] == '' and
            (address_field_val['city'] == '' or address_field_val['zip'] == ''
             or address_field_val['state'] == ''
             or address_field_val['address_one'] == '')):
            return jsonify({"error": "Missing contact information."}), 400

        old = {}
        old_address = {}
        new = {}
        new_address = {}

        for field in status_fields:
            if status_field_val[field] is not None:
                if field == 'is_agency_admin':
                    cur_val = user_.is_agency_admin(agency_ein)
                elif field == 'is_agency_active':
                    cur_val = user_.is_agency_active(agency_ein)
                else:
                    cur_val = getattr(user_, field)
                new_val = eval_request_bool(status_field_val[field])
                if cur_val != new_val:
                    old[field] = cur_val
                    new[field] = new_val

        for field in user_fields:
            val = user_field_val[field]
            if val is not None:
                if val == '':
                    user_field_val[
                        field] = None  # null in db, not empty string
                cur_val = getattr(user_, field)
                new_val = user_field_val[field]
                if cur_val != new_val:
                    old[field] = cur_val
                    new[field] = new_val

        for field in address_fields:
            val = address_field_val[field]
            if val is not None:
                if val == '':
                    address_field_val[field] = None
                cur_val = (user_.mailing_address.get(field)
                           if user_.mailing_address else None)
                new_val = address_field_val[field]
                if cur_val != new_val:
                    old_address[field] = cur_val
                    new_address[field] = new_val

        if new or new_address:
            # in spite of not changing, the guid and auth type of
            # the user being updated is added to Events.new_value
            # in order to identify this user
            new['user_guid'] = user_.guid
            new['auth_user_type'] = user_.auth_user_type

            if new_address:
                new['mailing_address'] = new_address
            if old_address:
                old['mailing_address'] = old_address

            if ('is_agency_admin' in new) or ('is_agency_active' in new):
                new['agency_ein'] = agency_ein
                update_object(new, AgencyUsers, (guid, auth_type, agency_ein))
            else:
                update_object(new, Users, (guid, auth_type))

            # create event(s)
            event_kwargs = {
                'request_id':
                user_.anonymous_request.id
                if user_.is_anonymous_requester else None,
                'response_id':
                None,
                'user_guid':
                current_user.guid,
                'auth_user_type':
                current_user.auth_user_type,
                'timestamp':
                datetime.utcnow()
            }

            if changing_status:
                new_statuses = {}
                old_statuses = {}
                for field in status_fields:
                    if new.get(field) is not None:
                        new_statuses[field] = new.pop(field)
                        old_statuses[field] = old.pop(field)

                # TODO: a better way to store user identifiers (than in the value columns)
                new_statuses['user_guid'] = user_.guid
                new_statuses['auth_user_type'] = user_.auth_user_type
                new_statuses['agency_ein'] = agency_ein

                is_agency_active = new_statuses.get('is_agency_active')
                is_agency_admin = new_statuses.get('is_agency_admin')

                if is_agency_active is not None and not is_agency_active:
                    # remove ALL UserRequests
                    for user_request in user_.user_requests.all():
                        create_user_request_event(event_type.USER_REMOVED,
                                                  user_request)
                        delete_object(user_request)
                elif is_agency_admin is not None:

                    def set_permissions_and_create_event(user_req, perms):
                        """
                        Set permissions for a user request and create a
                        'user_permissions_changed' Event.

                        :param user_req: user request
                        :param perms: permissions to set for user request
                        """
                        old_permissions = user_req.permissions
                        user_request.set_permissions(perms)
                        create_user_request_event(event_type.USER_PERM_CHANGED,
                                                  user_req, old_permissions)

                    if is_agency_admin:
                        permissions = Roles.query.filter_by(
                            name=role_name.AGENCY_ADMIN).one().permissions
                        # create UserRequests for ALL existing requests under user's agency where user is not assigned
                        # for where the user *is* assigned, only change the permissions
                        for req in user_.agencies.filter_by(
                                ein=agency_ein).one().requests:
                            user_request = UserRequests.query.filter_by(
                                request_id=req.id,
                                user_guid=user_.guid,
                                auth_user_type=user_.auth_user_type).first()
                            if user_request is None:
                                user_request = UserRequests(
                                    user_guid=user_.guid,
                                    auth_user_type=user_.auth_user_type,
                                    request_id=req.id,
                                    request_user_type=user_type_request.AGENCY,
                                    permissions=permissions)
                                create_object(user_request)
                                create_user_request_event(
                                    event_type.USER_ADDED, user_request)
                            else:
                                set_permissions_and_create_event(
                                    user_request, permissions)

                    else:
                        # update ALL UserRequests (strip user of permissions)
                        for user_request in user_.user_requests.all():
                            set_permissions_and_create_event(
                                user_request, permission.NONE)

                # TODO: single email detailing user changes?

                create_object(
                    Events(type_=event_type.USER_STATUS_CHANGED,
                           previous_value=old_statuses,
                           new_value=new_statuses,
                           **event_kwargs))

            if old:  # something besides status changed ('new' holds user guid and auth type)
                create_object(
                    Events(type_=(event_type.REQUESTER_INFO_EDITED
                                  if user_.is_anonymous_requester else
                                  event_type.USER_INFO_EDITED),
                           previous_value=old,
                           new_value=new,
                           **event_kwargs))
            return jsonify({}), 200
        else:
            return jsonify({"message": "No changes detected."}), 200

    return jsonify({}), 403