def _announce_task(event, event_status): task_id = event['uuid'] user_id, owner_id, dc_id = user_owner_dc_ids_from_task_id(task_id) if owner_id == internal_id: return # probably beat task if event.get('queue', None) == 'mgmt': return # sent task on mgmt if event.get('direct', None): # Send signal to ObjectOwner only users = (int(owner_id), ) else: # Send signal to all affected users users = User.get_super_admin_ids() # SuperAdmins users.update(User.get_dc_admin_ids(dc_id=dc_id)) # DcAdmins users.add(int(user_id)) # TaskCreator users.add(int(owner_id)) # ObjectOwner debug('Sending signal for %s task %s to %s', event_status, task_id, users) # Signal! for i in users: new_task = signal('task-for-%s' % i) new_task.send(event, task_id=task_id, event_status=event_status)
def delete(self): user = self.user # Predefined users can not be deleted if user.id in (settings.ADMIN_USER, settings.SYSTEM_USER, self.request.user.id): raise PermissionDenied relations = user.get_relations() if relations: message = { 'detail': _('Cannot delete user, because he has relations to some objects.'), 'relations': relations } return FailureTaskResponse(self.request, message, obj=user, dc_bound=False) dd = {'email': user.email, 'date_joined': user.date_joined} was_staff = user.is_staff old_roles = list(user.roles.all()) ser = self.serializer(self.request, user) ser.object.delete() res = SuccessTaskResponse(self.request, None, obj=user, msg=LOG_USER_DELETE, detail_dict=dd, dc_bound=False) # User was removed, which may affect the cached list of DC admins for DCs which are attached to user's groups # So we need to clear the list of admins cached for each affected DC affected_dcs = Dc.objects.distinct().filter(roles__in=old_roles, roles__permissions__id=AdminPermission.id) for dc in affected_dcs: User.clear_dc_admin_ids(dc) if was_staff: User.clear_super_admin_ids() return res
def _announce_task(event, event_status): task_id = event['uuid'] user_id, owner_id, dc_id = user_owner_dc_ids_from_task_id(task_id) if owner_id == internal_id: return # probably beat task if event.get('queue', None) == 'mgmt': return # sent task on mgmt if event.get('direct', None): # Send signal to ObjectOwner only users = (int(owner_id),) elif event.get('broadcast', None): # Send signal to all active socket.io sessions from sio.namespaces import ACTIVE_USERS users = set(session[0] for session in itervalues(ACTIVE_USERS)) else: # Send signal to all affected users users = User.get_super_admin_ids() # SuperAdmins users.update(User.get_dc_admin_ids(dc_id=dc_id)) # DcAdmins users.add(int(user_id)) # TaskCreator users.add(int(owner_id)) # ObjectOwner debug('Sending signal for %s task %s to %s', event_status, task_id, users) # Signal! for i in users: new_task = signal('task-for-%s' % i) new_task.send(event, task_id=task_id, event_status=event_status)
def user_modify(self, update=False, serializer=None): affected_groups = () if not serializer: serializer = self.serializer user = self.user ser = serializer(self.request, user, data=self.data, partial=update) if not ser.is_valid(): return FailureTaskResponse(self.request, ser.errors, obj=user, dc_bound=False) ser.save() if update: msg = LOG_USER_UPDATE status = HTTP_200_OK else: msg = LOG_USER_CREATE status = HTTP_201_CREATED res = SuccessTaskResponse(self.request, ser.data, status=status, obj=user, msg=msg, owner=ser.object, detail_dict=ser.detail_dict(), dc_bound=False) if serializer == UserSerializer: # User's is_staff attribute was changed -> Clear the cached list of super admins if ser.is_staff_changed: User.clear_super_admin_ids() # User's groups were changed, which may affect the cached list of DC admins for DCs which are attached # to these groups. So we need to clear the list of admins cached for each affected DC # noinspection PyProtectedMember if user._roles_to_save is not None: # noinspection PyProtectedMember affected_groups = set(user._roles_to_save) affected_groups.update(ser.old_roles) affected_dcs = Dc.objects.distinct().filter( roles__in=affected_groups, roles__permissions__id=AdminPermission.id) for dc in affected_dcs: User.clear_dc_admin_ids(dc) # User was removed from some groups and may loose access to DCs which are attached to this group # So we better set his current_dc to default_dc if ser.old_roles and not user.is_staff: user.reset_current_dc() connection.on_commit(lambda: user_relationship_changed.send( user_name=ser.object.username, affected_groups=tuple(group.id for group in affected_groups))) return res
def _update_affected_users(self, detach=False): # DC groups have changed -> invalidate the list of admins for this DC User.clear_dc_admin_ids(self.dc) # DC groups have changed on a non-default DC -> update the current_dc on every affected user # This is only required when the group is being removed from a DC and does not make sense when attaching if detach and not self.dc.is_default(): for user in self.role.user_set.select_related('default_dc').filter(default_dc=self.dc)\ .exclude(is_staff=True): user.reset_current_dc()
def put(self): dc = self.dc request = self.request ser = self.serializer(request, dc, data=self.data, partial=True) if not ser.is_valid(): return FailureTaskResponse(request, ser.errors, obj=dc) ser.save() res = SuccessTaskResponse(request, ser.data, obj=dc, detail_dict=ser.detail_dict(), msg=LOG_DC_UPDATE) task_id = res.data.get('task_id') # Changing DC groups affects the group.dc_bound flag if ser.groups_changed: # The groups that are removed or added should not be DC-bound anymore for group in ser.groups_changed: connection.on_commit(lambda: group_relationship_changed.send( dc_name=dc.name, group_name=group.name)) if group.dc_bound: remove_dc_binding_virt_object(task_id, LOG_GROUP_UPDATE, group, user=request.user) # After changing the DC owner or changing DC groups we have to invalidate the list of admins for this DC if ser.owner_changed or ser.groups_changed: connection.on_commit( lambda: dc_relationship_changed.send(dc_name=dc.name)) User.clear_dc_admin_ids(dc) # Remove user.dc_bound flag for new DC owner # Remove user.dc_bound flag for users in new dc.groups, which are DC-bound, but not to this datacenter self._remove_user_dc_binding(task_id, owner=dc.owner, groups=ser.groups_added) # When a user is removed as owner from non-default DC or groups are changed on a non-default DC # we have to update the current_dc on every affected user, because he could remain access to this DC # (this is because get_dc() uses current_dc as a shortcut) if not dc.is_default(): if ser.owner_changed and not ser.owner_changed.is_staff: ser.owner_changed.reset_current_dc() if ser.removed_users: for user in ser.removed_users.select_related( 'default_dc').exclude(is_staff=True): user.reset_current_dc() return res
def save(self, **kwargs): user = self.object new_flag = (not user.pk or getattr(user, 'new', False)) user.save() if user._roles_to_save is not None: self.old_roles = set(user.roles.all()) user.roles = user._roles_to_save # Newly created user via API is automatically marked as verified # Creator has to provide correct email, or in user profile set email as not verified (since email is required)! # Email change by user will trigger email with verification code so he can finish profile! # If admin doesnt set phone user is force to set it and when phone is changed sms verification is send if new_flag: user.userprofile.email_verified = True user.userprofile.phone_verified = True user.userprofile.save() # Changing a user email makes the email not verified # (unless request.user is not part of the staff or registration is disabled) if self.old_email and not self.request.user.is_staff and User.must_email_be_verified(): user.userprofile.email_verified = False user.userprofile.email_token = user.userprofile.generate_token(6) user.userprofile.save() self.send_email_verification(user)
def get_owners(request, dc=None, all=False, order_by=('username', )): """ Return QuerySet of all active users. WARNING: Use with care! """ dc = dc or request.dc qs = User.objects.exclude(id=settings.SYSTEM_USER).filter( is_active=True).order_by(*order_by).distinct() if all or dc.access == dc.PUBLIC: # Public DC is available for all active users return qs # Private DC is available to only staff, DC owner and DC admins ... admins = User.get_super_admin_ids() admins.update(User.get_dc_admin_ids(dc)) # ... and users who have access to DC: return qs.filter(Q(id__in=admins) | Q(roles__in=dc.roles.all()))
def _announce_task(event, event_status): task_id = event['uuid'] task_prefix = task_prefix_from_task_id(task_id) if task_prefix[2] == internal_id: # owner_id return # probably beat task if event.get('queue', None) == 'mgmt': return # sent task on mgmt users = User.get_super_admin_ids() # SuperAdmins users.update(User.get_dc_admin_ids(dc_id=task_prefix[4])) # DcAdmins users.add(int(task_prefix[0])) # TaskCreator users.add(int(task_prefix[2])) # ObjectOwner debug('Sending signal for %s task %s to %s', event_status, task_id, users) # Signal! for i in users: new_task = signal('task-for-%s' % i) new_task.send(event, task_id=task_id, event_status=event_status)
def log(msgdict): """ Save msgdict into DB and cache. """ # This dictionary can be store more than once dct = msgdict.copy() # DB TaskLogEntry.add(**msgdict) # Do not store PKs in cache dc_id = dct.pop('dc_id') owner_id = dct.pop('owner_id') del dct['user_id'] del dct['object_pk'] del dct['content_type'] dct['time'] = dct['time'].isoformat() # Always store everything in staff cached task log _cache_log(_cache_log_key(settings.TASK_LOG_STAFF_ID, dc_id), dct) # Store owner relevant actions in owners cached task log if owner_id not in User.get_super_admin_ids(): _cache_log(_cache_log_key(owner_id, dc_id), dct)
def _create_db_user(): user = User() user.first_name = get_random_string(10) user.last_name = get_random_string(10) user.api_access = True user.is_active = True user.is_super_admin = False user.callback_key = '***' user.password = get_random_string(10) user.email = get_random_string(10) + '@' + get_random_string( 10) + '.com' user.api_key = get_random_string(30) user.username = '******' + get_random_string(10) user.password = get_random_string(10) user.save() return user
def group_modify(self, update=False): group = self.group request = self.request if update: # We are deleting users that are not assigned to group any more, so we have to store all of them before # deleting because we have to update task log for user so he can see he was removed from group original_group_users = set( group.user_set.select_related('dc_bound', 'default_dc').all()) else: group.alias = group.name # just a default original_group_users = set() ser = self.serializer(request, group, data=self.data, partial=update) if not ser.is_valid(): return FailureTaskResponse(request, ser.errors, obj=group, dc_bound=False) ser.save() if update: msg = LOG_GROUP_UPDATE status = HTTP_200_OK else: msg = LOG_GROUP_CREATE status = HTTP_201_CREATED connection.on_commit(lambda: group_relationship_changed.send( group_name=ser.object.name)) res = SuccessTaskResponse(request, ser.data, status=status, obj=group, msg=msg, detail_dict=ser.detail_dict(), dc_bound=False) # let's get the task_id so we use the same one for each log message task_id = res.data.get('task_id') removed_users = None if group.dc_bound and not update: attach_dc_virt_object(res.data.get('task_id'), LOG_GROUP_ATTACH, group, group.dc_bound, user=request.user) if ser.object._users_to_save is not None: # Update Users log that are attached to group current_users = set(ser.object._users_to_save) added_users = current_users - original_group_users removed_users = original_group_users - current_users affected_users = current_users.symmetric_difference( original_group_users) # Remove user.dc_bound flag for newly added users if group is attached to multiple DCs or # to one DC that is different from user.dc_bound if added_users: group_dcs_count = group.dc_set.count() if group_dcs_count >= 1: if group_dcs_count == 1: dc = group.dc_set.get() else: dc = None for user in added_users: remove_user_dc_binding(task_id, user, dc=dc) # Update Users that were removed from group or added to group for user in affected_users: detail = "groups='%s'" % ','.join(user.roles.all().values_list( 'name', flat=True)) task_log_success(task_id, LOG_USER_UPDATE, obj=user, owner=user, update_user_tasks=False, detail=detail) # Permission or users for this group were changed, which may affect the cached list of DC admins for DCs which # are attached to this group. So we need to clear the list of admins cached for each affected DC if ser.object._permissions_to_save is not None or ser.object._users_to_save is not None: for dc in group.dc_set.all(): User.clear_dc_admin_ids(dc) # Users were removed from this group and may loose access to DCs which are attached to this group # So we better set all users current_dc to default_dc if removed_users: for user in removed_users: if not user.is_staff: user.reset_current_dc() return res
def _create_db_user(self): user = User() user.first_name = get_random_string(10) user.last_name = get_random_string(10) user.api_access = True user.is_active = True user.is_staff = False user.password = get_random_string(10) user.email = get_random_string(10) + '@' + get_random_string(10) + '.com' user.username = '******' + get_random_string(10) user.password = get_random_string(10) user.save() user.userprofile.alerting_email = user.email user.userprofile.alerting_phone = get_random_string(10) user.userprofile.alerting_jabber = 'jabber_' + user.email user.userprofile.save() return user