コード例 #1
0
class TestAccessControlRBAC(TestRBAC):
  """TestAccessControlRBAC tests if users get correct permissions on objects
     from the access control table"""

  def setUp(self):
    super(TestAccessControlRBAC, self).setUp()
    self.api = Api()
    self.set_up_people()
    self.set_up_acl_object()

  @ddt.data("Creator", "Reader", "Editor")
  def test_acl_object_cru(self, name):
    """Test if {0} can CRUD an object with all permissions"""
    control_id = self.control.id
    person = self.people.get(name)
    role_id = self.all_acr.id
    db.session.add(person)
    self.api.set_user(person)
    response = self.api.get(all_models.Control, control_id)
    assert response.status_code == 200, \
        "{} cannot GET object from acl. Received {}".format(
            name, response.status)
    acl = response.json["control"]["access_control_list"]
    assert len(response.json["control"]["access_control_list"]) == 3, \
        "ACL in control does not include all people {}".format(acl)

    assert acl[0].get("ac_role_id", None) == role_id, \
        "ACL list does not include role id {}".format(acl)
コード例 #2
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'
    )
コード例 #3
0
class TestDelete(TestCase, WithQueryApi):
  """Test objects deletion."""

  def setUp(self):
    super(TestDelete, self).setUp()
    self.client.get("/login")
    self.api = Api()

  def test_delete(self):
    """Deletion is synchronous and triggers compute_attributes."""
    control = factories.ControlFactory()

    result = self.api.delete(control)

    controls = db.session.query(all_models.Control).all()
    background_tasks = db.session.query(all_models.BackgroundTask).all()

    self.assert200(result)
    self.assertEqual(len(controls), 0)
    self.assertEqual(len(background_tasks), 1)
    self.assertTrue(background_tasks[0].name.startswith("compute_attributes"))

  def test_delete_http400(self):
    """Deletion returns HTTP400 if BadRequest is raised."""
    with factories.single_commit():
      audit = factories.AuditFactory()
      factories.AssessmentFactory(audit=audit)

    result = self.api.delete(audit)

    self.assert400(result)
    self.assertEqual(result.json["message"],
                     "This request will break a mandatory relationship from "
                     "assessments to audits.")
コード例 #4
0
  def setUp(self):
    """Imports test_csvs/audit_rbac_snapshot_create.csv needed by the tests"""
    TestCase.clear_data()
    self.api = Api()
    self.objgen = integration.ggrc.generator.ObjectGenerator()

    self.csv_files = itertools.cycle([
        "audit_rbac_snapshot_create.csv",
        "audit_rbac_snapshot_update.csv"
    ])

    self._import_file(next(self.csv_files))
    self.people = all_models.Person.eager_query().all()

    self.program = db.session.query(all_models.Program).filter(
        all_models.Program.slug == "PMRBACPROGRAM-1"
    ).one()

    sources = set(r.source for r in self.program.related_sources)
    destinations = set(r.destination
                       for r in self.program.related_destinations)
    related = [obj for obj in sources.union(destinations)
               if not isinstance(obj, all_models.Person)]
    self.related_objects = related

    self.api = Api()
    self.client.get("/login")

    self.audit = self.create_audit()

    self.snapshots = all_models.Snapshot.eager_query().all()

    self.sanity_check()
