def __init__(self, request, name, data): super(DcView, self).__init__(request) self.data = data self.name = name if request.user.is_staff: self.serializer = SuperDcSerializer if self.extended: self.serializer = ExtendedDcSerializer extra = {'select': ExtendedDcSerializer.extra_select} else: extra = None if name: # Return dc from cache (this will also check user permissions for requested DC) # We do this because GET is available for anybody if request.method == 'GET': get_dc(request, name) # But we will use this fresh DC object self.dc = get_object(request, Dc, {'name': name}, sr=('owner',), extra=extra) # Update current datacenter to log tasks for this dc request.dc = self.dc else: # GET many is available for anybody if (request.user.is_staff or self.full) or self.extended: pr = ('roles',) else: pr = None self.dc = get_dcs(request, sr=('owner',), pr=pr, extra=extra, order_by=self.order_by)
def _validate_dc_bound(self, value): # Overrides superclass method if value: data = self.init_data or {} return get_dc(self.request, data.get('dc', self.request.dc.name)) else: return None
def wrap(request, *args, **kwargs): if kwargs.get( 'data', None ) is None: # data parameter must exist in view function if request.method == 'GET': data_key = 'query_params' else: data_key = 'data' # noinspection PyBroadException try: kwargs['data'] = getattr(request, data_key, {}) except Exception: kwargs['data'] = {} dc = getattr(request, 'dc', DummyDc()) if catch_dc: if '/api/dc/' in request.path: try: _dc_name = kwargs.pop('dc') except KeyError: _dc_name = None else: _dc_name = None dc_name = kwargs['data'].get('dc', _dc_name) # Override request.dc set in DcMiddleware if dc_name and dc_name != dc.name: request.dc = get_dc(request, dc_name) if force_dc and (force_dc != request.dc.id or dc.is_dummy): # Override request.dc set in DcMiddleware and by catch_dc # WARNING: Make sure that the user has rights to access this DC request.dc = Dc.objects.get_by_id(force_dc) # Whenever we set a DC we have to set request.dc_user_permissions right after request.dc is available request.dc_user_permissions = request.dc.get_user_permissions( request.user) # request.dcs is used by some DC-mixed views - can be overridden by DcPermission request.dcs = Dc.objects.none() logger.debug('"%s %s (%s)" user="******" dc="%s" permissions=%s', request.method, fun.__name__, request.path, request.user.username, request.dc.name, request.dc_user_permissions) # Run permission checks for perm in permissions: if not perm(request, fun, args, kwargs): logger.error( 'Request by user "%s" to access API call "%s %s(%s, %s)" was denied by %s permission ' 'in DC "%s"!', request.user, request.method, fun.__name__, args, kwargs, perm.__name__, request.dc) raise PermissionDenied return fun(request, *args, **kwargs)
def get_domain(request, name, attrs=None, fetch_dc=False, data=None, count_records=False, **kwargs): """Return Domain object according to name. SuperAdmins have access to all domains and users can access only domain which they own. This function also acts as IsDomainOwner permission.""" user = request.user if attrs is None: attrs = {} if user.is_staff: dom_filter = None else: dom_filter = Q(user=user.id) if request.dcs: # noinspection PyAugmentAssignment dom_filter = dom_filter | Q(dc_bound__in=[dc.id for dc in request.dcs]) if count_records: # noinspection SqlDialectInspection,SqlNoDataSourceInspection kwargs['extra'] = { 'select': {'records': 'SELECT COUNT(*) FROM "records" WHERE "records"."domain_id" = "domains"."id"'} } attrs['name'] = name.lower() # The domain name must be always lowercased (DB requirement) domain = get_object(request, Domain, attrs, where=dom_filter, **kwargs) if domain.new: domain.dc_bound = get_dc(request, data.get('dc', request.dc.name)).id if not (user.is_staff or domain.user == user.id): # request.dcs is brought by IsAnyDcPermission if not (domain.dc_bound and Dc.objects.get_by_id(domain.dc_bound) in request.dcs): raise PermissionDenied # only DC-bound objects are visible by non-superadmin users if domain.dc_bound: # Change DC according to domain.dc_bound flag if request.dc.id != domain.dc_bound: request.dc = Dc.objects.get_by_id(domain.dc_bound) # Warning: Changing request.dc if not user.is_staff: request.dc_user_permissions = request.dc.get_user_permissions(user) logger.info('"%s %s" user="******" _changed_ dc="%s" permissions=%s', request.method, request.path, user.username, request.dc.name, request.dc_user_permissions) if fetch_dc: if domain.id: domain.dc = list(Dc.objects.filter(domaindc__domain_id=domain.id)) else: domain.dc = [] return domain
def save(self): dc_name = self.cleaned_data.get('name') if dc_name == self.request.dc.name: return False self.request.user.default_dc = dc = get_dc(self.request, dc_name) self.request.user.save(update_fields=('default_dc', )) messages.success(self.request, _('Datacenter successfully changed to %s') % dc.alias) logger.info('User "%s" changed default Datacenter to "%s"', self.request.user, dc) return True
def get_virt_object(request, model, sr=('owner', 'dc_bound'), pr=(), order_by=('name',), extra=None, many=False, name=None, get_attrs=None, data=None, where=None, **kwargs): """ Helper function for returning a virt object by get_attrs or queryset of objects. Used in dc-mixed views. """ user = request.user if many: qs = model.objects.select_related(*sr).prefetch_related(*pr).order_by(*order_by) if hasattr(model, 'INTERNAL'): qs = qs.filter(~Q(access=model.INTERNAL)) if not user.is_staff: # only DC-bound objects are visible by non-superadmin users qs = qs.filter(dc_bound__in=request.dcs) # request.dcs is brought by IsAnyDcPermission if where: qs = qs.filter(where) if extra: qs = qs.extra(**extra) return qs else: if get_attrs is None: get_attrs = {} if name: get_attrs['name'] = name obj = get_object(request, model, get_attrs, sr=sr, pr=pr, extra=extra, where=where, **kwargs) if obj.new: # POST request obj.dc_bound = get_dc(request, data.get('dc', request.dc.name)) if not user.is_staff: if not (obj.dc_bound and obj.dc_bound in request.dcs): # request.dcs is brought by IsAnyDcPermission raise PermissionDenied # only DC-bound objects are visible by non-superadmin users if obj.dc_bound: # Change DC according to obj.dc_bound flag if request.dc != obj.dc_bound: request.dc = obj.dc_bound # Warning: Changing request.dc if not user.is_staff: request.dc_user_permissions = request.dc.get_user_permissions(user) logger.info('"%s %s" user="******" _changed_ dc="%s" permissions=%s', request.method, request.path, user.username, request.dc.name, request.dc_user_permissions) return obj
def validate_dc_bound(self, attrs, source): try: value = bool(attrs[source]) except KeyError: pass else: if value != self.object.dc_bound_bool: if not self.request.user.is_staff: raise s.NoPermissionToModify if value: data = self.init_data or {} self._dc_bound = get_dc( self.request, data.get('dc', self.request.dc.name)) else: self._dc_bound = None return attrs