コード例 #1
0
class TestReader(TestCase):
  """Test that some objects cannot be deleted by anyone."""

  def setUp(self):
    super(TestReader, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_objects()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("creator", "Creator"), ("reader", "Reader"),
             ("editor", "Editor"), ("admin", "Administrator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def init_objects(self):
    """Creates the objects used by all the tests"""
    self.api.set_user(self.users["admin"])
    _, person = self.object_generator.generate_person()

    self.objects = [person]

  def test_undeletable_objects(self):
    """No user shoud be allowed to delete these objects."""
    for role, user in self.users.iteritems():
      self.api.set_user(user)
      for obj in self.objects:
        response = self.api.delete(obj)
        self.assertEqual(response.status_code, 403,
                         "{} can delete {}".format(role, obj.type))
コード例 #2
0
class TestReader(TestCase):
    """Test that some objects cannot be deleted by anyone."""
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_objects()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("creator", "Creator"), ("reader", "Reader"),
                 ("editor", "Editor"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def init_objects(self):
        """Creates the objects used by all the tests"""
        self.api.set_user(self.users["admin"])
        _, person = self.object_generator.generate_person()

        self.objects = [person]

    def test_undeletable_objects(self):
        """No user shoud be allowed to delete these objects."""
        for role, user in self.users.iteritems():
            self.api.set_user(user)
            for obj in self.objects:
                response = self.api.delete(obj)
                self.assertEqual(response.status_code, 403,
                                 "{} can delete {}".format(role, obj.type))
コード例 #3
0
ファイル: test_common.py プロジェクト: egorhm/ggrc-core
class TestFilteringByRequest(TestCase):
  """Test filter query by request"""

  def setUp(self):
    super(TestFilteringByRequest, self).setUp()
    self.object_generator = ObjectGenerator()
    self.api = Api()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = (
        ("creator", "Creator"),
        ("admin", "Administrator"),
        ("john", None),
    )
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def test_no_role_users_filtering(self):
    """Test 'No Role' users filtering"""
    self.api.set_user(self.users['admin'])
    response = self.api.get_query(all_models.Person, "__no_role=true")

    self.assertEqual(response.status_code, 200)
    self.assertEqual(len(response.json['people_collection']['people']), 1)
    self.assertEqual(
        response.json['people_collection']['people'][0]['name'],
        'john'
    )
コード例 #4
0
class TestFilteringByRequest(TestCase):
    """Test filter query by request"""
    def setUp(self):
        super(TestFilteringByRequest, self).setUp()
        self.object_generator = ObjectGenerator()
        self.api = Api()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """
        users = (
            ("creator", "Creator"),
            ("admin", "Administrator"),
            ("john", None),
        )
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_no_role_users_filtering(self):
        """Test 'No Role' users filtering"""
        self.api.set_user(self.users['admin'])
        response = self.api.get_query(all_models.Person, "__no_role=true")

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.json['people_collection']['people']), 1)
        self.assertEqual(
            response.json['people_collection']['people'][0]['name'], 'john')
コード例 #5
0
ファイル: test_ac_rbac.py プロジェクト: xuechaos/ggrc-core
    def set_up_people(self):
        """Set up people with different roles needed by the tests"""
        self.people = {}
        object_generator = ObjectGenerator()

        for name in ["Creator", "Reader", "Editor"]:
            _, user = object_generator.generate_person(data={"name": name},
                                                       user_role=name)
            self.people[name] = user
コード例 #6
0
  def set_up_people(self):
    """Set up people with different roles needed by the tests"""
    self.people = {}
    object_generator = ObjectGenerator()

    for name in ["Creator", "Reader", "Editor"]:
      _, user = object_generator.generate_person(
          data={"name": name}, user_role=name)
      self.people[name] = user
コード例 #7
0
class TestPersonProfilePermissions(TestCase):
    """Test PersonProfile."""
    def setUp(self):
        super(TestPersonProfilePermissions, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """Init user with different roles."""
        users = [("reader", "Reader"), ("editor", "Editor"),
                 ("admin", "Administrator"), ("creator", "Creator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    @ddt.data("reader", "editor", "admin", "creator")
    def test_permissions(self, name):
        """Test permissions for user roles."""
        user = all_models.Person.query.get(self.users[name].id)
        profile_id = user.profile.id
        self.api.set_user(self.users[name])
        response = self.api.get(all_models.PersonProfile, profile_id)
        self.assert200(response)

        new_date = "2018-05-20 22:05:17"
        response = self.api.put(
            user.profile, {
                "people_profiles": {
                    "id": profile_id,
                    "last_seen_whats_new": new_date,
                },
            })
        self.assert200(response)

        response = self.api.delete(user.profile, profile_id)
        if name == "admin":
            self.assert200(response)
        else:
            self.assert403(response)

        res = self.api.get(all_models.PersonProfile, None)
        api_profiles = res.json["people_profiles_collection"][
            "people_profiles"]
        api_profile_id = api_profiles[0]["id"]

        if name == "admin":
            self.assertEqual(len(api_profiles), 4)
        else:
            self.assertEqual(len(api_profiles), 1)
            self.assertEqual(profile_id, api_profile_id)
コード例 #8
0
class TestAccessControlRole(TestCase):
    """TestAccessControlRole"""
    def setUp(self):
        super(TestAccessControlRole, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.people = {}
        for name in ["Creator", "Reader", "Editor"]:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=name)
            self.people[name] = user

    def _post_role(self):
        """Helper function for POSTing roles"""
        name = random_str(prefix="Access Control Role - ")
        return self.api.post(
            AccessControlRole, {
                "access_control_role": {
                    "name": name,
                    "object_type": "Control",
                    "context": None,
                    "read": True
                },
            })

    def test_create(self):
        """Test Access Control Role creation"""
        response = self._post_role()
        assert response.status_code == 201, \
            "Failed to create a new access control role, response was {}".format(
                response.status)

        id_ = response.json['access_control_role']['id']
        role = AccessControlRole.query.filter(
            AccessControlRole.id == id_).first()
        assert role.read == 1, \
            "Read permission not correctly saved {}".format(role.read)
        assert role.update == 1, \
            "Update permission not correctly saved {}".format(role.update)
        assert role.delete == 1, \
            "Update permission not correctly saved {}".format(role.delete)

    def test_only_admin_can_post(self):
        """Only admin users should be able to POST access control roles"""
        for name in ("Creator", "Reader", "Editor"):
            person = self.people.get(name)
            self.api.set_user(person)
            response = self._post_role()
            assert response.status_code == 403, \
                "Non admins should get forbidden error when POSTing role. {}".format(
                    response.status)
コード例 #9
0
class TestPersonProfilePermissions(TestCase):
  """Test PersonProfile."""

  def setUp(self):
    super(TestPersonProfilePermissions, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """Init user with different roles."""
    users = [("reader", "Reader"),
             ("editor", "Editor"),
             ("admin", "Administrator"),
             ("creator", "Creator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name},
          user_role=role
      )
      self.users[name] = user

  @ddt.data("reader", "editor", "admin", "creator")
  def test_permissions(self, name):
    """Test permissions for user roles."""
    user = all_models.Person.query.get(self.users[name].id)
    profile = all_models.PersonProfile.query.join(
        all_models.PersonProfile.person
    ).filter_by(
        email=user.email
    ).one()
    self.api.set_user(self.users[name])
    response = self.api.get(all_models.PersonProfile, profile.id)
    self.assert200(response)

    new_date = "2018-05-20 22:05:17"
    response = self.api.put(profile, {
        "people_profiles": {
            "id": profile.id,
            "last_seen_whats_new": new_date,
        },
    })
    self.assert200(response)

    response = self.api.delete(profile)
    if name == "admin":
      self.assert200(response)
    else:
      self.assert403(response)
コード例 #10
0
ファイル: test_audit_rbac.py プロジェクト: zidarsk8/ggrc-core
class TestPermissionsOnAssessmentRelatedAssignables(TestCase):
  """Test check Reader permissions for Assessment related assignables

  Global Reader once assigned to Assessment as Assessor, should have
  permissions to read/update/delete URLs(Documents) related to this Assessment
  """
  def setUp(self):
    super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()

    _, self.reader = self.generator.generate_person(
        user_role="Reader"
    )
    audit = factories.AuditFactory()
    assessment = factories.AssessmentFactory(audit=audit)
    object_person_rel = factories.RelationshipFactory(
        source=assessment,
        destination=self.reader
    )
    factories.RelationshipAttrFactory(
        relationship_id=object_person_rel.id,
        attr_name="AssigneeType",
        attr_value="Assessor"
    )

    factories.RelationshipFactory(source=audit, destination=assessment)
    document = factories.DocumentFactory()
    document_id = document.id
    doc_rel = factories.RelationshipFactory(source=assessment,
                                            destination=document)
    doc_rel_id = doc_rel.id

    self.api.set_user(self.reader)
    self.document = all_models.Document.query.get(document_id)
    self.doc_relationship = all_models.Relationship.query.get(doc_rel_id)

  def test_delete_action(self):
    """Test permissions for delete action on Document"""
    resp = self.api.delete(self.document)
    self.assert200(resp)
    self.assertFalse(all_models.Document.query.filter(
        all_models.Document.id == self.document.id).all())

  def test_unmap_action(self):
    """Test permissions for unmap action on Document"""
    resp = self.api.delete(self.doc_relationship)
    self.assert200(resp)
    self.assertFalse(all_models.Relationship.query.filter(
        all_models.Relationship.id == self.doc_relationship.id).all())
コード例 #11
0
class TestAccessControlRole(TestCase):
  """TestAccessControlRole"""

  def setUp(self):
    super(TestAccessControlRole, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.people = {}
    for name in ["Creator", "Reader", "Editor"]:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=name)
      self.people[name] = user

  def _post_role(self):
    """Helper function for POSTing roles"""
    name = random_str(prefix="Access Control Role - ")
    return self.api.post(AccessControlRole, {
        "access_control_role": {
            "name": name,
            "object_type": "Control",
            "context": None,
            "read": True
        },
    })

  def test_create(self):
    """Test Access Control Role creation"""
    response = self._post_role()
    assert response.status_code == 201, \
        "Failed to create a new access control role, response was {}".format(
            response.status)

    id_ = response.json['access_control_role']['id']
    role = AccessControlRole.query.filter(AccessControlRole.id == id_).first()
    assert role.read == 1, \
        "Read permission not correctly saved {}".format(role.read)
    assert role.update == 1, \
        "Update permission not correctly saved {}".format(role.update)
    assert role.delete == 1, \
        "Update permission not correctly saved {}".format(role.delete)

  def test_only_admin_can_post(self):
    """Only admin users should be able to POST access control roles"""
    for name in ("Creator", "Reader", "Editor"):
      person = self.people.get(name)
      self.api.set_user(person)
      response = self._post_role()
      assert response.status_code == 403, \
          "Non admins should get forbidden error when POSTing role. {}".format(
              response.status)
コード例 #12
0
ファイル: test_common.py プロジェクト: Smotko/ggrc-core
class TestFilteringByRequest(TestCase):
  """Test filter query by request"""

  def setUp(self):
    super(TestFilteringByRequest, self).setUp()
    self.object_generator = ObjectGenerator()
    self.api = Api()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = (
        ("creator", "Creator"),
        ("admin", "Administrator"),
        ("john", "WorkflowOwner")
    )
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user
    context = (
        db.session.query(all_models.Context).filter(
            all_models.Context.id != 0
        ).first()
    )
    user_role = (
        db.session.query(all_models.UserRole).join(all_models.Person).
        filter(
            and_(
                all_models.UserRole.person_id == all_models.Person.id,
                all_models.Person.name == "john"
            )
        ).first()
    )
    user_role.context_id = context.id
    db.session.commit()
    db.session.flush()

  def test_no_role_users_filtering(self):
    """Test 'No Role' users filtering"""
    self.api.set_user(self.users['admin'])
    response = self.api.get_query(all_models.Person, "__no_role=true")

    self.assertEqual(response.status_code, 200)
    self.assertEqual(len(response.json['people_collection']['people']), 1)
    self.assertEqual(
        response.json['people_collection']['people'][0]['name'],
        'john'
    )
コード例 #13
0
ファイル: test_common.py プロジェクト: sskhatri/ggrc-core
class TestFilteringByRequest(TestCase):
  """Test filter query by request"""

  def setUp(self):
    super(TestFilteringByRequest, self).setUp()
    self.object_generator = ObjectGenerator()
    self.api = Api()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = (
        ("creator", "Creator"),
        ("admin", "Administrator"),
        ("john", "WorkflowOwner")
    )
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user
    context = (
        db.session.query(all_models.Context).filter(
            all_models.Context.id != 0
        ).first()
    )
    user_role = (
        db.session.query(all_models.UserRole).join(all_models.Person).
        filter(
            and_(
                all_models.UserRole.person_id == all_models.Person.id,
                all_models.Person.name == "john"
            )
        ).first()
    )
    user_role.context_id = context.id
    db.session.commit()
    db.session.flush()

  def test_no_role_users_filtering(self):
    """Test 'No Role' users filtering"""
    self.api.set_user(self.users['admin'])
    response = self.api.get_query(all_models.Person, "__no_role=true")

    self.assertEqual(response.status_code, 200)
    self.assertEqual(len(response.json['people_collection']['people']), 1)
    self.assertEqual(
        response.json['people_collection']['people'][0]['name'],
        'john'
    )
コード例 #14
0
  def test_import_evidence_mapped(self, status):
    """Test notifications for '{}' Assessment if Evidence mapped in import."""
    object_generator = ObjectGenerator()
    _, user = object_generator.generate_person(user_role="Creator")
    assessment = factories.AssessmentFactory()
    assessment.add_person_with_role_name(user, "Verifiers")
    assessment.status = status
    db.session.commit()

    response = self.import_data(collections.OrderedDict([
        ("object_type", "Assessment"),
        ("Code*", assessment.slug),
        ("Evidence URL", "some url"),
    ]))
    self._check_csv_response(response, {})
    self.assert_asmnt_notifications()
コード例 #15
0
class TestPermissions(TestCase):
    """Test permissions for background tasks"""
    def setUp(self):
        super(TestPermissions, self).setUp()
        self.generator = Generator()
        self.api = api_helper.Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("reader", "Reader"), ("admin", "Administrator"),
                 ("creator", "Creator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_bg_tasks_access(self):
        """Only admin can use admin requirement"""
        from ggrc.models import all_models

        control_dict = {
            "control": {
                "title": "Control title",
                "context": None,
            },
        }
        response = self.api.send_request(
            self.api.client.post,
            all_models.Control,
            control_dict,
            {"X-GGRC-BackgroundTask": "true"},
        )
        self.assertEqual(response.status_code, 201)

        for role in ("reader", "creator", "admin"):
            self.api.set_user(self.users[role])
            content = self.api.client.get("/api/background_tasks")
            self.assert200(content)
            bg_tasks_content = \
                content.json['background_tasks_collection']['background_tasks']
            for bg_task_content in bg_tasks_content:
                self.assertEqual(set(bg_task_content.keys()),
                                 {"id", "selfLink", "status", "type"})
            self.assertTrue(len(bg_tasks_content) >= 1)
コード例 #16
0
class TestPermissionsOnAssessmentRelatedAssignables(TestCase):
    """Test check Reader permissions for Assessment related assignables

  Global Reader once assigned to Assessment as Assessor, should have
  permissions to read/update/delete URLs(Documents) related to this Assessment
  """
    def setUp(self):
        super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp()
        self.api = Api()
        self.generator = ObjectGenerator()

        _, self.reader = self.generator.generate_person(user_role="Reader")
        audit = factories.AuditFactory()
        assessment = factories.AssessmentFactory(audit=audit)
        object_person_rel = factories.RelationshipFactory(
            source=assessment, destination=self.reader)
        factories.RelationshipAttrFactory(relationship_id=object_person_rel.id,
                                          attr_name="AssigneeType",
                                          attr_value="Assessor")

        factories.RelationshipFactory(source=audit, destination=assessment)
        document = factories.DocumentFactory()
        document_id = document.id
        doc_rel = factories.RelationshipFactory(source=assessment,
                                                destination=document)
        doc_rel_id = doc_rel.id

        self.api.set_user(self.reader)
        self.document = all_models.Document.query.get(document_id)
        self.doc_relationship = all_models.Relationship.query.get(doc_rel_id)

    def test_delete_action(self):
        """Test permissions for delete action on Document"""
        resp = self.api.delete(self.document)
        self.assert200(resp)
        self.assertFalse(
            all_models.Document.query.filter(
                all_models.Document.id == self.document.id).all())

    def test_unmap_action(self):
        """Test permissions for unmap action on Document"""
        resp = self.api.delete(self.doc_relationship)
        self.assert200(resp)
        self.assertFalse(
            all_models.Relationship.query.filter(
                all_models.Relationship.id == self.doc_relationship.id).all())
コード例 #17
0
ファイル: test_audit_rbac.py プロジェクト: egorhm/ggrc-core
class TestPermissionsOnAssessmentRelatedAssignables(TestCase):
  """Test check Reader permissions for Assessment related assignables

  Global Reader once assigned to Assessment as Assignee, should have
  permissions to read/update/delete URLs(Documents) related to this Assessment
  """

  def setUp(self):
    super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()

    _, self.reader = self.generator.generate_person(
        user_role="Reader"
    )
    audit = factories.AuditFactory()
    assessment = factories.AssessmentFactory(audit=audit)
    ac_role = all_models.AccessControlRole.query.filter_by(
        object_type=assessment.type, name="Assignees"
    ).first()
    factories.AccessControlListFactory(
        ac_role=ac_role,
        object=assessment,
        person=self.reader
    )
    factories.RelationshipFactory(source=audit, destination=assessment)
    evidence = factories.EvidenceUrlFactory()
    evidence_id = evidence.id
    evid_rel = factories.RelationshipFactory(source=assessment,
                                             destination=evidence)
    evid_rel_id = evid_rel.id

    self.api.set_user(self.reader)
    self.evidence = all_models.Evidence.query.get(evidence_id)
    self.evid_relationship = all_models.Relationship.query.get(evid_rel_id)

  def test_delete_action(self):
    """Test permissions for delete action on Evidence

    Allow only Global Admin to delete Documents.
    """
    resp = self.api.delete(self.evidence)
    self.assert403(resp)
    self.assertEquals(len(all_models.Evidence.query.filter(
        all_models.Evidence.id == self.evidence.id).all()), 1)
コード例 #18
0
    def test_add_comment(self):
        """Test add comment action."""
        generator = ObjectGenerator()

        _, reader = generator.generate_person(user_role="Administrator")
        self.api.set_user(reader)

        assessment = factories.AssessmentFactory()
        context = factories.ContextFactory(related_object=assessment)
        assessment.context = context

        acrs = all_models.AccessControlRole.query.filter(
            all_models.AccessControlRole.object_type == "Assessment",
            all_models.AccessControlRole.name.in_(["Assignees", "Creators"]),
        )

        for acr in acrs:
            factories.AccessControlListFactory(ac_role=acr,
                                               object=assessment,
                                               person=reader)

        response = self.api.put(
            assessment, {
                "actions": {
                    "add_related": [{
                        "id": None,
                        "type": "Comment",
                        "description": "comment",
                        "custom_attribute_definition_id": None,
                    }]
                }
            })
        self.assert200(response)
        # last relationship id (newly created relationship)
        rel_id = max(
            i["id"]
            for i in response.json["assessment"]["related_destinations"])
        relationship = all_models.Relationship.query.get(rel_id)
        self.assertIsNotNone(relationship)
        comment = all_models.Comment.query.get(relationship.destination_id)
        self.assertEqual(comment.description, "comment")
        self.assertEqual(comment.assignee_type, "Assignees,Creators")
        self.assertEqual(comment.context_id, assessment.context_id)
コード例 #19
0
  def test_import_snapshot_mapped(self, status):
    """Test notifications for '{}' Assessment if snapshot mapped in import."""
    object_generator = ObjectGenerator()
    _, user = object_generator.generate_person(user_role="Creator")
    with factories.single_commit():
      assessment = factories.AssessmentFactory()
      control = factories.ControlFactory()
    # pylint: disable=expression-not-assigned
    self._create_snapshots(assessment.audit, [control])[0]
    assessment.add_person_with_role_name(user, "Verifiers")
    assessment.status = status
    db.session.commit()

    response = self.import_data(collections.OrderedDict([
        ("object_type", "Assessment"),
        ("Code*", assessment.slug),
        ("Map:control versions", control.slug),
    ]))
    self._check_csv_response(response, {})
    self.assert_asmnt_notifications()
コード例 #20
0
class TestPermissionsOnAssessmentRelatedAssignables(TestCase):
  """Test check Reader permissions for Assessment related assignables

  Global Reader once assigned to Assessment as Assignee, should have
  permissions to read/update/delete URLs(Documents) related to this Assessment
  """

  def setUp(self):
    super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()

    _, self.reader = self.generator.generate_person(
        user_role="Reader"
    )
    audit = factories.AuditFactory()
    assessment = factories.AssessmentFactory(audit=audit)
    factories.AccessControlPersonFactory(
        ac_list=assessment.acr_name_acl_map["Assignees"],
        person=self.reader,
    )
    factories.RelationshipFactory(source=audit, destination=assessment)
    evidence = factories.EvidenceUrlFactory()
    evidence_id = evidence.id
    evid_rel = factories.RelationshipFactory(source=assessment,
                                             destination=evidence)
    evid_rel_id = evid_rel.id

    self.api.set_user(self.reader)
    self.evidence = all_models.Evidence.query.get(evidence_id)
    self.evid_relationship = all_models.Relationship.query.get(evid_rel_id)

  def test_delete_action(self):
    """Test permissions for delete action on Evidence

    Allow only Global Admin to delete Documents.
    """
    resp = self.api.delete(self.evidence)
    self.assert200(resp)
    self.assertEquals(len(all_models.Evidence.query.filter(
        all_models.Evidence.id == self.evidence.id).all()), 0)
コード例 #21
0
ファイル: test_with_action.py プロジェクト: egorhm/ggrc-core
  def test_add_comment(self):
    """Test add comment action."""
    generator = ObjectGenerator()

    _, reader = generator.generate_person(user_role="Administrator")
    self.api.set_user(reader)

    assessment = factories.AssessmentFactory()
    context = factories.ContextFactory(related_object=assessment)
    assessment.context = context

    acrs = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.object_type == "Assessment",
        all_models.AccessControlRole.name.in_(["Assignees", "Creators"]),
    )

    for acr in acrs:
      factories.AccessControlListFactory(
          ac_role=acr,
          object=assessment,
          person=reader
      )

    response = self.api.put(assessment, {"actions": {"add_related": [
        {
            "id": None,
            "type": "Comment",
            "description": "comment",
            "custom_attribute_definition_id": None,
        }
    ]}})
    self.assert200(response)
    # last relationship id (newly created relationship)
    relationship = _get_relationship(
        "Assessment", response.json["assessment"]["id"])
    self.assertIsNotNone(relationship)
    comment = all_models.Comment.query.get(relationship.destination_id)
    self.assertEqual(comment.description, "comment")
    self.assertEqual(comment.assignee_type, "Assignees,Creators")
    self.assertEqual(comment.context_id, assessment.context_id)
コード例 #22
0
    def test_add_comment(self):
        """Test add comment action."""
        generator = ObjectGenerator()

        _, reader = generator.generate_person(user_role="Reader")
        self.api.set_user(reader)

        assessment = factories.AssessmentFactory()
        context = factories.ContextFactory(related_object=assessment)
        assessment.context = context

        object_person_rel = factories.RelationshipFactory(source=assessment,
                                                          destination=reader)
        factories.RelationshipAttrFactory(relationship_id=object_person_rel.id,
                                          attr_name="AssigneeType",
                                          attr_value="Creator,Assessor")

        response = self.api.put(
            assessment, {
                "actions": {
                    "add_related": [{
                        "id": None,
                        "type": "Comment",
                        "description": "comment",
                        "custom_attribute_definition_id": None,
                    }]
                }
            })
        self.assert200(response)
        # last relationship id (newly created relationship)
        rel_id = max(
            i["id"]
            for i in response.json["assessment"]["related_destinations"])
        relationship = all_models.Relationship.query.get(rel_id)
        self.assertIsNotNone(relationship)
        comment = all_models.Comment.query.get(relationship.destination_id)
        self.assertEqual(comment.description, "comment")
        self.assertEqual(comment.assignee_type, "Creator,Assessor")
        self.assertEqual(comment.context_id, assessment.context_id)
コード例 #23
0
ファイル: test_with_action.py プロジェクト: Smotko/ggrc-core
  def test_add_comment(self):
    """Test add comment action."""
    generator = ObjectGenerator()

    _, reader = generator.generate_person(user_role="Reader")
    self.api.set_user(reader)

    assessment = factories.AssessmentFactory()
    context = factories.ContextFactory(related_object=assessment)
    assessment.context = context

    object_person_rel = factories.RelationshipFactory(
        source=assessment,
        destination=reader
    )
    factories.RelationshipAttrFactory(
        relationship_id=object_person_rel.id,
        attr_name="AssigneeType",
        attr_value="Creator,Assessor"
    )

    response = self.api.put(assessment, {"actions": {"add_related": [
        {
            "id": None,
            "type": "Comment",
            "description": "comment",
            "custom_attribute_definition_id": None,
        }
    ]}})
    self.assert200(response)
    # last relationship id (newly created relationship)
    rel_id = max(i["id"] for i in
                 response.json["assessment"]["related_destinations"])
    relationship = all_models.Relationship.query.get(rel_id)
    self.assertIsNotNone(relationship)
    comment = all_models.Comment.query.get(relationship.destination_id)
    self.assertEqual(comment.description, "comment")
    self.assertEqual(comment.assignee_type, "Creator,Assessor")
    self.assertEqual(comment.context_id, assessment.context_id)
コード例 #24
0
class TestPermissions(TestCase):
  """Test permissions for background tasks"""

  def setUp(self):
    super(TestPermissions, self).setUp()
    self.api = api_helper.Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("reader", "Reader"),
             ("admin", "Administrator"),
             ("creator", "Creator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def test_bg_tasks_access(self):
    """Only admin can use admin requirement"""
    from ggrc.models import all_models

    with self.object_generator.api.as_external():
      response, _ = self.object_generator.generate_object(
          all_models.Control, with_background_tasks=True)
    self.assertEqual(response.status_code, 201)

    for role in ("reader", "creator", "admin"):
      self.api.set_user(self.users[role])
      content = self.api.client.get("/api/background_tasks")
      self.assert200(content)
      bg_tasks_content = \
          content.json['background_tasks_collection']['background_tasks']
      for bg_task_content in bg_tasks_content:
        self.assertEqual(set(bg_task_content.keys()),
                         {"id", "selfLink", "status", "type"})
      self.assertTrue(len(bg_tasks_content) >= 1)
コード例 #25
0
  def test_import_lcad_changed(self, status):
    """Test notifications for '{}' Assessment if LCAD changed in import."""
    object_generator = ObjectGenerator()
    _, user = object_generator.generate_person(user_role="Creator")
    with factories.single_commit():
      assessment = factories.AssessmentFactory()
      factories.CustomAttributeDefinitionFactory(
          title="Test LCAD",
          definition_type="assessment",
          definition_id=assessment.id,
          attribute_type="Text",
      )
    assessment.add_person_with_role_name(user, "Verifiers")
    assessment.status = status
    db.session.commit()

    response = self.import_data(collections.OrderedDict([
        ("object_type", "Assessment"),
        ("Code*", assessment.slug),
        ("Test LCAD", "some value"),
    ]))
    self._check_csv_response(response, {})
    self.assert_asmnt_notifications()
コード例 #26
0
class TestCreatorAudit(TestCase):
  """Set up necessary objects and test Creator role with Audit roles"""

  def setUp(self):
    super(TestCreatorAudit, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_roles()
    self.init_test_cases()
    self.objects = {}

  def init_test_cases(self):
    """Create a dict of all possible test cases."""
    self.test_cases = {
        "Auditor": {
            "audit_role": "Auditor",
            "objects": {
                "audit": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "mapped_Issue": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated_Issue": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                },
                "mapped_Assessment": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated_Assessment": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
    }

  def init_roles(self):
    """Create a delete request for the given object."""
    response = self.api.get_query(all_models.Role, "")
    self.roles = {}
    for role in response.json.get("roles_collection").get("roles"):
      self.roles[role.get("name")] = role

  def init_users(self):
    """Create users used by test cases."""
    self.people = {}
    for name in ["creator", "notmapped", "mapped", "Auditor"]:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role="Creator")
      self.people[name] = user

    _, user = self.object_generator.generate_person(
        data={"name": "editor"}, user_role="Editor")
    self.people["editor"] = user

  def delete(self, obj):
    """Create a delete request for the given object.

    Args:
        obj (model instance): target object to delete
    Returns:
        int: http response status code
    """
    return self.api.delete(obj).status_code

  def get(self, obj):
    """Create a get request for the given object.

    Args:
        obj (model instance): target object to get
    Returns:
        int: http response status code
    """
    return self.api.get(obj.__class__, obj.id).status_code

  def put(self, obj):
    """Create a put request for the given object.

    Args:
        obj (model instance): target object to put
    Returns:
        int: http response status code
    """
    response = self.api.get(obj.__class__, obj.id)
    if response.status_code == 200:
      return self.api.put(obj, response.json).status_code
    else:
      return response.status_code

  def map(self, dest):
    """Map audit to dest.

    Args:
        dest (model instance): target object to map to the audit
    Returns:
        int: http response status code
    """
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.objects["audit"].id,
            "type": self.objects["audit"].type,
        }, "destination": {
            "id": dest.id,
            "type": dest.type
        }, "context": None},
    })
    return response.status_code

  def init_objects(self, test_case_name):
    """Create a Program, an Audit, and a Mapped object for the test case.

    Args:
        test_case_name (string): test case to init for
    """
    # Create a program
    dummy_audit = factories.AuditFactory()
    unrelated_audit = {
        "type": "Audit",
        "context_id": dummy_audit.context.id,
        "id": dummy_audit.id,
    }
    test_case = self.test_cases[test_case_name]
    editor = self.people.get('editor')
    self.api.set_user(editor)
    random_title = factories.random_str()
    response = self.api.post(all_models.Program, {
        "program": {"title": random_title, "context": None},
    })
    self.assertEqual(response.status_code, 201)
    program_id = response.json.get("program").get("id")
    self.objects["program"] = all_models.Program.query.get(program_id)
    response = self.api.post(all_models.Audit, {
        "audit": {
            "title": random_title + " audit",
            'program': {'id': program_id},
            "status": "Planned",
            "context": None
        }
    })
    self.assertEqual(response.status_code, 201)
    context = response.json.get("audit").get("context")
    audit_id = response.json.get("audit").get("id")
    self.objects["audit"] = all_models.Audit.query.get(audit_id)
    audits = {
        "mapped": {
            "type": "Audit",
            "context_id": context["id"],
            "id": audit_id,
        },
        "unrelated": unrelated_audit,
    }

    for prefix, audit_dict in audits.items():
      random_title = factories.random_str()

      response = self.api.post(all_models.Issue, {
          "issue": {
              "title": random_title,
              "context": {
                  "type": "Context",
                  "id": audit_dict["context_id"],
              },
              "audit": audit_dict,
          },
      })
      self.assertEqual(response.status_code, 201)
      issue_id = response.json.get("issue").get("id")
      self.objects[prefix + "_Issue"] = all_models.Issue.query.get(issue_id)

      response = self.api.post(all_models.Assessment, {
          "assessment": {
              "title": random_title,
              "context": {
                  "type": "Context",
                  "id": audit_dict["context_id"],
              },
              "audit": audit_dict,
          },
      })
      self.assertEqual(response.status_code, 201)
      assessment_id = response.json.get("assessment").get("id")
      self.objects[prefix + "_Assessment"] = \
          all_models.Assessment.query.get(assessment_id)

    self.assertEqual(self.map(self.objects["mapped_Issue"]), 201)
    self.assertEqual(self.map(self.objects["mapped_Assessment"]), 201)

    # Add roles to mapped users:
    if "audit_role" in test_case:
      person = self.people.get(test_case_name)
      role = self.roles[test_case["audit_role"]]
      response = self.api.post(all_models.UserRole, {"user_role": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "role": {
              "type": "Role",
              "href": "/api/roles/{}".format(role["id"]),
              "id": role["id"],
          }, "context": {
              "type": "Context",
              "id": context.get("id"),
              "href": "/api/contexts/{}".format(context.get("id"))
          }}})
      self.assertEqual(response.status_code, 201)

  def test_creator_audit_roles(self):
    """ Test creator role with all audit scoped roles """
    # Check permissions based on test_cases:
    errors = []
    for test_case in self.test_cases:
      self.init_objects(test_case)
      person = self.people.get(test_case)
      objects = self.test_cases.get(test_case).get('objects')
      self.api.set_user(person)
      for obj, actions in objects.iteritems():
        for action in ("map", "get", "put", "delete"):
          if action not in actions:
            continue
          # reset sesion:
          db.session.commit()
          func = getattr(self, action)
          res = func(self.objects[obj])
          if res != actions[action]:
            errors.append(
                "{}: Tried {} on {}, but received {} instead of {}".format(
                    test_case, action, obj, res, actions[action]))

    self.assertEqual(errors, [])
コード例 #27
0
ファイル: test_creator.py プロジェクト: zidarsk8/ggrc-core
class TestCreator(TestCase):
  """ TestCreator """

  def setUp(self):
    super(TestCreator, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """

    users = [("creator", "Creator"), ("admin", "Administrator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def test_admin_page_access(self):
    for role, code in (("creator", 403), ("admin", 200)):
      self.api.set_user(self.users[role])
      self.assertEqual(self.api.client.get("/admin").status_code, code)

  def test_creator_can_crud(self):
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["creator"])
    audit_id = factories.AuditFactory().id
    all_errors = []
    base_models = set([
        "Control", "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "Clause", "System", "Process", "Project", "AccessGroup"
    ])
    for model_singular in base_models:
      try:
        model = get_model(model_singular)
        table_singular = model._inflector.table_singular
        table_plural = model._inflector.table_plural
        # Test POST creation
        response = self.api.post(model, {
            table_singular: {
                "title": model_singular,
                "context": None,
                "reference_url": "ref",
                "contact": {
                    "type": "Person",
                    "id": self.users["creator"].id,
                },
                "audit": {  # this is ignored on everything but Issues
                    "id": audit_id,
                    "type": "Audit",
                }
            },
        })
        if response.status_code != 201:
          all_errors.append("{} post creation failed {} {}".format(
              model_singular, response.status, response.data))
          continue

        # Test GET when not owner
        obj_id = response.json.get(table_singular).get("id")
        response = self.api.get(model, obj_id)
        if response.status_code != 403:  # we are not onwers yet
          all_errors.append(
              "{} can retrieve object if not owner".format(model_singular))
          continue
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if len(collection) != 0:
          all_errors.append(
              "{} can retrieve object if not owner (collection)"
              .format(model_singular))
          continue
        # Become an owner
        response = self.api.post(all_models.ObjectOwner, {"object_owner": {
            "person": {
                "id": self.users['creator'].id,
                "type": "Person",
            }, "ownable": {
                "type": model_singular,
                "id": obj_id
            }, "context": None}})
        if response.status_code != 201:
          all_errors.append("{} can't create owner {}.".format(
              model_singular, response.status))
          continue

        # Test GET when owner
        response = self.api.get(model, obj_id)
        if response.status_code != 200:
          all_errors.append("{} can't GET object {}".format(
              model_singular, response.status))
          continue

        # Test GET collection when owner
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if len(collection) == 0:
          all_errors.append(
              "{} cannot retrieve object even if owner (collection)"
              .format(model_singular))
          continue
      except:
        all_errors.append("{} exception thrown".format(model_singular))
        raise
    self.assertEqual(all_errors, [])

  def test_creator_search(self):
    """Test if creator can see the correct object while using the search api"""
    self.api.set_user(self.users['admin'])
    self.api.post(all_models.Regulation, {
        "regulation": {"title": "Admin regulation", "context": None},
    })
    self.api.set_user(self.users['creator'])
    response = self.api.post(all_models.Policy, {
        "policy": {"title": "Creator Policy", "context": None},
    })
    obj_id = response.json.get("policy").get("id")
    self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Policy",
            "id": obj_id,
        }, "context": None}})
    response, _ = self.api.search("Regulation,Policy")
    entries = response.json["results"]["entries"]
    self.assertEqual(len(entries), 1)
    self.assertEqual(entries[0]["type"], "Policy")
    response, _ = self.api.search("Regulation,Policy", counts=True)
    self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
    self.assertEqual(
        response.json["results"]["counts"].get("Regulation"), None)

  def _get_count(self, obj):
    """ Return the number of counts for the given object from search """
    response, _ = self.api.search(obj, counts=True)
    return response.json["results"]["counts"].get(obj)

  def test_creator_should_see_users(self):
    """ Test if creator can see all the users in the system """
    self.api.set_user(self.users['admin'])
    admin_count = self._get_count("Person")
    self.api.set_user(self.users['creator'])
    creator_count = self._get_count("Person")
    self.assertEqual(admin_count, creator_count)

  def test_creator_cannot_be_owner(self):
    """Test if creator cannot become owner of the object he has not created"""
    self.api.set_user(self.users['admin'])
    _, obj = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    self.api.set_user(self.users['creator'])
    response = self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Regulation",
            "id": obj.id,
        }, "context": None}})
    self.assertEqual(response.status_code, 403)

  def test_relationships_access(self):
    """Check if creator cannot access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, obj_0 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    _, obj_1 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation 2", "context": None},
    })
    response, rel = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"source": {
                "id": obj_0.id,
                "type": "Regulation"
            }, "destination": {
                "id": obj_1.id,
                "type": "Regulation"
            }, "context": None},
        }
    )
    relationship_id = rel.id
    self.assertEqual(response.status_code, 201)
    self.api.set_user(self.users['creator'])
    response = self.api.get_collection(all_models.Relationship,
                                       relationship_id)
    self.assertEqual(response.status_code, 200)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 0)

  def test_revision_access(self):
    """Check if creator can access the right revision objects."""

    def gen(title):
      return self.generator.generate(all_models.Section, "section", {
          "section": {"title": title, "context": None},
      })[1]

    def check(obj, expected):
      """Check that how many revisions of an object current user can see."""
      response = self.api.get_query(
          all_models.Revision,
          "resource_type={}&resource_id={}".format(obj.type, obj.id)
      )
      self.assertEqual(response.status_code, 200)
      self.assertEqual(
          len(response.json['revisions_collection']['revisions']),
          expected
      )

    self.api.set_user(self.users["admin"])
    obj_1 = gen("Test Section 1")
    obj_2 = gen("Test Section 2")

    self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Section",
            "id": obj_2.id,
        }, "context": None}})

    self.api.set_user(self.users["creator"])
    check(obj_1, 0)
    check(obj_2, 2)
コード例 #28
0
class TestCsvImport(TestCase):

  def setUp(self):
    super(TestCsvImport, self).setUp()
    self.generator = ObjectGenerator()
    self.client.get("/login")

  def tearDown(self):
    pass

  def generate_people(self, people):
    for person in people:
      self.generator.generate_person({
          "name": person,
          "email": "{}@reciprocitylabs.com".format(person),
      }, "Administrator")

  def test_multi_basic_policy_orggroup_product(self):
    filename = "multi_basic_policy_orggroup_product.csv"
    response_json = self.import_file(filename)

    object_counts = {
        "Org Group": (4, 0, 0),
        "Policy": (4, 0, 0),
        "Product": (5, 0, 0),
    }

    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      self.assertEqual(set(), set(row["row_warnings"]))

    self.assertEqual(Policy.query.count(), 4)
    self.assertEqual(OrgGroup.query.count(), 4)
    self.assertEqual(Product.query.count(), 5)

  def test_multi_basic_policy_orggroup_product_with_warnings(self):
    """Test multi basic policy orggroup product with warnings"""
    filename = "multi_basic_policy_orggroup_product_with_warnings.csv"
    response_json = self.import_file(filename, safe=False)

    row_messages = []
    object_counts = {
        "Policy": (3, 0, 2),
        "Org Group": (0, 0, 4),
        "Product": (5, 0, 2),
    }
    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      row_messages.extend(row["row_warnings"])
      row_messages.extend(row["row_errors"])

    expected_warnings = set([
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line="6", processed_line="5", column_name="Title", value="dolor",
        ),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line="7", processed_line="6", column_name="Code", value="p-4",
        ),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line="26", processed_line="21", column_name="Title",
            value="meatloaf",
        ),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line="26", processed_line="21", column_name="Code", value="pro 1",
        ),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line="27", processed_line="21", column_name="Code", value="pro 1",
        ),
        errors.OWNER_MISSING.format(line=26, column_name="Admin"),
        errors.MISSING_COLUMN.format(line=13, column_names="Admin", s=""),
        errors.MISSING_COLUMN.format(line=14, column_names="Admin", s=""),
        errors.MISSING_COLUMN.format(line=15, column_names="Admin", s=""),
        errors.MISSING_COLUMN.format(line=16, column_names="Admin", s=""),
    ])

    self.assertEqual(expected_warnings, set(row_messages))
    self.assertEqual(Policy.query.count(), 3)
    self.assertEqual(OrgGroup.query.count(), 0)
    self.assertEqual(Product.query.count(), 5)

  def test_multi_basic_policy_orggroup_product_with_mappings(self):

    def get_relationships_for(obj):
      return Relationship.query.filter(or_(
          and_(Relationship.source_id == obj.id,
               Relationship.source_type == obj.type),
          and_(Relationship.destination_id == obj.id,
               Relationship.destination_type == obj.type),
      ))

    filename = "multi_basic_policy_orggroup_product_with_mappings.csv"
    response_json = self.import_file(filename)

    object_counts = {
        "Policy": (4, 0, 0),
        "Org Group": (4, 0, 0),
        "Product": (5, 0, 0),
    }
    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      self.assertEqual(set(), set(row["row_warnings"]))

    self.assertEqual(Policy.query.count(), 4)
    self.assertEqual(OrgGroup.query.count(), 4)
    self.assertEqual(Product.query.count(), 5)
    p1 = Policy.query.filter_by(slug="p-1").first()
    org1 = OrgGroup.query.filter_by(slug="org-1").first()

    self.assertEqual(get_relationships_for(p1).count(), 3)
    self.assertEqual(get_relationships_for(org1).count(), 5)
コード例 #29
0
class TestAccessControlRole(TestCase):
    """TestAccessControlRole"""
    def setUp(self):
        self.clear_data()
        super(TestAccessControlRole, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.people = {}
        for name in ["Creator", "Reader", "Editor"]:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=name)
            self.people[name] = user

    def _post_role(self, name=None, object_type="Control"):
        """Helper function for POSTing roles"""
        if name is None:
            name = random_str(prefix="Access Control Role - ")
        return self.api.post(
            AccessControlRole, {
                "access_control_role": {
                    "name": name,
                    "object_type": object_type,
                    "context": None,
                    "read": True
                },
            })

    def test_create_after_objects(self):
        """Test eager creation of ACLs on existing objects with new ACR."""
        program_id = factories.ProgramFactory().id
        role_name = "New Custom Role"
        self._post_role(name=role_name, object_type="Program")
        program = all_models.Program.query.get(program_id)
        self.assertIn(role_name, program.acr_name_acl_map.keys())
        self.assertIsNotNone(program.acr_name_acl_map[role_name])

    def test_create(self):
        """Test Access Control Role creation"""
        response = self._post_role(object_type="Program")
        assert response.status_code == 201, \
            "Failed to create a new access control role, response was {}".format(
                response.status)

        id_ = response.json['access_control_role']['id']
        role = AccessControlRole.query.filter(
            AccessControlRole.id == id_).first()
        assert role.read == 1, \
            "Read permission not correctly saved {}".format(role.read)
        assert role.update == 1, \
            "Update permission not correctly saved {}".format(role.update)
        assert role.delete == 1, \
            "Update permission not correctly saved {}".format(role.delete)

    @ddt.data(
        {
            "mandatory": True,
            "exp_response": MANDATORY_ROLE_RESPONSE
        },
        {
            "mandatory": False,
            "exp_response": NON_MANDATORY_ROLE_RESPONSE
        },
    )
    @ddt.unpack
    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="Program",
            mandatory=mandatory,
        )
        with factories.single_commit():
            user = factories.PersonFactory()
            program = factories.ProgramFactory()
            role_id = role.id
            factories.AccessControlPersonFactory(
                ac_list=program.acr_name_acl_map[ROLE_NAME],
                person=user,
            )
        response = self.import_data(
            OrderedDict([
                ("object_type", "Program"),
                ("Code*", program.slug),
                (ROLE_NAME, "--"),
            ]))
        self._check_csv_response(response, exp_response)
        db_data = defaultdict(set)
        program = all_models.Program.query.get(program.id)
        for person, acl in program.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])

    def test_only_admin_can_post(self):
        """Only admin users should be able to POST access control roles"""
        for name in ("Creator", "Reader", "Editor"):
            person = self.people.get(name)
            self.api.set_user(person)
            response = self._post_role()
            assert response.status_code == 403, \
                "Non admins should get forbidden error when POSTing role. {}".format(
                    response.status)

    @ddt.data(
        ("name", "New ACR"),
        ("read", False),
        ("mandatory", False),
        ("non_editable", False),
    )
    @ddt.unpack
    def test_modify_non_editable_role(self, field_name, field_value):
        """Test if user can modify non-editable role"""
        # Primary Contacts role of Control is non-editable
        ac_role = AccessControlRole.query.filter_by(
            object_type="Control",
            name="Control Operators",
        ).first()

        response = self.api.put(ac_role, {field_name: field_value})
        assert response.status_code == 403, \
            "Forbidden error should be thrown when non-editable " \
            "role {} updated.".format(ac_role.name)

    def test_delete_non_editable_role(self):
        """Test if user can delete non-editable role"""
        # Primary Contacts role of Control is non-editable
        ac_role = AccessControlRole.query.filter_by(
            object_type="Control",
            name="Control Operators",
        ).first()

        response = self.api.delete(ac_role)
        assert response.status_code == 403, \
            "Forbidden error should be thrown when non-editable " \
            "role {} deleted.".format(ac_role.name)

    @ddt.data("Control")
    def test_create_from_ggrcq(self, object_type):
        """Test that create action only for GGRCQ."""
        with self.api.as_external():
            response = self._post_role(object_type=object_type)
            self.assertEqual(response.status_code, 201)

    @ddt.data("Control")
    def test_create_from_ggrc(self, object_type):
        """Test create action not allowed for GGRC."""
        response = self._post_role(object_type=object_type)
        self.assertEqual(response.status_code, 405)

    @ddt.data("Control")
    def test_modify_from_ggrcq(self, object_type):
        """Test that modify action only for GGRCQ."""
        with factories.single_commit():
            acr_id = factories.AccessControlRoleFactory(
                object_type=object_type).id

        with self.api.as_external():
            acr = all_models.AccessControlRole.query.get(acr_id)
            response = self.api.put(acr, {"name": "new acr"})
            self.assertEqual(response.status_code, 200)

    @ddt.data("Control")
    def test_modify_from_ggrc(self, object_type):
        """Test modify action not allowed for GGRC."""
        with factories.single_commit():
            acr = factories.AccessControlRoleFactory(object_type=object_type)

        response = self.api.put(acr, {"name": "new acr"})
        self.assertEqual(response.status_code, 405)

    @ddt.data("Control")
    def test_delete_from_ggrcq(self, object_type):
        """Test that modify action only for GGRCQ."""
        with factories.single_commit():
            acr_id = factories.AccessControlRoleFactory(
                object_type=object_type).id

        with self.api.as_external():
            acr = all_models.AccessControlRole.query.get(acr_id)
            response = self.api.delete(acr)
            self.assertEqual(response.status_code, 200)

    @ddt.data("Control")
    def test_delete_from_ggrc(self, object_type):
        """Test modify action not allowed for GGRC."""
        with factories.single_commit():
            acr = factories.AccessControlRoleFactory(object_type=object_type)

        response = self.api.delete(acr)
        self.assertEqual(response.status_code, 405)

    @ddt.data(
        {
            "name": "Test 1",
            "update": False,
            "read": False,
            "delete": True
        },
        {
            "name": "Test 2",
            "update": True,
            "read": False,
            "delete": False
        },
        {
            "name": "Test 3",
            "update": True,
            "read": False,
            "delete": True
        },
    )
    @ddt.unpack
    def test_create_with_wrong_options(self, name, update, read, delete):
        """ Test if user create ACR with wrong options."""
        options = [{
            'access_control_role': {
                'modal_title': 'Add Custom Role to type Regulation',
                'object_type': 'Regulation',
                'parent_type': 'Regulation',
                'context': {
                    'id': None
                },
                'delete': delete,
                'update': update,
                'read': read,
                'name': name
            }
        }]
        response = self.api.post(AccessControlRole, options)
        self.assert400(response)
コード例 #30
0
class TestReader(TestCase):
  """Test Assignable RBAC"""

  def setUp(self):
    super(TestReader, self).setUp()
    self.audit_id = factories.AuditFactory().id
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_assignable()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("creator", "Creator"), ("reader", "Reader"),
             ("editor", "Editor"), ("admin", "Administrator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def init_assignable(self):
    """Creates the assignable object used by all the tests"""
    self.api.set_user(self.users["editor"])
    response = self.api.post(all_models.Assessment, {
        "assessment": {
            "title": "Assessment",
            "context": None,
            "audit": {
                "id": self.audit_id,
                "type": "Audit"
            }
        }
    })
    obj_id = response.json.get("assessment").get("id")
    self.assertEqual(response.status_code, 201, "Error setting up Assessment")
    self.obj_json = response.json
    self.obj = all_models.Assessment.query.get(obj_id)

  def _add_creator(self, asmnt, user):
    """Helper method for creating assignees on an object"""
    acr = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.object_type == "Assessment",
        all_models.AccessControlRole.name == "Creators",
    ).first()
    return self.api.put(asmnt, {
        "access_control_list": [acl_helper.get_acl_json(acr.id, user.id)]
    })

  def test_basic_with_no_assignee(self):
    """Editor creates an Assessment, but doesn't assign Reader/Creator as
       assignee. Reader should have Read access, Creator should have no access
    """

    # Reader should have read access, but shouldn't be allowed to edit or
    # create another assingee
    self.api.set_user(self.users["reader"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, self.obj_json)
    self.assertEqual(response.status_code, 403)
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 403)

    # Creator should have no access. We skip the put request because we can't
    # get the object etag.
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 403)
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 403)

  def test_basic_with_assignee(self):
    """Test if Reader/Creator have CRUD access once they become assignees"""

    # Admin adds reader as an assignee
    self.api.set_user(self.users["admin"])
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 200)

    # Reader is now allowed to update the object
    self.api.set_user(self.users["reader"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, response.json)
    self.assertEqual(response.status_code, 200)

    # Reader adds creator as an assignee
    response = self._add_creator(self.obj, self.users["creator"])
    self.assertEqual(response.status_code, 200)

    # Creator now has CRUD access
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, response.json)

    # Creator should even be allowed to add new assignees
    response = self._add_creator(self.obj, self.users["admin"])
    self.assertEqual(response.status_code, 200)

  def test_read_of_mapped_objects(self):
    """Test if assignees get Read access on all mapped objects"""

    # Editor creates a System object and maps it to the assignable object
    self.api.set_user(self.users["editor"])
    response = self.api.post(all_models.System, {
        "system": {
            "title": "System",
            "context": None,
        }
    })
    system_id = response.json.get("system").get("id")
    system = all_models.System.query.get(system_id)
    self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.obj.id,
            "type": "Assessment"
        }, "destination": {
            "id": system_id,
            "type": "System"
        }, "context": None},
    })

    # Since creator is not an assignee she should not have access to any of the
    # two objects
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 403)
    response = self.api.get(all_models.System, system_id)
    self.assertEqual(response.status_code, 403)

    # Editor adds creator as an assignee
    self.api.set_user(self.users["editor"])
    response = self._add_creator(self.obj, self.users["creator"])
    self.assertEqual(response.status_code, 200)

    # Creator should now have read access on the mapped object
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.System, system_id)
    self.assertEqual(response.status_code, 403)

    # But he should still not be allowed to update
    response = self.api.put(system, response.json)
    self.assertEqual(response.status_code, 403)
コード例 #31
0
class TestCreatorAudit(TestCase):
    """Set up necessary objects and test Creator role with Audit roles"""
    def setUp(self):
        super(TestCreatorAudit, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_roles()
        self.init_test_cases()
        self.objects = {}

    def init_test_cases(self):
        """Create a dict of all possible test cases."""
        self.test_cases = {
            "Auditor": {
                "audit_role": "Auditor",
                "objects": {
                    "audit": {
                        "get": 200,
                        "put": 403,
                        "delete": 403
                    },
                    "mapped_Issue": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "unrelated_Issue": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    },
                    "mapped_Assessment": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "unrelated_Assessment": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
        }

    def init_roles(self):
        """Create a delete request for the given object."""
        response = self.api.get_query(all_models.Role, "")
        self.roles = {}
        for role in response.json.get("roles_collection").get("roles"):
            self.roles[role.get("name")] = role

    def init_users(self):
        """Create users used by test cases."""
        self.people = {}
        for name in ["creator", "notmapped", "mapped", "Auditor"]:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role="Creator")
            self.people[name] = user

        _, user = self.object_generator.generate_person(
            data={"name": "editor"}, user_role="Editor")
        self.people["editor"] = user

    def delete(self, obj):
        """Create a delete request for the given object.

    Args:
        obj (model instance): target object to delete
    Returns:
        int: http response status code
    """
        return self.api.delete(obj).status_code

    def get(self, obj):
        """Create a get request for the given object.

    Args:
        obj (model instance): target object to get
    Returns:
        int: http response status code
    """
        return self.api.get(obj.__class__, obj.id).status_code

    def put(self, obj):
        """Create a put request for the given object.

    Args:
        obj (model instance): target object to put
    Returns:
        int: http response status code
    """
        response = self.api.get(obj.__class__, obj.id)
        if response.status_code == 200:
            return self.api.put(obj, response.json).status_code
        else:
            return response.status_code

    def map(self, dest):
        """Map audit to dest.

    Args:
        dest (model instance): target object to map to the audit
    Returns:
        int: http response status code
    """
        response = self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": self.objects["audit"].id,
                        "type": self.objects["audit"].type,
                    },
                    "destination": {
                        "id": dest.id,
                        "type": dest.type
                    },
                    "context": None
                },
            })
        return response.status_code

    def init_objects(self, test_case_name):
        """Create a Program, an Audit, and a Mapped object for the test case.

    Args:
        test_case_name (string): test case to init for
    """
        # Create a program
        dummy_audit = factories.AuditFactory()
        unrelated_audit = {
            "type": "Audit",
            "context_id": dummy_audit.context.id,
            "id": dummy_audit.id,
        }
        test_case = self.test_cases[test_case_name]
        editor = self.people.get('editor')
        self.api.set_user(editor)
        random_title = factories.random_str()
        response = self.api.post(all_models.Program, {
            "program": {
                "title": random_title,
                "context": None
            },
        })
        self.assertEqual(response.status_code, 201)
        program_id = response.json.get("program").get("id")
        self.objects["program"] = all_models.Program.query.get(program_id)
        response = self.api.post(
            all_models.Audit, {
                "audit": {
                    "title": random_title + " audit",
                    'program': {
                        'id': program_id
                    },
                    "status": "Planned",
                    "context": None
                }
            })
        self.assertEqual(response.status_code, 201)
        context = response.json.get("audit").get("context")
        audit_id = response.json.get("audit").get("id")
        self.objects["audit"] = all_models.Audit.query.get(audit_id)
        audits = {
            "mapped": {
                "type": "Audit",
                "context_id": context["id"],
                "id": audit_id,
            },
            "unrelated": unrelated_audit,
        }

        for prefix, audit_dict in audits.items():
            random_title = factories.random_str()

            response = self.api.post(all_models.Issue, {
                "issue": {
                    "title": random_title,
                    "context": None,
                },
            })
            self.assertEqual(response.status_code, 201)
            issue_id = response.json.get("issue").get("id")
            self.objects[prefix +
                         "_Issue"] = all_models.Issue.query.get(issue_id)

            response = self.api.post(
                all_models.Assessment, {
                    "assessment": {
                        "title": random_title,
                        "context": {
                            "type": "Context",
                            "id": audit_dict["context_id"],
                        },
                        "audit": audit_dict,
                    },
                })
            self.assertEqual(response.status_code, 201)
            assessment_id = response.json.get("assessment").get("id")
            self.objects[prefix + "_Assessment"] = \
                all_models.Assessment.query.get(assessment_id)

        self.assertEqual(self.map(self.objects["mapped_Issue"]), 201)
        self.assertEqual(self.map(self.objects["mapped_Assessment"]), 201)

        # Add roles to mapped users:
        if "audit_role" in test_case:
            person = self.people.get(test_case_name)
            role = self.roles[test_case["audit_role"]]
            response = self.api.post(
                all_models.UserRole, {
                    "user_role": {
                        "person": {
                            "id": person.id,
                            "type": "Person",
                            "href": "/api/people/{}".format(person.id),
                        },
                        "role": {
                            "type": "Role",
                            "href": "/api/roles/{}".format(role["id"]),
                            "id": role["id"],
                        },
                        "context": {
                            "type": "Context",
                            "id": context.get("id"),
                            "href": "/api/contexts/{}".format(
                                context.get("id"))
                        }
                    }
                })
            self.assertEqual(response.status_code, 201)

    def test_creator_audit_roles(self):
        """ Test creator role with all audit scoped roles """
        # Check permissions based on test_cases:
        errors = []
        for test_case in self.test_cases:
            self.init_objects(test_case)
            person = self.people.get(test_case)
            objects = self.test_cases.get(test_case).get('objects')
            self.api.set_user(person)
            for obj, actions in objects.iteritems():
                for action in ("map", "get", "put", "delete"):
                    if action not in actions:
                        continue
                    # reset sesion:
                    db.session.commit()
                    func = getattr(self, action)
                    res = func(self.objects[obj])
                    if res != actions[action]:
                        errors.append(
                            "{}: Tried {} on {}, but received {} instead of {}"
                            .format(test_case, action, obj, res,
                                    actions[action]))

        self.assertEqual(errors, [])
コード例 #32
0
class TestCustomAttributeImportExport(TestCase):
  """Test import and export with custom attributes."""

  _set_up = True

  def setUp(self):
    """Setup stage for each test.

    Generate all required objects and custom attributes for import of csvs
    containing custom attributes. This stage also initializes a http client
    that is used for sending import/export requests.
    """
    if TestCustomAttributeImportExport._set_up:
      super(TestCustomAttributeImportExport, self).setUp()
      self.generator = ObjectGenerator()
      self.create_custom_attributes()
      self.create_people()
    self.client.get("/login")
    self.headers = ObjectGenerator.get_header()
    TestCustomAttributeImportExport._set_up = False

  def create_custom_attributes(self):
    """Generate custom attributes needed for csv import

    This function generates all custom attributes on Product and Access Group,
    that are used in custom_attribute_tests.csv and
    multi_word_object_custom_attribute_test.csv files.
    """
    gen = self.generator.generate_custom_attribute
    gen("product", attribute_type="Text", title="normal text")
    gen("product", attribute_type="Text", title="man text", mandatory=True)
    gen("product", attribute_type="Rich Text", title="normal RT")
    gen("product", attribute_type="Rich Text", title="man RT", mandatory=True)
    gen("product", attribute_type="Date", title="normal Date")
    gen("product", attribute_type="Date", title="man Date", mandatory=True,
        helptext="Birthday")
    gen("product", attribute_type="Checkbox", title="normal CH")
    gen("product", attribute_type="Checkbox", title="man CH", mandatory=True)
    gen("product", attribute_type="Dropdown", title="normal select",
        options=u"a,b,c,\u017e", helptext="Your favorite number.")
    gen("product", attribute_type="Dropdown", title="man select",
        options="e,f,g", mandatory=True)
    gen("product", attribute_type="Map:Person", title="normal person")
    gen("product", attribute_type="Map:Person", title="man person",
        mandatory=True)

    gen("access_group", attribute_type="Text",
        title="access group test custom", mandatory=True)

  def create_people(self):
    """Create people used in the csv files.

    This function should be removed and people should be added into the csv
    file as a Person block.
    """
    emails = [
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
    ]
    for email in emails:
      self.generator.generate_person({
          "name": email.split("@")[0].title(),
          "email": email,
      }, "Administrator")

  def test_product_ca_import(self):
    """Test import of product with all custom attributes.

    This tests covers all possible custom attributes with mandatory flag turned
    off and on, and checks for all warnings that should be present.
    """
    filename = "custom_attribute_tests.csv"
    response = self.import_file(filename, safe=False)[0]
    expected_warnings = {
        errors.WRONG_VALUE.format(line=6, column_name="man CH"),
        errors.WRONG_VALUE.format(line=8, column_name="normal select"),
        errors.WRONG_VALUE.format(line=10, column_name="man select"),
        errors.WRONG_VALUE.format(line=11, column_name="normal CH"),
        errors.WRONG_VALUE.format(line=12, column_name="man CH"),
        errors.WRONG_VALUE.format(line=14, column_name="normal Date"),
        errors.WRONG_VALUE.format(line=16, column_name="man Date"),
        errors.OWNER_MISSING.format(line=21, column_name="Admin"),
        errors.UNKNOWN_USER_WARNING.format(line=22, email="*****@*****.**"),
        errors.OWNER_MISSING.format(line=22, column_name="Admin"),
        errors.OWNER_MISSING.format(line=26, column_name="Admin"),
        errors.UNKNOWN_USER_WARNING.format(
            line=27, email="*****@*****.**"),
        errors.OWNER_MISSING.format(line=27, column_name="Admin"),
    }

    expected_errors = {
        "Line 6: Field 'man CH' is required. The line will be ignored.",
        "Line 9: Field 'man select' is required. The line will be ignored.",
        "Line 10: Field 'man select' is required. The line will be ignored.",
        "Line 12: Field 'man CH' is required. The line will be ignored.",
        "Line 16: Field 'man Date' is required. The line will be ignored.",
        "Line 18: Field 'man RT' is required. The line will be ignored.",
        "Line 20: Field 'man text' is required. The line will be ignored.",
        "Line 21: Field 'man person' is required. The line will be ignored.",
        "Line 28: Field 'Title' is required. The line will be ignored."
    }

    self.assertEqual(expected_warnings, set(response["row_warnings"]))
    self.assertEqual(expected_errors, set(response["row_errors"]))
    self.assertEqual(17, response["created"])
    self.assertEqual(9, response["ignored"])
    self.assertEqual(17, Product.query.count())

    product10 = Product.query.filter_by(slug="prod10").first()
    people_emails = {cav.attribute_object.email
                     for cav in product10.custom_attribute_values
                     if cav.custom_attribute.attribute_type == "Map:Person"}

    self.assertEqual(people_emails, {"*****@*****.**", "*****@*****.**"})

  def test_product_ca_import_update(self):
    """Test updating of product with all custom attributes.

    This tests covers updates for all possible custom attributes
    """
    # TODO: check response data explicitly
    self.import_file("custom_attribute_tests.csv", safe=False)
    self.import_file("custom_attribute_update_tests.csv")
    prod_0 = Product.query.filter(Product.slug == "prod0").first()
    prod_0_expected = {
        u"normal text": u"edited normal text",
        u"man text": u"edited man text",
        u"normal RT": (u'some <br> edited rich <br> text '
                       u'<a href="https://www.google.com">'
                       u'https://www.google.com</a>'),
        u"man RT": u"other edited <br> rich text <a>http://www.google.com</a>",
        u"normal Date": u"2017-09-14",
        u"man Date": u"2018-01-17",
        u"normal CH": u"1",
        u"man CH": u"0",
        u"normal select": u"\u017e",
        u"man select": u"f",
        u"normal person": u"Person",
        u"man person": u"Person",
    }
    prod_0_new = {c.custom_attribute.title: c.attribute_value
                  for c in prod_0.custom_attribute_values}
    self.assertEqual(prod_0_expected, prod_0_new)

    people_emails = {cav.attribute_object.email
                     for cav in prod_0.custom_attribute_values
                     if cav.custom_attribute.attribute_type == "Map:Person"}

    self.assertEqual(people_emails, {"*****@*****.**", "*****@*****.**"})

  def tests_ca_export(self):
    """Test exporting products with custom attributes

    This test checks that we get a proper response when exporting objects with
    custom attributes and that the response data actually contains more lines
    than an empty template would.
    This tests relys on the import tests to work. If those fail they need to be
    fixied before this one.
    """
    # TODO: check response data explicitly
    self.import_file("custom_attribute_tests.csv", safe=False)

    data = {
        "export_to": "csv",
        "objects": [{
            "object_name": "Product",
            "filters": {
                "expression": {},
            },
            "fields": "all",
        }]
    }
    response = self.client.post("/_service/export_csv", data=dumps(data),
                                headers=self.headers)

    self.assert200(response)
    self.assertEqual(len(response.data.splitlines()), 33)
    self.assertIn("\"Accepted values are", response.data)
    self.assertIn("number.\n\nAccepted values are", response.data)
    self.assertIn("Birthday", response.data)

  def tests_ca_export_filters(self):
    """Test filtering on custom attribute values."""

    # TODO: check response data explicitly
    self.import_file("custom_attribute_tests.csv", safe=False)

    data = {
        "export_to": "csv",
        "objects": [{
            "object_name": "Product",
            "filters": {
                "expression": {
                    "left": "normal text",
                    "op": {"name": "="},
                    "right": "some text",
                },
            },
            "fields": "all",
        }]
    }
    response = self.client.post("/_service/export_csv", data=dumps(data),
                                headers=self.headers)
    self.assert200(response)
    self.assertIn("some text", response.data)

  def test_multi_word_object_with_ca(self):
    """Test multi-word (e.g. Access Group, Data Asset) object import"""
    filename = "multi_word_object_custom_attribute_test.csv"
    response = self.import_file(filename)[0]
    self.assertEqual([], response["row_warnings"])
    self.assertEqual([], response["row_errors"])
    self.assertEqual(10, response["created"])
    self.assertEqual(0, response["ignored"])
    self.assertEqual(0, response["updated"])
    self.assertEqual(10, AccessGroup.query.count())

    for id_ in range(1, 11):
      access_group = AccessGroup.query.filter(
          AccessGroup.slug == "ag-{}".format(id_)).first()
      filtered = [val for val in access_group.custom_attribute_values if
                  val.attribute_value == "some text {}".format(id_)]
      self.assertEqual(len(filtered), 1)
コード例 #33
0
ファイル: test_reader.py プロジェクト: bdsimpteam/ggrc-core
class TestReader(TestCase):
    """ Test reader role """
    def setUp(self):
        super(TestReader, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("reader", "Reader"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        for role, code in (("reader", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.client.get("/admin").status_code, code)

    def test_reader_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["reader"])
        all_errors = []
        base_models = set([
            "Control",
            "DataAsset",
            "Contract",
            "Policy",
            "Regulation",
            "Standard",
            "Document",
            "Facility",
            "Market",
            "Objective",
            "OrgGroup",
            "Vendor",
            "Product",
            "Clause",
            "System",
            "Process",
            "Project",
            "AccessGroup",
        ])
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response = self.api.post(
                    model, {
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "reference_url": "ref",
                            "contact": {
                                "type": "Person",
                                "id": self.users["reader"].id,
                            },
                        },
                    })
                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                obj_id = response.json.get(table_singular).get("id")

                # Test GET when owner
                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if len(collection) == 0:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_reader_search(self):
        """ Test if reader can see the correct object while using search api """
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['reader'])
        response = self.api.post(all_models.Policy, {
            "policy": {
                "title": "reader Policy",
                "context": None
            },
        })
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 2)
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"]["Regulation"], 1)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_reader_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['reader'])
        reader_count = self._get_count("Person")
        self.assertEqual(admin_count, reader_count)

    def test_relationships_access(self):
        """Check if reader can access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['reader'])
        response = self.api.get_collection(all_models.Relationship,
                                           relationship_id)
        self.assertEqual(response.status_code, 200)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 1)

    def test_creation_of_mappings(self):
        """Check if reader can't create mappings"""
        self.generator.api.set_user(self.users["admin"])
        _, control = self.generator.generate(all_models.Control, "control", {
            "control": {
                "title": "Test Control",
                "context": None
            },
        })
        self.generator.api.set_user(self.users['reader'])
        _, program = self.generator.generate(all_models.Program, "program", {
            "program": {
                "title": "Test Program",
                "context": None
            },
        })

        response, _ = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "destination": {
                        "id": program.id,
                        "type": "Program"
                    },
                    "source": {
                        "id": control.id,
                        "type": "Control"
                    },
                    "context": {
                        "id": program.context.id,
                        "type": "context"
                    }
                },
            })
        self.assertEqual(response.status_code, 403)