コード例 #5
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))
コード例 #6
0
class TestResource(TestCase):
  """
  Test /search REST API
  """

  def setUp(self):
    super(TestResource, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.create_objects()

  def create_objects(self):
    """Create objects to be searched.

    Creates five Requirements and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
    self.objects = [
        self.object_generator.generate_object(all_models.Requirement)[1].id
        for _ in xrange(5)
    ]
    self.objects = all_models.Requirement.eager_query().filter(
        all_models.Requirement.id.in_(self.objects)
    ).all()
    for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
      self.object_generator.generate_relationship(
          self.objects[src], self.objects[dst]
      )

  def search(self, *args, **kwargs):
    res, _ = self.api.search(*args, **kwargs)
    return res.json["results"]["entries"]

  def test_search_all(self):
    """Test search for all objects of a type."""
    res, _ = self.api.search("Requirement")
    self.assertEqual(len(res.json["results"]["entries"]), 5)

  def test_search_query(self):
    """Test search with query by title."""
    entries = self.search("Requirement", query=self.objects[0].title)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[0].id})

  def test_search_relevant(self):
    """Test search with 'relevant to' single object."""
    relevant_objects = "Requirement:{}".format(self.objects[0].id)
    entries = self.search("Requirement", relevant_objects=relevant_objects)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[i].id for i in [1, 2]})

  def test_search_relevant_multi(self):
    """Test search with 'relevant to' multiple objects."""
    ids = ",".join("Requirement:{}".format(self.objects[i].id) for i in (0, 3))
    entries = self.search("Requirement", relevant_objects=ids)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[2].id})
コード例 #7
0
ファイル: test_assessments.py プロジェクト: Smotko/ggrc-core
class TestCollection(TestCase, WithQueryApi):

  """Test for collection assessment objects."""

  def setUp(self):
    super(TestCollection, self).setUp()
    self.client.get("/login")
    self.clear_data()
    self.expected_ids = []
    self.api = Api()
    self.generator = ObjectGenerator()
    assessments = [factories.AssessmentFactory() for _ in range(10)]
    random.shuffle(assessments)
    for idx, assessment in enumerate(assessments):
      comment = factories.CommentFactory(description=str(idx))
      factories.RelationshipFactory(source=assessment, destination=comment)
      self.expected_ids.append(assessment.id)

  @data(True, False)
  def test_order_by_test(self, desc):
    """Order by fultext attr"""
    query = self._make_query_dict(
        "Assessment", order_by=[{"name": "comment", "desc": desc}]
    )
    expected_ids = self.expected_ids
    if desc:
      expected_ids = expected_ids[::-1]
    results = self._get_first_result_set(query, "Assessment", "values")
    self.assertEqual(expected_ids, [i['id'] for i in results])

  @data("Assessor", "Creator", "Verifier")
  def test_delete_assessment_by_role(self, role_name):
    """Delete assessment not allowed for based on Assignee Type."""
    with factories.single_commit():
      assessment = factories.AssessmentFactory()
      context = factories.ContextFactory(related_object=assessment)
      assessment.context = context
      person = factories.PersonFactory()
      object_person_rel = factories.RelationshipFactory(
          source=assessment, destination=person)
      factories.RelationshipAttrFactory(
          relationship_id=object_person_rel.id,
          attr_name="AssigneeType",
          attr_value=role_name,
      )
    assessment_id = assessment.id
    role = all_models.Role.query.filter(
        all_models.Role.name == "Creator"
    ).first()
    self.generator.generate_user_role(person, role, context)
    self.api.set_user(person)
    assessment = all_models.Assessment.query.get(assessment_id)
    resp = self.api.delete(assessment)
    self.assert403(resp)
    self.assertTrue(all_models.Assessment.query.filter(
        all_models.Assessment.id == assessment_id).one())
コード例 #8
0
ファイル: test_archived.py プロジェクト: egorhm/ggrc-core
class TestArchived(WithQueryApi, TestCase):
  """Tests for filtering by Archived field."""
  def setUp(self):
    super(TestArchived, self).setUp()
    self.client.get("/login")
    self.api = Api()

  @ddt.data([1, 3])
  def test_archived_audits(self, archived_audits):
    """Test filtration by Archived Audits."""
    with factories.single_commit():
      audit_ids = [factories.AuditFactory().id for _ in range(5)]

    expected_ids = []
    for i in archived_audits:
      audit = all_models.Audit.query.get(audit_ids[i])
      response = self.api.put(audit, {"archived": True})
      self.assert200(response)
      expected_ids.append(audit_ids[i])

    ids = self.simple_query(
        "Audit",
        expression=["archived", "=", "true"],
        type_="ids",
        field="ids"
    )
    self.assertItemsEqual(ids, expected_ids)

  @ddt.data([2, 4])
  def test_archived_assessments(self, archived_audits):
    """Test filtration by Archived Assessments."""
    # Create 5 Audits, each of them has 3 Assessment
    with factories.single_commit():
      audit_ids = []
      for _ in range(5):
        audit = factories.AuditFactory()
        audit_ids.append(audit.id)
        for _ in range(3):
          factories.AssessmentFactory(audit=audit)

    # This list contain ids of assessments from audits in archived_audits
    expected_ids = []
    for i in archived_audits:
      audit = all_models.Audit.query.get(audit_ids[i])
      expected_ids += [a.id for a in audit.assessments]
      response = self.api.put(audit, {"archived": True})
      self.assert200(response)

    ids = self.simple_query(
        "Assessment",
        expression=["archived", "=", "true"],
        type_="ids",
        field="ids"
    )
    self.assertItemsEqual(ids, expected_ids)
コード例 #9
0
ファイル: __init__.py プロジェクト: zidarsk8/ggrc-core
 def _import_file(cls, filename, dry_run=False, person=None):
   """Function that handle sending file to import_csv service"""
   data = {"file": (open(os.path.join(cls.CSV_DIR, filename)), filename)}
   headers = {
       "X-test-only": "true" if dry_run else "false",
       "X-requested-by": "GGRC",
   }
   api = Api()
   api.set_user(person)  # Ok if person is None
   response = api.client.post("/_service/import_csv",
                              data=data, headers=headers)
   return json.loads(response.data)
コード例 #10
0
ファイル: __init__.py プロジェクト: google/ggrc-core
 def send_import_request(cls, data, dry_run=False, person=None):
   """Sending import post request."""
   cls.init_taskqueue()
   headers = {
       "X-test-only": "true" if dry_run else "false",
       "X-requested-by": "GGRC",
   }
   api = Api()
   api.set_user(person)  # Ok if person is None
   response = api.client.post("/_service/import_csv",
                              data=data, headers=headers)
   return json.loads(response.data)
コード例 #11
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)
コード例 #12
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)
コード例 #13
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'
    )
コード例 #14
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())
コード例 #15
0
  def setUp(self):
    """Create API instance
    """

    super(TestWorkflowTypesBase, self).setUp()

    self.api = Api()
コード例 #16
0
ファイル: test_audit_rbac.py プロジェクト: egorhm/ggrc-core
  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)
コード例 #17
0
  def setUp(self):
    """Set up."""
    super(TestWfNotifsGenerator, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    with freeze_time("2015-05-01 14:29:00"):
      wf_slug = "wf1"
      with factories.single_commit():
        wf = wf_factories.WorkflowFactory(slug=wf_slug)
        task_group = wf_factories.TaskGroupFactory(workflow=wf)
        wf_factories.TaskGroupTaskFactory(
            task_group=task_group,
            title='task1',
            start_date=datetime.now(),
            end_date=datetime.now() + timedelta(7)
        )
      data = workflow_api.get_cycle_post_dict(wf)
      self.api.post(all_models.Cycle, data)
      wf = all_models.Workflow.query.filter_by(slug=wf_slug).one()
      self.cycle = all_models.Cycle.query.filter_by(workflow_id=wf.id).one()
      self.ctask = all_models.CycleTaskGroupObjectTask.query.filter_by(
          cycle_id=self.cycle.id).first()
コード例 #18
0
 def setUp(self):
   super(TestReader, self).setUp()
   self.generator = Generator()
   self.api = Api()
   self.object_generator = ObjectGenerator()
   self.init_users()
   self.init_assignable()
コード例 #19
0
 def setUp(self):
   super(TestWorkflowsApiPost, self).setUp()
   self.api = Api()
   self.generator = wf_generator.WorkflowsGenerator()
   self.wf_admin_id = all_models.Person.query.first().id
   with factories.single_commit():
     self.people_ids = [factories.PersonFactory().id for _ in xrange(6)]
コード例 #20
0
ファイル: test_audit_rbac.py プロジェクト: zidarsk8/ggrc-core
  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)
コード例 #21
0
class TestDocumentQueries(TestCase):
  """Tests for /query api for Document instance filtering."""

  def setUp(self):
    super(TestDocumentQueries, self).setUp()
    self.api = Api()

  @ddt.data(all_models.Document.FILE, all_models.Document.REFERENCE_URL)
  def test_filter_document_by_type(self, kind):
    """Test filter documents by document type."""
    data = {
        all_models.Document.FILE: factories.DocumentFileFactory().id,
        all_models.Document.REFERENCE_URL:
            factories.DocumentReferenceUrlFactory().id,
    }
    query_request_data = [{
        u'fields': [],
        u'filters': {
            u'expression': {
                u'left': u'kind',
                u'op': {u'name': u'='},
                u'right': kind,
            }
        },
        u'limit': [0, 5],
        u'object_name': u'Document',
        u'permissions': u'read',
        u'type': u'values',
    }]
    resp = self.api.send_request(self.api.client.post,
                                 data=query_request_data,
                                 api_link="/query")
    self.assertEqual(1, resp.json[0]["Document"]["count"])
    self.assertEqual(data[kind],
                     resp.json[0]["Document"]["values"][0]["id"])
コード例 #22
0
 def setUp(self):
   """Prepare data needed to run the tests"""
   self.api = Api()
   self.setup_roles()
   self.setup_users()
   self.setup_audits()
   self.setup_snapshots_and_issue()
コード例 #23
0
  def setUp(self):  # noqa
    super(TestBacklogWorkflow, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.create_backlog_workflow()
コード例 #24
0
 def setUp(self):
   super(TestCreatorAudit, self).setUp()
   self.generator = Generator()
   self.api = Api()
   self.object_generator = ObjectGenerator()
   self.init_users()
   self.init_test_cases()
   self.objects = {}
コード例 #25
0
class TestWorkflowTypesBase(TestCase):
  """
  Base class for /search REST API test
  """

  def setUp(self):
    """Create API instance
    """

    super(TestWorkflowTypesBase, self).setUp()

    self.api = Api()

  def _get_search_ids(self, types, query):
    """Make request and return entries in format dict(type->list_of_ids)"""
    response, _ = self.api.search(types=types, query=query, counts=False)

    entries = response.json['results']['entries']

    ret = defaultdict(set)
    for entry in entries:
      ret[entry['type']].add(entry['id'])

    return dict(ret)

  def _get_count_ids(self, types, query):
    """Make request and return entries in format dict(type->number_of_ids)"""
    response, _ = self.api.search(types=types, query=query, counts=True)

    return response.json['results']['counts']

  def _convert_expected_to_dict(self, type_, expected):
    """Convert list of (type, title) to dict (type -> list_of_ids)"""

    ret = defaultdict(set)
    for _, key in expected:
      ret[type_].add(self.objects[key])

    return dict(ret)

  @staticmethod
  # pylint: disable=invalid-name
  def _convert_expected_dict_to_counts(expected):
    """Convert dict(type->list_of_ids) to dict(type->count_of_ids)"""

    return dict((k, len(v)) for k, v in expected.iteritems())
コード例 #26
0
 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()
コード例 #27
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)
コード例 #28
0
  def setUp(self):
    super(TestPermissionsLoading, self).setUp()
    self.api = Api()
    self.generator = generator.ObjectGenerator()

    self.control_id = factories.ControlFactory().id

    _, user = self.generator.generate_person(user_role="Creator")
    self.api.set_user(user)
コード例 #29
0
 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
コード例 #30
0
 def setUp(self):
   super(TestAssigneeRBAC, self).setUp()
   self.api = Api()
   self.set_up_people()
   self.assignee_roles = {
       role_name: role_id
       for role_id, role_name in get_custom_roles_for("Assessment").items()
       if role_name in ["Assignees", "Creators", "Verifiers"]
   }
コード例 #31
0
 def setUp(self):
     super(TestDocumentQueries, self).setUp()
     self.api = Api()
コード例 #32
0
ファイル: test_api_calls.py プロジェクト: sepatus88/ggrc-core
class TestWorkflowsApiPost(TestCase):
  """Test class for ggrc workflow api post action."""

  def setUp(self):
    super(TestWorkflowsApiPost, self).setUp()
    self.api = Api()
    self.generator = wf_generator.WorkflowsGenerator()

  def tearDown(self):
    pass

  def test_send_invalid_data(self):
    """Test send invalid data on Workflow post."""
    data = self.get_workflow_dict()
    del data["workflow"]["title"]
    del data["workflow"]["context"]
    response = self.api.post(all_models.Workflow, data)
    self.assert400(response)
    # TODO: check why response.json["message"] is empty

  def test_create_one_time_workflows(self):
    """Test simple create one time Workflow over api."""
    data = self.get_workflow_dict()
    response = self.api.post(all_models.Workflow, data)
    self.assertEqual(response.status_code, 201)

  def test_create_weekly_workflow(self):
    """Test create valid weekly wf"""
    data = self.get_workflow_dict()
    data["workflow"]["repeat_every"] = 7
    data["workflow"]["unit"] = "day"
    data["workflow"]["title"] = "Weekly"
    response = self.api.post(all_models.Workflow, data)
    self.assertEqual(response.status_code, 201)

  def test_create_annually_workflow(self):
    """Test create valid annual wf"""
    data = self.get_workflow_dict()
    data["workflow"]["repeat_every"] = 12
    data["workflow"]["unit"] = "month"
    data["workflow"]["title"] = "Annually"
    response = self.api.post(all_models.Workflow, data)
    self.assertEqual(response.status_code, 201)

  @ddt.data("wrong value", 0, -4)
  def test_create_wrong_repeat_every_workflow(self, value):  # noqa pylint: disable=invalid-name
    """Test case for invalid repeat_every value"""
    data = self.get_workflow_dict()
    data["workflow"]["repeat_every"] = value
    data["workflow"]["unit"] = "month"
    data["workflow"]["title"] = "Wrong wf"
    response = self.api.post(all_models.Workflow, data)
    self.assertEqual(response.status_code, 400)

  def test_create_wrong_unit_workflow(self):
    """Test case for invalid unit value"""
    data = self.get_workflow_dict()
    data["workflow"]["repeat_every"] = 12
    data["workflow"]["unit"] = "wrong value"
    data["workflow"]["title"] = "Wrong wf"
    response = self.api.post(all_models.Workflow, data)
    self.assertEqual(response.status_code, 400)

  def test_create_task_group(self):
    """Test create task group over api."""
    wf_data = self.get_workflow_dict()
    wf_data["workflow"]["title"] = "Create_task_group"
    wf_response = self.api.post(all_models.Workflow, wf_data)

    data = self.get_task_group_dict(wf_response.json["workflow"])

    response = self.api.post(all_models.TaskGroup, data)
    self.assertEqual(response.status_code, 201)

  # TODO: Api should be able to handle invalid data
  @unittest.skip("Not implemented.")
  def test_create_task_group_invalid_workflow_data(self):  # noqa pylint: disable=invalid-name
    """Test create task group with invalid data."""
    data = self.get_task_group_dict({"id": -1, "context": {"id": -1}})
    response = self.api.post(all_models.TaskGroup, data)
    self.assert400(response)

  @staticmethod
  def get_workflow_dict():
    return {
        "workflow": {
            "custom_attribute_definitions": [],
            "custom_attributes": {},
            "title": "One_time",
            "description": "",
            "unit": None,
            "repeat_every": None,
            "notify_on_change": False,
            "task_group_title": "Task Group 1",
            "notify_custom_message": "",
            "is_verification_needed": True,
            "owners": None,
            "context": None,
        }
    }

  @staticmethod
  def get_task_group_dict(workflow):
    return {
        "task_group": {
            "custom_attribute_definitions": [],
            "custom_attributes": {},
            "_transient": {},
            "contact": {
                "id": 1,
                "href": "/api/people/1",
                "type": "Person"
            },
            "workflow": {
                "id": workflow["id"],
                "href": "/api/workflows/%d" % workflow["id"],
                "type": "Workflow"
            },
            "context": {
                "id": workflow["context"]["id"],
                "href": "/api/contexts/%d" % workflow["context"]["id"],
                "type": "Context"
            },
            "modal_title": "Create Task Group",
            "title": "Create_task_group",
            "description": "",
        }
    }

  @ddt.data({},
            {"repeat_every": 5,
             "unit": "month"})
  def test_repeat_multiplier_field(self, data):
    """Check repeat_multiplier is set to 0 after wf creation."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(**data)
    workflow_id = workflow.id
    self.assertEqual(
        0,
        all_models.Workflow.query.get(workflow_id).repeat_multiplier
    )

  # TODO: Unskip in the patch 2
  @unittest.skip("Will be activated in patch 2")
  def test_change_to_one_time_wf(self):
    """Check repeat_every and unit can be set to Null only together."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(repeat_every=12,
                                              unit="day")
    resp = self.api.put(workflow, {"repeat_every": None,
                                   "unit": None})
    self.assert200(resp)

  @ddt.data({"repeat_every": 5},
            {"unit": "month"})
  def test_change_repeat_every(self, data):
    """Check repeat_every or unit can not be changed once set."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory()
    resp = self.api.put(workflow, data)
    self.assert400(resp)

  def test_not_change_to_one_time_wf(self):
    """Check repeat_every or unit can't be set to Null separately.
    This test will be useful in the 2nd patch, where we allow to change
    WF setup
    """
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(repeat_every=12,
                                              unit="day")
    resp = self.api.put(workflow, {"repeat_every": None})
    self.assert400(resp)
    resp = self.api.put(workflow, {"unit": None})
    self.assert400(resp)

  @ddt.data(True, False)
  def test_autogen_verification_flag(self, flag):
    """Check is_verification_needed flag for activate WF action."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(is_verification_needed=flag)
      group = wf_factories.TaskGroupFactory(workflow=workflow)
      wf_factories.TaskGroupTaskFactory(task_group=group)
    data = [{
        "cycle": {
            "autogenerate": True,
            "isOverdue": False,
            "workflow": {
                "id": workflow.id,
                "type": "Workflow",
            },
            "context": {
                "id": workflow.context_id,
                "type": "Context",
            },
        }
    }]
    resp = self.api.send_request(
        self.api.client.post,
        api_link="/api/cycles",
        data=data)
    cycle_id = resp.json[0][1]["cycle"]["id"]
    self.assertEqual(
        flag,
        all_models.Cycle.query.get(cycle_id).is_verification_needed)

  @ddt.data(True, False)
  def test_change_verification_flag_positive(self, flag):  # noqa pylint: disable=invalid-name
    """is_verification_needed flag is changeable for DRAFT workflow."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(is_verification_needed=flag)
    self.assertEqual(workflow.status, all_models.Workflow.DRAFT)
    workflow_id = workflow.id
    resp = self.api.put(workflow, {"is_verification_needed": not flag})
    self.assert200(resp)
    self.assertEqual(
        all_models.Workflow.query.get(workflow_id).is_verification_needed,
        not flag)

  @ddt.data(True, False)
  def test_change_verification_flag_negative(self, flag):  # noqa pylint: disable=invalid-name
    with freezegun.freeze_time("2017-08-10"):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(
            unit=all_models.Workflow.WEEK_UNIT,
            is_verification_needed=flag,
            repeat_every=1)
        wf_factories.TaskGroupTaskFactory(
            task_group=wf_factories.TaskGroupFactory(
                context=factories.ContextFactory(),
                workflow=workflow
            ),
            # Two cycles should be created
            start_date=datetime.date(2017, 8, 3),
            end_date=datetime.date(2017, 8, 7))
      workflow_id = workflow.id
      self.assertEqual(workflow.status, all_models.Workflow.DRAFT)
      self.generator.activate_workflow(workflow)
      workflow = all_models.Workflow.query.get(workflow_id)
      self.assertEqual(workflow.status, all_models.Workflow.ACTIVE)
      resp = self.api.put(workflow, {"is_verification_needed": not flag})
      self.assert400(resp)
      workflow = all_models.Workflow.query.get(workflow_id)
      self.assertEqual(workflow.is_verification_needed, flag)

      # End all current cycles
      for cycle in workflow.cycles:
        self.generator.modify_object(cycle, {'is_current': False})
      workflow = all_models.Workflow.query.filter(
          all_models.Workflow.id == workflow_id).first()
      self.assertEqual(workflow.status, all_models.Workflow.INACTIVE)
      resp = self.api.put(workflow, {"is_verification_needed": not flag})
      self.assert400(resp)
      workflow = all_models.Workflow.query.get(workflow_id)
      self.assertEqual(workflow.is_verification_needed, flag)

  @ddt.data(True, False)
  def test_not_change_vf_flag(self, flag):
    """Check is_verification_needed not change on update."""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory(is_verification_needed=flag)
    workflow_id = workflow.id
    resp = self.api.put(workflow, {"is_verification_needed": flag})
    self.assert200(resp)
    self.assertEqual(
        flag,
        all_models.Workflow.query.get(workflow_id).is_verification_needed)

  @ddt.data(True, False, None)
  def test_create_vf_flag(self, flag):
    """Check is_verification_needed flag setup on create."""
    data = self.get_workflow_dict()
    if flag is None:
      data['workflow'].pop('is_verification_needed', None)
    else:
      data['workflow']['is_verification_needed'] = flag
    resp = self.api.post(all_models.Workflow, data)
    self.assertEqual(201, resp.status_code)
    workflow_id = resp.json['workflow']['id']
    self.assertEqual(
        flag if flag is not None else True,
        all_models.Workflow.query.get(workflow_id).is_verification_needed)
コード例 #33
0
ファイル: test_reader.py プロジェクト: sepatus88/ggrc-core
 def setUp(self):
   super(TestReader, self).setUp()
   self.generator = Generator()
   self.api = Api()
   self.object_generator = ObjectGenerator()
   self.init_users()
コード例 #34
0
 def setUp(self):
   super(TestProposalEmail, self).setUp()
   self.api = Api()
   self.client.get("/login")
コード例 #35
0
ファイル: test_delete.py プロジェクト: vincent9407/ggrc-core
 def setUp(self):
     super(TestDelete, self).setUp()
     self.client.get("/login")
     self.api = Api()
コード例 #36
0
class TestAuditRBAC(TestCase):
  """Test audit RBAC"""
  # pylint: disable=too-many-instance-attributes

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

  def setUp(self):
    """Imports test_csvs/audit_rbac_snapshot_create.csv needed by the tests"""
    TestCase.clear_data()
    self.api = Api()
    self.objgen = integration.ggrc.generator.ObjectGenerator()

    self.csv_files = itertools.cycle([
        "audit_rbac_snapshot_create.csv",
        "audit_rbac_snapshot_update.csv"
    ])

    response = self._import_file(next(self.csv_files))
    self._check_csv_response(response, {})

    self.people = all_models.Person.eager_query().all()

    self.auditor_role = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Auditors"
    ).one()

    self.program = db.session.query(all_models.Program).filter(
        all_models.Program.slug == "PMRBACPROGRAM-1"
    ).one()

    sources = set(r.source for r in self.program.related_sources)
    destinations = set(r.destination
                       for r in self.program.related_destinations)
    related = [obj for obj in sources.union(destinations)
               if not isinstance(obj, all_models.Person)]
    self.related_objects = related

    self.api = Api()
    self.client.get("/login")

    self.audit = self.create_audit()

    self.snapshots = all_models.Snapshot.eager_query().all()

  def create_audit(self):
    """Create default audit for audit snapshot RBAC tests"""
    people = {person.email: person for person in self.people}
    auditor_emails = [
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
    ]
    _, audit = self.objgen.generate_object(all_models.Audit, {
        "title": "Snapshotable audit",
        "program": {"id": self.program.id},
        "status": "Planned",
        "snapshots": {
            "operation": "create",
        },
        "access_control_list": [{
            "ac_role_id": self.auditor_role.id,
            "person": {
                "id": people[person].id,
                "type": "Person"
            }
        } for person in auditor_emails],
        "context": {
            "type": "Context",
            "id": self.program.context_id,
            "href": "/api/contexts/{}".format(self.program.context_id)
        }
    })
    return audit

  def update_audit(self):
    """Update default audit"""
    response = self._import_file(next(self.csv_files))
    self._check_csv_response(response, {})

    audit = all_models.Audit.query.filter(
        all_models.Audit.title == "Snapshotable audit"
    ).one()
    self.audit = audit

    self.api.modify_object(self.audit, {
        "snapshots": {
            "operation": "upsert"
        }
    })

  def read(self, objects):
    """Attempt to do a GET request for every object in the objects list"""
    responses = []
    for obj in objects:
      status_code = self.api.get(obj.__class__, obj.id).status_code
      responses.append((obj.type, status_code))
    return responses

  def update(self, objects):
    """Attempt to do a PUT request for every object in the objects list"""
    scope_response = self.api.get(self.audit.__class__, self.audit.id)
    if scope_response.status_code == 200:
      self.update_audit()

    responses = []
    for obj in objects:
      response = self.api.get(obj.__class__, obj.id)
      status_code = response.status_code
      if response.status_code == 200:
        data = response.json
        if obj.type == "Snapshot":
          data.update({
              "update_revision": "latest"
          })
        put_call = self.api.put(obj, data)
        status_code = put_call.status_code
      responses.append((obj.type, status_code))
    return responses

  def call_api(self, method, expected_statuses):
    """Calls the REST api with a given method and returns a list of
       status_codes that do not match the expected_statuses dict"""
    all_errors = []
    for person in self.people:
      self.api.set_user(person)
      responses = method(self.snapshots + [self.audit])
      for type_, code in responses:
        if code != expected_statuses[person.email][type_]:
          all_errors.append("{} does not have {} access to {} ({})".format(
              person.email, method.__name__, type_, code))
    return all_errors

  def test_read_access_on_mapped(self):
    """Test READ access to snapshotted objects of default audit"""
    expected_statuses = defaultdict(lambda: defaultdict(lambda: 200))
    exceptional_users = (
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
    )
    for user, exceptions in exceptional_users:
      for type_, status_code in exceptions.items():
        expected_statuses[user][type_] = status_code
    errors = self.call_api(self.read, expected_statuses)
    assert not errors, "\n".join(errors)

  def test_update_access_on_mapped(self):
    """Test UPDATE access to snapshotted objects of default audit"""
    expected_statuses = defaultdict(lambda: defaultdict(lambda: 200))

    exceptional_users = (
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        # Auditor roles
        ("*****@*****.**", DEFAULT_AUDITOR_PERMISSIONS),
        ("*****@*****.**", DEFAULT_AUDITOR_PERMISSIONS)
    )

    for user, exceptions in exceptional_users:
      for type_, status_code in exceptions.items():
        expected_statuses[user][type_] = status_code

    errors = self.call_api(self.update, expected_statuses)
    assert not errors, "\n".join(errors)
