def test_Privilege_isAggregateOf(self):
        """
        Privilege.isAggregateOf()
        """
        for a, b in (
            (davxml.All(), davxml.Write()),
            (davxml.All(), davxml.ReadACL()),
            (davxml.Write(), davxml.WriteProperties()),
            (davxml.Write(), davxml.WriteContent()),
            (davxml.Write(), davxml.Bind()),
            (davxml.Write(), davxml.Unbind()),
        ):
            pa = davxml.Privilege(a)
            pb = davxml.Privilege(b)

            self.failUnless(pa.isAggregateOf(pb, davPrivilegeSet),
                            "%s contains %s" % (a.sname(), b.sname()))
            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet),
                        "%s does not contain %s" % (b.sname(), a.sname()))

        for a, b in (
            (davxml.Unlock(), davxml.Write()),
            (davxml.Unlock(), davxml.WriteACL()),
            (davxml.ReadCurrentUserPrivilegeSet(), davxml.WriteProperties()),
        ):
            pa = davxml.Privilege(a)
            pb = davxml.Privilege(b)

            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet),
                        "%s does not contain %s" % (b.sname(), a.sname()))
def report_DAV__acl_principal_prop_set(self, request, acl_prinicpal_prop_set):
    """
    Generate an acl-prinicpal-prop-set REPORT. (RFC 3744, section 9.2)
    """
    # Verify root element
    if not isinstance(acl_prinicpal_prop_set, davxml.ACLPrincipalPropSet):
        raise ValueError("%s expected as root element, not %s." %
                         (davxml.ACLPrincipalPropSet.sname(),
                          acl_prinicpal_prop_set.sname()))

    # Depth must be "0"
    depth = request.headers.getHeader("depth", "0")
    if depth != "0":
        log.error("Error in prinicpal-prop-set REPORT, Depth set to %s" %
                  (depth, ))
        raise HTTPError(
            StatusResponse(responsecode.BAD_REQUEST,
                           "Depth %s not allowed" % (depth, )))

    #
    # Check authentication and access controls
    #
    x = waitForDeferred(self.authorize(request, (davxml.ReadACL(), )))
    yield x
    x.getResult()

    # Get a single DAV:prop element from the REPORT request body
    propertiesForResource = None
    propElement = None
    for child in acl_prinicpal_prop_set.children:
        if child.qname() == ("DAV:", "prop"):
            if propertiesForResource is not None:
                log.error("Only one DAV:prop element allowed")
                raise HTTPError(
                    StatusResponse(responsecode.BAD_REQUEST,
                                   "Only one DAV:prop element allowed"))
            propertiesForResource = prop_common.propertyListForResource
            propElement = child

    if propertiesForResource is None:
        log.error(
            "Error in acl-principal-prop-set REPORT, no DAV:prop element")
        raise HTTPError(
            StatusResponse(responsecode.BAD_REQUEST, "No DAV:prop element"))

    # Enumerate principals on ACL in current resource
    principals = []

    acl = waitForDeferred(self.accessControlList(request))
    yield acl
    acl = acl.getResult()

    for ace in acl.children:
        resolved = waitForDeferred(
            self.resolvePrincipal(ace.principal.children[0], request))
        yield resolved
        resolved = resolved.getResult()
        if resolved is not None and resolved not in principals:
            principals.append(resolved)

    # Run report for each referenced principal
    try:
        responses = []
        matchcount = 0
        for principal in principals:
            # Check size of results is within limit
            matchcount += 1
            if matchcount > max_number_of_matches:
                raise NumberOfMatchesWithinLimits(max_number_of_matches)

            resource = waitForDeferred(request.locateResource(str(principal)))
            yield resource
            resource = resource.getResult()

            if resource is not None:
                #
                # Check authentication and access controls
                #
                x = waitForDeferred(
                    resource.authorize(request, (davxml.Read(), )))
                yield x
                try:
                    x.getResult()
                except HTTPError:
                    responses.append(
                        davxml.StatusResponse(
                            principal,
                            davxml.Status.fromResponseCode(
                                responsecode.FORBIDDEN)))
                else:
                    d = waitForDeferred(
                        prop_common.responseForHref(request, responses,
                                                    principal, resource,
                                                    propertiesForResource,
                                                    propElement))
                    yield d
                    d.getResult()
            else:
                log.error("Requested principal resource not found: %s" %
                          (str(principal), ))
                responses.append(
                    davxml.StatusResponse(
                        principal,
                        davxml.Status.fromResponseCode(
                            responsecode.NOT_FOUND)))

    except NumberOfMatchesWithinLimits:
        log.error("Too many matching components")
        raise HTTPError(
            ErrorResponse(responsecode.FORBIDDEN,
                          davxml.NumberOfMatchesWithinLimits()))

    yield MultiStatusResponse(responses)
