Example #1
0
  def test_last_reviewed(self):
    """last_reviewed_by, last_reviewed_by should be set if reviewed"""
    risk = factories.RiskFactory()
    resp, review = self.generator.generate_object(
        all_models.Review,
        {
            "reviewable": {
                "type": risk.type,
                "id": risk.id,
            },
            "context": None,
            "status": all_models.Review.STATES.UNREVIEWED,
            "access_control_list": build_reviewer_acl(),
            "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE
        },
    )
    review_id = review.id
    resp = self.api.put(
        review,
        {
            "status": all_models.Review.STATES.REVIEWED,
        },
    )
    self.assert200(resp)
    self.assertIsNotNone(resp.json["review"]["last_reviewed_by"])
    self.assertIsNotNone(resp.json["review"]["last_reviewed_at"])

    review = all_models.Review.query.get(review_id)
    self.assertIsNotNone(review.last_reviewed_by)
    self.assertIsNotNone(review.last_reviewed_at)
Example #2
0
  def test_search_risk_by_dates(self, field, attr):
    """Test query endpoint for risk by dates."""
    current_date = datetime.date.today()
    with factories.single_commit():
      factories.RiskFactory(**{attr: current_date})
    request_data = [{
        "filters": {
            "expression": {
                "left": {"left": field,
                         "op": {"name": "~"},
                         "right": current_date.strftime("%Y-%m-%d")},
                "op": {"name": "AND"},
                "right": {"left": "Status",
                          "op": {"name": "IN"},
                          "right": ["Active", "Draft", "Deprecated"]}
            }
        },
        "object_name": "Risk",
        "order_by": [{"name": "updated_at", "desc": "true"}],
    }]

    response = self.api.post(
        all_models.Risk,
        data=request_data,
        url="/query",
    )

    self.assert200(response)
    response_data = response.json[0]["Risk"]
    self.assertEqual(response_data["count"], 1)
    self.assertEqual(response_data["values"][0][attr],
                     current_date.strftime("%Y-%m-%d"))
Example #3
0
  def test_get_risk_external_comment(self):
    """Test query endpoint for risk ExternalComments."""
    with factories.single_commit():
      risk = factories.RiskFactory()
      comment = factories.ExternalCommentFactory(description="comment")
      factories.RelationshipFactory(source=risk, destination=comment)
    request_data = [{
        "filters": {
            "expression": {
                "object_name": "Risk",
                "op": {
                    "name": "relevant"
                },
                "ids": [risk.id]
            },
        },
        "object_name":"ExternalComment",
        "order_by": [{"name": "created_at", "desc": "true"}],
    }]

    response = self.api.post(
        all_models.Risk,
        data=request_data,
        url="/query",
    )

    self.assert200(response)
    response_data = response.json[0]["ExternalComment"]
    self.assertEqual(response_data["count"], 1)
    self.assertEqual(response_data["values"][0]["description"], "comment")
Example #4
0
  def test_search_risk_by_users(self, field, attr):
    """Test query endpoint for risk by users."""
    with factories.single_commit():
      person = factories.PersonFactory()
      factories.RiskFactory(**{attr: person})
    request_data = [{
        "filters": {
            "expression": {
                "left": {"left": field,
                         "op": {"name": "~"},
                         "right": person.email},
                "op": {"name": "AND"},
                "right": {"left": "Status",
                          "op": {"name": "IN"},
                          "right": ["Active", "Draft", "Deprecated"]}
            }
        },
        "object_name": "Risk",
        "order_by": [{"name": "updated_at", "desc": "true"}],
    }]

    response = self.api.post(
        all_models.Risk,
        data=request_data,
        url="/query",
    )

    self.assert200(response)
    response_data = response.json[0]["Risk"]
    self.assertEqual(response_data["count"], 1)
    self.assertEqual(response_data["values"][0][attr]['email'],
                     person.email)
Example #5
0
  def _create_external_object():
    """Populate external model object that could not be imported."""
    with factories.single_commit():
      objects = [
          factories.ControlFactory(directive=None),
          factories.RiskFactory()
      ]

      ca_definitions = {
          cad.title: cad
          for object in objects
          for cad in object.get_custom_attribute_definitions([
              "CA text",
              "CA rich text",
              "CA date",
              "CA multiselect",
              "CA dropdown"
          ])
      }
      ca_values = {
          "CA text": "Control ca text",
          "CA rich text": "control<br><br>\nrich text",
          "CA date": "22/02/2022",
          "CA multiselect": "yes",
          "CA dropdown": "one"
      }

      for title, value in ca_values.items():
        for obj in objects:
          factories.ExternalCustomAttributeValueFactory(
              custom_attribute=ca_definitions[title],
              attributable=obj,
              attribute_value=value
          )
