[CalendarServer-changes] [6038] CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore
source_changes at macosforge.org
source_changes at macosforge.org
Tue Aug 10 14:33:53 PDT 2010
Revision: 6038
http://trac.macosforge.org/projects/calendarserver/changeset/6038
Author: glyph at apple.com
Date: 2010-08-10 14:33:52 -0700 (Tue, 10 Aug 2010)
Log Message:
-----------
invites table and most of the sharing invitesDB implementation
Modified Paths:
--------------
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres_schema_v1.sql
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py 2010-08-10 21:32:27 UTC (rev 6037)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py 2010-08-10 21:33:52 UTC (rev 6038)
@@ -1,4 +1,4 @@
-# -*- test-case-name: txcaldav.calendarstore.test.test_postgres.SQLStorageTests -*- # FIXME: verify
+# -*- test-case-name: txcaldav.calendarstore.test.test_postgres -*-
##
# Copyright (c) 2010 Apple Inc. All rights reserved.
#
@@ -65,21 +65,25 @@
from twext.python.vcomponent import VComponent
from twistedcaldav.vcard import Component as VCard
+from twistedcaldav.sharing import Invite
v1_schema = getModule(__name__).filePath.sibling(
"postgres_schema_v1.sql").getContent()
-# these are in the schema, and should probably be discovered from there
-# somehow.
+# FIXME: these constants are in the schema, and should probably be discovered
+# from there somehow.
+_BIND_STATUS_INVITED = 0
_BIND_STATUS_ACCEPTED = 1
_BIND_STATUS_DECLINED = 2
_ATTACHMENTS_MODE_WRITE = 1
_BIND_MODE_OWN = 0
+_BIND_MODE_READ = 1
+_BIND_MODE_WRITE = 2
@@ -338,9 +342,12 @@
return None
+
def _pathToName(path):
return path.rsplit(".", 1)[0].split("-", 3)[-1]
+
+
class PostgresAttachment(object):
implements(IAttachment)
@@ -455,6 +462,10 @@
class PostgresLegacyInvitesEmulator(object):
+ """
+ Emulator for the implicit interface specified by
+ L{twistedcaldav.sharing.InvitesDatabase}.
+ """
def __init__(self, calendar):
@@ -467,42 +478,148 @@
def create(self):
- return
+ "No-op, because the index implicitly always exists in the database."
def remove(self):
- return
+ "No-op, because the index implicitly always exists in the database."
def allRecords(self):
- return []
+ for row in self._txn.execSQL(
+ """
+ select
+ INVITE.INVITE_UID, INVITE.NAME, INVITE.SENDER_ADDRESS,
+ CALENDAR_HOME.OWNER_UID, CALENDAR_BIND.BIND_MODE,
+ CALENDAR_BIND.BIND_STATUS, CALENDAR_BIND.MESSAGE
+ from
+ INVITE, CALENDAR_HOME, CALENDAR_BIND
+ where
+ INVITE.RESOURCE_ID = %s and
+ INVITE.HOME_RESOURCE_ID =
+ CALENDAR_HOME.RESOURCE_ID and
+ CALENDAR_BIND.CALENDAR_RESOURCE_ID =
+ INVITE.RESOURCE_ID and
+ CALENDAR_BIND.CALENDAR_HOME_RESOURCE_ID =
+ INVITE.HOME_RESOURCE_ID
+ order by
+ INVITE.NAME asc
+ """, [self._calendar._resourceID]):
+ [inviteuid, common_name, userid, ownerUID,
+ bindMode, bindStatus, summary] = row
+ # FIXME: this is really the responsibility of the protocol layer.
+ state = {
+ _BIND_STATUS_INVITED: "NEEDS-ACTION",
+ _BIND_STATUS_ACCEPTED: "ACCEPTED",
+ _BIND_STATUS_DECLINED: "DECLINED"
+ }[bindStatus]
+ access = {
+ _BIND_MODE_READ: "read-only",
+ _BIND_MODE_WRITE: "read-write"
+ }[bindMode]
+ principalURL = "/principals/__uids__/" + ownerUID
+ yield Invite(
+ inviteuid, userid, principalURL, common_name,
+ access, state, summary
+ )
def recordForUserID(self, userid):
- return
+ raise NotImplementedError("recordForUserID")
def recordForPrincipalURL(self, principalURL):
- return None
+ for record in self.allRecords():
+ if record.principalURL == principalURL:
+ return record
def recordForInviteUID(self, inviteUID):
- return None
+ raise NotImplementedError("recordForInviteUID")
+
def addOrUpdateRecord(self, record):
- return
+ bindMode = {'read-only': _BIND_MODE_READ,
+ 'read-write': _BIND_MODE_WRITE}[record.access]
+ bindStatus = {
+ "NEEDS-ACTION": _BIND_STATUS_INVITED,
+ "ACCEPTED": _BIND_STATUS_ACCEPTED,
+ "DECLINED": _BIND_STATUS_DECLINED,
+ }[record.state]
+ # principalURL is derived from a directory record's principalURL() so
+ # it will always contain the UID.
+ principalUID = record.principalURL.split("/")[-1]
+ shareeHome = self._txn.calendarHomeWithUID(principalUID, create=True)
+ rows = self._txn.execSQL(
+ "select RESOURCE_ID, HOME_RESOURCE_ID from INVITE where INVITE_UID = %s",
+ [record.inviteuid]
+ )
+ if rows:
+ [[resourceID, homeResourceID]] = rows
+ # Invite(inviteuid, userid, principalURL, common_name, access, state, summary)
+ self._txn.execSQL("""
+ update CALENDAR_BIND set BIND_MODE = %s,
+ BIND_STATUS = %s, MESSAGE = %s
+ where
+ CALENDAR_RESOURCE_ID = %s and
+ CALENDAR_HOME_RESOURCE_ID = %s
+ """, [bindMode, bindStatus, record.summary,
+ resourceID, homeResourceID])
+ self._txn.execSQL("""
+ update INVITE set NAME = %s, SENDER_ADDRESS = %s
+ where INVITE_UID = %s
+ """,
+ [record.name, record.userid, record.inviteuid]
+ )
+ else:
+ self._txn.execSQL(
+ """
+ insert into CALENDAR_BIND
+ (
+ CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID,
+ CALENDAR_RESOURCE_NAME, BIND_MODE, BIND_STATUS,
+ SEEN_BY_OWNER, SEEN_BY_SHAREE, MESSAGE
+ )
+ values (%s, %s, %s, %s, %s, %s, %s, %s)
+ """,
+ [
+ shareeHome._resourceID,
+ self._calendar._resourceID,
+ None, # this is NULL because it is not bound yet, let's be
+ # explicit about that.
+ bindMode,
+ bindStatus,
+ False,
+ False,
+ record.summary
+ ])
+ self._txn.execSQL(
+ """
+ insert into INVITE (
+ INVITE_UID, NAME,
+ HOME_RESOURCE_ID, RESOURCE_ID,
+ SENDER_ADDRESS
+ )
+ values (%s, %s, %s, %s, %s)
+ """,
+ [
+ record.inviteuid, record.name,
+ shareeHome._resourceID, self._calendar._resourceID,
+ record.userid
+ ])
def removeRecordForUserID(self, userid):
- return
+ raise NotImplementedError("removeRecordForUserID")
def removeRecordForPrincipalURL(self, principalURL):
- return
+ raise NotImplementedError("removeRecordForPrincipalURL")
def removeRecordForInviteUID(self, inviteUID):
- return
+ self._txn.execSQL("delete from INVITE where INVITE_UID = %s",
+ [inviteUID])
@@ -553,7 +670,7 @@
def addOrUpdateRecord(self, record):
- pass
+ print record
# self._db_execute("""insert or replace into SHARES (SHAREUID, SHARETYPE, HOSTURL, LOCALNAME, SUMMARY)
# values (:1, :2, :3, :4, :5)
@@ -621,7 +738,30 @@
return []
+ def bruteForceSearch(self):
+ return self._txn.execSQL(
+ "select RESOURCE_NAME, ICALENDAR_UID, ICALENDAR_TYPE from "
+ "CALENDAR_OBJECT where CALENDAR_RESOURCE_ID = %s",
+ [self.calendar._resourceID]
+ )
+
+ def resourcesExist(self, names):
+ return list(set(names).intersection(
+ set(self.calendar.listCalendarObjects())))
+
+
+ def resourceExists(self, name):
+ return bool(
+ self._txn.execSQL(
+ "select RESOURCE_NAME from CALENDAR_OBJECT where "
+ "RESOURCE_NAME = %s and CALENDAR_RESOURCE_ID = %s",
+ [name, self.calendar._resourceID]
+ )
+ )
+
+
+
class PostgresCalendar(object):
implements(ICalendar)
@@ -1330,7 +1470,7 @@
return self._home
- def listAddressBookObjects(self):
+ def listAddressbookObjects(self):
# FIXME: see listChildren
rows = self._txn.execSQL(
"select RESOURCE_NAME from "
@@ -1341,7 +1481,7 @@
def addressbookObjects(self):
- for name in self.listAddressBookObjects():
+ for name in self.listAddressbookObjects():
yield self.addressbookObjectWithName(name)
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres_schema_v1.sql
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres_schema_v1.sql 2010-08-10 21:32:27 UTC (rev 6037)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres_schema_v1.sql 2010-08-10 21:33:52 UTC (rev 6038)
@@ -25,6 +25,19 @@
);
+------------------------
+-- Sharing Invitation --
+------------------------
+
+create table INVITE (
+ INVITE_UID varchar(255) not null,
+ NAME varchar(255) not null,
+ SENDER_ADDRESS varchar(255) not null,
+ HOME_RESOURCE_ID varchar(255) not null,
+ RESOURCE_ID varchar(255) not null
+);
+
+
-------------------
-- Calendar Bind --
-------------------
@@ -34,12 +47,16 @@
create table CALENDAR_BIND (
CALENDAR_HOME_RESOURCE_ID varchar(255) not null references CALENDAR_HOME,
CALENDAR_RESOURCE_ID varchar(255) not null references CALENDAR,
- CALENDAR_RESOURCE_NAME varchar(255) not null,
+
+ -- An invitation which hasn't been accepted yet will not yet have a resource
+ -- name, so this field may be null.
+
+ CALENDAR_RESOURCE_NAME varchar(255),
BIND_MODE integer not null, -- enum CALENDAR_BIND_MODE
BIND_STATUS integer not null, -- enum CALENDAR_BIND_STATUS
SEEN_BY_OWNER bool not null,
SEEN_BY_SHAREE bool not null,
- MESSAGE text, -- FIXME: xml?
+ MESSAGE text,
primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID),
unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)
@@ -83,8 +100,13 @@
ORGANIZER varchar(255),
ORGANIZER_OBJECT varchar(255) references CALENDAR_OBJECT,
- unique(CALENDAR_RESOURCE_ID, RESOURCE_NAME),
- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+ unique(CALENDAR_RESOURCE_ID, RESOURCE_NAME)
+
+ -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+ -- calendar objects, this constraint has to be selectively enforced by the
+ -- application layer.
+
+ -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
);
-- Enumeration of attachment modes
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py 2010-08-10 21:32:27 UTC (rev 6037)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py 2010-08-10 21:33:52 UTC (rev 6038)
@@ -124,7 +124,8 @@
"%s schema-cleanup" % (testCase.id(),)
)
cursor = cleanupConn.cursor()
- tables = ['RESOURCE_PROPERTY',
+ tables = ['INVITE',
+ 'RESOURCE_PROPERTY',
'ATTACHMENT',
'ADDRESSBOOK_OBJECT',
'CALENDAR_OBJECT',
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100810/22f85503/attachment-0001.html>
More information about the calendarserver-changes
mailing list