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