コード例 #34
0
class TestCycleTaskImportUpdate(BaseTestCycleTaskImportUpdate):

  """ This class contains simple cycle task update tests using import
  functionality
  """

  CSV_DIR = join(abspath(dirname(__file__)), "test_csvs/")

  def setUp(self):
    super(TestCycleTaskImportUpdate, self).setUp()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    self.ftime_active = "2016-07-01"
    self.ftime_historical = "2014-05-01"
    self._create_test_cases_data()
    # It is needed because cycle-tasks are generated automatically with
    # 'slug' based on auto_increment 'id' field.
    # At start of each test we suppose that created cycle-task's 'slug'
    # lie in range from 1 to 10.
    db.session.execute('ALTER TABLE cycle_task_group_object_tasks '
                       'AUTO_INCREMENT = 1')

  def test_cycle_task_correct(self):
    """Test cycle task update via import with correct data"""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_correct.csv")
      self._check_csv_response(response, {})
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_warnings(self):
    """Test cycle task update via import with data which is the reason of
    warnings about non-importable columns."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_warnings.csv")
      self._check_csv_response(response, self.expected_warnings)
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_create_error(self):
    """Test cycle task update via import with data which is the reason of
    errors about new cycle task creation."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_create_error.csv")
      self._check_csv_response(response, self.expected_create_error)
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_date_error(self):
    """Test cycle task update via import with data which is the reason of
    errors about incorrect dates in csv file."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_date_error.csv")
      self._check_csv_response(response, self.expected_date_error)
      self._cmp_tasks(self.expected_cycle_task_date_error)

  def test_cycle_task_permission_error(self):
    """Test cycle task update via import with non-admin user which is the
    reason of error. Only admin can update cycle tasks via import."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      _, creator = self.object_generator.generate_person(user_role="Creator")
      response = self.import_file("cycle_task_correct.csv", person=creator)
      self._check_csv_response(response, self.expected_permission_error)
      # Cycle tasks' data shouldn't be changed in test DB after import run from
      # non-admin user
      expected_cycle_task_permission_error = {}
      expected_cycle_task_permission_error.update(
          self.generated_cycle_tasks_active)
      expected_cycle_task_permission_error.update(
          self.generated_cycle_tasks_historical)
      self._cmp_tasks(expected_cycle_task_permission_error)

  def _cmp_tasks(self, expected_ctasks):
    """Compare tasks values from argument's list and test DB."""
    for ctask in db.session.query(CycleTaskGroupObjectTask).all():
      if ctask.slug not in expected_ctasks:
        continue
      exp_task = expected_ctasks[ctask.slug]
      for attr, val in exp_task.iteritems():
        self.assertEqual(str(getattr(ctask, attr, None)), val)

  # pylint: disable=too-many-arguments
  def _activate_workflow(self, ftime, workflow, task_group, task_group_tasks,
                         random_object, cycle_tasks):
    """Helper which is responsible for active cycle-tasks creation"""
    with freeze_time(ftime):
      _, wf = self.wf_generator.generate_workflow(workflow)
      _, tg = self.wf_generator.generate_task_group(wf, task_group)
      for task in task_group_tasks:
        self.wf_generator.generate_task_group_task(tg, task)
      self.wf_generator.generate_task_group_object(tg, random_object)

      _, cycle = self.wf_generator.generate_cycle(wf)
      self.wf_generator.activate_workflow(wf)

      for exp_slug, exp_task in cycle_tasks.iteritems():
        obj = db.session.query(CycleTaskGroupObjectTask).filter_by(
            slug=exp_slug
        ).first()
        if exp_task["status"] == "Verified":
          self.wf_generator.modify_object(obj, {"status": "Finished"})
        self.wf_generator.modify_object(obj, {"status": exp_task["status"]})
    self._cmp_tasks(cycle_tasks)
    return cycle

  def _generate_cycle_tasks(self):
    """Helper which is responsible for test data creation"""
    self._activate_workflow(self.ftime_active, self.workflow_active,
                            self.task_group_active,
                            self.task_group_tasks_active,
                            self.random_objects[0],
                            self.generated_cycle_tasks_active)
    cycle = self._activate_workflow(self.ftime_historical,
                                    self.workflow_historical,
                                    self.task_group_historical,
                                    self.task_group_tasks_historical,
                                    self.random_objects[1],
                                    self.generated_cycle_tasks_historical)
    with freeze_time(self.ftime_historical):
      cycle = Cycle.query.get(cycle.id)
      self.wf_generator.modify_object(cycle, data={"is_current": False})

  def _create_test_cases_data(self):
    """Create test cases data: for object generation,
    expected data for checks"""
    def person_dict(person_id):
      """Return person data"""
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.workflow_active = {
        "title": "workflow active title",
        "description": "workflow active description",
        "frequency": "one_time",
        "owners": [person_dict(self.person_1.id)],
        "notify_on_change": False,
    }

    self.task_group_active = {
        "title": "task group active title",
        "contact": person_dict(self.person_1.id),
    }

    self.task_group_tasks_active = [{
        "title": "task active title 1",
        "description": "task active description 1",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/01/2016",
        "end_date": "07/06/2016",
    }, {
        "title": "task active title 2",
        "description": "task active description 2",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/07/2016",
        "end_date": "07/12/2016",
    }, {
        "title": "task active title 3",
        "description": "task active description 3",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/13/2016",
        "end_date": "07/18/2016",
    }, {
        "title": "task active title 4",
        "description": "task active description 4",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/19/2016",
        "end_date": "07/24/2016",
    }, {
        "title": "task active title 5",
        "description": "task active description 5",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/25/2016",
        "end_date": "07/30/2016",
    }]

    # Active cycle tasks which should be generated from previous structure
    # at the beginning of each test
    self.generated_cycle_tasks_active = {
        "CYCLETASK-1": {
            "title": self.task_group_tasks_active[0]["title"],
            "description": self.task_group_tasks_active[0]["description"],
            "start_date": "2016-07-01",
            "end_date": "2016-07-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-2": {
            "title": self.task_group_tasks_active[1]["title"],
            "description": self.task_group_tasks_active[1]["description"],
            "start_date": "2016-07-07",
            "end_date": "2016-07-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-3": {
            "title": self.task_group_tasks_active[2]["title"],
            "description": self.task_group_tasks_active[2]["description"],
            "start_date": "2016-07-13",
            "end_date": "2016-07-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-4": {
            "title": self.task_group_tasks_active[3]["title"],
            "description": self.task_group_tasks_active[3]["description"],
            "start_date": "2016-07-19",
            "end_date": "2016-07-24",
            "finished_date": "2016-07-01 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-5": {
            "title": self.task_group_tasks_active[4]["title"],
            "description": self.task_group_tasks_active[4]["description"],
            "start_date": "2016-07-25",
            "end_date": "2016-07-30",
            "finished_date": "2016-07-01 00:00:00",
            "verified_date": "2016-07-01 00:00:00",
            "status": "Verified"
        }
    }

    self.workflow_historical = {
        "title": "workflow historical title",
        "description": "workflow historical description",
        "frequency": "one_time",
        "owners": [person_dict(self.person_1.id)],
        "notify_on_change": False,
    }

    self.task_group_historical = {
        "title": "task group historical title",
        "contact": person_dict(self.person_1.id),
    }

    self.task_group_tasks_historical = [{
        "title": "task historical title 1",
        "description": "task historical description 1",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/01/2014",
        "end_date": "05/06/2014",
    }, {
        "title": "task historical title 2",
        "description": "task historical description 2",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/07/2014",
        "end_date": "05/12/2014",
    }, {
        "title": "task historical title 3",
        "description": "task historical description 3",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/13/2014",
        "end_date": "05/18/2014",
    }, {
        "title": "task historical title 4",
        "description": "task historical description 4",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/19/2014",
        "end_date": "05/24/2014",
    }, {
        "title": "task historical title 5",
        "description": "task historical description 5",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/25/2014",
        "end_date": "05/30/2014",
    },
    ]

    # Historical cycle tasks which should be generated from previous structure
    # at the beginning of each test.
    self.generated_cycle_tasks_historical = {
        "CYCLETASK-6": {
            "title": self.task_group_tasks_historical[0]["title"],
            "description": self.task_group_tasks_historical[0]["description"],
            "start_date": "2014-05-01",
            "end_date": "2014-05-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-7": {
            "title": self.task_group_tasks_historical[1]["title"],
            "description": self.task_group_tasks_historical[1]["description"],
            "start_date": "2014-05-07",
            "end_date": "2014-05-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-8": {
            "title": self.task_group_tasks_historical[2]["title"],
            "description": self.task_group_tasks_historical[2]["description"],
            "start_date": "2014-05-13",
            "end_date": "2014-05-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-9": {
            "title": self.task_group_tasks_historical[3]["title"],
            "description": self.task_group_tasks_historical[3]["description"],
            "start_date": "2014-05-19",
            "end_date": "2014-05-24",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-10": {
            "title": self.task_group_tasks_historical[4]["title"],
            "description": self.task_group_tasks_historical[4]["description"],
            "start_date": "2014-05-25",
            "end_date": "2014-05-30",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "2014-05-01 00:00:00",
            "status": "Verified"
        }
    }

    # Expected cycle tasks which should be created in correct cycle task update
    # case. It is needed for most tests.
    self.expected_cycle_task_correct = {
        "CYCLETASK-1": {
            "title": self.task_group_tasks_active[0]["title"] + " one",
            "description":
                self.task_group_tasks_active[0]["description"] + " one",
            "start_date": "2016-06-01",
            "end_date": "2016-06-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-2": {
            "title": self.task_group_tasks_active[1]["title"] + " two",
            "description":
                self.task_group_tasks_active[1]["description"] + " two",
            "start_date": "2016-06-07",
            "end_date": "2016-06-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-3": {
            "title": self.task_group_tasks_active[2]["title"] + " three",
            "description":
                self.task_group_tasks_active[2]["description"] + " three",
            "start_date": "2016-06-13",
            "end_date": "2016-06-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-4": {
            "title": self.task_group_tasks_active[3]["title"] + " four",
            "description":
                self.task_group_tasks_active[3]["description"] + " four",
            "start_date": "2016-06-19",
            "end_date": "2016-06-24",
            "finished_date": "2016-07-19 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-5": {
            "title": self.task_group_tasks_active[4]["title"] + " five",
            "description":
                self.task_group_tasks_active[4]["description"] + " five",
            "start_date": "2016-06-25",
            "end_date": "2016-06-30",
            "finished_date": "2016-07-25 00:00:00",
            "verified_date": "2016-08-30 00:00:00",
            "status": "Verified"
        },
        "CYCLETASK-6": {
            "title": self.task_group_tasks_historical[0]["title"] + " one",
            "description":
                self.task_group_tasks_historical[0]["description"] + " one",
            "start_date": "2014-04-01",
            "end_date": "2014-04-06",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "2014-06-06 00:00:00",
            "status": "Assigned"
        },
        "CYCLETASK-7": {
            "title": self.task_group_tasks_historical[1]["title"] + " two",
            "description":
                self.task_group_tasks_historical[1]["description"] + " two",
            "start_date": "2014-04-07",
            "end_date": "2014-04-12",
            "finished_date": "2014-05-07 00:00:00",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-8": {
            "title": self.task_group_tasks_historical[2]["title"] + " three",
            "description":
                self.task_group_tasks_historical[2]["description"] + " three",
            "start_date": "2014-04-13",
            "end_date": "2014-04-18",
            "finished_date": "2014-05-13 00:00:00",
            "verified_date": "2014-06-18 00:00:00",
            "status": "InProgress"
        },
        "CYCLETASK-9": {
            "title": self.task_group_tasks_historical[3]["title"] + " four",
            "description":
                self.task_group_tasks_historical[3]["description"] + " four",
            "start_date": "2014-04-19",
            "end_date": "2014-04-24",
            "finished_date": "2014-05-19 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-10": {
            "title": self.task_group_tasks_historical[4]["title"] + " five",
            "description":
                self.task_group_tasks_historical[4]["description"] + " five",
            "start_date": "2014-04-25",
            "end_date": "2014-04-30",
            "finished_date": "2014-05-25 00:00:00",
            "verified_date": "2014-06-30 00:00:00",
            "status": "Verified"
        }
    }

    # Below is description of warning for non-importable columns. It is needed
    # for test_cycle_task_warnings.
    importable_column_names = []
    for field_name in CycleTaskGroupObjectTask.IMPORTABLE_FIELDS:
      if field_name == 'slug':
        continue
      # pylint: disable=protected-access
      name = CycleTaskGroupObjectTask._aliases.get(field_name, field_name)
      if isinstance(name, dict):
        name = name['display_name']
      importable_column_names.append(name)
    self.expected_warnings = self.generate_expected_warning(
        *importable_column_names)

    # This is an error message which should be shown during
    # test_cycle_task_create_error test
    self.expected_create_error = {
        'Cycle Task': {
            'row_errors': {errors.CREATE_INSTANCE_ERROR.format(line=13)}
        }
    }

    # Below is expected date errors for test_cycle_task_date_error. They should
    # be shown during date validator's tests.
    self.expected_date_error = {
        'Cycle Task': {
            'row_errors': {
                errors.INVALID_START_END_DATES.format(
                    line=3,
                    start_date="Start Date",
                    end_date="End Date",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=4,
                    date="Actual Finish Date",
                    status="not Finished",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=5,
                    date="Actual Verified Date",
                    status="not Verified",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=6,
                    date="Actual Verified Date",
                    status="not Verified",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=7,
                    start_date="Actual Finish Date",
                    end_date="Actual Verified Date",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=8,
                    start_date="Start Date",
                    end_date="End Date",
                ),
                errors.MISSING_VALUE_ERROR.format(
                    line=9,
                    column_name="Actual Finish Date",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=10,
                    start_date="Actual Finish Date",
                    end_date="Actual Verified Date",
                ),
            },
        }
    }
    # Below is expected cycle-tasks data which should appear in test DB after
    # test_cycle_task_date_error run
    self.expected_cycle_task_date_error = dict()
    self.expected_cycle_task_date_error.update(
        self.generated_cycle_tasks_active)
    self.expected_cycle_task_date_error.update(
        self.generated_cycle_tasks_historical)
    self.expected_cycle_task_date_error["CYCLETASK-9"] = (
        self.expected_cycle_task_correct["CYCLETASK-9"])
    self.expected_cycle_task_date_error["CYCLETASK-10"] = (
        self.expected_cycle_task_correct["CYCLETASK-10"])

    # Expected error message which should be shown after
    # test_cycle_task_permission_error run
    self.expected_permission_error = {
        'Cycle Task': {
            'block_errors': {errors.PERMISSION_ERROR.format(line=2)}
        }
    }
コード例 #35
0
ファイル: test_audit_rbac.py プロジェクト: zidarsk8/ggrc-core
class TestPermissionsOnAssessmentTemplate(TestCase):
  """ Test check permissions for ProgramEditor on

  get and post assessment_temaplte action"""

  def setUp(self):
    super(TestPermissionsOnAssessmentTemplate, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()
    _, program = self.generator.generate_object(all_models.Program)
    program_id = program.id
    _, self.editor = self.generator.generate_person(
        user_role="Creator"
    )
    role = perms.all_models.Role.query.filter(
        perms.all_models.Role.name == "ProgramEditor"
    ).first()
    self.generator.generate_user_role(
        self.editor,
        role,
        all_models.Program.query.get(program_id)
    )
    _, audit = self.generator.generate_object(
        all_models.Audit,
        {
            "title": "Audit",
            "program": {"id": program_id},
            "status": "Planned"
        },
    )
    audit_id = audit.id

    generated_at = self.generator.generate_object(
        all_models.AssessmentTemplate,
        {
            "title": "Template",
            "_NON_RELEVANT_OBJ_TYPES": {},
            "_objectTypes": {},
            "audit": {"id": audit.id},
            "audit_title": audit.title,
            "people_value": [],
            "default_people": {
                "assessors": "Object Owners",
                "verifiers": "Object Owners",
            },
            "context": {"id": audit.context.id},
        }
    )
    self.assessment_template_resp, assessment_template = generated_at
    assessment_template_id = assessment_template.id
    self.api.set_user(self.editor)
    self.perms_data = self.api.client.get("/permissions").json
    self.audit = all_models.Audit.query.get(audit_id)
    self.assessment_template = all_models.AssessmentTemplate.query.get(
        assessment_template_id)

  def test_post_action(self):
    """Test create action on AssessmentTemplate created by api"""
    data = [{
        "assessment_template": {
            "_NON_RELEVANT_OBJ_TYPES": {},
            "_objectTypes": {},
            "audit": {"id": self.audit.id},
            "audit_title": self.audit.title,
            "people_value": [],
            "default_people": {
                "assessors": "Object Owners",
                "verifiers": "Object Owners",
            },
            "context": {"id": self.audit.context.id},
            "title": "123",
        }
    }]
    self.api.set_user(self.editor)
    resp = self.api.post(all_models.AssessmentTemplate, data)
    self.assert200(resp)

  def test_get_action(self):
    """Test read action on AssessmentTemplate created by api"""
    resp = self.api.get(all_models.AssessmentTemplate,
                        self.assessment_template.id)
    self.assert200(resp)

  def test_put_action(self):
    """Test update action on AssessmentTemplate created by api"""
    to_update = copy.deepcopy(self.assessment_template_resp.json)
    new_title = "new_{}".format(self.assessment_template.title)
    to_update['assessment_template']['title'] = new_title
    resp = self.api.put(self.assessment_template, to_update)
    self.assert200(resp)
    assessment_tmpl = all_models.AssessmentTemplate.query.get(
        self.assessment_template.id
    )
    self.assertEqual(new_title, assessment_tmpl.title)

  def test_delete_action(self):
    """Test delete action on AssessmentTemplate created by api"""
    resp = self.api.delete(self.assessment_template)
    self.assert200(resp)
    self.assertFalse(all_models.AssessmentTemplate.query.filter(
        all_models.AssessmentTemplate == self.assessment_template.id).all())
コード例 #36
0
class TestNotificationsForDeletedObjects(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestNotificationsForDeletedObjects, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_delete_activated_workflow(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, workflow = self.wf_generator.generate_workflow(self.quarterly_wf_1)
      response, workflow = self.wf_generator.activate_workflow(workflow)

      self.assert200(response)

      user = Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])

      workflow = Workflow.query.get(workflow.id)
      # After workflow deletion its notifications object_ids updated to 0
      # value, this is the error, them should be deleted
      # so this query checks existence of notifications with object_id
      # equal to workflow id or 0 id before and
      # after deletion workflow instance
      exists_qs = db.session.query(
          Notification.query.filter(
              Notification.object_type == workflow.__class__.__name__,
              Notification.object_id.in_((workflow.id, 0))
          ).exists()
      )
      self.assertTrue(exists_qs.one()[0])
      response = self.wf_generator.api.delete(workflow)
      self.assert200(response)

      self.assertFalse(exists_qs.one()[0])

      _, notif_data = common.get_daily_notifications()
      user = Person.query.get(self.user.id)

      self.assertNotIn(user.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "notify_on_change": True,
        "description": "",
        "owners": [person_dict(self.user.id)],
        "frequency": "quarterly",
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
                "relative_start_day": 5,
                "relative_start_month": 2,
                "relative_end_day": 25,
                "relative_end_month": 2,
            },
            ],
        },
        ]
    }
コード例 #37
0
class TestTaskOverdueNotificationsUsingAPI(TestTaskOverdueNotifications):
  """Tests for overdue notifications when changing Tasks with an API."""

  # pylint: disable=invalid-name

  def setUp(self):
    super(TestTaskOverdueNotificationsUsingAPI, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self._create_test_cases()

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_sending_overdue_notifications_for_tasks(self, is_vf_needed, _):
    """Overdue notifications should be sent for overdue tasks every day.

    Even if an overdue notification has already been sent, it should still be
    sent in every following daily digest f a task is still overdue.
    """
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    tasks = workflow.cycles[0].cycle_task_group_object_tasks
    task1_id = tasks[0].id
    task2_id = tasks[1].id

    user = models.Person.query.get(self.user.id)

    with freeze_time("2017-05-14 08:09:10"):
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

    with freeze_time("2017-05-15 08:09:10"):  # task 1 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

    with freeze_time("2017-05-16 08:09:10"):  # task 2 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id])

    with freeze_time("2017-05-17 08:09:10"):  # after both tasks' due dates
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id, task2_id])

      common.send_daily_digest_notifications()

    # even after sending the overdue notifications, they are sent again the
    # day after, too
    with freeze_time("2017-05-18 08:09:10"):
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id, task2_id])

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_adjust_overdue_notifications_on_task_due_date_change(self,
                                                                is_vf_needed,
                                                                _):
    """Sending overdue notifications should adjust to task due date changes."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

      tasks = workflow.cycles[0].cycle_task_group_object_tasks
      task1, task2 = tasks
      self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)})

      user = models.Person.query.get(self.user.id)

    with freeze_time("2017-05-16 08:09:10"):  # a day after task1 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

      # change task1 due date, there should be no overdue notification anymore
      self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 16)})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

      # change task1 due date to the past there should a notification again
      self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 14)})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_adjust_overdue_notifications_on_task_status_change(self,
                                                              is_vf_needed,
                                                              _):
    """Sending overdue notifications should take task status into account."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

      tasks = workflow.cycles[0].cycle_task_group_object_tasks
      task1, task2 = tasks
      self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)})

      user = models.Person.query.get(self.user.id)
      user_email = user.email
    if is_vf_needed:
      non_final_states = [CycleTaskGroupObjectTask.ASSIGNED,
                          CycleTaskGroupObjectTask.IN_PROGRESS,
                          CycleTaskGroupObjectTask.FINISHED,
                          CycleTaskGroupObjectTask.DECLINED]
      final_state = CycleTaskGroupObjectTask.VERIFIED
    else:
      non_final_states = [CycleTaskGroupObjectTask.ASSIGNED,
                          CycleTaskGroupObjectTask.IN_PROGRESS]
      final_state = CycleTaskGroupObjectTask.FINISHED

    with freeze_time("2017-05-16 08:09:10"):  # a day after task1 due date
      for state in non_final_states:
        # clear all notifications before before changing the task status
        models.Notification.query.delete()
        _, notif_data = common.get_daily_notifications()
        self.assertEqual(notif_data, {})

        self.wf_generator.modify_object(task1, {"status": state})

        _, notif_data = common.get_daily_notifications()
        user_notifs = notif_data.get(user_email, {})
        self.assertIn("task_overdue", user_notifs)
        self.assertEqual(len(user_notifs["task_overdue"]), 1)

      # WITHOUT clearing the overdue notifications, move the task to "verified"
      # state, and the overdue notification should disappear.

      self.wf_generator.modify_object(task1, {"status": final_state})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertNotIn("task_overdue", user_notifs)

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_stop_sending_overdue_notification_if_task_gets_deleted(self,
                                                                  is_vf_needed,
                                                                  _):
    """Overdue notifications should not be sent for deleted tasks."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    tasks = workflow.cycles[0].cycle_task_group_object_tasks
    task1, task2 = tasks

    user = models.Person.query.get(self.user.id)
    user_email = user.email

    with freeze_time("2017-10-16 08:09:10"):  # long after both task due dates
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 2)

      db.session.delete(task2)
      db.session.commit()

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

      db.session.delete(task1)
      db.session.commit()

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

  def _create_test_cases(self):
    """Create configuration to use for generating a new workflow."""
    def person_dict(person_id):
      return {
          "href": "/api/people/" + str(person_id),
          "id": person_id,
          "type": "Person"
      }
    role_id = models.all_models.AccessControlRole.query.filter(
        models.all_models.AccessControlRole.name == "Task Assignees",
        models.all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    self.one_time_workflow = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "start_date": date(2017, 5, 5),  # Friday
                "end_date": date(2017, 5, 15),
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
            }, {
                "title": "task 2",
                "description": "some task 2",
                "start_date": date(2017, 5, 5),  # Friday
                "end_date": date(2017, 5, 16),
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
            }],
            "task_group_objects": self.random_objects
        }]
    }
コード例 #38
0
class TestCreator(TestCase):
  """ TestCreator """

  def setUp(self):
    super(TestCreator, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """

    users = [("creator", "Creator"), ("admin", "Administrator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def test_admin_page_access(self):
    """Permissions to admin page."""
    for role, code in (("creator", 403), ("admin", 200)):
      self.api.set_user(self.users[role])
      self.assertEqual(self.api.client.get("/admin").status_code, code)

  def test_creator_can_crud(self):
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["creator"])
    creator_id = self.users["creator"].id
    audit_id = factories.AuditFactory().id
    all_errors = []
    base_models = set([
        "Control", "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "Clause", "System", "Process", "Project", "AccessGroup",
        "Metric"
    ])
    for model_singular in base_models:
      try:
        model = get_model(model_singular)
        table_singular = model._inflector.table_singular
        table_plural = model._inflector.table_plural
        # Test POST creation
        response = self.api.post(model, {
            table_singular: {
                "title": model_singular,
                "context": None,
                "documents_reference_url": "ref",
                "link": "https://example.com",  # ignored except for Document
                "contact": {
                    "type": "Person",
                    "id": creator_id,
                },
                "audit": {  # this is ignored on everything but Issues
                    "id": audit_id,
                    "type": "Audit",
                }
            },
        })
        if response.status_code != 201:
          all_errors.append("{} post creation failed {} {}".format(
              model_singular, response.status, response.data))
          continue

        # Test GET when not owner
        obj_id = response.json.get(table_singular).get("id")
        response = self.api.get(model, obj_id)
        if response.status_code != 403:  # we are not onwers yet
          all_errors.append(
              "{} can retrieve object if not owner".format(model_singular))
          continue
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if collection:
          all_errors.append(
              "{} can retrieve object if not owner (collection)"
              .format(model_singular))
          continue

        # Test GET when owner
        acr = all_models.AccessControlRole.query.filter_by(
            object_type=model_singular,
            name="Admin"
        ).first()
        factories.AccessControlListFactory(
            object_id=obj_id,
            object_type=model_singular,
            ac_role=acr,
            person_id=creator_id
        )
        response = self.api.get(model, obj_id)
        if response.status_code != 200:
          all_errors.append("{} can't GET object {}".format(
              model_singular, response.status))
          continue

        # Test GET collection when owner
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if not collection:
          all_errors.append(
              "{} cannot retrieve object even if owner (collection)"
              .format(model_singular))
          continue
      except:
        all_errors.append("{} exception thrown".format(model_singular))
        raise
    self.assertEqual(all_errors, [])

  def test_creator_search(self):
    """Test if creator can see the correct object while using the search api"""
    self.api.set_user(self.users['admin'])
    self.api.post(all_models.Regulation, {
        "regulation": {"title": "Admin regulation", "context": None},
    })
    self.api.set_user(self.users['creator'])
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="Policy",
        name="Admin"
    ).first().id
    response = self.api.post(all_models.Policy, {
        "policy": {
            "title": "Creator Policy",
            "context": None,
            "access_control_list": [
                acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
        },
    })
    response.json.get("policy").get("id")
    response, _ = self.api.search("Regulation,Policy")
    entries = response.json["results"]["entries"]
    self.assertEqual(len(entries), 1)
    self.assertEqual(entries[0]["type"], "Policy")
    response, _ = self.api.search("Regulation,Policy", counts=True)
    self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
    self.assertEqual(
        response.json["results"]["counts"].get("Regulation"), None)

  def _get_count(self, obj):
    """ Return the number of counts for the given object from search """
    response, _ = self.api.search(obj, counts=True)
    return response.json["results"]["counts"].get(obj)

  def test_creator_should_see_users(self):
    """ Test if creator can see all the users in the system """
    self.api.set_user(self.users['admin'])
    admin_count = self._get_count("Person")
    self.api.set_user(self.users['creator'])
    creator_count = self._get_count("Person")
    self.assertEqual(admin_count, creator_count)

  def test_relationships_access(self):
    """Check if creator cannot access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, obj_0 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    _, obj_1 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation 2", "context": None},
    })
    response, rel = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"source": {
                "id": obj_0.id,
                "type": "Regulation"
            }, "destination": {
                "id": obj_1.id,
                "type": "Regulation"
            }, "context": None},
        }
    )
    relationship_id = rel.id
    self.assertEqual(response.status_code, 201)
    self.api.set_user(self.users['creator'])
    response = self.api.get_collection(all_models.Relationship,
                                       relationship_id)
    self.assertEqual(response.status_code, 200)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 0)

  def test_revision_access(self):
    """Check if creator can access the right revision objects."""

    def gen(title, extra_data=None):
      """Generates section."""
      section_content = {"title": title, "context": None}
      if extra_data:
        section_content.update(**extra_data)
      return self.generator.generate(all_models.Section, "section", {
          "section": section_content
      })[1]

    def check(obj, expected):
      """Check that how many revisions of an object current user can see."""
      response = self.api.get_query(
          all_models.Revision,
          "resource_type={}&resource_id={}".format(obj.type, obj.id)
      )
      self.assertEqual(response.status_code, 200)
      self.assertEqual(
          len(response.json['revisions_collection']['revisions']),
          expected
      )

    self.api.set_user(self.users["admin"])
    obj_1 = gen("Test Section 1")

    self.api.set_user(self.users["creator"])
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="Section",
        name="Admin"
    ).first().id
    linked_acl = {
        "access_control_list": [
            acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
    }
    check(obj_1, 0)
    obj_2 = gen("Test Section 2", linked_acl)
    obj2_acl = obj_2.access_control_list[0]
    check(obj_2, 1)
    check(obj2_acl, 1)

  @ddt.data("creator", "admin")
  def test_count_type_in_accordion(self, glob_role):
    """Return count of Persons in DB for side accordion."""
    self.api.set_user(self.users[glob_role])
    ocordion_api_person_count_link = (
        "/search?"
        "q=&types=Program%2CWorkflow_All%2C"
        "Audit%2CAssessment%2CIssue%2CRegulation%2C"
        "Policy%2CStandard%2CContract%2CClause%2CSection%2CControl%2C"
        "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C"
        "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C"
        "Market%2CRisk%2CThreat&counts_only=true&"
        "extra_columns=Workflow_All%3DWorkflow%2C"
        "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D"
        "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&"
        "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active"
        "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D"
        "Inactive%3BWorkflow_Draft%3Astatus%3DDraft"
    )
    resp = self.api.client.get(ocordion_api_person_count_link)
    self.assertIn("Person", resp.json["results"]["counts"])
    self.assertEqual(all_models.Person.query.count(),
                     resp.json["results"]["counts"]["Person"])

  @ddt.data(
      ("/api/revisions?resource_type={}&resource_id={}", 1),
      ("/api/revisions?source_type={}&source_id={}", 0),
      ("/api/revisions?destination_type={}&destination_id={}", 1),
  )
  @ddt.unpack
  def test_changelog_access(self, link, revision_count):
    """Test accessing changelog under GC user who is assigned to object"""
    with factories.single_commit():
      audit = factories.AuditFactory()
      asmnt = factories.AssessmentFactory(audit=audit)
      asmnt_id = asmnt.id
      factories.RelationshipFactory(source=audit, destination=asmnt)
      verifier_role = all_models.AccessControlRole.query.filter_by(
          object_type="Assessment",
          name="Verifiers",
      ).first()
      factories.AccessControlListFactory(
          person=self.users["creator"],
          ac_role=verifier_role,
          object=asmnt,
      )

    self.api.set_user(self.users["creator"])
    response = self.api.client.get(link.format("Assessment", asmnt_id))
    self.assert200(response)
    self.assertEqual(
        len(response.json.get("revisions_collection", {}).get("revisions")),
        revision_count
    )

  @ddt.data(all_models.ControlCategory, all_models.ControlAssertion)
  def test_permissions_for_categories(self, category_model):
    """Test get collection for {0}."""
    self.api.set_user(self.users["creator"])
    resp = self.api.get_collection(category_model, None)
    plural_name = category_model._inflector.table_plural
    key_name = "{}_collection".format(plural_name)
    self.assertIn(key_name, resp.json)
    self.assertIn(plural_name, resp.json[key_name])
    collection = resp.json[key_name][plural_name]
    self.assertTrue(collection, "Collection shouldn't be empty")
コード例 #39
0
class TestCreator(TestCase):
    """ TestCreator """
    def setUp(self):
        super(TestCreator, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """

        users = [("creator", "Creator"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        """Permissions to admin page."""
        for role, code in (("creator", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.client.get("/admin").status_code, code)

    def test_creator_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["creator"])
        creator_id = self.users["creator"].id
        audit_id = factories.AuditFactory().id
        all_errors = []
        base_models = {
            "Control", "DataAsset", "Contract", "Policy", "Regulation",
            "Standard", "Document", "Facility", "Market", "Objective",
            "OrgGroup", "Vendor", "Product", "Clause", "System", "Process",
            "Project", "AccessGroup", "Metric", "ProductGroup",
            "TechnologyEnvironment"
        }
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response = self.api.post(model, {
                    table_singular: {
                        "title": model_singular,
                        "context": None,
                        "documents_reference_url": "ref",
                        "link": "https://example.com",  # ignored except for Document
                        "contact": {
                            "type": "Person",
                            "id": creator_id,
                        },
                        "audit": {  # this is ignored on everything but Issues
                            "id": audit_id,
                            "type": "Audit",
                        }
                    },
                })
                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                # Test GET when not owner
                obj_id = response.json.get(table_singular).get("id")
                response = self.api.get(model, obj_id)
                if response.status_code != 403:  # we are not onwers yet
                    all_errors.append(
                        "{} can retrieve object if not owner".format(
                            model_singular))
                    continue
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if collection:
                    all_errors.append(
                        "{} can retrieve object if not owner (collection)".
                        format(model_singular))
                    continue

                # Test GET when owner
                acr = all_models.AccessControlRole.query.filter_by(
                    object_type=model_singular, name="Admin").first()
                factories.AccessControlListFactory(object_id=obj_id,
                                                   object_type=model_singular,
                                                   ac_role=acr,
                                                   person_id=creator_id)
                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if not collection:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_creator_search(self):
        """Test if creator can see the correct object while using the search api"""
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['creator'])
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="Policy", name="Admin").first().id
        response = self.api.post(
            all_models.Policy, {
                "policy": {
                    "title":
                    "Creator Policy",
                    "context":
                    None,
                    "access_control_list": [
                        acl_helper.get_acl_json(acr_id,
                                                self.users["creator"].id)
                    ],
                },
            })
        response.json.get("policy").get("id")
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 1)
        self.assertEqual(entries[0]["type"], "Policy")
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"].get("Regulation"),
                         None)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_creator_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['creator'])
        creator_count = self._get_count("Person")
        self.assertEqual(admin_count, creator_count)

    def test_relationships_access(self):
        """Check if creator cannot access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['creator'])
        response = self.api.get_collection(all_models.Relationship,
                                           relationship_id)
        self.assertEqual(response.status_code, 200)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 0)

    def test_revision_access(self):
        """Check if creator can access the right revision objects."""
        def gen(title, extra_data=None):
            """Generates requirement."""
            requirement_content = {"title": title, "context": None}
            if extra_data:
                requirement_content.update(**extra_data)
            return self.generator.generate(
                all_models.Requirement, "requirement",
                {"requirement": requirement_content})[1]

        def check(obj, expected):
            """Check that how many revisions of an object current user can see."""
            response = self.api.get_query(
                all_models.Revision,
                "resource_type={}&resource_id={}".format(obj.type, obj.id))
            self.assertEqual(response.status_code, 200)
            self.assertEqual(
                len(response.json['revisions_collection']['revisions']),
                expected)

        self.api.set_user(self.users["admin"])
        obj_1 = gen("Test Requirement 1")

        self.api.set_user(self.users["creator"])
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="Requirement", name="Admin").first().id
        linked_acl = {
            "access_control_list":
            [acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
        }
        check(obj_1, 0)
        obj_2 = gen("Test Requirement 2", linked_acl)
        obj2_acl = obj_2.access_control_list[0]
        check(obj_2, 1)
        check(obj2_acl, 1)

    @ddt.data("creator", "admin")
    def test_count_type_in_accordion(self, glob_role):
        """Return count of Persons in DB for side accordion."""
        self.api.set_user(self.users[glob_role])
        ocordion_api_person_count_link = (
            "/search?"
            "q=&types=Program%2CWorkflow_All%2C"
            "Audit%2CAssessment%2CIssue%2CRegulation%2C"
            "Policy%2CStandard%2CContract%2CClause%2CRequirement%2CControl%2C"
            "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C"
            "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C"
            "Market%2CRisk%2CThreat&counts_only=true&"
            "extra_columns=Workflow_All%3DWorkflow%2C"
            "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D"
            "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&"
            "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active"
            "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D"
            "Inactive%3BWorkflow_Draft%3Astatus%3DDraft")
        resp = self.api.client.get(ocordion_api_person_count_link)
        self.assertIn("Person", resp.json["results"]["counts"])
        self.assertEqual(all_models.Person.query.count(),
                         resp.json["results"]["counts"]["Person"])

    @ddt.data(
        ("/api/revisions?resource_type={}&resource_id={}", 1),
        ("/api/revisions?source_type={}&source_id={}", 0),
        ("/api/revisions?destination_type={}&destination_id={}", 1),
    )
    @ddt.unpack
    def test_changelog_access(self, link, revision_count):
        """Test accessing changelog under GC user who is assigned to object"""
        with factories.single_commit():
            audit = factories.AuditFactory()
            asmnt = factories.AssessmentFactory(audit=audit)
            asmnt_id = asmnt.id
            factories.RelationshipFactory(source=audit, destination=asmnt)
            verifier_role = all_models.AccessControlRole.query.filter_by(
                object_type="Assessment",
                name="Verifiers",
            ).first()
            factories.AccessControlListFactory(
                person=self.users["creator"],
                ac_role=verifier_role,
                object=asmnt,
            )

        self.api.set_user(self.users["creator"])
        response = self.api.client.get(link.format("Assessment", asmnt_id))
        self.assert200(response)
        self.assertEqual(
            len(
                response.json.get("revisions_collection",
                                  {}).get("revisions")), revision_count)

    @ddt.data(all_models.ControlCategory, all_models.ControlAssertion)
    def test_permissions_for_categories(self, category_model):
        """Test get collection for {0}."""
        self.api.set_user(self.users["creator"])
        resp = self.api.get_collection(category_model, None)
        plural_name = category_model._inflector.table_plural
        key_name = "{}_collection".format(plural_name)
        self.assertIn(key_name, resp.json)
        self.assertIn(plural_name, resp.json[key_name])
        collection = resp.json[key_name][plural_name]
        self.assertTrue(collection, "Collection shouldn't be empty")
コード例 #40
0
class TestEvidenceRolePropagation(TestCase):
  """Evidence role propagation test case"""
  # pylint: disable=invalid-name

  def setUp(self):
    super(TestEvidenceRolePropagation, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()

  # Propagation isn't work for 'Primary Contacts', 'Secondary Contacts'
  # just add them to data list to check if fix works.

  @ddt.data("Assignees", "Creators", "Verifiers")
  def test_assessment_role_propagation_edit(self, role_name):
    """Asses user with role '{0}' should be able to edit related evidence"""

    _, reader = self.generator.generate_person(user_role="Creator")
    with factories.single_commit():
      assessment = factories.AssessmentFactory()
      assessment.add_person_with_role_name(reader, role_name)
      evidence = factories.EvidenceFactory()
      evidence_id = evidence.id
      factories.RelationshipFactory(source=assessment, destination=evidence)

    self.api.set_user(reader)

    evidence = all_models.Evidence.query.get(evidence_id)
    new_description = 'new description'
    resp = self.api.modify_object(evidence, {'description': new_description})
    evidence = self.refresh_object(evidence)
    self.assert200(resp)
    self.assertEquals(new_description, evidence.description)
    self.assertEquals(reader.id, evidence.modified_by_id)

  @ddt.data(
      ("Creator", "Audit Captains", 200),
      ("Creator", "Auditors", 403),
      ("Reader", "Audit Captains", 200),
      ("Reader", "Auditors", 403),
      ("Editor", "Audit Captains", 200),
      ("Editor", "Auditors", 200),
  )
  @ddt.unpack
  def test_audit_role_propagation_edit(self, user_role, audit_role,
                                       status_code):
    """'{0}' assigned as '{1}' should get '{2}' when editing audit evidence"""
    _, user = self.generator.generate_person(user_role=user_role)
    with factories.single_commit():
      audit = factories.AuditFactory()
      audit.add_person_with_role_name(user, audit_role)
      evidence = factories.EvidenceFactory()
      evidence_id = evidence.id

    factories.RelationshipFactory(source=audit, destination=evidence)

    self.api.set_user(user)

    evidence = all_models.Evidence.query.get(evidence_id)
    new_description = 'new description'
    resp = self.api.modify_object(evidence, {'description': new_description})
    evidence = self.refresh_object(evidence)

    if status_code == 200:
      self.assert200(resp)
      self.assertEquals(new_description, evidence.description)
      self.assertEquals(user.id, evidence.modified_by_id)
    else:
      self.assertStatus(resp, status_code)

  def test_audit_role_propagation_not_delete(self):
    """Audit user with role Auditors can NOT delete related evidence"""
    role_name = "Auditors"
    _, reader = self.generator.generate_person(user_role="Reader")
    with factories.single_commit():
      audit = factories.AuditFactory()
      audit.add_person_with_role_name(reader, role_name)
      evidence = factories.EvidenceFactory()
      evidence_id = evidence.id

    factories.RelationshipFactory(source=audit, destination=evidence)

    self.api.set_user(reader)
    evidence = all_models.Evidence.query.get(evidence_id)

    resp = self.api.delete(evidence)
    self.assertStatus(resp, 403)
    evidence = all_models.Evidence.query.get(evidence_id)
    self.assertTrue(evidence)
コード例 #41
0
ファイル: test_creator.py プロジェクト: jasonray716/ggrc-core
class TestCreator(TestCase):
    """ TestCreator """
    def setUp(self):
        super(TestCreator, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """

        users = [("creator", "Creator"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        for role, code in (("creator", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.tc.get("/admin").status_code, code)

    def test_creator_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["creator"])
        all_errors = []
        base_models = set([
            "Control", "DataAsset", "Contract", "Policy", "Regulation",
            "Standard", "Document", "Facility", "Market", "Objective",
            "OrgGroup", "Vendor", "Product", "Clause", "System", "Process",
            "Issue", "Project", "AccessGroup"
        ])
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response = self.api.post(
                    model, {
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "reference_url": "ref",
                            "contact": {
                                "type": "Person",
                                "id": self.users["creator"].id,
                            },
                        },
                    })
                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                # Test GET when not owner
                obj_id = response.json.get(table_singular).get("id")
                response = self.api.get(model, obj_id)
                if response.status_code != 403:  # we are not onwers yet
                    all_errors.append(
                        "{} can retrieve object if not owner".format(
                            model_singular))
                    continue
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if len(collection) != 0:
                    all_errors.append(
                        "{} can retrieve object if not owner (collection)".
                        format(model_singular))
                    continue
                # Become an owner
                response = self.api.post(
                    all_models.ObjectOwner, {
                        "object_owner": {
                            "person": {
                                "id": self.users['creator'].id,
                                "type": "Person",
                            },
                            "ownable": {
                                "type": model_singular,
                                "id": obj_id
                            },
                            "context": None
                        }
                    })
                if response.status_code != 201:
                    all_errors.append("{} can't create owner {}.".format(
                        model_singular, response.status))
                    continue

                # Test GET when owner
                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if len(collection) == 0:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_creator_search(self):
        """Test if creator can see the correct object while using the search api"""
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['creator'])
        response = self.api.post(all_models.Policy, {
            "policy": {
                "title": "Creator Policy",
                "context": None
            },
        })
        obj_id = response.json.get("policy").get("id")
        self.api.post(
            all_models.ObjectOwner, {
                "object_owner": {
                    "person": {
                        "id": self.users['creator'].id,
                        "type": "Person",
                    },
                    "ownable": {
                        "type": "Policy",
                        "id": obj_id,
                    },
                    "context": None
                }
            })
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 1)
        self.assertEqual(entries[0]["type"], "Policy")
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"].get("Regulation"),
                         None)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_creator_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['creator'])
        creator_count = self._get_count("Person")
        self.assertEqual(admin_count, creator_count)

    def test_creator_cannot_be_owner(self):
        """Test if creator cannot become owner of the object he has not created"""
        self.api.set_user(self.users['admin'])
        _, obj = self.generator.generate(all_models.Regulation, "regulation", {
            "regulation": {
                "title": "Test regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['creator'])
        response = self.api.post(
            all_models.ObjectOwner, {
                "object_owner": {
                    "person": {
                        "id": self.users['creator'].id,
                        "type": "Person",
                    },
                    "ownable": {
                        "type": "Regulation",
                        "id": obj.id,
                    },
                    "context": None
                }
            })
        self.assertEqual(response.status_code, 403)

    def test_relationships_access(self):
        """Check if creator cannot access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['creator'])
        response = self.api.get_collection(all_models.Relationship,
                                           relationship_id)
        self.assertEqual(response.status_code, 200)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 0)

    def test_revision_access(self):
        """Check if creator can access the right revision objects."""
        def gen(title):
            return self.generator.generate(all_models.Section, "section", {
                "section": {
                    "title": title,
                    "context": None
                },
            })[1]

        def check(obj, expected):
            """Check that how many revisions of an object current user can see."""
            response = self.api.get_query(
                all_models.Revision,
                "resource_type={}&resource_id={}".format(obj.type, obj.id))
            self.assertEqual(response.status_code, 200)
            self.assertEqual(
                len(response.json['revisions_collection']['revisions']),
                expected)

        self.api.set_user(self.users["admin"])
        obj_1 = gen("Test Section 1")
        obj_2 = gen("Test Section 2")

        self.api.post(
            all_models.ObjectOwner, {
                "object_owner": {
                    "person": {
                        "id": self.users['creator'].id,
                        "type": "Person",
                    },
                    "ownable": {
                        "type": "Section",
                        "id": obj_2.id,
                    },
                    "context": None
                }
            })

        self.api.set_user(self.users["creator"])
        check(obj_1, 0)
        check(obj_2, 2)
コード例 #42
0
class TestReader(TestCase):
    """Test Assignable RBAC"""
    def setUp(self):
        super(TestReader, self).setUp()
        self.audit_id = factories.AuditFactory().id
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_assignable()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("creator", "Creator"), ("reader", "Reader"),
                 ("editor", "Editor"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def init_assignable(self):
        """Creates the assignable object used by all the tests"""
        self.api.set_user(self.users["editor"])
        response = self.api.post(
            all_models.Assessment, {
                "assessment": {
                    "title": "Assessment",
                    "context": None,
                    "audit": {
                        "id": self.audit_id,
                        "type": "Audit"
                    }
                }
            })
        obj_id = response.json.get("assessment").get("id")
        self.assertEqual(response.status_code, 201,
                         "Error setting up Assessment")
        self.obj_json = response.json
        self.obj = all_models.Assessment.query.get(obj_id)

    def _add_creator(self, asmnt, user):
        """Helper method for creating assignees on an object"""
        acr = all_models.AccessControlRole.query.filter(
            all_models.AccessControlRole.object_type == "Assessment",
            all_models.AccessControlRole.name == "Creators",
        ).first()
        return self.api.put(
            asmnt, {
                "access_control_list": [{
                    "ac_role_id": acr.id,
                    "person": {
                        "id": user.id
                    },
                    "type": "AccessControlList",
                }]
            })

    def test_basic_with_no_assignee(self):
        """Editor creates an Assessment, but doesn't assign Reader/Creator as
       assignee. Reader should have Read access, Creator should have no access
    """

        # Reader should have read access, but shouldn't be allowed to edit or
        # create another assingee
        self.api.set_user(self.users["reader"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, self.obj_json)
        self.assertEqual(response.status_code, 403)
        response = self._add_creator(self.obj, self.users["reader"])
        self.assertEqual(response.status_code, 403)

        # Creator should have no access. We skip the put request because we can't
        # get the object etag.
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 403)
        response = self._add_creator(self.obj, self.users["reader"])
        self.assertEqual(response.status_code, 403)

    def test_basic_with_assignee(self):
        """Test if Reader/Creator have CRUD access once they become assignees"""

        # Admin adds reader as an assignee
        self.api.set_user(self.users["admin"])
        response = self._add_creator(self.obj, self.users["reader"])
        self.assertEqual(response.status_code, 200)

        # Reader is now allowed to update the object
        self.api.set_user(self.users["reader"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, response.json)
        self.assertEqual(response.status_code, 200)

        # Reader adds creator as an assignee
        response = self._add_creator(self.obj, self.users["creator"])
        self.assertEqual(response.status_code, 200)

        # Creator now has CRUD access
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, response.json)

        # Creator should even be allowed to add new assignees
        response = self._add_creator(self.obj, self.users["admin"])
        self.assertEqual(response.status_code, 200)

    def test_read_of_mapped_objects(self):
        """Test if assignees get Read access on all mapped objects"""

        # Editor creates a System object and maps it to the assignable object
        self.api.set_user(self.users["editor"])
        response = self.api.post(
            all_models.System,
            {"system": {
                "title": "System",
                "context": None,
            }})
        system_id = response.json.get("system").get("id")
        system = all_models.System.query.get(system_id)
        self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": self.obj.id,
                        "type": "Assessment"
                    },
                    "destination": {
                        "id": system_id,
                        "type": "System"
                    },
                    "context": None
                },
            })

        # Since creator is not an assignee she should not have access to any of the
        # two objects
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 403)
        response = self.api.get(all_models.System, system_id)
        self.assertEqual(response.status_code, 403)

        # Editor adds creator as an assignee
        self.api.set_user(self.users["editor"])
        response = self._add_creator(self.obj, self.users["creator"])
        self.assertEqual(response.status_code, 200)

        # Creator should now have read access on the mapped object
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.System, system_id)
        self.assertEqual(response.status_code, 200)

        # But he should still not be allowed to update
        response = self.api.put(system, response.json)
        self.assertEqual(response.status_code, 403)
コード例 #43
0
class TestReader(TestCase):
  """ Test reader role """

  def setUp(self):
    super(TestReader, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("reader", "Reader"),
             ("admin", "Administrator"),
             ("creator", "Creator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

    self.users["external"] = self.object_generator.generate_person(
        data={"email": "*****@*****.**"})[1]

  def test_admin_page_access(self):
    """Only admin can use admin requirement"""
    for role, code in (("reader", 403), ("admin", 200)):
      self.api.set_user(self.users[role])
      self.assertEqual(self.api.client.get("/admin").status_code, code)

  def test_reader_can_crud(self):
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["reader"])
    all_errors = []
    base_models = set([
        "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "System", "Process", "Project", "AccessGroup",
        "Metric", "TechnologyEnvironment", "ProductGroup", "KeyReport",
        "AccountBalance",
    ])
    for model_singular in base_models:
      try:
        model = get_model(model_singular)
        table_singular = model._inflector.table_singular
        table_plural = model._inflector.table_plural
        # Test POST creation
        response, _ = self.object_generator.generate_object(
            model,
            data={
                table_singular: {
                    "title": model_singular,
                    "context": None,
                    "documents_reference_url": "ref",
                    "link": "https://example.com",  # only for Document
                    "contact": {
                        "type": "Person",
                        "id": self.users["reader"].id,
                    }
                },
            }
        )

        if response.status_code != 201:
          all_errors.append("{} post creation failed {} {}".format(
              model_singular, response.status, response.data))
          continue

        obj_id = response.json.get(table_singular).get("id")

        # Test GET when owner
        response = self.api.get(model, obj_id)
        if response.status_code != 200:
          all_errors.append("{} can't GET object {}".format(
              model_singular, response.status))
          continue

        # Test GET collection when owner
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if not collection:
          all_errors.append(
              "{} cannot retrieve object even if owner (collection)".format(
                  model_singular))
          continue
      except:
        all_errors.append("{} exception thrown".format(model_singular))
        raise
    self.assertEqual(all_errors, [])

  def test_reader_search(self):
    """ Test if reader can see the correct object while using search api """
    self.api.set_user(self.users['admin'])
    self.api.post(all_models.Regulation, {
        "regulation": {"title": "Admin regulation", "context": None},
    })
    self.api.set_user(self.users['reader'])
    response = self.api.post(all_models.Policy, {
        "policy": {"title": "reader Policy", "context": None},
    })
    response, _ = self.api.search("Regulation,Policy")
    entries = response.json["results"]["entries"]
    self.assertEqual(len(entries), 2)
    response, _ = self.api.search("Regulation,Policy", counts=True)
    self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
    self.assertEqual(response.json["results"]["counts"]["Regulation"], 1)

  def _get_count(self, obj):
    """ Return the number of counts for the given object from search """
    response, _ = self.api.search(obj, counts=True)
    return response.json["results"]["counts"].get(obj)

  def test_reader_should_see_users(self):
    """ Test if creator can see all the users in the system """
    self.api.set_user(self.users['admin'])
    admin_count = self._get_count("Person")
    self.api.set_user(self.users['reader'])
    reader_count = self._get_count("Person")
    self.assertEqual(admin_count, reader_count)

  def test_relationships_access(self):
    """Check if reader can access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, first_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation", "context": None}}
    )
    _, second_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation 2", "context": None}}
    )
    response, rel = self.object_generator.generate_relationship(
        first_regulation, second_regulation
    )
    self.assertStatus(response, 201)
    self.api.set_user(self.users['reader'])
    response = self.api.get_collection(all_models.Relationship, rel.id)
    self.assert200(response)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 1)

  def test_creation_of_mappings(self):
    """Check if reader can't create mappings"""
    self.object_generator.api.set_user(self.users["external"])
    _, control = self.object_generator.generate_object(
        all_models.Control,
        data={"control": {"title": "Test Control", "context": None}}
    )

    self.object_generator.api.set_user(self.users['reader'])
    _, program = self.object_generator.generate_object(
        all_models.Program,
        data={"program": {"title": "Test Program", "context": None}}
    )

    response, _ = self.object_generator.generate_relationship(
        control, program, program.context
    )
    self.assert403(response)

  @ddt.data("creator", "reader")
  def test_unmap_people(self, user_role):
    """Test that global reader/creator can't unmap people from program"""
    user = self.users[user_role]
    with factories.single_commit():
      program = factories.ProgramFactory()
      mapped_person = factories.ObjectPersonFactory(
          personable=program, person=user, context=program.context
      )
    self.api.set_user(user)
    db.session.add(mapped_person)
    response = self.api.delete(mapped_person)
    self.assert403(response)

  def test_read_evidence_revision(self):
    """Global Read can read Evidence revision content"""
    user = self.users["reader"]
    link = "google.com"
    evidence = factories.EvidenceUrlFactory(link=link)
    evidence_id = evidence.id
    self.api.set_user(user)
    resp = self.api.client.get(
        "/api/revisions?resource_type={}&resource_id={}".format(evidence.type,
                                                                evidence_id))
    rev_content = resp.json["revisions_collection"]["revisions"][0]["content"]
    self.assertTrue(rev_content)
    self.assertEquals(link, rev_content["link"])