Exemple #3
0
    def shareeAccessControlList(self, request, *args, **kwargs):
        """
        Return WebDAV ACLs appropriate for the current user accessing the
        shared collection.  For an "invite" share we take the privilege granted
        to the sharee in the invite and map that to WebDAV ACLs.  For a
        "direct" share, if it is a wiki collection we map the wiki privileges
        into WebDAV ACLs, otherwise we use whatever privileges exist on the
        underlying shared collection.

        @param request: the request used to locate the owner resource.
        @type request: L{txweb2.iweb.IRequest}

        @param args: The arguments for
            L{txweb2.dav.idav.IDAVResource.accessControlList}

        @param kwargs: The keyword arguments for
            L{txweb2.dav.idav.IDAVResource.accessControlList}, plus
            keyword-only arguments.

        @return: the appropriate WebDAV ACL for the sharee
        @rtype: L{davxml.ACL}
        """

        assert self._isShareeResource, "Only call this for a sharee resource"
        assert self.isCalendarCollection() or self.isAddressBookCollection(
        ), "Only call this for a address book or calendar resource"

        sharee = yield self.principalForUID(
            self._newStoreObject.viewerHome().uid())
        access = yield self._checkAccessControl()

        if access == "original" and not self._newStoreObject.ownerHome(
        ).external():
            original = (yield request.locateResource(self._share_url))
            result = (yield original.accessControlList(request, *args,
                                                       **kwargs))
            returnValue(result)

        # Direct shares use underlying privileges of shared collection
        userprivs = []
        if access in (
                "read-only",
                "read-write",
        ):
            userprivs.append(element.Privilege(element.Read()))
            userprivs.append(element.Privilege(element.ReadACL()))
            userprivs.append(
                element.Privilege(element.ReadCurrentUserPrivilegeSet()))
        if access in ("read-only", ):
            userprivs.append(element.Privilege(element.WriteProperties()))
        if access in ("read-write", ):
            userprivs.append(element.Privilege(element.Write()))
        proxyprivs = list(userprivs)
        try:
            proxyprivs.remove(element.Privilege(element.ReadACL()))
        except ValueError:
            # If wiki says no-access then ReadACL won't be in the list
            pass

        aces = (
            # Inheritable specific access for the resource's associated principal.
            element.ACE(
                element.Principal(element.HRef(sharee.principalURL())),
                element.Grant(*userprivs),
                element.Protected(),
                TwistedACLInheritable(),
            ), )

        if self.isCalendarCollection():
            aces += (
                # Inheritable CALDAV:read-free-busy access for authenticated users.
                element.ACE(
                    element.Principal(element.Authenticated()),
                    element.Grant(element.Privilege(caldavxml.ReadFreeBusy())),
                    TwistedACLInheritable(),
                ), )

        # Give read access to config.ReadPrincipals
        aces += config.ReadACEs

        # Give all access to config.AdminPrincipals
        aces += config.AdminACEs

        if self.isCalendarCollection() and config.EnableProxyPrincipals:
            aces += (
                # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
                element.ACE(
                    element.Principal(
                        element.HRef(
                            joinURL(sharee.principalURL(),
                                    "calendar-proxy-read/"))),
                    element.Grant(
                        element.Privilege(element.Read()),
                        element.Privilege(
                            element.ReadCurrentUserPrivilegeSet()),
                        element.Privilege(element.WriteProperties()),
                    ),
                    element.Protected(),
                    TwistedACLInheritable(),
                ),
                # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
                element.ACE(
                    element.Principal(
                        element.HRef(
                            joinURL(sharee.principalURL(),
                                    "calendar-proxy-write/"))),
                    element.Grant(*proxyprivs),
                    element.Protected(),
                    TwistedACLInheritable(),
                ),
            )

        returnValue(element.ACL(*aces))