Esempio n. 1
0
def contact():
    if request.method == 'POST':
        name = request.form.get('name')
        email = request.form.get('email')
        subject = request.form.get('subject')
        message = request.form.get('message')

        if all((name, email, subject, message)):
            body = "Name: {}\n\nEmail: {}\n\nSubject: {}\n\nMessage:\n{}".format(
                name, email, subject, message)
            create_object(
                Emails(
                    request_id=None,
                    privacy=PRIVATE,
                    to=OPENRECORDS_DL_EMAIL,
                    cc=None,
                    bcc=None,
                    subject=subject,
                    body=body,
                ))
            send_contact_email(subject, [OPENRECORDS_DL_EMAIL], body, email)
            flash('Your message has been sent. We will get back to you.',
                  category='success')
        else:
            flash('Cannot send email.', category='danger')
    error_id = request.args.get('error_id', '')
    return render_template('main/contact.html', error_id=error_id)
Esempio n. 2
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()
        ))
Esempio n. 3
0
def remove_point_of_contact(request_id):
    """
    Remove the current point of contact from a given request
    :param request_id: FOIL request ID
    """
    point_of_contact = get_current_point_of_contact(request_id)
    set_point_of_contact(request_id, point_of_contact, False)
    create_object(
        Events(
            request_id,
            current_user.guid,
            current_user.auth_user_type,
            event_type.REQ_POINT_OF_CONTACT_REMOVED,
            previous_value={
                "user_guid": point_of_contact.user_guid,
                "auth_user_type": point_of_contact.auth_user_type,
                "point_of_contact": "True"
            },
            new_value={
                "user_guid": point_of_contact.user_guid,
                "auth_user_type": point_of_contact.auth_user_type,
                "point_of_contact": "False"
            },
            timestamp=datetime.utcnow(),
        ))
Esempio n. 4
0
def test_get_content_with_token(self):
    rf = RequestsFactory(self.request_id)
    response = rf.add_file()

    valid_token = ResponseTokens(response.id)
    expired_token = ResponseTokens(response.id,
                                   expiration_date=datetime.utcnow())
    create_object(valid_token)
    create_object(expired_token)

    path = '/response/' + str(response.id)

    # invalid token (400)
    resp = self.client.get(path, query_string={'token': 'not_a_real_token'})
    self.assertEqual(resp.status_code, 400)

    # expired token (400)
    resp = self.client.get(path, query_string={'token': expired_token.token})
    self.assertEqual(resp.status_code, 400)
    self.assertTrue(
        ResponseTokens.query.filter_by(token=expired_token.token).first() is
        None)  # assert response token has been deleted

    # valid token (success)
    resp = self.client.get(path, query_string={'token': valid_token.token})
    self.assert_file_sent(resp, rf.request.id, response.name)
Esempio n. 5
0
    def add_file(self,
                 filepath=None,
                 mime_type='text/plain',
                 contents=None,
                 title=None):
        if filepath is None:
            filename = str(uuid.uuid4())
            filepath = os.path.join(current_app.config['UPLOAD_DIRECTORY'],
                                    self.request.id, filename)
        else:
            filename = os.path.basename(filepath)

        self.filepaths.append(filepath)

        # create an empty file if the specified path does not exist
        if not fu.exists(filepath):
            fu.makedirs(os.path.dirname(filepath), exist_ok=True)
            with open(filepath, 'w') as fp:
                fp.write(contents or ''.join(
                    random.choice(ascii_letters)
                    for _ in range(random.randrange(100, 500))))

        response = Files(self.request.id, PRIVATE, title or filename,
                         filename, mime_type, fu.getsize(filepath),
                         fu.get_hash(filepath))
        # TODO: add Events FILE_ADDED
        create_object(response)
        return response
Esempio n. 6
0
def technical_support():
    if request.method == 'POST':
        name = request.form.get('name')
        email = request.form.get('email')
        subject = request.form.get('subject')
        message = request.form.get('message')

        if all((name, email, subject, message)):
            body = "Name: {}\n\nEmail: {}\n\nSubject: {}\n\nMessage:\n{}".format(
                name, email, subject, message)
            create_object(
                Emails(
                    request_id=None,
                    privacy=PRIVATE,
                    to=OPENRECORDS_DL_EMAIL,
                    cc=None,
                    bcc=None,
                    subject=subject,
                    body=body,
                )
            )
            if current_user.is_agency:
                send_contact_email(subject, [current_app.config['OPENRECORDS_AGENCY_SUPPORT_DL']], body, email)
            else:
                send_contact_email(subject, [OPENRECORDS_DL_EMAIL], body, email)
            flash('Your message has been sent. We will get back to you.', category='success')
        else:
            flash('Cannot send email.', category='danger')
    error_id = request.args.get('error_id', '')
    return render_template('main/contact.html', error_id=error_id)
Esempio n. 7
0
    def add_file(
            self,
            title=None,
            filepath=None,
            name=None,  # will be ignored if filepath supplied
            privacy=response_privacy.PRIVATE,
            user=None):
        if filepath is None:
            filename = name or fake.file_name(extension='txt')
            filepath = os.path.join(current_app.config["UPLOAD_DIRECTORY"],
                                    self.request.id, filename)
        else:
            filename = os.path.basename(filepath)

        if not fu.exists(filepath):
            fu.makedirs(os.path.dirname(filepath), exist_ok=True)
            with open(filepath, "w") as fp:
                fp.write(fake.file_content())
            self.__files.append(filepath)

        response = Files(
            self.request.id,
            privacy=privacy,
            title=title or fake.title(),
            name=filename,
            mime_type=fu.get_mime_type(filepath),
            size=fu.getsize(filepath),
            hash_=fu.get_hash(filepath),
        )
        create_object(response)
        self.__create_event(event_type.FILE_ADDED, response, user)
        return response
