##// END OF EJS Templates
users: personal repo-group shouldn't be available for default user.
marcink -
r1690:5e538546 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,900 +1,901 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-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 users model for RhodeCode
22 users model for RhodeCode
23 """
23 """
24
24
25 import logging
25 import logging
26 import traceback
26 import traceback
27
27
28 import datetime
28 import datetime
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 import ipaddress
31 import ipaddress
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.sql.expression import true, false
33 from sqlalchemy.sql.expression import true, false
34
34
35 from rhodecode import events
35 from rhodecode import events
36 from rhodecode.lib.user_log_filter import user_log_filter
36 from rhodecode.lib.user_log_filter import user_log_filter
37 from rhodecode.lib.utils2 import (
37 from rhodecode.lib.utils2 import (
38 safe_unicode, get_current_rhodecode_user, action_logger_generic,
38 safe_unicode, get_current_rhodecode_user, action_logger_generic,
39 AttributeDict, str2bool)
39 AttributeDict, str2bool)
40 from rhodecode.lib.caching_query import FromCache
40 from rhodecode.lib.caching_query import FromCache
41 from rhodecode.model import BaseModel
41 from rhodecode.model import BaseModel
42 from rhodecode.model.auth_token import AuthTokenModel
42 from rhodecode.model.auth_token import AuthTokenModel
43 from rhodecode.model.db import (
43 from rhodecode.model.db import (
44 or_, joinedload, User, UserToPerm, UserEmailMap, UserIpMap, UserLog)
44 or_, joinedload, User, UserToPerm, UserEmailMap, UserIpMap, UserLog)
45 from rhodecode.lib.exceptions import (
45 from rhodecode.lib.exceptions import (
46 DefaultUserException, UserOwnsReposException, UserOwnsRepoGroupsException,
46 DefaultUserException, UserOwnsReposException, UserOwnsRepoGroupsException,
47 UserOwnsUserGroupsException, NotAllowedToCreateUserError)
47 UserOwnsUserGroupsException, NotAllowedToCreateUserError)
48 from rhodecode.model.meta import Session
48 from rhodecode.model.meta import Session
49 from rhodecode.model.repo_group import RepoGroupModel
49 from rhodecode.model.repo_group import RepoGroupModel
50
50
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 class UserModel(BaseModel):
55 class UserModel(BaseModel):
56 cls = User
56 cls = User
57
57
58 def get(self, user_id, cache=False):
58 def get(self, user_id, cache=False):
59 user = self.sa.query(User)
59 user = self.sa.query(User)
60 if cache:
60 if cache:
61 user = user.options(FromCache("sql_cache_short",
61 user = user.options(FromCache("sql_cache_short",
62 "get_user_%s" % user_id))
62 "get_user_%s" % user_id))
63 return user.get(user_id)
63 return user.get(user_id)
64
64
65 def get_user(self, user):
65 def get_user(self, user):
66 return self._get_user(user)
66 return self._get_user(user)
67
67
68 def _serialize_user(self, user):
68 def _serialize_user(self, user):
69 import rhodecode.lib.helpers as h
69 import rhodecode.lib.helpers as h
70
70
71 return {
71 return {
72 'id': user.user_id,
72 'id': user.user_id,
73 'first_name': user.name,
73 'first_name': user.name,
74 'last_name': user.lastname,
74 'last_name': user.lastname,
75 'username': user.username,
75 'username': user.username,
76 'email': user.email,
76 'email': user.email,
77 'icon_link': h.gravatar_url(user.email, 30),
77 'icon_link': h.gravatar_url(user.email, 30),
78 'value_display': h.person(user),
78 'value_display': h.person(user),
79 'value': user.username,
79 'value': user.username,
80 'value_type': 'user',
80 'value_type': 'user',
81 'active': user.active,
81 'active': user.active,
82 }
82 }
83
83
84 def get_users(self, name_contains=None, limit=20, only_active=True):
84 def get_users(self, name_contains=None, limit=20, only_active=True):
85
85
86 query = self.sa.query(User)
86 query = self.sa.query(User)
87 if only_active:
87 if only_active:
88 query = query.filter(User.active == true())
88 query = query.filter(User.active == true())
89
89
90 if name_contains:
90 if name_contains:
91 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
91 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
92 query = query.filter(
92 query = query.filter(
93 or_(
93 or_(
94 User.name.ilike(ilike_expression),
94 User.name.ilike(ilike_expression),
95 User.lastname.ilike(ilike_expression),
95 User.lastname.ilike(ilike_expression),
96 User.username.ilike(ilike_expression)
96 User.username.ilike(ilike_expression)
97 )
97 )
98 )
98 )
99 query = query.limit(limit)
99 query = query.limit(limit)
100 users = query.all()
100 users = query.all()
101
101
102 _users = [
102 _users = [
103 self._serialize_user(user) for user in users
103 self._serialize_user(user) for user in users
104 ]
104 ]
105 return _users
105 return _users
106
106
107 def get_by_username(self, username, cache=False, case_insensitive=False):
107 def get_by_username(self, username, cache=False, case_insensitive=False):
108
108
109 if case_insensitive:
109 if case_insensitive:
110 user = self.sa.query(User).filter(User.username.ilike(username))
110 user = self.sa.query(User).filter(User.username.ilike(username))
111 else:
111 else:
112 user = self.sa.query(User)\
112 user = self.sa.query(User)\
113 .filter(User.username == username)
113 .filter(User.username == username)
114 if cache:
114 if cache:
115 user = user.options(FromCache("sql_cache_short",
115 user = user.options(FromCache("sql_cache_short",
116 "get_user_%s" % username))
116 "get_user_%s" % username))
117 return user.scalar()
117 return user.scalar()
118
118
119 def get_by_email(self, email, cache=False, case_insensitive=False):
119 def get_by_email(self, email, cache=False, case_insensitive=False):
120 return User.get_by_email(email, case_insensitive, cache)
120 return User.get_by_email(email, case_insensitive, cache)
121
121
122 def get_by_auth_token(self, auth_token, cache=False):
122 def get_by_auth_token(self, auth_token, cache=False):
123 return User.get_by_auth_token(auth_token, cache)
123 return User.get_by_auth_token(auth_token, cache)
124
124
125 def get_active_user_count(self, cache=False):
125 def get_active_user_count(self, cache=False):
126 return User.query().filter(
126 return User.query().filter(
127 User.active == True).filter(
127 User.active == True).filter(
128 User.username != User.DEFAULT_USER).count()
128 User.username != User.DEFAULT_USER).count()
129
129
130 def create(self, form_data, cur_user=None):
130 def create(self, form_data, cur_user=None):
131 if not cur_user:
131 if not cur_user:
132 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
132 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
133
133
134 user_data = {
134 user_data = {
135 'username': form_data['username'],
135 'username': form_data['username'],
136 'password': form_data['password'],
136 'password': form_data['password'],
137 'email': form_data['email'],
137 'email': form_data['email'],
138 'firstname': form_data['firstname'],
138 'firstname': form_data['firstname'],
139 'lastname': form_data['lastname'],
139 'lastname': form_data['lastname'],
140 'active': form_data['active'],
140 'active': form_data['active'],
141 'extern_type': form_data['extern_type'],
141 'extern_type': form_data['extern_type'],
142 'extern_name': form_data['extern_name'],
142 'extern_name': form_data['extern_name'],
143 'admin': False,
143 'admin': False,
144 'cur_user': cur_user
144 'cur_user': cur_user
145 }
145 }
146
146
147 if 'create_repo_group' in form_data:
147 if 'create_repo_group' in form_data:
148 user_data['create_repo_group'] = str2bool(
148 user_data['create_repo_group'] = str2bool(
149 form_data.get('create_repo_group'))
149 form_data.get('create_repo_group'))
150
150
151 try:
151 try:
152 if form_data.get('password_change'):
152 if form_data.get('password_change'):
153 user_data['force_password_change'] = True
153 user_data['force_password_change'] = True
154 return UserModel().create_or_update(**user_data)
154 return UserModel().create_or_update(**user_data)
155 except Exception:
155 except Exception:
156 log.error(traceback.format_exc())
156 log.error(traceback.format_exc())
157 raise
157 raise
158
158
159 def update_user(self, user, skip_attrs=None, **kwargs):
159 def update_user(self, user, skip_attrs=None, **kwargs):
160 from rhodecode.lib.auth import get_crypt_password
160 from rhodecode.lib.auth import get_crypt_password
161
161
162 user = self._get_user(user)
162 user = self._get_user(user)
163 if user.username == User.DEFAULT_USER:
163 if user.username == User.DEFAULT_USER:
164 raise DefaultUserException(
164 raise DefaultUserException(
165 _("You can't Edit this user since it's"
165 _("You can't Edit this user since it's"
166 " crucial for entire application"))
166 " crucial for entire application"))
167
167
168 # first store only defaults
168 # first store only defaults
169 user_attrs = {
169 user_attrs = {
170 'updating_user_id': user.user_id,
170 'updating_user_id': user.user_id,
171 'username': user.username,
171 'username': user.username,
172 'password': user.password,
172 'password': user.password,
173 'email': user.email,
173 'email': user.email,
174 'firstname': user.name,
174 'firstname': user.name,
175 'lastname': user.lastname,
175 'lastname': user.lastname,
176 'active': user.active,
176 'active': user.active,
177 'admin': user.admin,
177 'admin': user.admin,
178 'extern_name': user.extern_name,
178 'extern_name': user.extern_name,
179 'extern_type': user.extern_type,
179 'extern_type': user.extern_type,
180 'language': user.user_data.get('language')
180 'language': user.user_data.get('language')
181 }
181 }
182
182
183 # in case there's new_password, that comes from form, use it to
183 # in case there's new_password, that comes from form, use it to
184 # store password
184 # store password
185 if kwargs.get('new_password'):
185 if kwargs.get('new_password'):
186 kwargs['password'] = kwargs['new_password']
186 kwargs['password'] = kwargs['new_password']
187
187
188 # cleanups, my_account password change form
188 # cleanups, my_account password change form
189 kwargs.pop('current_password', None)
189 kwargs.pop('current_password', None)
190 kwargs.pop('new_password', None)
190 kwargs.pop('new_password', None)
191
191
192 # cleanups, user edit password change form
192 # cleanups, user edit password change form
193 kwargs.pop('password_confirmation', None)
193 kwargs.pop('password_confirmation', None)
194 kwargs.pop('password_change', None)
194 kwargs.pop('password_change', None)
195
195
196 # create repo group on user creation
196 # create repo group on user creation
197 kwargs.pop('create_repo_group', None)
197 kwargs.pop('create_repo_group', None)
198
198
199 # legacy forms send name, which is the firstname
199 # legacy forms send name, which is the firstname
200 firstname = kwargs.pop('name', None)
200 firstname = kwargs.pop('name', None)
201 if firstname:
201 if firstname:
202 kwargs['firstname'] = firstname
202 kwargs['firstname'] = firstname
203
203
204 for k, v in kwargs.items():
204 for k, v in kwargs.items():
205 # skip if we don't want to update this
205 # skip if we don't want to update this
206 if skip_attrs and k in skip_attrs:
206 if skip_attrs and k in skip_attrs:
207 continue
207 continue
208
208
209 user_attrs[k] = v
209 user_attrs[k] = v
210
210
211 try:
211 try:
212 return self.create_or_update(**user_attrs)
212 return self.create_or_update(**user_attrs)
213 except Exception:
213 except Exception:
214 log.error(traceback.format_exc())
214 log.error(traceback.format_exc())
215 raise
215 raise
216
216
217 def create_or_update(
217 def create_or_update(
218 self, username, password, email, firstname='', lastname='',
218 self, username, password, email, firstname='', lastname='',
219 active=True, admin=False, extern_type=None, extern_name=None,
219 active=True, admin=False, extern_type=None, extern_name=None,
220 cur_user=None, plugin=None, force_password_change=False,
220 cur_user=None, plugin=None, force_password_change=False,
221 allow_to_create_user=True, create_repo_group=None,
221 allow_to_create_user=True, create_repo_group=None,
222 updating_user_id=None, language=None, strict_creation_check=True):
222 updating_user_id=None, language=None, strict_creation_check=True):
223 """
223 """
224 Creates a new instance if not found, or updates current one
224 Creates a new instance if not found, or updates current one
225
225
226 :param username:
226 :param username:
227 :param password:
227 :param password:
228 :param email:
228 :param email:
229 :param firstname:
229 :param firstname:
230 :param lastname:
230 :param lastname:
231 :param active:
231 :param active:
232 :param admin:
232 :param admin:
233 :param extern_type:
233 :param extern_type:
234 :param extern_name:
234 :param extern_name:
235 :param cur_user:
235 :param cur_user:
236 :param plugin: optional plugin this method was called from
236 :param plugin: optional plugin this method was called from
237 :param force_password_change: toggles new or existing user flag
237 :param force_password_change: toggles new or existing user flag
238 for password change
238 for password change
239 :param allow_to_create_user: Defines if the method can actually create
239 :param allow_to_create_user: Defines if the method can actually create
240 new users
240 new users
241 :param create_repo_group: Defines if the method should also
241 :param create_repo_group: Defines if the method should also
242 create an repo group with user name, and owner
242 create an repo group with user name, and owner
243 :param updating_user_id: if we set it up this is the user we want to
243 :param updating_user_id: if we set it up this is the user we want to
244 update this allows to editing username.
244 update this allows to editing username.
245 :param language: language of user from interface.
245 :param language: language of user from interface.
246
246
247 :returns: new User object with injected `is_new_user` attribute.
247 :returns: new User object with injected `is_new_user` attribute.
248 """
248 """
249 if not cur_user:
249 if not cur_user:
250 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
250 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
251
251
252 from rhodecode.lib.auth import (
252 from rhodecode.lib.auth import (
253 get_crypt_password, check_password, generate_auth_token)
253 get_crypt_password, check_password, generate_auth_token)
254 from rhodecode.lib.hooks_base import (
254 from rhodecode.lib.hooks_base import (
255 log_create_user, check_allowed_create_user)
255 log_create_user, check_allowed_create_user)
256
256
257 def _password_change(new_user, password):
257 def _password_change(new_user, password):
258 # empty password
258 # empty password
259 if not new_user.password:
259 if not new_user.password:
260 return False
260 return False
261
261
262 # password check is only needed for RhodeCode internal auth calls
262 # password check is only needed for RhodeCode internal auth calls
263 # in case it's a plugin we don't care
263 # in case it's a plugin we don't care
264 if not plugin:
264 if not plugin:
265
265
266 # first check if we gave crypted password back, and if it
266 # first check if we gave crypted password back, and if it
267 # matches it's not password change
267 # matches it's not password change
268 if new_user.password == password:
268 if new_user.password == password:
269 return False
269 return False
270
270
271 password_match = check_password(password, new_user.password)
271 password_match = check_password(password, new_user.password)
272 if not password_match:
272 if not password_match:
273 return True
273 return True
274
274
275 return False
275 return False
276
276
277 # read settings on default personal repo group creation
277 # read settings on default personal repo group creation
278 if create_repo_group is None:
278 if create_repo_group is None:
279 default_create_repo_group = RepoGroupModel()\
279 default_create_repo_group = RepoGroupModel()\
280 .get_default_create_personal_repo_group()
280 .get_default_create_personal_repo_group()
281 create_repo_group = default_create_repo_group
281 create_repo_group = default_create_repo_group
282
282
283 user_data = {
283 user_data = {
284 'username': username,
284 'username': username,
285 'password': password,
285 'password': password,
286 'email': email,
286 'email': email,
287 'firstname': firstname,
287 'firstname': firstname,
288 'lastname': lastname,
288 'lastname': lastname,
289 'active': active,
289 'active': active,
290 'admin': admin
290 'admin': admin
291 }
291 }
292
292
293 if updating_user_id:
293 if updating_user_id:
294 log.debug('Checking for existing account in RhodeCode '
294 log.debug('Checking for existing account in RhodeCode '
295 'database with user_id `%s` ' % (updating_user_id,))
295 'database with user_id `%s` ' % (updating_user_id,))
296 user = User.get(updating_user_id)
296 user = User.get(updating_user_id)
297 else:
297 else:
298 log.debug('Checking for existing account in RhodeCode '
298 log.debug('Checking for existing account in RhodeCode '
299 'database with username `%s` ' % (username,))
299 'database with username `%s` ' % (username,))
300 user = User.get_by_username(username, case_insensitive=True)
300 user = User.get_by_username(username, case_insensitive=True)
301
301
302 if user is None:
302 if user is None:
303 # we check internal flag if this method is actually allowed to
303 # we check internal flag if this method is actually allowed to
304 # create new user
304 # create new user
305 if not allow_to_create_user:
305 if not allow_to_create_user:
306 msg = ('Method wants to create new user, but it is not '
306 msg = ('Method wants to create new user, but it is not '
307 'allowed to do so')
307 'allowed to do so')
308 log.warning(msg)
308 log.warning(msg)
309 raise NotAllowedToCreateUserError(msg)
309 raise NotAllowedToCreateUserError(msg)
310
310
311 log.debug('Creating new user %s', username)
311 log.debug('Creating new user %s', username)
312
312
313 # only if we create user that is active
313 # only if we create user that is active
314 new_active_user = active
314 new_active_user = active
315 if new_active_user and strict_creation_check:
315 if new_active_user and strict_creation_check:
316 # raises UserCreationError if it's not allowed for any reason to
316 # raises UserCreationError if it's not allowed for any reason to
317 # create new active user, this also executes pre-create hooks
317 # create new active user, this also executes pre-create hooks
318 check_allowed_create_user(user_data, cur_user, strict_check=True)
318 check_allowed_create_user(user_data, cur_user, strict_check=True)
319 events.trigger(events.UserPreCreate(user_data))
319 events.trigger(events.UserPreCreate(user_data))
320 new_user = User()
320 new_user = User()
321 edit = False
321 edit = False
322 else:
322 else:
323 log.debug('updating user %s', username)
323 log.debug('updating user %s', username)
324 events.trigger(events.UserPreUpdate(user, user_data))
324 events.trigger(events.UserPreUpdate(user, user_data))
325 new_user = user
325 new_user = user
326 edit = True
326 edit = True
327
327
328 # we're not allowed to edit default user
328 # we're not allowed to edit default user
329 if user.username == User.DEFAULT_USER:
329 if user.username == User.DEFAULT_USER:
330 raise DefaultUserException(
330 raise DefaultUserException(
331 _("You can't edit this user (`%(username)s`) since it's "
331 _("You can't edit this user (`%(username)s`) since it's "
332 "crucial for entire application") % {'username': user.username})
332 "crucial for entire application") % {'username': user.username})
333
333
334 # inject special attribute that will tell us if User is new or old
334 # inject special attribute that will tell us if User is new or old
335 new_user.is_new_user = not edit
335 new_user.is_new_user = not edit
336 # for users that didn's specify auth type, we use RhodeCode built in
336 # for users that didn's specify auth type, we use RhodeCode built in
337 from rhodecode.authentication.plugins import auth_rhodecode
337 from rhodecode.authentication.plugins import auth_rhodecode
338 extern_name = extern_name or auth_rhodecode.RhodeCodeAuthPlugin.name
338 extern_name = extern_name or auth_rhodecode.RhodeCodeAuthPlugin.name
339 extern_type = extern_type or auth_rhodecode.RhodeCodeAuthPlugin.name
339 extern_type = extern_type or auth_rhodecode.RhodeCodeAuthPlugin.name
340
340
341 try:
341 try:
342 new_user.username = username
342 new_user.username = username
343 new_user.admin = admin
343 new_user.admin = admin
344 new_user.email = email
344 new_user.email = email
345 new_user.active = active
345 new_user.active = active
346 new_user.extern_name = safe_unicode(extern_name)
346 new_user.extern_name = safe_unicode(extern_name)
347 new_user.extern_type = safe_unicode(extern_type)
347 new_user.extern_type = safe_unicode(extern_type)
348 new_user.name = firstname
348 new_user.name = firstname
349 new_user.lastname = lastname
349 new_user.lastname = lastname
350
350
351 # set password only if creating an user or password is changed
351 # set password only if creating an user or password is changed
352 if not edit or _password_change(new_user, password):
352 if not edit or _password_change(new_user, password):
353 reason = 'new password' if edit else 'new user'
353 reason = 'new password' if edit else 'new user'
354 log.debug('Updating password reason=>%s', reason)
354 log.debug('Updating password reason=>%s', reason)
355 new_user.password = get_crypt_password(password) if password else None
355 new_user.password = get_crypt_password(password) if password else None
356
356
357 if force_password_change:
357 if force_password_change:
358 new_user.update_userdata(force_password_change=True)
358 new_user.update_userdata(force_password_change=True)
359 if language:
359 if language:
360 new_user.update_userdata(language=language)
360 new_user.update_userdata(language=language)
361 new_user.update_userdata(notification_status=True)
361 new_user.update_userdata(notification_status=True)
362
362
363 self.sa.add(new_user)
363 self.sa.add(new_user)
364
364
365 if not edit and create_repo_group:
365 if not edit and create_repo_group:
366 RepoGroupModel().create_personal_repo_group(
366 RepoGroupModel().create_personal_repo_group(
367 new_user, commit_early=False)
367 new_user, commit_early=False)
368
368
369 if not edit:
369 if not edit:
370 # add the RSS token
370 # add the RSS token
371 AuthTokenModel().create(username,
371 AuthTokenModel().create(username,
372 description='Generated feed token',
372 description='Generated feed token',
373 role=AuthTokenModel.cls.ROLE_FEED)
373 role=AuthTokenModel.cls.ROLE_FEED)
374 log_create_user(created_by=cur_user, **new_user.get_dict())
374 log_create_user(created_by=cur_user, **new_user.get_dict())
375 events.trigger(events.UserPostCreate(user_data))
375 events.trigger(events.UserPostCreate(user_data))
376 return new_user
376 return new_user
377 except (DatabaseError,):
377 except (DatabaseError,):
378 log.error(traceback.format_exc())
378 log.error(traceback.format_exc())
379 raise
379 raise
380
380
381 def create_registration(self, form_data):
381 def create_registration(self, form_data):
382 from rhodecode.model.notification import NotificationModel
382 from rhodecode.model.notification import NotificationModel
383 from rhodecode.model.notification import EmailNotificationModel
383 from rhodecode.model.notification import EmailNotificationModel
384
384
385 try:
385 try:
386 form_data['admin'] = False
386 form_data['admin'] = False
387 form_data['extern_name'] = 'rhodecode'
387 form_data['extern_name'] = 'rhodecode'
388 form_data['extern_type'] = 'rhodecode'
388 form_data['extern_type'] = 'rhodecode'
389 new_user = self.create(form_data)
389 new_user = self.create(form_data)
390
390
391 self.sa.add(new_user)
391 self.sa.add(new_user)
392 self.sa.flush()
392 self.sa.flush()
393
393
394 user_data = new_user.get_dict()
394 user_data = new_user.get_dict()
395 kwargs = {
395 kwargs = {
396 # use SQLALCHEMY safe dump of user data
396 # use SQLALCHEMY safe dump of user data
397 'user': AttributeDict(user_data),
397 'user': AttributeDict(user_data),
398 'date': datetime.datetime.now()
398 'date': datetime.datetime.now()
399 }
399 }
400 notification_type = EmailNotificationModel.TYPE_REGISTRATION
400 notification_type = EmailNotificationModel.TYPE_REGISTRATION
401 # pre-generate the subject for notification itself
401 # pre-generate the subject for notification itself
402 (subject,
402 (subject,
403 _h, _e, # we don't care about those
403 _h, _e, # we don't care about those
404 body_plaintext) = EmailNotificationModel().render_email(
404 body_plaintext) = EmailNotificationModel().render_email(
405 notification_type, **kwargs)
405 notification_type, **kwargs)
406
406
407 # create notification objects, and emails
407 # create notification objects, and emails
408 NotificationModel().create(
408 NotificationModel().create(
409 created_by=new_user,
409 created_by=new_user,
410 notification_subject=subject,
410 notification_subject=subject,
411 notification_body=body_plaintext,
411 notification_body=body_plaintext,
412 notification_type=notification_type,
412 notification_type=notification_type,
413 recipients=None, # all admins
413 recipients=None, # all admins
414 email_kwargs=kwargs,
414 email_kwargs=kwargs,
415 )
415 )
416
416
417 return new_user
417 return new_user
418 except Exception:
418 except Exception:
419 log.error(traceback.format_exc())
419 log.error(traceback.format_exc())
420 raise
420 raise
421
421
422 def _handle_user_repos(self, username, repositories, handle_mode=None):
422 def _handle_user_repos(self, username, repositories, handle_mode=None):
423 _superadmin = self.cls.get_first_super_admin()
423 _superadmin = self.cls.get_first_super_admin()
424 left_overs = True
424 left_overs = True
425
425
426 from rhodecode.model.repo import RepoModel
426 from rhodecode.model.repo import RepoModel
427
427
428 if handle_mode == 'detach':
428 if handle_mode == 'detach':
429 for obj in repositories:
429 for obj in repositories:
430 obj.user = _superadmin
430 obj.user = _superadmin
431 # set description we know why we super admin now owns
431 # set description we know why we super admin now owns
432 # additional repositories that were orphaned !
432 # additional repositories that were orphaned !
433 obj.description += ' \n::detached repository from deleted user: %s' % (username,)
433 obj.description += ' \n::detached repository from deleted user: %s' % (username,)
434 self.sa.add(obj)
434 self.sa.add(obj)
435 left_overs = False
435 left_overs = False
436 elif handle_mode == 'delete':
436 elif handle_mode == 'delete':
437 for obj in repositories:
437 for obj in repositories:
438 RepoModel().delete(obj, forks='detach')
438 RepoModel().delete(obj, forks='detach')
439 left_overs = False
439 left_overs = False
440
440
441 # if nothing is done we have left overs left
441 # if nothing is done we have left overs left
442 return left_overs
442 return left_overs
443
443
444 def _handle_user_repo_groups(self, username, repository_groups,
444 def _handle_user_repo_groups(self, username, repository_groups,
445 handle_mode=None):
445 handle_mode=None):
446 _superadmin = self.cls.get_first_super_admin()
446 _superadmin = self.cls.get_first_super_admin()
447 left_overs = True
447 left_overs = True
448
448
449 from rhodecode.model.repo_group import RepoGroupModel
449 from rhodecode.model.repo_group import RepoGroupModel
450
450
451 if handle_mode == 'detach':
451 if handle_mode == 'detach':
452 for r in repository_groups:
452 for r in repository_groups:
453 r.user = _superadmin
453 r.user = _superadmin
454 # set description we know why we super admin now owns
454 # set description we know why we super admin now owns
455 # additional repositories that were orphaned !
455 # additional repositories that were orphaned !
456 r.group_description += ' \n::detached repository group from deleted user: %s' % (username,)
456 r.group_description += ' \n::detached repository group from deleted user: %s' % (username,)
457 self.sa.add(r)
457 self.sa.add(r)
458 left_overs = False
458 left_overs = False
459 elif handle_mode == 'delete':
459 elif handle_mode == 'delete':
460 for r in repository_groups:
460 for r in repository_groups:
461 RepoGroupModel().delete(r)
461 RepoGroupModel().delete(r)
462 left_overs = False
462 left_overs = False
463
463
464 # if nothing is done we have left overs left
464 # if nothing is done we have left overs left
465 return left_overs
465 return left_overs
466
466
467 def _handle_user_user_groups(self, username, user_groups, handle_mode=None):
467 def _handle_user_user_groups(self, username, user_groups, handle_mode=None):
468 _superadmin = self.cls.get_first_super_admin()
468 _superadmin = self.cls.get_first_super_admin()
469 left_overs = True
469 left_overs = True
470
470
471 from rhodecode.model.user_group import UserGroupModel
471 from rhodecode.model.user_group import UserGroupModel
472
472
473 if handle_mode == 'detach':
473 if handle_mode == 'detach':
474 for r in user_groups:
474 for r in user_groups:
475 for user_user_group_to_perm in r.user_user_group_to_perm:
475 for user_user_group_to_perm in r.user_user_group_to_perm:
476 if user_user_group_to_perm.user.username == username:
476 if user_user_group_to_perm.user.username == username:
477 user_user_group_to_perm.user = _superadmin
477 user_user_group_to_perm.user = _superadmin
478 r.user = _superadmin
478 r.user = _superadmin
479 # set description we know why we super admin now owns
479 # set description we know why we super admin now owns
480 # additional repositories that were orphaned !
480 # additional repositories that were orphaned !
481 r.user_group_description += ' \n::detached user group from deleted user: %s' % (username,)
481 r.user_group_description += ' \n::detached user group from deleted user: %s' % (username,)
482 self.sa.add(r)
482 self.sa.add(r)
483 left_overs = False
483 left_overs = False
484 elif handle_mode == 'delete':
484 elif handle_mode == 'delete':
485 for r in user_groups:
485 for r in user_groups:
486 UserGroupModel().delete(r)
486 UserGroupModel().delete(r)
487 left_overs = False
487 left_overs = False
488
488
489 # if nothing is done we have left overs left
489 # if nothing is done we have left overs left
490 return left_overs
490 return left_overs
491
491
492 def delete(self, user, cur_user=None, handle_repos=None,
492 def delete(self, user, cur_user=None, handle_repos=None,
493 handle_repo_groups=None, handle_user_groups=None):
493 handle_repo_groups=None, handle_user_groups=None):
494 if not cur_user:
494 if not cur_user:
495 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
495 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
496 user = self._get_user(user)
496 user = self._get_user(user)
497
497
498 try:
498 try:
499 if user.username == User.DEFAULT_USER:
499 if user.username == User.DEFAULT_USER:
500 raise DefaultUserException(
500 raise DefaultUserException(
501 _(u"You can't remove this user since it's"
501 _(u"You can't remove this user since it's"
502 u" crucial for entire application"))
502 u" crucial for entire application"))
503
503
504 left_overs = self._handle_user_repos(
504 left_overs = self._handle_user_repos(
505 user.username, user.repositories, handle_repos)
505 user.username, user.repositories, handle_repos)
506 if left_overs and user.repositories:
506 if left_overs and user.repositories:
507 repos = [x.repo_name for x in user.repositories]
507 repos = [x.repo_name for x in user.repositories]
508 raise UserOwnsReposException(
508 raise UserOwnsReposException(
509 _(u'user "%s" still owns %s repositories and cannot be '
509 _(u'user "%s" still owns %s repositories and cannot be '
510 u'removed. Switch owners or remove those repositories:%s')
510 u'removed. Switch owners or remove those repositories:%s')
511 % (user.username, len(repos), ', '.join(repos)))
511 % (user.username, len(repos), ', '.join(repos)))
512
512
513 left_overs = self._handle_user_repo_groups(
513 left_overs = self._handle_user_repo_groups(
514 user.username, user.repository_groups, handle_repo_groups)
514 user.username, user.repository_groups, handle_repo_groups)
515 if left_overs and user.repository_groups:
515 if left_overs and user.repository_groups:
516 repo_groups = [x.group_name for x in user.repository_groups]
516 repo_groups = [x.group_name for x in user.repository_groups]
517 raise UserOwnsRepoGroupsException(
517 raise UserOwnsRepoGroupsException(
518 _(u'user "%s" still owns %s repository groups and cannot be '
518 _(u'user "%s" still owns %s repository groups and cannot be '
519 u'removed. Switch owners or remove those repository groups:%s')
519 u'removed. Switch owners or remove those repository groups:%s')
520 % (user.username, len(repo_groups), ', '.join(repo_groups)))
520 % (user.username, len(repo_groups), ', '.join(repo_groups)))
521
521
522 left_overs = self._handle_user_user_groups(
522 left_overs = self._handle_user_user_groups(
523 user.username, user.user_groups, handle_user_groups)
523 user.username, user.user_groups, handle_user_groups)
524 if left_overs and user.user_groups:
524 if left_overs and user.user_groups:
525 user_groups = [x.users_group_name for x in user.user_groups]
525 user_groups = [x.users_group_name for x in user.user_groups]
526 raise UserOwnsUserGroupsException(
526 raise UserOwnsUserGroupsException(
527 _(u'user "%s" still owns %s user groups and cannot be '
527 _(u'user "%s" still owns %s user groups and cannot be '
528 u'removed. Switch owners or remove those user groups:%s')
528 u'removed. Switch owners or remove those user groups:%s')
529 % (user.username, len(user_groups), ', '.join(user_groups)))
529 % (user.username, len(user_groups), ', '.join(user_groups)))
530
530
531 # we might change the user data with detach/delete, make sure
531 # we might change the user data with detach/delete, make sure
532 # the object is marked as expired before actually deleting !
532 # the object is marked as expired before actually deleting !
533 self.sa.expire(user)
533 self.sa.expire(user)
534 self.sa.delete(user)
534 self.sa.delete(user)
535 from rhodecode.lib.hooks_base import log_delete_user
535 from rhodecode.lib.hooks_base import log_delete_user
536 log_delete_user(deleted_by=cur_user, **user.get_dict())
536 log_delete_user(deleted_by=cur_user, **user.get_dict())
537 except Exception:
537 except Exception:
538 log.error(traceback.format_exc())
538 log.error(traceback.format_exc())
539 raise
539 raise
540
540
541 def reset_password_link(self, data, pwd_reset_url):
541 def reset_password_link(self, data, pwd_reset_url):
542 from rhodecode.lib.celerylib import tasks, run_task
542 from rhodecode.lib.celerylib import tasks, run_task
543 from rhodecode.model.notification import EmailNotificationModel
543 from rhodecode.model.notification import EmailNotificationModel
544 user_email = data['email']
544 user_email = data['email']
545 try:
545 try:
546 user = User.get_by_email(user_email)
546 user = User.get_by_email(user_email)
547 if user:
547 if user:
548 log.debug('password reset user found %s', user)
548 log.debug('password reset user found %s', user)
549
549
550 email_kwargs = {
550 email_kwargs = {
551 'password_reset_url': pwd_reset_url,
551 'password_reset_url': pwd_reset_url,
552 'user': user,
552 'user': user,
553 'email': user_email,
553 'email': user_email,
554 'date': datetime.datetime.now()
554 'date': datetime.datetime.now()
555 }
555 }
556
556
557 (subject, headers, email_body,
557 (subject, headers, email_body,
558 email_body_plaintext) = EmailNotificationModel().render_email(
558 email_body_plaintext) = EmailNotificationModel().render_email(
559 EmailNotificationModel.TYPE_PASSWORD_RESET, **email_kwargs)
559 EmailNotificationModel.TYPE_PASSWORD_RESET, **email_kwargs)
560
560
561 recipients = [user_email]
561 recipients = [user_email]
562
562
563 action_logger_generic(
563 action_logger_generic(
564 'sending password reset email to user: {}'.format(
564 'sending password reset email to user: {}'.format(
565 user), namespace='security.password_reset')
565 user), namespace='security.password_reset')
566
566
567 run_task(tasks.send_email, recipients, subject,
567 run_task(tasks.send_email, recipients, subject,
568 email_body_plaintext, email_body)
568 email_body_plaintext, email_body)
569
569
570 else:
570 else:
571 log.debug("password reset email %s not found", user_email)
571 log.debug("password reset email %s not found", user_email)
572 except Exception:
572 except Exception:
573 log.error(traceback.format_exc())
573 log.error(traceback.format_exc())
574 return False
574 return False
575
575
576 return True
576 return True
577
577
578 def reset_password(self, data):
578 def reset_password(self, data):
579 from rhodecode.lib.celerylib import tasks, run_task
579 from rhodecode.lib.celerylib import tasks, run_task
580 from rhodecode.model.notification import EmailNotificationModel
580 from rhodecode.model.notification import EmailNotificationModel
581 from rhodecode.lib import auth
581 from rhodecode.lib import auth
582 user_email = data['email']
582 user_email = data['email']
583 pre_db = True
583 pre_db = True
584 try:
584 try:
585 user = User.get_by_email(user_email)
585 user = User.get_by_email(user_email)
586 new_passwd = auth.PasswordGenerator().gen_password(
586 new_passwd = auth.PasswordGenerator().gen_password(
587 12, auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
587 12, auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
588 if user:
588 if user:
589 user.password = auth.get_crypt_password(new_passwd)
589 user.password = auth.get_crypt_password(new_passwd)
590 # also force this user to reset his password !
590 # also force this user to reset his password !
591 user.update_userdata(force_password_change=True)
591 user.update_userdata(force_password_change=True)
592
592
593 Session().add(user)
593 Session().add(user)
594
594
595 # now delete the token in question
595 # now delete the token in question
596 UserApiKeys = AuthTokenModel.cls
596 UserApiKeys = AuthTokenModel.cls
597 UserApiKeys().query().filter(
597 UserApiKeys().query().filter(
598 UserApiKeys.api_key == data['token']).delete()
598 UserApiKeys.api_key == data['token']).delete()
599
599
600 Session().commit()
600 Session().commit()
601 log.info('successfully reset password for `%s`', user_email)
601 log.info('successfully reset password for `%s`', user_email)
602
602
603 if new_passwd is None:
603 if new_passwd is None:
604 raise Exception('unable to generate new password')
604 raise Exception('unable to generate new password')
605
605
606 pre_db = False
606 pre_db = False
607
607
608 email_kwargs = {
608 email_kwargs = {
609 'new_password': new_passwd,
609 'new_password': new_passwd,
610 'user': user,
610 'user': user,
611 'email': user_email,
611 'email': user_email,
612 'date': datetime.datetime.now()
612 'date': datetime.datetime.now()
613 }
613 }
614
614
615 (subject, headers, email_body,
615 (subject, headers, email_body,
616 email_body_plaintext) = EmailNotificationModel().render_email(
616 email_body_plaintext) = EmailNotificationModel().render_email(
617 EmailNotificationModel.TYPE_PASSWORD_RESET_CONFIRMATION,
617 EmailNotificationModel.TYPE_PASSWORD_RESET_CONFIRMATION,
618 **email_kwargs)
618 **email_kwargs)
619
619
620 recipients = [user_email]
620 recipients = [user_email]
621
621
622 action_logger_generic(
622 action_logger_generic(
623 'sent new password to user: {} with email: {}'.format(
623 'sent new password to user: {} with email: {}'.format(
624 user, user_email), namespace='security.password_reset')
624 user, user_email), namespace='security.password_reset')
625
625
626 run_task(tasks.send_email, recipients, subject,
626 run_task(tasks.send_email, recipients, subject,
627 email_body_plaintext, email_body)
627 email_body_plaintext, email_body)
628
628
629 except Exception:
629 except Exception:
630 log.error('Failed to update user password')
630 log.error('Failed to update user password')
631 log.error(traceback.format_exc())
631 log.error(traceback.format_exc())
632 if pre_db:
632 if pre_db:
633 # we rollback only if local db stuff fails. If it goes into
633 # we rollback only if local db stuff fails. If it goes into
634 # run_task, we're pass rollback state this wouldn't work then
634 # run_task, we're pass rollback state this wouldn't work then
635 Session().rollback()
635 Session().rollback()
636
636
637 return True
637 return True
638
638
639 def fill_data(self, auth_user, user_id=None, api_key=None, username=None):
639 def fill_data(self, auth_user, user_id=None, api_key=None, username=None):
640 """
640 """
641 Fetches auth_user by user_id,or api_key if present.
641 Fetches auth_user by user_id,or api_key if present.
642 Fills auth_user attributes with those taken from database.
642 Fills auth_user attributes with those taken from database.
643 Additionally set's is_authenitated if lookup fails
643 Additionally set's is_authenitated if lookup fails
644 present in database
644 present in database
645
645
646 :param auth_user: instance of user to set attributes
646 :param auth_user: instance of user to set attributes
647 :param user_id: user id to fetch by
647 :param user_id: user id to fetch by
648 :param api_key: api key to fetch by
648 :param api_key: api key to fetch by
649 :param username: username to fetch by
649 :param username: username to fetch by
650 """
650 """
651 if user_id is None and api_key is None and username is None:
651 if user_id is None and api_key is None and username is None:
652 raise Exception('You need to pass user_id, api_key or username')
652 raise Exception('You need to pass user_id, api_key or username')
653
653
654 log.debug(
654 log.debug(
655 'doing fill data based on: user_id:%s api_key:%s username:%s',
655 'doing fill data based on: user_id:%s api_key:%s username:%s',
656 user_id, api_key, username)
656 user_id, api_key, username)
657 try:
657 try:
658 dbuser = None
658 dbuser = None
659 if user_id:
659 if user_id:
660 dbuser = self.get(user_id)
660 dbuser = self.get(user_id)
661 elif api_key:
661 elif api_key:
662 dbuser = self.get_by_auth_token(api_key)
662 dbuser = self.get_by_auth_token(api_key)
663 elif username:
663 elif username:
664 dbuser = self.get_by_username(username)
664 dbuser = self.get_by_username(username)
665
665
666 if not dbuser:
666 if not dbuser:
667 log.warning(
667 log.warning(
668 'Unable to lookup user by id:%s api_key:%s username:%s',
668 'Unable to lookup user by id:%s api_key:%s username:%s',
669 user_id, api_key, username)
669 user_id, api_key, username)
670 return False
670 return False
671 if not dbuser.active:
671 if not dbuser.active:
672 log.debug('User `%s` is inactive, skipping fill data', username)
672 log.debug('User `%s:%s` is inactive, skipping fill data',
673 username, user_id)
673 return False
674 return False
674
675
675 log.debug('filling user:%s data', dbuser)
676 log.debug('filling user:%s data', dbuser)
676
677
677 # TODO: johbo: Think about this and find a clean solution
678 # TODO: johbo: Think about this and find a clean solution
678 user_data = dbuser.get_dict()
679 user_data = dbuser.get_dict()
679 user_data.update(dbuser.get_api_data(include_secrets=True))
680 user_data.update(dbuser.get_api_data(include_secrets=True))
680
681
681 for k, v in user_data.iteritems():
682 for k, v in user_data.iteritems():
682 # properties of auth user we dont update
683 # properties of auth user we dont update
683 if k not in ['auth_tokens', 'permissions']:
684 if k not in ['auth_tokens', 'permissions']:
684 setattr(auth_user, k, v)
685 setattr(auth_user, k, v)
685
686
686 # few extras
687 # few extras
687 setattr(auth_user, 'feed_token', dbuser.feed_token)
688 setattr(auth_user, 'feed_token', dbuser.feed_token)
688 except Exception:
689 except Exception:
689 log.error(traceback.format_exc())
690 log.error(traceback.format_exc())
690 auth_user.is_authenticated = False
691 auth_user.is_authenticated = False
691 return False
692 return False
692
693
693 return True
694 return True
694
695
695 def has_perm(self, user, perm):
696 def has_perm(self, user, perm):
696 perm = self._get_perm(perm)
697 perm = self._get_perm(perm)
697 user = self._get_user(user)
698 user = self._get_user(user)
698
699
699 return UserToPerm.query().filter(UserToPerm.user == user)\
700 return UserToPerm.query().filter(UserToPerm.user == user)\
700 .filter(UserToPerm.permission == perm).scalar() is not None
701 .filter(UserToPerm.permission == perm).scalar() is not None
701
702
702 def grant_perm(self, user, perm):
703 def grant_perm(self, user, perm):
703 """
704 """
704 Grant user global permissions
705 Grant user global permissions
705
706
706 :param user:
707 :param user:
707 :param perm:
708 :param perm:
708 """
709 """
709 user = self._get_user(user)
710 user = self._get_user(user)
710 perm = self._get_perm(perm)
711 perm = self._get_perm(perm)
711 # if this permission is already granted skip it
712 # if this permission is already granted skip it
712 _perm = UserToPerm.query()\
713 _perm = UserToPerm.query()\
713 .filter(UserToPerm.user == user)\
714 .filter(UserToPerm.user == user)\
714 .filter(UserToPerm.permission == perm)\
715 .filter(UserToPerm.permission == perm)\
715 .scalar()
716 .scalar()
716 if _perm:
717 if _perm:
717 return
718 return
718 new = UserToPerm()
719 new = UserToPerm()
719 new.user = user
720 new.user = user
720 new.permission = perm
721 new.permission = perm
721 self.sa.add(new)
722 self.sa.add(new)
722 return new
723 return new
723
724
724 def revoke_perm(self, user, perm):
725 def revoke_perm(self, user, perm):
725 """
726 """
726 Revoke users global permissions
727 Revoke users global permissions
727
728
728 :param user:
729 :param user:
729 :param perm:
730 :param perm:
730 """
731 """
731 user = self._get_user(user)
732 user = self._get_user(user)
732 perm = self._get_perm(perm)
733 perm = self._get_perm(perm)
733
734
734 obj = UserToPerm.query()\
735 obj = UserToPerm.query()\
735 .filter(UserToPerm.user == user)\
736 .filter(UserToPerm.user == user)\
736 .filter(UserToPerm.permission == perm)\
737 .filter(UserToPerm.permission == perm)\
737 .scalar()
738 .scalar()
738 if obj:
739 if obj:
739 self.sa.delete(obj)
740 self.sa.delete(obj)
740
741
741 def add_extra_email(self, user, email):
742 def add_extra_email(self, user, email):
742 """
743 """
743 Adds email address to UserEmailMap
744 Adds email address to UserEmailMap
744
745
745 :param user:
746 :param user:
746 :param email:
747 :param email:
747 """
748 """
748 from rhodecode.model import forms
749 from rhodecode.model import forms
749 form = forms.UserExtraEmailForm()()
750 form = forms.UserExtraEmailForm()()
750 data = form.to_python({'email': email})
751 data = form.to_python({'email': email})
751 user = self._get_user(user)
752 user = self._get_user(user)
752
753
753 obj = UserEmailMap()
754 obj = UserEmailMap()
754 obj.user = user
755 obj.user = user
755 obj.email = data['email']
756 obj.email = data['email']
756 self.sa.add(obj)
757 self.sa.add(obj)
757 return obj
758 return obj
758
759
759 def delete_extra_email(self, user, email_id):
760 def delete_extra_email(self, user, email_id):
760 """
761 """
761 Removes email address from UserEmailMap
762 Removes email address from UserEmailMap
762
763
763 :param user:
764 :param user:
764 :param email_id:
765 :param email_id:
765 """
766 """
766 user = self._get_user(user)
767 user = self._get_user(user)
767 obj = UserEmailMap.query().get(email_id)
768 obj = UserEmailMap.query().get(email_id)
768 if obj:
769 if obj:
769 self.sa.delete(obj)
770 self.sa.delete(obj)
770
771
771 def parse_ip_range(self, ip_range):
772 def parse_ip_range(self, ip_range):
772 ip_list = []
773 ip_list = []
773 def make_unique(value):
774 def make_unique(value):
774 seen = []
775 seen = []
775 return [c for c in value if not (c in seen or seen.append(c))]
776 return [c for c in value if not (c in seen or seen.append(c))]
776
777
777 # firsts split by commas
778 # firsts split by commas
778 for ip_range in ip_range.split(','):
779 for ip_range in ip_range.split(','):
779 if not ip_range:
780 if not ip_range:
780 continue
781 continue
781 ip_range = ip_range.strip()
782 ip_range = ip_range.strip()
782 if '-' in ip_range:
783 if '-' in ip_range:
783 start_ip, end_ip = ip_range.split('-', 1)
784 start_ip, end_ip = ip_range.split('-', 1)
784 start_ip = ipaddress.ip_address(start_ip.strip())
785 start_ip = ipaddress.ip_address(start_ip.strip())
785 end_ip = ipaddress.ip_address(end_ip.strip())
786 end_ip = ipaddress.ip_address(end_ip.strip())
786 parsed_ip_range = []
787 parsed_ip_range = []
787
788
788 for index in xrange(int(start_ip), int(end_ip) + 1):
789 for index in xrange(int(start_ip), int(end_ip) + 1):
789 new_ip = ipaddress.ip_address(index)
790 new_ip = ipaddress.ip_address(index)
790 parsed_ip_range.append(str(new_ip))
791 parsed_ip_range.append(str(new_ip))
791 ip_list.extend(parsed_ip_range)
792 ip_list.extend(parsed_ip_range)
792 else:
793 else:
793 ip_list.append(ip_range)
794 ip_list.append(ip_range)
794
795
795 return make_unique(ip_list)
796 return make_unique(ip_list)
796
797
797 def add_extra_ip(self, user, ip, description=None):
798 def add_extra_ip(self, user, ip, description=None):
798 """
799 """
799 Adds ip address to UserIpMap
800 Adds ip address to UserIpMap
800
801
801 :param user:
802 :param user:
802 :param ip:
803 :param ip:
803 """
804 """
804 from rhodecode.model import forms
805 from rhodecode.model import forms
805 form = forms.UserExtraIpForm()()
806 form = forms.UserExtraIpForm()()
806 data = form.to_python({'ip': ip})
807 data = form.to_python({'ip': ip})
807 user = self._get_user(user)
808 user = self._get_user(user)
808
809
809 obj = UserIpMap()
810 obj = UserIpMap()
810 obj.user = user
811 obj.user = user
811 obj.ip_addr = data['ip']
812 obj.ip_addr = data['ip']
812 obj.description = description
813 obj.description = description
813 self.sa.add(obj)
814 self.sa.add(obj)
814 return obj
815 return obj
815
816
816 def delete_extra_ip(self, user, ip_id):
817 def delete_extra_ip(self, user, ip_id):
817 """
818 """
818 Removes ip address from UserIpMap
819 Removes ip address from UserIpMap
819
820
820 :param user:
821 :param user:
821 :param ip_id:
822 :param ip_id:
822 """
823 """
823 user = self._get_user(user)
824 user = self._get_user(user)
824 obj = UserIpMap.query().get(ip_id)
825 obj = UserIpMap.query().get(ip_id)
825 if obj:
826 if obj:
826 self.sa.delete(obj)
827 self.sa.delete(obj)
827
828
828 def get_accounts_in_creation_order(self, current_user=None):
829 def get_accounts_in_creation_order(self, current_user=None):
829 """
830 """
830 Get accounts in order of creation for deactivation for license limits
831 Get accounts in order of creation for deactivation for license limits
831
832
832 pick currently logged in user, and append to the list in position 0
833 pick currently logged in user, and append to the list in position 0
833 pick all super-admins in order of creation date and add it to the list
834 pick all super-admins in order of creation date and add it to the list
834 pick all other accounts in order of creation and add it to the list.
835 pick all other accounts in order of creation and add it to the list.
835
836
836 Based on that list, the last accounts can be disabled as they are
837 Based on that list, the last accounts can be disabled as they are
837 created at the end and don't include any of the super admins as well
838 created at the end and don't include any of the super admins as well
838 as the current user.
839 as the current user.
839
840
840 :param current_user: optionally current user running this operation
841 :param current_user: optionally current user running this operation
841 """
842 """
842
843
843 if not current_user:
844 if not current_user:
844 current_user = get_current_rhodecode_user()
845 current_user = get_current_rhodecode_user()
845 active_super_admins = [
846 active_super_admins = [
846 x.user_id for x in User.query()
847 x.user_id for x in User.query()
847 .filter(User.user_id != current_user.user_id)
848 .filter(User.user_id != current_user.user_id)
848 .filter(User.active == true())
849 .filter(User.active == true())
849 .filter(User.admin == true())
850 .filter(User.admin == true())
850 .order_by(User.created_on.asc())]
851 .order_by(User.created_on.asc())]
851
852
852 active_regular_users = [
853 active_regular_users = [
853 x.user_id for x in User.query()
854 x.user_id for x in User.query()
854 .filter(User.user_id != current_user.user_id)
855 .filter(User.user_id != current_user.user_id)
855 .filter(User.active == true())
856 .filter(User.active == true())
856 .filter(User.admin == false())
857 .filter(User.admin == false())
857 .order_by(User.created_on.asc())]
858 .order_by(User.created_on.asc())]
858
859
859 list_of_accounts = [current_user.user_id]
860 list_of_accounts = [current_user.user_id]
860 list_of_accounts += active_super_admins
861 list_of_accounts += active_super_admins
861 list_of_accounts += active_regular_users
862 list_of_accounts += active_regular_users
862
863
863 return list_of_accounts
864 return list_of_accounts
864
865
865 def deactivate_last_users(self, expected_users):
866 def deactivate_last_users(self, expected_users):
866 """
867 """
867 Deactivate accounts that are over the license limits.
868 Deactivate accounts that are over the license limits.
868 Algorithm of which accounts to disabled is based on the formula:
869 Algorithm of which accounts to disabled is based on the formula:
869
870
870 Get current user, then super admins in creation order, then regular
871 Get current user, then super admins in creation order, then regular
871 active users in creation order.
872 active users in creation order.
872
873
873 Using that list we mark all accounts from the end of it as inactive.
874 Using that list we mark all accounts from the end of it as inactive.
874 This way we block only latest created accounts.
875 This way we block only latest created accounts.
875
876
876 :param expected_users: list of users in special order, we deactivate
877 :param expected_users: list of users in special order, we deactivate
877 the end N ammoun of users from that list
878 the end N ammoun of users from that list
878 """
879 """
879
880
880 list_of_accounts = self.get_accounts_in_creation_order()
881 list_of_accounts = self.get_accounts_in_creation_order()
881
882
882 for acc_id in list_of_accounts[expected_users + 1:]:
883 for acc_id in list_of_accounts[expected_users + 1:]:
883 user = User.get(acc_id)
884 user = User.get(acc_id)
884 log.info('Deactivating account %s for license unlock', user)
885 log.info('Deactivating account %s for license unlock', user)
885 user.active = False
886 user.active = False
886 Session().add(user)
887 Session().add(user)
887 Session().commit()
888 Session().commit()
888
889
889 return
890 return
890
891
891 def get_user_log(self, user, filter_term):
892 def get_user_log(self, user, filter_term):
892 user_log = UserLog.query()\
893 user_log = UserLog.query()\
893 .filter(or_(UserLog.user_id == user.user_id,
894 .filter(or_(UserLog.user_id == user.user_id,
894 UserLog.username == user.username))\
895 UserLog.username == user.username))\
895 .options(joinedload(UserLog.user))\
896 .options(joinedload(UserLog.user))\
896 .options(joinedload(UserLog.repository))\
897 .options(joinedload(UserLog.repository))\
897 .order_by(UserLog.action_date.desc())
898 .order_by(UserLog.action_date.desc())
898
899
899 user_log = user_log_filter(user_log, filter_term)
900 user_log = user_log_filter(user_log, filter_term)
900 return user_log
901 return user_log
General Comments 0
You need to be logged in to leave comments. Login now