[CalendarServer-changes] [13015] CalendarServer/branches/users/sagen/move2who-4
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 27 19:06:05 PDT 2014
Revision: 13015
http://trac.calendarserver.org//changeset/13015
Author: sagen at apple.com
Date: 2014-03-27 19:06:05 -0700 (Thu, 27 Mar 2014)
Log Message:
-----------
Port wiki and sharing to twext.who
Modified Paths:
--------------
CalendarServer/branches/users/sagen/move2who-4/calendarserver/platform/darwin/wiki.py
CalendarServer/branches/users/sagen/move2who-4/calendarserver/provision/root.py
CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/util.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/augment.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/calendar.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/wiki.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/sharing.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/stdconfig.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/storebridge.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_sharing.py
CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py
CalendarServer/branches/users/sagen/move2who-4/txdav/who/directory.py
CalendarServer/branches/users/sagen/move2who-4/txdav/who/util.py
CalendarServer/branches/users/sagen/move2who-4/txdav/who/wiki.py
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/platform/darwin/wiki.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/platform/darwin/wiki.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/platform/darwin/wiki.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -27,16 +27,17 @@
log = Logger()
+
@inlineCallbacks
-def guidForAuthToken(token, host="localhost", port=80):
+def uidForAuthToken(token, host="localhost", port=80):
"""
Send a GET request to the web auth service to retrieve the user record
- guid associated with the provided auth token.
+ uid associated with the provided auth token.
@param token: An auth token, usually passed in via cookie when webcal
makes a request.
@type token: C{str}
- @return: deferred returning a guid (C{str}) if successful, or
+ @return: deferred returning a uid (C{str}) if successful, or
will raise WebAuthError otherwise.
"""
url = "http://%s:%d/auth/verify?auth_token=%s" % (host, port, token,)
@@ -44,8 +45,10 @@
try:
response = json.loads(jsonResponse)
except Exception, e:
- log.error("Error parsing JSON response from webauth: %s (%s)" %
- (jsonResponse, str(e)))
+ log.error(
+ "Error parsing JSON response from webauth: {resp} {error}",
+ resp=jsonResponse, error=str(e)
+ )
raise WebAuthError("Could not look up token: %s" % (token,))
if response["succeeded"]:
returnValue(response["generated_uid"])
@@ -57,10 +60,10 @@
def accessForUserToWiki(user, wiki, host="localhost", port=4444):
"""
Send a GET request to the wiki collabd service to retrieve the access level
- the given user (in GUID form) has to the given wiki (in wiki short-name
+ the given user (uid) has to the given wiki (in wiki short-name
form).
- @param user: The GUID of the user
+ @param user: The UID of the user
@type user: C{str}
@param wiki: The short name of the wiki
@type wiki: C{str}
@@ -69,8 +72,9 @@
status FORBIDDEN will errBack; an unknown wiki will have a status
of NOT_FOUND
"""
- url = "http://%s:%s/cal/accessLevelForUserWikiCalendar/%s/%s" % (host, port,
- user, wiki)
+ url = "http://%s:%s/cal/accessLevelForUserWikiCalendar/%s/%s" % (
+ host, port, user, wiki
+ )
return _getPage(url, host, port)
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/provision/root.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/provision/root.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/provision/root.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -19,29 +19,29 @@
"RootResource",
]
+from calendarserver.platform.darwin.wiki import uidForAuthToken
from twext.python.log import Logger
-from txweb2 import responsecode
-from txweb2.auth.wrapper import UnauthorizedResponse
-from txdav.xml import element as davxml
-from txweb2.dav.xattrprops import xattrPropertyStore
-from txweb2.http import HTTPError, StatusResponse, RedirectResponse
-
+from twext.who.idirectory import RecordType
from twisted.cred.error import LoginFailed, UnauthorizedLogin
from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.python.reflect import namedClass
+from twisted.web.error import Error as WebError
from twisted.web.xmlrpc import Proxy
-from twisted.web.error import Error as WebError
-
+from twistedcaldav.cache import DisabledCache
+from twistedcaldav.cache import MemcacheResponseCache, MemcacheChangeNotifier
from twistedcaldav.cache import _CachedResponseResource
-from twistedcaldav.cache import MemcacheResponseCache, MemcacheChangeNotifier
-from twistedcaldav.cache import DisabledCache
from twistedcaldav.config import config
+from twistedcaldav.directory.principal import DirectoryPrincipalResource
from twistedcaldav.extensions import DAVFile, CachingPropertyStore
from twistedcaldav.extensions import DirectoryPrincipalPropertySearchMixIn
from twistedcaldav.extensions import ReadOnlyResourceMixIn
from twistedcaldav.resource import CalDAVComplianceMixIn
-from twistedcaldav.directory.principal import DirectoryPrincipalResource
-from calendarserver.platform.darwin.wiki import guidForAuthToken
+from txdav.who.wiki import DirectoryService as WikiDirectoryService
+from txdav.xml import element as davxml
+from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.dav.xattrprops import xattrPropertyStore
+from txweb2.http import HTTPError, StatusResponse, RedirectResponse
log = Logger()
@@ -234,20 +234,20 @@
record = None
try:
if wikiConfig.LionCompatibility:
- guid = None
+ uid = None
proxy = Proxy(wikiConfig["URL"])
username = (yield proxy.callRemote(wikiConfig["UserMethod"], token))
directory = request.site.resource.getDirectory()
- record = directory.recordWithShortName("users", username)
+ record = yield directory.recordWithShortName(RecordType.user, username)
if record is not None:
- guid = record.guid
+ uid = record.uid
else:
- guid = (yield guidForAuthToken(token))
- if guid == "unauthenticated":
- guid = None
+ uid = (yield uidForAuthToken(token))
+ if uid == "unauthenticated":
+ uid = None
except WebError, w:
- guid = None
+ uid = None
# FORBIDDEN status means it's an unknown token
if int(w.status) == responsecode.NOT_FOUND:
log.debug("Unknown wiki token: %s" % (token,))
@@ -257,18 +257,18 @@
except Exception, e:
log.error("Failed to look up wiki token (%s)" % (e,))
- guid = None
+ uid = None
- if guid is not None:
- log.debug("Wiki lookup returned guid: %s" % (guid,))
+ if uid is not None:
+ log.debug("Wiki lookup returned uid: %s" % (uid,))
principal = None
directory = request.site.resource.getDirectory()
- record = directory.recordWithGUID(guid)
+ record = yield directory.recordWithUID(uid)
if record is not None:
username = record.shortNames[0]
log.debug("Wiki user record for user %s : %s" % (username, record))
for collection in self.principalCollections():
- principal = collection.principalForRecord(record)
+ principal = yield collection.principalForRecord(record)
if principal is not None:
break
@@ -317,7 +317,7 @@
elif (len(segments) > 2 and segments[0] in ("calendars", "principals") and
(
segments[1] == "wikis" or
- (segments[1] == "__uids__" and segments[2].startswith("wiki-"))
+ (segments[1] == "__uids__" and segments[2].startswith(WikiDirectoryService.uidPrefix))
)
):
# This is a wiki-related calendar resource. SACLs are not checked.
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/util.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/util.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -28,7 +28,6 @@
import errno
import os
-from time import sleep
from socket import fromfd, AF_UNIX, SOCK_STREAM, socketpair
import psutil
@@ -46,17 +45,13 @@
from twisted.internet import reactor as _reactor
from twisted.internet.reactor import addSystemEventTrigger
from twisted.internet.tcp import Connection
-from twisted.python.reflect import namedClass
-# from twisted.python.failure import Failure
from twistedcaldav.bind import doBind
from twistedcaldav.cache import CacheStoreNotifierFactory
-from twistedcaldav.directory import calendaruserproxy
from twistedcaldav.directory.addressbook import DirectoryAddressBookHomeProvisioningResource
from twistedcaldav.directory.calendar import DirectoryCalendarHomeProvisioningResource
from twistedcaldav.directory.digest import QopDigestCredentialFactory
from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
-from twistedcaldav.directory.wiki import WikiDirectoryService
from calendarserver.push.notifier import NotifierFactory
from calendarserver.push.applepush import APNSubscriptionResource
from twistedcaldav.directorybackedaddressbook import DirectoryBackedAddressBookResource
@@ -98,8 +93,6 @@
from urllib import quote
from twisted.python.usage import UsageError
-from txdav.dps.client import DirectoryService as DirectoryProxyClientService
-
from twext.who.checker import UsernamePasswordCredentialChecker
from twext.who.checker import HTTPDigestCredentialChecker
from twisted.cred.error import UnauthorizedLogin
@@ -281,96 +274,6 @@
-def REMOVEMEdirectoryFromConfig(config):
- """
- Create an L{AggregateDirectoryService} from the given configuration.
- """
-
- #
- # Setup the Augment Service
- #
- if config.AugmentService.type:
- augmentClass = namedClass(config.AugmentService.type)
- log.info("Configuring augment service of type: {augmentClass}",
- augmentClass=augmentClass)
- try:
- augmentService = augmentClass(**config.AugmentService.params)
- except IOError:
- log.error("Could not start augment service")
- raise
- else:
- augmentService = None
-
- #
- # Setup the group membership cacher
- #
- if config.GroupCaching.Enabled:
- groupMembershipCache = GroupMembershipCache(
- config.GroupCaching.MemcachedPool,
- expireSeconds=config.GroupCaching.ExpireSeconds)
- else:
- groupMembershipCache = None
-
- #
- # Setup the Directory
- #
- directories = []
-
- directoryClass = namedClass(config.DirectoryService.type)
- principalResourceClass = DirectoryPrincipalProvisioningResource
-
- log.info("Configuring directory service of type: {directoryType}",
- directoryType=config.DirectoryService.type)
-
- config.DirectoryService.params.augmentService = augmentService
- config.DirectoryService.params.groupMembershipCache = groupMembershipCache
- baseDirectory = directoryClass(config.DirectoryService.params)
-
- # Wait for the directory to become available
- while not baseDirectory.isAvailable():
- sleep(5)
-
- directories.append(baseDirectory)
-
- #
- # Setup the Locations and Resources Service
- #
- if config.ResourceService.Enabled:
- resourceClass = namedClass(config.ResourceService.type)
-
- log.info("Configuring resource service of type: {resourceClass}",
- resourceClass=resourceClass)
-
- config.ResourceService.params.augmentService = augmentService
- config.ResourceService.params.groupMembershipCache = groupMembershipCache
- resourceDirectory = resourceClass(config.ResourceService.params)
- resourceDirectory.realmName = baseDirectory.realmName
- directories.append(resourceDirectory)
-
- #
- # Add wiki directory service
- #
- if config.Authentication.Wiki.Enabled:
- wikiDirectory = WikiDirectoryService()
- wikiDirectory.realmName = baseDirectory.realmName
- directories.append(wikiDirectory)
-
- directory = AggregateDirectoryService(directories, groupMembershipCache)
-
- #
- # Use system-wide realm on OSX
- #
- try:
- import ServerFoundation
- realmName = ServerFoundation.XSAuthenticator.defaultRealm().encode("utf-8")
- directory.setRealm(realmName)
- except ImportError:
- pass
- log.info("Setting up principal collection: {cls}", cls=principalResourceClass)
- principalResourceClass("/principals/", directory)
- return directory
-
-
# MOVE2WHO -- should we move this class somewhere else?
class PrincipalCredentialChecker(object):
credentialInterfaces = (IPrincipalCredentials,)
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/augment.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/augment.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -81,6 +81,7 @@
"locations": "Location",
"resources": "Resource",
"addresses": "Address",
+ "wikis": "Wiki",
}
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/calendar.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/calendar.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -38,7 +38,7 @@
from twistedcaldav.directory.common import uidsResourceName, \
CommonUIDProvisioningResource, CommonHomeTypeProvisioningResource
-from twistedcaldav.directory.wiki import getWikiACL
+from txdav.who.wiki import getWikiACL
from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource, \
DAVResourceWithChildrenMixin
from twistedcaldav.resource import CalendarHomeResource
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -48,7 +48,7 @@
from twistedcaldav.directory.util import (
formatLink, formatLinks, formatPrincipals, formatList
)
-from twistedcaldav.directory.wiki import getWikiACL
+from txdav.who.wiki import getWikiACL
from twistedcaldav.extensions import (
ReadOnlyResourceMixIn, DAVPrincipalResource, DAVResourceWithChildrenMixin
)
@@ -1308,6 +1308,7 @@
Return a CUA for this principal, preferring in this order:
urn:uuid: form
mailto: form
+ /principal/__uids__/ form
first in calendarUserAddresses( ) list
"""
return self.record.canonicalCalendarUserAddress()
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/wiki.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/wiki.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -250,8 +250,8 @@
-def getWikiACL(resource, request):
- return succeed(None)
+# def getWikiACL(resource, request):
+# return succeed(None)
# @inlineCallbacks
# def getWikiACL(resource, request):
# """
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/sharing.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/sharing.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -44,7 +44,7 @@
from twistedcaldav import customxml, caldavxml
from twistedcaldav.config import config
from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
+from txdav.who.wiki import RecordType as WikiRecordType, WikiAccessLevel
from twistedcaldav.linkresource import LinkFollowerMixIn
@@ -269,15 +269,13 @@
if self._newStoreObject.direct():
owner = yield self.principalForUID(self._newStoreObject.ownerHome().uid())
sharee = yield self.principalForUID(self._newStoreObject.viewerHome().uid())
- if owner.record.recordType == WikiDirectoryService.recordType_wikis:
+ if owner.record.recordType == WikiRecordType.macOSXServerWiki:
# Access level comes from what the wiki has granted to the
# sharee
- userID = sharee.record.guid
- wikiID = owner.record.shortNames[0]
- access = (yield getWikiAccess(userID, wikiID))
- if access == "read":
+ access = (yield owner.record.accessForRecord(sharee.record))
+ if access == WikiAccessLevel.read:
returnValue("read-only")
- elif access in ("write", "admin"):
+ elif access == WikiAccessLevel.write:
returnValue("read-write")
else:
returnValue(None)
@@ -502,7 +500,7 @@
@inlineCallbacks
- def inviteSingleUserToShare(self, userid, cn, ace, summary, request): #@UnusedVariable
+ def inviteSingleUserToShare(self, userid, cn, ace, summary, request): #@UnusedVariable
# We currently only handle local users
sharee = yield self.principalForCalendarUserAddress(userid)
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/stdconfig.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/stdconfig.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -1257,7 +1257,13 @@
# Default DirectoryRealmName from ServerHostName
if not configDict.DirectoryRealmName:
- configDict.DirectoryRealmName = configDict.ServerHostName
+ # Use system-wide realm on OSX
+ try:
+ import ServerFoundation
+ realmName = ServerFoundation.XSAuthenticator.defaultRealm()
+ configDict.DirectoryRealmName = realmName
+ except ImportError:
+ configDict.DirectoryRealmName = configDict.ServerHostName
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/storebridge.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/storebridge.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -15,77 +15,89 @@
# limitations under the License.
##
+import collections
+import hashlib
+import time
+from urlparse import urlsplit, urljoin
+import uuid
+
from pycalendar.datetime import DateTime
-
from twext.enterprise.locking import LockTimeout
from twext.python.log import Logger
-from txweb2 import responsecode, http_headers, http
-from txweb2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
-from txweb2.dav.noneprops import NonePropertyStore
-from txweb2.dav.resource import TwistedACLInheritable, AccessDeniedError, \
- davPrivilegeSet
-from txweb2.dav.util import parentForURL, allDataFromStream, joinURL, davXMLFromStream
-from txweb2.filter.location import addLocation
-from txweb2.http import HTTPError, StatusResponse, Response
-from txweb2.http_headers import ETag, MimeType, MimeDisposition
-from txweb2.iweb import IResponse
-from txweb2.responsecode import \
- FORBIDDEN, NO_CONTENT, NOT_FOUND, CREATED, CONFLICT, PRECONDITION_FAILED, \
- BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE
-from txweb2.stream import ProducerStream, readStream, MemoryStream
-
from twisted.internet.defer import succeed, inlineCallbacks, returnValue, maybeDeferred
from twisted.internet.protocol import Protocol
from twisted.python.hashlib import md5
from twisted.python.util import FancyEqMixin
-
from twistedcaldav import customxml, carddavxml, caldavxml, ical
-from twistedcaldav.caldavxml import caldav_namespace, MaxAttendeesPerInstance, \
- MaxInstances, NoUIDConflict
+from twistedcaldav.caldavxml import (
+ caldav_namespace, MaxAttendeesPerInstance, MaxInstances, NoUIDConflict
+)
from twistedcaldav.carddavxml import carddav_namespace, NoUIDConflict as NovCardUIDConflict
from twistedcaldav.config import config
from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
-from twistedcaldav.ical import Component as VCalendar, Property as VProperty, \
- InvalidICalendarDataError, iCalendarProductID, Component
-from twistedcaldav.instance import InvalidOverriddenInstanceError, \
- TooManyInstancesError
+from twistedcaldav.ical import (
+ Component as VCalendar, Property as VProperty, InvalidICalendarDataError,
+ iCalendarProductID, Component
+)
+from twistedcaldav.instance import (
+ InvalidOverriddenInstanceError, TooManyInstancesError
+)
from twistedcaldav.memcachelock import MemcacheLockTimeoutError
from twistedcaldav.notifications import NotificationCollectionResource, NotificationResource
from twistedcaldav.resource import CalDAVResource, DefaultAlarmPropertyMixin
from twistedcaldav.scheduling_store.caldav.resource import ScheduleInboxResource
-from twistedcaldav.sharing import invitationBindStatusToXMLMap, \
- invitationBindModeToXMLMap
+from twistedcaldav.sharing import (
+ invitationBindStatusToXMLMap, invitationBindModeToXMLMap
+)
from twistedcaldav.util import bestAcceptType
from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError
-
from txdav.base.propertystore.base import PropertyName
-from txdav.caldav.icalendarstore import QuotaExceeded, AttachmentStoreFailed, \
- AttachmentStoreValidManagedID, AttachmentRemoveFailed, \
- AttachmentDropboxNotAllowed, InvalidComponentTypeError, \
- TooManyAttendeesError, InvalidCalendarAccessError, ValidOrganizerError, \
- InvalidPerUserDataMerge, \
- AttendeeAllowedError, ResourceDeletedError, InvalidAttachmentOperation, \
+from txdav.caldav.icalendarstore import (
+ QuotaExceeded, AttachmentStoreFailed,
+ AttachmentStoreValidManagedID, AttachmentRemoveFailed,
+ AttachmentDropboxNotAllowed, InvalidComponentTypeError,
+ TooManyAttendeesError, InvalidCalendarAccessError, ValidOrganizerError,
+ InvalidPerUserDataMerge,
+ AttendeeAllowedError, ResourceDeletedError, InvalidAttachmentOperation,
ShareeAllowedError, DuplicatePrivateCommentsError, InvalidSplit
-from txdav.carddav.iaddressbookstore import KindChangeNotAllowedError, \
- GroupWithUnsharedAddressNotAllowedError
-from txdav.common.datastore.sql_tables import _BIND_MODE_READ, _BIND_MODE_WRITE, \
+)
+from txdav.carddav.iaddressbookstore import (
+ KindChangeNotAllowedError, GroupWithUnsharedAddressNotAllowedError
+)
+from txdav.common.datastore.sql_tables import (
+ _BIND_MODE_READ, _BIND_MODE_WRITE,
_BIND_MODE_DIRECT, _BIND_STATUS_ACCEPTED
-from txdav.common.icommondatastore import NoSuchObjectResourceError, \
- TooManyObjectResourcesError, ObjectResourceTooBigError, \
- InvalidObjectResourceError, ObjectResourceNameNotAllowedError, \
- ObjectResourceNameAlreadyExistsError, UIDExistsError, \
- UIDExistsElsewhereError, InvalidUIDError, InvalidResourceMove, \
+)
+from txdav.common.icommondatastore import (
+ NoSuchObjectResourceError,
+ TooManyObjectResourcesError, ObjectResourceTooBigError,
+ InvalidObjectResourceError, ObjectResourceNameNotAllowedError,
+ ObjectResourceNameAlreadyExistsError, UIDExistsError,
+ UIDExistsElsewhereError, InvalidUIDError, InvalidResourceMove,
InvalidComponentForStoreError
+)
from txdav.idav import PropertyChangeNotAllowedError
+from txdav.who.wiki import RecordType as WikiRecordType
from txdav.xml import element as davxml, element
from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
+from txweb2 import responsecode, http_headers, http
+from txweb2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.dav.resource import (
+ TwistedACLInheritable, AccessDeniedError, davPrivilegeSet
+)
+from txweb2.dav.util import parentForURL, allDataFromStream, joinURL, davXMLFromStream
+from txweb2.filter.location import addLocation
+from txweb2.http import HTTPError, StatusResponse, Response
+from txweb2.http_headers import ETag, MimeType, MimeDisposition
+from txweb2.iweb import IResponse
+from txweb2.responsecode import (
+ FORBIDDEN, NO_CONTENT, NOT_FOUND, CREATED, CONFLICT, PRECONDITION_FAILED,
+ BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE
+)
+from txweb2.stream import ProducerStream, readStream, MemoryStream
-from urlparse import urlsplit, urljoin
-import collections
-import hashlib
-import time
-import uuid
+
"""
Wrappers to translate between the APIs in L{txdav.caldav.icalendarstore} and
L{txdav.carddav.iaddressbookstore} and those in L{twistedcaldav}.
@@ -93,6 +105,7 @@
log = Logger()
+
class _NewStorePropertiesWrapper(object):
"""
Wrap a new-style property store (a L{txdav.idav.IPropertyStore}) in the old-
@@ -1983,15 +1996,13 @@
"""
if invite.mode in (_BIND_MODE_DIRECT,):
ownerUID = invite.ownerUID
- owner = self.principalForUID(ownerUID)
+ owner = yield self.principalForUID(ownerUID)
shareeUID = invite.shareeUID
- if owner.record.recordType == WikiDirectoryService.recordType_wikis:
+ if owner.record.recordType == WikiRecordType.macOSXServerWiki:
# Access level comes from what the wiki has granted to the
# sharee
- sharee = self.principalForUID(shareeUID)
- userID = sharee.record.uid
- wikiID = owner.record.shortNames[0]
- access = (yield getWikiAccess(userID, wikiID))
+ sharee = yield self.principalForUID(shareeUID)
+ access = (yield owner.record.accessForRecord(sharee.record))
if access == "read":
returnValue("read-only")
elif access in ("write", "admin"):
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_sharing.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_sharing.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -19,30 +19,31 @@
from txweb2.http_headers import MimeType
from txweb2.iweb import IResponse
-from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twistedcaldav import customxml
-from twistedcaldav import sharing
from twistedcaldav.config import config
from twistedcaldav.directory.principal import DirectoryCalendarPrincipalResource
-from twistedcaldav.resource import CalDAVResource
-from twistedcaldav.sharing import WikiDirectoryService
from twistedcaldav.test.test_cache import StubResponseCacheResource
from twistedcaldav.test.util import norequest, StoreTestCase, SimpleStoreRequest
-from txdav.caldav.datastore.test.util import buildDirectory
from txdav.common.datastore.sql_tables import _BIND_MODE_DIRECT
from txdav.xml import element as davxml
from txdav.xml.parser import WebDAVDocument
from xml.etree.cElementTree import XML
+from txdav.who.wiki import (
+ DirectoryRecord as WikiDirectoryRecord,
+ DirectoryService as WikiDirectoryService,
+ RecordType as WikiRecordType,
+ WikiAccessLevel
+)
+sharedOwnerType = davxml.ResourceType.sharedownercalendar # @UndefinedVariable
+regularCalendarType = davxml.ResourceType.calendar # @UndefinedVariable
-sharedOwnerType = davxml.ResourceType.sharedownercalendar #@UndefinedVariable
-regularCalendarType = davxml.ResourceType.calendar #@UndefinedVariable
-
def normalize(x):
"""
Normalize some XML by parsing it, collapsing whitespace, and
@@ -63,8 +64,8 @@
self.fullName = name
self.guid = name
self.calendarUserAddresses = set((cuaddr,))
- if name.startswith("wiki-"):
- recordType = WikiDirectoryService.recordType_wikis
+ if name.startswith(WikiDirectoryService.uidPrefix):
+ recordType = WikiRecordType.macOSXServerWiki
else:
recordType = None
self.recordType = recordType
@@ -131,42 +132,45 @@
super(SharingTests, self).configure()
self.patch(config.Sharing, "Enabled", True)
self.patch(config.Sharing.Calendars, "Enabled", True)
+ self.patch(config.Authentication.Wiki, "Enabled", True)
@inlineCallbacks
def setUp(self):
yield super(SharingTests, self).setUp()
- def patched(c):
- """
- The decorated method is patched on L{CalDAVResource} for the
- duration of the test.
- """
- self.patch(CalDAVResource, c.__name__, c)
- return c
+ # FIXME: not sure what these were for:
- @patched
- def principalForCalendarUserAddress(resourceSelf, cuaddr):
- if "bogus" in cuaddr:
- return None
- else:
- return FakePrincipal(cuaddr, self)
+ # def patched(c):
+ # """
+ # The decorated method is patched on L{CalDAVResource} for the
+ # duration of the test.
+ # """
+ # self.patch(CalDAVResource, c.__name__, c)
+ # return c
- @patched
- def validUserIDForShare(resourceSelf, userid, request):
- """
- Temporary replacement for L{CalDAVResource.validUserIDForShare}
- that marks any principal without 'bogus' in its name.
- """
- result = principalForCalendarUserAddress(resourceSelf, userid)
- if result is None:
- return result
- return result.principalURL()
+ # @patched
+ # def principalForCalendarUserAddress(resourceSelf, cuaddr):
+ # if "bogus" in cuaddr:
+ # return None
+ # else:
+ # return FakePrincipal(cuaddr, self)
- @patched
- def principalForUID(resourceSelf, principalUID):
- return FakePrincipal("urn:uuid:" + principalUID, self)
+ # @patched
+ # def validUserIDForShare(resourceSelf, userid, request):
+ # """
+ # Temporary replacement for L{CalDAVResource.validUserIDForShare}
+ # that marks any principal without 'bogus' in its name.
+ # """
+ # result = principalForCalendarUserAddress(resourceSelf, userid)
+ # if result is None:
+ # return result
+ # return result.principalURL()
+ # @patched
+ # def principalForUID(resourceSelf, principalUID):
+ # return FakePrincipal("urn:uuid:" + principalUID, self)
+
self.resource = yield self._getResource()
@@ -321,7 +325,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
)
@@ -351,7 +355,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
)
@@ -400,7 +404,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadAccess()),
customxml.InviteStatusNoResponse(),
)
@@ -475,21 +479,21 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user03"),
- customxml.CommonName.fromString("USER03"),
+ customxml.CommonName.fromString("User 03"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user04"),
- customxml.CommonName.fromString("USER04"),
+ customxml.CommonName.fromString("User 04"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
@@ -533,14 +537,14 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user04"),
- customxml.CommonName.fromString("USER04"),
+ customxml.CommonName.fromString("User 04"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
@@ -584,14 +588,14 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user03"),
- customxml.CommonName.fromString("USER03"),
+ customxml.CommonName.fromString("User 03"),
customxml.InviteAccess(customxml.ReadAccess()),
customxml.InviteStatusNoResponse(),
),
@@ -701,7 +705,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
)
@@ -738,23 +742,24 @@
@inlineCallbacks
def wikiSetup(self):
"""
- Create a wiki called C{wiki-testing}, and share it with the user whose
+ Create a wiki called C{[wiki]testing}, and share it with the user whose
home is at /. Return the name of the newly shared calendar in the
sharee's home.
"""
- self._sqlCalendarStore._directoryService = buildDirectory(homes=("wiki-testing",))
+ # self._sqlCalendarStore._directoryService = buildDirectory(homes=("wiki-testing",))
wcreate = self._sqlCalendarStore.newTransaction("create wiki")
- yield wcreate.calendarHomeWithUID("wiki-testing", create=True)
+ yield wcreate.calendarHomeWithUID(
+ u"{prefix}testing".format(prefix=WikiDirectoryService.uidPrefix),
+ create=True
+ )
yield wcreate.commit()
- newService = WikiDirectoryService()
- newService.realmName = self.directory.realmName
- self.directory.addService(newService)
-
txn = self.transactionUnderTest()
- sharee = yield self.homeUnderTest(name="user01")
- sharer = yield txn.calendarHomeWithUID("wiki-testing")
+ sharee = yield self.homeUnderTest(name="user01", create=True)
+ sharer = yield txn.calendarHomeWithUID(
+ u"{prefix}testing".format(prefix=WikiDirectoryService.uidPrefix),
+ )
cal = yield sharer.calendarWithName("calendar")
sharedName = yield cal.shareWith(sharee, _BIND_MODE_DIRECT)
returnValue(sharedName)
@@ -767,13 +772,14 @@
to the sharee, so that delegates of the sharee get the same level of
access.
"""
+ sharedName = yield self.wikiSetup()
+ access = WikiAccessLevel.read
- access = "read"
- def stubWikiAccessMethod(userID, wikiID):
- return access
- self.patch(sharing, "getWikiAccess", stubWikiAccessMethod)
+ def stubAccessForRecord(*args):
+ return succeed(access)
- sharedName = yield self.wikiSetup()
+ self.patch(WikiDirectoryRecord, "accessForRecord", stubAccessForRecord)
+
request = SimpleStoreRequest(self, "GET", "/calendars/__uids__/user01/")
collection = yield request.locateResource("/calendars/__uids__/user01/" + sharedName)
@@ -782,7 +788,7 @@
self.assertFalse("<write/>" in acl.toxml())
# Simulate the wiki server granting Read-Write access
- access = "write"
+ access = WikiAccessLevel.write
acl = (yield collection.shareeAccessControlList(request))
self.assertTrue("<write/>" in acl.toxml())
@@ -795,10 +801,13 @@
un-share that collection.
"""
sharedName = yield self.wikiSetup()
- access = "write"
- def stubWikiAccessMethod(userID, wikiID):
- return access
- self.patch(sharing, "getWikiAccess", stubWikiAccessMethod)
+ access = WikiAccessLevel.write
+
+ def stubAccessForRecord(*args):
+ return succeed(access)
+
+ self.patch(WikiDirectoryRecord, "accessForRecord", stubAccessForRecord)
+
@inlineCallbacks
def listChildrenViaPropfind():
authRecord = yield self.directory.recordWithUID(u"user01")
@@ -814,9 +823,10 @@
seq.remove(shortest)
filtered = [elem[len(shortest):].rstrip("/") for elem in seq]
returnValue(filtered)
+
childNames = yield listChildrenViaPropfind()
self.assertIn(sharedName, childNames)
- access = "no-access"
+ access = WikiAccessLevel.none
childNames = yield listChildrenViaPropfind()
self.assertNotIn(sharedName, childNames)
@@ -841,7 +851,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
@@ -871,7 +881,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
@@ -915,7 +925,7 @@
customxml.InviteUser(
customxml.UID.fromString(""),
davxml.HRef.fromString("urn:uuid:user02"),
- customxml.CommonName.fromString("USER02"),
+ customxml.CommonName.fromString("User 02"),
customxml.InviteAccess(customxml.ReadWriteAccess()),
customxml.InviteStatusNoResponse(),
),
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -417,3 +417,7 @@
def verifyHTTPDigest(self, *args):
return self._baseRecord.verifyHTTPDigest(*args)
+
+
+ def accessForRecord(self, record):
+ return self._baseRecord.accessForRecord(record)
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/directory.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/directory.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/directory.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -178,6 +178,7 @@
"location": "locations",
"resource": "resources",
"user": "users",
+ "macOSXServerWiki": "wikis",
"readDelegateGroup": "readDelegateGroups",
"writeDelegateGroup": "writeDelegateGroups",
"readDelegatorGroup": "readDelegatorGroups",
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/util.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/util.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -23,7 +23,7 @@
from calendarserver.tap.util import getDBPool, storeFromConfig
from twext.who.idirectory import (
- RecordType, DirectoryConfigurationError, FieldName
+ RecordType, DirectoryConfigurationError
)
from twext.who.ldap import DirectoryService as LDAPDirectoryService
from twext.who.util import ConstantsContainer
@@ -36,6 +36,7 @@
FieldName as CalFieldName
)
from txdav.who.xml import DirectoryService as XMLDirectoryService
+from txdav.who.wiki import DirectoryService as WikiDirectoryService
log = Logger()
@@ -160,15 +161,29 @@
log.error("No directory service set up for users")
raise DirectoryConfigurationError
+ # Delegate service
delegateDirectory = DelegateDirectoryService(
userDirectory.realmName,
store
)
aggregatedServices.append(delegateDirectory)
+ # Wiki service
+ if config.Authentication.Wiki.Enabled:
+ aggregatedServices.append(
+ WikiDirectoryService(
+ userDirectory.realmName,
+ config.Authentication.Wiki.CollabHost,
+ config.Authentication.Wiki.CollabPort
+ )
+ )
+
+ # Aggregate service
aggregateDirectory = AggregateDirectoryService(
userDirectory.realmName, aggregatedServices
)
+
+ # Augment service
try:
fieldNames.append(CalFieldName)
augmented = AugmentedDirectoryService(
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/wiki.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/wiki.py 2014-03-28 00:46:42 UTC (rev 13014)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/wiki.py 2014-03-28 02:06:05 UTC (rev 13015)
@@ -23,21 +23,28 @@
"WikiAccessLevel",
]
-from twisted.python.constants import Names, NamedConstant
-from twisted.internet.defer import inlineCallbacks, returnValue, succeed
-from twisted.web.error import Error as WebError
-
+from calendarserver.platform.darwin.wiki import accessForUserToWiki
+from twext.internet.gaiendpoint import MultiFailure
from twext.python.log import Logger
-from twext.internet.gaiendpoint import MultiFailure
-from .idirectory import FieldName
from twext.who.directory import (
DirectoryService as BaseDirectoryService,
DirectoryRecord as BaseDirectoryRecord
)
+from twext.who.idirectory import FieldName as BaseFieldName
+from twext.who.util import ConstantsContainer
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twisted.python.constants import Names, NamedConstant
+from twisted.web.error import Error as WebError
+from txdav.who.idirectory import FieldName
+from txdav.who.directory import CalendarDirectoryRecordMixin
+from txdav.xml import element as davxml
from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.dav.resource import TwistedACLInheritable
+from txweb2.http import HTTPError, StatusResponse
-from calendarserver.platform.darwin.wiki import accessForUserToWiki
+log = Logger()
# FIXME: Should this be Flags?
@@ -59,13 +66,20 @@
Mac OS X Server Wiki directory service.
"""
- uidPrefix = "[wiki]"
+ uidPrefix = u"[wiki]"
recordType = RecordType
+ fieldName = ConstantsContainer((
+ BaseFieldName,
+ FieldName,
+ ))
- def __init__(self):
- BaseDirectoryService.__init__(self)
+
+ def __init__(self, realmName, wikiHost, wikiPort):
+ BaseDirectoryService.__init__(self, realmName)
+ self.wikiHost = wikiHost
+ self.wikiPort = wikiPort
self._recordsByName = {}
@@ -91,9 +105,10 @@
record = DirectoryRecord(
self,
{
- FieldName.uid: "{}{}".format(self.uidPrefix, name),
- FieldName.recordType: RecordType.macOSXServerWiki,
- FieldName.shortNames: [name],
+ self.fieldName.uid: u"{}{}".format(self.uidPrefix, name),
+ self.fieldName.recordType: RecordType.macOSXServerWiki,
+ self.fieldName.shortNames: [name],
+ self.fieldName.fullNames: [u"Wiki: {}".format(name)],
}
)
self._recordsByName[name] = record
@@ -114,8 +129,12 @@
return succeed(None)
+ def recordsFromExpression(self, expression, records=None):
+ return succeed(())
-class DirectoryRecord(BaseDirectoryRecord):
+
+
+class DirectoryRecord(BaseDirectoryRecord, CalendarDirectoryRecordMixin):
"""
Mac OS X Server Wiki directory record.
"""
@@ -133,9 +152,13 @@
"""
Look up the access level for a record in this wiki.
- @param user: The record to check access for.
+ @param user: The record to check access for. A value of None means
+ unauthenticated
"""
- guid = record.guid
+ if record is None:
+ uid = u"unauthenticated"
+ else:
+ uid = record.uid
try:
# FIXME: accessForUserToWiki() API is lame.
@@ -145,7 +168,7 @@
# When we do that note: isn't there a getPage() in twisted.web?
access = yield accessForUserToWiki(
- guid, self.shortNames[0],
+ uid, self.shortNames[0],
host=self.service.wikiHost,
port=self.service.wikiPort,
)
@@ -189,4 +212,124 @@
except KeyError:
self.log.error("Unknown wiki access level: {level}", level=access)
- return WikiAccessLevel.none
+ returnValue(WikiAccessLevel.none)
+
+
+ at inlineCallbacks
+def getWikiACL(resource, request):
+ """
+ Ask the wiki server we're paired with what level of access the authnUser has.
+
+ Returns an ACL.
+
+ Wiki authentication is a bit tricky because the end-user accessing a group
+ calendar may not actually be enabled for calendaring. Therefore in that
+ situation, the authzUser will have been replaced with the wiki principal
+ in locateChild( ), so that any changes the user makes will have the wiki
+ as the originator. The authnUser will always be the end-user.
+ """
+ from twistedcaldav.directory.principal import DirectoryPrincipalResource
+
+ if (
+ not hasattr(resource, "record") or
+ resource.record.recordType != RecordType.macOSXServerWiki
+ ):
+ returnValue(None)
+
+ if hasattr(request, 'wikiACL'):
+ returnValue(request.wikiACL)
+
+ wikiRecord = resource.record
+ wikiID = wikiRecord.shortNames[0]
+ userRecord = None
+
+ try:
+ url = str(request.authnUser.children[0])
+ principal = (yield request.locateResource(url))
+ if isinstance(principal, DirectoryPrincipalResource):
+ userRecord = principal.record
+ except:
+ # TODO: better error handling
+ pass
+
+ try:
+ access = yield wikiRecord.accessForRecord(userRecord)
+
+ # The ACL we returns has ACEs for the end-user and the wiki principal
+ # in case authzUser is the wiki principal.
+ if access == WikiAccessLevel.read:
+ request.wikiACL = davxml.ACL(
+ davxml.ACE(
+ request.authnUser,
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+
+ # We allow write-properties so that direct sharees can change
+ # e.g. calendar color properties
+ davxml.Privilege(davxml.WriteProperties()),
+ ),
+ TwistedACLInheritable(),
+ ),
+ davxml.ACE(
+ davxml.Principal(
+ davxml.HRef.fromString("/principals/wikis/%s/" % (wikiID,))
+ ),
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+ ),
+ TwistedACLInheritable(),
+ )
+ )
+ returnValue(request.wikiACL)
+
+ elif access in (WikiAccessLevel.write, WikiAccessLevel.admin):
+ request.wikiACL = davxml.ACL(
+ davxml.ACE(
+ request.authnUser,
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+ davxml.Privilege(davxml.Write()),
+ ),
+ TwistedACLInheritable(),
+ ),
+ davxml.ACE(
+ davxml.Principal(
+ davxml.HRef.fromString("/principals/wikis/%s/" % (wikiID,))
+ ),
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+ davxml.Privilege(davxml.Write()),
+ ),
+ TwistedACLInheritable(),
+ )
+ )
+ returnValue(request.wikiACL)
+
+ else: # "no-access":
+
+ if userRecord is None:
+ # Return a 401 so they have an opportunity to log in
+ response = (yield UnauthorizedResponse.makeResponse(
+ request.credentialFactories,
+ request.remoteAddr,
+ ))
+ raise HTTPError(response)
+
+ raise HTTPError(
+ StatusResponse(
+ responsecode.FORBIDDEN,
+ "You are not allowed to access this wiki"
+ )
+ )
+
+ except HTTPError:
+ # pass through the HTTPError we might have raised above
+ raise
+
+ except Exception, e:
+ log.error("Wiki ACL lookup failed: %s" % (e,))
+ raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "Wiki ACL lookup failed"))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140327/38472856/attachment-0001.html>
More information about the calendarserver-changes
mailing list