Example #6
0
  def test_update_risk_snapshot(self):
    """Update risk snapshot to the latest version"""
    with factories.single_commit():
      program = factories.ProgramFactory(title="P1")
      risk = factories.RiskFactory(title="R1")
      risk_id = risk.id
      factories.RelationshipFactory(source=program, destination=risk)
    # Risk snapshot created for audit during mapping audit to program
    self.objgen.generate_object(all_models.Audit, {
        "title": "A1",
        "program": {"id": program.id},
        "status": "Planned",
        "snapshots": {
            "operation": "create",
        },
    })
    # Update risk to get outdated snapshot (new risk revision)
    risk = all_models.Risk.query.get(risk_id)
    self.api.put(risk, risk.id, {
        "title": "New risk title",
    })
    audit = all_models.Audit.query.filter_by(title="A1").one()
    snapshot = all_models.Snapshot.query.first()
    self.assertEquals(audit, snapshot.parent)

    # Update snapshot to the latest revision
    response = self.api.put(snapshot, snapshot.id, {
        "update_revision": "latest",
    })

    self.assert200(response)
    self.assertTrue(response.json["snapshot"]["is_latest_revision"])
Example #7
0
 def test_apply_mapping_cad(self):
     """Test apply mapping CAVs proposal."""
     with factories.single_commit():
         risk = factories.RiskFactory(title="1")
         cad = factories.CustomAttributeDefinitionFactory(
             definition_type="risk", attribute_type="Map:Person")
         person = factories.PersonFactory()
         cav = factories.CustomAttributeValueFactory(
             custom_attribute=cad,
             attributable=risk,
             attribute_object_id=person.id,
             attribute_value="Person",
         )
     self.assertEqual(person,
                      risk.custom_attribute_values[0].attribute_object)
     risk_id = risk.id
     proposal = factories.ProposalFactory(instance=risk,
                                          content={
                                              "custom_attribute_values": {
                                                  cad.id: {
                                                      "attribute_value":
                                                      "Person",
                                                      "attribute_object":
                                                      None,
                                                  },
                                              },
                                          },
                                          agenda="agenda content")
     with self.number_obj_revisions_for(risk):
         self.apply_proposal(proposal)
     risk = all_models.Risk.query.get(risk_id)
     cav = risk.custom_attribute_values[0]
     self.assertEqual("Person", cav.attribute_value)
     self.assertIsNone(cav.attribute_object_id)
 def test_mandatory_delete(self, mandatory, exp_response):
     """Test set empty field via import if acr mandatory is {mandatory}"""
     role = factories.AccessControlRoleFactory(
         name=ROLE_NAME,
         object_type="Risk",
         mandatory=mandatory,
     )
     with factories.single_commit():
         user = factories.PersonFactory()
         risk = factories.RiskFactory()
         role_id = role.id
         factories.AccessControlPersonFactory(
             ac_list=risk.acr_name_acl_map[ROLE_NAME],
             person=user,
         )
     response = self.import_data(
         OrderedDict([
             ("object_type", "Risk"),
             ("Code*", risk.slug),
             (ROLE_NAME, "--"),
         ]))
     self._check_csv_response(response, exp_response)
     db_data = defaultdict(set)
     risk = all_models.Risk.query.get(risk.id)
     for person, acl in risk.access_control_list:
         db_data[acl.ac_role_id].add(person.id)
     if mandatory:
         cur_user = all_models.Person.query.filter_by(
             email="*****@*****.**").first()
         self.assertEqual(set([cur_user.id]), db_data[role_id])
     else:
         self.assertFalse(db_data[role_id])
Example #9
0
 def test_change_cad(self):
     """Test create proposal with change CAVs."""
     with factories.single_commit():
         risk = factories.RiskFactory(title="1")
         cad = factories.CustomAttributeDefinitionFactory(
             definition_type="risk")
         factories.CustomAttributeValueFactory(custom_attribute=cad,
                                               attributable=risk,
                                               attribute_value="123")
     risk_id = risk.id
     cad_id = cad.id
     data = risk.log_json()
     data["custom_attribute_values"][0]["attribute_value"] = "321"
     self.create_proposal(risk,
                          full_instance_content=data,
                          agenda="update cav",
                          context=None)
     risk = all_models.Risk.query.get(risk_id)
     self.assertEqual(1, len(risk.proposals))
     self.assertIn("custom_attribute_values", risk.proposals[0].content)
     self.assertEqual(
         {
             unicode(cad_id): {
                 "attribute_value": u"321",
                 "attribute_object": None
             }
         }, risk.proposals[0].content["custom_attribute_values"])
     self.assertEqual(1, len(risk.comments))
 def test_create_after_objects(self):
     """Test eager creation of ACLs on existing objects with new ACR."""
     risk_id = factories.RiskFactory().id
     role_name = "New Custom Role"
     self._post_role(name=role_name, object_type="Risk")
     risk = all_models.Risk.query.get(risk_id)
     self.assertIn(role_name, risk.acr_name_acl_map.keys())
     self.assertIsNotNone(risk.acr_name_acl_map[role_name])