コード例 #37
0
class TestBulkIssuesSync(TestCase):
  """Base class for bulk issuetracker synchronization tests."""

  def setUp(self):
    """Set up for test methods."""
    super(TestBulkIssuesSync, self).setUp()
    self.api = Api()
    self.gen = generator.ObjectGenerator()

    self.role_people = {
        "Audit Captains": factories.PersonFactory(email="*****@*****.**"),
        "Creators": factories.PersonFactory(email="*****@*****.**"),
        "Assignees": factories.PersonFactory(email="*****@*****.**"),
        "Verifiers": factories.PersonFactory(email="*****@*****.**"),
    }
    self.issue_id = "42"

  def setup_assessments(self, asmnt_count, issue_id=None, enabled=True):
    """Create Audit with couple of Assessments and linked IssueTrackerIssues.

    Args:
        asmnt_count: Count of Assessments in Audit.

    Returns:
        Tuple with Audit id and list of Assessment ids.
    """
    with factories.single_commit():
      audit = factories.AuditFactory()
      audit.add_person_with_role_name(
          self.role_people["Audit Captains"],
          "Audit Captains",
      )
      factories.IssueTrackerIssueFactory(
          enabled=enabled,
          issue_tracked_obj=audit,
          issue_id=issue_id,
          issue_type=constants.DEFAULT_ISSUETRACKER_VALUES['issue_type'],
          component_id=12345,
          hotlist_id=12345,
          issue_priority="P2",
          issue_severity="S2",
      )

      assessment_ids = []
      for _ in range(asmnt_count):
        asmnt = factories.AssessmentFactory(audit=audit)
        factories.RelationshipFactory(source=audit, destination=asmnt)
        for role_name in ["Creators", "Assignees", "Verifiers"]:
          asmnt.add_person_with_role_name(
              self.role_people[role_name],
              role_name,
          )
        factories.IssueTrackerIssueFactory(
            enabled=enabled,
            issue_tracked_obj=asmnt,
            issue_id=issue_id,
            title=None,
        )
        assessment_ids.append(asmnt.id)
      return audit.id, assessment_ids

  @staticmethod
  def setup_issues(issue_count, issue_id=None, enabled=True):
    """Create issues with enabled integration."""
    with factories.single_commit():
      issue_ids = []
      for _ in range(issue_count):
        issue = factories.IssueFactory()
        factories.IssueTrackerIssueFactory(
            enabled=enabled,
            issue_tracked_obj=issue,
            issue_id=issue_id,
            title=None,
        )
        issue_ids.append(issue.id)
      return issue_ids

  def issuetracker_sync_mock(self, sync_func_name):
    """IssueTracker sync method mock."""
    return mock.patch.object(
        sync_utils,
        sync_func_name,
        return_value={"issueId": self.issue_id}
    )

  def generate_children_issues_for(self, parent_type, parent_id, child_type):
    """Generate IssueTracker issue for objects with provided type and ids.

    Args:
        obj_type: Type of objects. Now only 'Assessment' supported.
        obj_ids: List with ids of objects.

    Returns:
        Response with result of issues generation.
    """
    with self.issuetracker_sync_mock("create_issue"):
      return self.api.send_request(
          self.api.client.post,
          api_link="/generate_children_issues",
          data={
              "parent": {"type": parent_type, "id": parent_id},
              "child_type": child_type,
          }
      )

  def generate_issues_for(self, object_info):
    """Generate IssueTracker issues for provided objects."""
    with self.issuetracker_sync_mock("create_issue"):
      return self.api.send_request(
          self.api.client.post,
          api_link="/generate_issues",
          data={
              "objects": [{
                  "type": type_,
                  "id": id_,
                  "hotlist_ids": hotlist_id,
                  "component_id": component_id,
              } for type_, id_, hotlist_id, component_id in object_info],
          }
      )

  def update_issues_for(self, object_info):
    """Update IssueTracker issues for provided objects."""
    with self.issuetracker_sync_mock("update_issue"):
      return self.api.send_request(
          self.api.client.post,
          api_link="/update_issues",
          data={
              "objects": [{
                  "type": type_,
                  "id": id_,
                  "hotlist_ids": hotlist_id,
                  "component_id": component_id,
              } for type_, id_, hotlist_id, component_id in object_info],
          }
      )

  def assert_obj_issues(self, issuetracker_info, assignee=None):
    """Check correctness of created IssueTracker issues."""
    for type_, id_, hotlist_id, component_id in issuetracker_info:
      obj = inflector.get_model(type_).query.get(id_)
      issue = obj.issuetracker_issue

      self.assertEqual(issue.enabled, 1)
      self.assertEqual(issue.title, obj.title)
      self.assertEqual(issue.component_id, component_id)
      self.assertEqual(issue.hotlist_id, hotlist_id)
      self.assertEqual(
          issue.issue_type,
          constants.DEFAULT_ISSUETRACKER_VALUES['issue_type']
      )
      self.assertEqual(issue.issue_priority, "P2")
      self.assertEqual(issue.issue_severity, "S2")
      self.assertEqual(issue.assignee, assignee)
      self.assertEqual(issue.cc_list, "")
      self.assertEqual(issue.issue_id, self.issue_id)
      self.assertEqual(
          issue.issue_url,
          "http://issue/{}".format(self.issue_id)
      )

  def assert_children_asmnt_issues(self, asmnt_ids):
    """Check if Assessments IssueTracker issues inherit data from Audit."""
    assessments = all_models.Assessment.query.filter(
        all_models.Assessment.id.in_(asmnt_ids)
    )
    for asmnt in assessments:
      issue = asmnt.issuetracker_issue
      parent_issue = asmnt.audit.issuetracker_issue

      self.assertEqual(issue.enabled, 1)
      self.assertEqual(issue.title, asmnt.title)
      self.assertEqual(issue.component_id, parent_issue.component_id)
      self.assertEqual(issue.hotlist_id, parent_issue.hotlist_id)
      self.assertEqual(issue.issue_type, parent_issue.issue_type)
      self.assertEqual(issue.issue_priority, parent_issue.issue_priority)
      self.assertEqual(issue.issue_severity, parent_issue.issue_severity)
      self.assertEqual(issue.assignee, "*****@*****.**")
      self.assertEqual(issue.cc_list, "")
      self.assertEqual(issue.issue_id, self.issue_id)
      self.assertEqual(
          issue.issue_url,
          "http://issue/{}".format(self.issue_id)
      )

  def assert_not_updated(self, object_type, object_ids):
    """Check if IssueTracker issues have empty fields.

    Args:
        object_type: Type of objects which issues should be checked.
        object_ids: List with ids for objects which issues should be checked.

    Raise:
        AssertionError if relevant Issues have non-empty base fields.
    """
    issues = all_models.IssuetrackerIssue.query.filter(
        all_models.IssuetrackerIssue.object_type == object_type,
        all_models.IssuetrackerIssue.object_id.in_(object_ids),
    )
    for issue in issues:
      self.assertEqual(issue.issue_id, None)
      self.assertEqual(issue.assignee, None)
      self.assertEqual(issue.cc_list, "")
      self.assertEqual(issue.title, None)
コード例 #38
0
 def setUp(self):
   super(TestWorkflowsCycleGeneration, self).setUp()
   self.api = Api()
   self.generator = WorkflowsGenerator()
   self.object_generator = ObjectGenerator()
コード例 #39
0
class TestWorkflowsCycleGeneration(TestCase):
  """
  Tests for Cycle generation logic
  """
  def setUp(self):
    super(TestWorkflowsCycleGeneration, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

  def tearDown(self):
    pass

  @ddt.data(
      True, False
  )
  def test_recurring_without_tgts_skip(self, has_tg):
    """Test that Active Workflow without TGTs is skipped on cron job"""
    with freeze_time(dtm.date(2017, 9, 25)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                unit=Workflow.MONTH_UNIT)
        workflow_id = workflow.id
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=dtm.date(2017, 9, 26),
            end_date=dtm.date(2017, 9, 26) + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)
      active_wf = db.session.query(Workflow).filter(
          Workflow.id == workflow_id).one()
      self.assertEqual(active_wf.next_cycle_start_date, dtm.date(2017, 9, 26))
      self.assertEqual(active_wf.recurrences, True)
      self.assertEqual(len(active_wf.cycles), 0)
      TaskGroupTask.query.delete()
      if not has_tg:
        TaskGroup.query.delete()
      db.session.commit()

    with freeze_time(dtm.date(2017, 10, 25)):
      start_recurring_cycles()
      active_wf = db.session.query(Workflow).filter(
          Workflow.id == workflow_id).one()
      self.assertEqual(active_wf.next_cycle_start_date, dtm.date(2017, 9, 26))
      self.assertEqual(active_wf.recurrences, True)
      self.assertEqual(len(active_wf.cycles), 0)

  @ddt.data(
      # (expected, setup_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 2, 28)),
      (dtm.date(2017, 3, 3), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 8, 4), dtm.date(2017, 8, 5)),
      (dtm.date(2017, 7, 21), dtm.date(2017, 7, 22)),
  )
  @ddt.unpack
  def test_one_time_wf_start_date_shifting(self, expected, setup_date):
    """Test case for correct cycle task start_ dates for one_time wf"""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory()
      group = wf_factories.TaskGroupFactory(workflow=workflow)
      wf_factories.TaskGroupTaskFactory(
          task_group=group,
          start_date=setup_date,
          end_date=setup_date + dtm.timedelta(days=4))
    self.generator.generate_cycle(workflow)
    self.generator.activate_workflow(workflow)
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(1,
                     len(active_wf.cycles[0].cycle_task_group_object_tasks))
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(expected, adj_start_date)

  @ddt.data(
      # (expected, end_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 2, 28)),
      (dtm.date(2017, 3, 3), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 8, 4), dtm.date(2017, 8, 5)),
      (dtm.date(2017, 7, 21), dtm.date(2017, 7, 22)),
  )
  @ddt.unpack
  def test_one_time_wf_end_date_shifting(self, expected, setup_date):
    """Test case for correct cycle task end_ dates for one_time wf"""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory()
      group = wf_factories.TaskGroupFactory(workflow=workflow)
      wf_factories.TaskGroupTaskFactory(
          task_group=group,
          start_date=setup_date - dtm.timedelta(days=4),
          end_date=setup_date)
    self.generator.generate_cycle(workflow)
    self.generator.activate_workflow(workflow)
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(1,
                     len(active_wf.cycles[0].cycle_task_group_object_tasks))
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_end_date = cycle_task.end_date
    self.assertEqual(expected, adj_end_date)

  # pylint: disable=too-many-arguments
  @ddt.data(
      # (expected, setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 3, 31), dtm.date(2017, 2, 28), dtm.date(2017, 4, 1), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2016, 3, 28), dtm.date(2016, 2, 28), dtm.date(2016, 4, 1), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 2, 28), dtm.date(2017, 1, 31), dtm.date(2017, 3, 31), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 17), dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1,
       Workflow.WEEK_UNIT),
      (dtm.date(2017, 2, 28), dtm.date(2016, 2, 29), dtm.date(2017, 3, 29), 12,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 4, 28), dtm.date(2017, 1, 31), dtm.date(2017, 5, 31), 3,
       Workflow.MONTH_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_start_date_shifting(self, expected, setup_date,
                                            freeze_date, repeat_every, unit):
    """Test case for correct next cycle task start_date for recurring wf"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    cycle_task = active_wf.cycles[1].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(expected, adj_start_date)

  @ddt.data(
      # today is dtm.date(2017, 8, 15), task repeat every
      # (setup_start_date, update_start_date, expected_date),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 1), dtm.date(2017, 9, 1)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 5), dtm.date(2017, 9, 5)),
      # new cycle starts on weekend that's why it moves to friday
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 10), dtm.date(2017, 9, 8)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 8, 15), dtm.date(2017, 9, 15)),
      # new cycle starts on weekend that's why it moves to friday
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 20), dtm.date(2017, 8, 18)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 25), dtm.date(2017, 8, 25)),
      (dtm.date(2017, 8, 16), dtm.date(2017, 8, 14), dtm.date(2017, 9, 14)),
      (dtm.date(2017, 8, 16), dtm.date(2017, 8, 18), dtm.date(2017, 8, 18)),
      (dtm.date(2017, 8, 14), dtm.date(2017, 8, 18), dtm.date(2017, 8, 18)),
  )
  @ddt.unpack
  def test_recalculate_date(self,
                            setup_start_date,
                            update_start_date,
                            expected_date):
    """Recalculate next cycle start date"""
    with freeze_time(dtm.date(2017, 8, 15)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                status=Workflow.DRAFT,
                                                unit=Workflow.MONTH_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        task_id = wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_start_date,
            end_date=setup_start_date + dtm.timedelta(days=4)).id
      self.generator.activate_workflow(workflow)
      self.api.put(TaskGroupTask.query.get(task_id),
                   {"start_date": update_start_date,
                    "end_date": update_start_date + dtm.timedelta(4)})
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(expected_date, active_wf.next_cycle_start_date)

  def test_recalculate_date_not_started(self):
    """Changing start_date on notstarted workflow will
       not affect next_cycle_start_date"""
    setup_start_date = dtm.date(2017, 1, 15)
    update_start_date = dtm.date(2017, 1, 1)
    with freeze_time(dtm.date(2017, 8, 15)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                status=Workflow.DRAFT,
                                                unit=Workflow.MONTH_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        task_id = wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_start_date,
            end_date=setup_start_date + dtm.timedelta(days=4)).id
        workflow_id = workflow.id
    self.api.put(TaskGroupTask.query.get(task_id),
                 {"start_date": update_start_date,
                  "end_date": update_start_date + dtm.timedelta(4)})
    self.assertIsNone(Workflow.query.get(workflow_id).next_cycle_start_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 2, 28), dtm.date(2017, 4, 28), 1, Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1, Workflow.WEEK_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_start_date_and_cycles(self, setup_date, freeze_date,
                                              repeat_every, unit):
    """Test case for correct cycle start date and number of cycles"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # freeze_date is chosen so that we expect 3 cycles to be generated:
    self.assertEqual(len(active_wf.cycles), 3)
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(setup_date, adj_start_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit,
      #  exp_start_date, exp_end_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 4, 28), 1, Workflow.MONTH_UNIT,
       dtm.date(2017, 2, 27), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1, Workflow.WEEK_UNIT,
       dtm.date(2017, 3, 9), dtm.date(2017, 3, 14)),
  )
  @ddt.unpack
  def test_recurring_wf_start_end_cycle_dates(self,
                                              setup_date,
                                              freeze_date,
                                              repeat_every,
                                              unit,
                                              exp_start_date,
                                              exp_end_date):
    """Test case for correct cycle start and end dates"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date - dtm.timedelta(days=1),
            end_date=setup_date + dtm.timedelta(days=3))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # freeze_date is chosen so that we expect 3 cycles to be generated:
    self.assertEqual(len(active_wf.cycles), 3)
    cycle = active_wf.cycles[0]
    self.assertEqual(cycle.start_date, exp_start_date)
    self.assertEqual(cycle.end_date, exp_end_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 4, 28), dtm.date(2017, 2, 28), 1, Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 5), dtm.date(2017, 3, 3), 1, Workflow.DAY_UNIT),
      (dtm.date(2017, 3, 24), dtm.date(2017, 3, 10), 1, Workflow.WEEK_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_future_start_date(self, setup_date, freeze_date,
                                          repeat_every, unit):
    """Test case for 0 number of cycles for future setup date"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # no cycles should be generated:
    self.assertEqual(len(active_wf.cycles), 0)

  @ddt.data(
      # (expected_date, expected_num, setup_date,
      #  freeze_date, repeat_every),
      # should not exclude Jul 4
      (dtm.date(2017, 1, 2), 2, dtm.date(2016, 12, 30),
       dtm.date(2017, 1, 2), 1),
      (dtm.date(2017, 1, 4), 2, dtm.date(2016, 12, 30),
       dtm.date(2017, 1, 8), 3),
      (dtm.date(2017, 7, 7), 5, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 8), 1),
      (dtm.date(2017, 7, 11), 3, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 12), 3),
      (dtm.date(2017, 7, 10), 2, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 11), 5),
      (dtm.date(2017, 7, 12), 2, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 20), 7),
      (dtm.date(2017, 7, 13), 2, dtm.date(2017, 6, 1),
       dtm.date(2017, 7, 31), 30),
  )
  @ddt.unpack
  def test_recurring_daily_workflow_dates(self,
                                          expected_date,
                                          expected_num,
                                          setup_date,
                                          freeze_date,
                                          repeat_every):
    """Test for correct weekdays for daily based workflows.

    When calculating the dates for daily workflows - only week working days
    are taken into account. So neither start date nor end date can fall on
    a weekend. But can fall on holiday.
    Params:
    expected - last generated cycle start date
    """
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=Workflow.DAY_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=repeat_every))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(len(active_wf.cycles), expected_num)
    last_cycle_task = active_wf.cycles[-1].cycle_task_group_object_tasks[0]
    self.assertEqual(expected_date, last_cycle_task.start_date)
コード例 #40
0
ファイル: test_person.py プロジェクト: zdqf/ggrc-core
 def setUp(self):
   super(TestPersonResource, self).setUp()
   self.client.get("/login")
   self.api = Api()
   self.generator = WorkflowsGenerator()
コード例 #41
0
ファイル: test_reader.py プロジェクト: sepatus88/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):
    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)

  @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)
コード例 #42
0
class TestAssessmentGeneration(TestCase):
    """Test assessment generation"""

    # pylint: disable=invalid-name

    def setUp(self):
        super(TestAssessmentGeneration, self).setUp()
        self.api = Api()

        self.audit = factories.AuditFactory()
        self.control = factories.ControlFactory(test_plan="Control Test Plan")
        revision = Revision.query.filter(
            Revision.resource_id == self.control.id, Revision.resource_type ==
            self.control.__class__.__name__).order_by(
                Revision.id.desc()).first()
        self.snapshot = factories.SnapshotFactory(
            parent=self.audit,
            child_id=self.control.id,
            child_type=self.control.__class__.__name__,
            revision_id=revision.id)

    def assessment_post(self, template=None):
        """Helper function to POST an assessment"""
        assessment_dict = {
            "_generated": True,
            "audit": {
                "id": self.audit.id,
                "type": "Audit"
            },
            "object": {
                "id": self.snapshot.id,
                "type": "Snapshot"
            },
            "context": {
                "id": self.audit.context.id,
                "type": "Context"
            },
            "title": "Temp title"
        }
        if template:
            assessment_dict["template"] = {
                "id": template.id,
                "type": "AssessmentTemplate"
            }

        return self.api.post(Assessment, {"assessment": assessment_dict})

    def test_autogenerated_title(self):
        """Test autogenerated assessment title"""
        control_title = self.control.title
        audit_title = self.audit.title
        response = self.assessment_post()
        title = response.json["assessment"]["title"]
        self.assertIn(audit_title, title)
        self.assertIn(control_title, title)

    def test_autogenerated_assignees_verifiers(self):
        """Test autogenerated assessment assignees"""
        auditor_role = Role.query.filter_by(name="Auditor").first()

        audit_context = factories.ContextFactory()
        self.audit.context = audit_context

        users = ["*****@*****.**", "*****@*****.**"]

        auditors = []
        for user in users:
            person = factories.PersonFactory(email=user)
            auditors += [person]

        for auditor in auditors:
            rbac_factories.UserRoleFactory(context=audit_context,
                                           role=auditor_role,
                                           person=auditor)

        self.assertEqual(
            UserRole.query.filter_by(role=auditor_role,
                                     context=self.audit.context).count(), 2,
            "Auditors not present")

        response = self.assessment_post()
        verifiers = response.json["assessment"]["assignees"]["Verifier"]
        verifiers = set([v.get("email") for v in verifiers])
        self.assertEqual(verifiers, set(users))

        assessors = response.json["assessment"]["assignees"]["Assessor"]
        assessor = assessors[0].get("email")
        db.session.add(self.audit)
        self.assertEqual(assessor, self.audit.contact.email)

        creators = response.json["assessment"]["assignees"]["Creator"]
        creators = set([c.get("email") for c in creators])
        self.assertEqual(set(creators), {"*****@*****.**"})

    def test_template_test_plan(self):
        """Test if generating assessments from template sets default test plan"""
        template = factories.AssessmentTemplateFactory(
            test_plan_procedure=False,
            procedure_description="Assessment Template Test Plan")
        response = self.assessment_post(template)
        self.assertEqual(response.json["assessment"]["test_plan"],
                         template.procedure_description)

    def test_control_test_plan(self):
        """Test test_plan from control"""
        test_plan = self.control.test_plan
        template = factories.AssessmentTemplateFactory(
            test_plan_procedure=True)
        response = self.assessment_post(template)
        self.assertEqual(response.json["assessment"]["test_plan"], test_plan)