Esempio n. 8
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()))
Esempio n. 9
0
 def add_note(self, content=None):
     response = Notes(self.request.id,
                      PRIVATE,
                      content=content or ''.join(
                          random.choice(ascii_letters)
                          for _ in range(random.randrange(10, 50))))
     # TODO: add Events NOTE_ADDED
     create_object(response)
     return response
Esempio n. 10
0
 def add_instructions(self,
                      content=None,
                      privacy=response_privacy.PRIVATE,
                      user=None):
     response = Instructions(self.request.id,
                             privacy,
                             content=content or fake.paragraph())
     create_object(response)
     self.__create_event(event_type.INSTRUCTIONS_ADDED, response, user)
     return response
Esempio n. 11
0
 def add_note(self,
              content=None,
              privacy=response_privacy.PRIVATE,
              user=None):
     response = Notes(self.request.id,
                      privacy,
                      content=content or fake.paragraph())
     create_object(response)
     self.__create_event(event_type.NOTE_ADDED, response, user)
     return response
Esempio n. 12
0
 def test_request_es_doc_not_created(self, es_create_patch):
     create_object(
         Requests('FOIL-COT',
                  title="Where's my money Denny?",
                  description="Oh Hi!",
                  agency_ein=54,
                  date_created=datetime.utcnow(),
                  date_submitted=datetime.utcnow(),
                  due_date=datetime.utcnow(),
                  submission=IN_PERSON,
                  status=OVERDUE))
     self.assertFalse(es_create_patch.called)
Esempio n. 13
0
 def add_link(self,
              title=None,
              url=None,
              privacy=response_privacy.PRIVATE,
              user=None):
     response = Links(self.request.id,
                      privacy,
                      title=title or fake.title(),
                      url=url or fake.url())
     create_object(response)
     self.__create_event(event_type.LINK_ADDED, response, user)
     return response
Esempio n. 14
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)
Esempio n. 15
0
def create_request_info_event(request_id, type_, previous_value, new_value):
    """
    Create and store events object for updating the request information into database.
    :param request_id: request ID
    :param type_: event type
    :param previous_value: previous value
    :param new_value: new value
    """
    event = Events(request_id=request_id,
                   user_guid=current_user.guid,
                   type_=type_,
                   previous_value=previous_value,
                   new_value=new_value)
    create_object(event)
Esempio n. 16
0
 def __extend(self,
              extend_type,
              new_due_date,
              user,
              request_update_data=None,
              reason=None):
     assert new_due_date > self.request.due_date
     request_update_data["due_date"] = new_due_date
     self.__update(request_update_data)
     response = Determinations(self.request.id,
                               response_privacy.RELEASE_AND_PUBLIC,
                               extend_type, reason, new_due_date)
     create_object(response)
     self.__create_event(extend_type, response, user)
     return response
Esempio n. 17
0
def fix_anonymous_requesters():
    """
    Ensures there is only one anonymous requester per request by
    creating a new anonymous requester (User) for every User Requests record with
    a duplicate anonymous requester guid and updates the User Requests record.
    The new user will be identical to the existing one with the exception of the guid.
    """
    from app.constants import user_type_request
    from app.request.utils import generate_guid
    from app.lib.db_utils import create_object, update_object

    guids = db.engine.execute("""
        SELECT
          user_requests.user_guid AS "GUID"
        FROM user_requests
          JOIN users ON user_requests.user_guid = users.guid AND user_requests.auth_user_type = users.auth_user_type
        WHERE user_requests.request_user_type = 'requester'
        GROUP BY user_requests.user_guid
        HAVING COUNT(user_requests.request_id) > 1;
    """)

    for guid, in guids:
        # get all User Requests with dups, excluding the first (since we need to change all but 1)
        for ur in UserRequests.query.filter_by(
                user_guid=guid,
                request_user_type=user_type_request.REQUESTER).offset(1):
            user = Users.query.filter_by(
                guid=guid, auth_user_type=user_type_auth.ANONYMOUS_USER).one()
            new_guid = generate_guid()
            print("{} -> {}".format(guid, new_guid))
            # create new anonymous requester with new guid
            create_object(
                Users(guid=new_guid,
                      auth_user_type=user_type_auth.ANONYMOUS_USER,
                      email=user.email,
                      first_name=user.first_name,
                      last_name=user.last_name,
                      title=user.title,
                      organization=user.organization,
                      email_validated=False,
                      terms_of_use_accepted=False,
                      phone_number=user.phone_number,
                      fax_number=user.fax_number,
                      mailing_address=user.mailing_address))
            # update user request with new guid
            update_object({"user_guid": new_guid}, UserRequests,
                          (ur.user_guid, ur.auth_user_type, ur.request_id))