Example #11
0
    def test_delete_risk(self):
        """Test risk delete with internal user."""
        risk = factories.RiskFactory()

        response = self.api.delete(risk)

        self.assert403(response)
        risk = all_models.Risk.query.get(risk.id)
        self.assertIsNotNone(risk.title)
Example #12
0
    def test_update_risk(self):
        """Test risk update with internal user."""
        risk = factories.RiskFactory()
        old_title = risk.title

        response = self.api.put(risk, {"title": "new-title"})

        self.assert403(response)
        risk = all_models.Risk.query.get(risk.id)
        self.assertEqual(old_title, risk.title)
    def test_delete(self):
        """Test risk delete with internal user."""
        risk = factories.RiskFactory()
        url = "/api/risks/%s" % risk.id

        response = self.api.delete(url)
        self.assert403(response)

        risk = all_models.Risk.query.get(risk.id)
        self.assertIsNotNone(risk)
Example #14
0
    def test_update_review_status_to_null(self):
        """Test review_status is not set to None"""
        risk = factories.RiskFactory()
        response = self.api.put(risk, {"review_status": None})
        self.assert400(response)
        self.assertEqual(response.json["message"],
                         "Review status for the object is not specified")

        risk = db.session.query(all_models.Risk).get(risk.id)
        self.assertIsNotNone(risk.external_id)
Example #15
0
    def test_rel_remove_parent(self):
        """Test if relationship will be removed if parent instance is removed."""
        risk = factories.RiskFactory()
        self.create_proposal_for(risk)
        self.assertEqual(1, self.proposal_relationships(risk).count())

        response = self.api.delete(risk)

        self.assert200(response)
        self.assertEqual(0, self.proposal_relationships(risk).count())
Example #16
0
    def test_rel_remove_proposal(self):
        """Test if relationship will be removed if proposal is removed."""
        risk = factories.RiskFactory()
        response = self.create_proposal_for(risk)
        self.assertEqual(1, self.proposal_relationships(risk).count())

        proposal = all_models.Proposal.query.get(
            response.json["proposal"]["id"])
        response = self.api.delete(proposal)
        self.assert200(response)
        self.assertEqual(0, self.proposal_relationships(risk).count())
    def test_update(self):
        """Test risk update with external user."""
        risk = factories.RiskFactory()
        url = "/api/risks/%s" % risk.id

        risk_body = self.generate_risk_body()
        risk_body["id"] = risk.id
        response = self.api.put(url, {"risk": risk_body})
        self.assert200(response)

        risk = all_models.Risk.query.get(risk.id)
        self.assert_instance(risk_body, risk)
    def test_update(self):
        """Test risk update with internal user."""
        risk = factories.RiskFactory()
        url = "/api/risks/%s" % risk.id
        old_title = risk.title

        data = {"risk": {"title": "new-title", "risk_type": "risk"}}
        response = self.api.put(url, data)
        self.assert403(response)

        risk = all_models.Risk.query.get(risk.id)
        self.assertEqual(old_title, risk.title)
Example #19
0
  def test_update_review_status_display_name(self):
    """Test review_status_display_name is updated"""
    risk = factories.RiskFactory()
    new_value = "test123"

    self.api.put(risk, risk.id, {
        "review_status_display_name": new_value,
        "review_status": all_models.Review.STATES.UNREVIEWED
    })

    risk = db.session.query(all_models.Risk).get(risk.id)
    self.assertEquals(risk.review_status_display_name, new_value)
Example #20
0
    def test_update_review_status(self):
        """Test review_status is updated"""
        risk = factories.RiskFactory()
        new_value = all_models.Review.STATES.REVIEWED
        self.api.put(
            risk, {
                "review_status": new_value,
                "review_status_display_name": "some status"
            })

        risk = db.session.query(all_models.Risk).get(risk.id)
        self.assertEquals(risk.review_status, new_value)
