##// END OF EJS Templates
user defined permission will update the global permissions, and overwrite default settings.
marcink -
r1267:d534aff5 beta
parent child Browse files
Show More
@@ -1,342 +1,353 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user
3 rhodecode.model.user
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 users model for RhodeCode
6 users model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from rhodecode.model import BaseModel
31 from rhodecode.model import BaseModel
32 from rhodecode.model.caching_query import FromCache
32 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
34 UserToPerm, UsersGroupToPerm, UsersGroupMember
34 UserToPerm, UsersGroupToPerm, UsersGroupMember
35 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
35 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
36
36
37 from sqlalchemy.exc import DatabaseError
37 from sqlalchemy.exc import DatabaseError
38 from rhodecode.lib import generate_api_key
38 from rhodecode.lib import generate_api_key
39
39
40 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
41
41
42
43 PERM_ = ''
44
42 PERM_WEIGHTS = {'repository.none':0,
45 PERM_WEIGHTS = {'repository.none':0,
43 'repository.read':1,
46 'repository.read':1,
44 'repository.write':3,
47 'repository.write':3,
45 'repository.admin':3}
48 'repository.admin':3}
46
49
50
47 class UserModel(BaseModel):
51 class UserModel(BaseModel):
48
52
49 def get(self, user_id, cache=False):
53 def get(self, user_id, cache=False):
50 user = self.sa.query(User)
54 user = self.sa.query(User)
51 if cache:
55 if cache:
52 user = user.options(FromCache("sql_cache_short",
56 user = user.options(FromCache("sql_cache_short",
53 "get_user_%s" % user_id))
57 "get_user_%s" % user_id))
54 return user.get(user_id)
58 return user.get(user_id)
55
59
56
60
57 def get_by_username(self, username, cache=False, case_insensitive=False):
61 def get_by_username(self, username, cache=False, case_insensitive=False):
58
62
59 if case_insensitive:
63 if case_insensitive:
60 user = self.sa.query(User).filter(User.username.ilike(username))
64 user = self.sa.query(User).filter(User.username.ilike(username))
61 else:
65 else:
62 user = self.sa.query(User)\
66 user = self.sa.query(User)\
63 .filter(User.username == username)
67 .filter(User.username == username)
64 if cache:
68 if cache:
65 user = user.options(FromCache("sql_cache_short",
69 user = user.options(FromCache("sql_cache_short",
66 "get_user_%s" % username))
70 "get_user_%s" % username))
67 return user.scalar()
71 return user.scalar()
68
72
69
73
70 def get_by_api_key(self, api_key, cache=False):
74 def get_by_api_key(self, api_key, cache=False):
71
75
72 user = self.sa.query(User)\
76 user = self.sa.query(User)\
73 .filter(User.api_key == api_key)
77 .filter(User.api_key == api_key)
74 if cache:
78 if cache:
75 user = user.options(FromCache("sql_cache_short",
79 user = user.options(FromCache("sql_cache_short",
76 "get_user_%s" % api_key))
80 "get_user_%s" % api_key))
77 return user.scalar()
81 return user.scalar()
78
82
79 def create(self, form_data):
83 def create(self, form_data):
80 try:
84 try:
81 new_user = User()
85 new_user = User()
82 for k, v in form_data.items():
86 for k, v in form_data.items():
83 setattr(new_user, k, v)
87 setattr(new_user, k, v)
84
88
85 new_user.api_key = generate_api_key(form_data['username'])
89 new_user.api_key = generate_api_key(form_data['username'])
86 self.sa.add(new_user)
90 self.sa.add(new_user)
87 self.sa.commit()
91 self.sa.commit()
88 except:
92 except:
89 log.error(traceback.format_exc())
93 log.error(traceback.format_exc())
90 self.sa.rollback()
94 self.sa.rollback()
91 raise
95 raise
92
96
93 def create_ldap(self, username, password, user_dn, attrs):
97 def create_ldap(self, username, password, user_dn, attrs):
94 """
98 """
95 Checks if user is in database, if not creates this user marked
99 Checks if user is in database, if not creates this user marked
96 as ldap user
100 as ldap user
97 :param username:
101 :param username:
98 :param password:
102 :param password:
99 :param user_dn:
103 :param user_dn:
100 :param attrs:
104 :param attrs:
101 """
105 """
102 from rhodecode.lib.auth import get_crypt_password
106 from rhodecode.lib.auth import get_crypt_password
103 log.debug('Checking for such ldap account in RhodeCode database')
107 log.debug('Checking for such ldap account in RhodeCode database')
104 if self.get_by_username(username, case_insensitive=True) is None:
108 if self.get_by_username(username, case_insensitive=True) is None:
105 try:
109 try:
106 new_user = User()
110 new_user = User()
107 new_user.username = username.lower() # add ldap account always lowercase
111 new_user.username = username.lower() # add ldap account always lowercase
108 new_user.password = get_crypt_password(password)
112 new_user.password = get_crypt_password(password)
109 new_user.api_key = generate_api_key(username)
113 new_user.api_key = generate_api_key(username)
110 new_user.email = attrs['email']
114 new_user.email = attrs['email']
111 new_user.active = True
115 new_user.active = True
112 new_user.ldap_dn = user_dn
116 new_user.ldap_dn = user_dn
113 new_user.name = attrs['name']
117 new_user.name = attrs['name']
114 new_user.lastname = attrs['lastname']
118 new_user.lastname = attrs['lastname']
115
119
116
120
117 self.sa.add(new_user)
121 self.sa.add(new_user)
118 self.sa.commit()
122 self.sa.commit()
119 return True
123 return True
120 except (DatabaseError,):
124 except (DatabaseError,):
121 log.error(traceback.format_exc())
125 log.error(traceback.format_exc())
122 self.sa.rollback()
126 self.sa.rollback()
123 raise
127 raise
124 log.debug('this %s user exists skipping creation of ldap account',
128 log.debug('this %s user exists skipping creation of ldap account',
125 username)
129 username)
126 return False
130 return False
127
131
128 def create_registration(self, form_data):
132 def create_registration(self, form_data):
129 from rhodecode.lib.celerylib import tasks, run_task
133 from rhodecode.lib.celerylib import tasks, run_task
130 try:
134 try:
131 new_user = User()
135 new_user = User()
132 for k, v in form_data.items():
136 for k, v in form_data.items():
133 if k != 'admin':
137 if k != 'admin':
134 setattr(new_user, k, v)
138 setattr(new_user, k, v)
135
139
136 self.sa.add(new_user)
140 self.sa.add(new_user)
137 self.sa.commit()
141 self.sa.commit()
138 body = ('New user registration\n'
142 body = ('New user registration\n'
139 'username: %s\n'
143 'username: %s\n'
140 'email: %s\n')
144 'email: %s\n')
141 body = body % (form_data['username'], form_data['email'])
145 body = body % (form_data['username'], form_data['email'])
142
146
143 run_task(tasks.send_email, None,
147 run_task(tasks.send_email, None,
144 _('[RhodeCode] New User registration'),
148 _('[RhodeCode] New User registration'),
145 body)
149 body)
146 except:
150 except:
147 log.error(traceback.format_exc())
151 log.error(traceback.format_exc())
148 self.sa.rollback()
152 self.sa.rollback()
149 raise
153 raise
150
154
151 def update(self, user_id, form_data):
155 def update(self, user_id, form_data):
152 try:
156 try:
153 user = self.get(user_id, cache=False)
157 user = self.get(user_id, cache=False)
154 if user.username == 'default':
158 if user.username == 'default':
155 raise DefaultUserException(
159 raise DefaultUserException(
156 _("You can't Edit this user since it's"
160 _("You can't Edit this user since it's"
157 " crucial for entire application"))
161 " crucial for entire application"))
158
162
159 for k, v in form_data.items():
163 for k, v in form_data.items():
160 if k == 'new_password' and v != '':
164 if k == 'new_password' and v != '':
161 user.password = v
165 user.password = v
162 user.api_key = generate_api_key(user.username)
166 user.api_key = generate_api_key(user.username)
163 else:
167 else:
164 setattr(user, k, v)
168 setattr(user, k, v)
165
169
166 self.sa.add(user)
170 self.sa.add(user)
167 self.sa.commit()
171 self.sa.commit()
168 except:
172 except:
169 log.error(traceback.format_exc())
173 log.error(traceback.format_exc())
170 self.sa.rollback()
174 self.sa.rollback()
171 raise
175 raise
172
176
173 def update_my_account(self, user_id, form_data):
177 def update_my_account(self, user_id, form_data):
174 try:
178 try:
175 user = self.get(user_id, cache=False)
179 user = self.get(user_id, cache=False)
176 if user.username == 'default':
180 if user.username == 'default':
177 raise DefaultUserException(
181 raise DefaultUserException(
178 _("You can't Edit this user since it's"
182 _("You can't Edit this user since it's"
179 " crucial for entire application"))
183 " crucial for entire application"))
180 for k, v in form_data.items():
184 for k, v in form_data.items():
181 if k == 'new_password' and v != '':
185 if k == 'new_password' and v != '':
182 user.password = v
186 user.password = v
183 user.api_key = generate_api_key(user.username)
187 user.api_key = generate_api_key(user.username)
184 else:
188 else:
185 if k not in ['admin', 'active']:
189 if k not in ['admin', 'active']:
186 setattr(user, k, v)
190 setattr(user, k, v)
187
191
188 self.sa.add(user)
192 self.sa.add(user)
189 self.sa.commit()
193 self.sa.commit()
190 except:
194 except:
191 log.error(traceback.format_exc())
195 log.error(traceback.format_exc())
192 self.sa.rollback()
196 self.sa.rollback()
193 raise
197 raise
194
198
195 def delete(self, user_id):
199 def delete(self, user_id):
196 try:
200 try:
197 user = self.get(user_id, cache=False)
201 user = self.get(user_id, cache=False)
198 if user.username == 'default':
202 if user.username == 'default':
199 raise DefaultUserException(
203 raise DefaultUserException(
200 _("You can't remove this user since it's"
204 _("You can't remove this user since it's"
201 " crucial for entire application"))
205 " crucial for entire application"))
202 if user.repositories:
206 if user.repositories:
203 raise UserOwnsReposException(_('This user still owns %s '
207 raise UserOwnsReposException(_('This user still owns %s '
204 'repositories and cannot be '
208 'repositories and cannot be '
205 'removed. Switch owners or '
209 'removed. Switch owners or '
206 'remove those repositories') \
210 'remove those repositories') \
207 % user.repositories)
211 % user.repositories)
208 self.sa.delete(user)
212 self.sa.delete(user)
209 self.sa.commit()
213 self.sa.commit()
210 except:
214 except:
211 log.error(traceback.format_exc())
215 log.error(traceback.format_exc())
212 self.sa.rollback()
216 self.sa.rollback()
213 raise
217 raise
214
218
215 def reset_password(self, data):
219 def reset_password(self, data):
216 from rhodecode.lib.celerylib import tasks, run_task
220 from rhodecode.lib.celerylib import tasks, run_task
217 run_task(tasks.reset_user_password, data['email'])
221 run_task(tasks.reset_user_password, data['email'])
218
222
219
223
220 def fill_data(self, auth_user, user_id=None, api_key=None):
224 def fill_data(self, auth_user, user_id=None, api_key=None):
221 """
225 """
222 Fetches auth_user by user_id,or api_key if present.
226 Fetches auth_user by user_id,or api_key if present.
223 Fills auth_user attributes with those taken from database.
227 Fills auth_user attributes with those taken from database.
224 Additionally set's is_authenitated if lookup fails
228 Additionally set's is_authenitated if lookup fails
225 present in database
229 present in database
226
230
227 :param auth_user: instance of user to set attributes
231 :param auth_user: instance of user to set attributes
228 :param user_id: user id to fetch by
232 :param user_id: user id to fetch by
229 :param api_key: api key to fetch by
233 :param api_key: api key to fetch by
230 """
234 """
231 if user_id is None and api_key is None:
235 if user_id is None and api_key is None:
232 raise Exception('You need to pass user_id or api_key')
236 raise Exception('You need to pass user_id or api_key')
233
237
234 try:
238 try:
235 if api_key:
239 if api_key:
236 dbuser = self.get_by_api_key(api_key)
240 dbuser = self.get_by_api_key(api_key)
237 else:
241 else:
238 dbuser = self.get(user_id)
242 dbuser = self.get(user_id)
239
243
240 if dbuser is not None:
244 if dbuser is not None:
241 log.debug('filling %s data', dbuser)
245 log.debug('filling %s data', dbuser)
242 for k, v in dbuser.get_dict().items():
246 for k, v in dbuser.get_dict().items():
243 setattr(auth_user, k, v)
247 setattr(auth_user, k, v)
244
248
245 except:
249 except:
246 log.error(traceback.format_exc())
250 log.error(traceback.format_exc())
247 auth_user.is_authenticated = False
251 auth_user.is_authenticated = False
248
252
249 return auth_user
253 return auth_user
250
254
251
255
252 def fill_perms(self, user):
256 def fill_perms(self, user):
253 """Fills user permission attribute with permissions taken from database
257 """Fills user permission attribute with permissions taken from database
254 works for permissions given for repositories, and for permissions that
258 works for permissions given for repositories, and for permissions that
255 as part of beeing group member
259 as part of beeing group member
256
260
257 :param user: user instance to fill his perms
261 :param user: user instance to fill his perms
258 """
262 """
259
263
260 user.permissions['repositories'] = {}
264 user.permissions['repositories'] = {}
261 user.permissions['global'] = set()
265 user.permissions['global'] = set()
262
266
263 #===========================================================================
267 #======================================================================
264 # fetch default permissions
268 # fetch default permissions
265 #===========================================================================
269 #======================================================================
266 default_user = self.get_by_username('default', cache=True)
270 default_user = self.get_by_username('default', cache=True)
267
271
268 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
272 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
269 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
273 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
270 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
274 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
271 .filter(RepoToPerm.user == default_user).all()
275 .filter(RepoToPerm.user == default_user).all()
272
276
273 if user.is_admin:
277 if user.is_admin:
274 #=======================================================================
278 #==================================================================
275 # #admin have all default rights set to admin
279 # #admin have all default rights set to admin
276 #=======================================================================
280 #==================================================================
277 user.permissions['global'].add('hg.admin')
281 user.permissions['global'].add('hg.admin')
278
282
279 for perm in default_perms:
283 for perm in default_perms:
280 p = 'repository.admin'
284 p = 'repository.admin'
281 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
285 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
282
286
283 else:
287 else:
284 #=======================================================================
288 #==================================================================
285 # set default permissions
289 # set default permissions
286 #=======================================================================
290 #==================================================================
287
291
288 #default global
292 #default global
289 default_global_perms = self.sa.query(UserToPerm)\
293 default_global_perms = self.sa.query(UserToPerm)\
290 .filter(UserToPerm.user == self.sa.query(User)\
294 .filter(UserToPerm.user == User.by_username('default'))
291 .filter(User.username == 'default').one())
292
295
293 for perm in default_global_perms:
296 for perm in default_global_perms:
294 user.permissions['global'].add(perm.permission.permission_name)
297 user.permissions['global'].add(perm.permission.permission_name)
295
298
296 #default for repositories
299 #default for repositories
297 for perm in default_perms:
300 for perm in default_perms:
298 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
301 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
299 #diself.sable defaults for private repos,
302 #diself.sable defaults for private repos,
300 p = 'repository.none'
303 p = 'repository.none'
301 elif perm.Repository.user_id == user.user_id:
304 elif perm.Repository.user_id == user.user_id:
302 #set admin if owner
305 #set admin if owner
303 p = 'repository.admin'
306 p = 'repository.admin'
304 else:
307 else:
305 p = perm.Permission.permission_name
308 p = perm.Permission.permission_name
306
309
307 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
310 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
308
311
309 #=======================================================================
312 #==================================================================
310 # overwrite default with user permissions if any
313 # overwrite default with user permissions if any
311 #=======================================================================
314 #==================================================================
312 user_perms = self.sa.query(RepoToPerm, Permission, Repository)\
315
316 user_perms = self.sa.query(UserToPerm)\
317 .filter(UserToPerm.user ==
318 User.get(user.user_id)).all()
319
320 for perm in user_perms:
321 user.permissions['global'].add(perm.permission.permission_name)
322
323 user_repo_perms = self.sa.query(RepoToPerm, Permission, Repository)\
313 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
324 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
314 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
325 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
315 .filter(RepoToPerm.user_id == user.user_id).all()
326 .filter(RepoToPerm.user_id == user.user_id).all()
316
327
317 for perm in user_perms:
328 for perm in user_repo_perms:
318 if perm.Repository.user_id == user.user_id:#set admin if owner
329 if perm.Repository.user_id == user.user_id:#set admin if owner
319 p = 'repository.admin'
330 p = 'repository.admin'
320 else:
331 else:
321 p = perm.Permission.permission_name
332 p = perm.Permission.permission_name
322 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
333 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
323
334
324
335
325 #=======================================================================
336 #=======================================================================
326 # check if user is part of groups for this repository and fill in
337 # check if user is part of groups for this repository and fill in
327 # (or replace with higher) permissions
338 # (or replace with higher) permissions
328 #=======================================================================
339 #=======================================================================
329 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm, Permission, Repository,)\
340 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm, Permission, Repository,)\
330 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
341 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
331 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
342 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
332 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
343 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
333 .filter(UsersGroupMember.user_id == user.user_id).all()
344 .filter(UsersGroupMember.user_id == user.user_id).all()
334
345
335 for perm in user_perms_from_users_groups:
346 for perm in user_perms_from_users_groups:
336 p = perm.Permission.permission_name
347 p = perm.Permission.permission_name
337 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
348 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
338 #overwrite permission only if it's greater than permission given from other sources
349 #overwrite permission only if it's greater than permission given from other sources
339 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
350 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
340 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
351 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
341
352
342 return user
353 return user
General Comments 0
You need to be logged in to leave comments. Login now