Esempio n. 18
0
def create_contact_record(request, first_name, last_name, email, subject,
                          message):
    """
    Creates Users, Emails, and Events entries for a contact submission for a request.
    Sends email with message to all agency users associated with the request.

    :param request: request object
    :param first_name: sender's first name
    :param last_name: sender's last name
    :param email: sender's email
    :param subject: subject of email
    :param message: email body
    """
    if current_user == request.requester:
        user = current_user
    else:
        user = Users(guid=generate_guid(),
                     email=email,
                     first_name=first_name,
                     last_name=last_name,
                     email_validated=False,
                     terms_of_use_accepted=False,
                     is_anonymous_requester=True)
        create_object(user)

        create_object(
            Events(request_id=request.id,
                   user_guid=None,
                   type_=event_type.USER_CREATED,
                   new_value=user.val_for_events))

    body = "Name: {} {}\n\nEmail: {}\n\nSubject: {}\n\nMessage:\n{}".format(
        first_name, last_name, email, subject, message)

    agency_emails = get_assigned_users_emails(request.id)

    email_obj = Emails(request.id,
                       PRIVATE,
                       to=','.join([
                           email.replace('{', '').replace('}', '')
                           for email in agency_emails
                       ]),
                       cc=None,
                       bcc=None,
                       subject=subject,
                       body=body)

    create_object(email_obj)

    create_object(
        Events(request_id=request.id,
               user_guid=user.guid,
               type_=event_type.CONTACT_EMAIL_SENT,
               response_id=email_obj.id,
               new_value=email_obj.val_for_events))

    send_contact_email(subject, agency_emails, message, email)
Esempio n. 19
0
def remove_point_of_contact(request_id):
    """
    Remove the current point of contact from a given request
    :param request_id: FOIL request ID
    """
    point_of_contact = get_current_point_of_contact(request_id)
    set_point_of_contact(request_id, point_of_contact, False)
    create_object(Events(
        request_id,
        current_user.guid,
        event_type.REQ_POINT_OF_CONTACT_REMOVED,
        previous_value={"user_guid": point_of_contact.user_guid,
                        "point_of_contact": "True"},
        new_value={"user_guid": point_of_contact.user_guid,
                   "point_of_contact": "False"},
        timestamp=datetime.utcnow(),
    ))
Esempio n. 20
0
def test_get_content_with_token(self):
    rf = RequestsFactory(self.request_id)
    response = rf.add_file()

    valid_token = ResponseTokens(response.id)
    expired_token = ResponseTokens(response)
    create_object(valid_token)
    create_object(expired_token)

    path = '/response/' + str(response.id)

    # invalid token (400)
    resp = self.client.get(path, query_string={'token': 'not_a_real_token'})
    self.assertEqual(resp.status_code, 400)

    # valid token (success)
    resp = self.client.get(path, query_string={'token': valid_token.token})
    self.assert_file_sent(resp, rf.request.id, response.name)
Esempio n. 21
0
def create_user_request_event(events_type, user_request, old_permissions=None):
    """
    Create an Event for the addition, removal, or updating of a UserRequest

    """
    if old_permissions is not None:
        previous_value = {"permissions": old_permissions}
    else:
        previous_value = None
    create_object(
        Events(
            user_request.request_id,
            current_user.guid,
            current_user.auth_user_type,
            events_type,
            previous_value=previous_value,
            new_value=user_request.val_for_events,
            timestamp=datetime.utcnow(),
        ))
Esempio n. 22
0
def create_auth_event(auth_event_type: str, user_guid: str, new_value: dict):
    """
    Create and store event object for given response.

    Args:
        auth_event_type (str): one of app.constants.event_type
        user_guid (Users): Users object performing the authentication event
        new_value (dict): Value to be stored in events table

    """
    event = Events(request_id=None,
                   user_guid=user_guid,
                   type_=auth_event_type,
                   timestamp=datetime.utcnow(),
                   response_id=None,
                   previous_value=None,
                   new_value=new_value)
    # store event object
    create_object(event)
Esempio n. 23
0
def create_user_request_event(events_type, user_request, old_permissions=None, old_point_of_contact=None,
                              user=current_user):
    """
    Create an Event for the addition, removal, or updating of a UserRequest and insert into the database.

    Args:
        events_type (str): event type from the constants defined in constants.event_type.
        user_request (UserRequests): UserRequests object.
        old_permissions (int): Value of permissions for the request.
        user (Users): Users object that represents the user being modified.

    Returns:
        Events: The event object representing the change made to the user.

    """
    event = create_user_request_event_object(events_type, user_request, old_permissions, old_point_of_contact, user)
    create_object(
        event
    )
Esempio n. 24
0
 def create_user(self,
                 auth_type,
                 guid=None,
                 agency_ein=None,
                 email=None,
                 first_name=None,
                 last_name=None,
                 title=None,
                 organization=None,
                 phone_number=None,
                 fax_number=None,
                 mailing_address=None,
                 email_validated=True,
                 terms_of_use_accepted=True,
                 is_agency_active=False,
                 is_agency_admin=False):
     if auth_type == user_type_auth.AGENCY_USER:
         assert agency_ein is not None
     else:
         assert all((agency_ein is None, not is_agency_active,
                     not is_agency_admin))
     if auth_type == user_type_auth.ANONYMOUS_USER:
         email_validated, terms_of_use_accepted = False, False
     user = Users(
         guid=guid or self.generate_user_guid(auth_type),
         auth_user_type=auth_type,
         agency_ein=agency_ein,
         email=email or fake.email(),
         first_name=first_name or fake.first_name(),
         last_name=last_name or fake.last_name(),
         title=title or fake.user_title(),
         organization=organization or fake.organization(),
         phone_number=phone_number or fake.phone_number(),
         fax_number=fax_number or fake.fax_number(),
         mailing_address=mailing_address or fake.mailing_address(),
         email_validated=email_validated,
         terms_of_use_accepted=terms_of_use_accepted,
         is_agency_active=is_agency_active,
         is_agency_admin=is_agency_admin,
     )
     create_object(user)
     return user