コード例 #43
0
 def setUp(self):
     super(TestPermissions, self).setUp()
     self.api = Api()
     roles = {r.name: r for r in all_models.Role.query.all()}
     with factories.single_commit():
         self.control = factories.ControlFactory()
         acrs = {
             "ACL_Reader":
             factories.AccessControlRoleFactory(name="ACL_Reader",
                                                object_type="Control",
                                                update=0),
             "ACL_Editor":
             factories.AccessControlRoleFactory(name="ACL_Editor",
                                                object_type="Control"),
         }
         self.program = factories.ProgramFactory()
         self.program.context.related_object = self.program
         self.relationship = factories.RelationshipFactory(
             source=self.program,
             destination=self.control,
             context=self.program.context,
         )
         self.people = {
             "Creator": factories.PersonFactory(),
             "Reader": factories.PersonFactory(),
             "Editor": factories.PersonFactory(),
             "Administrator": factories.PersonFactory(),
             "ACL_Reader": factories.PersonFactory(),
             "ACL_Editor": factories.PersonFactory(),
             "ProgramEditor": factories.PersonFactory(),
             "ProgramOwner": factories.PersonFactory(),
             "ProgramReader": factories.PersonFactory(),
         }
         for role_name in ["Creator", "Reader", "Editor", "Administrator"]:
             rbac_factories.UserRoleFactory(role=roles[role_name],
                                            person=self.people[role_name])
         for role_name in [
                 "ProgramEditor", "ProgramOwner", "ProgramReader"
         ]:
             person = self.people[role_name]
             rbac_factories.UserRoleFactory(role=roles["Creator"],
                                            person=person)
             rbac_factories.UserRoleFactory(role=roles[role_name],
                                            person=person,
                                            context=self.program.context)
         self.proposal = factories.ProposalFactory(
             instance=self.control,
             content={
                 "access_control_list": {},
                 "custom_attribute_values": {},
                 "fields": {},
                 "mapping_fields": {},
                 "mapping_list_fields": {},
             })
         for role_name in ["ACL_Reader", "ACL_Editor"]:
             rbac_factories.UserRoleFactory(role=roles["Creator"],
                                            person=self.people[role_name])
             factories.AccessControlListFactory(
                 ac_role=acrs[role_name],
                 object=self.control,
                 person=self.people[role_name])
         proposal_model.set_acl_to_all_proposals_for(self.control)
コード例 #44
0
ファイル: test_person.py プロジェクト: zdqf/ggrc-core
class TestPersonResource(TestCase, WithQueryApi):
  """Tests for special people api endpoints."""

  def setUp(self):
    super(TestPersonResource, self).setUp()
    self.client.get("/login")
    self.api = Api()
    self.generator = WorkflowsGenerator()

  @staticmethod
  def _create_users_names_rbac(users):
    """Create name and Creator role for users, created vid PersonFactory"""
    if not users:
      return
    roles = {r.name: r for r in all_models.Role.query.all()}
    for user in users:
      user.name = user.email.split("@")[0]
      rbac_factories.UserRoleFactory(role=roles["Creator"], person=user)

  def assert_profile_get_successful(self, response, expected_datetime):
    """Verify assertions for successful GET profile method"""
    self.assert200(response)
    response_datetime = date_parser.parse(response.json["last_seen_whats_new"])
    self.assertEqual(expected_datetime, response_datetime)

  @freeze_time("2018-05-20 12:23:17")
  def test_profile_get_successful(self):
    """Test person_profile GET method successfully achieves correct data"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    response = self.api.client.get("/api/people/{}/profile".format(user.id))
    self.assert_profile_get_successful(response, default_date())

  def test_profile_get_no_profile(self):
    """Test person_profile GET method achieves data with missing profile"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    profiles_table = PersonProfile.__table__
    db_request = profiles_table.delete().where(
        profiles_table.c.person_id == user.id)
    db.engine.execute(db_request)
    with freeze_time("2018-05-28 23:30:10"):
      response = self.api.client.get("/api/people/{}/profile".format(user.id))
      self.assert_profile_get_successful(response, default_date())

  def test_profile_get_failed(self):
    """Test person_profiles GET method fails

    Now only logged user can request his profile
    """
    with factories.single_commit():
      valid_user = factories.PersonFactory()
      self._create_users_names_rbac([valid_user])

    response = self.client.get(
        "/api/people/{}/profile".format(valid_user.id))
    # logged with default user during setUp
    self.assert403(response)
    response = self.api.client.get(
        "/api/people/{}/profile".format(valid_user.id))
    # not authorized user
    self.assert403(response)

  @ddt.data("Creator", "Reader", "Editor", "Administrator")
  def test_profile_post_empty_body(self, role_name):
    """Test person_profile POST method with empty body - {}."""
    role = all_models.Role.query.filter(
        all_models.Role.name == role_name
    ).one()
    with factories.single_commit():
      user = factories.PersonFactory()
      rbac_factories.UserRoleFactory(role=role, person=user)
    self.api.set_user(person=user)

    response = self.api.send_request(
        self.api.client.post,
        data={},
        api_link="/api/people/{}/profile".format(user.id))

    self.assert405(response)

  def test_profile_post_unauthorized(self):
    """Test person_profile POST method with empty body - No Access."""
    with factories.single_commit():
      user = factories.PersonFactory()

    response = self.api.send_request(
        self.api.client.post,
        data={},
        api_link="/api/people/{}/profile".format(user.id))
    # not authorized user
    self.assert405(response)

  def assert_profile_put_successful(self,
                                    response,
                                    correct_response,
                                    user,
                                    expected):
    """Verify assertions for successful PUT profile method"""
    self.assert200(response)
    self.assertEqual(response.json, correct_response)
    profile = PersonProfile.query.filter_by(person_id=user.id).first()
    self.assertEqual(profile.last_seen_whats_new, date_parser.parse(expected))

  @ddt.data(
      ["2018-05-20 16:38:17", "2018-05-20 16:38:17"],
      ["2018-07-05T14:11:31Z", "2018-07-05T14:11:31"])
  @ddt.unpack
  def test_profile_put_successful(self, new_date, expected_date):
    """Test person_profile PUT method for setting data and correct response"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    data = {"last_seen_whats_new": new_date}
    correct_response = {"Person": {"id": user.id, "profile": data}}
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    self.assert_profile_put_successful(response,
                                       correct_response,
                                       user,
                                       expected_date)

  def test_profile_put_no_profile(self):
    """Test person_profile PUT method for setting data for missing profile"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    new_date = "2018-05-20 22:05:17"
    data = {"last_seen_whats_new": new_date}
    correct_response = {"Person": {"id": user.id, "profile": data}}
    profiles_table = PersonProfile.__table__
    db_request = profiles_table.delete().where(
        profiles_table.c.person_id == user.id)
    db.engine.execute(db_request)
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    self.assert_profile_put_successful(response,
                                       correct_response,
                                       user,
                                       new_date)

  def test_profile_put_unauthorized(self):
    """Test person_profiles PUT method fails for unauthorized user"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])

    new_date = "2018-05-20 22:05:17"
    data = {"last_seen_whats_new": new_date}
    response = self.client.put("/api/people/{}/profile".format(user.id),
                               content_type='application/json',
                               data=json.dumps(data),
                               headers=[('X-Requested-By', 'Tests')])
    # logged with default user during setUp
    self.assert403(response)
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    # not authorized user
    self.assert403(response)

  @ddt.data({"last_seen_whats_new": "NOT A 123 DAT456A"},
            {"other_key": "2018-05-20 22:05:17", "one_more_key": 42})
  def test_profile_put_corrupted_data(self, data):
    """Test person_profiles PUT method fails via incorrect request data

    If request doesn't have "last_seen_whats_new" key or date is incorrect,
      response is code 400 "Bad Request"
    """
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    # missed key in request
    self.assert400(response)

  def test_task_count_empty(self):
    """Test query count without any workflows and tasks."""
    user = all_models.Person.query.first()
    response = self.client.get("/api/people/{}/task_count".format(user.id))
    self.assertEqual(
        response.json,
        {"open_task_count": 0, "has_overdue": False}
    )

  @ddt.data(
      (True, [
          ("task 1", "Finished", 3, True, 3),
          ("task 1", "Verified", 2, True, 3),
          ("task 2", "Declined", 2, True, 3),
          ("task 2", "Verified", 1, False, 3),
          ("task 2", "Finished", 2, True, 3),
          ("task 3", "Verified", 1, True, 3),
          ("task 2", "Verified", 0, False, 3),
      ]),
      (False, [
          ("task 1", "Finished", 2, True, 3),
          ("task 2", "In Progress", 2, True, 3),
          ("task 2", "Finished", 1, False, 3),
          ("task 3", "Finished", 0, False, 3),
      ]),
  )
  @ddt.unpack
  def test_task_count(self, is_verification_needed, transitions):
    """Test person task counts.

    This tests checks for correct task counts
     - with inactive workflows and
     - with overdue tasks
     - without overdue tasks
     - with finished overdue tasks

    The four checks are done in a single test due to complex differences
    between tests that make ddt cumbersome and the single test also improves
    integration test performance due to slow workflow setup stage.
    """
    # pylint: disable=too-many-locals

    user = all_models.Person.query.first()
    dummy_user = factories.PersonFactory()
    user_id = user.id
    role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    secondary_role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Secondary Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id

    one_time_workflow = {
        "title": "Person resource test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [create_stub(user)],
        "is_verification_needed": is_verification_needed,
        "task_groups": [{
            "title": "one time task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, user.id)
                ],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }, {
                "title": "task 2",
                "description": "some task 3",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, dummy_user.id)
                ],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 9, 16),
            }, {
                "title": "task 3",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(role_id, dummy_user.id)
                ],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 10, 16),
            }, {
                "title": "dummy task 4",  # task should not counted
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, dummy_user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 17),
            }, {
                "title": "dummy task 5",  # task should not counted
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, dummy_user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 18),
            }],
            "task_group_objects": []
        }]
    }

    inactive_workflow = {
        "title": "Activated workflow with archived cycles",
        "notify_on_change": True,
        "description": "Extra test workflow",
        "owners": [create_stub(user)],
        "task_groups": [{
            "title": "Extra task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "not counted existing task",
                "description": "",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }],
            "task_group_objects": []
        }]
    }

    with freeze_time("2017-10-16 05:09:10"):
      self.client.get("/login")
      # Activate normal one time workflow
      _, workflow = self.generator.generate_workflow(one_time_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      tasks = {t.title: t for t in cycle.cycle_task_group_object_tasks}
      _, workflow = self.generator.activate_workflow(workflow)

      # Activate and close the inactive workflow
      _, workflow = self.generator.generate_workflow(inactive_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      _, workflow = self.generator.activate_workflow(workflow)
      self.generator.modify_object(cycle, data={"is_current": False})

    with freeze_time("2017-7-16 07:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": False}
      )

    with freeze_time("2017-10-16 08:09:10"):  # same day as task 3 end date
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": True}
      )

      for task, status, count, overdue, my_work_count in transitions:
        self.generator.modify_object(tasks[task], data={"status": status})
        task_count_response = \
            self.client.get("/api/people/{}/task_count".format(user_id))
        my_work_count_response = \
            self.client.get("/api/people/{}/my_work_count".format(user_id))

        self.assertEqual(
            task_count_response.json,
            {"open_task_count": count, "has_overdue": overdue}
        )

        self.assertEqual(
            my_work_count_response.json["CycleTaskGroupObjectTask"],
            my_work_count
        )

  def test_task_count_multiple_wfs(self):
    """Test task count with both verified and non verified workflows.

    This checks task counts with 4 tasks
        2017, 8, 15  - verification needed
        2017, 11, 18  - verification needed
        2017, 8, 15  - No verification needed
        2017, 11, 18  - No verification needed
    """

    user = all_models.Person.query.first()
    user_id = user.id
    role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    workflow_template = {
        "title": "verified workflow",
        "owners": [create_stub(user)],
        "is_verification_needed": True,
        "task_groups": [{
            "title": "one time task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }, {
                "title": "dummy task 5",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 18),
            }],
            "task_group_objects": []
        }]
    }

    with freeze_time("2017-10-16 05:09:10"):
      self.client.get("/login")
      verified_workflow = workflow_template.copy()
      verified_workflow["is_verification_needed"] = True
      _, workflow = self.generator.generate_workflow(verified_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      verified_tasks = {
          task.title: task
          for task in cycle.cycle_task_group_object_tasks
      }
      _, workflow = self.generator.activate_workflow(workflow)

      non_verified_workflow = workflow_template.copy()
      non_verified_workflow["is_verification_needed"] = False
      _, workflow = self.generator.generate_workflow(non_verified_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      non_verified_tasks = {
          task.title: task
          for task in cycle.cycle_task_group_object_tasks
      }
      _, workflow = self.generator.activate_workflow(workflow)

    with freeze_time("2017-7-16 07:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": False}
      )

    with freeze_time("2017-10-16 08:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": True}
      )

      # transition 1, task that needs verification goes to finished state. This
      # transition should not change anything
      self.generator.modify_object(
          verified_tasks["task 1"],
          data={"status": "Finished"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": True}
      )

      # transition 2, task that needs verification goes to verified state. This
      # transition should reduce task count.
      self.generator.modify_object(
          verified_tasks["task 1"],
          data={"status": "Verified"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": True}
      )

      # transition 3, task that does not need verification goes into Finished
      # state. This transition should reduce task count and remove all overdue
      # tasks
      self.generator.modify_object(
          non_verified_tasks["task 1"],
          data={"status": "Finished"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 2, "has_overdue": False}
      )

  @ddt.data(("Creator", 403),
            ("Reader", 403),
            ("Editor", 200),
            ("Administrator", 200))
  @ddt.unpack
  def test_person_editing(self, role_name, status):
    """{0} should receive {1} status code on edit Person."""
    role = all_models.Role.query.filter(
        all_models.Role.name == role_name
    ).one()
    with factories.single_commit():
      client_user = factories.PersonFactory()
      rbac_factories.UserRoleFactory(role=role, person=client_user)
    self.api.set_user(client_user)
    self.client.get("/login")
    base_email = "*****@*****.**"
    person = factories.PersonFactory(email=base_email)
    person_id = person.id
    new_email = "new_{}".format(base_email)
    resp = self.api.put(person, {"email": new_email})
    self.assertEqual(status, resp.status_code)
    person = all_models.Person.query.get(person_id)
    if status == 200:
      self.assertEqual(new_email, person.email)
    else:
      self.assertEqual(base_email, person.email)
コード例 #45
0
ファイル: test_summary.py プロジェクト: zdqf/ggrc-core
 def setUp(self):
   """Set up for test methods."""
   super(TestAuditSummary, self).setUp()
   self.api = Api()
コード例 #46
0
class TestReviewStatusUpdate(TestCase):
  """Base TestCase class automatic review status update."""

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

  @ddt.data(
      ("title", "new title"),
      ("description", "new description"),
      ("test_plan", "new test_plan"),
      ("notes", "new notes"),
      ("fraud_related", 1),
      ("key_control", 1),
      ("start_date", "2020-01-01"),
      ("status", "Active"),
      ("kind", get_kind_data),
      ("means", get_mean_data),
      ("verify_frequency", get_verify_frequency_data),
      ("assertions", get_assertions_data),
      ("categories", get_categories_data),
  )
  @ddt.unpack
  def test_reviewable_attributes(self, attr_to_modify, new_value):
    """If attribute '{0}' modified move review to Unreviewed state"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
    review_id = review.id
    reviewable = review.reviewable

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

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

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

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

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

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

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

  def test_update_gca(self):
    """if existing GCA value changed review -> unreviewed"""
    with factories.single_commit():
      ca_factory = factories.CustomAttributeDefinitionFactory
      gca = ca_factory(
          definition_type="control",
          title="rich_test_gca",
          attribute_type="Rich Text"
      )
      control = factories.ControlFactory()

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

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

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

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

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

  @ddt.data("custom attr", "slug", "self")
  def test_gca_with_varying_titles(self, title):
    """if GCA with any title is changed review -> unreviewed"""
    with factories.single_commit():
      ca_factory = factories.CustomAttributeDefinitionFactory
      gca = ca_factory(
          definition_type="control",
          title=title,
          attribute_type="Rich Text"
      )
      control = factories.ControlFactory()

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

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

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

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

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

  def test_map_person_gca(self):
    """if Map:Person GCA value added review -> unreviewed"""
    with factories.single_commit():
      ca_factory = factories.CustomAttributeDefinitionFactory
      gca = ca_factory(
          definition_type="control",
          title="map_test_gca",
          attribute_type="Map:Person"
      )

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

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

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

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

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

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

  def test_update_map_person_gca(self):
    """if existing Map:Person GCA value changed review -> unreviewed"""
    with factories.single_commit():
      ca_factory = factories.CustomAttributeDefinitionFactory
      gca = ca_factory(
          definition_type="control",
          title="map_test_gca",
          attribute_type="Map:Person"
      )

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

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

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

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

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

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

  def test_delete_map_person_gca(self):
    """if existing Map:Person GCA value deleted review -> unreviewed"""
    with factories.single_commit():
      ca_factory = factories.CustomAttributeDefinitionFactory
      gca = ca_factory(
          definition_type="control",
          title="map_test_gca",
          attribute_type="Map:Person"
      )

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

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

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

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

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

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

  def test_reference_url(self):
    """If reference url is updated state should not updated"""
    with factories.single_commit():
      control = factories.ControlFactory()
      doc = factories.DocumentReferenceUrlFactory(
          title="Simple title",
          link="some_url.com",
          description="mega description",
          parent_obj={
              "id": control.id,
              "type": "Control"
          }
      )
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
    review_id = review.id

    self.api.modify_object(doc, {"link": "new_link.com"})
    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  def test_acl_roles(self):
    """Update of reviewable ACL shouldn't change review status"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
    review_id = review.id

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

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

    self.api.modify_object(
        control, {
            "access_control_list":
            [{
                "ac_role_id": ac_role_id,
                "person": {
                    "id": user_id
                },
            }],
        }
    )
    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  def test_comments(self):
    """Add comment to reviewable shouldn't update review state"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
    review_id = review.id

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

    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  def test_mapping_non_snapshotable(self):
    """Map non-snapshotable shouldn't change review status"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
      review_id = review.id

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

    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  @ddt.data(
      "Standard",
      "Regulation",
      "Requirement",
      "Objective",
      "Control",
      "Product",
      "System",
      "Process",
      "AccessGroup",
      "Contract",
      "DataAsset",
      "Facility",
      "Market",
      "OrgGroup",
      "Policy",
      "Risk",
      "Threat",
      "Vendor"
  )
  def test_map_snapshotable(self, snapshotable):
    """Map '{}' should change review status"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED, reviewable=control
      )
      review_id = review.id

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

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

  def test_unmap_snapshotable(self):
    """Unmap snapshotable should change review status"""
    control = factories.ControlFactory()
    resp, review = generate_review_object(control)
    review_id = review.id

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

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

    resp = self.api.delete(rel)
    self.assert200(resp)
    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)

  @ddt.data(
      "Assessment",
      "Issue",
      "Program",
      "Project",
      "Audit",
      "RiskAssessment",
      "AssessmentTemplate",
      "Person",
  )
  def test_map_nonsnapshotable(self, nonsnapshotable):
    """Map '{}' shouldn't change review status"""
    control = factories.ControlFactory()
    _, review = generate_review_object(
        control, state=all_models.Review.STATES.REVIEWED)
    review_id = review.id

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

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

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

    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  def test_unmap_nonsnapshotable(self):
    """Unmap nonsnapshotable shouldn't change review status"""
    control = factories.ControlFactory()
    resp, review = generate_review_object(
        control, state=all_models.Review.STATES.REVIEWED)
    review_id = review.id
    _, rel = self.generator.generate_relationship(
        source=control,
        destination=factories.ProgramFactory(),
        context=None,
    )

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

    resp = self.api.delete(rel)
    self.assert200(resp)
    review = all_models.Review.query.get(review_id)
    self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

  def test_proposal_apply(self):
    """Reviewable object changed via proposal -> review.state-> UNREVIEWED"""
    control = factories.ControlFactory()
    _, review = generate_review_object(control)

    review_id = review.id

    proposal_content = {
        "fields": {
            "title": "new title"
        },
    }
    proposal = factories.ProposalFactory(
        instance=control, content=proposal_content, agenda="agenda content"
    )
    self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED})

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

  def test_review_status_update(self):
    """Test updating folder preserves review status"""
    control = factories.ControlFactory()
    factories.ReviewFactory(
        reviewable=control,
        status=all_models.Review.STATES.REVIEWED,
    )
    self.api.put(control, {"folder": factories.random_str()})
    control = all_models.Control.query.get(control.id)
    self.assertEqual(control.review.status, all_models.Review.STATES.REVIEWED)
