Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: appengine/monorail/sitewide/groupdetail.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/monorail/sitewide/groupcreate.py ('k') | appengine/monorail/sitewide/grouplist.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is govered by a BSD-style
3 # license that can be found in the LICENSE file or at
4 # https://developers.google.com/open-source/licenses/bsd
5
6 """A class to display a user group, including a paginated list of members."""
7
8 import logging
9 import time
10
11 from third_party import ezt
12
13 from framework import framework_helpers
14 from framework import framework_views
15 from framework import paginate
16 from framework import permissions
17 from framework import servlet
18 from project import project_helpers
19 from proto import usergroup_pb2
20 from services import usergroup_svc
21 from sitewide import group_helpers
22 from sitewide import sitewide_views
23
24 MEMBERS_PER_PAGE = 50
25
26
27 class GroupDetail(servlet.Servlet):
28 """The group detail page presents information about one user group."""
29
30 _PAGE_TEMPLATE = 'sitewide/group-detail-page.ezt'
31
32 def AssertBasePermission(self, mr):
33 """Assert that the user has the permissions needed to view this page."""
34 super(GroupDetail, self).AssertBasePermission(mr)
35
36 group_id = mr.viewed_user_auth.user_id
37 group_settings = self.services.usergroup.GetGroupSettings(
38 mr.cnxn, group_id)
39
40 member_ids, owner_ids = self.services.usergroup.LookupAllMembers(
41 mr.cnxn, [group_id])
42 (owned_project_ids, membered_project_ids,
43 contrib_project_ids) = self.services.project.GetUserRolesInAllProjects(
44 mr.cnxn, mr.auth.effective_ids)
45 project_ids = owned_project_ids.union(
46 membered_project_ids).union(contrib_project_ids)
47 if not permissions.CanViewGroup(
48 mr.perms, mr.auth.effective_ids, group_settings, member_ids[group_id],
49 owner_ids[group_id], project_ids):
50 raise permissions.PermissionException(
51 'User is not allowed to view a user group')
52
53 def GatherPageData(self, mr):
54 """Build up a dictionary of data values to use when rendering the page."""
55 group_id = mr.viewed_user_auth.user_id
56 group_settings = self.services.usergroup.GetGroupSettings(
57 mr.cnxn, group_id)
58
59 member_ids_dict, owner_ids_dict = (
60 self.services.usergroup.LookupVisibleMembers(
61 mr.cnxn, [group_id], mr.perms, mr.auth.effective_ids,
62 self.services))
63 member_ids = member_ids_dict[group_id]
64 owner_ids = owner_ids_dict[group_id]
65 member_pbs_dict = self.services.user.GetUsersByIDs(
66 mr.cnxn, member_ids)
67 owner_pbs_dict = self.services.user.GetUsersByIDs(
68 mr.cnxn, owner_ids)
69 member_dict = {}
70 for user_id, user_pb in member_pbs_dict.iteritems():
71 member_view = group_helpers.GroupMemberView(
72 user_id, user_pb.email, user_pb.obscure_email, group_id, 'member')
73 member_dict[user_id] = member_view
74 owner_dict = {}
75 for user_id, user_pb in owner_pbs_dict.iteritems():
76 member_view = group_helpers.GroupMemberView(
77 user_id, user_pb.email, user_pb.obscure_email, group_id, 'owner')
78 owner_dict[user_id] = member_view
79
80 member_user_views = []
81 member_user_views.extend(
82 sorted(owner_dict.values(), key=lambda u: u.email))
83 member_user_views.extend(
84 sorted(member_dict.values(), key=lambda u: u.email))
85
86 group_view = sitewide_views.GroupView(
87 mr.viewed_user_auth.email, len(member_ids), group_settings,
88 mr.viewed_user_auth.user_id)
89 pagination = paginate.ArtifactPagination(
90 mr, member_user_views, MEMBERS_PER_PAGE, group_view.detail_url)
91
92 is_imported_group = bool(group_settings.ext_group_type)
93
94 offer_membership_editing = permissions.CanEditGroup(
95 mr.perms, mr.auth.effective_ids, owner_ids) and not is_imported_group
96
97 return {
98 'admin_tab_mode': self.ADMIN_TAB_META,
99 'offer_membership_editing': ezt.boolean(offer_membership_editing),
100 'initial_add_members': '',
101 'initially_expand_form': ezt.boolean(False),
102 'groupid': group_id,
103 'groupname': mr.viewed_username,
104 'settings': group_settings,
105 'pagination': pagination,
106 }
107
108 def ProcessFormData(self, mr, post_data):
109 """Process the posted form."""
110 _, owner_ids_dict = self.services.usergroup.LookupMembers(
111 mr.cnxn, [mr.viewed_user_auth.user_id])
112 owner_ids = owner_ids_dict[mr.viewed_user_auth.user_id]
113 permit_edit = permissions.CanEditGroup(
114 mr.perms, mr.auth.effective_ids, owner_ids)
115 if not permit_edit:
116 raise permissions.PermissionException(
117 'User is not permitted to edit group membership')
118
119 group_settings = self.services.usergroup.GetGroupSettings(
120 mr.cnxn, mr.viewed_user_auth.user_id)
121 if bool(group_settings.ext_group_type):
122 raise permissions.PermissionException(
123 'Imported groups are read-only')
124
125 if 'addbtn' in post_data:
126 return self.ProcessAddMembers(mr, post_data)
127 elif 'removebtn' in post_data:
128 return self.ProcessRemoveMembers(mr, post_data)
129
130 def ProcessAddMembers(self, mr, post_data):
131 """Process the user's request to add members.
132
133 Args:
134 mr: common information parsed from the HTTP request.
135 post_data: dictionary of form data.
136
137 Returns:
138 String URL to redirect the user to after processing.
139 """
140 # 1. Gather data from the request.
141 group_id = mr.viewed_user_auth.user_id
142 add_members_str = post_data.get('addmembers')
143 new_member_ids = project_helpers.ParseUsernames(
144 mr.cnxn, self.services.user, add_members_str)
145 role = post_data['role']
146
147 # 2. Call services layer to save changes.
148 if not mr.errors.AnyErrors():
149 try:
150 self.services.usergroup.UpdateMembers(
151 mr.cnxn, group_id, new_member_ids, role)
152 except usergroup_svc.CircularGroupException:
153 mr.errors.addmembers = (
154 'The members are already ancestors of current group.')
155
156 # 3. Determine the next page in the UI flow.
157 if mr.errors.AnyErrors():
158 self.PleaseCorrect(
159 mr, initial_add_members=add_members_str,
160 initially_expand_form=ezt.boolean(True))
161 else:
162 return framework_helpers.FormatAbsoluteURL(
163 mr, '/g/%s/' % mr.viewed_username, include_project=False,
164 saved=1, ts=int(time.time()))
165
166 def ProcessRemoveMembers(self, mr, post_data):
167 """Process the user's request to remove members.
168
169 Args:
170 mr: common information parsed from the HTTP request.
171 post_data: dictionary of form data.
172
173 Returns:
174 String URL to redirect the user to after processing.
175 """
176 # 1. Gather data from the request.
177 remove_strs = post_data.getall('remove')
178 logging.info('remove_strs = %r', remove_strs)
179
180 if not remove_strs:
181 mr.errors.remove = 'No users specified'
182
183 # 2. Call services layer to save changes.
184 if not mr.errors.AnyErrors():
185 remove_ids = set(
186 self.services.user.LookupUserIDs(mr.cnxn, remove_strs).values())
187 self.services.usergroup.RemoveMembers(
188 mr.cnxn, mr.viewed_user_auth.user_id, remove_ids)
189
190 # 3. Determine the next page in the UI flow.
191 if mr.errors.AnyErrors():
192 self.PleaseCorrect(mr)
193 else:
194 return framework_helpers.FormatAbsoluteURL(
195 mr, '/g/%s/' % mr.viewed_username, include_project=False,
196 saved=1, ts=int(time.time()))
OLDNEW
« no previous file with comments | « appengine/monorail/sitewide/groupcreate.py ('k') | appengine/monorail/sitewide/grouplist.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698