Merge lp:~cjwatson/launchpad/transitive-participation-visibility into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 17479
Proposed branch: lp:~cjwatson/launchpad/transitive-participation-visibility
Merge into: lp:launchpad
Diff against target: 109 lines (+40/-8)
2 files modified
lib/lp/registry/browser/person.py (+7/-2)
lib/lp/registry/browser/tests/test_person.py (+33/-6)
To merge this branch: bzr merge lp:~cjwatson/launchpad/transitive-participation-visibility
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+258285@code.launchpad.net

Commit message

On Person:+participation, show teams without LimitedView as "[private team]".

Description of the change

On Person:+participation, show teams without LimitedView as "[private team]".

It's possible that this will cause performance issues since PublicOrPrivateTeamsExistence.checkAuthenticated is terrible; but hopefully the authorisation cache will save us from the worst of that, and we can deal with that once we have OOPSes to work from if necessary. If you think we need to tackle this up-front, then suggestions on plausible ways to do that check in bulk would be good.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

We just have to hope that there aren't too many private teams shown, I suppose. Any more than a handful and the page will faceplant.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2015-04-19 12:56:32 +0000
+++ lib/lp/registry/browser/person.py 2015-05-05 17:01:46 +0000
@@ -2041,8 +2041,13 @@
2041 # When showing the path, it's unnecessary to show the team in2041 # When showing the path, it's unnecessary to show the team in
2042 # question at the beginning of the path, or the user at the2042 # question at the beginning of the path, or the user at the
2043 # end of the path.2043 # end of the path.
2044 via = ", ".join(2044 via_names = []
2045 [via_team.displayname for via_team in via[1:-1]])2045 for via_team in via[1:-1]:
2046 if check_permission('launchpad.LimitedView', via_team):
2047 via_names.append(via_team.displayname)
2048 else:
2049 via_names.append('[private team]')
2050 via = ", ".join(via_names)
20462051
2047 if membership is None:2052 if membership is None:
2048 # Membership is via an indirect team so sane defaults exist.2053 # Membership is via an indirect team so sane defaults exist.
20492054
=== modified file 'lib/lp/registry/browser/tests/test_person.py'
--- lib/lp/registry/browser/tests/test_person.py 2015-03-09 11:38:14 +0000
+++ lib/lp/registry/browser/tests/test_person.py 2015-05-05 17:01:46 +0000
@@ -760,13 +760,13 @@
760 self.user = self.factory.makePerson()760 self.user = self.factory.makePerson()
761 self.view = create_view(self.user, name='+participation')761 self.view = create_view(self.user, name='+participation')
762762
763 def test__asParticpation_owner(self):763 def test__asParticipation_owner(self):
764 # Team owners have the role of 'Owner'.764 # Team owners have the role of 'Owner'.
765 self.factory.makeTeam(owner=self.user)765 self.factory.makeTeam(owner=self.user)
766 [participation] = self.view.active_participations766 [participation] = self.view.active_participations
767 self.assertEqual('Owner', participation['role'])767 self.assertEqual('Owner', participation['role'])
768768
769 def test__asParticpation_admin(self):769 def test__asParticipation_admin(self):
770 # Team admins have the role of 'Admin'.770 # Team admins have the role of 'Admin'.
771 team = self.factory.makeTeam()771 team = self.factory.makeTeam()
772 login_person(team.teamowner)772 login_person(team.teamowner)
@@ -777,7 +777,7 @@
777 [participation] = self.view.active_participations777 [participation] = self.view.active_participations
778 self.assertEqual('Admin', participation['role'])778 self.assertEqual('Admin', participation['role'])
779779
780 def test__asParticpation_member(self):780 def test__asParticipation_member(self):
781 # The default team role is 'Member'.781 # The default team role is 'Member'.
782 team = self.factory.makeTeam()782 team = self.factory.makeTeam()
783 login_person(team.teamowner)783 login_person(team.teamowner)
@@ -785,7 +785,7 @@
785 [participation] = self.view.active_participations785 [participation] = self.view.active_participations
786 self.assertEqual('Member', participation['role'])786 self.assertEqual('Member', participation['role'])
787787
788 def test__asParticpation_without_mailing_list(self):788 def test__asParticipation_without_mailing_list(self):
789 # The default team role is 'Member'.789 # The default team role is 'Member'.
790 team = self.factory.makeTeam()790 team = self.factory.makeTeam()
791 login_person(team.teamowner)791 login_person(team.teamowner)
@@ -793,7 +793,7 @@
793 [participation] = self.view.active_participations793 [participation] = self.view.active_participations
794 self.assertEqual('—', participation['subscribed'])794 self.assertEqual('—', participation['subscribed'])
795795
796 def test__asParticpation_unsubscribed_to_mailing_list(self):796 def test__asParticipation_unsubscribed_to_mailing_list(self):
797 # The default team role is 'Member'.797 # The default team role is 'Member'.
798 team = self.factory.makeTeam()798 team = self.factory.makeTeam()
799 self.factory.makeMailingList(team, team.teamowner)799 self.factory.makeMailingList(team, team.teamowner)
@@ -802,7 +802,7 @@
802 [participation] = self.view.active_participations802 [participation] = self.view.active_participations
803 self.assertEqual('Not subscribed', participation['subscribed'])803 self.assertEqual('Not subscribed', participation['subscribed'])
804804
805 def test__asParticpation_subscribed_to_mailing_list(self):805 def test__asParticipation_subscribed_to_mailing_list(self):
806 # The default team role is 'Member'.806 # The default team role is 'Member'.
807 team = self.factory.makeTeam()807 team = self.factory.makeTeam()
808 mailing_list = self.factory.makeMailingList(team, team.teamowner)808 mailing_list = self.factory.makeMailingList(team, team.teamowner)
@@ -869,6 +869,33 @@
869 self.assertEqual('A', participations[1]['via'])869 self.assertEqual('A', participations[1]['via'])
870 self.assertEqual('B, A', participations[2]['via'])870 self.assertEqual('B, A', participations[2]['via'])
871871
872 def test_active_participations_public_via_private_team(self):
873 # Private teams that grant a user access to public teams are listed,
874 # but redacted if the requesting user does not have access to them.
875 owner = self.factory.makePerson()
876 direct_team = self.factory.makeTeam(
877 owner=owner, name='a', visibility=PersonVisibility.PRIVATE)
878 indirect_team = self.factory.makeTeam(owner=owner, name='b')
879 login_person(owner)
880 direct_team.addMember(self.user, owner)
881 indirect_team.addMember(direct_team, owner)
882 # The private team is included in active_participations and via.
883 login_person(self.user)
884 view = create_view(
885 self.user, name='+participation', principal=self.user)
886 participations = view.active_participations
887 self.assertEqual(2, len(participations))
888 self.assertIsNone(participations[0]['via'])
889 self.assertEqual('A', participations[1]['via'])
890 # The private team is not included in active_participations and via.
891 observer = self.factory.makePerson()
892 login_person(observer)
893 view = create_view(
894 self.user, name='+participation', principal=observer)
895 participations = view.active_participations
896 self.assertEqual(1, len(participations))
897 self.assertEqual('[private team]', participations[0]['via'])
898
872 def test_has_participations_false(self):899 def test_has_participations_false(self):
873 participations = self.view.active_participations900 participations = self.view.active_participations
874 self.assertEqual(0, len(participations))901 self.assertEqual(0, len(participations))