コード例 #47
0
ファイル: test_creator.py プロジェクト: k-alexey/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):
        """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")
コード例 #48
0
 def setUp(self):
   super(TestReviewStatusUpdate, self).setUp()
   self.api = Api()
   self.api.client.get("/login")
   self.generator = generator.ObjectGenerator()
コード例 #49
0
 def setUp(self):
   # pylint: disable=super-on-old-class
   super(TestIssueTrackedImport, self).setUp()
   self.api = Api()
   self.client.get("/login")
コード例 #50
0
ファイル: test_evidence.py プロジェクト: weizai118/ggrc-core
 def setUp(self):
   super(TestEvidence, self).setUp()
   self.api = Api()
   self.gen = generator.ObjectGenerator()
コード例 #51
0
class TestReviewStatusUpdate(TestCase):
    """Base TestCase class automatic review status update."""
    def setUp(self):
        super(TestReviewStatusUpdate, self).setUp()
        self.api = Api()

        self.generator = generator.ObjectGenerator()

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

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

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

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

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

    def test_update_gca(self):
        """if existing GCA value changed review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="program",
                             title="rich_test_gca",
                             attribute_type="Rich Text")
            program = factories.ProgramFactory()

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

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

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

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

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

    @ddt.data("custom attr", "slug", "self")
    def test_gca_with_varying_titles(self, title):
        """if GCA with any title is changed review -> unreviewed"""
        with factories.single_commit():
            ca_factory = factories.CustomAttributeDefinitionFactory
            gca = ca_factory(definition_type="program",
                             title=title,
                             attribute_type="Rich Text")
            program = factories.ProgramFactory()

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

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

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

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

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

    def test_reference_url(self):
        """If reference url is updated state should not updated"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            doc = factories.DocumentReferenceUrlFactory(
                title="Simple title",
                link="some_url.com",
                description="mega description",
                parent_obj={
                    "id": program.id,
                    "type": "Program"
                })
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)
        review_id = review.id

        self.api.modify_object(doc, {"link": "new_link.com"})
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    def test_acl_roles(self):
        """Update of reviewable ACL shouldn't change review status"""
        with factories.single_commit():
            threat = factories.ThreatFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=threat)
        review_id = review.id

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

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

        self.api.modify_object(
            threat, {
                "access_control_list": [{
                    "ac_role_id": ac_role_id,
                    "person": {
                        "id": user_id
                    },
                }],
            })
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    def test_comments(self):
        """Add comment to reviewable shouldn't update review state"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)
        review_id = review.id

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

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    def test_mapping_non_snapshotable(self):
        """Map non-snapshotable shouldn't change review status"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)
            review_id = review.id

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

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    @ddt.data("Standard", "Regulation", "Requirement", "Objective", "Control",
              "Product", "System", "Process", "AccessGroup", "Contract",
              "DataAsset", "Facility", "Market", "OrgGroup", "Policy", "Risk",
              "Threat", "Vendor")
    def test_map_snapshotable(self, snapshotable):
        """Map '{}' should change review status"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            review = factories.ReviewFactory(
                status=all_models.Review.STATES.REVIEWED, reviewable=program)
            review_id = review.id

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

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

    def test_unmap_snapshotable(self):
        """Unmap snapshotable should change review status"""
        program = factories.ProgramFactory()
        resp, review = generate_review_object(program)
        review_id = review.id

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

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

        resp = self.api.delete(rel)
        self.assert200(resp)
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)

    @ddt.data(
        "Assessment",
        "Issue",
        "Program",
        "Project",
        "Audit",
        "RiskAssessment",
        "AssessmentTemplate",
        "Person",
    )
    def test_map_nonsnapshotable(self, nonsnapshotable):
        """Map '{}' shouldn't change review status"""
        program = factories.ProgramFactory()
        _, review = generate_review_object(
            program, state=all_models.Review.STATES.REVIEWED)
        review_id = review.id

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

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

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

        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    def test_unmap_nonsnapshotable(self):
        """Unmap nonsnapshotable shouldn't change review status"""
        program = factories.ProgramFactory()
        resp, review = generate_review_object(
            program, state=all_models.Review.STATES.REVIEWED)
        review_id = review.id
        _, rel = self.generator.generate_relationship(
            source=program,
            destination=factories.ProgramFactory(),
            context=None,
        )

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

        resp = self.api.delete(rel)
        self.assert200(resp)
        review = all_models.Review.query.get(review_id)
        self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)

    def test_proposal_apply(self):
        """Reviewable object changed via proposal -> review.state-> UNREVIEWED"""
        program = factories.ProgramFactory()
        _, review = generate_review_object(program)

        review_id = review.id

        proposal_content = {
            "fields": {
                "title": "new title"
            },
        }
        proposal = factories.ProposalFactory(instance=program,
                                             content=proposal_content,
                                             agenda="agenda content")
        self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED})

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

    def test_review_status_update(self):
        """Test updating folder preserves review status"""
        threat = factories.ThreatFactory()
        factories.ReviewFactory(
            reviewable=threat,
            status=all_models.Review.STATES.REVIEWED,
        )
        self.api.put(threat, {"folder": factories.random_str()})
        program = all_models.Threat.query.get(threat.id)
        self.assertEqual(program.review.status,
                         all_models.Review.STATES.REVIEWED)
コード例 #52
0
class TestProposalEmail(TestCase):
  """Test case about email sending and email presenting for proposals."""

  def setUp(self):
    super(TestProposalEmail, self).setUp()
    self.api = Api()
    self.client.get("/login")

  @ddt.data(True, False)
  def test_email_presentation(self, is_admin):
    """Test presentation of proposal digest email if is_admin is {0}."""
    person = factories.PersonFactory()
    self.api.set_user(person=person)
    with mock.patch("ggrc.rbac.permissions.is_admin", return_value=is_admin):
      resp = self.client.get("/_notifications/show_fast_digest")
    if is_admin:
      self.assert200(resp)
    else:
      self.assert403(resp)

  def test_email_sending(self):
    """Test sending emails about proposals."""
    role_1 = factories.AccessControlRoleFactory(object_type="Risk",
                                                notify_about_proposal=True)
    role_2 = factories.AccessControlRoleFactory(object_type="Risk",
                                                notify_about_proposal=True)
    role_3 = factories.AccessControlRoleFactory(object_type="Risk",
                                                notify_about_proposal=False)
    with factories.single_commit():
      risk = factories.RiskFactory()
      person_1 = factories.PersonFactory()  # has 1 role
      person_2 = factories.PersonFactory()  # has no roles
      person_3 = factories.PersonFactory()  # has 2 roles
      factories.PersonFactory()  # not related to risk at all
      factories.AccessControlPersonFactory(
          ac_list=risk.acr_acl_map[role_1],
          person=person_1
      )
      factories.AccessControlPersonFactory(
          ac_list=risk.acr_acl_map[role_1],
          person=person_3
      )
      factories.AccessControlPersonFactory(
          ac_list=risk.acr_acl_map[role_2],
          person=person_3
      )
      factories.AccessControlPersonFactory(
          ac_list=risk.acr_acl_map[role_3],
          person=person_2
      )
      proposal_1 = factories.ProposalFactory(
          instance=risk,
          content={
              "fields": {"title": "a"},
              "access_control_list": {},
              "custom_attribute_values": {},
              "mapping_fields": {},
              "mapping_list_fields": {},
          },
          agenda="agenda 1")
      proposal_2 = factories.ProposalFactory(
          instance=risk,
          content={
              "fields": {"title": "b"},
              "access_control_list": {},
              "custom_attribute_values": {},
              "mapping_fields": {},
              "mapping_list_fields": {},
          },
          agenda="agenda 2")
    self.assertIsNone(proposal_1.proposed_notified_datetime)
    self.assertIsNone(proposal_2.proposed_notified_datetime)
    with mock.patch("google.appengine.api.mail.send_mail") as mailer_mock:
      with mock.patch.object(fast_digest.DIGEST_TMPL,
                             "render") as bodybuilder_mock:
        fast_digest.send_notification()
    self.assertIsNotNone(proposal_1.proposed_notified_datetime)
    self.assertIsNotNone(proposal_2.proposed_notified_datetime)
    self.assertEqual(2, len(bodybuilder_mock.call_args_list))
    self.assertEqual(2, len(mailer_mock.call_args_list))
    # email to each required person
    self.assertListEqual(
        sorted([person_1.email, person_3.email]),
        sorted([a[1]["to"] for a in mailer_mock.call_args_list]))
    # no matter how many roles each proposal should be otified
    # only once for that person
    self.assertListEqual(
        [2] * 2,
        [len(a[1]["proposals"]) for a in bodybuilder_mock.call_args_list])
