示例#1
0
    def test_collection_get(self):
        """Test simple collection get"""
        with factories.single_commit():
            review1 = factories.ReviewFactory(
                status=all_models.Review.STATES.UNREVIEWED)
            review2 = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED)

        resp = self.api.get_collection(all_models.Review,
                                       [review1.id, review2.id])
        self.assert200(resp)
        self.assertIn("reviews_collection", resp.json)
        self.assertIn("reviews", resp.json["reviews_collection"])
        self.assertEquals(2, len(resp.json["reviews_collection"]["reviews"]))
    def test_gca_with_varying_titles(self, title):
        """if GCA with any title is changed review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="program",
                             title=title,
                             attribute_type="Rich Text")
            program = factories.ProgramFactory()

            program.custom_attribute_values = [{
                "attribute_value": "starting_value",
                "custom_attribute_id": gca.id
            }]
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)
        review_id = review.id
        reviewable = review.reviewable

        review = all_models.Review.query.get(review_id)

        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

        self.api.modify_object(
            reviewable, {
                "custom_attribute_values": [{
                    "custom_attribute_id": gca.id,
                    "attribute_value": "new_value",
                }],
            })

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
    def test_gca(self):
        """if GCA of reviewable is changed review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="control",
                             title="rich_test_gca",
                             attribute_type="Rich Text")
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
        review_id = review.id
        reviewable = review.reviewable

        review = all_models.Review.query.get(review_id)

        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

        self.api.modify_object(
            reviewable, {
                "custom_attribute_values": [{
                    "custom_attribute_id": gca.id,
                    "attribute_value": "new_value",
                }],
            })

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
示例#4
0
    def test_proposal_apply_notification(self, notification_type,
                                         expected_notifications):
        """Reviewable object changed via proposal -> notification created"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED,
                reviewable=program,
                notification_type=notification_type)
            review_id = review.id

            proposal_content = {
                "fields": {
                    "title": "new title"
                },
            }
            proposal = factories.ProposalFactory(instance=program,
                                                 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.UNREVIEWED)
        review_notif_types = all_models.Review.NotificationObjectTypes

        notyf_unreviewed_type = all_models.Notification.query.join(
            all_models.NotificationType).filter(
                all_models.NotificationType.name ==
                review_notif_types.STATUS_UNREVIEWED).all()
        self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
示例#5
0
    def test_map_person_gca(self):
        """if Map:Person GCA value added review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="control",
                             title="map_test_gca",
                             attribute_type="Map:Person")

            user_id = all_models.Person.query.filter_by(
                email="*****@*****.**").one().id

            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)

        review_id = review.id
        reviewable = review.reviewable
        review = all_models.Review.query.get(review_id)

        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

        self.api.modify_object(
            reviewable, {
                "custom_attribute_values": [{
                    "custom_attribute_id": gca.id,
                    "attribute_object_id": user_id,
                    "attribute_value": "Person",
                }],
            })

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
示例#6
0
    def test_reviewable_attributes(self, notification_type,
                                   expected_notifications):
        """Review change state to Unreviewed

     Notification with notification type STATUS_UNREVIEWED created
    """
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED,
                reviewable=program,
                notification_type=notification_type)
        review_id = review.id
        reviewable = review.reviewable

        self.api.modify_object(reviewable, {"title": "new title"})
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)

        review_notif_types = all_models.Review.NotificationObjectTypes

        notyf_unreviewed_type = all_models.Notification.query.join(
            all_models.NotificationType).filter(
                all_models.NotificationType.name ==
                review_notif_types.STATUS_UNREVIEWED).all()
        self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