Esempio n. 25
0
def create_user_request_event(events_type,
                              user_request,
                              old_permissions=None,
                              user=current_user):
    """
    Create an Event for the addition, removal, or updating of a UserRequest and insert into the database.

    Args:
        events_type (str): event type from the constants defined in constants.event_type.
        user_request (UserRequests): UserRequests object.
        old_permissions (int): Value of permissions for the request.
        user (Users): Users object that represents the user being modified.

    Returns:
        Events: The event object representing the change made to the user.

    """
    event = create_user_request_event_object(events_type, user_request,
                                             old_permissions, user)
    create_object(event)
Esempio n. 26
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
Esempio n. 27
0
def create_user(auth_type=user_type_auth.PUBLIC_USER_NYC_ID):
    """
    :param auth_type: one of app.constants.user_type_auth
    """
    len_firstname = random.randrange(3, 8)
    len_lastname = random.randrange(3, 15)
    firstname = ''.join(
        random.choice(ascii_lowercase) for _ in range(len_firstname)).title()
    lastname = ''.join(
        random.choice(ascii_lowercase) for _ in range(len_lastname)).title()
    user = Users(
        guid=generate_user_guid(auth_type),
        auth_user_type=auth_type,
        agency_ein=(random.choice([
            ein[0] for ein in Agencies.query.with_entities(Agencies.ein).all()
        ]) if auth_type == user_type_auth.AGENCY_USER else None),
        first_name=firstname,
        last_name=lastname,
        email='{}{}@email.com'.format(firstname[0].lower(), lastname.lower()),
        email_validated=True,
        terms_of_use_accepted=True)
    create_object(user)
    return user
Esempio n. 28
0
def patch(agency_ein):
    """
    Only accessible by Super Users

    Currently only changes:
        is_active
    """
    if not current_user.is_anonymous and current_user.is_super:
        is_active = request.form.get('is_active')
        if is_active is not None and Agencies.query.filter_by(
                ein=agency_ein).first() is not None:
            update_object({'is_active': eval_request_bool(is_active)},
                          Agencies, agency_ein)
            create_object(
                Events(request_id=None,
                       user_guid=current_user.guid,
                       auth_user_type=current_user.auth_user_type,
                       type_=AGENCY_ACTIVATED,
                       new_value={"ein": agency_ein},
                       timestamp=datetime.utcnow()))
            return '', 200
        return '', 400
    return '', 403
Esempio n. 29
0
 def __close(self, close_type, user, reason_ids=None):
     if reason_ids is None:
         reasons = "|".join(
             (r.content
              for r in Reasons.query.filter_by(type=close_type).order_by(
                  func.random()).limit(random.randrange(1, 6)).all()))
     else:
         reasons = format_determination_reasons(reason_ids)
     self.__update({
         "status":
         request_status.CLOSED,
         "agency_request_summary_release_date":
         calendar.addbusdays(datetime.utcnow(), RELEASE_PUBLIC_DAYS)
     })
     response = Determinations(
         self.request.id,
         response_privacy.RELEASE_AND_PUBLIC,
         close_type,
         reasons,
     )
     create_object(response)
     self.__create_event(event_type.REQ_CLOSED, response, user)
     return response
Esempio n. 30
0
 def __set_due_soon_or_overdue(self, status, new_due_date, shift_dates):
     data = {"status": status}
     if shift_dates:
         shift = new_due_date - self.request.due_date
         data.update({
             "due_date":
             new_due_date,
             "date_submitted":
             self.request.date_submitted + shift,
             "date_created":
             self.request.date_created + shift,
             "agency_request_summary_release_date":
             (self.request.agency_request_summary_release_date + shift
              if self.request.agency_request_summary_release_date else None)
         })
     create_object(
         Events(self.request.id,
                user_guid=None,
                auth_user_type=None,
                type_=event_type.REQ_STATUS_CHANGED,
                previous_value={"status": self.request.status},
                new_value={"status": status},
                response_id=None))
     self.__update(data)
Esempio n. 31
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)
Esempio n. 32
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)
Esempio n. 33
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)
Esempio n. 34
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
Esempio n. 35
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
Esempio n. 36
0
def update_agency_active_status(agency_ein, is_active):
    """
    Update the active status of an agency.
    :param agency_ein: String identifier for agency (4 characters)
    :param is_active: Boolean value for agency active status (True = Active)
    :return: Boolean value (True if successfully changed active status)
    """
    agency = Agencies.query.filter_by(ein=agency_ein).first()
    is_valid_agency = agency is not None
    activate_agency = eval_request_bool(is_active)

    if is_active is not None and is_valid_agency:
        update_object(
            {'is_active': activate_agency},
            Agencies,
            agency_ein
        )
        if activate_agency:
            create_object(
                Events(
                    request_id=None,
                    user_guid=current_user.guid,
                    type_=AGENCY_ACTIVATED,
                    previous_value={"ein": agency_ein, "is_active": "False"},
                    new_value={"ein": agency_ein, "is_active": "True"},
                    timestamp=datetime.utcnow()
                )
            )
            # create request documents
            for request in agency.requests:
                request.es_create()

            return True
        else:
            create_object(
                Events(
                    request_id=None,
                    user_guid=current_user.guid,
                    type_=AGENCY_DEACTIVATED,
                    previous_value={"ein": agency_ein, "is_active": "True"},
                    new_value={"ein": agency_ein, "is_active": "False"},
                    timestamp=datetime.utcnow()
                )
            )
            # remove requests from index
            for request in agency.requests:
                request.es_delete()
            # deactivate agency users
            for user in agency.active_users:
                update_object(
                    {"is_agency_active": "False",
                     "is_agency_admin": "False"},
                    AgencyUsers,
                    (user.guid, agency_ein)
                )
                create_object(
                    Events(
                        request_id=None,
                        user_guid=current_user.guid,
                        type_=AGENCY_USER_DEACTIVATED,
                        previous_value={"user_guid": user.guid,
                                        "ein": agency_ein,
                                        "is_active": "True"},
                        new_value={"user_guid": user.guid,
                                   "ein": agency_ein,
                                   "is_active": "False"},
                        timestamp=datetime.utcnow()
                    )
                )

            return True
    return False