Example #21
0
    def test_review_status_search(self):
        """Review status search.

    The query should take data form review_status_display_name field
    """
        risk_id = factories.RiskFactory(
            review_status_display_name="Review Needed").id
        risk_by_review_status = self.simple_query(
            "Risk", expression=["Review Status", "=", "Review Needed"])

        self.assertEquals(1, len(risk_by_review_status))
        self.assertEquals(risk_id, risk_by_review_status[0]["id"])
Example #22
0
  def test_delete_review(self):
    """Test delete review via API"""
    with factories.single_commit():
      risk = factories.RiskFactory()
      risk_id = risk.id
      review = factories.ReviewFactory(reviewable=risk)
      review_id = review.id
    resp = self.api.delete(review)
    self.assert200(resp)
    review = all_models.Review.query.get(review_id)
    risk = all_models.Risk.query.get(risk_id)

    self.assertIsNone(review)
    self.assertEquals(0, len(risk.related_objects(_types=["Review"])))
Example #23
0
    def test_nonadmin_has_no_access(self):
        """Test access to proposal for non creator of proposal"""
        role_creator = all_models.Role.query.filter(
            all_models.Role.name == "Creator").one()

        # prepare - create risk, assign roles
        factories.AccessControlRoleFactory(name="ACL_Reader",
                                           object_type="Risk",
                                           update=0)
        with factories.single_commit():
            risk = factories.RiskFactory()
            person1 = factories.PersonFactory()
            person2 = factories.PersonFactory()
            for person in (person1, person2):
                rbac_factories.UserRoleFactory(role=role_creator,
                                               person=person)
                factories.AccessControlPersonFactory(
                    ac_list=risk.acr_name_acl_map["ACL_Reader"],
                    person=person,
                )
            risk_id = risk.id
            person2_id = person2.id

        # make query to create proposal by person1
        self.api.set_user(person1)
        self.client.get("/login")

        acr_class = all_models.AccessControlRole
        acr = acr_class.query.filter(
            acr_class.name == 'ProposalEditor',
            acr_class.object_type == 'Proposal').one()

        create_data = self._get_create_proposal_request(
            risk_id, acr.id, person1.id)
        self.api.post(all_models.Proposal, create_data)

        # login as person2 and make request
        self.api.set_user(all_models.Person.query.get(person2_id))
        self.client.get("/login")

        query_data = self._get_query_proposal_request(risk_id)
        headers = {
            "Content-Type": "application/json",
        }
        resp = self.api.client.post("/query",
                                    data=json.dumps(query_data),
                                    headers=headers).json
        self.assertEqual(1, len(resp))
        self.assertEqual(resp[0]["Proposal"]["count"], 0)
 def test_risk_memcache(self):
     """Test get updated risk revisions."""
     risk = factories.RiskFactory()
     risk_id = risk.id
     self.api.put(risk, {"title": "new_title"})
     self.update_revisions(risk)
     db.session.expire_all()
     risk = all_models.Risk.eager_query().get(risk_id)
     self.api.put(risk, {"description": "new test description BLA"})
     risk = all_models.Risk.eager_query().get(risk_id)
     self.update_revisions(risk)
     risk = all_models.Risk.eager_query().get(risk_id)
     self.api.put(risk, {"description": "BLA bla bla"})
     risk = all_models.Risk.eager_query().get(risk_id)
     self.update_revisions(risk)
    def setUp(self):
        """Set up for Reviewable test cases."""
        super(TestExportReviewable, self).setUp()

        with factories.single_commit():
            person1 = factories.PersonFactory()
            self.person1_email = person1.email
            person2 = factories.PersonFactory()
            self.person2_email = person2.email
            risk = factories.RiskFactory(title="Test risk")
            review = factories.ReviewFactory(reviewable=risk)

            review.add_person_with_role_name(person1, 'Reviewers')
            review.add_person_with_role_name(person2, 'Reviewers')

        self.client.get("/login")
