0001-manager-show-indirect-members-of-roles-real-roles-44.patch
src/authentic2/manager/role_views.py | ||
---|---|---|
23 | 23 |
from django.views.generic.detail import SingleObjectMixin |
24 | 24 |
from django.contrib import messages |
25 | 25 |
from django.contrib.contenttypes.models import ContentType |
26 |
from django.db.models.query import Q |
|
26 |
from django.db.models.query import Q, Prefetch
|
|
27 | 27 |
from django.db.models import Count |
28 | 28 |
from django.contrib.auth import get_user_model |
29 | 29 | |
... | ... | |
158 | 158 |
self._can_manage_members = value |
159 | 159 | |
160 | 160 |
def get_table_queryset(self): |
161 |
return self.object.all_members() |
|
161 |
children = self.object.children(include_self=False) |
|
162 |
via_prefetch = Prefetch('roles', queryset=children, to_attr='via') |
|
163 |
return self.object.all_members().prefetch_related(via_prefetch) |
|
162 | 164 | |
163 | 165 |
def form_valid(self, form): |
164 | 166 |
user = form.cleaned_data['user'] |
src/authentic2/manager/tables.py | ||
---|---|---|
68 | 68 |
class RoleMembersTable(UserTable): |
69 | 69 |
direct = tables.BooleanColumn(verbose_name=_('Direct member'), |
70 | 70 |
orderable=False) |
71 |
via = tables.TemplateColumn( |
|
72 |
'{% for role in record.via %}' |
|
73 |
'<a href="{% url "a2-manager-role-members" pk=role.pk %}">{{ role }}</a>{% if not forloop.last %}, {% endif %}' |
|
74 |
'{% endfor %}', |
|
75 |
verbose_name=_('Inherited from'), orderable=False) |
|
71 | 76 | |
72 | 77 |
class Meta(UserTable.Meta): |
73 | 78 |
pass |
tests/test_role_manager.py | ||
---|---|---|
13 | 13 |
# |
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 |
from django.utils.encoding import force_bytes |
|
17 |
from django.utils.encoding import force_text |
|
18 | 16 | |
19 |
from .utils import login |
|
17 |
from django.utils.encoding import force_bytes, force_text |
|
18 | ||
19 |
from authentic2.custom_user.models import User |
|
20 |
from authentic2.a2_rbac.models import Role |
|
21 | ||
22 |
from .utils import login, text_content |
|
20 | 23 | |
21 | 24 | |
22 | 25 |
def test_manager_role_export(app, admin, ou1, role_ou1, ou2, role_ou2): |
... | ... | |
88 | 91 |
response.form.set('name', 'Role1') |
89 | 92 |
response = response.form.submit('Save') |
90 | 93 |
assert response.pyquery('.error').text() == 'Name already used' |
94 | ||
95 | ||
96 |
def test_role_members_via(app, admin): |
|
97 |
user1 = User.objects.create(username='user1') |
|
98 |
user2 = User.objects.create(username='user2') |
|
99 |
role1 = Role.objects.create(name='role1') |
|
100 |
role2 = Role.objects.create(name='role2') |
|
101 | ||
102 |
role1.add_child(role2) |
|
103 |
user1.roles.add(role1) |
|
104 |
user2.roles.add(role2) |
|
105 | ||
106 |
response = login(app, admin, '/manage/roles/%s/' % role1.id) |
|
107 |
rows = list(zip([text_content(el) for el in response.pyquery('tr td.username')], |
|
108 |
[text_content(el) for el in response.pyquery('tr td.direct')], |
|
109 |
[text_content(el) for el in response.pyquery('tr td.via')])) |
|
110 |
assert rows == [ |
|
111 |
('user1', '✔', ''), |
|
112 |
('user2', '✘', 'role2'), |
|
113 |
] |
tests/utils.py | ||
---|---|---|
215 | 215 |
select2_field_id = response.pyquery('select')[0].attrib['data-field_id'] |
216 | 216 |
select2_response = app.get(select2_url, params={'field_id': select2_field_id, 'term': term}) |
217 | 217 |
return select2_response.json |
218 | ||
219 | ||
220 |
def text_content(node): |
|
221 |
'''Extract text content from node and all its children. Equivalent to |
|
222 |
xmlNodeGetContent from libxml.''' |
|
223 | ||
224 |
if node is None: |
|
225 |
return '' |
|
226 | ||
227 |
def helper(node): |
|
228 |
s = [] |
|
229 |
if node.text: |
|
230 |
s.append(node.text) |
|
231 |
for child in node: |
|
232 |
s.extend(helper(child)) |
|
233 |
if child.tail: |
|
234 |
s.append(child.tail) |
|
235 |
return s |
|
236 |
return u''.join(helper(node)) |
|
218 |
- |