示例#7
0
    def test_map_snapshotable_notification(self, notification_type,
                                           expected_notifications):
        """Map snapshotable should change review status and add notification"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED,
                reviewable=program,
                notification_type=notification_type)
            review_id = review.id

        self.generator.generate_relationship(
            source=program,
            destination=factories.ProductFactory(),
            context=None,
        )

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
        review_notif_types = all_models.Review.NotificationObjectTypes

        notyf_unreviewed_type = all_models.Notification.query.join(
            all_models.NotificationType).filter(
                all_models.NotificationType.name ==
                review_notif_types.STATUS_UNREVIEWED).all()
        self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
    def test_acl_roles(self):
        """Update of reviewable ACL shouldn't change review status"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
        review_id = review.id

        ac_role_id = all_models.AccessControlRole.query.filter_by(
            name="Primary Contacts", object_type="Control").one().id

        user_id = all_models.Person.query.filter_by(
            email="*****@*****.**").one().id

        self.api.modify_object(
            control, {
                "access_control_list": [{
                    "ac_role_id": ac_role_id,
                    "person": {
                        "id": user_id
                    },
                }],
            })
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
 def test_review_status_update(self):
   """Test updating folder preserves review status"""
   threat = factories.ThreatFactory()
   factories.ReviewFactory(
       reviewable=threat,
       status=all_models.Review.STATES.REVIEWED,
   )
   self.api.put(threat, {"folder": factories.random_str()})
   program = all_models.Threat.query.get(threat.id)
   self.assertEqual(program.review.status, all_models.Review.STATES.REVIEWED)
示例#10
0
 def test_review_status_update(self):
   """Test updating folder preserves review status"""
   control = factories.ControlFactory()
   factories.ReviewFactory(
       reviewable=control,
       status=all_models.Review.STATES.REVIEWED,
   )
   self.api.put(control, {"folder": factories.random_str()})
   control = all_models.Control.query.get(control.id)
   self.assertEqual(control.review.status, all_models.Review.STATES.REVIEWED)
示例#11
0
    def test_review_get(self):
        """Test that review data is present in control get response"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(reviewable=control)
            review_id = review.id

        resp = self.api.get(all_models.Control, control.id)
        self.assert200(resp)
        resp_control = resp.json["control"]
        self.assertIn("review", resp_control)
        self.assertEquals(review_id, resp_control["review"]["id"])
示例#12
0
    def test_mapping_non_snapshotable(self):
        """Map non-snapshotable shouldn't change review status"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
            review_id = review.id

        factories.RelationshipFactory(source=control,
                                      destination=factories.IssueFactory())

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
示例#13
0
    def test_delete_review(self):
        """Test delete review via API"""
        with factories.single_commit():
            control = factories.ControlFactory()
            control_id = control.id
            review = factories.ReviewFactory(reviewable=control)
            review_id = review.id
        resp = self.api.delete(review)
        self.assert200(resp)
        review = all_models.Review.query.get(review_id)
        control = all_models.Control.query.get(control_id)

        self.assertIsNone(review)
        self.assertEquals(0, len(control.related_objects(_types=["Review"])))
示例#14
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"])))
示例#15
0
    def test_delete_review(self):
        """Test delete review via API"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            program_id = program.id
            review = factories.ReviewFactory(reviewable=program)
            review_id = review.id
        resp = self.api.delete(review)
        self.assert200(resp)
        review = all_models.Review.query.get(review_id)
        program = all_models.Program.query.get(program_id)

        self.assertIsNone(review)
        self.assertEquals(0, len(program.related_objects(_types=["Review"])))
示例#16
0
    def test_comments(self):
        """Add comment to reviewable shouldn't update review state"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
        review_id = review.id

        self.generator.generate_comment(control,
                                        "Verifiers",
                                        "some comment",
                                        send_notification="false")

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
示例#17
0
    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
            program = factories.ProgramFactory(title="Test program")
            review = factories.ReviewFactory(reviewable=program)

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

        self.client.get("/login")