コード例 #44
0
class TestCycleTaskImportUpdate(TestCase):
    """ This class contains simple cycle task update tests using import
  functionality
  """

    CSV_DIR = join(abspath(dirname(__file__)), "test_csvs/")

    def setUp(self):
        super(TestCycleTaskImportUpdate, self).setUp()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        self.random_objects = self.object_generator.generate_random_objects(2)
        _, self.person_1 = self.object_generator.generate_person(
            user_role="Administrator")
        self.ftime_active = "2016-07-01"
        self.ftime_historical = "2014-05-01"
        self._create_test_cases_data()
        # It is needed because cycle-tasks are generated automatically with
        # 'slug' based on auto_increment 'id' field.
        # At start of each test we suppose that created cycle-task's 'slug'
        # lie in range from 1 to 10.
        db.session.execute('ALTER TABLE cycle_task_group_object_tasks '
                           'AUTO_INCREMENT = 1')

    def test_cycle_task_correct(self):
        """Test cycle task update via import with correct data"""
        self._generate_cycle_tasks()
        with freeze_time(self.ftime_active):
            response = self.import_file("cycle_task_correct.csv")
            self._check_csv_response(response, {})
            self._cmp_tasks(self.expected_cycle_task_correct)

    def test_cycle_task_warnings(self):
        """Test cycle task update via import with data which is the reason of
    warnings about non-importable columns."""
        self._generate_cycle_tasks()
        with freeze_time(self.ftime_active):
            response = self.import_file("cycle_task_warnings.csv")
            self._check_csv_response(response, self.expected_warnings)
            self._cmp_tasks(self.expected_cycle_task_correct)

    def test_cycle_task_create_error(self):
        """Test cycle task update via import with data which is the reason of
    errors about new cycle task creation."""
        self._generate_cycle_tasks()
        with freeze_time(self.ftime_active):
            response = self.import_file("cycle_task_create_error.csv")
            self._check_csv_response(response, self.expected_create_error)
            self._cmp_tasks(self.expected_cycle_task_correct)

    def test_cycle_task_date_error(self):
        """Test cycle task update via import with data which is the reason of
    errors about incorrect dates in csv file."""
        self._generate_cycle_tasks()
        with freeze_time(self.ftime_active):
            response = self.import_file("cycle_task_date_error.csv")
            self._check_csv_response(response, self.expected_date_error)
            self._cmp_tasks(self.expected_cycle_task_date_error)

    def test_cycle_task_permission_error(self):
        """Test cycle task update via import with non-admin user which is the
    reason of error. Only admin can update cycle tasks via import."""
        self._generate_cycle_tasks()
        with freeze_time(self.ftime_active):
            _, creator = self.object_generator.generate_person(
                user_role="Creator")
            response = self.import_file("cycle_task_correct.csv",
                                        person=creator)
            self._check_csv_response(response, self.expected_permission_error)
            # Cycle tasks' data shouldn't be changed in test DB after import run from
            # non-admin user
            expected_cycle_task_permission_error = {}
            expected_cycle_task_permission_error.update(
                self.generated_cycle_tasks_active)
            expected_cycle_task_permission_error.update(
                self.generated_cycle_tasks_historical)
            self._cmp_tasks(expected_cycle_task_permission_error)

    def _cmp_tasks(self, expected_ctasks):
        """Compare tasks values from argument's list and test DB."""
        for ctask in db.session.query(CycleTaskGroupObjectTask).all():
            if ctask.slug not in expected_ctasks:
                continue
            exp_task = expected_ctasks[ctask.slug]
            for attr, val in exp_task.iteritems():
                self.assertEqual(str(getattr(ctask, attr, None)), val)

    # pylint: disable=too-many-arguments
    def _activate_workflow(self, ftime, workflow, task_group, task_group_tasks,
                           random_object, cycle_tasks):
        """Helper which is responsible for active cycle-tasks creation"""
        with freeze_time(ftime):
            _, wf = self.wf_generator.generate_workflow(workflow)
            _, tg = self.wf_generator.generate_task_group(wf, task_group)
            for task in task_group_tasks:
                self.wf_generator.generate_task_group_task(tg, task)
            self.wf_generator.generate_task_group_object(tg, random_object)

            _, cycle = self.wf_generator.generate_cycle(wf)
            self.wf_generator.activate_workflow(wf)

            for exp_slug, exp_task in cycle_tasks.iteritems():
                obj = db.session.query(CycleTaskGroupObjectTask).filter_by(
                    slug=exp_slug).first()
                if exp_task["status"] == "Verified":
                    self.wf_generator.modify_object(obj,
                                                    {"status": "Finished"})
                self.wf_generator.modify_object(obj,
                                                {"status": exp_task["status"]})
        self._cmp_tasks(cycle_tasks)
        return cycle

    def _generate_cycle_tasks(self):
        """Helper which is responsible for test data creation"""
        self._activate_workflow(self.ftime_active, self.workflow_active,
                                self.task_group_active,
                                self.task_group_tasks_active,
                                self.random_objects[0],
                                self.generated_cycle_tasks_active)
        cycle = self._activate_workflow(self.ftime_historical,
                                        self.workflow_historical,
                                        self.task_group_historical,
                                        self.task_group_tasks_historical,
                                        self.random_objects[1],
                                        self.generated_cycle_tasks_historical)
        with freeze_time(self.ftime_historical):
            cycle = Cycle.query.get(cycle.id)
            self.wf_generator.modify_object(cycle, data={"is_current": False})

    def _create_test_cases_data(self):
        """Create test cases data: for object generation,
    expected data for checks"""
        def person_dict(person_id):
            """Return person data"""
            return {
                "href": "/api/people/%d" % person_id,
                "id": person_id,
                "type": "Person"
            }

        self.workflow_active = {
            "title": "workflow active title",
            "description": "workflow active description",
            "frequency": "one_time",
            "owners": [person_dict(self.person_1.id)],
            "notify_on_change": False,
        }

        self.task_group_active = {
            "title": "task group active title",
            "contact": person_dict(self.person_1.id),
        }

        self.task_group_tasks_active = [{
            "title":
            "task active title 1",
            "description":
            "task active description 1",
            "contact":
            person_dict(self.person_1.id),
            "start_date":
            "07/01/2016",
            "end_date":
            "07/06/2016",
        }, {
            "title":
            "task active title 2",
            "description":
            "task active description 2",
            "contact":
            person_dict(self.person_1.id),
            "start_date":
            "07/07/2016",
            "end_date":
            "07/12/2016",
        }, {
            "title":
            "task active title 3",
            "description":
            "task active description 3",
            "contact":
            person_dict(self.person_1.id),
            "start_date":
            "07/13/2016",
            "end_date":
            "07/18/2016",
        }, {
            "title":
            "task active title 4",
            "description":
            "task active description 4",
            "contact":
            person_dict(self.person_1.id),
            "start_date":
            "07/19/2016",
            "end_date":
            "07/24/2016",
        }, {
            "title":
            "task active title 5",
            "description":
            "task active description 5",
            "contact":
            person_dict(self.person_1.id),
            "start_date":
            "07/25/2016",
            "end_date":
            "07/30/2016",
        }]

        # Active cycle tasks which should be generated from previous structure
        # at the beginning of each test
        self.generated_cycle_tasks_active = {
            "CYCLETASK-1": {
                "title": self.task_group_tasks_active[0]["title"],
                "description": self.task_group_tasks_active[0]["description"],
                "start_date": "2016-07-01",
                "end_date": "2016-07-06",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Assigned"
            },
            "CYCLETASK-2": {
                "title": self.task_group_tasks_active[1]["title"],
                "description": self.task_group_tasks_active[1]["description"],
                "start_date": "2016-07-07",
                "end_date": "2016-07-12",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Declined"
            },
            "CYCLETASK-3": {
                "title": self.task_group_tasks_active[2]["title"],
                "description": self.task_group_tasks_active[2]["description"],
                "start_date": "2016-07-13",
                "end_date": "2016-07-18",
                "finished_date": "None",
                "verified_date": "None",
                "status": "InProgress"
            },
            "CYCLETASK-4": {
                "title": self.task_group_tasks_active[3]["title"],
                "description": self.task_group_tasks_active[3]["description"],
                "start_date": "2016-07-19",
                "end_date": "2016-07-24",
                "finished_date": "2016-07-01 00:00:00",
                "verified_date": "None",
                "status": "Finished"
            },
            "CYCLETASK-5": {
                "title": self.task_group_tasks_active[4]["title"],
                "description": self.task_group_tasks_active[4]["description"],
                "start_date": "2016-07-25",
                "end_date": "2016-07-30",
                "finished_date": "2016-07-01 00:00:00",
                "verified_date": "2016-07-01 00:00:00",
                "status": "Verified"
            }
        }

        self.workflow_historical = {
            "title": "workflow historical title",
            "description": "workflow historical description",
            "frequency": "one_time",
            "owners": [person_dict(self.person_1.id)],
            "notify_on_change": False,
        }

        self.task_group_historical = {
            "title": "task group historical title",
            "contact": person_dict(self.person_1.id),
        }

        self.task_group_tasks_historical = [
            {
                "title": "task historical title 1",
                "description": "task historical description 1",
                "contact": person_dict(self.person_1.id),
                "start_date": "05/01/2014",
                "end_date": "05/06/2014",
            },
            {
                "title": "task historical title 2",
                "description": "task historical description 2",
                "contact": person_dict(self.person_1.id),
                "start_date": "05/07/2014",
                "end_date": "05/12/2014",
            },
            {
                "title": "task historical title 3",
                "description": "task historical description 3",
                "contact": person_dict(self.person_1.id),
                "start_date": "05/13/2014",
                "end_date": "05/18/2014",
            },
            {
                "title": "task historical title 4",
                "description": "task historical description 4",
                "contact": person_dict(self.person_1.id),
                "start_date": "05/19/2014",
                "end_date": "05/24/2014",
            },
            {
                "title": "task historical title 5",
                "description": "task historical description 5",
                "contact": person_dict(self.person_1.id),
                "start_date": "05/25/2014",
                "end_date": "05/30/2014",
            },
        ]

        # Historical cycle tasks which should be generated from previous structure
        # at the beginning of each test.
        self.generated_cycle_tasks_historical = {
            "CYCLETASK-6": {
                "title": self.task_group_tasks_historical[0]["title"],
                "description":
                self.task_group_tasks_historical[0]["description"],
                "start_date": "2014-05-01",
                "end_date": "2014-05-06",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Assigned"
            },
            "CYCLETASK-7": {
                "title": self.task_group_tasks_historical[1]["title"],
                "description":
                self.task_group_tasks_historical[1]["description"],
                "start_date": "2014-05-07",
                "end_date": "2014-05-12",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Declined"
            },
            "CYCLETASK-8": {
                "title": self.task_group_tasks_historical[2]["title"],
                "description":
                self.task_group_tasks_historical[2]["description"],
                "start_date": "2014-05-13",
                "end_date": "2014-05-18",
                "finished_date": "None",
                "verified_date": "None",
                "status": "InProgress"
            },
            "CYCLETASK-9": {
                "title": self.task_group_tasks_historical[3]["title"],
                "description":
                self.task_group_tasks_historical[3]["description"],
                "start_date": "2014-05-19",
                "end_date": "2014-05-24",
                "finished_date": "2014-05-01 00:00:00",
                "verified_date": "None",
                "status": "Finished"
            },
            "CYCLETASK-10": {
                "title": self.task_group_tasks_historical[4]["title"],
                "description":
                self.task_group_tasks_historical[4]["description"],
                "start_date": "2014-05-25",
                "end_date": "2014-05-30",
                "finished_date": "2014-05-01 00:00:00",
                "verified_date": "2014-05-01 00:00:00",
                "status": "Verified"
            }
        }

        # Expected cycle tasks which should be created in correct cycle task update
        # case. It is needed for most tests.
        self.expected_cycle_task_correct = {
            "CYCLETASK-1": {
                "title": self.task_group_tasks_active[0]["title"] + " one",
                "description":
                self.task_group_tasks_active[0]["description"] + " one",
                "start_date": "2016-06-01",
                "end_date": "2016-06-06",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Assigned"
            },
            "CYCLETASK-2": {
                "title": self.task_group_tasks_active[1]["title"] + " two",
                "description":
                self.task_group_tasks_active[1]["description"] + " two",
                "start_date": "2016-06-07",
                "end_date": "2016-06-12",
                "finished_date": "None",
                "verified_date": "None",
                "status": "Declined"
            },
            "CYCLETASK-3": {
                "title": self.task_group_tasks_active[2]["title"] + " three",
                "description":
                self.task_group_tasks_active[2]["description"] + " three",
                "start_date": "2016-06-13",
                "end_date": "2016-06-18",
                "finished_date": "None",
                "verified_date": "None",
                "status": "InProgress"
            },
            "CYCLETASK-4": {
                "title": self.task_group_tasks_active[3]["title"] + " four",
                "description":
                self.task_group_tasks_active[3]["description"] + " four",
                "start_date": "2016-06-19",
                "end_date": "2016-06-24",
                "finished_date": "2016-07-19 00:00:00",
                "verified_date": "None",
                "status": "Finished"
            },
            "CYCLETASK-5": {
                "title": self.task_group_tasks_active[4]["title"] + " five",
                "description":
                self.task_group_tasks_active[4]["description"] + " five",
                "start_date": "2016-06-25",
                "end_date": "2016-06-30",
                "finished_date": "2016-07-25 00:00:00",
                "verified_date": "2016-08-30 00:00:00",
                "status": "Verified"
            },
            "CYCLETASK-6": {
                "title":
                self.task_group_tasks_historical[0]["title"] + " one",
                "description":
                self.task_group_tasks_historical[0]["description"] + " one",
                "start_date":
                "2014-04-01",
                "end_date":
                "2014-04-06",
                "finished_date":
                "2014-05-01 00:00:00",
                "verified_date":
                "2014-06-06 00:00:00",
                "status":
                "Assigned"
            },
            "CYCLETASK-7": {
                "title":
                self.task_group_tasks_historical[1]["title"] + " two",
                "description":
                self.task_group_tasks_historical[1]["description"] + " two",
                "start_date":
                "2014-04-07",
                "end_date":
                "2014-04-12",
                "finished_date":
                "2014-05-07 00:00:00",
                "verified_date":
                "None",
                "status":
                "Declined"
            },
            "CYCLETASK-8": {
                "title":
                self.task_group_tasks_historical[2]["title"] + " three",
                "description":
                self.task_group_tasks_historical[2]["description"] + " three",
                "start_date":
                "2014-04-13",
                "end_date":
                "2014-04-18",
                "finished_date":
                "2014-05-13 00:00:00",
                "verified_date":
                "2014-06-18 00:00:00",
                "status":
                "InProgress"
            },
            "CYCLETASK-9": {
                "title":
                self.task_group_tasks_historical[3]["title"] + " four",
                "description":
                self.task_group_tasks_historical[3]["description"] + " four",
                "start_date":
                "2014-04-19",
                "end_date":
                "2014-04-24",
                "finished_date":
                "2014-05-19 00:00:00",
                "verified_date":
                "None",
                "status":
                "Finished"
            },
            "CYCLETASK-10": {
                "title":
                self.task_group_tasks_historical[4]["title"] + " five",
                "description":
                self.task_group_tasks_historical[4]["description"] + " five",
                "start_date":
                "2014-04-25",
                "end_date":
                "2014-04-30",
                "finished_date":
                "2014-05-25 00:00:00",
                "verified_date":
                "2014-06-30 00:00:00",
                "status":
                "Verified"
            }
        }

        # Below is description of warning for non-importable columns. It is needed
        # for test_cycle_task_warnings.
        importable_column_names = []
        for field_name in CycleTaskGroupObjectTask.IMPORTABLE_FIELDS:
            if field_name == 'slug':
                continue
            # pylint: disable=protected-access
            importable_column_names.append(
                CycleTaskGroupObjectTask._aliases.get(field_name, field_name))
        self.expected_warnings = {
            'Cycle Task Group Object Task': {
                'block_warnings': {
                    errors.ONLY_IMPORTABLE_COLUMNS_WARNING.format(
                        line=2, columns=", ".join(importable_column_names))
                },
            }
        }

        # This is an error message which should be shown during
        # test_cycle_task_create_error test
        self.expected_create_error = {
            'Cycle Task Group Object Task': {
                'row_errors': {errors.CREATE_INSTANCE_ERROR.format(line=13)}
            }
        }

        # Below is expected date errors for test_cycle_task_date_error. They should
        # be shown during date validator's tests.
        self.expected_date_error = {
            'Cycle Task Group Object Task': {
                'row_errors': {
                    errors.INVALID_START_END_DATES.format(
                        line=3,
                        start_date="Start Date",
                        end_date="End Date",
                    ),
                    errors.INVALID_STATUS_DATE_CORRELATION.format(
                        line=4,
                        date="Actual Finish Date",
                        status="not Finished",
                    ),
                    errors.INVALID_STATUS_DATE_CORRELATION.format(
                        line=5,
                        date="Actual Verified Date",
                        status="not Verified",
                    ),
                    errors.INVALID_STATUS_DATE_CORRELATION.format(
                        line=6,
                        date="Actual Verified Date",
                        status="not Verified",
                    ),
                    errors.INVALID_START_END_DATES.format(
                        line=7,
                        start_date="Actual Finish Date",
                        end_date="Actual Verified Date",
                    ),
                    errors.INVALID_START_END_DATES.format(
                        line=8,
                        start_date="Start Date",
                        end_date="End Date",
                    ),
                    errors.MISSING_VALUE_ERROR.format(
                        line=9,
                        column_name="Actual Finish Date",
                    ),
                    errors.INVALID_START_END_DATES.format(
                        line=10,
                        start_date="Actual Finish Date",
                        end_date="Actual Verified Date",
                    ),
                },
            }
        }
        # Below is expected cycle-tasks data which should appear in test DB after
        # test_cycle_task_date_error run
        self.expected_cycle_task_date_error = dict()
        self.expected_cycle_task_date_error.update(
            self.generated_cycle_tasks_active)
        self.expected_cycle_task_date_error.update(
            self.generated_cycle_tasks_historical)
        self.expected_cycle_task_date_error["CYCLETASK-9"] = (
            self.expected_cycle_task_correct["CYCLETASK-9"])
        self.expected_cycle_task_date_error["CYCLETASK-10"] = (
            self.expected_cycle_task_correct["CYCLETASK-10"])

        # Expected error message which should be shown after
        # test_cycle_task_permission_error run
        self.expected_permission_error = {
            'Cycle Task Group Object Task': {
                'block_errors': {errors.PERMISSION_ERROR.format(line=2)}
            }
        }
