##// END OF EJS Templates
user-groups: fix potential problem with group sync of external plugins....
marcink -
r2193:20e24a44 stable
parent child Browse files
Show More
@@ -1,623 +1,629 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 """
22 """
23 user group model for RhodeCode
23 user group model for RhodeCode
24 """
24 """
25
25
26
26
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from rhodecode.lib.utils2 import safe_str, safe_unicode
30 from rhodecode.lib.utils2 import safe_str, safe_unicode
31 from rhodecode.lib.exceptions import (
31 from rhodecode.lib.exceptions import (
32 UserGroupAssignedException, RepoGroupAssignmentError)
32 UserGroupAssignedException, RepoGroupAssignmentError)
33 from rhodecode.lib.utils2 import (
33 from rhodecode.lib.utils2 import (
34 get_current_rhodecode_user, action_logger_generic)
34 get_current_rhodecode_user, action_logger_generic)
35 from rhodecode.model import BaseModel
35 from rhodecode.model import BaseModel
36 from rhodecode.model.scm import UserGroupList
36 from rhodecode.model.scm import UserGroupList
37 from rhodecode.model.db import (
37 from rhodecode.model.db import (
38 true, func, User, UserGroupMember, UserGroup,
38 true, func, User, UserGroupMember, UserGroup,
39 UserGroupRepoToPerm, Permission, UserGroupToPerm, UserUserGroupToPerm,
39 UserGroupRepoToPerm, Permission, UserGroupToPerm, UserUserGroupToPerm,
40 UserGroupUserGroupToPerm, UserGroupRepoGroupToPerm)
40 UserGroupUserGroupToPerm, UserGroupRepoGroupToPerm)
41
41
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 class UserGroupModel(BaseModel):
46 class UserGroupModel(BaseModel):
47
47
48 cls = UserGroup
48 cls = UserGroup
49
49
50 def _get_user_group(self, user_group):
50 def _get_user_group(self, user_group):
51 return self._get_instance(UserGroup, user_group,
51 return self._get_instance(UserGroup, user_group,
52 callback=UserGroup.get_by_group_name)
52 callback=UserGroup.get_by_group_name)
53
53
54 def _create_default_perms(self, user_group):
54 def _create_default_perms(self, user_group):
55 # create default permission
55 # create default permission
56 default_perm = 'usergroup.read'
56 default_perm = 'usergroup.read'
57 def_user = User.get_default_user()
57 def_user = User.get_default_user()
58 for p in def_user.user_perms:
58 for p in def_user.user_perms:
59 if p.permission.permission_name.startswith('usergroup.'):
59 if p.permission.permission_name.startswith('usergroup.'):
60 default_perm = p.permission.permission_name
60 default_perm = p.permission.permission_name
61 break
61 break
62
62
63 user_group_to_perm = UserUserGroupToPerm()
63 user_group_to_perm = UserUserGroupToPerm()
64 user_group_to_perm.permission = Permission.get_by_key(default_perm)
64 user_group_to_perm.permission = Permission.get_by_key(default_perm)
65
65
66 user_group_to_perm.user_group = user_group
66 user_group_to_perm.user_group = user_group
67 user_group_to_perm.user_id = def_user.user_id
67 user_group_to_perm.user_id = def_user.user_id
68 return user_group_to_perm
68 return user_group_to_perm
69
69
70 def update_permissions(self, user_group, perm_additions=None, perm_updates=None,
70 def update_permissions(self, user_group, perm_additions=None, perm_updates=None,
71 perm_deletions=None, check_perms=True, cur_user=None):
71 perm_deletions=None, check_perms=True, cur_user=None):
72 from rhodecode.lib.auth import HasUserGroupPermissionAny
72 from rhodecode.lib.auth import HasUserGroupPermissionAny
73 if not perm_additions:
73 if not perm_additions:
74 perm_additions = []
74 perm_additions = []
75 if not perm_updates:
75 if not perm_updates:
76 perm_updates = []
76 perm_updates = []
77 if not perm_deletions:
77 if not perm_deletions:
78 perm_deletions = []
78 perm_deletions = []
79
79
80 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
80 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
81
81
82 # update permissions
82 # update permissions
83 for member_id, perm, member_type in perm_updates:
83 for member_id, perm, member_type in perm_updates:
84 member_id = int(member_id)
84 member_id = int(member_id)
85 if member_type == 'user':
85 if member_type == 'user':
86 # this updates existing one
86 # this updates existing one
87 self.grant_user_permission(
87 self.grant_user_permission(
88 user_group=user_group, user=member_id, perm=perm
88 user_group=user_group, user=member_id, perm=perm
89 )
89 )
90 else:
90 else:
91 # check if we have permissions to alter this usergroup
91 # check if we have permissions to alter this usergroup
92 member_name = UserGroup.get(member_id).users_group_name
92 member_name = UserGroup.get(member_id).users_group_name
93 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
93 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
94 self.grant_user_group_permission(
94 self.grant_user_group_permission(
95 target_user_group=user_group, user_group=member_id, perm=perm
95 target_user_group=user_group, user_group=member_id, perm=perm
96 )
96 )
97
97
98 # set new permissions
98 # set new permissions
99 for member_id, perm, member_type in perm_additions:
99 for member_id, perm, member_type in perm_additions:
100 member_id = int(member_id)
100 member_id = int(member_id)
101 if member_type == 'user':
101 if member_type == 'user':
102 self.grant_user_permission(
102 self.grant_user_permission(
103 user_group=user_group, user=member_id, perm=perm
103 user_group=user_group, user=member_id, perm=perm
104 )
104 )
105 else:
105 else:
106 # check if we have permissions to alter this usergroup
106 # check if we have permissions to alter this usergroup
107 member_name = UserGroup.get(member_id).users_group_name
107 member_name = UserGroup.get(member_id).users_group_name
108 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
108 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
109 self.grant_user_group_permission(
109 self.grant_user_group_permission(
110 target_user_group=user_group, user_group=member_id, perm=perm
110 target_user_group=user_group, user_group=member_id, perm=perm
111 )
111 )
112
112
113 # delete permissions
113 # delete permissions
114 for member_id, perm, member_type in perm_deletions:
114 for member_id, perm, member_type in perm_deletions:
115 member_id = int(member_id)
115 member_id = int(member_id)
116 if member_type == 'user':
116 if member_type == 'user':
117 self.revoke_user_permission(user_group=user_group, user=member_id)
117 self.revoke_user_permission(user_group=user_group, user=member_id)
118 else:
118 else:
119 # check if we have permissions to alter this usergroup
119 # check if we have permissions to alter this usergroup
120 member_name = UserGroup.get(member_id).users_group_name
120 member_name = UserGroup.get(member_id).users_group_name
121 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
121 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
122 self.revoke_user_group_permission(
122 self.revoke_user_group_permission(
123 target_user_group=user_group, user_group=member_id
123 target_user_group=user_group, user_group=member_id
124 )
124 )
125
125
126 def get(self, user_group_id, cache=False):
126 def get(self, user_group_id, cache=False):
127 return UserGroup.get(user_group_id)
127 return UserGroup.get(user_group_id)
128
128
129 def get_group(self, user_group):
129 def get_group(self, user_group):
130 return self._get_user_group(user_group)
130 return self._get_user_group(user_group)
131
131
132 def get_by_name(self, name, cache=False, case_insensitive=False):
132 def get_by_name(self, name, cache=False, case_insensitive=False):
133 return UserGroup.get_by_group_name(name, cache, case_insensitive)
133 return UserGroup.get_by_group_name(name, cache, case_insensitive)
134
134
135 def create(self, name, description, owner, active=True, group_data=None):
135 def create(self, name, description, owner, active=True, group_data=None):
136 try:
136 try:
137 new_user_group = UserGroup()
137 new_user_group = UserGroup()
138 new_user_group.user = self._get_user(owner)
138 new_user_group.user = self._get_user(owner)
139 new_user_group.users_group_name = name
139 new_user_group.users_group_name = name
140 new_user_group.user_group_description = description
140 new_user_group.user_group_description = description
141 new_user_group.users_group_active = active
141 new_user_group.users_group_active = active
142 if group_data:
142 if group_data:
143 new_user_group.group_data = group_data
143 new_user_group.group_data = group_data
144 self.sa.add(new_user_group)
144 self.sa.add(new_user_group)
145 perm_obj = self._create_default_perms(new_user_group)
145 perm_obj = self._create_default_perms(new_user_group)
146 self.sa.add(perm_obj)
146 self.sa.add(perm_obj)
147
147
148 self.grant_user_permission(user_group=new_user_group,
148 self.grant_user_permission(user_group=new_user_group,
149 user=owner, perm='usergroup.admin')
149 user=owner, perm='usergroup.admin')
150
150
151 return new_user_group
151 return new_user_group
152 except Exception:
152 except Exception:
153 log.error(traceback.format_exc())
153 log.error(traceback.format_exc())
154 raise
154 raise
155
155
156 def _get_memberships_for_user_ids(self, user_group, user_id_list):
156 def _get_memberships_for_user_ids(self, user_group, user_id_list):
157 members = []
157 members = []
158 for user_id in user_id_list:
158 for user_id in user_id_list:
159 member = self._get_membership(user_group.users_group_id, user_id)
159 member = self._get_membership(user_group.users_group_id, user_id)
160 members.append(member)
160 members.append(member)
161 return members
161 return members
162
162
163 def _get_added_and_removed_user_ids(self, user_group, user_id_list):
163 def _get_added_and_removed_user_ids(self, user_group, user_id_list):
164 current_members = user_group.members or []
164 current_members = user_group.members or []
165 current_members_ids = [m.user.user_id for m in current_members]
165 current_members_ids = [m.user.user_id for m in current_members]
166
166
167 added_members = [
167 added_members = [
168 user_id for user_id in user_id_list
168 user_id for user_id in user_id_list
169 if user_id not in current_members_ids]
169 if user_id not in current_members_ids]
170 if user_id_list == []:
170 if user_id_list == []:
171 # all members were deleted
171 # all members were deleted
172 deleted_members = current_members_ids
172 deleted_members = current_members_ids
173 else:
173 else:
174 deleted_members = [
174 deleted_members = [
175 user_id for user_id in current_members_ids
175 user_id for user_id in current_members_ids
176 if user_id not in user_id_list]
176 if user_id not in user_id_list]
177
177
178 return added_members, deleted_members
178 return added_members, deleted_members
179
179
180 def _set_users_as_members(self, user_group, user_ids):
180 def _set_users_as_members(self, user_group, user_ids):
181 user_group.members = []
181 user_group.members = []
182 self.sa.flush()
182 self.sa.flush()
183 members = self._get_memberships_for_user_ids(
183 members = self._get_memberships_for_user_ids(
184 user_group, user_ids)
184 user_group, user_ids)
185 user_group.members = members
185 user_group.members = members
186 self.sa.add(user_group)
186 self.sa.add(user_group)
187
187
188 def _update_members_from_user_ids(self, user_group, user_ids):
188 def _update_members_from_user_ids(self, user_group, user_ids):
189 added, removed = self._get_added_and_removed_user_ids(
189 added, removed = self._get_added_and_removed_user_ids(
190 user_group, user_ids)
190 user_group, user_ids)
191 self._set_users_as_members(user_group, user_ids)
191 self._set_users_as_members(user_group, user_ids)
192 self._log_user_changes('added to', user_group, added)
192 self._log_user_changes('added to', user_group, added)
193 self._log_user_changes('removed from', user_group, removed)
193 self._log_user_changes('removed from', user_group, removed)
194 return added, removed
194 return added, removed
195
195
196 def _clean_members_data(self, members_data):
196 def _clean_members_data(self, members_data):
197 if not members_data:
197 if not members_data:
198 members_data = []
198 members_data = []
199
199
200 members = []
200 members = []
201 for user in members_data:
201 for user in members_data:
202 uid = int(user['member_user_id'])
202 uid = int(user['member_user_id'])
203 if uid not in members and user['type'] in ['new', 'existing']:
203 if uid not in members and user['type'] in ['new', 'existing']:
204 members.append(uid)
204 members.append(uid)
205 return members
205 return members
206
206
207 def update(self, user_group, form_data):
207 def update(self, user_group, form_data):
208 user_group = self._get_user_group(user_group)
208 user_group = self._get_user_group(user_group)
209 if 'users_group_name' in form_data:
209 if 'users_group_name' in form_data:
210 user_group.users_group_name = form_data['users_group_name']
210 user_group.users_group_name = form_data['users_group_name']
211 if 'users_group_active' in form_data:
211 if 'users_group_active' in form_data:
212 user_group.users_group_active = form_data['users_group_active']
212 user_group.users_group_active = form_data['users_group_active']
213 if 'user_group_description' in form_data:
213 if 'user_group_description' in form_data:
214 user_group.user_group_description = form_data[
214 user_group.user_group_description = form_data[
215 'user_group_description']
215 'user_group_description']
216
216
217 # handle owner change
217 # handle owner change
218 if 'user' in form_data:
218 if 'user' in form_data:
219 owner = form_data['user']
219 owner = form_data['user']
220 if isinstance(owner, basestring):
220 if isinstance(owner, basestring):
221 owner = User.get_by_username(form_data['user'])
221 owner = User.get_by_username(form_data['user'])
222
222
223 if not isinstance(owner, User):
223 if not isinstance(owner, User):
224 raise ValueError(
224 raise ValueError(
225 'invalid owner for user group: %s' % form_data['user'])
225 'invalid owner for user group: %s' % form_data['user'])
226
226
227 user_group.user = owner
227 user_group.user = owner
228
228
229 added_user_ids = []
229 added_user_ids = []
230 removed_user_ids = []
230 removed_user_ids = []
231 if 'users_group_members' in form_data:
231 if 'users_group_members' in form_data:
232 members_id_list = self._clean_members_data(
232 members_id_list = self._clean_members_data(
233 form_data['users_group_members'])
233 form_data['users_group_members'])
234 added_user_ids, removed_user_ids = \
234 added_user_ids, removed_user_ids = \
235 self._update_members_from_user_ids(user_group, members_id_list)
235 self._update_members_from_user_ids(user_group, members_id_list)
236
236
237 self.sa.add(user_group)
237 self.sa.add(user_group)
238 return user_group, added_user_ids, removed_user_ids
238 return user_group, added_user_ids, removed_user_ids
239
239
240 def delete(self, user_group, force=False):
240 def delete(self, user_group, force=False):
241 """
241 """
242 Deletes repository group, unless force flag is used
242 Deletes repository group, unless force flag is used
243 raises exception if there are members in that group, else deletes
243 raises exception if there are members in that group, else deletes
244 group and users
244 group and users
245
245
246 :param user_group:
246 :param user_group:
247 :param force:
247 :param force:
248 """
248 """
249 user_group = self._get_user_group(user_group)
249 user_group = self._get_user_group(user_group)
250 try:
250 try:
251 # check if this group is not assigned to repo
251 # check if this group is not assigned to repo
252 assigned_to_repo = [x.repository for x in UserGroupRepoToPerm.query()\
252 assigned_to_repo = [x.repository for x in UserGroupRepoToPerm.query()\
253 .filter(UserGroupRepoToPerm.users_group == user_group).all()]
253 .filter(UserGroupRepoToPerm.users_group == user_group).all()]
254 # check if this group is not assigned to repo
254 # check if this group is not assigned to repo
255 assigned_to_repo_group = [x.group for x in UserGroupRepoGroupToPerm.query()\
255 assigned_to_repo_group = [x.group for x in UserGroupRepoGroupToPerm.query()\
256 .filter(UserGroupRepoGroupToPerm.users_group == user_group).all()]
256 .filter(UserGroupRepoGroupToPerm.users_group == user_group).all()]
257
257
258 if (assigned_to_repo or assigned_to_repo_group) and not force:
258 if (assigned_to_repo or assigned_to_repo_group) and not force:
259 assigned = ','.join(map(safe_str,
259 assigned = ','.join(map(safe_str,
260 assigned_to_repo+assigned_to_repo_group))
260 assigned_to_repo+assigned_to_repo_group))
261
261
262 raise UserGroupAssignedException(
262 raise UserGroupAssignedException(
263 'UserGroup assigned to %s' % (assigned,))
263 'UserGroup assigned to %s' % (assigned,))
264 self.sa.delete(user_group)
264 self.sa.delete(user_group)
265 except Exception:
265 except Exception:
266 log.error(traceback.format_exc())
266 log.error(traceback.format_exc())
267 raise
267 raise
268
268
269 def _log_user_changes(self, action, user_group, user_or_users):
269 def _log_user_changes(self, action, user_group, user_or_users):
270 users = user_or_users
270 users = user_or_users
271 if not isinstance(users, (list, tuple)):
271 if not isinstance(users, (list, tuple)):
272 users = [users]
272 users = [users]
273 rhodecode_user = get_current_rhodecode_user()
273 rhodecode_user = get_current_rhodecode_user()
274 ipaddr = getattr(rhodecode_user, 'ip_addr', '')
274 ipaddr = getattr(rhodecode_user, 'ip_addr', '')
275 group_name = user_group.users_group_name
275 group_name = user_group.users_group_name
276
276
277 for user_or_user_id in users:
277 for user_or_user_id in users:
278 user = self._get_user(user_or_user_id)
278 user = self._get_user(user_or_user_id)
279 log_text = 'User {user} {action} {group}'.format(
279 log_text = 'User {user} {action} {group}'.format(
280 action=action, user=user.username, group=group_name)
280 action=action, user=user.username, group=group_name)
281 log.info('Logging action: {0} by {1} ip:{2}'.format(
281 log.info('Logging action: {0} by {1} ip:{2}'.format(
282 log_text, rhodecode_user, ipaddr))
282 log_text, rhodecode_user, ipaddr))
283
283
284 def _find_user_in_group(self, user, user_group):
284 def _find_user_in_group(self, user, user_group):
285 user_group_member = None
285 user_group_member = None
286 for m in user_group.members:
286 for m in user_group.members:
287 if m.user_id == user.user_id:
287 if m.user_id == user.user_id:
288 # Found this user's membership row
288 # Found this user's membership row
289 user_group_member = m
289 user_group_member = m
290 break
290 break
291
291
292 return user_group_member
292 return user_group_member
293
293
294 def _get_membership(self, user_group_id, user_id):
294 def _get_membership(self, user_group_id, user_id):
295 user_group_member = UserGroupMember(user_group_id, user_id)
295 user_group_member = UserGroupMember(user_group_id, user_id)
296 return user_group_member
296 return user_group_member
297
297
298 def add_user_to_group(self, user_group, user):
298 def add_user_to_group(self, user_group, user):
299 user_group = self._get_user_group(user_group)
299 user_group = self._get_user_group(user_group)
300 user = self._get_user(user)
300 user = self._get_user(user)
301 user_member = self._find_user_in_group(user, user_group)
301 user_member = self._find_user_in_group(user, user_group)
302 if user_member:
302 if user_member:
303 # user already in the group, skip
303 # user already in the group, skip
304 return True
304 return True
305
305
306 member = self._get_membership(
306 member = self._get_membership(
307 user_group.users_group_id, user.user_id)
307 user_group.users_group_id, user.user_id)
308 user_group.members.append(member)
308 user_group.members.append(member)
309
309
310 try:
310 try:
311 self.sa.add(member)
311 self.sa.add(member)
312 except Exception:
312 except Exception:
313 # what could go wrong here?
313 # what could go wrong here?
314 log.error(traceback.format_exc())
314 log.error(traceback.format_exc())
315 raise
315 raise
316
316
317 self._log_user_changes('added to', user_group, user)
317 self._log_user_changes('added to', user_group, user)
318 return member
318 return member
319
319
320 def remove_user_from_group(self, user_group, user):
320 def remove_user_from_group(self, user_group, user):
321 user_group = self._get_user_group(user_group)
321 user_group = self._get_user_group(user_group)
322 user = self._get_user(user)
322 user = self._get_user(user)
323 user_group_member = self._find_user_in_group(user, user_group)
323 user_group_member = self._find_user_in_group(user, user_group)
324
324
325 if not user_group_member:
325 if not user_group_member:
326 # User isn't in that group
326 # User isn't in that group
327 return False
327 return False
328
328
329 try:
329 try:
330 self.sa.delete(user_group_member)
330 self.sa.delete(user_group_member)
331 except Exception:
331 except Exception:
332 log.error(traceback.format_exc())
332 log.error(traceback.format_exc())
333 raise
333 raise
334
334
335 self._log_user_changes('removed from', user_group, user)
335 self._log_user_changes('removed from', user_group, user)
336 return True
336 return True
337
337
338 def has_perm(self, user_group, perm):
338 def has_perm(self, user_group, perm):
339 user_group = self._get_user_group(user_group)
339 user_group = self._get_user_group(user_group)
340 perm = self._get_perm(perm)
340 perm = self._get_perm(perm)
341
341
342 return UserGroupToPerm.query()\
342 return UserGroupToPerm.query()\
343 .filter(UserGroupToPerm.users_group == user_group)\
343 .filter(UserGroupToPerm.users_group == user_group)\
344 .filter(UserGroupToPerm.permission == perm).scalar() is not None
344 .filter(UserGroupToPerm.permission == perm).scalar() is not None
345
345
346 def grant_perm(self, user_group, perm):
346 def grant_perm(self, user_group, perm):
347 user_group = self._get_user_group(user_group)
347 user_group = self._get_user_group(user_group)
348 perm = self._get_perm(perm)
348 perm = self._get_perm(perm)
349
349
350 # if this permission is already granted skip it
350 # if this permission is already granted skip it
351 _perm = UserGroupToPerm.query()\
351 _perm = UserGroupToPerm.query()\
352 .filter(UserGroupToPerm.users_group == user_group)\
352 .filter(UserGroupToPerm.users_group == user_group)\
353 .filter(UserGroupToPerm.permission == perm)\
353 .filter(UserGroupToPerm.permission == perm)\
354 .scalar()
354 .scalar()
355 if _perm:
355 if _perm:
356 return
356 return
357
357
358 new = UserGroupToPerm()
358 new = UserGroupToPerm()
359 new.users_group = user_group
359 new.users_group = user_group
360 new.permission = perm
360 new.permission = perm
361 self.sa.add(new)
361 self.sa.add(new)
362 return new
362 return new
363
363
364 def revoke_perm(self, user_group, perm):
364 def revoke_perm(self, user_group, perm):
365 user_group = self._get_user_group(user_group)
365 user_group = self._get_user_group(user_group)
366 perm = self._get_perm(perm)
366 perm = self._get_perm(perm)
367
367
368 obj = UserGroupToPerm.query()\
368 obj = UserGroupToPerm.query()\
369 .filter(UserGroupToPerm.users_group == user_group)\
369 .filter(UserGroupToPerm.users_group == user_group)\
370 .filter(UserGroupToPerm.permission == perm).scalar()
370 .filter(UserGroupToPerm.permission == perm).scalar()
371 if obj:
371 if obj:
372 self.sa.delete(obj)
372 self.sa.delete(obj)
373
373
374 def grant_user_permission(self, user_group, user, perm):
374 def grant_user_permission(self, user_group, user, perm):
375 """
375 """
376 Grant permission for user on given user group, or update
376 Grant permission for user on given user group, or update
377 existing one if found
377 existing one if found
378
378
379 :param user_group: Instance of UserGroup, users_group_id,
379 :param user_group: Instance of UserGroup, users_group_id,
380 or users_group_name
380 or users_group_name
381 :param user: Instance of User, user_id or username
381 :param user: Instance of User, user_id or username
382 :param perm: Instance of Permission, or permission_name
382 :param perm: Instance of Permission, or permission_name
383 """
383 """
384
384
385 user_group = self._get_user_group(user_group)
385 user_group = self._get_user_group(user_group)
386 user = self._get_user(user)
386 user = self._get_user(user)
387 permission = self._get_perm(perm)
387 permission = self._get_perm(perm)
388
388
389 # check if we have that permission already
389 # check if we have that permission already
390 obj = self.sa.query(UserUserGroupToPerm)\
390 obj = self.sa.query(UserUserGroupToPerm)\
391 .filter(UserUserGroupToPerm.user == user)\
391 .filter(UserUserGroupToPerm.user == user)\
392 .filter(UserUserGroupToPerm.user_group == user_group)\
392 .filter(UserUserGroupToPerm.user_group == user_group)\
393 .scalar()
393 .scalar()
394 if obj is None:
394 if obj is None:
395 # create new !
395 # create new !
396 obj = UserUserGroupToPerm()
396 obj = UserUserGroupToPerm()
397 obj.user_group = user_group
397 obj.user_group = user_group
398 obj.user = user
398 obj.user = user
399 obj.permission = permission
399 obj.permission = permission
400 self.sa.add(obj)
400 self.sa.add(obj)
401 log.debug('Granted perm %s to %s on %s', perm, user, user_group)
401 log.debug('Granted perm %s to %s on %s', perm, user, user_group)
402 action_logger_generic(
402 action_logger_generic(
403 'granted permission: {} to user: {} on usergroup: {}'.format(
403 'granted permission: {} to user: {} on usergroup: {}'.format(
404 perm, user, user_group), namespace='security.usergroup')
404 perm, user, user_group), namespace='security.usergroup')
405
405
406 return obj
406 return obj
407
407
408 def revoke_user_permission(self, user_group, user):
408 def revoke_user_permission(self, user_group, user):
409 """
409 """
410 Revoke permission for user on given user group
410 Revoke permission for user on given user group
411
411
412 :param user_group: Instance of UserGroup, users_group_id,
412 :param user_group: Instance of UserGroup, users_group_id,
413 or users_group name
413 or users_group name
414 :param user: Instance of User, user_id or username
414 :param user: Instance of User, user_id or username
415 """
415 """
416
416
417 user_group = self._get_user_group(user_group)
417 user_group = self._get_user_group(user_group)
418 user = self._get_user(user)
418 user = self._get_user(user)
419
419
420 obj = self.sa.query(UserUserGroupToPerm)\
420 obj = self.sa.query(UserUserGroupToPerm)\
421 .filter(UserUserGroupToPerm.user == user)\
421 .filter(UserUserGroupToPerm.user == user)\
422 .filter(UserUserGroupToPerm.user_group == user_group)\
422 .filter(UserUserGroupToPerm.user_group == user_group)\
423 .scalar()
423 .scalar()
424 if obj:
424 if obj:
425 self.sa.delete(obj)
425 self.sa.delete(obj)
426 log.debug('Revoked perm on %s on %s', user_group, user)
426 log.debug('Revoked perm on %s on %s', user_group, user)
427 action_logger_generic(
427 action_logger_generic(
428 'revoked permission from user: {} on usergroup: {}'.format(
428 'revoked permission from user: {} on usergroup: {}'.format(
429 user, user_group), namespace='security.usergroup')
429 user, user_group), namespace='security.usergroup')
430
430
431 def grant_user_group_permission(self, target_user_group, user_group, perm):
431 def grant_user_group_permission(self, target_user_group, user_group, perm):
432 """
432 """
433 Grant user group permission for given target_user_group
433 Grant user group permission for given target_user_group
434
434
435 :param target_user_group:
435 :param target_user_group:
436 :param user_group:
436 :param user_group:
437 :param perm:
437 :param perm:
438 """
438 """
439 target_user_group = self._get_user_group(target_user_group)
439 target_user_group = self._get_user_group(target_user_group)
440 user_group = self._get_user_group(user_group)
440 user_group = self._get_user_group(user_group)
441 permission = self._get_perm(perm)
441 permission = self._get_perm(perm)
442 # forbid assigning same user group to itself
442 # forbid assigning same user group to itself
443 if target_user_group == user_group:
443 if target_user_group == user_group:
444 raise RepoGroupAssignmentError('target repo:%s cannot be '
444 raise RepoGroupAssignmentError('target repo:%s cannot be '
445 'assigned to itself' % target_user_group)
445 'assigned to itself' % target_user_group)
446
446
447 # check if we have that permission already
447 # check if we have that permission already
448 obj = self.sa.query(UserGroupUserGroupToPerm)\
448 obj = self.sa.query(UserGroupUserGroupToPerm)\
449 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
449 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
450 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
450 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
451 .scalar()
451 .scalar()
452 if obj is None:
452 if obj is None:
453 # create new !
453 # create new !
454 obj = UserGroupUserGroupToPerm()
454 obj = UserGroupUserGroupToPerm()
455 obj.user_group = user_group
455 obj.user_group = user_group
456 obj.target_user_group = target_user_group
456 obj.target_user_group = target_user_group
457 obj.permission = permission
457 obj.permission = permission
458 self.sa.add(obj)
458 self.sa.add(obj)
459 log.debug(
459 log.debug(
460 'Granted perm %s to %s on %s', perm, target_user_group, user_group)
460 'Granted perm %s to %s on %s', perm, target_user_group, user_group)
461 action_logger_generic(
461 action_logger_generic(
462 'granted permission: {} to usergroup: {} on usergroup: {}'.format(
462 'granted permission: {} to usergroup: {} on usergroup: {}'.format(
463 perm, user_group, target_user_group),
463 perm, user_group, target_user_group),
464 namespace='security.usergroup')
464 namespace='security.usergroup')
465
465
466 return obj
466 return obj
467
467
468 def revoke_user_group_permission(self, target_user_group, user_group):
468 def revoke_user_group_permission(self, target_user_group, user_group):
469 """
469 """
470 Revoke user group permission for given target_user_group
470 Revoke user group permission for given target_user_group
471
471
472 :param target_user_group:
472 :param target_user_group:
473 :param user_group:
473 :param user_group:
474 """
474 """
475 target_user_group = self._get_user_group(target_user_group)
475 target_user_group = self._get_user_group(target_user_group)
476 user_group = self._get_user_group(user_group)
476 user_group = self._get_user_group(user_group)
477
477
478 obj = self.sa.query(UserGroupUserGroupToPerm)\
478 obj = self.sa.query(UserGroupUserGroupToPerm)\
479 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
479 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
480 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
480 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
481 .scalar()
481 .scalar()
482 if obj:
482 if obj:
483 self.sa.delete(obj)
483 self.sa.delete(obj)
484 log.debug(
484 log.debug(
485 'Revoked perm on %s on %s', target_user_group, user_group)
485 'Revoked perm on %s on %s', target_user_group, user_group)
486 action_logger_generic(
486 action_logger_generic(
487 'revoked permission from usergroup: {} on usergroup: {}'.format(
487 'revoked permission from usergroup: {} on usergroup: {}'.format(
488 user_group, target_user_group),
488 user_group, target_user_group),
489 namespace='security.repogroup')
489 namespace='security.repogroup')
490
490
491 def enforce_groups(self, user, groups, extern_type=None):
491 def enforce_groups(self, user, groups, extern_type=None):
492 user = self._get_user(user)
492 user = self._get_user(user)
493 log.debug('Enforcing groups %s on user %s', groups, user)
494 current_groups = user.group_member
493 current_groups = user.group_member
495 # find the external created groups
496 externals = [x.users_group for x in current_groups
497 if 'extern_type' in x.users_group.group_data]
498
494
495 # find the external created groups, i.e automatically created
496 log.debug('Enforcing user group set `%s` on user %s', groups, user)
499 # calculate from what groups user should be removed
497 # calculate from what groups user should be removed
500 # externals that are not in groups
498 # external_groups that are not in groups
501 for gr in externals:
499 for gr in [x.users_group for x in current_groups]:
500 managed = gr.group_data.get('extern_type')
501 if managed:
502 if gr.users_group_name not in groups:
502 if gr.users_group_name not in groups:
503 log.debug('Removing user %s from user group %s', user, gr)
503 log.debug('Removing user %s from user group %s. '
504 'Group sync managed by: %s', user, gr, managed)
504 self.remove_user_from_group(gr, user)
505 self.remove_user_from_group(gr, user)
506 else:
507 log.debug('Skipping removal from group %s since it is '
508 'not set to be automatically synchronized' % gr)
505
509
506 # now we calculate in which groups user should be == groups params
510 # now we calculate in which groups user should be == groups params
507 owner = User.get_first_super_admin().username
511 owner = User.get_first_super_admin().username
508 for gr in set(groups):
512 for gr in set(groups):
509 existing_group = UserGroup.get_by_group_name(gr)
513 existing_group = UserGroup.get_by_group_name(gr)
510 if not existing_group:
514 if not existing_group:
511 desc = 'Automatically created from plugin:%s' % extern_type
515 desc = 'Automatically created from plugin:%s' % extern_type
512 # we use first admin account to set the owner of the group
516 # we use first admin account to set the owner of the group
513 existing_group = UserGroupModel().create(
517 existing_group = UserGroupModel().create(
514 gr, desc, owner, group_data={'extern_type': extern_type})
518 gr, desc, owner, group_data={'extern_type': extern_type})
515
519
516 # we can only add users to special groups created via plugins
520 # we can only add users to groups which have set sync flag via
517 managed = 'extern_type' in existing_group.group_data
521 # extern_type attribute.
522 # This is either set and created via plugins, or manually
523 managed = existing_group.group_data.get('extern_type')
518 if managed:
524 if managed:
519 log.debug('Adding user %s to user group %s', user, gr)
525 log.debug('Adding user %s to user group %s', user, gr)
520 UserGroupModel().add_user_to_group(existing_group, user)
526 UserGroupModel().add_user_to_group(existing_group, user)
521 else:
527 else:
522 log.debug('Skipping addition to group %s since it is '
528 log.debug('Skipping addition to group %s since it is '
523 'not set to be automatically synchronized' % gr)
529 'not set to be automatically synchronized' % gr)
524
530
525 def change_groups(self, user, groups):
531 def change_groups(self, user, groups):
526 """
532 """
527 This method changes user group assignment
533 This method changes user group assignment
528 :param user: User
534 :param user: User
529 :param groups: array of UserGroupModel
535 :param groups: array of UserGroupModel
530 :return:
536 :return:
531 """
537 """
532 user = self._get_user(user)
538 user = self._get_user(user)
533 log.debug('Changing user(%s) assignment to groups(%s)', user, groups)
539 log.debug('Changing user(%s) assignment to groups(%s)', user, groups)
534 current_groups = user.group_member
540 current_groups = user.group_member
535 current_groups = [x.users_group for x in current_groups]
541 current_groups = [x.users_group for x in current_groups]
536
542
537 # calculate from what groups user should be removed/add
543 # calculate from what groups user should be removed/add
538 groups = set(groups)
544 groups = set(groups)
539 current_groups = set(current_groups)
545 current_groups = set(current_groups)
540
546
541 groups_to_remove = current_groups - groups
547 groups_to_remove = current_groups - groups
542 groups_to_add = groups - current_groups
548 groups_to_add = groups - current_groups
543
549
544 for gr in groups_to_remove:
550 for gr in groups_to_remove:
545 log.debug('Removing user %s from user group %s', user.username, gr.users_group_name)
551 log.debug('Removing user %s from user group %s', user.username, gr.users_group_name)
546 self.remove_user_from_group(gr.users_group_name, user.username)
552 self.remove_user_from_group(gr.users_group_name, user.username)
547 for gr in groups_to_add:
553 for gr in groups_to_add:
548 log.debug('Adding user %s to user group %s', user.username, gr.users_group_name)
554 log.debug('Adding user %s to user group %s', user.username, gr.users_group_name)
549 UserGroupModel().add_user_to_group(gr.users_group_name, user.username)
555 UserGroupModel().add_user_to_group(gr.users_group_name, user.username)
550
556
551 def _serialize_user_group(self, user_group):
557 def _serialize_user_group(self, user_group):
552 import rhodecode.lib.helpers as h
558 import rhodecode.lib.helpers as h
553 return {
559 return {
554 'id': user_group.users_group_id,
560 'id': user_group.users_group_id,
555 # TODO: marcink figure out a way to generate the url for the
561 # TODO: marcink figure out a way to generate the url for the
556 # icon
562 # icon
557 'icon_link': '',
563 'icon_link': '',
558 'value_display': 'Group: %s (%d members)' % (
564 'value_display': 'Group: %s (%d members)' % (
559 user_group.users_group_name, len(user_group.members),),
565 user_group.users_group_name, len(user_group.members),),
560 'value': user_group.users_group_name,
566 'value': user_group.users_group_name,
561 'description': user_group.user_group_description,
567 'description': user_group.user_group_description,
562 'owner': user_group.user.username,
568 'owner': user_group.user.username,
563
569
564 'owner_icon': h.gravatar_url(user_group.user.email, 30),
570 'owner_icon': h.gravatar_url(user_group.user.email, 30),
565 'value_display_owner': h.person(user_group.user.email),
571 'value_display_owner': h.person(user_group.user.email),
566
572
567 'value_type': 'user_group',
573 'value_type': 'user_group',
568 'active': user_group.users_group_active,
574 'active': user_group.users_group_active,
569 }
575 }
570
576
571 def get_user_groups(self, name_contains=None, limit=20, only_active=True,
577 def get_user_groups(self, name_contains=None, limit=20, only_active=True,
572 expand_groups=False):
578 expand_groups=False):
573 query = self.sa.query(UserGroup)
579 query = self.sa.query(UserGroup)
574 if only_active:
580 if only_active:
575 query = query.filter(UserGroup.users_group_active == true())
581 query = query.filter(UserGroup.users_group_active == true())
576
582
577 if name_contains:
583 if name_contains:
578 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
584 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
579 query = query.filter(
585 query = query.filter(
580 UserGroup.users_group_name.ilike(ilike_expression))\
586 UserGroup.users_group_name.ilike(ilike_expression))\
581 .order_by(func.length(UserGroup.users_group_name))\
587 .order_by(func.length(UserGroup.users_group_name))\
582 .order_by(UserGroup.users_group_name)
588 .order_by(UserGroup.users_group_name)
583
589
584 query = query.limit(limit)
590 query = query.limit(limit)
585 user_groups = query.all()
591 user_groups = query.all()
586 perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
592 perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
587 user_groups = UserGroupList(user_groups, perm_set=perm_set)
593 user_groups = UserGroupList(user_groups, perm_set=perm_set)
588
594
589 # store same serialize method to extract data from User
595 # store same serialize method to extract data from User
590 from rhodecode.model.user import UserModel
596 from rhodecode.model.user import UserModel
591 serialize_user = UserModel()._serialize_user
597 serialize_user = UserModel()._serialize_user
592
598
593 _groups = []
599 _groups = []
594 for group in user_groups:
600 for group in user_groups:
595 entry = self._serialize_user_group(group)
601 entry = self._serialize_user_group(group)
596 if expand_groups:
602 if expand_groups:
597 expanded_members = []
603 expanded_members = []
598 for member in group.members:
604 for member in group.members:
599 expanded_members.append(serialize_user(member.user))
605 expanded_members.append(serialize_user(member.user))
600 entry['members'] = expanded_members
606 entry['members'] = expanded_members
601 _groups.append(entry)
607 _groups.append(entry)
602 return _groups
608 return _groups
603
609
604 @staticmethod
610 @staticmethod
605 def get_user_groups_as_dict(user_group):
611 def get_user_groups_as_dict(user_group):
606 import rhodecode.lib.helpers as h
612 import rhodecode.lib.helpers as h
607
613
608 data = {
614 data = {
609 'users_group_id': user_group.users_group_id,
615 'users_group_id': user_group.users_group_id,
610 'group_name': user_group.users_group_name,
616 'group_name': user_group.users_group_name,
611 'group_description': user_group.user_group_description,
617 'group_description': user_group.user_group_description,
612 'active': user_group.users_group_active,
618 'active': user_group.users_group_active,
613 "owner": user_group.user.username,
619 "owner": user_group.user.username,
614 'owner_icon': h.gravatar_url(user_group.user.email, 30),
620 'owner_icon': h.gravatar_url(user_group.user.email, 30),
615 "owner_data": {
621 "owner_data": {
616 'owner': user_group.user.username,
622 'owner': user_group.user.username,
617 'owner_icon': h.gravatar_url(user_group.user.email, 30)}
623 'owner_icon': h.gravatar_url(user_group.user.email, 30)}
618 }
624 }
619 return data
625 return data
620
626
621
627
622
628
623
629
General Comments 0
You need to be logged in to leave comments. Login now