コード例 #53
0
class TestResource(TestCase):
  """
  Test /search REST API
  """

  def setUp(self):
    super(TestResource, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.create_objects()

  def create_objects(self):
    """Create objects to be searched.

    Creates five controls and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
    self.objects = [
        self.object_generator.generate_object(Control)[1].id
        for _ in xrange(5)
    ]
    self.objects = Control.eager_query().filter(
        Control.id.in_(self.objects)
    ).all()
    for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
      self.object_generator.generate_relationship(
          self.objects[src], self.objects[dst]
      )

  def search(self, *args, **kwargs):
    res, _ = self.api.search(*args, **kwargs)
    return res.json["results"]["entries"]

  def test_search_all(self):
    """Test search for all objects of a type."""
    res, _ = self.api.search("Control")
    self.assertEqual(len(res.json["results"]["entries"]), 5)

  def test_search_query(self):
    """Test search with query by title."""
    entries = self.search("Control", query=self.objects[0].title)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[0].id})

  def test_search_relevant(self):
    """Test search with 'relevant to' single object."""
    relevant_objects = "Control:{}".format(self.objects[0].id)
    entries = self.search("Control", relevant_objects=relevant_objects)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[i].id for i in [1, 2]})

  def test_search_relevant_multi(self):
    """Test search with 'relevant to' multiple objects."""
    ids = ",".join("Control:{}".format(self.objects[i].id) for i in (0, 3))
    entries = self.search("Control", relevant_objects=ids)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[2].id})

  def test_search_fail_with_terms_none(self):
    """Test search to fail with BadRequest (400 Error) when terms are None."""
    query = '/search?types={}&counts_only={}'.format("Control", False)
    response = self.api.client.get(query)
    self.assert400(response)
    self.assertEqual(response.json['message'], 'Query parameter "q" '
                     'specifying search terms must be provided.')
コード例 #54
0
class TestWorkflowsApiPost(TestCase):
    """Test class for ggrc workflow api post action."""
    def setUp(self):
        super(TestWorkflowsApiPost, self).setUp()
        self.api = Api()
        self.generator = wf_generator.WorkflowsGenerator()
        self.wf_admin_id = all_models.Person.query.first().id
        with factories.single_commit():
            self.people_ids = [factories.PersonFactory().id for _ in xrange(6)]

    def tearDown(self):
        pass

    def _delete_and_check_related_acl(self, related_model, exp_acl_count,
                                      is_deleted):
        """Delete related model and check remaining ACL count.

    Args:
        related_model: related model class
        exp_acl_count: expected related ACL count after delete operation
        is_deleted: is related object already deleted
    """
        if is_deleted:
            related_count = related_model.query.count()
            self.assertEqual(related_count, 0)
        else:
            related = related_model.query.one()
            response = self.api.delete(related)
            self.assert200(response)

        related_acl_count = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.object_type ==
            related_model.__name__).count()
        self.assertEqual(related_acl_count, 0)

        bg_task_count = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.object_type ==
            "BackgroundTask").count()

        all_acl_count = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.object_type != 'PersonProfile').count(
            )
        self.assertEqual(all_acl_count - bg_task_count, exp_acl_count)

    def test_acl_on_object_deletion(self):
        """Test related ACL records removed on related object delete"""
        self._create_propagation_acl_test_data()
        acl_count = all_models.AccessControlList.query.count()
        self.assertNotEqual(acl_count, 0)

        admin = all_models.Person.query.get(1)
        self.api.set_user(admin)

        related_models = (
            (all_models.TaskGroup, 16, False),
            (all_models.TaskGroupTask, 16, True),
            (all_models.Cycle, 2, False),
            (all_models.CycleTaskGroup, 2, True),
            (all_models.CycleTaskGroupObjectTask, 2, True),
        )
        for related_model, acl_count, is_deleted in related_models:
            self._delete_and_check_related_acl(related_model, acl_count,
                                               is_deleted)

    def test_acl_on_workflow_delete(self):
        """Test related ACL records removed on Workflow delete"""
        self._create_propagation_acl_test_data()
        acl_count = all_models.AccessControlList.query.count()
        self.assertNotEqual(acl_count, 0)

        admin = all_models.Person.query.get(1)
        self.api.set_user(admin)
        workflow = all_models.Workflow.query.one()
        response = self.api.delete(workflow)
        self.assert200(response)

        acl_count = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.object_type != 'PersonProfile').count(
            )
        bg_acl_count = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.object_type ==
            "BackgroundTask").count()
        self.assertEqual(acl_count, bg_acl_count)

    def test_acl_for_new_related_object(self):
        """Test Workflow ACL propagation for new related objects."""
        data = self.get_workflow_dict()
        acl_map = {
            self.people_ids[0]: WF_ROLES['Admin'],
            self.people_ids[1]: WF_ROLES['Workflow Member'],
        }
        data["workflow"]["access_control_list"] = acl_helper.get_acl_list(
            acl_map)
        data["workflow"]["unit"] = "week"
        data["workflow"]["repeat_every"] = 1
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

        data = self.get_task_group_dict(response.json["workflow"])
        data["task_group"]["contact"]["id"] = self.people_ids[2]
        data["task_group"]["contact"]["href"] = "/api/people/{}".format(
            self.people_ids[2])
        response = self.api.post(all_models.TaskGroup, data)
        self.assertEqual(response.status_code, 201)

        task_group = all_models.TaskGroup.eager_query().one()
        data = self.get_task_dict(task_group)
        data["task_group_task"]["start_date"] = "2018-01-04"
        data["task_group_task"]["end_date"] = "2018-01-05"
        response = self.api.post(all_models.TaskGroupTask, data)
        self.assertEqual(response.status_code, 201)

        workflow = all_models.Workflow.query.one()
        with freezegun.freeze_time("2018-01-05"):  # Generate 1 cycle
            self.generator.activate_workflow(workflow)

        cycle_task = all_models.CycleTaskGroupObjectTask.query.one()
        with factories.single_commit():
            comment = factories.CommentFactory()
            factories.RelationshipFactory(source=comment,
                                          destination=cycle_task)

        self._check_propagated_acl(2, has_comment=True)

    @ddt.data('Admin', 'Workflow Member')
    def test_tg_assignee(self, role_name):
        """Test TaskGroup assignee already has {0} role."""
        data = self.get_workflow_dict()
        init_acl = {
            self.people_ids[0]: WF_ROLES['Admin'],
            self.people_ids[1]: WF_ROLES[role_name],
        }
        data['workflow']['access_control_list'] = acl_helper.get_acl_list(
            init_acl)
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

        data = self.get_task_group_dict(response.json["workflow"])
        data["task_group"]["contact"]["id"] = self.people_ids[1]
        data["task_group"]["contact"]["href"] = "/api/people/{}".format(
            self.people_ids[1])
        response = self.api.post(all_models.TaskGroup, data)
        self.assertEqual(response.status_code, 201)

        workflow = all_models.Workflow.query.one()
        task_group = all_models.TaskGroup.query.one()

        ac_people = all_models.AccessControlPerson.query.filter(
            all_models.AccessControlPerson.person_id == task_group.contact_id,
        ).all()
        self.assertEqual(len(ac_people), 2)

        actual = {(acp.ac_list.object_type, acp.ac_list.object_id)
                  for acp in ac_people}
        self.assertIn((workflow.type, workflow.id), actual)
        self.assertNotIn((task_group.type, task_group.id), actual)

    def test_task_group_assignee_gets_workflow_member(self):  # noqa pylint: disable=invalid-name
        """Test TaskGroup assignee gets WorkflowMember role."""
        data = self.get_workflow_dict()
        init_acl = {
            self.people_ids[0]: WF_ROLES['Admin'],
            self.people_ids[1]: WF_ROLES['Workflow Member'],
        }
        data['workflow']['access_control_list'] = acl_helper.get_acl_list(
            init_acl)
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

        data = self.get_task_group_dict(response.json["workflow"])
        data["task_group"]["contact"]["id"] = self.people_ids[2]
        data["task_group"]["contact"]["href"] = "/api/people/{}".format(
            self.people_ids[2])
        response = self.api.post(all_models.TaskGroup, data)
        self.assertEqual(response.status_code, 201)

        workflow = all_models.Workflow.query.one()

        wf_members = [
            acp.person.id for acp in
            workflow.acr_name_acl_map["Workflow Member"].access_control_people
        ]
        self.assertIn(self.people_ids[2], wf_members)

    def _create_propagation_acl_test_data(self):  # noqa pylint: disable=invalid-name
        """Create objects for Workflow ACL propagation test."""
        with freezegun.freeze_time("2017-08-9"):
            with factories.single_commit():
                workflow = wf_factories.WorkflowFactory(
                    title='wf1',
                    unit=all_models.Workflow.WEEK_UNIT,
                    is_verification_needed=True,
                    repeat_every=1)
                wf_factories.TaskGroupTaskFactory(
                    title='tgt1',
                    task_group=wf_factories.TaskGroupFactory(
                        title='tg1',
                        context=factories.ContextFactory(),
                        workflow=workflow),
                    # One cycle should be created
                    start_date=datetime.date(2017, 8, 3),
                    end_date=datetime.date(2017, 8, 7))
            self.generator.activate_workflow(workflow)
            workflow = all_models.Workflow.query.one()
            acl_map = {
                self.people_ids[0]: WF_ROLES['Admin'],
                self.people_ids[1]: WF_ROLES['Workflow Member'],
                self.people_ids[2]: WF_ROLES['Workflow Member'],
            }
            put_params = {
                'access_control_list': acl_helper.get_acl_list(acl_map)
            }
            response = self.api.put(workflow, put_params)
            self.assert200(response)

    def _check_propagated_acl(self, roles_count, has_comment=False):
        """ Check Workflow propagated ACL records.

    Args:
        roles_count: roles' count created in test
        has_comment: indicator that related objects contain comments
    """
        related_objects = [
            (all_models.TaskGroup.query.one().id,
             all_models.TaskGroup.__name__),
            (all_models.TaskGroupTask.query.one().id,
             all_models.TaskGroupTask.__name__),
            (all_models.Cycle.query.one().id, all_models.Cycle.__name__),
            (all_models.CycleTaskGroup.query.one().id,
             all_models.CycleTaskGroup.__name__),
            (all_models.CycleTaskGroupObjectTask.query.one().id,
             all_models.CycleTaskGroupObjectTask.__name__),
        ]
        if has_comment:
            related_objects.append((all_models.Comment.query.one().id,
                                    all_models.Comment.__name__), )

        # *2 is for relationships
        related_count = roles_count * len(related_objects) * 2

        # additional acl count for Relationship and Comment propagation of
        # Task Assignees/Task Secondary Assignees access control roles
        if has_comment:
            related_count += roles_count * 2

        all_acls = all_models.AccessControlList.query.filter(
            all_models.AccessControlList.parent_id_nn != 0).count()
        self.assertEqual(all_acls, related_count)

    def test_assign_workflow_acl(self):
        """Test propagation Workflow ACL roles on Workflow's update ACL records."""
        self._create_propagation_acl_test_data()
        self._check_propagated_acl(2)

    def test_unassign_workflow_acl(self):
        """Test propagation Workflow ACL roles on person unassigned."""
        self._create_propagation_acl_test_data()
        with freezegun.freeze_time("2017-08-9"):
            workflow = all_models.Workflow.query.one()
            acl_map = {
                self.people_ids[0]: WF_ROLES['Admin'],
                self.people_ids[1]: WF_ROLES['Workflow Member'],
            }
            put_params = {
                'access_control_list': acl_helper.get_acl_list(acl_map)
            }
            response = self.api.put(workflow, put_params)
            self.assert200(response)

        self._check_propagated_acl(2)

    def test_post_workflow_with_acl(self):
        """Test PUT workflow with ACL."""
        data = self.get_workflow_dict()

        exp_res = {
            self.wf_admin_id: WF_ROLES['Admin'],
            self.people_ids[0]: WF_ROLES['Admin'],
            self.people_ids[1]: WF_ROLES['Workflow Member'],
            self.people_ids[2]: WF_ROLES['Workflow Member'],
            self.people_ids[3]: WF_ROLES['Workflow Member']
        }
        data['workflow']['access_control_list'] = acl_helper.get_acl_list(
            exp_res)
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)
        workflow = all_models.Workflow.eager_query().one()
        act_res = {
            person.id: acl.ac_role_id
            for person, acl in workflow.access_control_list
        }
        self.assertDictEqual(exp_res, act_res)

    def test_update_workflow_acl_people(self):
        """Test PUT workflow with updated ACL."""
        data = self.get_workflow_dict()
        init_map = {
            self.wf_admin_id: WF_ROLES['Admin'],
            self.people_ids[0]: WF_ROLES['Workflow Member'],
        }
        data['workflow']['access_control_list'] = acl_helper.get_acl_list(
            init_map)
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)
        exp_res = {
            self.people_ids[0]: WF_ROLES['Admin'],
            self.people_ids[1]: WF_ROLES['Admin'],
            self.people_ids[2]: WF_ROLES['Workflow Member'],
            self.people_ids[3]: WF_ROLES['Workflow Member'],
            self.people_ids[4]: WF_ROLES['Workflow Member']
        }
        workflow = all_models.Workflow.eager_query().one()
        put_params = {'access_control_list': acl_helper.get_acl_list(exp_res)}
        response = self.api.put(workflow, put_params)
        self.assert200(response)
        workflow = all_models.Workflow.eager_query().one()
        act_res = {
            person.id: acl.ac_role_id
            for person, acl in workflow.access_control_list
        }
        self.assertDictEqual(exp_res, act_res)

    def test_send_invalid_data(self):
        """Test send invalid data on Workflow post."""
        data = self.get_workflow_dict()
        del data["workflow"]["title"]
        response = self.api.post(all_models.Workflow, data)
        self.assert400(response)

    def test_create_one_time_workflows(self):
        """Test simple create one time Workflow over api."""
        data = self.get_workflow_dict()
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

    def test_create_weekly_workflow(self):
        """Test create valid weekly wf"""
        data = self.get_workflow_dict()
        data["workflow"]["repeat_every"] = 7
        data["workflow"]["unit"] = "day"
        data["workflow"]["title"] = "Weekly"
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

    def test_create_annually_workflow(self):
        """Test create valid annual wf"""
        data = self.get_workflow_dict()
        data["workflow"]["repeat_every"] = 12
        data["workflow"]["unit"] = "month"
        data["workflow"]["title"] = "Annually"
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 201)

    @ddt.data("wrong value", 0, -4)
    def test_create_wrong_repeat_every_workflow(self, value):  # noqa pylint: disable=invalid-name
        """Test case for invalid repeat_every value"""
        data = self.get_workflow_dict()
        data["workflow"]["repeat_every"] = value
        data["workflow"]["unit"] = "month"
        data["workflow"]["title"] = "Wrong wf"
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 400)

    def test_create_wrong_unit_workflow(self):
        """Test case for invalid unit value"""
        data = self.get_workflow_dict()
        data["workflow"]["repeat_every"] = 12
        data["workflow"]["unit"] = "wrong value"
        data["workflow"]["title"] = "Wrong wf"
        response = self.api.post(all_models.Workflow, data)
        self.assertEqual(response.status_code, 400)

    def test_create_task_group(self):
        """Test create task group over api."""
        wf_data = self.get_workflow_dict()
        wf_data["workflow"]["title"] = "Create_task_group"
        wf_response = self.api.post(all_models.Workflow, wf_data)

        data = self.get_task_group_dict(wf_response.json["workflow"])

        response = self.api.post(all_models.TaskGroup, data)
        self.assertEqual(response.status_code, 201)

    def test_incorrect_wf_id_on_tg_post(self):
        """Tests incorrect id in tg post payload.

    Tests that 400 is raised on tg post if id in
    payload has incorrect type."""
        wf_data = self.get_workflow_dict()
        wf_response = self.api.post(all_models.Workflow, wf_data)
        data = {
            "workflow": {
                "id": {
                    "id": wf_response.json["workflow"]["id"]
                },
                "type": "Workflow"
            }
        }
        tg_response = self.api.post(all_models.TaskGroup, data)
        self.assertEqual(tg_response.status_code, 400)
        self.assertEqual(tg_response.json["message"],
                         ("Either type or id are specified "
                          "incorrectly in the request payload."))

    @staticmethod
    def get_workflow_dict():
        return {
            "workflow": {
                "custom_attribute_definitions": [],
                "custom_attributes": {},
                "title": "One_time",
                "description": "",
                "unit": None,
                "repeat_every": None,
                "notify_on_change": False,
                "task_group_title": "Task Group 1",
                "notify_custom_message": "",
                "is_verification_needed": True,
                "context": None,
            }
        }

    def get_task_group_dict(self, workflow):
        return {
            "task_group": {
                "custom_attribute_definitions": [],
                "custom_attributes": {},
                "_transient": {},
                "contact": {
                    "id": self.wf_admin_id,
                    "href": "/api/people/{}".format(self.wf_admin_id),
                    "type": "Person"
                },
                "workflow": {
                    "id": workflow["id"],
                    "href": "/api/workflows/%d" % workflow["id"],
                    "type": "Workflow"
                },
                "context": {
                    "id": workflow["context"]["id"],
                    "href": "/api/contexts/%d" % workflow["context"]["id"],
                    "type": "Context"
                },
                "modal_title": "Create Task Group",
                "title": "Create_task_group",
                "description": "",
            }
        }

    def get_task_dict(self, task_group):
        return {
            "task_group_task": {
                "start_date": "2017-12-25",
                "end_date": "2017-12-31",
                "custom_attributes": {},
                "contact": {
                    "id": self.wf_admin_id,
                    "href": "/api/people/{}".format(self.wf_admin_id),
                    "type": "Person"
                },
                "task_group": {
                    "id": task_group.id,
                    "href": "/api/task_groups/{}".format(task_group.id),
                    "type": "TaskGroup"
                },
                "context": {
                    "id": task_group.context_id,
                    "href": "/api/contexts/{}".format(task_group.context_id),
                    "type": "Context"
                },
                "title": "Create_task",
                "task_type": "text",
                "description": ""
            }
        }

    @ddt.data({}, {"repeat_every": 5, "unit": "month"})
    def test_repeat_multiplier_field(self, data):
        """Check repeat_multiplier is set to 0 after wf creation."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(**data)
        workflow_id = workflow.id
        self.assertEqual(
            0,
            all_models.Workflow.query.get(workflow_id).repeat_multiplier)

    # TODO: Unskip in the patch 2
    @unittest.skip("Will be activated in patch 2")
    def test_change_to_one_time_wf(self):
        """Check repeat_every and unit can be set to Null only together."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(repeat_every=12,
                                                    unit="day")
        resp = self.api.put(workflow, {"repeat_every": None, "unit": None})
        self.assert200(resp)

    @ddt.data({"repeat_every": 5}, {"unit": "month"})
    def test_change_repeat_every(self, data):
        """Check repeat_every or unit can not be changed once set."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory()
        resp = self.api.put(workflow, data)
        self.assert400(resp)

    def test_not_change_to_one_time_wf(self):
        """Check repeat_every or unit can't be set to Null separately.
    This test will be useful in the 2nd patch, where we allow to change
    WF setup
    """
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(repeat_every=12,
                                                    unit="day")
        resp = self.api.put(workflow, {"repeat_every": None})
        self.assert400(resp)
        resp = self.api.put(workflow, {"unit": None})
        self.assert400(resp)

    @ddt.data(True, False)
    def test_autogen_verification_flag(self, flag):
        """Check is_verification_needed flag for activate WF action."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(
                is_verification_needed=flag)
            group = wf_factories.TaskGroupFactory(workflow=workflow)
            wf_factories.TaskGroupTaskFactory(task_group=group)
        data = [{
            "cycle": {
                "autogenerate": True,
                "isOverdue": False,
                "title": factories.random_str(prefix='cycle - '),
                "workflow": {
                    "id": workflow.id,
                    "type": "Workflow",
                },
                "context": {
                    "id": workflow.context_id,
                    "type": "Context",
                },
            }
        }]
        resp = self.api.send_request(self.api.client.post,
                                     api_link="/api/cycles",
                                     data=data)
        cycle_id = resp.json[0][1]["cycle"]["id"]
        self.assertEqual(
            flag,
            all_models.Cycle.query.get(cycle_id).is_verification_needed)

    @ddt.data(True, False)
    def test_verification_flag_positive(self, flag):  # noqa pylint: disable=invalid-name
        """is_verification_needed flag is changeable for DRAFT workflow."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(
                is_verification_needed=flag)
        self.assertEqual(workflow.status, all_models.Workflow.DRAFT)
        workflow_id = workflow.id
        resp = self.api.put(workflow, {"is_verification_needed": not flag})
        self.assert200(resp)
        self.assertEqual(
            all_models.Workflow.query.get(workflow_id).is_verification_needed,
            not flag)

    @ddt.data(True, False)
    def test_verification_flag_negative(self, flag):
        """Test immutable verification flag on active workflows."""
        with freezegun.freeze_time("2017-08-10"):
            with factories.single_commit():
                workflow = wf_factories.WorkflowFactory(
                    unit=all_models.Workflow.WEEK_UNIT,
                    is_verification_needed=flag,
                    repeat_every=1)
                wf_factories.TaskGroupTaskFactory(
                    task_group=wf_factories.TaskGroupFactory(
                        context=factories.ContextFactory(), workflow=workflow),
                    # Two cycles should be created
                    start_date=datetime.date(2017, 8, 3),
                    end_date=datetime.date(2017, 8, 7))
            workflow_id = workflow.id
            self.assertEqual(workflow.status, all_models.Workflow.DRAFT)
            self.generator.activate_workflow(workflow)
            workflow = all_models.Workflow.query.get(workflow_id)
            self.assertEqual(workflow.status, all_models.Workflow.ACTIVE)
            resp = self.api.put(workflow, {"is_verification_needed": not flag})
            self.assert400(resp)
            workflow = all_models.Workflow.query.get(workflow_id)
            self.assertEqual(workflow.is_verification_needed, flag)

            # End all current cycles
            for cycle in workflow.cycles:
                self.generator.modify_object(cycle, {'is_current': False})
            workflow = all_models.Workflow.query.filter(
                all_models.Workflow.id == workflow_id).first()
            self.assertEqual(workflow.status, all_models.Workflow.INACTIVE)
            resp = self.api.put(workflow, {"is_verification_needed": not flag})
            self.assert400(resp)
            workflow = all_models.Workflow.query.get(workflow_id)
            self.assertEqual(workflow.is_verification_needed, flag)

    @ddt.data(True, False)
    def test_not_change_vf_flag(self, flag):
        """Check is_verification_needed not change on update."""
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory(
                is_verification_needed=flag)
        workflow_id = workflow.id
        resp = self.api.put(workflow, {"is_verification_needed": flag})
        self.assert200(resp)
        self.assertEqual(
            flag,
            all_models.Workflow.query.get(workflow_id).is_verification_needed)

    @ddt.data(True, False, None)
    def test_create_vf_flag(self, flag):
        """Check is_verification_needed flag setup on create."""
        data = self.get_workflow_dict()
        if flag is None:
            data['workflow'].pop('is_verification_needed', None)
        else:
            data['workflow']['is_verification_needed'] = flag
        resp = self.api.post(all_models.Workflow, data)
        self.assertEqual(201, resp.status_code)
        workflow_id = resp.json['workflow']['id']
        self.assertEqual(
            flag if flag is not None else False,
            all_models.Workflow.query.get(workflow_id).is_verification_needed)

    @ddt.data(
        ('Editor', 201, 1),
        ('Creator', 403, 0),
        ('Reader', 403, 0),
        ('Administrator', 201, 1),
    )
    @ddt.unpack
    def test_create_ctg_wf_member(self, member_role, response_code, exp_count):
        """Check creation cycle task group by workflow member"""
        member = self.create_user_with_role(member_role)
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory()
            workflow.add_person_with_role_name(member, 'Workflow Member')
            task_group = wf_factories.TaskGroupFactory(
                title='TestTG',
                context=factories.ContextFactory(),
                workflow=workflow)
            wf_factories.TaskGroupTaskFactory(
                title='TestTGT',
                task_group=task_group,
                start_date=datetime.date(2017, 8, 3),
                end_date=datetime.date(2017, 8, 7))
            cycle = wf_factories.CycleFactory(workflow=workflow)
        self.generator.activate_workflow(workflow)
        self.api.set_user(member)

        response = self.api.post(
            all_models.CycleTaskGroup, {
                "cycle_task_group": {
                    "cycle": {
                        "id": cycle.id,
                    },
                    "contact": {
                        "id": member.id,
                    },
                    "title": 'title1',
                },
            })

        self.assertEquals(response.status_code, response_code)
        count = len(all_models.CycleTaskGroup.query.all())
        self.assertEquals(count, exp_count)

    @ddt.data(
        'Reader',
        'Editor',
        'Administrator',
        'Creator',
    )
    def test_create_ctg_wf_admin(self, admin_role):
        """Check creation cycle task group by workflow admin"""
        admin = self.create_user_with_role(admin_role)
        exp_count = 1
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory()
            workflow.add_person_with_role_name(admin, 'Admin')
            task_group = wf_factories.TaskGroupFactory(
                title='TestTG',
                context=factories.ContextFactory(),
                workflow=workflow)
            wf_factories.TaskGroupTaskFactory(
                title='TestTGT',
                task_group=task_group,
                start_date=datetime.date(2017, 8, 3),
                end_date=datetime.date(2017, 8, 7))
            cycle = wf_factories.CycleFactory(workflow=workflow)
        self.generator.activate_workflow(workflow)
        self.api.set_user(admin)

        response = self.api.post(
            all_models.CycleTaskGroup, {
                "cycle_task_group": {
                    "cycle": {
                        "id": cycle.id,
                    },
                    "contact": {
                        "id": admin.id,
                    },
                    "title": 'title1',
                },
            })

        self.assert201(response)
        count = len(all_models.CycleTaskGroup.query.all())
        self.assertEquals(count, exp_count)

    @ddt.data(
        ('Editor', 200, 0),
        ('Creator', 403, 1),
        ('Reader', 403, 1),
        ('Administrator', 200, 0),
    )
    @ddt.unpack
    def test_delete_ctg_wf_member(self, member_role, response_code, exp_count):
        """Check deletion cycle task group by workflow member"""
        member = self.create_user_with_role(member_role)
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory()
            workflow.add_person_with_role_name(member, 'Workflow Member')
            task_group = wf_factories.TaskGroupFactory(
                title='TestTG',
                context=factories.ContextFactory(),
                workflow=workflow)
            wf_factories.TaskGroupTaskFactory(
                title='TestTGT',
                task_group=task_group,
                start_date=datetime.date(2017, 8, 3),
                end_date=datetime.date(2017, 8, 7))
            cycle = wf_factories.CycleFactory(workflow=workflow)
            cycle_task_group = wf_factories.CycleTaskGroupFactory(
                cycle=cycle, title='Title1')
        ctg = all_models.CycleTaskGroup.query.get(cycle_task_group.id)
        self.generator.activate_workflow(workflow)
        self.api.set_user(member)

        response = self.api.delete(ctg)

        self.assertEquals(response.status_code, response_code)
        count = len(all_models.CycleTaskGroup.query.all())
        self.assertEquals(count, exp_count)

    @ddt.data(
        'Reader',
        'Editor',
        'Administrator',
        'Creator',
    )
    def test_delete_ctg_wf_admin(self, admin_role):
        """Check deletion cycle task group by workflow member"""
        admin = self.create_user_with_role(admin_role)
        exp_count = 0
        with factories.single_commit():
            workflow = wf_factories.WorkflowFactory()
            workflow.add_person_with_role_name(admin, 'Admin')
            task_group = wf_factories.TaskGroupFactory(
                title='TestTG',
                context=factories.ContextFactory(),
                workflow=workflow)
            wf_factories.TaskGroupTaskFactory(
                title='TestTGT',
                task_group=task_group,
                start_date=datetime.date(2017, 8, 3),
                end_date=datetime.date(2017, 8, 7))
            cycle = wf_factories.CycleFactory(workflow=workflow)
            cycle_task_group = wf_factories.CycleTaskGroupFactory(
                cycle=cycle, title='Title1')
        ctg = all_models.CycleTaskGroup.query.get(cycle_task_group.id)
        self.generator.activate_workflow(workflow)
        self.api.set_user(admin)

        response = self.api.delete(ctg)

        self.assert200(response)
        count = len(all_models.CycleTaskGroup.query.all())
        self.assertEquals(count, exp_count)
コード例 #55
0
 def setUp(self):
   super(TestResource, self).setUp()
   self.api = Api()
   self.object_generator = ObjectGenerator()
   self.create_objects()
コード例 #56
0
class TestRevisionHistory(TestCase):
    """Test checks permissions for revision history."""
    def setUp(self):
        super(TestRevisionHistory, self).setUp()
        self.api = Api()
        roles = {r.name: r for r in all_models.Role.query.all()}

        with factories.single_commit():
            factories.AccessControlRoleFactory(
                name="ACL_Reader",
                object_type="Control",
                update=0,
            )
            factories.AccessControlRoleFactory(name="ACL_Editor",
                                               object_type="Control")

        with factories.single_commit():
            self.control = factories.ControlFactory()
            self.objective = factories.ObjectiveFactory()
            self.program = factories.ProgramFactory()
            self.program.context.related_object = self.program
            self.relationship = factories.RelationshipFactory(
                source=self.program,
                destination=self.control,
                context=self.program.context,
            )
            self.people = {
                "Creator": factories.PersonFactory(),
                "Reader": factories.PersonFactory(),
                "Editor": factories.PersonFactory(),
                "Administrator": factories.PersonFactory(),
                "ACL_Reader": factories.PersonFactory(),
                "ACL_Editor": factories.PersonFactory(),
                "Program Editors": factories.PersonFactory(),
                "Program Managers": factories.PersonFactory(),
                "Program Readers": factories.PersonFactory(),
            }
            for role_name in ["Creator", "Reader", "Editor", "Administrator"]:
                rbac_factories.UserRoleFactory(role=roles[role_name],
                                               person=self.people[role_name])
            for role_name in [
                    "Program Editors", "Program Managers", "Program Readers"
            ]:
                person = self.people[role_name]
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=person)
                factories.AccessControlPersonFactory(
                    ac_list=self.program.acr_name_acl_map[role_name],
                    person=self.people[role_name],
                )
        with factories.single_commit():
            for role_name in ["ACL_Reader", "ACL_Editor"]:
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=self.people[role_name])
                factories.AccessControlPersonFactory(
                    ac_list=self.control.acr_name_acl_map[role_name],
                    person=self.people[role_name],
                )

    @ddt.data(
        ("Creator", True),
        ("Reader", False),
        ("Editor", False),
        ("ACL_Reader", False),
        ("ACL_Editor", False),
        ("Administrator", False),
        ("Program Editors", False),
        ("Program Managers", False),
        ("Program Readers", False),
    )
    @ddt.unpack
    def test_get(self, role_name, empty):
        """Test get revision history for {0}."""
        control_id = self.control.id
        query = all_models.Revision.query.filter(
            all_models.Revision.resource_id == control_id,
            all_models.Revision.resource_type == self.control.type,
        )
        if empty:
            ids = []
        else:
            ids = [i.id for i in query]
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api.client.get(
            "/api/revisions"
            "?resource_type=Control&resource_id={}".format(control_id))
        self.assertEqual(
            ids,
            [i["id"] for i in resp.json["revisions_collection"]["revisions"]])

    def update_revisions(self, obj):
        """Assert revision diff between api and calculated in test.."""
        query = all_models.Revision.query.filter(
            all_models.Revision.resource_id == obj.id,
            all_models.Revision.resource_type == obj.type,
        ).order_by(sa.desc(all_models.Revision.updated_at))
        diffs = [(i.id, json.loads(json.dumps(i.diff_with_current())))
                 for i in query]
        for i in range(3):
            resp = self.api.client.get(
                "/api/revisions"
                "?__sort=-updated_at"
                "&resource_type={}"
                "&resource_id={}"
                "&_={}".format(obj.type, obj.id,
                               random.randint(1100000000, 1153513123412)))
            resp_diffs = [
                (i["id"], i["diff_with_current"])
                for i in resp.json["revisions_collection"]["revisions"]
            ]
            self.assertDictEqual(dict(diffs), dict(resp_diffs))
        self.assertFalse(any(resp_diffs[0][1].values()))

    def test_control_memcache(self):
        """Test get updated control revisions."""
        control_id = self.control.id
        self.api.put(self.control, {"title": "new_title"})
        self.control = all_models.Control.eager_query().get(control_id)
        self.update_revisions(self.control)
        db.session.expire_all()
        self.control = all_models.Control.eager_query().get(control_id)
        self.api.put(self.control, {"description": "new test description BLA"})
        self.control = all_models.Control.eager_query().get(control_id)
        self.update_revisions(self.control)
        self.api.put(self.control, {"description": "bla bla bla"})
        self.control = all_models.Control.eager_query().get(control_id)
        self.update_revisions(self.control)

    def test_risk_memcache(self):
        """Test get updated risk revisions."""
        risk = factories.RiskFactory()
        risk_id = risk.id
        self.api.put(risk, {"title": "new_title"})
        self.update_revisions(risk)
        db.session.expire_all()
        risk = all_models.Risk.eager_query().get(risk_id)
        self.api.put(risk, {"description": "new test description BLA"})
        risk = all_models.Risk.eager_query().get(risk_id)
        self.update_revisions(risk)
        risk = all_models.Risk.eager_query().get(risk_id)
        self.api.put(risk, {"description": "BLA bla bla"})
        risk = all_models.Risk.eager_query().get(risk_id)
        self.update_revisions(risk)

    def test_change_log(self):
        """Test Change log where CAV attribute_object_id is str in revision
     content"""
        person = factories.PersonFactory()
        cad = factories.CustomAttributeDefinitionFactory(
            definition_type="objective",
            definition_id=self.objective.id,
            attribute_type="Map:Person",
            title="Local Person CA",
        )
        factories.CustomAttributeValueFactory(
            attributable=self.objective,
            custom_attribute=cad,
            attribute_value=person.type,
            attribute_object_id=str(person.id),
        )
        self.api.put(self.objective, {"title": "new_title"})
        objective = all_models.Objective.eager_query().get(self.objective.id)
        self.update_revisions(objective)

    @ddt.data(True, False)
    def test_get_mandatory_acrs(self, mandatory):
        """ACR and mandatory meta info if mandatory flag is {0}."""
        control_id = self.control.id
        acr = factories.AccessControlRoleFactory(name="test_name",
                                                 object_type=self.control.type,
                                                 mandatory=mandatory)
        acr_id = acr.id
        resp = self.api.client.get(
            "/api/revisions"
            "?resource_type=Control&resource_id={}".format(control_id))
        collection = resp.json["revisions_collection"]["revisions"]
        self.assertTrue(collection)
        self.assertIn("meta", collection[0])
        self.assertIn("mandatory", collection[0]["meta"])
        self.assertIn("access_control_roles",
                      collection[0]["meta"]["mandatory"])
        mandatory_acrs = collection[0]["meta"]["mandatory"][
            "access_control_roles"]
        self.assertEqual(mandatory, acr_id in mandatory_acrs)

    @ddt.data(True, False)
    def test_get_mandatory_cads(self, mandatory):
        """CAD and mandatory meta info if mandatory flag is {0}."""
        control_id = self.control.id
        cad = factories.ExternalCustomAttributeDefinitionFactory(
            title="test_name", definition_type="control", mandatory=mandatory)
        cad_id = cad.id
        resp = self.api.client.get(
            "/api/revisions"
            "?resource_type=Control&resource_id={}".format(control_id))
        collection = resp.json["revisions_collection"]["revisions"]
        self.assertTrue(collection)
        self.assertIn("meta", collection[0])
        self.assertIn("mandatory", collection[0]["meta"])
        mandatory_meta = collection[0]["meta"]["mandatory"]
        self.assertIn("custom_attribute_definitions", mandatory_meta)
        mandatory_cads = mandatory_meta["custom_attribute_definitions"]
        self.assertEqual(mandatory, cad_id in mandatory_cads)

    @ddt.data(
        {
            "factory": factories.ControlFactory,
            "fields": ['test_plan', 'status', 'notes', 'description', 'title']
        },
        {
            "factory":
            factories.RiskFactory,
            "fields": [
                'test_plan', 'status', 'description', 'external_id', 'notes',
                'title'
            ]
        },
    )
    @ddt.unpack
    def test_get_mandatory_fields(self, factory, fields):
        """Fields mandatory meta info for {factory._meta.model}."""
        instance = factory()
        resp = self.api.client.get("/api/revisions"
                                   "?resource_type={}&resource_id={}".format(
                                       instance.type, instance.id))
        collection = resp.json["revisions_collection"]["revisions"]
        self.assertTrue(collection)
        self.assertIn("meta", collection[0])
        self.assertIn("mandatory", collection[0]["meta"])
        mandatory_meta = collection[0]["meta"]["mandatory"]
        self.assertIn("fields", mandatory_meta)
        self.assertItemsEqual(fields, mandatory_meta["fields"])

    @ddt.data(
        {
            "factory": factories.ControlFactory,
            "fields": []
        },
        {
            "factory": factories.RiskFactory,
            "fields": []
        },
        {
            "factory": factories.AssessmentFactory,
            "fields": []
        },
    )
    @ddt.unpack
    def test_mandatory_mapping_list(self, factory, fields):
        """Mapping List mandatory meta info for {factory._meta.model}."""
        instance = factory()
        resp = self.api.client.get("/api/revisions"
                                   "?resource_type={}&resource_id={}".format(
                                       instance.type, instance.id))
        collection = resp.json["revisions_collection"]["revisions"]
        self.assertTrue(collection)
        self.assertIn("meta", collection[0])
        self.assertIn("mandatory", collection[0]["meta"])
        mandatory_meta = collection[0]["meta"]["mandatory"]
        self.assertIn("mapping_list_fields", mandatory_meta)
        self.assertEqual(fields, mandatory_meta["mapping_list_fields"])

    @ddt.data(
        {
            "factory": factories.ControlFactory,
            "fields": []
        },
        {
            "factory": factories.RiskFactory,
            "fields": []
        },
        {
            "factory": factories.AssessmentFactory,
            "fields": ["audit"]
        },
    )
    @ddt.unpack
    def test_mandatory_mappings(self, factory, fields):
        """Mapping fields mandatory meta info for {factory._meta.model}."""
        instance = factory()
        resp = self.api.client.get("/api/revisions"
                                   "?resource_type={}&resource_id={}".format(
                                       instance.type, instance.id))
        collection = resp.json["revisions_collection"]["revisions"]
        self.assertTrue(collection)
        self.assertIn("meta", collection[0])
        self.assertIn("mandatory", collection[0]["meta"])
        mandatory_meta = collection[0]["meta"]["mandatory"]
        self.assertIn("mapping_fields", mandatory_meta)
        self.assertEqual(fields, mandatory_meta["mapping_fields"])
コード例 #57
0
class TestAssessment(TestCase):
    """Assessment test cases"""

    # pylint: disable=invalid-name

    def setUp(self):
        super(TestAssessment, self).setUp()
        self.api = Api()

    def test_auto_slug_generation(self):
        """Test auto slug generation"""
        factories.AssessmentFactory(title="Some title")
        ca = Assessment.query.first()
        self.assertEqual("ASSESSMENT-{}".format(ca.id), ca.slug)

    def test_enabling_comment_notifications_by_default(self):
        """New Assessments should have comment notifications enabled by default."""
        asmt = factories.AssessmentFactory()

        self.assertTrue(asmt.send_by_default)
        recipients = asmt.recipients.split(",") if asmt.recipients else []
        self.assertEqual(sorted(recipients),
                         ["Assessor", "Creator", "Verifier"])

    def test_audit_changes_api(self):
        """Test that users can't change the audit mapped to an assessment."""
        audit_id = factories.AuditFactory().id
        asmt = factories.AssessmentFactory()
        correct_audit_id = asmt.audit_id
        response = self.api.put(asmt,
                                {"audit": {
                                    "type": "Audit",
                                    "id": audit_id
                                }})
        self.assert400(response)
        assessment = Assessment.query.first()
        self.assertEqual(assessment.audit_id, correct_audit_id)

    def test_put_no_audit_change(self):
        """Test that put requests works without audit changes"""
        asmt = factories.AssessmentFactory()
        correct_audit_id = asmt.audit_id
        response = self.api.put(
            asmt, {"audit": {
                "type": "Audit",
                "id": correct_audit_id
            }})
        self.assert200(response)
        assessment = Assessment.query.first()
        self.assertEqual(assessment.audit_id, correct_audit_id)

    def test_audit_changes_import(self):
        """Test that users can't change the audit mapped to an assessment."""
        audit = factories.AuditFactory()
        asmt = factories.AssessmentFactory()
        correct_audit_id = asmt.audit_id
        response = self.import_data(
            OrderedDict([
                ("object_type", "Assessment"),
                ("Code*", asmt.slug),
                ("audit", audit.slug),
            ]))
        self._check_csv_response(
            response, {
                "Assessment": {
                    "row_warnings": {
                        errors.UNMODIFIABLE_COLUMN.format(line=3,
                                                          column_name="Audit")
                    }
                }
            })
        assessment = Assessment.query.first()
        self.assertEqual(assessment.audit_id, correct_audit_id)

    def test_no_audit_change_imports(self):
        """Test that imports work if audit field does not contain changes."""
        factories.AuditFactory()
        asmt = factories.AssessmentFactory()
        correct_audit_id = asmt.audit_id
        response = self.import_data(
            OrderedDict([
                ("object_type", "Assessment"),
                ("Code*", asmt.slug),
                ("audit", asmt.audit.slug),
            ]))
        self._check_csv_response(response, {})
        assessment = Assessment.query.first()
        self.assertEqual(assessment.audit_id, correct_audit_id)

    def test_empty_audit_import(self):
        """Test empty audit import"""
        factories.AuditFactory()
        asmt = factories.AssessmentFactory()
        correct_audit_id = asmt.audit_id
        response = self.import_data(
            OrderedDict([
                ("object_type", "Assessment"),
                ("Code*", asmt.slug),
                ("audit", ""),
            ]))
        self._check_csv_response(response, {})
        assessment = Assessment.query.first()
        self.assertEqual(assessment.audit_id, correct_audit_id)
