Merge lp:~jcsackett/launchpad/edit-icons-permissions into lp:launchpad

Proposed by j.c.sackett
Status: Merged
Approved by: j.c.sackett
Approved revision: no longer in the source branch.
Merged at revision: 16382
Proposed branch: lp:~jcsackett/launchpad/edit-icons-permissions
Merge into: lp:launchpad
Diff against target: 121 lines (+26/-12)
5 files modified
lib/lp/registry/browser/pillar.py (+9/-7)
lib/lp/registry/browser/tests/test_pillar_sharing.py (+1/-1)
lib/lp/registry/javascript/sharing/granteetable.js (+6/-3)
lib/lp/registry/javascript/sharing/pillarsharingview.js (+2/-1)
lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js (+8/-0)
To merge this branch: bzr merge lp:~jcsackett/launchpad/edit-icons-permissions
Reviewer Review Type Date Requested Status
Richard Harding (community) Approve
Review via email: mp+140556@code.launchpad.net

Commit message

Ensures widgets are not clickable on +sharing without the user having `launchpad.Edit`.

Description of the change

Summary
=======
The edit icons show up on +sharing for people who only have
`launchpad.Driver`; that's sufficient to view sharing data but not to edit, so
errors occur when you try to actually use the widget.

We shouldn't make the widgets editable for those without `launchpad.Edit`.

Preimp
======
Spoke with Deryck and Curtis.

Implementation
==============
On the sharing view, we add `has_edit_permission` to the JSON cache. This is
used in the JS to ensure that the widgets' clickable_content property is only
set if the permission exists.

Tests
=====
bin/test -vvct sharing --layer=YUI

QA
==
Go check a page you have Edit on; you should be able to use the widgets. Go to
one you only have driver on; you should see the data but be unable to alter it
and be given no indication you can do so.

LoC
===
Part of private projects.

Lint
====

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/registry/javascript/sharing/pillarsharingview.js
  lib/lp/registry/javascript/sharing/granteetable.js
  lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js
  lib/lp/registry/browser/pillar.py

To post a comment you must log in.
Revision history for this message
Richard Harding (rharding) wrote :