コード例 #45
0
class TestRecurringCycleNotifications(TestCase):

  def setUp(self):
    super(TestRecurringCycleNotifications, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    _, self.assignee = self.object_generator.generate_person(
        user_role="Administrator")

    self.create_test_cases()

  def tearDown(self):
    pass

  def test_cycle_starts_in_less_than_X_days(self):

    with freeze_time("2015-02-01"):
      _, wf = self.generator.generate_workflow(self.quarterly_wf_1)
      response, wf = self.generator.activate_workflow(wf)

      self.assert200(response)

      assignee = Person.query.get(self.assignee.id)

    with freeze_time("2015-01-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-01-29"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(assignee.email, notif_data)

    with freeze_time("2015-02-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(assignee.email, notif_data)

  # TODO: this should mock google email api.
  @patch("ggrc.notifications.common.send_email")
  def test_marking_sent_notifications(self, mail_mock):
    mail_mock.return_value = True

    with freeze_time("2015-02-01"):
      _, wf = self.generator.generate_workflow(self.quarterly_wf_1)
      response, wf = self.generator.activate_workflow(wf)

      self.assert200(response)

      assignee = Person.query.get(self.assignee.id)

    with freeze_time("2015-01-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-01-29"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-02-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "notify_on_change": True,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.assignee.id),
            "task_group_tasks": [{
                "contact": person_dict(self.assignee.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }

    self.all_workflows = [
        self.quarterly_wf_1,
    ]
コード例 #46
0
class TestCsvImport(TestCase):
    """Tests for import of multiple objects"""
    def setUp(self):
        super(TestCsvImport, self).setUp()
        self.generator = ObjectGenerator()
        self.client.get("/login")
        self.policy_data = [
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-1"),
                ("Admin*", "*****@*****.**"),
            ]),
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-2"),
                ("Admin*", "*****@*****.**"),
            ]),
        ]
        self.org_group_data = [
            collections.OrderedDict([("object_type", "OrgGroup"),
                                     ("Code*", ""), ("Title*", "OrgGroup-1"),
                                     ("Admin*", "*****@*****.**"),
                                     ("Assignee", "*****@*****.**"),
                                     ("Verifier", "*****@*****.**")]),
        ]
        self.product_data = [
            collections.OrderedDict([("object_type", "Product"), ("Code*", ""),
                                     ("Title*", "Product-1"),
                                     ("Admin*", "*****@*****.**"),
                                     ("Assignee", "*****@*****.**"),
                                     ("Verifier", "*****@*****.**")]),
        ]

    def tearDown(self):
        pass

    def generate_people(self, people):
        for person in people:
            self.generator.generate_person(
                {
                    "name": person,
                    "email": "{}@reciprocitylabs.com".format(person),
                }, "Administrator")

    def test_multi_basic_policy_orggroup_product(self):
        """Tests for import of multiple objects, defined correctly"""
        test_data = self.product_data + self.org_group_data + self.policy_data
        responses = self.import_data(*test_data)

        object_counts = {
            "Org Group": (1, 0, 0),
            "Policy": (2, 0, 0),
            "Product": (1, 0, 0),
        }

        for response in responses:
            created, updated, ignored = object_counts[response["name"]]
            self.assertEqual(created, response["created"])
            self.assertEqual(updated, response["updated"])
            self.assertEqual(ignored, response["ignored"])
            self.assertEqual(set(), set(response["row_warnings"]))

        self.assertEqual(Policy.query.count(), 2)
        self.assertEqual(OrgGroup.query.count(), 1)
        self.assertEqual(Product.query.count(), 1)

    def test_multi_basic_policy_orggroup_product_with_warnings(self):
        """Test multi basic policy orggroup product with warnings"""

        wrong_policy_data = self.policy_data + [
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-1"),
                ("Admin*", "*****@*****.**"),
            ])
        ]

        wrong_org_group_data = self.org_group_data + [
            collections.OrderedDict([("object_type", "OrgGroup"),
                                     ("Code*", ""), ("Title*", "OrgGroup-1"),
                                     ("Admin*", ""),
                                     ("Assignee", "*****@*****.**"),
                                     ("Verifier", "*****@*****.**")])
        ]

        wrong_product_data = self.product_data + [
            collections.OrderedDict([("object_type", "Product"), ("Code*", ""),
                                     ("Title*", "Product-2"), ("Admin*", ""),
                                     ("Assignee", "*****@*****.**"),
                                     ("Verifier", "*****@*****.**")])
        ]

        for org_grp in wrong_org_group_data:
            org_grp.pop("Admin*")

        test_data = wrong_product_data + wrong_org_group_data + wrong_policy_data
        responses = self.import_data(*test_data)

        row_messages = []
        object_counts = {
            "Policy": (2, 0, 1),
            "Org Group": (0, 0, 2),
            "Product": (2, 0, 0),
        }
        for response in responses:
            created, updated, ignored = object_counts[response["name"]]
            self.assertEqual(created, response["created"])
            self.assertEqual(updated, response["updated"])
            self.assertEqual(ignored, response["ignored"])
            row_messages.extend(response["row_warnings"])
            row_messages.extend(response["row_errors"])

        expected_warnings = set([
            errors.DUPLICATE_VALUE_IN_CSV.format(
                line="9",
                processed_line="8",
                column_name="Title",
                value="OrgGroup-1",
            ),
            errors.DUPLICATE_VALUE_IN_CSV.format(
                line="15",
                processed_line="13",
                column_name="Title",
                value="Policy-1",
            ),
            errors.OWNER_MISSING.format(line=4, column_name="Admin"),
            errors.MISSING_COLUMN.format(line=8, column_names="Admin", s=""),
        ])

        self.assertEqual(expected_warnings, set(row_messages))
        self.assertEqual(Policy.query.count(), 2)
        self.assertEqual(OrgGroup.query.count(), 0)
        self.assertEqual(Product.query.count(), 2)

    def test_multi_basic_policy_orggroup_product_with_mappings(self):
        """Tests mapping of multiple objects"""
        def get_relationships_for(obj):
            return Relationship.query.filter(
                or_(
                    and_(Relationship.source_id == obj.id,
                         Relationship.source_type == obj.type),
                    and_(Relationship.destination_id == obj.id,
                         Relationship.destination_type == obj.type),
                ))

        test_data = self.org_group_data + self.product_data
        responses = self.import_data(*test_data)

        product1 = Product.query.first()
        org_grp1 = OrgGroup.query.first()

        mapped_policy_data = [
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-1"),
                ("Admin*", "*****@*****.**"),
                ("map:product", product1.slug),
                ("map:Org group", org_grp1.slug),
            ]),
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-2"),
                ("Admin*", "*****@*****.**"),
                ("map:product", product1.slug),
                ("map:Org group", ""),
            ]),
            collections.OrderedDict([
                ("object_type", "Policy"),
                ("Code*", ""),
                ("Title*", "Policy-3"),
                ("Admin*", "*****@*****.**"),
                ("map:product", ""),
                ("map:Org group", org_grp1.slug),
            ]),
        ]

        responses += self.import_data(*mapped_policy_data)

        object_counts = {
            "Policy": (3, 0, 0),
            "Org Group": (1, 0, 0),
            "Product": (1, 0, 0),
        }
        for response in responses:
            created, updated, ignored = object_counts[response["name"]]
            self.assertEqual(created, response["created"])
            self.assertEqual(updated, response["updated"])
            self.assertEqual(ignored, response["ignored"])
            self.assertEqual(set(), set(response["row_warnings"]))

        self.assertEqual(Policy.query.count(), 3)
        self.assertEqual(OrgGroup.query.count(), 1)
        self.assertEqual(Product.query.count(), 1)

        policy1 = Policy.query.filter_by(title="Policy-1").first()
        policy2 = Policy.query.filter_by(title="Policy-2").first()
        policy3 = Policy.query.filter_by(title="Policy-3").first()

        self.assertEqual(get_relationships_for(product1).count(), 2)
        self.assertEqual(get_relationships_for(org_grp1).count(), 2)
        self.assertEqual(get_relationships_for(policy1).count(), 2)
        self.assertEqual(get_relationships_for(policy2).count(), 1)
        self.assertEqual(get_relationships_for(policy3).count(), 1)
