示例#1
0
                    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)
示例#2
0
 def __create_event(self, type_, obj, user=None, **kwargs):
     """
     Create a Responses or UserRequests event.
     :param type_: event type
     :param obj: Responses or UserRequests object
     :param user: user creating event
     """
     assert (isinstance(obj, Responses) or isinstance(obj, UserRequests))
     assert (
         user or self.user
     ), "a user must be provided when creating a Responses or UserRequests event"
     user = user or self.user
     if isinstance(obj, Responses):
         create_response_event(type_, obj, user)
     elif isinstance(obj, UserRequests):
         create_user_request_event(type_, obj, user=user, **kwargs)
示例#3
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