Esempio n. 37
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

    """

    # Anonymous users cannot access endpoint
    if current_user.is_anonymous:
        return jsonify({'error': 'Anonymous users cannot access this endpoint'}), 403

    # Public users cannot access endpoint
    if current_user.is_public:
        return jsonify({'error': 'Public users cannot access this endpoint'}), 403

    # Unauthenticated users cannot access endpoint
    if not current_user.is_authenticated:
        return jsonify({'error': 'User must be authenticated to access endpoint'}), 403

    # Retrieve the user
    user_ = Users.query.filter_by(guid=user_id).one_or_none()

    # If the user does not exist, return 404 - Not Found
    if not user_:
        return jsonify({'error': 'Specified user does not exist.'}), 404

    # Gather Form details
    is_agency_admin = eval_request_bool(request.form.get('is_agency_admin')) if request.form.get('is_agency_admin',
                                                                                                 None) else None
    is_agency_active = eval_request_bool(request.form.get('is_agency_active')) if request.form.get('is_agency_active',
                                                                                                   None) else None
    is_super = eval_request_bool(request.form.get('is_super')) if request.form.get('is_super', None) else None

    agency_ein = request.form.get('agency_ein', None)

    # Checks that apply if user is changing their own profile
    changing_self = current_user == user_

    # Agency User Restrictions (applies to Admins and Regular Users)
    if user_.is_agency:
        # Endpoint can only be used for a specific agency
        if not agency_ein:
            return jsonify({'error': 'agency_ein must be provided to modify an agency user'}), 400

        # Agency must exist and be active to modify users
        agency = Agencies.query.filter_by(ein=agency_ein).one_or_none()
        if not agency and agency.is_active:
            return jsonify({'error': 'Agency must exist in the database and be active'}), 400

        if not current_user.is_super:
            # Current user must belong to agency specified by agency_ein
            current_user_is_agency_admin = current_user.is_agency_admin(agency.ein)

            if not current_user_is_agency_admin:
                return jsonify({'error': 'Current user must belong to agency specified by agency_ein'}), 400

            user_in_agency = AgencyUsers.query.filter(AgencyUsers.user_guid == user_.guid, AgencyUsers.agency_ein == agency_ein).one_or_none()

            if user_in_agency is None:
                return jsonify({'error': 'User to be modified must belong to agency specified by agency_ein'}), 400

        # Non-Agency Admins cannot access endpoint to modify other agency_users
        if not current_user.is_super and not current_user.is_agency_admin(agency_ein):
            return jsonify({'error': 'User must be agency admin to modify users'}), 403

        # Cannot modify super status when changing agency active or agency admin status
        if (is_agency_admin or is_agency_active) and is_super:
            return jsonify({
                'error': 'Cannot modify super status when changing agency active or agency admin status'}), 400

        if changing_self:
            # Super users cannot change their own is_super value
            if current_user.is_super and is_super:
                return jsonify({'error': 'Super users cannot change their own `super` status'}), 400

            if is_agency_admin:
                return jsonify({'error': 'Agency Administrators cannot change their administrator permissions'}), 400

    elif user_.is_public:
        if current_user != user_:
            return jsonify({'error': 'Public user attributes cannot be modified by agency users.'}), 400

    elif user_.is_anonymous_requester:
        ur = current_user.user_requests.filter_by(request_id=user_.anonymous_request.id).one_or_none()
        if not ur:
            return jsonify({
                'error': 'Agency users can only modify anonymous requesters for requests where they are assigned.'}), 403

        if not ur.has_permission(permission.EDIT_REQUESTER_INFO):
            return jsonify({'error': 'Current user does not have EDIT_REQUESTER_INFO permission'}), 403

    # Gather User Fields

    user_editable_fields = user_attrs.UserEditableFieldsDict(
        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'),
        address_one=request.form.get('address_one'),
        address_two=request.form.get('address_two'),
        zip=request.form.get('zipcode'),
        city=request.form.get('city'),
    )
    status_field_val = user_attrs.UserStatusDict(
        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')
    )
    if changing_self:
        if not user_editable_fields.is_valid:
            return jsonify({"error": "Missing contact information."}), 400
    else:
        if user_.is_agency and not status_field_val.is_valid:
            return jsonify({"error": "User status values invalid"}), 400

    # Status Values for Events
    old_status = {}
    new_status = {}

    # User Attributes for Events
    old_user_attrs = {'_mailing_address': {}}
    new_user_attrs = {'_mailing_address': {}}

    for key, value in status_field_val.items():
        if value is not None:
            if key == 'is_agency_admin':
                cur_val = user_.is_agency_admin(agency_ein)
            elif key == 'is_agency_active':
                cur_val = user_.is_agency_active(agency_ein)
            else:
                cur_val = getattr(user_, key)
            new_val = eval_request_bool(status_field_val[key])
            if cur_val != new_val:
                old_status[key] = cur_val
                new_status[key] = new_val

    for key, value in user_editable_fields.items():
        # Address is a dictionary and needs to be handled separately
        if key == 'address':
            for address_key, address_value in value.items():
                cur_val = (user_.mailing_address.get(address_key)
                           if user_.mailing_address else None)
                new_val = address_value
                if cur_val != new_val:
                    old_user_attrs['_mailing_address'][address_key] = cur_val
                    new_user_attrs['_mailing_address'][address_key] = new_val
            continue
        if value is not None:
            cur_val = getattr(user_, key)
            new_val = user_editable_fields[key]
            if cur_val != new_val:
                old_user_attrs[key] = cur_val
                new_user_attrs[key] = new_val

    # Update the Users object if new_user_attrs is not None (empty dict)
    if new_user_attrs and new_user_attrs.get('_mailing_address') and old_user_attrs:
        update_object(
            new_user_attrs,
            Users,
            user_id
        )
        # GUID is added to the 'new' value in events to identify the user that was changed
        new_user_attrs['user_guid'] = user_.guid

        # 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,
            'timestamp': datetime.utcnow()
        }

        create_object(Events(
            type_=(event_type.REQUESTER_INFO_EDITED
                   if user_.is_anonymous_requester
                   else event_type.USER_INFO_EDITED),
            previous_value=old_user_attrs,
            new_value=new_user_attrs,
            **event_kwargs
        ))

    if new_status:
        redis_key = "{current_user_guid}-{update_user_guid}-{agency_ein}-{timestamp}".format(
            current_user_guid=current_user.guid, update_user_guid=user_.guid, agency_ein=agency_ein,
            timestamp=datetime.now())
        old_status['user_guid'] = user_.guid
        new_status['user_guid'] = user_.guid

        old_status['agency_ein'] = agency_ein
        new_status['agency_ein'] = agency_ein

        # Update agency active status and create associated event. Occurs first because a user can be
        # activated / deactivated with admin status set to True.
        if is_agency_active is not None:
            update_object(
                new_status,
                AgencyUsers,
                (user_.guid, agency_ein)
            )
            event_kwargs = {
                'request_id': user_.anonymous_request.id if user_.is_anonymous_requester else None,
                'response_id': None,
                'user_guid': current_user.guid,
                'timestamp': datetime.utcnow()
            }
            if is_agency_active:
                create_object(Events(
                    type_=event_type.AGENCY_USER_ACTIVATED,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
                if is_agency_admin is not None and is_agency_admin:
                    make_user_admin.apply_async(args=(user_.guid, current_user.guid, agency_ein), task_id=redis_key)
                    return jsonify({'status': 'success', 'message': 'Update task has been scheduled.'}), 200
            else:
                create_object(Events(
                    type_=event_type.AGENCY_USER_DEACTIVATED,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
                remove_user_permissions.apply_async(
                    args=(user_.guid, current_user.guid, agency_ein, event_type.AGENCY_USER_DEACTIVATED), task_id=redis_key)
                return jsonify({'status': 'success', 'message': 'Update task has been scheduled.'}), 200
            return jsonify({'status': 'success', 'message': 'Agency user successfully updated'}), 200

        # Update agency admin status and create associated event.
        elif is_agency_admin is not None:
            new_status['agency_ein'] = agency_ein
            update_object(
                new_status,
                AgencyUsers,
                (user_.guid, agency_ein)
            )
            event_kwargs = {
                'request_id': user_.anonymous_request.id if user_.is_anonymous_requester else None,
                'response_id': None,
                'user_guid': current_user.guid,
                'timestamp': datetime.utcnow()
            }
            if is_agency_admin:
                create_object(Events(
                    type_=event_type.USER_MADE_AGENCY_ADMIN,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
                make_user_admin.apply_async(args=(user_.guid, current_user.guid, agency_ein), task_id=redis_key)
                return jsonify({'status': 'success', 'message': 'Update task has been scheduled.'}), 200
            else:
                create_object(Events(
                    type_=event_type.USER_MADE_AGENCY_USER,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
                remove_user_permissions.apply_async(
                    args=(user_.guid, current_user.guid, agency_ein, event_type.USER_MADE_AGENCY_USER), task_id=redis_key)
                return jsonify({'status': 'success', 'message': 'Update task has been scheduled.'}), 200

        # Update user super status and create associated event.
        elif is_super is not None:
            new_status['agency_ein'] = agency_ein
            update_object(
                new_status,
                AgencyUsers,
                (user_.guid, agency_ein)
            )
            event_kwargs = {
                'request_id': user_.anonymous_request.id if user_.is_anonymous_requester else None,
                'response_id': None,
                'user_guid': current_user.guid,
                'timestamp': datetime.utcnow()
            }
            if is_super:
                create_object(Events(
                    type_=event_type.USER_MADE_SUPER_USER,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
            else:
                create_object(Events(
                    type_=event_type.USER_REMOVED_FROM_SUPER,
                    previous_value=old_status,
                    new_value=new_status,
                    **event_kwargs
                ))
            return jsonify({'status': 'success', 'message': 'Agency user successfully updated'}), 200
    # Always returns 200 so that we can use the data from the response in the client side javascript
    return jsonify({'status': 'Not Modified', 'message': 'No changes detected'}), 200
Esempio n. 38
0
def _process_user_data(guid,
                       email,
                       first_name,
                       middle_initial,
                       last_name,
                       email_validated,
                       is_nyc_employee,
                       has_nyc_account,
                       active,
                       terms_of_use_accepted,
                       is_anonymous_requester):
    """
    Create or Update an OpenRecords User based on the data received from the SAML Assertion.

    If no first_name is provided, the mailbox portion of the email will be used
        e.g. [email protected] -> first_name: jdoe

    If a user cannot be found using the specified guid and user_type, a second attempt is made with the specified email.

    NOTE: A user's agency is not determined here. After login, a user's agency supervisor must email us requesting that
    user be added to the agency.
    TODO (@joelbcastillo): Add endpoint to add user by email to the Agency on the Agency Administration Page

    Args:
        guid (str): The users unique identifier
        email (str): The users email address
        first_name (str): The users' first name. If None, then the mailbox part of the email address will be used
        middle_initial (str): The users' middle initial. Can be None
        last_name (str): The users' last name. Required.
        email_validated (bool): Determines whether the users' email has been validated.
        is_nyc_employee (bool): Determines
        has_nyc_account,
        active,
        terms_of_use_accepted,
        is_anonymous_requester

    Returns:
        Users: The user that was pulled from the database (and updated) or the new user)
    """
    mailbox, _ = email.split('@')

    if first_name is None:
        first_name = mailbox

    user = Users.query.filter_by(guid=guid).first()
    if user is None:
        user = find_user_by_email(email)

    # update or create user
    if user is not None:
        _update_user_data(
            user,
            guid,
            email,
            first_name,
            middle_initial,
            last_name,
            email_validated,
            is_nyc_employee,
            has_nyc_account,
            active,
            terms_of_use_accepted,
            is_anonymous_requester
        )
    else:
        user = Users(
            guid=guid,
            email=email,
            first_name=first_name,
            middle_initial=middle_initial,
            last_name=last_name,
            email_validated=email_validated,
            is_nyc_employee=is_nyc_employee,
            has_nyc_account=has_nyc_account,
            active=active,
            terms_of_use_accepted=terms_of_use_accepted,
            is_anonymous_requester=is_anonymous_requester
        )
        create_object(user)

    return user
Esempio n. 39
0
def create_contact_record(request, first_name, last_name, email, subject, message):
    """
    Creates Users, Emails, and Events entries for a contact submission for a request.
    Sends email with message to all agency users associated with the request.

    :param request: request object
    :param first_name: sender's first name
    :param last_name: sender's last name
    :param email: sender's email
    :param subject: subject of email
    :param message: email body
    """
    if current_user == request.requester:
        user = current_user
    else:
        user = Users(
            guid=generate_guid(),
            email=email,
            first_name=first_name,
            last_name=last_name,
            email_validated=False,
            terms_of_use_accepted=False,
            is_anonymous_requester=True
        )
        create_object(user)

        create_object(Events(
            request_id=request.id,
            user_guid=None,
            type_=event_type.USER_CREATED,
            new_value=user.val_for_events
        ))

    body = "Name: {} {}\n\nEmail: {}\n\nSubject: {}\n\nMessage:\n{}".format(
        first_name, last_name, email, subject, message)

    agency_emails = get_agency_emails(request.id)

    email_obj = Emails(
        request.id,
        PRIVATE,
        to=','.join([email.replace('{', '').replace('}', '') for email in agency_emails]),
        cc=None,
        bcc=None,
        subject=subject,
        body=body
    )

    create_object(email_obj)

    create_object(Events(
        request_id=request.id,
        user_guid=user.guid,
        type_=event_type.CONTACT_EMAIL_SENT,
        response_id=email_obj.id,
        new_value=email_obj.val_for_events
    ))

    send_contact_email(
        subject,
        agency_emails,
        message,
        email
    )
Esempio n. 40
0
def _update_request_statuses():
    """
    Update statuses for all requests that are now Due Soon or Overdue
    and send a notification email to agency admins listing the requests.
    """
    now = datetime.utcnow()
    due_soon_date = calendar.addbusdays(
        now, current_app.config['DUE_SOON_DAYS_THRESHOLD']
    ).replace(hour=23, minute=59, second=59)  # the entire day

    agencies = Agencies.query.with_entities(Agencies.ein).filter_by(is_active=True).all()
    for agency_ein, in agencies:
        requests_overdue = Requests.query.filter(
            Requests.due_date < now,
            Requests.status != request_status.CLOSED,
            Requests.agency_ein == agency_ein
        ).order_by(
            Requests.due_date.asc()
        ).all()

        requests_due_soon = Requests.query.filter(
            Requests.due_date > now,
            Requests.due_date <= due_soon_date,
            Requests.status != request_status.CLOSED,
            Requests.agency_ein == agency_ein
        ).order_by(
            Requests.due_date.asc()
        ).all()

        if not requests_overdue and not requests_due_soon:
            continue

        agency_requests_overdue = []
        agency_acknowledgments_overdue = []
        agency_requests_due_soon = []
        agency_acknowledgments_due_soon = []

        # OVERDUE
        for request in requests_overdue:

            if request.was_acknowledged:
                agency_requests_overdue.append(request)
            else:
                agency_acknowledgments_overdue.append(request)

            if request.status != request_status.OVERDUE:
                create_object(
                    Events(
                        request.id,
                        user_guid=None,
                        type_=REQ_STATUS_CHANGED,
                        previous_value={"status": request.status},
                        new_value={"status": request_status.OVERDUE},
                        response_id=None,
                    )
                )
                update_object(
                    {"status": request_status.OVERDUE},
                    Requests,
                    request.id)

        # DUE SOON
        for request in requests_due_soon:

            if request.was_acknowledged:
                agency_requests_due_soon.append(request)
            else:
                agency_acknowledgments_due_soon.append(request)

            if request.status != request_status.DUE_SOON:
                create_object(
                    Events(
                        request.id,
                        user_guid=None,
                        type_=REQ_STATUS_CHANGED,
                        previous_value={"status": request.status},
                        new_value={"status": request_status.DUE_SOON},
                        response_id=None,
                    )
                )
                update_object(
                    {"status": request_status.DUE_SOON},
                    Requests,
                    request.id)

        # mail to agency admins for each agency
        user_emails = list(set(admin.notification_email or admin.email for admin
                               in Agencies.query.filter_by(ein=agency_ein).one().administrators))

        send_email(
            STATUSES_EMAIL_SUBJECT,
            to=user_emails,
            template=STATUSES_EMAIL_TEMPLATE,
            requests_overdue=agency_requests_overdue,
            acknowledgments_overdue=agency_acknowledgments_overdue,
            requests_due_soon=agency_requests_due_soon,
            acknowledgments_due_soon=agency_acknowledgments_due_soon
        )
        email = Emails(
            request.id,
            PRIVATE,
            to=','.join(user_emails),
            cc=None,
            bcc=None,
            subject=STATUSES_EMAIL_SUBJECT,
            body=render_template(
                STATUSES_EMAIL_TEMPLATE + ".html",
                requests_overdue=agency_requests_overdue,
                acknowledgments_overdue=agency_acknowledgments_overdue,
                requests_due_soon=agency_requests_due_soon,
                acknowledgments_due_soon=agency_acknowledgments_due_soon
            )
        )
        create_object(email)
        create_object(
            Events(
                request.id,
                user_guid=None,
                type_=EMAIL_NOTIFICATION_SENT,
                previous_value=None,
                new_value=email.val_for_events,
                response_id=None,
                timestamp=datetime.utcnow()
            )
        )
Esempio n. 41
0
def update_request_statuses():
    """
    Update statuses for all requests that are now Due Soon or Overdue
    and send a notification email to agency admins listing the requests.
    """
    with scheduler.app.app_context():
        now = datetime.utcnow()
        due_soon_date = calendar.addbusdays(
            now, current_app.config['DUE_SOON_DAYS_THRESHOLD']).replace(
                hour=23, minute=59, second=59)  # the entire day

        requests_overdue = Requests.query.filter(
            Requests.due_date < now,
            Requests.status != request_status.CLOSED).order_by(
                Requests.due_date.asc()).all()

        requests_due_soon = Requests.query.filter(
            Requests.due_date > now, Requests.due_date <= due_soon_date,
            Requests.status != request_status.CLOSED).order_by(
                Requests.due_date.asc()).all()

        agencies_to_requests_overdue = {}
        agencies_to_acknowledgments_overdue = {}
        agencies_to_requests_due_soon = {}
        agencies_to_acknowledgments_due_soon = {}

        def add_to_agencies_to_request_dict(req, agencies_to_request_dict):
            if req.agency.ein not in agencies_to_request_dict:
                agencies_to_request_dict[req.agency.ein] = [req]
            else:
                agencies_to_request_dict[req.agency.ein].append(req)

        # OVERDUE
        for request in requests_overdue:

            if request.was_acknowledged:
                add_to_agencies_to_request_dict(request,
                                                agencies_to_requests_overdue)
            else:
                add_to_agencies_to_request_dict(
                    request, agencies_to_acknowledgments_overdue)

            if request.status != request_status.OVERDUE:
                update_object({"status": request_status.OVERDUE}, Requests,
                              request.id)

        # DUE SOON
        for request in requests_due_soon:

            if request.was_acknowledged:
                add_to_agencies_to_request_dict(request,
                                                agencies_to_requests_due_soon)
            else:
                add_to_agencies_to_request_dict(
                    request, agencies_to_acknowledgments_due_soon)

            if request.status != request_status.DUE_SOON:
                update_object({"status": request_status.DUE_SOON}, Requests,
                              request.id)

        # get all possible agencies to email
        agency_eins = set(
            list(agencies_to_requests_overdue) +
            list(agencies_to_acknowledgments_overdue) +
            list(agencies_to_requests_due_soon) +
            list(agencies_to_acknowledgments_due_soon))

        # mail to agency admins for each agency
        for agency_ein in agency_eins:
            agency_requests_overdue = agencies_to_requests_overdue.get(
                agency_ein, [])
            agency_acknowledgments_overdue = agencies_to_acknowledgments_overdue.get(
                agency_ein, [])
            agency_requests_due_soon = agencies_to_requests_due_soon.get(
                agency_ein, [])
            agency_acknowledgments_due_soon = agencies_to_acknowledgments_due_soon.get(
                agency_ein, [])

            user_emails = list(
                set(admin.notification_email or admin.email
                    for admin in Agencies.query.filter_by(
                        ein=agency_ein).one().administrators))
            send_email(
                STATUSES_EMAIL_SUBJECT,
                to=user_emails,
                template=STATUSES_EMAIL_TEMPLATE,
                requests_overdue=agency_requests_overdue,
                acknowledgments_overdue=agency_acknowledgments_overdue,
                requests_due_soon=agency_requests_due_soon,
                acknowledgments_due_soon=agency_acknowledgments_due_soon)
            email = Emails(
                request.id,
                PRIVATE,
                to=','.join(user_emails),
                cc=None,
                bcc=None,
                subject=STATUSES_EMAIL_SUBJECT,
                body=render_template(
                    STATUSES_EMAIL_TEMPLATE + ".html",
                    requests_overdue=agency_requests_overdue,
                    acknowledgments_overdue=agency_acknowledgments_overdue,
                    requests_due_soon=agency_requests_due_soon,
                    acknowledgments_due_soon=agency_acknowledgments_due_soon))
            create_object(email)
            create_object(
                Events(request.id,
                       user_guid=None,
                       auth_user_type=None,
                       type_=EMAIL_NOTIFICATION_SENT,
                       previous_value=None,
                       new_value=email.val_for_events,
                       response_id=None,
                       timestamp=datetime.utcnow()))