コード例 #58
0
class TestBacklogWorkflow(TestCase):
    """Test cases for backlog workflow"""
    def setUp(self):  # noqa
        super(TestBacklogWorkflow, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.create_backlog_workflow()

    def tearDown(self):
        pass

    def create_backlog_workflow(self):  # pylint: disable=no-self-use
        """Creates one time backlog workflow in database."""

        Workflow.ensure_backlog_workflow_exists()

    def test_add_ctgot_to_backlog_workflow(self):  # pylint: disable=invalid-name
        """Check that backlog workflow exists and test it's basic functionality"""
        # find a backlog workflow
        backlog_workflow = db.session\
                             .query(Workflow)\
                             .filter(Workflow.kind == "Backlog").one()
        backlog_workflow_context_id = backlog_workflow.context.id

        # check that it has an active cycle and a cycle task group
        self.assertEqual(len(backlog_workflow.cycles), 1)
        backlog_cycle = backlog_workflow.cycles[0]
        self.assertEqual(backlog_cycle.is_current, 1)

        # check if it has a cycle task group
        self.assertEqual(len(backlog_cycle.cycle_task_groups), 1)
        backlog_cycle_task_group = backlog_cycle.cycle_task_groups[0]

        # Check that backlog workflow has no workflow people
        self.assertEqual(len(backlog_workflow.people), 0)
        # create a cycle task with creator and put it in backlog workflow
        _, creator = self.object_generator.generate_person(user_role="Creator")
        self.api.set_user(creator)

        # add a task that finishes before the first task in the cycle
        cycle_task_json = {
            'cycle_task_group_object_task': {
                "title": "Cycle task for backlog",
                "cycle": {
                    "id": backlog_cycle.id,
                    "type": "Cycle"
                },
                "status": "Assigned",
                "cycle_task_group": {
                    "id": backlog_cycle_task_group.id,
                    "type": "CycleTaskGroup"
                },
                "start_date": "07/1/2015",
                "end_date": "07/2/2015",
                "task_type": "text",
                "context": {
                    "id": backlog_workflow_context_id,
                    "type": "Context"
                },
                "task_group_task": {
                    "id": 0,
                    "type": "TaskGroupTask"
                }
            }
        }

        response = self.generator.api.post(CycleTaskGroupObjectTask,
                                           cycle_task_json)
        self.assertEqual(response.status_code, 201)

        backlog_cycle_task_group = db.session.query(CycleTaskGroup).filter(
            CycleTaskGroup.cycle_id == backlog_cycle.id).one()
        # Check that changes were not propagated to backlog's CycleTaskGroup
        self.assertEqual(backlog_cycle_task_group.status, "InProgress")
        self.assertEqual(backlog_cycle_task_group.start_date, None)
        self.assertEqual(backlog_cycle_task_group.end_date, None)

        backlog_cycle = db.session.query(Cycle).filter(
            Cycle.id == backlog_cycle.id).one()
        # Check that cycle is still running
        self.assertEqual(backlog_cycle.is_current, 1)
        self.assertEqual(backlog_cycle.status, "Assigned")

    @mock.patch('ggrc_basic_permissions.get_current_user')
    def test_permissions_for_backlog_workflow(self, mock_get_current_user):  # noqa # pylint: disable=invalid-name
        """Tests whether the creator has all the necessary permissions for
    backlog workflow."""

        my_person = Person(name="kekec", email="*****@*****.**")
        creator_role = Role.query.filter(Role.name == "Creator").one()
        user_role = UserRole(role=creator_role, person=my_person)  # noqa # pylint: disable=unused-variable
        mock_get_current_user.return_value = Person(name="Mojca",
                                                    email="*****@*****.**")
        backlog_workflow = db.session\
                             .query(Workflow)\
                             .filter(Workflow.kind == "Backlog").one()
        workflow_ctx = backlog_workflow.context.id
        user_perms = load_permissions_for(my_person)

        actions = ["read", "edit", "update"]
        _types = [
            "Workflow", "Cycle", "CycleTaskGroup", "CycleTaskGroupObjectTask",
            "TaskGroup"
        ]

        for action in actions:
            for obj_type in _types:
                self.assertTrue(
                    workflow_ctx in user_perms[action][obj_type]['contexts'])
        ctgot_ctxs = user_perms['delete']['CycleTaskGroupObjectTask'][
            'contexts']
        self.assertTrue(workflow_ctx in ctgot_ctxs)
コード例 #59
0
class TestPermissions(TestCase):
    """Test checks permissions for proposals."""
    def setUp(self):
        super(TestPermissions, self).setUp()
        self.api = Api()
        roles = {r.name: r for r in all_models.Role.query.all()}
        with factories.single_commit():
            self.control = factories.ControlFactory()
            acrs = {
                "ACL_Reader":
                factories.AccessControlRoleFactory(name="ACL_Reader",
                                                   object_type="Control",
                                                   update=0),
                "ACL_Editor":
                factories.AccessControlRoleFactory(name="ACL_Editor",
                                                   object_type="Control"),
            }
            self.program = factories.ProgramFactory()
            self.program.context.related_object = self.program
            self.relationship = factories.RelationshipFactory(
                source=self.program,
                destination=self.control,
                context=self.program.context,
            )
            self.people = {
                "Creator": factories.PersonFactory(),
                "Reader": factories.PersonFactory(),
                "Editor": factories.PersonFactory(),
                "Administrator": factories.PersonFactory(),
                "ACL_Reader": factories.PersonFactory(),
                "ACL_Editor": factories.PersonFactory(),
                "ProgramEditor": factories.PersonFactory(),
                "ProgramOwner": factories.PersonFactory(),
                "ProgramReader": factories.PersonFactory(),
            }
            for role_name in ["Creator", "Reader", "Editor", "Administrator"]:
                rbac_factories.UserRoleFactory(role=roles[role_name],
                                               person=self.people[role_name])
            for role_name in [
                    "ProgramEditor", "ProgramOwner", "ProgramReader"
            ]:
                person = self.people[role_name]
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=person)
                rbac_factories.UserRoleFactory(role=roles[role_name],
                                               person=person,
                                               context=self.program.context)
            self.proposal = factories.ProposalFactory(
                instance=self.control,
                content={
                    "access_control_list": {},
                    "custom_attribute_values": {},
                    "fields": {},
                    "mapping_fields": {},
                    "mapping_list_fields": {},
                })
            for role_name in ["ACL_Reader", "ACL_Editor"]:
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=self.people[role_name])
                factories.AccessControlListFactory(
                    ac_role=acrs[role_name],
                    object=self.control,
                    person=self.people[role_name])
            proposal_model.set_acl_to_all_proposals_for(self.control)

    @ddt.data(
        ("Creator", 403),
        ("Reader", 200),
        ("Editor", 200),
        ("ACL_Reader", 200),
        ("ACL_Editor", 200),
        ("Administrator", 200),
        ("ProgramEditor", 200),
        ("ProgramOwner", 200),
        ("ProgramReader", 200),
    )
    @ddt.unpack
    def test_permissions_on_get(self, role_name, status):
        """Test get proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api.get(all_models.Proposal, proposal_id)
        self.assertEqual(status, resp.status_code)

    def api_proposal_status_change(self, proposal_id, status):
        return self.api.put(all_models.Proposal.query.get(proposal_id),
                            {"proposal": {
                                "status": status
                            }})

    @ddt.data(("Creator", 403), ("Reader", 403), ("Editor", 200),
              ("Administrator", 200), ("ACL_Reader", 403), ("ACL_Editor", 200),
              ("ProgramEditor", 200), ("ProgramOwner", 200),
              ("ProgramReader", 403))
    @ddt.unpack
    def test_permissions_on_apply(self, role_name, status):
        """Test apply proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api_proposal_status_change(
            proposal_id, all_models.Proposal.STATES.APPLIED)
        self.assertEqual(status, resp.status_code)

    @ddt.data(
        ("Creator", 403),
        ("Reader", 403),
        ("Editor", 200),
        ("ACL_Reader", 403),
        ("ACL_Editor", 200),
        ("Administrator", 200),
        ("ProgramEditor", 200),
        ("ProgramOwner", 200),
        ("ProgramReader", 403),
    )
    @ddt.unpack
    def test_permissions_on_decline(self, role_name, status):
        """Test decline proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api_proposal_status_change(
            proposal_id, all_models.Proposal.STATES.DECLINED)
        self.assertEqual(status, resp.status_code)

    @ddt.data(
        ("Creator", 403),
        ("Reader", 201),
        ("Editor", 201),
        ("ACL_Reader", 201),
        ("ACL_Editor", 201),
        ("Administrator", 201),
        ("ProgramEditor", 201),
        ("ProgramOwner", 201),
        ("ProgramReader", 201),
    )
    @ddt.unpack
    def test_permissions_on_create(self, role_name, status):
        """Test create proposal for {0}."""
        data = {
            "proposal": {
                "instance": {
                    "id": self.control.id,
                    "type": self.control.type,
                },
                "full_instance_content": {
                    "title": "new_title"
                },
                "agenda": "update cav",
                "context": None,
            }
        }
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api.post(all_models.Proposal, data)
        self.assertEqual(status, resp.status_code)
コード例 #60
0
 def setUp(self):
     super(TestAssessment, self).setUp()
     self.api = Api()