Пример #1
0
    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)
Пример #2
0
    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
Пример #3
0
        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)
Пример #4
0
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
Пример #5
0
    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
Пример #6
0
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
Пример #7
0
    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