1647
def setPrivate(self, private, who):
1650
We also record who made the change and when the change took
1649
def setPrivacyAndSecurityRelated(self, private, security_related, who):
1651
private_changed = False
1652
security_related_changed = False
1654
# Before we update the privacy or security_related status, we need to
1655
# reconcile the subscribers to avoid leaking private information.
1656
if (self.private != private
1657
or self.security_related != security_related):
1658
self.reconcileSubscribers(private, security_related, who)
1653
1660
if self.private != private:
1655
# Change indirect subscribers into direct subscribers
1656
# *before* setting private because
1657
# getIndirectSubscribers() behaves differently when
1658
# the bug is private.
1659
for person in self.getIndirectSubscribers():
1660
self.subscribe(person, who)
1661
subscribers_for_who = self.getSubscribersForPerson(who)
1662
if subscribers_for_who.is_empty():
1663
# We also add `who` as a subscriber, if they're not
1664
# already directly subscribed or part of a team
1665
# that's directly subscribed, so that they can
1666
# see the bug they've just marked private.
1667
self.subscribe(who, who)
1661
private_changed = True
1669
1662
self.private = private
1680
1673
for attachment in self.attachments_unpopulated:
1681
1674
attachment.libraryfile.restricted = private
1683
# Correct the heat for the bug immediately, so that we don't have
1684
# to wait for the next calculation job for the adjusted heat.
1686
return True # Changed.
1688
return False # Not changed.
1690
def setSecurityRelated(self, security_related):
1691
"""Setter for the `security_related` property."""
1692
1676
if self.security_related != security_related:
1677
security_related_changed = True
1693
1678
self.security_related = security_related
1680
if private_changed or security_related_changed:
1695
1681
# Correct the heat for the bug immediately, so that we don't have
1696
1682
# to wait for the next calculation job for the adjusted heat.
1697
1683
self.updateHeat()
1699
return True # Changed
1701
return False # Unchanged
1685
return private_changed, security_related_changed
1687
def setPrivate(self, private, who):
1690
We also record who made the change and when the change took
1693
return self.setPrivacyAndSecurityRelated(
1694
private, self.security_related, who)[0]
1696
def setSecurityRelated(self, security_related, who):
1697
"""Setter for the `security_related` property."""
1698
return self.setPrivacyAndSecurityRelated(
1699
self.private, security_related, who)[1]
1701
def getRequiredSubscribers(self, for_private, for_security_related, who):
1702
"""Return the mandatory subscribers for a bug with given attributes.
1704
When a bug is marked as private or security related, it is required
1705
that certain people be subscribed so they can access details about the
1707
security=true, private=true/false ->
1708
subscribers = the reporter + security contact for each task
1709
security=false, private=true ->
1710
subscribers = the reporter + bug supervisor for each task
1711
security=false, private=false ->
1714
If bug supervisor or security contact is unset, fallback to bugtask
1717
if not for_private and not for_security_related:
1720
result.add(self.owner)
1721
for bugtask in self.bugtasks:
1722
maintainer = bugtask.pillar.owner
1723
if for_security_related:
1724
result.add(bugtask.pillar.security_contact or maintainer)
1726
result.add(bugtask.pillar.bug_supervisor or maintainer)
1728
subscribers_for_who = self.getSubscribersForPerson(who)
1729
if subscribers_for_who.is_empty():
1733
def getAutoRemovedSubscribers(self, for_private, for_security_related):
1734
"""Return the to be removed subscribers for bug with given attributes.
1736
When a bug's privacy or security related attributes change, some
1737
existing subscribers may need to be automatically removed.
1740
auto removed subscribers = (bugtask security contacts)
1742
auto removed subscribers = (bugtask bug supervisors)
1747
# There has been some discussion as to whether we really want to
1748
# automatically unsubscribe the security contact if a bug is marked
1749
# as no longer security related or the bug supervisor if a bug is no
1751
# We want this behaviour for Launchpad but perhaps not Ubuntu.
1752
# Until this can be clarified, we will not automatically unsubscribe
1755
# for bugtask in self.bugtasks:
1756
# if not for_security_related and bugtask.pillar.security_contact:
1757
# result.add(bugtask.pillar.security_contact)
1758
# if not for_private and bugtask.pillar.bug_supervisor:
1759
# result.add(bugtask.pillar.bug_supervisor)
1762
def reconcileSubscribers(self, for_private, for_security_related, who):
1763
""" Ensure only appropriate people are subscribed to private bugs.
1765
When a bug is marked as either private = True or security_related =
1766
True, we need to ensure that only people who are authorised to know
1767
about the privileged contents of the bug remain directly subscribed
1769
1. Get the required subscribers depending on the bug status.
1770
2. Get the auto removed subscribers depending on the bug status.
1771
eg security contacts when a bug is updated to security related =
1773
3. Get the allowed subscribers = required subscribers
1775
4. Remove any current direct subscribers who are not allowed or are
1777
5. Add any subscribers who are required.
1779
current_direct_subscribers = (
1780
self.getSubscriptionInfo().direct_subscribers)
1781
required_subscribers = self.getRequiredSubscribers(
1782
for_private, for_security_related, who)
1783
auto_removed_subscribers = self.getAutoRemovedSubscribers(
1784
for_private, for_security_related)
1785
allowed_subscribers = set()
1786
allowed_subscribers.add(self.owner)
1787
for bugtask in self.bugtasks:
1788
allowed_subscribers.add(bugtask.owner)
1789
allowed_subscribers.add(bugtask.pillar.owner)
1790
allowed_subscribers.update(set(bugtask.pillar.drivers))
1791
allowed_subscribers = required_subscribers.union(allowed_subscribers)
1793
subscribers_to_remove = auto_removed_subscribers
1794
if for_private or for_security_related:
1795
subscribers_to_remove = auto_removed_subscribers.union(
1796
current_direct_subscribers.difference(allowed_subscribers))
1797
for subscriber in subscribers_to_remove:
1798
self.unsubscribe(subscriber, who, ignore_permissions=True)
1800
subscribers_to_add = (
1801
required_subscribers.difference(current_direct_subscribers))
1802
for subscriber in subscribers_to_add:
1803
self.subscribe(subscriber, who)
1703
1805
def getBugTask(self, target):
1704
1806
"""See `IBug`."""