コード例 #47
0
class TestCycleStartFailed(TestCase):
    """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        Notification.query.delete()

        self.random_objects = self.object_generator.generate_random_objects(2)
        _, self.user = self.object_generator.generate_person(
            user_role="Administrator")
        self.create_test_cases()

        def init_decorator(init):
            def new_init(self, *args, **kwargs):
                init(self, *args, **kwargs)
                if hasattr(self, "created_at"):
                    self.created_at = datetime.now()

            return new_init

        Notification.__init__ = init_decorator(Notification.__init__)

    @patch("ggrc.notifications.common.send_email")
    def test_start_failed(self, mock_mail):

        wf_owner = "*****@*****.**"

        with freeze_time("2015-02-01 13:39:20"):
            _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
            response, wf = self.wf_generator.activate_workflow(wf)
            print wf.next_cycle_start_date

            self.assert200(response)

        with freeze_time("2015-01-01 13:39:20"):
            _, notif_data = common.get_daily_notifications()
            self.assertNotIn(wf_owner, notif_data)

        with freeze_time("2015-01-29 13:39:20"):
            _, notif_data = common.get_daily_notifications()
            self.assertIn(wf_owner, notif_data)
            self.assertIn("cycle_starts_in", notif_data[wf_owner])

        with freeze_time("2015-03-05 13:39:20"):
            _, notif_data = common.get_daily_notifications()
            self.assertIn(wf_owner, notif_data)
            self.assertNotIn("cycle_started", notif_data[wf_owner])
            self.assertIn(wf_owner, notif_data)
            self.assertIn("cycle_start_failed", notif_data[wf_owner])

            common.send_daily_digest_notifications()

            _, notif_data = common.get_daily_notifications()
            self.assertNotIn(wf_owner, notif_data)

    # TODO: investigate why next_cycle_start date remains the same after
    # start_recurring_cycles

    # @patch("ggrc.notifications.common.send_email")
    # def test_start_failed_send_notifications(self, mock_mail):

    #   wf_owner = "*****@*****.**"

    #   with freeze_time("2015-02-01 13:39:20"):
    #     _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
    #     response, wf = self.wf_generator.activate_workflow(wf)
    #     print wf.next_cycle_start_date

    #     self.assert200(response)

    #   with freeze_time("2015-01-01 13:39:20"):
    #     _, notif_data = common.get_daily_notifications()
    #     self.assertNotIn(wf_owner, notif_data)

    #   with freeze_time("2015-01-29 13:39:20"):
    #     _, notif_data = common.get_daily_notifications()
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertIn("cycle_starts_in", notif_data[wf_owner])

    #   with freeze_time("2015-02-05 13:39:20"):
    #     _, notif_data = common.get_daily_notifications()
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertNotIn("cycle_started", notif_data[wf_owner])
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertIn("cycle_start_failed", notif_data[wf_owner])

    #     start_recurring_cycles()
    #     _, notif_data = common.get_daily_notifications()
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertIn("cycle_started", notif_data[wf_owner])
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertNotIn("cycle_start_failed", notif_data[wf_owner])

    #     common.send_daily_digest_notifications()

    #     _, notif_data = common.get_daily_notifications()
    #     self.assertNotIn(wf_owner, notif_data)

    # @patch("ggrc.notifications.common.send_email")
    # def test_start_failed_send_notifications_monthly(self, mock_mail):

    #   wf_owner = "*****@*****.**"

    #   with freeze_time("2015-05-12 13:39:20"):
    #     _, wf = self.wf_generator.generate_workflow(self.monthly)
    #     response, wf = self.wf_generator.activate_workflow(wf)

    #   with freeze_time("2015-05-14 13:39:20"):
    #     _, wf = self.wf_generator.generate_workflow(self.monthly)
    #     response, wf = self.wf_generator.activate_workflow(wf)

    #     self.assert200(response)

    #     _, notif_data = common.get_daily_notifications()
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertNotIn("cycle_started", notif_data[wf_owner])
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertIn("cycle_start_failed", notif_data[wf_owner])

    #     start_recurring_cycles()
    #     _, notif_data = common.get_daily_notifications()
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertIn("cycle_started", notif_data[wf_owner])
    #     self.assertIn(wf_owner, notif_data)
    #     self.assertNotIn("cycle_start_failed", notif_data[wf_owner])

    #     common.send_daily_digest_notifications()

    #     _, notif_data = common.get_daily_notifications()
    #     self.assertNotIn(wf_owner, notif_data)

    def create_test_cases(self):
        def person_dict(person_id):
            return {
                "href": "/api/people/%d" % person_id,
                "id": person_id,
                "type": "Person"
            }

        self.quarterly_wf = {
            "title":
            "quarterly wf forced notifications",
            "notify_on_change":
            True,
            "description":
            "",
            "owners": [person_dict(self.user.id)],
            "frequency":
            "quarterly",
            "task_groups": [
                {
                    "title":
                    "tg_1",
                    "contact":
                    person_dict(self.user.id),
                    "task_group_tasks": [
                        {
                            "contact": person_dict(self.user.id),
                            "description": self.wf_generator.random_str(100),
                            "relative_start_day": 5,
                            "relative_start_month": 2,
                            "relative_end_day": 25,
                            "relative_end_month": 2,
                        },
                    ],
                },
            ]
        }
        self.monthly = {
            "title":
            "monthly",
            "notify_on_change":
            True,
            "description":
            "",
            "owners": [person_dict(self.user.id)],
            "frequency":
            "monthly",
            "task_groups": [
                {
                    "title":
                    "tg_1",
                    "contact":
                    person_dict(self.user.id),
                    "task_group_tasks": [
                        {
                            "contact": person_dict(self.user.id),
                            "description": self.wf_generator.random_str(100),
                            "relative_start_day": 14,
                            "relative_end_day": 25,
                        },
                    ],
                },
            ]
        }
コード例 #48
0
ファイル: test_reader.py プロジェクト: k-alexey/ggrc-core
class TestReader(TestCase):
    """ Test reader role """
    def setUp(self):
        super(TestReader, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("reader", "Reader"), ("admin", "Administrator"),
                 ("creator", "Creator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        """Only admin can use admin section"""
        for role, code in (("reader", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.client.get("/admin").status_code, code)

    def test_reader_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["reader"])
        all_errors = []
        base_models = set([
            "Control", "DataAsset", "Contract", "Policy", "Regulation",
            "Standard", "Document", "Facility", "Market", "Objective",
            "OrgGroup", "Vendor", "Product", "Clause", "System", "Process",
            "Project", "AccessGroup", "Metric"
        ])
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response = self.api.post(
                    model,
                    {
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "documents_reference_url": "ref",
                            "link":
                            "https://example.com",  # ignored except for Document
                            "contact": {
                                "type": "Person",
                                "id": self.users["reader"].id,
                            },
                        },
                    })
                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                obj_id = response.json.get(table_singular).get("id")

                # Test GET when owner
                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if not collection:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_reader_search(self):
        """ Test if reader can see the correct object while using search api """
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['reader'])
        response = self.api.post(all_models.Policy, {
            "policy": {
                "title": "reader Policy",
                "context": None
            },
        })
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 2)
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"]["Regulation"], 1)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_reader_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['reader'])
        reader_count = self._get_count("Person")
        self.assertEqual(admin_count, reader_count)

    def test_relationships_access(self):
        """Check if reader can access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['reader'])
        response = self.api.get_collection(all_models.Relationship,
                                           relationship_id)
        self.assertEqual(response.status_code, 200)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 1)

    def test_creation_of_mappings(self):
        """Check if reader can't create mappings"""
        self.generator.api.set_user(self.users["admin"])
        _, control = self.generator.generate(all_models.Control, "control", {
            "control": {
                "title": "Test Control",
                "context": None
            },
        })
        self.generator.api.set_user(self.users['reader'])
        _, program = self.generator.generate(all_models.Program, "program", {
            "program": {
                "title": "Test Program",
                "context": None
            },
        })

        response, _ = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "destination": {
                        "id": program.id,
                        "type": "Program"
                    },
                    "source": {
                        "id": control.id,
                        "type": "Control"
                    },
                    "context": {
                        "id": program.context.id,
                        "type": "context"
                    }
                },
            })
        self.assertEqual(response.status_code, 403)

    @ddt.data("creator", "reader")
    def test_unmap_people(self, user_role):
        """Test that global reader/creator can't unmap people from program"""
        user = self.users[user_role]
        with factories.single_commit():
            program = factories.ProgramFactory()
            mapped_person = factories.ObjectPersonFactory(
                personable=program, person=user, context=program.context)
        self.api.set_user(user)
        db.session.add(mapped_person)
        response = self.api.delete(mapped_person)
        self.assertEqual(response.status_code, 403)

    def test_read_evidence_revision(self):
        """Global Read can read Evidence revision content"""
        user = self.users["reader"]
        link = "google.com"
        evidence = factories.EvidenceUrlFactory(link=link)
        evidence_id = evidence.id
        self.api.set_user(user)
        resp = self.api.client.get(
            "/api/revisions?resource_type={}&resource_id={}".format(
                evidence.type, evidence_id))
        rev_content = resp.json["revisions_collection"]["revisions"][0][
            "content"]
        self.assertTrue(rev_content)
        self.assertEquals(link, rev_content["link"])
コード例 #49
0
class TestTaskOverdueNotificationsUsingAPI(TestTaskOverdueNotifications):
  """Tests for overdue notifications when changing Tasks with an API."""

  # pylint: disable=invalid-name

  def setUp(self):
    super(TestTaskOverdueNotificationsUsingAPI, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self._create_test_cases()

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_sending_overdue_notifications_for_tasks(self, is_vf_needed, _):
    """Overdue notifications should be sent for overdue tasks every day.

    Even if an overdue notification has already been sent, it should still be
    sent in every following daily digest f a task is still overdue.
    """
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    tasks = workflow.cycles[0].cycle_task_group_object_tasks
    task1_id = tasks[0].id
    task2_id = tasks[1].id

    user = models.Person.query.get(self.user.id)

    with freeze_time("2017-05-14 08:09:10"):
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

    with freeze_time("2017-05-15 08:09:10"):  # task 1 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

    with freeze_time("2017-05-16 08:09:10"):  # task 2 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id])

    with freeze_time("2017-05-17 08:09:10"):  # after both tasks' due dates
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id, task2_id])

      common.send_daily_digest_notifications()

    # even after sending the overdue notifications, they are sent again the
    # day after, too
    with freeze_time("2017-05-18 08:09:10"):
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)

      overdue_task_ids = sorted(user_notifs["task_overdue"].keys())
      self.assertEqual(overdue_task_ids, [task1_id, task2_id])

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_adjust_overdue_notifications_on_task_due_date_change(self,
                                                                is_vf_needed,
                                                                _):
    """Sending overdue notifications should adjust to task due date changes."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

      tasks = workflow.cycles[0].cycle_task_group_object_tasks
      task1, task2 = tasks
      self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)})

      user = models.Person.query.get(self.user.id)

    with freeze_time("2017-05-16 08:09:10"):  # a day after task1 due date
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

      # change task1 due date, there should be no overdue notification anymore
      self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 16)})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

      # change task1 due date to the past there should a notification again
      self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 14)})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_adjust_overdue_notifications_on_task_status_change(self,
                                                              is_vf_needed,
                                                              _):
    """Sending overdue notifications should take task status into account."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

      tasks = workflow.cycles[0].cycle_task_group_object_tasks
      task1, task2 = tasks
      self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)})

      user = models.Person.query.get(self.user.id)
      user_email = user.email
    if is_vf_needed:
      non_final_states = [CycleTaskGroupObjectTask.ASSIGNED,
                          CycleTaskGroupObjectTask.IN_PROGRESS,
                          CycleTaskGroupObjectTask.FINISHED,
                          CycleTaskGroupObjectTask.DECLINED]
      final_state = CycleTaskGroupObjectTask.VERIFIED
    else:
      non_final_states = [CycleTaskGroupObjectTask.ASSIGNED,
                          CycleTaskGroupObjectTask.IN_PROGRESS]
      final_state = CycleTaskGroupObjectTask.FINISHED

    with freeze_time("2017-05-16 08:09:10"):  # a day after task1 due date
      for state in non_final_states:
        # clear all notifications before before changing the task status
        models.Notification.query.delete()
        _, notif_data = common.get_daily_notifications()
        self.assertEqual(notif_data, {})

        self.wf_generator.modify_object(task1, {"status": state})

        _, notif_data = common.get_daily_notifications()
        user_notifs = notif_data.get(user_email, {})
        self.assertIn("task_overdue", user_notifs)
        self.assertEqual(len(user_notifs["task_overdue"]), 1)

      # WITHOUT clearing the overdue notifications, move the task to "verified"
      # state, and the overdue notification should disappear.

      self.wf_generator.modify_object(task1, {"status": final_state})
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertNotIn("task_overdue", user_notifs)

  @ddt.data(True, False)
  @patch("ggrc.notifications.common.send_email")
  def test_stop_sending_overdue_notification_if_task_gets_deleted(self,
                                                                  is_vf_needed,
                                                                  _):
    """Overdue notifications should not be sent for deleted tasks."""
    with freeze_time("2017-05-15 14:25:36"):
      tmp = self.one_time_workflow.copy()
      tmp['is_verification_needed'] = is_vf_needed
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    tasks = workflow.cycles[0].cycle_task_group_object_tasks
    task1, task2 = tasks

    user = models.Person.query.get(self.user.id)
    user_email = user.email

    with freeze_time("2017-10-16 08:09:10"):  # long after both task due dates
      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 2)

      db.session.delete(task2)
      db.session.commit()

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user_email, {})
      self.assertIn("task_overdue", user_notifs)
      self.assertEqual(len(user_notifs["task_overdue"]), 1)

      db.session.delete(task1)
      db.session.commit()

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})
      self.assertNotIn("task_overdue", user_notifs)

  def _create_test_cases(self):
    """Create configuration to use for generating a new workflow."""
    def person_dict(person_id):
      return {
          "href": "/api/people/" + str(person_id),
          "id": person_id,
          "type": "Person"
      }
    role_id = models.all_models.AccessControlRole.query.filter(
        models.all_models.AccessControlRole.name == "Task Assignees",
        models.all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    self.one_time_workflow = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [person_dict(self.user.id)],
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "start_date": date(2017, 5, 5),  # Friday
                "end_date": date(2017, 5, 15),
                "access_control_list": [{
                    "person": {"id": self.user.id, },
                    "ac_role_id": role_id,
                }],
            }, {
                "title": "task 2",
                "description": "some task 2",
                "start_date": date(2017, 5, 5),  # Friday
                "end_date": date(2017, 5, 16),
                "access_control_list": [{
                    "person": {"id": self.user.id, },
                    "ac_role_id": role_id,
                }],
            }],
            "task_group_objects": self.random_objects
        }]
    }