Example #26
0
    def test_revision_review_stub(self):
        """ Test proper review stub population in revision content """
        risk = factories.RiskFactory()
        revisions = _get_revisions(risk)
        self.assertEqual(len(revisions), 1)
        self.assertEqual(revisions[0].action, "created")

        resp = self.api_helper.post(
            all_models.Review,
            {
                "review": {
                    "reviewable": {
                        "type": risk.type,
                        "id": risk.id,
                    },
                    "context": None,
                    "notification_type": "email",
                    "status": all_models.Review.STATES.REVIEWED,
                    "access_control_list": build_reviewer_acl()
                },
            },
        )
        self.assertEqual(201, resp.status_code)
        self.assertIn("review", resp.json)
        resp_review = resp.json["review"]
        self.assertEqual(all_models.Review.STATES.REVIEWED,
                         resp_review["status"])

        revisions = _get_revisions(risk)
        self.assertEqual(len(revisions), 2)
        self.assertEqual(revisions[0].action, "created")
        self.assertEqual(revisions[1].action, "modified")

        rev_content = revisions[1].content
        self.assertIsNotNone(rev_content)
        self.assertIn("review", rev_content)
        review = rev_content["review"]
        self.assertIsNotNone(review)

        expected = {
            "context_id": None,
            "href": "/api/reviews/{}".format(resp_review["id"]),
            "id": resp_review["id"],
            "type": resp_review["type"],
        }

        self.assertEqual(review, expected)
    def test_notification_subject(self, send_mail_mock):
        """Test that emails are sent with proper subject."""
        expected_subject = "GGRC Change requests review digest " \
                           "for 01/15/2019 04:00:00 PST"

        reviewer = factories.PersonFactory()
        reviewer_role_id = all_models.AccessControlRole.query.filter_by(
            name="Reviewers",
            object_type="Review",
        ).one().id

        with factories.single_commit():
            risk_admin = factories.PersonFactory()
            risk = factories.RiskFactory()
            risk.add_person_with_role_name(risk_admin, "Admin")

        email_message = "email email_message"
        _, review = self.generator.generate_object(
            all_models.Review,
            {
                "reviewable": {
                    "type": risk.type,
                    "id": risk.id,
                },
                "context":
                None,
                "notification_type":
                all_models.Review.NotificationTypes.EMAIL_TYPE,
                "status":
                all_models.Review.STATES.REVIEWED,
                "email_message":
                email_message,
                "access_control_list": [{
                    "ac_role_id": reviewer_role_id,
                    "person": {
                        "id": reviewer.id
                    },
                }],
            },
        )

        self.api.modify_object(review.reviewable, {"title": "new title"})
        with mock.patch.object(fast_digest.DIGEST_TMPL, "render"):
            fast_digest.send_notification()
            for call_item in send_mail_mock.call_args_list:
                self.assertEqual(expected_subject, call_item[1]["subject"])
Example #28
0
  def test_proposal_apply_review_status(self, notification_type,
                                        num_notifications_expected):
    """Change via proposal with ignorable attrs review status not change"""
    with factories.single_commit():
      risk = factories.RiskFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED,
          reviewable=risk,
          notification_type=notification_type
      )
      review_id = review.id

      user = factories.PersonFactory()
      acl = factories.AccessControlListFactory(
          ac_role=factories.AccessControlRoleFactory(object_type="Risk"),
          object=risk
      )

      proposal_content = {
          "access_control_list": {
              acl.ac_role_id: {
                  "added": [{"id": user.id, "email": user.email}],
                  "deleted": []
              }
          }
      }

      proposal = factories.ProposalFactory(
          instance=risk,
          content=proposal_content,
          agenda="agenda content"
      )

    self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED})
    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    review_notif_types = all_models.Review.NotificationObjectTypes
    notif_unreviewed_type = all_models.Notification.query.join(
        all_models.NotificationType
    ).filter(
        all_models.NotificationType.name ==
        review_notif_types.STATUS_UNREVIEWED
    ).all()

    self.assertEqual(num_notifications_expected, len(notif_unreviewed_type))
 def test_comment_import(self):
     """Don't revert state when comment added.
 Review -> REVIEWED
 """
     risk = factories.RiskFactory()
     resp, review = generate_review_object(
         risk, state=all_models.Review.STATES.REVIEWED)
     del review
     risk_id = risk.id
     self.assertEqual(201, resp.status_code)
     import_data = OrderedDict([("object_type", "Risk"),
                                ("Code*", risk.slug),
                                ("comments", "some comments")])
     response = self.import_data(import_data)
     self._check_csv_response(response, {})
     risk = all_models.Risk.query.get(risk_id)
     self.assertEqual(all_models.Review.STATES.REVIEWED, risk.review_status)
Example #30
0
 def test_simple_create_proposal(self):
     """Test simple create proposal."""
     new_vulnerability = "2"
     risk = factories.RiskFactory(vulnerability="1")
     risk_id = risk.id
     risk.vulnerability = new_vulnerability
     self.assertEqual(0, len(risk.comments))
     self.create_proposal(risk,
                          full_instance_content=risk.log_json(),
                          agenda="update title from 1 to 2",
                          context=None)
     risk = all_models.Risk.query.get(risk_id)
     self.assertEqual(1, len(risk.proposals))
     self.assertIn("fields", risk.proposals[0].content)
     self.assertEqual({"vulnerability": "2"},
                      risk.proposals[0].content["fields"])
     self.assertEqual(1, len(risk.comments))