comparison rhodecode/model/user_group.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl

Imported some of the GPLv3'd changes from RhodeCode v2.2.5. This imports changes between changesets 21af6c4eab3d and 6177597791c2 in RhodeCode's original repository, including only changes to Python files and HTML. RhodeCode clearly licensed its changes to these files under GPLv3 in their /LICENSE file, which states the following: The Python code and integrated HTML are licensed under the GPLv3 license. (See: https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE or http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE for an online copy of that LICENSE file) Conservancy reviewed these changes and confirmed that they can be licensed as a whole to the Kallithea project under GPLv3-only. While some of the contents committed herein are clearly licensed GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the statement above from RhodeCode indicates that they intend GPLv3-only as their license, per GPLv3ยง14 and other relevant sections of GPLv3.
author Bradley M. Kuhn <bkuhn@sfconservancy.org>
date Wed, 02 Jul 2014 19:03:13 -0400
parents
children 7e5f8c12a3fc
comparison
equal deleted inserted replaced
4115:8b7294a804a0 4116:ffd45b185016
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
15 rhodecode.model.users_group
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
18 user group model for RhodeCode
19
20 :created_on: Oct 1, 2011
21 :author: nvinot, marcink
22 """
23
24
25 import logging
26 import traceback
27
28 from rhodecode.model import BaseModel
29 from rhodecode.model.db import UserGroupMember, UserGroup,\
30 UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
31 UserGroupUserGroupToPerm
32 from rhodecode.lib.exceptions import UserGroupsAssignedException,\
33 RepoGroupAssignmentError
34
35 log = logging.getLogger(__name__)
36
37
38 class UserGroupModel(BaseModel):
39
40 cls = UserGroup
41
42 def _get_user_group(self, user_group):
43 return self._get_instance(UserGroup, user_group,
44 callback=UserGroup.get_by_group_name)
45
46 def _create_default_perms(self, user_group):
47 # create default permission
48 default_perm = 'usergroup.read'
49 def_user = User.get_default_user()
50 for p in def_user.user_perms:
51 if p.permission.permission_name.startswith('usergroup.'):
52 default_perm = p.permission.permission_name
53 break
54
55 user_group_to_perm = UserUserGroupToPerm()
56 user_group_to_perm.permission = Permission.get_by_key(default_perm)
57
58 user_group_to_perm.user_group = user_group
59 user_group_to_perm.user_id = def_user.user_id
60 return user_group_to_perm
61
62 def _update_permissions(self, user_group, perms_new=None,
63 perms_updates=None):
64 from rhodecode.lib.auth import HasUserGroupPermissionAny
65 if not perms_new:
66 perms_new = []
67 if not perms_updates:
68 perms_updates = []
69
70 # update permissions
71 for member, perm, member_type in perms_updates:
72 if member_type == 'user':
73 # this updates existing one
74 self.grant_user_permission(
75 user_group=user_group, user=member, perm=perm
76 )
77 else:
78 #check if we have permissions to alter this usergroup
79 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
80 'usergroup.admin')(member):
81 self.grant_user_group_permission(
82 target_user_group=user_group, user_group=member, perm=perm
83 )
84 # set new permissions
85 for member, perm, member_type in perms_new:
86 if member_type == 'user':
87 self.grant_user_permission(
88 user_group=user_group, user=member, perm=perm
89 )
90 else:
91 #check if we have permissions to alter this usergroup
92 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
93 'usergroup.admin')(member):
94 self.grant_user_group_permission(
95 target_user_group=user_group, user_group=member, perm=perm
96 )
97
98 def get(self, user_group_id, cache=False):
99 return UserGroup.get(user_group_id)
100
101 def get_group(self, user_group):
102 return self._get_user_group(user_group)
103
104 def get_by_name(self, name, cache=False, case_insensitive=False):
105 return UserGroup.get_by_group_name(name, cache, case_insensitive)
106
107 def create(self, name, description, owner, active=True, group_data=None):
108 try:
109 new_user_group = UserGroup()
110 new_user_group.user = self._get_user(owner)
111 new_user_group.users_group_name = name
112 new_user_group.user_group_description = description
113 new_user_group.users_group_active = active
114 if group_data:
115 new_user_group.group_data = group_data
116 self.sa.add(new_user_group)
117 perm_obj = self._create_default_perms(new_user_group)
118 self.sa.add(perm_obj)
119
120 self.grant_user_permission(user_group=new_user_group,
121 user=owner, perm='usergroup.admin')
122
123 return new_user_group
124 except Exception:
125 log.error(traceback.format_exc())
126 raise
127
128 def update(self, user_group, form_data):
129
130 try:
131 user_group = self._get_user_group(user_group)
132
133 for k, v in form_data.items():
134 if k == 'users_group_members':
135 user_group.members = []
136 self.sa.flush()
137 members_list = []
138 if v:
139 v = [v] if isinstance(v, basestring) else v
140 for u_id in set(v):
141 member = UserGroupMember(user_group.users_group_id, u_id)
142 members_list.append(member)
143 setattr(user_group, 'members', members_list)
144 setattr(user_group, k, v)
145
146 self.sa.add(user_group)
147 except Exception:
148 log.error(traceback.format_exc())
149 raise
150
151 def delete(self, user_group, force=False):
152 """
153 Deletes repository group, unless force flag is used
154 raises exception if there are members in that group, else deletes
155 group and users
156
157 :param user_group:
158 :param force:
159 """
160 user_group = self._get_user_group(user_group)
161 try:
162 # check if this group is not assigned to repo
163 assigned_groups = UserGroupRepoToPerm.query()\
164 .filter(UserGroupRepoToPerm.users_group == user_group).all()
165
166 if assigned_groups and not force:
167 raise UserGroupsAssignedException(
168 'RepoGroup assigned to %s' % assigned_groups)
169 self.sa.delete(user_group)
170 except Exception:
171 log.error(traceback.format_exc())
172 raise
173
174 def add_user_to_group(self, user_group, user):
175 user_group = self._get_user_group(user_group)
176 user = self._get_user(user)
177
178 for m in user_group.members:
179 u = m.user
180 if u.user_id == user.user_id:
181 # user already in the group, skip
182 return True
183
184 try:
185 user_group_member = UserGroupMember()
186 user_group_member.user = user
187 user_group_member.users_group = user_group
188
189 user_group.members.append(user_group_member)
190 user.group_member.append(user_group_member)
191
192 self.sa.add(user_group_member)
193 return user_group_member
194 except Exception:
195 log.error(traceback.format_exc())
196 raise
197
198 def remove_user_from_group(self, user_group, user):
199 user_group = self._get_user_group(user_group)
200 user = self._get_user(user)
201
202 user_group_member = None
203 for m in user_group.members:
204 if m.user.user_id == user.user_id:
205 # Found this user's membership row
206 user_group_member = m
207 break
208
209 if user_group_member:
210 try:
211 self.sa.delete(user_group_member)
212 return True
213 except Exception:
214 log.error(traceback.format_exc())
215 raise
216 else:
217 # User isn't in that group
218 return False
219
220 def has_perm(self, user_group, perm):
221 user_group = self._get_user_group(user_group)
222 perm = self._get_perm(perm)
223
224 return UserGroupToPerm.query()\
225 .filter(UserGroupToPerm.users_group == user_group)\
226 .filter(UserGroupToPerm.permission == perm).scalar() is not None
227
228 def grant_perm(self, user_group, perm):
229 user_group = self._get_user_group(user_group)
230 perm = self._get_perm(perm)
231
232 # if this permission is already granted skip it
233 _perm = UserGroupToPerm.query()\
234 .filter(UserGroupToPerm.users_group == user_group)\
235 .filter(UserGroupToPerm.permission == perm)\
236 .scalar()
237 if _perm:
238 return
239
240 new = UserGroupToPerm()
241 new.users_group = user_group
242 new.permission = perm
243 self.sa.add(new)
244 return new
245
246 def revokehas_permrevoke_permgrant_perm_perm(self, user_group, perm):
247 user_group = self._get_user_group(user_group)
248 perm = self._get_perm(perm)
249
250 obj = UserGroupToPerm.query()\
251 .filter(UserGroupToPerm.users_group == user_group)\
252 .filter(UserGroupToPerm.permission == perm).scalar()
253 if obj:
254 self.sa.delete(obj)
255
256 def grant_user_permission(self, user_group, user, perm):
257 """
258 Grant permission for user on given user group, or update
259 existing one if found
260
261 :param user_group: Instance of UserGroup, users_group_id,
262 or users_group_name
263 :param user: Instance of User, user_id or username
264 :param perm: Instance of Permission, or permission_name
265 """
266
267 user_group = self._get_user_group(user_group)
268 user = self._get_user(user)
269 permission = self._get_perm(perm)
270
271 # check if we have that permission already
272 obj = self.sa.query(UserUserGroupToPerm)\
273 .filter(UserUserGroupToPerm.user == user)\
274 .filter(UserUserGroupToPerm.user_group == user_group)\
275 .scalar()
276 if obj is None:
277 # create new !
278 obj = UserUserGroupToPerm()
279 obj.user_group = user_group
280 obj.user = user
281 obj.permission = permission
282 self.sa.add(obj)
283 log.debug('Granted perm %s to %s on %s' % (perm, user, user_group))
284 return obj
285
286 def revoke_user_permission(self, user_group, user):
287 """
288 Revoke permission for user on given repository group
289
290 :param user_group: Instance of RepoGroup, repositories_group_id,
291 or repositories_group name
292 :param user: Instance of User, user_id or username
293 """
294
295 user_group = self._get_user_group(user_group)
296 user = self._get_user(user)
297
298 obj = self.sa.query(UserUserGroupToPerm)\
299 .filter(UserUserGroupToPerm.user == user)\
300 .filter(UserUserGroupToPerm.user_group == user_group)\
301 .scalar()
302 if obj:
303 self.sa.delete(obj)
304 log.debug('Revoked perm on %s on %s' % (user_group, user))
305
306 def grant_user_group_permission(self, target_user_group, user_group, perm):
307 """
308 Grant user group permission for given target_user_group
309
310 :param target_user_group:
311 :param user_group:
312 :param perm:
313 """
314 target_user_group = self._get_user_group(target_user_group)
315 user_group = self._get_user_group(user_group)
316 permission = self._get_perm(perm)
317 # forbid assigning same user group to itself
318 if target_user_group == user_group:
319 raise RepoGroupAssignmentError('target repo:%s cannot be '
320 'assigned to itself' % target_user_group)
321
322 # check if we have that permission already
323 obj = self.sa.query(UserGroupUserGroupToPerm)\
324 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
325 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
326 .scalar()
327 if obj is None:
328 # create new !
329 obj = UserGroupUserGroupToPerm()
330 obj.user_group = user_group
331 obj.target_user_group = target_user_group
332 obj.permission = permission
333 self.sa.add(obj)
334 log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group))
335 return obj
336
337 def revoke_user_group_permission(self, target_user_group, user_group):
338 """
339 Revoke user group permission for given target_user_group
340
341 :param target_user_group:
342 :param user_group:
343 """
344 target_user_group = self._get_user_group(target_user_group)
345 user_group = self._get_user_group(user_group)
346
347 obj = self.sa.query(UserGroupUserGroupToPerm)\
348 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
349 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
350 .scalar()
351 if obj:
352 self.sa.delete(obj)
353 log.debug('Revoked perm on %s on %s' % (target_user_group, user_group))
354
355 def enforce_groups(self, user, groups, extern_type=None):
356 user = self._get_user(user)
357 log.debug('Enforcing groups %s on user %s' % (user, groups))
358 current_groups = user.group_member
359 # find the external created groups
360 externals = [x.users_group for x in current_groups
361 if 'extern_type' in x.users_group.group_data]
362
363 # calculate from what groups user should be removed
364 # externals that are not in groups
365 for gr in externals:
366 if gr.users_group_name not in groups:
367 log.debug('Removing user %s from user group %s' % (user, gr))
368 self.remove_user_from_group(gr, user)
369
370 # now we calculate in which groups user should be == groups params
371 owner = User.get_first_admin().username
372 for gr in set(groups):
373 existing_group = UserGroup.get_by_group_name(gr)
374 if not existing_group:
375 desc = 'Automatically created from plugin:%s' % extern_type
376 # we use first admin account to set the owner of the group
377 existing_group = UserGroupModel().create(gr, desc, owner,
378 group_data={'extern_type': extern_type})
379
380 # we can only add users to special groups created via plugins
381 managed = 'extern_type' in existing_group.group_data
382 if managed:
383 log.debug('Adding user %s to user group %s' % (user, gr))
384 UserGroupModel().add_user_to_group(existing_group, user)
385 else:
386 log.debug('Skipping addition to group %s since it is '
387 'not managed by auth plugins' % gr)