Looks ok. I'd rather the editable was an ATTR that had the valueFn set to pull the value out of the LP.cache, but then you could easily over ride it manually by setting that attribute for testing and manual changes. In this way the cache is static and untouched. That might not be possible here if these YUI objects aren't full base class extensions so just take it as a suggestion vs a please fix.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/pillar.py'
2--- lib/lp/registry/browser/pillar.py 2012-12-02 01:51:46 +0000
3+++ lib/lp/registry/browser/pillar.py 2012-12-20 15:05:55 +0000
4@@ -58,6 +58,7 @@
5 from lp.services.config import config
6 from lp.services.features import getFeatureFlag
7 from lp.services.propertycache import cachedproperty
8+from lp.services.webapp.authorization import check_permission
9 from lp.services.webapp.batching import (
10 BatchNavigator,
11 StormRangeFactory,
12@@ -190,10 +191,10 @@
13 def has_involvement(self):
14 """This `IPillar` uses Launchpad."""
15 return (self.official_malone
16- or service_uses_launchpad(self.answers_usage)
17- or service_uses_launchpad(self.blueprints_usage)
18- or service_uses_launchpad(self.translations_usage)
19- or service_uses_launchpad(self.codehosting_usage))
20+ or service_uses_launchpad(self.answers_usage)
21+ or service_uses_launchpad(self.blueprints_usage)
22+ or service_uses_launchpad(self.translations_usage)
23+ or service_uses_launchpad(self.codehosting_usage))
24
25 @property
26 def enabled_links(self):
27@@ -354,9 +355,10 @@
28 self.branch_sharing_policies)
29 cache.objects['specification_sharing_policies'] = (
30 self.specification_sharing_policies)
31-
32- view_names = set(reg.name for reg
33- in iter_view_registrations(self.__class__))
34+ cache.objects['has_edit_permission'] = check_permission(
35+ "launchpad.Edit", self.context)
36+ view_names = set(reg.name for reg in
37+ iter_view_registrations(self.__class__))
38 if len(view_names) != 1:
39 raise AssertionError("Ambiguous view name.")
40 cache.objects['view_name'] = view_names.pop()
41
42=== modified file 'lib/lp/registry/browser/tests/test_pillar_sharing.py'
43--- lib/lp/registry/browser/tests/test_pillar_sharing.py 2012-12-03 18:42:09 +0000
44+++ lib/lp/registry/browser/tests/test_pillar_sharing.py 2012-12-20 15:05:55 +0000
45@@ -321,7 +321,7 @@
46 view = create_view(self.pillar, name='+sharing')
47 with StormStatementRecorder() as recorder:
48 view.initialize()
49- self.assertThat(recorder, HasQueryCount(LessThan(10)))
50+ self.assertThat(recorder, HasQueryCount(LessThan(11)))
51
52 def test_view_invisible_information_types(self):
53 # Test the expected invisible information type data is in the
54
55=== modified file 'lib/lp/registry/javascript/sharing/granteetable.js'
56--- lib/lp/registry/javascript/sharing/granteetable.js 2012-09-12 18:40:35 +0000
57+++ lib/lp/registry/javascript/sharing/granteetable.js 2012-12-20 15:05:55 +0000
58@@ -218,7 +218,7 @@
59 '<li class="nowrap">',
60 '<span id="{{policy}}-permission-{{grantee_name}}">',
61 ' <span class="value"></span>',
62- ' <a class="editicon sprite edit action-icon"',
63+ ' <a class="editicon sprite edit action-icon hidden"',
64 ' href="#">Edit</a>',
65 '</span></li>',
66 '{{/information_types}}'].join(' ');
67@@ -249,9 +249,12 @@
68 var contentBox = permission_node.one(
69 '[id="' + policy + '-' + id + '"]');
70 var value_location = contentBox.one('.value');
71+ var editable = LP.cache.has_edit_permission;
72 var editicon = permission_node.one('a.editicon');
73-
74- var clickable_content = this.get('write_enabled');
75+ if (editable) {
76+ editicon.removeClass('hidden');
77+ }
78+ var clickable_content = (this.get('write_enabled') && editable);
79 var permission_edit = new Y.ChoiceSource({
80 clickable_content: clickable_content,
81 contentBox: contentBox,
82
83=== modified file 'lib/lp/registry/javascript/sharing/pillarsharingview.js'
84--- lib/lp/registry/javascript/sharing/pillarsharingview.js 2012-09-14 00:45:29 +0000
85+++ lib/lp/registry/javascript/sharing/pillarsharingview.js 2012-12-20 15:05:55 +0000
86@@ -156,7 +156,8 @@
87 }
88 choice_items.push.apply(
89 choice_items, this.getSharingPolicyInformation(artifact_type));
90- var editable = choice_items.length > 1;
91+ var edit_permission = LP.cache.has_edit_permission;
92+ var editable = (edit_permission && choice_items.length> 1);
93 var policy_edit = new Y.ChoiceSource({
94 flashEnabled: false,
95 clickable_content: editable,
96
97=== modified file 'lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js'
98--- lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2012-10-26 10:00:20 +0000
99+++ lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2012-12-20 15:05:55 +0000
100@@ -520,6 +520,7 @@
101 // When there is no sharing policy defined for a pillar, the default
102 // policy becomes the legacy policy.
103 test_sharing_policy_render_no_model_value: function() {
104+ window.LP.cache.has_edit_permission = true;
105 this.view = this._create_Widget();
106 this.view.render();
107 this._assert_sharing_policies_editable(true);
108@@ -533,6 +534,13 @@
109
110 // A pillar's sharing policy is correctly rendered.
111 test_sharing_policy_render: function() {
112+ // If there is no permission to edit the policy, it's not editable
113+ this.view = this._create_Widget();
114+ this.view.render();
115+ this._assert_sharing_policies_editable(false);
116+
117+ // If there is permission, it is editable.
118+ window.LP.cache.has_edit_permission = true;
119 this.view = this._create_Widget();
120 this.view.render();
121 this._assert_sharing_policies_editable(true);