示例#18
0
    def test_reviewable_attributes(self, attr_to_modify, new_value):
        """If attribute '{0}' modified move review to Unreviewed state"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
        review_id = review.id
        reviewable = review.reviewable

        self.api.modify_object(reviewable, {
            attr_to_modify:
            new_value() if callable(new_value) else new_value
        })

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
示例#19
0
    def test_map_snapshotable(self, snapshotable):
        """Map '{}' should change review status"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
            review_id = review.id

        self.generator.generate_relationship(
            source=control,
            destination=factories.get_model_factory(snapshotable)(),
            context=None,
        )

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
示例#20
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))
示例#21
0
 def test_change_control_folder(self):
     """Updating folder via import should not change review status."""
     control = factories.ControlFactory(title="Control")
     factories.ReviewFactory(
         reviewable=control,
         status=all_models.Review.STATES.REVIEWED,
     )
     import_data = OrderedDict([("object_type", "Control"),
                                ("Code*", control.slug),
                                ("Folder", factories.random_str())])
     response = self.import_data(import_data)
     self._check_csv_response(response, {})
     control = all_models.Control.query.get(control.id)
     self.assertEqual(
         all_models.Review.STATES.REVIEWED,
         control.review_status,
     )
示例#22
0
 def test_simple_get(self):
     """Test simple get"""
     with factories.single_commit():
         control = factories.ControlFactory()
         review = factories.ReviewFactory(
             email_message="test email message",
             notification_type="email",
             reviewable=control,
             status=all_models.Review.STATES.UNREVIEWED)
     resp = self.api.get(all_models.Review, review.id)
     self.assert200(resp)
     self.assertIn("review", resp.json)
     resp_review = resp.json["review"]
     self.assertEqual(all_models.Review.STATES.UNREVIEWED,
                      resp_review["status"])
     self.assertEqual(all_models.Review.NotificationTypes.EMAIL_TYPE,
                      resp_review["notification_type"])
     self.assertEqual("test email message", resp_review["email_message"])
示例#23
0
    def test_last_reviewed(self):
        """last_reviewed_by, last_reviewed_by should be set if reviewed"""
        review = factories.ReviewFactory(
            status=all_models.Review.STATES.UNREVIEWED)
        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)
示例#24
0
    def test_restore_review_status(self):
        """Test empty restore from Version History
    shouldn't restore review_status"""
        factories.ReviewFactory(status=all_models.Review.STATES.REVIEWED,
                                reviewable=self.program)

        response = self.api.put(
            self.program,
            data={},
        )

        self.assert200(response)
        self.program = self.refresh_object(
            all_models.Program,
            id_=self.program.id,
        )
        self.assertEqual(self.program.review_status,
                         all_models.Review.STATES.REVIEWED)
