Commit 6fa5d474 authored by Enrico Zini's avatar Enrico Zini
Browse files

Implemented and tested permissions for viewing private logs

parent b435fe95
...@@ -50,6 +50,7 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions): ...@@ -50,6 +50,7 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions):
pass pass
elif self.visitor.is_admin: elif self.visitor.is_admin:
self.add("view_mbox") self.add("view_mbox")
self.add("view_private_log")
if not self.process.closed: if not self.process.closed:
if not self.process_frozen: if not self.process_frozen:
self.add("proc_freeze") self.add("proc_freeze")
...@@ -59,8 +60,10 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions): ...@@ -59,8 +60,10 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions):
self.update(("proc_unfreeze", "proc_approve")) self.update(("proc_unfreeze", "proc_approve"))
elif self.visitor == self.person: elif self.visitor == self.person:
self.add("view_mbox") self.add("view_mbox")
self.add("view_private_log")
elif self.visitor.is_active_am: elif self.visitor.is_active_am:
self.add("view_mbox") self.add("view_mbox")
self.add("view_private_log")
# TODO: advocates of this process can see the mailbox(?) # TODO: advocates of this process can see the mailbox(?)
#elif self.process.advocates.filter(pk=self.visitor.pk).exists(): #elif self.process.advocates.filter(pk=self.visitor.pk).exists():
# self.add("view_mbox") # self.add("view_mbox")
...@@ -68,6 +71,7 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions): ...@@ -68,6 +71,7 @@ class ProcessVisitorPermissions(bmodels.PersonVisitorPermissions):
# The current AM can see fd comments in this process # The current AM can see fd comments in this process
if self.is_current_am: if self.is_current_am:
self.add("fd_comments") self.add("fd_comments")
self.add("view_private_log")
class RequirementVisitorPermissions(ProcessVisitorPermissions): class RequirementVisitorPermissions(ProcessVisitorPermissions):
...@@ -243,7 +247,7 @@ class Process(models.Model): ...@@ -243,7 +247,7 @@ class Process(models.Model):
for s in adv.statements.all(): for s in adv.statements.all():
advocates.add(s.uploaded_by) advocates.add(s.uploaded_by)
log = self.log.order_by("logdate") log = list(self.log.order_by("logdate"))
return { return {
"requirements": requirements, "requirements": requirements,
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
</thead> </thead>
<tbody> <tbody>
{% for e in entries %} {% for e in entries %}
{% if e.is_public or "view_private_log" in visit_perms %}
<tr> <tr>
<td>{{e.logdate|date:"Y-m-d H:i"}}</td> <td>{{e.logdate|date:"Y-m-d H:i"}}</td>
<td>{{e.changed_by.a_link}}</a></td> <td>{{e.changed_by.a_link}}</a></td>
...@@ -56,6 +57,7 @@ ...@@ -56,6 +57,7 @@
<td><a href="{% url 'admin:process_log_change' e.pk %}">admin</a></td> <td><a href="{% url 'admin:process_log_change' e.pk %}">admin</a></td>
{% endif %} {% endif %}
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
...@@ -152,15 +152,18 @@ class ProcessFixtureMixin(PersonFixtureMixin): ...@@ -152,15 +152,18 @@ class ProcessFixtureMixin(PersonFixtureMixin):
def setUpClass(cls): def setUpClass(cls):
super(ProcessFixtureMixin, cls).setUpClass() super(ProcessFixtureMixin, cls).setUpClass()
cls.processes = TestProcesses(**cls.get_processes_defaults()) cls.processes = TestProcesses(**cls.get_processes_defaults())
cls.amassignments = NamedObjects(pmodels.AMAssignment)
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
cls.amassignments.delete_all()
cls.processes.delete_all() cls.processes.delete_all()
super(ProcessFixtureMixin, cls).tearDownClass() super(ProcessFixtureMixin, cls).tearDownClass()
def setUp(self): def setUp(self):
super(ProcessFixtureMixin, self).setUp() super(ProcessFixtureMixin, self).setUp()
self.processes.refresh(); self.processes.refresh()
self.amassignments.refresh()
def get_all_process_types(): def get_all_process_types():
......
...@@ -25,7 +25,7 @@ class ProcExpected(object): ...@@ -25,7 +25,7 @@ class ProcExpected(object):
def patch_generic_process_started(self): def patch_generic_process_started(self):
self.proc.set("app dd_nu dd_u activeam fd dam", "update_keycheck view_person_audit_log") self.proc.set("app dd_nu dd_u activeam fd dam", "update_keycheck view_person_audit_log")
self.proc.patch("activeam fd dam app", "+edit_bio +edit_ldap +view_mbox") self.proc.patch("activeam fd dam app", "+edit_bio +edit_ldap +view_mbox +view_private_log")
self.proc.patch("fd dam app", "+request_new_status") self.proc.patch("fd dam app", "+request_new_status")
self.proc.patch("fd dam", "+proc_freeze +fd_comments") self.proc.patch("fd dam", "+proc_freeze +fd_comments")
self.proc.patch("dc dc_ga dm dm_ga dd_nu dd_u dd_e dd_r activeam fd dam app", "+add_log") self.proc.patch("dc dc_ga dm dm_ga dd_nu dd_u dd_e dd_r activeam fd dam app", "+add_log")
...@@ -38,7 +38,7 @@ class ProcExpected(object): ...@@ -38,7 +38,7 @@ class ProcExpected(object):
if self.keycheck is not None: if self.keycheck is not None:
pass pass
if self.am_ok is not None: if self.am_ok is not None:
self.proc.set("am", "update_keycheck view_person_audit_log edit_bio edit_ldap view_mbox add_log") self.proc.patch("am", "+update_keycheck +view_person_audit_log +edit_bio +edit_ldap +view_mbox +view_private_log +add_log")
self.intent.patch("am", "+req_approve") self.intent.patch("am", "+req_approve")
self.sc_dmup.patch("am", "+req_approve") self.sc_dmup.patch("am", "+req_approve")
if self.advocate: if self.advocate:
...@@ -499,131 +499,4 @@ class TestVisitApplicant(ProcessFixtureMixin, TestCase): ...@@ -499,131 +499,4 @@ class TestVisitApplicant(ProcessFixtureMixin, TestCase):
expected.patch_generic_process_closed() expected.patch_generic_process_closed()
self.assertPerms(expected) self.assertPerms(expected)
# TODO: process closed but not frozen and approved (aborted)
#class RequirementTestMixin(ProcessFixtureMixin):
# Changes according to:
# visitor (admin, dd, active am, applicant, dm (if applying for GA) (for advocate), current am (for am_ok)
# state of the requirement (approved or not)
# presence of statements
# uploader of statement
# state of the process (frozen or not)
# TODO: intent with no statements
# TODO: intent with a statement
# TODO: intent approved
# TODO: probably better, test requirements separately (like, intent and
# sc_dmup are the same for everyone)
# then here just test what happens when the various steps are
# completed, or the AM is assigned
# requirements = ["intent", "sc_dmup"]
# if applying_for == const.STATUS_DC_GA:
# if person.status != const.STATUS_DC:
# raise RuntimeError("Invalid applying_for value {} for a person with status {}".format(applying_for, person.status))
# requirements.append("advocate")
# elif applying_for == const.STATUS_DM:
# if person.status != const.STATUS_DC:
# raise RuntimeError("Invalid applying_for value {} for a person with status {}".format(applying_for, person.status))
# requirements.append("advocate")
# requirements.append("keycheck")
# elif applying_for == const.STATUS_DM_GA:
# if person.status == const.STATUS_DC_GA:
# requirements.append("advocate")
# requirements.append("keycheck")
# elif person.status == const.STATUS_DM:
# # No extra requirement: the declaration of intents is
# # sufficient
# pass
# else:
# raise RuntimeError("Invalid applying_for value {} for a person with status {}".format(applying_for, person.status))
# elif applying_for in (const.STATUS_DD_U, const.STATUS_DD_NU):
# if person.status != const.STATUS_DD_NU:
# requirements.append("keycheck")
# requirements.append("am_ok")
# if person.status not in (const.STATUS_EMERITUS_DD, const.STATUS_REMOVED_DD):
# requirements.append("advocate")
# else:
# raise RuntimeError("Invalid applying_for value {}".format(applying_for))
#class TestPermsRequirementIntent(ProcessFixtureMixin, TestCase):
# @classmethod
# def __add_extra_tests__(cls):
# # Process list is visible by anyone
# for src, tgt in get_all_process_types():
# cls._add_method(cls._test_requirement, src, tgt)
#
# def _test_requirement(self, src_state, applying_for):
# self.persons.create("app", status=src_state)
# self.persons.create("adv", status=const.STATUS_DD_NU)
# self.processes.create("app", person=self.persons.app, applying_for=applying_for)
#
# expected_advs = ExpectedSets("{visitor} advocating app", "{problem} target {mismatch}")
# expected.advs.set("fd dam dd_nu dd_u", "dc_ga dm dd_u dd_nu")
# expected_perms = ExpectedSets("{visitor} visiting app's intent requirement", "{problem} permissions {mismatch}")
# expected.perms.set("fd dam app", "update_keycheck edit_bio edit_ldap view_person_audit_log see_statements edit_statements view_mbox request_new_status")
#
# # Requirement just created
# req = pmodels.Requirement.objects.get(process=self.processes, type="intent")
#
#
# self.assertIsNone(req.approved_by)
# self.assertIsNone(req.approved_time)
#
# # Anyone can see the requirement page
# for visitor in ("pending", "dc", "dc_ga", "dm", "dm_ga", "dd_nu", "dd_u", "dd_e", "dd_r", "fd", "dam", None):
# client = self.make_test_client(visitor)
# response = client.get(req.get_absolute_url())
# self.assertEquals(response.status_code, 200)
#
# # Only the applicant, FD and DAM can upload a statement
# for visitor in ("pending", "dc", "dc_ga", "dm", "dm_ga", "dd_nu", "dd_u", "dd_e", "dd_r", "fd", "dam", None):
# for visitor in ("pending", "dc", "dc_ga", "dm", "dm_ga", "dd_nu", "dd_u", "dd_e", "dd_r", "fd", "dam", None):
# client = self.make_test_client(visitor)
# response = client.get(req.get_absolute_url())
# self.assertEquals(response.status_code, 200)
#url(r'^(?P<pk>\d+)/intent$', views.ReqIntent.as_view(), name="process_req_intent"),
#url(r'^(?P<pk>\d+)/(?P<type>[^/]+)/statement/create$', views.StatementCreate.as_view(), name="process_statement_create"),
#url(r'^(?P<pk>\d+)/(?P<type>[^/]+)/statement/(?P<st>\d+)/edit$', views.StatementEdit.as_view(), name="process_statement_edit"),
#url(r'^(?P<pk>\d+)/(?P<type>[^/]+)/statement/(?P<st>\d+)/raw$', views.StatementRaw.as_view(), name="process_statement_raw"),
#url(r'^(?P<pk>\d+)/(?P<type>[^/]+)/add_log$', views.AddProcessLog.as_view(), name="process_add_requirement_log"),
#class Requirement(models.Model):
# process = models.ForeignKey(Process, related_name="requirements")
# type = models.CharField(verbose_name=_("Requirement type"), max_length=16, choices=REQUIREMENT_TYPES_CHOICES)
# approved_by = models.ForeignKey(bmodels.Person, null=True, blank=True, help_text=_("Set to the person that reviewed and approved this requirement"))
# approved_time = models.DateTimeField(null=True, blank=True, help_text=_("When the requirement has been approved"))
#class Statement(models.Model):
# requirement = models.ForeignKey(Requirement, related_name="statements")
# fpr = models.ForeignKey(bmodels.Fingerprint, related_name="+", help_text=_("Fingerprint used to verify the statement"))
# statement = models.TextField(verbose_name=_("Signed statement"), blank=True)
# uploaded_by = models.ForeignKey(bmodels.Person, related_name="+", help_text=_("Person who uploaded the statement"))
# uploaded_time = models.DateTimeField(help_text=_("When the statement has been uploaded"))
#class Log(models.Model):
# changed_by = models.ForeignKey(bmodels.Person, related_name="+", null=True)
# process = models.ForeignKey(Process, related_name="log")
# requirement = models.ForeignKey(Requirement, related_name="log", null=True, blank=True)
# is_public = models.BooleanField(default=False)
# logdate = models.DateTimeField(default=now)
# action = models.CharField(max_length=16, blank=True, help_text=_("Action performed with this log entry, if any"))
# logtext = models.TextField(blank=True, default="")
# add statement (app, fd, dam)
# remove statement (app if own, fd, dam)
# edit statement (app if own, fd, dam)
# approve
# log comments
# freeze process and ensure it's unchangeable
...@@ -22,6 +22,10 @@ class TestProcessShow(ProcessFixtureMixin, TestCase): ...@@ -22,6 +22,10 @@ class TestProcessShow(ProcessFixtureMixin, TestCase):
cls.processes.create("app", person=cls.persons.app, applying_for=const.STATUS_DD_U, fd_comment="test") cls.processes.create("app", person=cls.persons.app, applying_for=const.STATUS_DD_U, fd_comment="test")
cls.persons.create("am", status=const.STATUS_DD_NU) cls.persons.create("am", status=const.STATUS_DD_NU)
cls.ams.create("am", person=cls.persons.am) cls.ams.create("am", person=cls.persons.am)
cls.amassignments.create("am", process=cls.processes.app, am=cls.ams.am, assigned_by=cls.persons["fd"], assigned_time=now())
cls.processes.app.add_log(cls.persons.fd, "xxxx_public_xxxx", is_public=True)
cls.processes.app.add_log(cls.persons.fd, "xxxx_private_xxxx", is_public=False)
cls.visitor = cls.persons.dc cls.visitor = cls.persons.dc
...@@ -34,16 +38,18 @@ class TestProcessShow(ProcessFixtureMixin, TestCase): ...@@ -34,16 +38,18 @@ class TestProcessShow(ProcessFixtureMixin, TestCase):
cls.page_elements.add_id("proc_unfreeze") cls.page_elements.add_id("proc_unfreeze")
cls.page_elements.add_id("proc_approve") cls.page_elements.add_id("proc_approve")
cls.page_elements.add_id("proc_unapprove") cls.page_elements.add_id("proc_unapprove")
cls.page_elements.add_string("view_public_log", "xxxx_public_xxxx")
cls.page_elements.add_string("view_private_log", "xxxx_private_xxxx")
def assertPageElements(self, response): def assertPageElements(self, response):
# Check page elements based on visit_perms # Check page elements based on visit_perms
visit_perms = self.processes.app.permissions_of(self.visitor) visit_perms = self.processes.app.permissions_of(self.visitor)
wanted = [] wanted = ["view_public_log"]
if "fd_comments" in visit_perms: if "fd_comments" in visit_perms:
wanted.append("view_fd_comment") wanted.append("view_fd_comment")
if "add_log" in visit_perms: if "add_log" in visit_perms:
wanted += ["log_public", "log_private"] wanted += ["log_public", "log_private"]
for el in ("view_mbox", "proc_freeze", "proc_unfreeze", "proc_approve", "proc_unapprove"): for el in ("view_mbox", "view_private_log", "proc_freeze", "proc_unfreeze", "proc_approve", "proc_unapprove"):
if el in visit_perms: wanted.append(el) if el in visit_perms: wanted.append(el)
self.assertContainsElements(response, self.page_elements, *wanted) self.assertContainsElements(response, self.page_elements, *wanted)
...@@ -56,40 +62,30 @@ class TestProcessShow(ProcessFixtureMixin, TestCase): ...@@ -56,40 +62,30 @@ class TestProcessShow(ProcessFixtureMixin, TestCase):
def test_none(self): def test_none(self):
self.tryVisitingWithPerms(set()) self.tryVisitingWithPerms(set())
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set()) def test_view_private_log(self):
self.tryVisitingWithPerms(set(["view_private_log"]))
def test_view_mbox(self):
self.tryVisitingWithPerms(set(["view_mbox"]))
def test_fd_comments(self): def test_fd_comments(self):
self.tryVisitingWithPerms(set(["fd_comments"])) self.tryVisitingWithPerms(set(["fd_comments"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["fd_comments"]))
def test_add_log(self): def test_add_log(self):
self.tryVisitingWithPerms(set(["add_log"])) self.tryVisitingWithPerms(set(["add_log"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["add_log"]))
def test_view_mbox(self): def test_view_mbox(self):
self.tryVisitingWithPerms(set(["view_mbox"])) self.tryVisitingWithPerms(set(["view_mbox"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["view_mbox"]))
def test_proc_freeze(self): def test_proc_freeze(self):
self.tryVisitingWithPerms(set(["proc_freeze"])) self.tryVisitingWithPerms(set(["proc_freeze"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["proc_freeze"]))
def test_proc_unfreeze(self): def test_proc_unfreeze(self):
self.tryVisitingWithPerms(set(["proc_unfreeze"])) self.tryVisitingWithPerms(set(["proc_unfreeze"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["proc_unfreeze"]))
def test_proc_approve(self): def test_proc_approve(self):
self.tryVisitingWithPerms(set(["proc_approve"])) self.tryVisitingWithPerms(set(["proc_approve"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["proc_approve"]))
def test_proc_unapprove(self): def test_proc_unapprove(self):
self.tryVisitingWithPerms(set(["proc_unapprove"])) self.tryVisitingWithPerms(set(["proc_unapprove"]))
pmodels.AMAssignment.objects.create(process=self.processes.app, am=self.ams.am, assigned_by=self.persons["fd"], assigned_time=now())
self.tryVisitingWithPerms(set(["proc_unapprove"]))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment