Merge lp://qastaging/~sinzui/launchpad/closed-teams-0 into lp://qastaging/launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 12018
Proposed branch: lp://qastaging/~sinzui/launchpad/closed-teams-0
Merge into: lp://qastaging/launchpad
Diff against target: 762 lines (+264/-144)
15 files modified
lib/canonical/launchpad/vocabularies/dbobjects.py (+2/-0)
lib/canonical/launchpad/webapp/vocabulary.py (+5/-1)
lib/canonical/widgets/popup.py (+21/-13)
lib/lp/answers/vocabulary.py (+1/-2)
lib/lp/app/widgets/tests/test_popup.py (+43/-0)
lib/lp/blueprints/vocabularies/specificationdependency.py (+1/-0)
lib/lp/code/vocabularies/branch.py (+1/-0)
lib/lp/registry/browser/configure.zcml (+1/-1)
lib/lp/registry/browser/person.py (+7/-0)
lib/lp/registry/browser/tests/test_team.py (+14/-0)
lib/lp/registry/doc/vocabularies.txt (+1/-93)
lib/lp/registry/javascript/team.js (+2/-2)
lib/lp/registry/templates/team-portlet-membership.pt (+4/-2)
lib/lp/registry/tests/test_person_vocabularies.py (+99/-18)
lib/lp/registry/vocabularies.py (+62/-12)
To merge this branch: bzr merge lp://qastaging/~sinzui/launchpad/closed-teams-0
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+42500@code.qastaging.launchpad.net

Description of the change

Need a closed team and user vocabulary and picker

    Launchpad bug: https://bugs.launchpad.net/bugs/681035
    Pre-implementation: jcsackett, flacoste, gary_poster
    Test command: ./bin/test -vv \
        -t test_popup -t test_team -t test_person_vocabularies

There are several cases where Launchpad must prevent users from selecting a
team with an open subscription policy because it compromises security or
discloses information. The person picker and forms need a vocabulary that is
composed on closed teams (restricted and moderated), and users. The
picker/vocabulary is needed is needed in:

1. closed team owner role
2. closed team +addmember
3. moderated team +proposemember

------------------------------------------------------------------------------

RULES

    * Update the ValidTeamMemberVocabulary and ValidTeamOwnerVocabulary
      to exclude open teams when the context team is closed.
    * Update IHugeVocabulary, <intermediate classes>, VocabularyPickerWidget
      to use the vocabs step_title so that users understand what can and
      cannot be searched for. This issue was discovered in user testing.
    * Update all IHugeVocabularies to have a step_title
    * Update the add member ajax feature to also use the vocabulary's
      step_title

QA

    Using a moderated or restricted team to test.
    * Verify that open teams to not appear in the person picker to add
      a new member from the team's front page.
    * Verify that open teams to not appear in the person picker to add
      a new member from the teams +addmember page.
    * Verify that open teams to not appear in the person picker to change
      the team owner

LINT

    lib/canonical/launchpad/vocabularies/dbobjects.py
    lib/canonical/launchpad/webapp/vocabulary.py
    lib/canonical/widgets/popup.py
    lib/lp/answers/vocabulary.py
    lib/lp/app/widgets/
    lib/lp/app/widgets/__init__.py
    lib/lp/app/widgets/tests/
    lib/lp/app/widgets/tests/__init__.py
    lib/lp/app/widgets/tests/test_popup.py
    lib/lp/blueprints/vocabularies/specificationdependency.py
    lib/lp/code/vocabularies/branch.py
    lib/lp/registry/vocabularies.py
    lib/lp/registry/browser/configure.zcml
    lib/lp/registry/browser/person.py
    lib/lp/registry/browser/tests/test_team.py
    lib/lp/registry/javascript/team.js
    lib/lp/registry/templates/team-portlet-membership.pt
    lib/lp/registry/tests/test_person_vocabularies.py

IMPLEMENTATION

Updated ValidTeamMemberVocabulary and ValidTeamOwnerVocabulary to exclude
open teams when the context team is closed.
    lib/lp/registry/vocabularies.py
    lib/lp/registry/tests/test_person_vocabularies.py

Added step_title to the vocabulary. The value is the same that appears in
the UI now.
    lib/canonical/launchpad/webapp/vocabulary.py
    lib/canonical/launchpad/vocabularies/dbobjects.py
    lib/lp/answers/vocabulary.py
    lib/lp/blueprints/vocabularies/specificationdependency.py
    lib/lp/code/vocabularies/branch.py
    lib/lp/registry/vocabularies.py

Updated VocabularyPickerWidget to use the vocab's step_title. There are
no direct tests of this widget. Moving the whole module would make the diff
hard to read so I create a test where the module should be moved.
    lib/canonical/widgets/popup.py
    lib/lp/app/widgets/
    lib/lp/app/widgets/__init__.py
    lib/lp/app/widgets/tests/
    lib/lp/app/widgets/tests/__init__.py
    lib/lp/app/widgets/tests/test_popup.py

Updated the TeamIndexView and team membership portlet to use the step_title
from the vocabulary.
    lib/lp/registry/browser/configure.zcml
    lib/lp/registry/browser/person.py
    lib/lp/registry/browser/tests/test_team.py
    lib/lp/registry/javascript/team.js
    lib/lp/registry/templates/team-portlet-membership.pt

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Hi Curtis. Some incredibly minor comments, +1.

[1]

         js = js_template % simplejson.dumps(args)
         # If the YUI widget or javascript is not supported in the browser,
         # it will degrade to being this "Find..." link instead of the
@@ -154,8 +163,7 @@
             css = ''
         return ('<span class="%s">(<a id="%s" href="/people/">'
                 'Find&hellip;</a>)</span>'
- '\n<script>\n%s\n</script>'
- ) % (css, self.show_widget_id, js)
+ '\n<script>\n%s\n</script>') % (css, self.show_widget_id, js)

It's not part of your change, but using simplejson.dumps() can be
hazardous for embedding javascript into <script> tags. See:

  http://code.google.com/p/simplejson/issues/detail?id=66

Instead the following should be used:

  simplejson.dumps(args, cls=simplejson.encoder.JSONEncoderForHTML)

Or:

  simplejson.encoder.JSONEncoderForHTML().encode(obj)

[2]

+ Y.lp.registry.team.setup_add_member_handler(
+ '${step_title}');

The lack of escaping and all that jazz makes me a little uneasy, but
it's not user-supplied so I'm not too worried.

[3]

+ def test_open_team_cannot_be_a_member_or_a_closed_team(self):

s/or/of/

[4]

+ def test_open_team_can_be_a_member_or_an_open_team(self):

s/or/of/

[5]

+ return 'Search for a restricted or moderated team or person'

This could be parsed as:

  Search for a (restricted or moderated) (team or person)

Perhaps the following would be less ambiguous:

  Search for a restricted team, a moderated team, or a person

?

[6]

+ Person.subscriptionpolicy != TeamSubscriptionPolicy.OPEN)

Maybe it's worth taking a defensive approach here (to someone adding
another TeamSubscriptionPolicy member) instead:

  In(Person.subscriptionpolicy, (
      TeamSubscriptionPolicy.RESTRICTED,
      TeamSubscriptionPolicy.MODERATED))

The same clause appears twice.

review: Approve
Revision history for this message
Curtis Hovey (sinzui) wrote :

On Thu, 2010-12-02 at 17:12 +0000, Gavin Panella wrote:
> Review: Approve
> Hi Curtis. Some incredibly minor comments, +1.
>
>
> [1]
>
> js = js_template % simplejson.dumps(args)
> # If the YUI widget or javascript is not supported in the browser,
> # it will degrade to being this "Find..." link instead of the
> @@ -154,8 +163,7 @@
> css = ''
> return ('<span class="%s">(<a id="%s" href="/people/">'
> 'Find&hellip;</a>)</span>'
> - '\n<script>\n%s\n</script>'
> - ) % (css, self.show_widget_id, js)
> + '\n<script>\n%s\n</script>') % (css, self.show_widget_id, js)
>
> It's not part of your change, but using simplejson.dumps() can be
> hazardous for embedding javascript into <script> tags. See:
>
> http://code.google.com/p/simplejson/issues/detail?id=66
>
> Instead the following should be used:
>
> simplejson.dumps(args, cls=simplejson.encoder.JSONEncoderForHTML)
>
> Or:
>
> simplejson.encoder.JSONEncoderForHTML().encode(obj)

Interesting. We cannot do this right now because Lp is using 2.0.9. I
can see it my version of 2.1.1

> [2]
>
> + Y.lp.registry.team.setup_add_member_handler(
> + '${step_title}');
>
> The lack of escaping and all that jazz makes me a little uneasy, but
> it's not user-supplied so I'm not too worried.

This content is in a tal:content rule and is escaped. A single-quote
will break the script. I updated the method to escape quotes and added a
test.

> [3]
>
> + def test_open_team_cannot_be_a_member_or_a_closed_team(self):
>
> s/or/of/

fixed

> [4]
>
> + def test_open_team_can_be_a_member_or_an_open_team(self):
>
> s/or/of/

fixed

> [5]
>
> + return 'Search for a restricted or moderated team or person'
>
> This could be parsed as:
>
> Search for a (restricted or moderated) (team or person)
>
> Perhaps the following would be less ambiguous:
>
> Search for a restricted team, a moderated team, or a person

I accept your proposal.

> [6]
>
> + Person.subscriptionpolicy != TeamSubscriptionPolicy.OPEN)
>
> Maybe it's worth taking a defensive approach here (to someone adding
> another TeamSubscriptionPolicy member) instead:
>
> In(Person.subscriptionpolicy, (
> TeamSubscriptionPolicy.RESTRICTED,
> TeamSubscriptionPolicy.MODERATED))

We have not changed the policies in 5 years. I do not think we will be
adding other policies. If I am wrong, we may need to update the proposed
revision. Since this issue is about OPEN, I think the clause should
remain as is.

--
__Curtis C. Hovey_________
http://launchpad.net/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.