示例#25
0
    def test_reference_url(self):
        """If reference url is updated state should not updated"""
        with factories.single_commit():
            control = factories.ControlFactory()
            doc = factories.DocumentReferenceUrlFactory(
                title="Simple title",
                link="some_url.com",
                description="mega description",
                parent_obj={
                    "id": control.id,
                    "type": "Control"
                })
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
        review_id = review.id

        self.api.modify_object(doc, {"link": "new_link.com"})
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
示例#26
0
    def test_proposal_apply(self):
        """Reviewable object changed via proposal -> review.state-> UNREVIEWED"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=control)
            review_id = review.id

            proposal_content = {
                "fields": {
                    "title": "new title"
                },
            }
            proposal = factories.ProposalFactory(instance=control,
                                                 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.UNREVIEWED)
示例#27
0
    def test_reviewable_revisions(self):
        """Check that proper revisions are created"""
        with factories.single_commit():
            control = factories.ControlFactory()
            control_id = control.id
            review = factories.ReviewFactory(
                reviewable=control, status=all_models.Review.STATES.UNREVIEWED)
        reviewable = review.reviewable

        control_revisions = all_models.Revision.query.filter_by(
            resource_id=control_id, resource_type=control.type).order_by(
                all_models.Revision.created_at, ).all()
        self.assertEquals(1, len(control_revisions))
        self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                          control_revisions[0].content["review_status"])

        resp = self.api.put(
            review,
            {
                "status": all_models.Review.STATES.REVIEWED,
            },
        )
        self.assert200(resp)

        control_revisions = all_models.Revision.query.filter_by(
            resource_id=control_id, resource_type=control.type).order_by(
                all_models.Revision.created_at, ).all()
        self.assertEquals(2, len(control_revisions))
        self.assertEquals(all_models.Review.STATES.REVIEWED,
                          control_revisions[1].content["review_status"])

        resp = self.api.put(reviewable,
                            {"description": "some new description"})
        self.assert200(resp)

        control_revisions = all_models.Revision.query.filter_by(
            resource_id=control_id, resource_type=control.type).order_by(
                all_models.Revision.created_at, ).all()
        self.assertEquals(3, len(control_revisions))
        self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                          control_revisions[2].content["review_status"])
示例#28
0
    def test_unmap_snapshotable(self):
        """Unmap snapshotable should change review status"""
        with factories.single_commit():
            control = factories.ControlFactory()
            review = factories.ReviewFactory(reviewable=control)
            review_id = review.id

        _, rel = self.obj_gen.generate_relationship(
            source=control,
            destination=factories.ProductFactory(),
            context=None,
        )

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

        resp = self.api.delete(rel)
        self.assert200(resp)
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
    def test_update_map_person_gca(self):
        """if existing Map:Person GCA value changed review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="program",
                             title="map_test_gca",
                             attribute_type="Map:Person")

            first_user_id = all_models.Person.query.filter_by(
                email="*****@*****.**").one().id
            second_user_id = factories.PersonFactory().id

            program = factories.ProgramFactory()
            program.custom_attribute_values = [{
                "attribute_object_id": first_user_id,
                "custom_attribute_id": gca.id,
                "attribute_value": "Person"
            }]
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)

        review_id = review.id
        reviewable = review.reviewable
        review = all_models.Review.query.get(review_id)

        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

        self.api.modify_object(
            reviewable, {
                "custom_attribute_values": [{
                    "custom_attribute_id": gca.id,
                    "attribute_object_id": second_user_id,
                    "attribute_value": "Person",
                }],
            })

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
示例#30
0
class TestFullFilledModelExport(TestCase):
  """Test for export a full filled model"""
  # pylint: disable=undefined-variable

  FIELDS_FILLED_RULES = {
      'archived': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'archived',
          False
      ),
      'assertions': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'assertions',
          'assertions'
      ),
      'assessment_template': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'assessment_template',
          'assessment_template'
      ),
      'assessment_type': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'assessment_type',
          'Control'
      ),
      'audit': lambda **kwargs: TestFullFilledModelExport._map_object(
          source=kwargs['obj'],
          destination=kwargs['obj'].audit
      ),
      'categories': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'categories',
          '["categories"]'
      ),
      'comments': lambda **kwargs: TestFullFilledModelExport._map_object(
          source=kwargs['obj'],
          destination=factories.CommentFactory(
              description='description',
              assignee_type='Admin'
          )
      ),
      'company': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'company',
          'company'
      ),
      'component_id': lambda **kwargs: factories.IssueTrackerIssueFactory(
          enabled=True,
          issue_tracked_obj=kwargs['obj'],
          issue_id=123,
          issue_type="PROCESS",
          component_id=12345,
          hotlist_id=12345,
          issue_priority="P2",
          issue_severity="S2",
          issue_url="somelink",
      ),
      'contact': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'contact',
          kwargs['user']
      ),
      'created_at': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'created_at',
          datetime.date(2019, 9, 24)
      ),
      'created_by': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'created_by_id',
          kwargs['user'].id
      ),
      'cycle': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'cycle',
          'cycle'
      ),
      'cycle_task_group': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'cycle_task_group',
          'cycle_task_group'
      ),
      'cycle_workflow': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'cycle_workflow',
          'cycle_workflow'
      ),
      'default_assignees': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'default_assignees',
          kwargs['user']
      ),
      'default_verifier': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'default_verifier',
          kwargs['user']
      ),
      'directive': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'directive',
          'directive'
      ),
      'delete': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'delete',
          'delete'
      ),
      'description': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'description',
          'description'
      ),
      'design': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'design',
          'Effective'
      ),
      'documents_file': lambda **kwargs: TestFullFilledModelExport._map_object(
          source=factories.DocumentFileFactory(link='link'),
          destination=kwargs['obj'],
      ),
      'documents_reference_url':
      lambda **kwargs: TestFullFilledModelExport._map_object(
          source=factories.DocumentReferenceUrlFactory(link='link'),
          destination=kwargs['obj'],
      ),
      'due_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'due_date',
          datetime.date(2019, 9, 24)
      ),
      'email': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'email',
          '*****@*****.**'
      ),
      'enabled': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'enabled',
          True
      ),
      'end_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'end_date',
          datetime.date(2019, 9, 24)
      ),
      'evidences_file': lambda **kwargs: TestFullFilledModelExport._map_object(
          source=factories.EvidenceFileFactory(),
          destination=kwargs['obj'],
      ),
      'evidences_url': lambda **kwargs: TestFullFilledModelExport._map_object(
          source=factories.EvidenceUrlFactory(),
          destination=kwargs['obj'],
      ),
      'finished_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'finished_date',
          datetime.date(2019, 9, 24)
      ),
      'folder': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'folder',
          'folder'
      ),
      'fraud_related': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'fraud_related',
          True
      ),
      'hotlist_id': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'hotlist_id',
          'hotlist_id'
      ),
      'is_verification_needed': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'is_verification_needed',
          True
      ),
      'issue_priority': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'issue_priority',
          'issue_priority'
      ),
      'issue_severity': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'issue_severity',
          'issue_severity'
      ),
      'issue_title': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'issue_title',
          'issue_title'
      ),
      'issue_tracker': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'issue_tracker',
          'issue_tracker'
      ),
      'issue_type': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'issue_type',
          'issue_type'
      ),
      'key_control': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'key_control',
          True
      ),
      'kind': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'kind',
          all_models.Option.query.filter(
              all_models.Option == 'product_type'
          ).first()
      ),
      'labels': lambda **kwargs: factories.ObjectLabelFactory(
          labeled_object=kwargs['obj'],
          label=factories.LabelFactory(
              object_type=kwargs['obj'].__tablename__
          ),
      ),
      'last_assessment_date':
      lambda **kwargs: TestFullFilledModelExport._create_attributes(
          kwargs['obj'],
          1
      ),
      'last_comment':
      lambda **kwargs: TestFullFilledModelExport._create_attributes(
          kwargs['obj'],
          3
      ),
      'last_deprecated_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'last_deprecated_date',
          datetime.date(2019, 9, 24)
      ),
      'last_submitted_at': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'last_submitted_at',
          datetime.date(2019, 9, 24)
      ),
      'last_submitted_by': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'last_submitted_by_id',
          kwargs['user'].id
      ),
      'last_verified_at': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'last_verified_at',
          datetime.date(2019, 9, 24)
      ),
      'last_verified_by': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'last_verified_by_id',
          kwargs['user'].id
      ),
      'means': lambda **kwargs: set_attribute(kwargs['obj'], 'means', 'means'),
      'modified_by': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'modified_by',
          kwargs['user']
      ),
      'name': lambda **kwargs: set_attribute(kwargs['obj'], 'name', 'name'),
      'network_zone': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'network_zone',
          all_models.Option.query.filter(
              all_models.Option == 'network_zone'
          ).first()
      ),
      'notes': lambda **kwargs: set_attribute(kwargs['obj'], 'notes', 'notes'),
      'notify_custom_message': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'notify_custom_message',
          'notify_custom_message'
      ),
      'notify_on_change': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'notify_on_change',
          True
      ),
      'operationally': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'operationally',
          'Effective'
      ),
      'people_sync_enabled': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'people_sync_enabled',
          True
      ),
      'procedure_description': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'procedure_description',
          'procedure description'
      ),
      'program': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'program',
          'program'
      ),
      'readonly': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'readonly',
          True
      ),
      'recipients': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'recipients',
          'recipients'
      ),
      'repeat_every': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'repeat_every',
          1
      ),
      'report_end_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'report_end_date',
          datetime.date(2019, 9, 24)),
      'report_start_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'report_start_date',
          datetime.date(2019, 8, 20)
      ),
      'review_status': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'review_status',
          'review status'
      ),
      'review_status_display_name': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'review_status_display_name',
          'review status display name'
      ),
      'reviewers': lambda **kwargs: TestFullFilledModelExport._create_acl(
          'Reviewers',
          factories.ReviewFactory(reviewable=kwargs['obj']),
          kwargs['user'],
      ),
      'risk_type': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'risk_type',
          'risk_type'
      ),
      'secondary_contact': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'secondary_contact',
          kwargs['user']
      ),
      'send_by_default': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'send_by_default',
          True
      ),
      'slug': lambda **kwargs: set_attribute(kwargs['obj'], 'slug', 'slug'),
      'sox_302_enabled': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'sox_302_enabled',
          True
      ),
      'start_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'start_date',
          datetime.date(2019, 8, 20)
      ),
      'status': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'status',
          'In Progress'
      ),
      'task_group': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'task_group',
          'task_group'
      ),
      'task_type': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'task_type',
          'text'
      ),
      'template_custom_attributes': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'template_custom_attributes',
          'adsasd'
      ),
      'template_object_type': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'template_object_type',
          'Objective'
      ),
      'test_plan': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'test_plan',
          'test_plan'
      ),
      'test_plan_procedure': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'test_plan_procedure',
          True
      ),
      'threat_event': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'threat_event',
          'threat event'
      ),
      'threat_source': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'threat_source',
          'threat source'
      ),
      'title': lambda **kwargs: set_attribute(kwargs['obj'], 'title', 'title'),
      'unit': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'unit',
          all_models.Workflow.DAY_UNIT
      ),
      'updated_at': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'updated_at',
          datetime.date(2019, 8, 20)
      ),
      'user_role': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'user_role',
          'user_role'
      ),
      'verified_date': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'verified_date',
          datetime.date(2019, 9, 24)
      ),
      'verify_frequency': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'verify_frequency',
          'verify frequency'
      ),
      'vulnerability': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'vulnerability',
          'vulnerability'
      ),
      'workflow': lambda **kwargs: set_attribute(
          kwargs['obj'],
          'workflow',
          'workflow'
      ),
  }

  @staticmethod
  def _create_attributes(obj, attribute_template_id):
    """Create attribute for object"""
    attr = all_models.Attributes(
        object_id=obj.id,
        object_type=obj.__class__.__name__,
        value_datetime=datetime.datetime(2019, 9, 26),
        value_string="last comment",
        attribute_template_id=attribute_template_id,
        updated_at=datetime.datetime.now(),
        created_at=datetime.datetime.now(),
    )
    db.session.add(attr)
    db.session.commit()

  @staticmethod
  def _map_object(source, destination):
    """Create relationship with between two objects"""
    from ggrc.models import exceptions
    try:
      factories.RelationshipFactory(source=source, destination=destination)
    except exceptions.ValidationError:
      return

  def _map_snapshot(self, obj, destination):
    """Create relationship between object and his snapshot"""
    revision = self._get_latest_object_revisions([obj])[0]
    parent = destination
    if not isinstance(parent, all_models.Audit):
      parent = destination.audit
    snapshot = factories.SnapshotFactory(
        child_id=revision.resource_id,
        child_type=revision.resource_type,
        revision=revision,
        parent=parent,
        parent_id=parent.id,
    )
    factories.RelationshipFactory(source=snapshot, destination=destination)

  @staticmethod
  def _create_acl(role, obj, user):
    """Propagate acl for obj"""
    ac_role = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == role,
        all_models.AccessControlRole.object_type == obj.__class__.__name__,
    ).one()
    factories.AccessControlPersonFactory(
        ac_list=obj.acr_acl_map[ac_role],
        person=user,
    )

  @staticmethod
  def _set_field(alias, obj, user):
    """Set field for model"""
    kwargs = {'obj': obj, 'user': user}
    set_attr = TestFullFilledModelExport.FIELDS_FILLED_RULES[alias]
    set_attr(**kwargs)

  @staticmethod
  def _get_aliases(model):
    """Get aliases for provided model"""
    return [c for c in import_helper.get_object_column_definitions(model)]

  def assert_full_filled_model(self, data):
    """Assert that all columns are filled for export

    Args:
      data: list of rows from csv table

    Raises:
      AssertionError: if not all require columns are filled for model

    """
    errors = []
    # these columns only for import
    ignore = ['Delete', 'Comments',
              'Policy / Regulation / Standard / Contract',
              'Template', 'Custom Attributes']
    rows = csv.reader(StringIO(data))
    rows = [r for r in rows][:3]

    for top, column_name, field_value in zip(*rows):
      if column_name.startswith('unmap:') or column_name in ignore:
        continue
      elif top == 'Object type':
        title = column_name
        continue
      if field_value == '':
        errors.append(column_name)

    self.assertEqual(errors, [],
                     'These columns for {0} are not exported: {1}'.format(
                     title, ', '.join(errors)))

  def build_object(self, model):
    """Fill all fields in model"""
    errors = []
    obj = factories.get_model_factory(model.__name__)()
    aliases = sorted(self._get_aliases(model))

    for alias in aliases:
      if alias.startswith('__mapping__'):
        title = alias.split(':')[1]
        mapped_model = ''.join([part.title() for part in title.split()])
        destination_obj = factories.get_model_factory(mapped_model)()

        self._map_object(source=obj, destination=destination_obj)
      elif alias.startswith('__snapshot_mapping__'):
        title = alias.split(':')[1]
        mapped_model = ''.join([part.title() for part in title.split()])
        destination_obj = factories.get_model_factory(mapped_model)()

        self._map_snapshot(destination_obj, obj)
      elif alias.startswith('__acl__'):
        role = alias.split(':')[1]
        self._create_acl(role, obj, self.user)
      elif not alias.startswith('__'):
        try:
          self._set_field(alias, obj, self.user)
        except KeyError:
          errors.append(alias)
      else:
        continue

    db.session.commit()

    self.assertEqual(errors, [],
                     'These columns are not filled for model: {}. '
                     'Need to add rule for these into '
                     'FIELDS_FILLED_RULES'.format(
                     ', '.join(errors)))
    return obj

  def setUp(self):
    super(TestFullFilledModelExport, self).setUp()
    self.api = api_helper.Api()
    self.client.get('/login')

    self.user = all_models.Person.query.filter(
        all_models.Person.email == "*****@*****.**"
    ).one()

  @ddt.data(
      *get_exportables()
  )
  def test_full_filled_model_export(self, model):
    """Test export of {0.__name__} with all filled columns

    We defined dict with fillable fields from all models.
    So since we get some new column in model we need define it in `attrs_dict`

    Raises:
      AssertionError: 1. Raised when column isn't present in `attrs_dict`.
        So we need to add rules for this column to dict.

        2. Raised when some columns are missed for export. So we need fix rules
        for columns in `attrs_dict`.
    """
    model_name = model.__name__
    obj = self.build_object(model)

    data = [{
        "object_name": model_name,
        "filters": {
            "expression": {
                'left': 'id',
                'op': {'name': '='},
                'right': obj.id,
            }
        },
        "fields": "all",
    }]
    response = self.export_csv(data)
    response_data = response.data

    self.assert_full_filled_model(response_data)
    self.assert200(response)