コード例 #50
0
class TestFilterByAuditor(TestCase):
  """ Test for filter by Auditor. """

  def setUp(self):
    super(TestFilterByAuditor, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()
    _, self.auditor = self.generator.generate_person(user_role="Creator")
    auditor_role = all_models.AccessControlRole.query.filter_by(
        name="Auditors").one()
    with factories.single_commit():
      self.audit = factories.AuditFactory(status="In Progress")
      self.audit_id = self.audit.id
      audit_context = factories.ContextFactory()
      self.audit.context = audit_context
      factories.AccessControlListFactory(
          ac_role=auditor_role,
          object=self.audit,
          person=self.auditor
      )
    self.api.set_user(self.auditor)

  def test_query_audits_by_auditor(self):
    """test get audit as query get"""
    objects = self.api.get_query(all_models.Audit, "")
    self.assertEqual(1, len(objects.json["audits_collection"]["audits"]))
    audit_dict = objects.json["audits_collection"]["audits"][0]
    self.assertEqual(self.audit_id, audit_dict["id"])

  def test_filter_audits_by_auditor(self):
    """Test query on audit Global Search.

    This query is the fact query that frontend is sending in global search.
    """
    query_request_data = [
        {
            u'fields': [],
            u'filters': {
                u'expression': {
                    u'left': {
                        u'left': u'status',
                        u'op': {u'name': u'='},
                        u'right': u'Planned'
                    },
                    u'op': {u'name': u'OR'},
                    u'right': {
                        u'left': {
                            u'left': u'status',
                            u'op': {u'name': u'='},
                            u'right': u'In Progress'
                        },
                        u'op': {u'name': u'OR'},
                        u'right': {
                            u'left': {
                                u'left': u'status',
                                u'op': {u'name': u'='},
                                u'right': u'Manager Review'
                            },
                            u'op': {u'name': u'OR'},
                            u'right': {
                                u'left': {
                                    u'left': u'status',
                                    u'op': {u'name': u'='},
                                    u'right': u'Ready for External Review',
                                },
                                u'op': {u'name': u'OR'},
                                u'right': {
                                    u'left': u'status',
                                    u'op': {u'name': u'='},
                                    u'right': u'Completed',
                                }
                            },
                        },
                    },
                },
                u'keys': [u'status'],
                u'order_by': {
                    u'compare': None,
                    u'keys': [],
                    u'order': u'',
                }
            },
            u'limit': [0, 5],
            u'object_name': u'Audit',
            u'permissions': u'read',
            u'type': u'values',
        },
        {
            u'filters': {
                u'expression': {
                    u'ids': [u'150'],
                    u'object_name': u'undefined',
                    u'op': {u'name': u'relevant'}
                },
                u'keys': [],
                u'order_by': {u'compare': None, u'keys': [], u'order': u''}
            },
            u'object_name': u'Audit',
            u'type': u'ids',
        },
    ]
    resp = self.api.send_request(self.api.client.post,
                                 data=query_request_data,
                                 api_link="/query")
    self.assertEqual(1, resp.json[0]["Audit"]["count"])
    self.assertEqual(self.audit_id, resp.json[0]["Audit"]["values"][0]["id"])
コード例 #51
0
class TestOneTimeWorkflowNotification(TestCase):
    """ Tests are defined in the g-sheet test grid under:
    WF EMAILS for unit tests (middle level)
  """
    def setUp(self):
        super(TestOneTimeWorkflowNotification, self).setUp()
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.random_people = [
            self.object_generator.generate_person(user_role="Administrator")[1]
            for _ in range(5)
        ]
        self.create_test_cases()

        self.create_users()

        db.session.query(Notification).delete()

        def init_decorator(init):
            def new_init(self, *args, **kwargs):
                init(self, *args, **kwargs)
                if hasattr(self, "created_at"):
                    self.created_at = datetime.now()

            return new_init

        Notification.__init__ = init_decorator(Notification.__init__)

    def tearDown(self):
        db.session.query(Notification).delete()

    def short_dict(self, obj, plural):
        return {
            "href": "/api/%s/%d" % (plural, obj.id),
            "id": obj.id,
            "type": obj.__class__.__name__,
        }

    def setup_cycle_tasks(self):
        """Prepare environment with couple of active cycle tasks."""
        with freeze_time("2018-11-01"):
            _, workflow = self.wf_generator.generate_workflow(
                self.one_time_workflow_1)
            self.wf_generator.generate_cycle(workflow)
            self.wf_generator.activate_workflow(workflow)
        return all_models.CycleTaskGroupObjectTask.query

    def assert_nofication_sent_with(self, text):
        """Assert if text exists in sent notification."""
        with mock.patch("ggrc.notifications.common.send_email") as send_email:
            self.client.get("/_notifications/send_daily_digest")
            _, _, content = send_email.call_args[0]
        self.assertIn(text, content)

    def assert_nofication_sent_without(self, text):
        """Assert if text doesn't exist in sent notification."""
        with mock.patch("ggrc.notifications.common.send_email") as send_email:
            self.client.get("/_notifications/send_daily_digest")
            _, _, content = send_email.call_args[0]
        self.assertNotIn(text, content)

    def test_one_time_wf(self):
        # setup
        with freeze_time("2015-04-07 03:21:34"):
            wf_response, wf = self.wf_generator.generate_workflow(
                data={
                    # admin will be the current user
                    "notify_on_change":
                    True,  # force real time updates
                    "title":
                    "One-time WF",
                    "notify_custom_message":
                    textwrap.dedent("""\
              Hi all.
              Did you know that Irelnd city namd Newtownmountkennedy has 19
              letters? But it's not the longest one. The recordsman is the
              city in New Zealand that contains 97 letter."""),
                })

            _, tg = self.wf_generator.generate_task_group(
                wf,
                data={
                    "title": "TG #1 for the One-time WF",
                    "contact": self.short_dict(self.tgassignee1, "people"),
                })

            self.wf_generator.generate_task_group_task(
                tg, {
                    "title": "task #1 for one-time workflow",
                    "contact": self.short_dict(self.member1, "people"),
                    "start_date": "04/07/2015",
                    "end_date": "04/15/2015",
                })

            self.wf_generator.generate_task_group_object(
                tg, self.random_objects[0])
            self.wf_generator.generate_task_group_object(
                tg, self.random_objects[1])

        # test
        with freeze_time("2015-04-07 03:21:34"):
            cycle_response, cycle = self.wf_generator.generate_cycle(wf)
            self.wf_generator.activate_workflow(wf)

            common.get_daily_notifications()

    def test_deprecated_ct_acl_update(self):
        """Test if acl update for deprecated CT will not create notification."""
        cycle_task = self.setup_cycle_tasks().first()
        cycle_task_title = cycle_task.title
        response = self.api.put(cycle_task, {"status": "Deprecated"})
        self.assert200(response)
        self.assert_nofication_sent_without(cycle_task_title)

        task_assignee = all_models.AccessControlRole.query.filter_by(
            name="Task Assignees",
            object_type="CycleTaskGroupObjectTask",
        ).first()
        person = self.object_generator.generate_person(user_role="Creator")[1]
        response = self.api.put(
            cycle_task, {
                "access_control_list": [{
                    "ac_role_id": task_assignee.id,
                    "person": {
                        "id": person.id,
                        "type": "Person",
                    }
                }]
            })
        self.assert200(response)
        self.assert_nofication_sent_without(cycle_task_title)

    def test_restore_deprecated_ct(self):
        """Test notifications for CT which was restored from Deprecated."""
        cycle_task = self.setup_cycle_tasks().first()
        cycle_task_title = cycle_task.title

        self.assert_nofication_sent_with(cycle_task_title)

        response = self.api.put(cycle_task, {"status": "Deprecated"})
        self.assert200(response)
        self.assert_nofication_sent_without(cycle_task_title)

        response = self.api.put(cycle_task, {"status": "Assigned"})
        self.assert200(response)
        self.assert_nofication_sent_with(cycle_task_title)

    def create_test_cases(self):
        def person_dict(person_id):
            return {
                "href": "/api/people/%d" % person_id,
                "id": person_id,
                "type": "Person"
            }

        self.one_time_workflow_1 = {
            "title":
            "one time test workflow",
            "description":
            "some test workflow",
            # admin will be current user with id == 1
            "task_groups": [
                {
                    "title":
                    "one time task group",
                    "task_group_tasks": [
                        {
                            "title": "task_{}".format(str(uuid.uuid4())),
                            "description": "some task",
                            "contact": person_dict(self.random_people[0].id),
                            "start_date": date(2015, 5, 1),  # friday
                            "end_date": date(2015, 5, 5),
                        },
                        {
                            "title": "task_{}".format(str(uuid.uuid4())),
                            "description": "some task",
                            "contact": person_dict(self.random_people[1].id),
                            "start_date": date(2015, 5, 4),
                            "end_date": date(2015, 5, 7),
                        }
                    ],
                    "task_group_objects":
                    self.random_objects[:2]
                },
                {
                    "title":
                    "another one time task group",
                    "task_group_tasks": [
                        {
                            "title": "task_{}".format(str(uuid.uuid4())),
                            "description": "some task",
                            "contact": person_dict(self.random_people[0].id),
                            "start_date": date(2015, 5, 8),  # friday
                            "end_date": date(2015, 5, 12),
                        },
                        {
                            "title": "task_{}".format(str(uuid.uuid4())),
                            "description": "some task",
                            "contact": person_dict(self.random_people[2].id),
                            "start_date": date(2015, 5, 1),  # friday
                            "end_date": date(2015, 5, 5),
                        }
                    ],
                    "task_group_objects": []
                }
            ]
        }

    def create_users(self):
        _, self.admin1 = self.object_generator.generate_person(
            # data={"name": "User1 Admin1", "email": "*****@*****.**"},
            user_role="Administrator")
        _, self.tgassignee1 = self.object_generator.generate_person(
            # data={"name": "User2 TGassignee1",
            #       "email": "*****@*****.**"},
            user_role="Administrator")
        _, self.member1 = self.object_generator.generate_person(
            # data={"name": "User3 Member1", "email": "*****@*****.**"},
            user_role="Administrator")
        _, self.member2 = self.object_generator.generate_person(
            # data={"name": "User4 Member2", "email": "*****@*****.**"},
            user_role="Administrator")
コード例 #52
0
class TestNotificationsForDeletedObjects(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    TestCase.setUp(self)
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_delete_activated_workflow(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, workflow = self.wf_generator.generate_workflow(self.quarterly_wf_1)
      response, workflow = self.wf_generator.activate_workflow(workflow)

      self.assert200(response)

      user = Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])

      workflow = Workflow.query.get(workflow.id)

      response = self.wf_generator.api.delete(workflow)
      self.assert200(response)

      _, notif_data = common.get_daily_notifications()
      user = Person.query.get(self.user.id)

      self.assertNotIn(user.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "notify_on_change": True,
        "description": "",
        "owners": [person_dict(self.user.id)],
        "frequency": "quarterly",
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
                "relative_start_day": 5,
                "relative_start_month": 2,
                "relative_end_day": 25,
                "relative_end_month": 2,
            },
            ],
        },
        ]
    }
コード例 #53
0
class TestAccessControlRole(TestCase):
  """TestAccessControlRole"""

  def setUp(self):
    self.clear_data()
    super(TestAccessControlRole, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.people = {}
    for name in ["Creator", "Reader", "Editor"]:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=name)
      self.people[name] = user

  def _post_role(self, name=None, object_type="Control"):
    """Helper function for POSTing roles"""
    if name is None:
      name = random_str(prefix="Access Control Role - ")
    return self.api.post(AccessControlRole, {
        "access_control_role": {
            "name": name,
            "object_type": object_type,
            "context": None,
            "read": True
        },
    })

  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])

  def test_create(self):
    """Test Access Control Role creation"""
    response = self._post_role(object_type="Risk")
    assert response.status_code == 201, \
        "Failed to create a new access control role, response was {}".format(
            response.status)

    id_ = response.json['access_control_role']['id']
    role = AccessControlRole.query.filter(AccessControlRole.id == id_).first()
    assert role.read == 1, \
        "Read permission not correctly saved {}".format(role.read)
    assert role.update == 1, \
        "Update permission not correctly saved {}".format(role.update)
    assert role.delete == 1, \
        "Update permission not correctly saved {}".format(role.delete)

  @ddt.data(
      {"mandatory": True, "exp_response": MANDATORY_ROLE_RESPONSE},
      {"mandatory": False, "exp_response": NON_MANDATORY_ROLE_RESPONSE},
  )
  @ddt.unpack
  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])

  def test_only_admin_can_post(self):
    """Only admin users should be able to POST access control roles"""
    for name in ("Creator", "Reader", "Editor"):
      person = self.people.get(name)
      self.api.set_user(person)
      response = self._post_role()
      assert response.status_code == 403, \
          "Non admins should get forbidden error when POSTing role. {}".format(
              response.status)

  @ddt.data(
      ("name", "New ACR"),
      ("read", False),
      ("mandatory", False),
      ("non_editable", False),
  )
  @ddt.unpack
  def test_modify_non_editable_role(self, field_name, field_value):
    """Test if user can modify non-editable role"""
    # Primary Contacts role of Control is non-editable
    ac_role = AccessControlRole.query.filter_by(
        object_type="Control",
        name="Control Operators",
    ).first()

    response = self.api.put(ac_role, {field_name: field_value})
    assert response.status_code == 403, \
        "Forbidden error should be thrown when non-editable " \
        "role {} updated.".format(ac_role.name)

  def test_delete_non_editable_role(self):
    """Test if user can delete non-editable role"""
    # Primary Contacts role of Control is non-editable
    ac_role = AccessControlRole.query.filter_by(
        object_type="Control",
        name="Control Operators",
    ).first()

    response = self.api.delete(ac_role)
    assert response.status_code == 403, \
        "Forbidden error should be thrown when non-editable " \
        "role {} deleted.".format(ac_role.name)

  @ddt.data("Control")
  def test_create_from_ggrcq(self, object_type):
    """Test that create action only for GGRCQ."""
    with self.api.as_external():
      response = self._post_role(object_type=object_type)
      self.assertEqual(response.status_code, 201)

  @ddt.data("Control")
  def test_create_from_ggrc(self, object_type):
    """Test create action not allowed for GGRC."""
    response = self._post_role(object_type=object_type)
    self.assertEqual(response.status_code, 405)

  @ddt.data("Control")
  def test_modify_from_ggrcq(self, object_type):
    """Test that modify action only for GGRCQ."""
    with factories.single_commit():
      acr_id = factories.AccessControlRoleFactory(object_type=object_type).id

    with self.api.as_external():
      acr = all_models.AccessControlRole.query.get(acr_id)
      response = self.api.put(acr, {"name": "new acr"})
      self.assertEqual(response.status_code, 200)

  @ddt.data("Control")
  def test_modify_from_ggrc(self, object_type):
    """Test modify action not allowed for GGRC."""
    with factories.single_commit():
      acr = factories.AccessControlRoleFactory(object_type=object_type)

    response = self.api.put(acr, {"name": "new acr"})
    self.assertEqual(response.status_code, 405)

  @ddt.data("Control")
  def test_delete_from_ggrcq(self, object_type):
    """Test that modify action only for GGRCQ."""
    with factories.single_commit():
      acr_id = factories.AccessControlRoleFactory(object_type=object_type).id

    with self.api.as_external():
      acr = all_models.AccessControlRole.query.get(acr_id)
      response = self.api.delete(acr)
      self.assertEqual(response.status_code, 200)

  @ddt.data("Control")
  def test_delete_from_ggrc(self, object_type):
    """Test modify action not allowed for GGRC."""
    with factories.single_commit():
      acr = factories.AccessControlRoleFactory(object_type=object_type)

    response = self.api.delete(acr)
    self.assertEqual(response.status_code, 405)
コード例 #54
0
class TestCsvImport(TestCase):

  def setUp(self):
    super(TestCsvImport, self).setUp()
    self.generator = ObjectGenerator()
    self.client.get("/login")

  def tearDown(self):
    pass

  def generate_people(self, people):
    for person in people:
      self.generator.generate_person({
          "name": person,
          "email": "{}@reciprocitylabs.com".format(person),
      }, "Administrator")

  def test_multi_basic_policy_orggroup_product(self):
    filename = "multi_basic_policy_orggroup_product.csv"
    response_json = self.import_file(filename)

    object_counts = {
        "Org Group": (4, 0, 0),
        "Policy": (4, 0, 0),
        "Product": (5, 0, 0),
    }

    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      self.assertEqual(set(), set(row["row_warnings"]))

    self.assertEqual(Policy.query.count(), 4)
    self.assertEqual(OrgGroup.query.count(), 4)
    self.assertEqual(Product.query.count(), 5)

  def test_multi_basic_policy_orggroup_product_with_warnings(self):
    filename = "multi_basic_policy_orggroup_product_with_warnings.csv"
    response_json = self.import_file(filename)

    row_messages = []
    object_counts = {
        "Policy": (3, 0, 2),
        "Org Group": (0, 0, 4),
        "Product": (5, 0, 2),
    }
    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      row_messages.extend(row["row_warnings"])
      row_messages.extend(row["row_errors"])

    expected_warnings = set([
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line_list="5, 6", column_name="Title", value="dolor",
            s="", ignore_lines="6"),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line_list="6, 7", column_name="Code", value="p-4",
            s="", ignore_lines="7"),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line_list="21, 26", column_name="Title", value="meatloaf",
            s="", ignore_lines="26"),
        errors.DUPLICATE_VALUE_IN_CSV.format(
            line_list="21, 26, 27", column_name="Code", value="pro 1",
            s="s", ignore_lines="26, 27"),
        errors.OWNER_MISSING.format(line=26, column_name="Owner"),
        errors.MISSING_COLUMN.format(line=13, column_names="Owner", s=""),
        errors.MISSING_COLUMN.format(line=14, column_names="Owner", s=""),
        errors.MISSING_COLUMN.format(line=15, column_names="Owner", s=""),
        errors.MISSING_COLUMN.format(line=16, column_names="Owner", s=""),
    ])

    self.assertEqual(expected_warnings, set(row_messages))
    self.assertEqual(Policy.query.count(), 3)
    self.assertEqual(OrgGroup.query.count(), 0)
    self.assertEqual(Product.query.count(), 5)

  def test_multi_basic_policy_orggroup_product_with_mappings(self):

    def get_relationships_for(obj):
      return Relationship.query.filter(or_(
          and_(Relationship.source_id == obj.id,
               Relationship.source_type == obj.type),
          and_(Relationship.destination_id == obj.id,
               Relationship.destination_type == obj.type),
      ))

    filename = "multi_basic_policy_orggroup_product_with_mappings.csv"
    response_json = self.import_file(filename)

    object_counts = {
        "Policy": (4, 0, 0),
        "Org Group": (4, 0, 0),
        "Product": (5, 0, 0),
    }
    for row in response_json:
      created, updated, ignored = object_counts[row["name"]]
      self.assertEqual(created, row["created"])
      self.assertEqual(updated, row["updated"])
      self.assertEqual(ignored, row["ignored"])
      self.assertEqual(set(), set(row["row_warnings"]))

    self.assertEqual(Policy.query.count(), 4)
    self.assertEqual(OrgGroup.query.count(), 4)
    self.assertEqual(Product.query.count(), 5)
    p1 = Policy.query.filter_by(slug="p-1").first()
    org1 = OrgGroup.query.filter_by(slug="org-1").first()

    self.assertEqual(get_relationships_for(p1).count(), 3)
    self.assertEqual(get_relationships_for(org1).count(), 5)

  def test_big_import_with_mappings(self):
    response = self.import_file("data_for_export_testing.csv")
    self._check_csv_response(response, {})
コード例 #55
0
class TestEnableAndDisableNotifications(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestEnableAndDisableNotifications, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    models.Notification.__init__ = init_decorator(models.Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_default_notifications_settings(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_disabled_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", False)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_enabled_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)
      self.assert200(response)

    with freeze_time("2015-01-29 13:39:20"):
      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", True)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_forced_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf_forced)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", True)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_force_one_wf_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf_forced = self.wf_generator.generate_workflow(
          self.quarterly_wf_forced)
      response, wf_forced = self.wf_generator.activate_workflow(wf_forced)
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])
      self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"])
      self.assertIn(wf.id, notif_data[user.email]["cycle_starts_in"])

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", False)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])
      self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"])
      self.assertNotIn(wf.id, notif_data[user.email]["cycle_starts_in"])

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_forced = {
        "title": "quarterly wf forced notifications",
        "notify_on_change": True,
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }

    self.quarterly_wf = {
        "title": "quarterly wf 1",
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }
コード例 #56
0
class TestOneTimeWfEndDateChange(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestOneTimeWfEndDateChange, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_no_date_change(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-04-11 03:21:34"):
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn("cycle_started", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_started", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      self.assertNotIn("due_today", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-04 03:21:34"):  # one day before due date
      _, notif_data = common.get_daily_notifications()
      user = get_person(self.user.id)
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_in"]), 2)

    with freeze_time("2015-05-04 03:21:34"):  # one day before due date
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 3)

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn("due_today", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]), 2)

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_future(self, mock_mail):
    """
    test moving the end date to the future, befor due_in and due_today
    notifications have been sent
    """
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-04-11 03:21:34"):
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn("cycle_started", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_started", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      self.assertNotIn("due_today", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 15)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 15)})

    with freeze_time("2015-05-04 03:21:34"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      user = get_person(self.user.id)
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-14 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_in"]),
                       len(self.random_objects))

    with freeze_time("2015-05-15 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      # yesterdays mail has not been sent
      self.assertIn("due_in", notif_data[user.email])

      self.assertIn("due_today", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]),
                       len(self.random_objects))

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_past(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 1)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 1)})

    with freeze_time("2015-05-03 03:21:34"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-04 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_today(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 3)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 4)})

    with freeze_time("2015-05-03 03:21:34"):  # one day befor due date
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()

      self.assertNotEquals(notif_data, {})
      self.assertIn(user.email, notif_data)
      self.assertIn("due_today", notif_data[user.email])
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]), 1)

      common.send_daily_digest_notifications()

    with freeze_time("2015-05-04 03:21:34"):  # due date
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("due_today", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      common.send_daily_digest_notifications()

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.one_time_workflow_1 = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [person_dict(self.user.id)],
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "contact": person_dict(self.user.id),
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }, {
                "title": "task 2",
                "description": "some task 2",
                "contact": person_dict(self.user.id),
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }],
            "task_group_objects": self.random_objects
        }]
    }
コード例 #57
0
ファイル: test_monthly_wf.py プロジェクト: egorhm/ggrc-core
class TestMonthlyWorkflowNotification(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestMonthlyWorkflowNotification, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    _, self.person_2 = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = dt.datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_auto_generate_cycle(self, mock_mail):

    person_1_email = Person.query.get(self.person_1.id).email
    with freeze_time("2015-04-01"):
      _, wf = self.wf_generator.generate_workflow(self.monthly_workflow_1)
      self.wf_generator.activate_workflow(wf)
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(person_1_email, notif_data)

    with freeze_time("2015-04-02"):
      self.api.client.get("nightly_cron_endpoint")
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(person_1_email, notif_data)
      start_recurring_cycles()
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(person_1_email, notif_data)

    # cycle starts on monday - 6th, and not on 5th
    with freeze_time("2015-04-03"):
      start_recurring_cycles()
      _, notif_data = common.get_daily_notifications()
      self.assertIn(person_1_email, notif_data)
      self.assertIn("cycle_started", notif_data[person_1_email])

    with freeze_time("2015-04-15"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(person_1_email, notif_data)

    with freeze_time("2015-04-25"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(person_1_email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_manual_generate_cycle(self, mock_mail):

    with freeze_time("2015-04-01"):
      _, wf = self.wf_generator.generate_workflow(self.monthly_workflow_1)
      self.wf_generator.activate_workflow(wf)

      person_1 = Person.query.get(self.person_1.id)

    with freeze_time("2015-04-03"):
      _, notif_data = common.get_daily_notifications()

    with freeze_time("2015-04-03"):
      _, cycle = self.wf_generator.generate_cycle(wf)
      _, notif_data = common.get_daily_notifications()
      person_1 = Person.query.get(self.person_1.id)
      self.assertIn("cycle_started", notif_data[person_1.email])

    with freeze_time("2015-05-03"):  # two days befor due date
      _, notif_data = common.get_daily_notifications()
      person_1 = Person.query.get(self.person_1.id)
      self.assertIn(person_1.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.monthly_workflow_1 = {
        "title": "test monthly wf notifications",
        "notify_on_change": True,
        "description": "some test workflow",
        # admin will be current user with id == 1
        "unit": "month",
        "recurrences": True,
        "repeat_every": 1,
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.person_1.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
                "start_date": dt.date(2015, 4, 5),
                "end_date": dt.date(2015, 4, 25),
            }, {
                "title": "task 2",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
                "start_date": dt.date(2015, 4, 10),
                "end_date": dt.date(2015, 4, 21),
            }],
            "task_group_objects": self.random_objects[:2]
        }, {
            "title": "another one time task group",
            "contact": person_dict(self.person_1.id),
            "task_group_tasks": [{
                "title": "task 1 in tg 2",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
                "start_date": dt.date(2015, 4, 15),
                "end_date": dt.date(2015, 4, 15),
            }, {
                "title": "task 2 in tg 2",
                "description": "some task",
                "contact": person_dict(self.person_2.id),
                "start_date": dt.date(2015, 4, 15),
                "end_date": dt.date(2015, 4, 28),
            }],
            "task_group_objects": []
        }]
    }
コード例 #58
0
class TestEvidenceRolePropagation(TestCase):
    """Evidence role propagation test case"""

    # pylint: disable=invalid-name

    def setUp(self):
        super(TestEvidenceRolePropagation, self).setUp()
        self.api = Api()
        self.generator = ObjectGenerator()

    # Propagation isn't work for 'Primary Contacts', 'Secondary Contacts'
    # just add them to data list to check if fix works.

    @ddt.data("Assignees", "Creators", "Verifiers")
    def test_assessment_role_propagation_edit(self, role_name):
        """Asses user with role '{0}' should be able to edit related evidence"""

        _, reader = self.generator.generate_person(user_role="Creator")
        with factories.single_commit():
            assessment = factories.AssessmentFactory()
            assessment.add_person_with_role_name(reader, role_name)
            evidence = factories.EvidenceFactory()
            evidence_id = evidence.id
            factories.RelationshipFactory(source=assessment,
                                          destination=evidence)

        self.api.set_user(reader)

        evidence = all_models.Evidence.query.get(evidence_id)
        new_description = 'new description'
        resp = self.api.modify_object(evidence,
                                      {'description': new_description})
        evidence = self.refresh_object(evidence)
        self.assert200(resp)
        self.assertEquals(new_description, evidence.description)
        self.assertEquals(reader.id, evidence.modified_by_id)

    @ddt.data(
        ("Creator", "Audit Captains", 200),
        ("Creator", "Auditors", 403),
        ("Reader", "Audit Captains", 200),
        ("Reader", "Auditors", 403),
        ("Editor", "Audit Captains", 200),
        ("Editor", "Auditors", 200),
    )
    @ddt.unpack
    def test_audit_role_propagation_edit(self, user_role, audit_role,
                                         status_code):
        """'{0}' assigned as '{1}' should get '{2}' when editing audit evidence"""
        _, user = self.generator.generate_person(user_role=user_role)
        with factories.single_commit():
            audit = factories.AuditFactory()
            audit.add_person_with_role_name(user, audit_role)
            evidence = factories.EvidenceFactory()
            evidence_id = evidence.id

        factories.RelationshipFactory(source=audit, destination=evidence)

        self.api.set_user(user)

        evidence = all_models.Evidence.query.get(evidence_id)
        new_description = 'new description'
        resp = self.api.modify_object(evidence,
                                      {'description': new_description})
        evidence = self.refresh_object(evidence)

        if status_code == 200:
            self.assert200(resp)
            self.assertEquals(new_description, evidence.description)
            self.assertEquals(user.id, evidence.modified_by_id)
        else:
            self.assertStatus(resp, status_code)

    def test_audit_role_propagation_not_delete(self):
        """Audit user with role Auditors can NOT delete related evidence"""
        role_name = "Auditors"
        _, reader = self.generator.generate_person(user_role="Reader")
        with factories.single_commit():
            audit = factories.AuditFactory()
            audit.add_person_with_role_name(reader, role_name)
            evidence = factories.EvidenceFactory()
            evidence_id = evidence.id

        factories.RelationshipFactory(source=audit, destination=evidence)

        self.api.set_user(reader)
        evidence = all_models.Evidence.query.get(evidence_id)

        resp = self.api.delete(evidence)
        self.assertStatus(resp, 403)
        evidence = all_models.Evidence.query.get(evidence_id)
        self.assertTrue(evidence)
コード例 #59
0
class TestTaskDueNotifications(TestCase):
  """Test suite for task due soon/today notifications."""

  # pylint: disable=invalid-name

  def _fix_notification_init(self):
    """Fix Notification object init function.

    This is a fix needed for correct created_at field when using freezgun. By
    default the created_at field is left empty and filed by database, which
    uses system time and not the fake date set by freezugun plugin. This fix
    makes sure that object created in freeze_time block has all dates set with
    the correct date and time.
    """
    def init_decorator(init):
      """"Adjust the value of the object's created_at attribute to now."""
      @functools.wraps(init)
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    models.Notification.__init__ = init_decorator(models.Notification.__init__)

  def setUp(self):
    super(TestTaskDueNotifications, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")

    role_id = models.all_models.AccessControlRole.query.filter(
        models.all_models.AccessControlRole.name == "Task Assignees",
        models.all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id

    self.one_time_workflow = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "is_verification_needed": False,
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": {
                "href": "/api/people/{}".format(self.user.id),
                "id": self.user.id,
                "type": "Person",
            },
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 15),
                "end_date": date(2017, 6, 11),
            }, {
                "title": "task 2",
                "description": "some task 2",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 8),
                "end_date": date(2017, 6, 12),
            }, {
                "title": "task 3",
                "description": "some task 3",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 31),
                "end_date": date(2017, 6, 13),
            }, {
                "title": "task 4",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 2),
                "end_date": date(2017, 6, 14),
            }, {
                "title": "task 5",
                "description": "some task 5",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 8),
                "end_date": date(2017, 6, 15),
            }],
            "task_group_objects": self.random_objects
        }]
    }

  @ddt.unpack
  @ddt.data(
      ("2017-06-12 12:12:12", ["task 1"], ["task 2"], ["task 3"]),
      ("2017-06-13 13:13:13", ["task 1", "task 2"], ["task 3"], ["task 4"]),
  )
  @patch("ggrc.notifications.common.send_email")
  def test_creating_obsolete_notifications(
      self, fake_now, expected_overdue, expected_due_today, expected_due_in, _
  ):
    """Notifications already obsolete on creation date should not be created.
    """
    with freeze_time("2017-06-12 09:39:32"):
      tmp = self.one_time_workflow.copy()
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    user = models.Person.query.get(self.user.id)

    with freeze_time(fake_now):
      # mark all yeasterday notifications as sent
      models.all_models.Notification.query.filter(
          sa.func.DATE(models.all_models.Notification.send_on) < date.today()
      ).update({models.all_models.Notification.sent_at:
                datetime.now() - timedelta(1)},
               synchronize_session="fetch")

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})

      actual_overdue = [n['title'] for n in
                        user_notifs.get("task_overdue", {}).itervalues()]
      actual_overdue.sort()
      self.assertEqual(actual_overdue, expected_overdue)

      self.assertEqual(
          [n['title'] for n in user_notifs.get("due_today", {}).itervalues()],
          expected_due_today)

      self.assertEqual(
          [n['title'] for n in user_notifs.get("due_in", {}).itervalues()],
          expected_due_in)