Code Repositories xandikos / 5ab68a6
Add a principal store type. Jelmer Vernooń≥ 2 years ago
2 changed file(s) with 56 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
3636
3737 STORE_TYPE_ADDRESSBOOK = 'addressbook'
3838 STORE_TYPE_CALENDAR = 'calendar'
39 STORE_TYPE_PRINCIPAL = 'principal'
3940 STORE_TYPE_OTHER = 'other'
4041 VALID_STORE_TYPES = (
4142 STORE_TYPE_ADDRESSBOOK,
4243 STORE_TYPE_CALENDAR,
44 STORE_TYPE_PRINCIPAL,
4345 STORE_TYPE_OTHER)
4446
4547 MIMETYPES = mimetypes.MimeTypes()
237239 def set_type(self, store_type):
238240 """Set store type.
239241
240 :param store_type: New store type (one of STORE_TYPE_ADDRESSBOOK,
241 STORE_TYPE_CALENDAR, STORE_TYPE_OTHER)
242 :param store_type: New store type (one of VALID_STORE_TYPES)
242243 """
243244 raise NotImplementedError(self.set_type)
244245
245246 def get_type(self):
246247 """Get type of this store.
247248
248 :return: one of [STORE_TYPE_ADDRESSBOOK, STORE_TYPE_CALENDAR,
249 STORE_TYPE_OTHER]
249 :return: one of VALID_STORE_TYPES
250250 """
251251 ret = STORE_TYPE_OTHER
252252 for (name, content_type, etag) in self.iter_with_etag():
578578 def set_type(self, store_type):
579579 """Set store type.
580580
581 :param store_type: New store type (one of STORE_TYPE_ADDRESSBOOK,
582 STORE_TYPE_CALENDAR, STORE_TYPE_OTHER)
581 :param store_type: New store type (one of VALID_STORE_TYPES)
583582 """
584583 config = self.repo.get_config()
585584 config.set(b'xandikos', b'type', store_type.encode(DEFAULT_ENCODING))
4444 NotStoreError,
4545 STORE_TYPE_ADDRESSBOOK,
4646 STORE_TYPE_CALENDAR,
47 STORE_TYPE_PRINCIPAL,
4748 STORE_TYPE_OTHER,
4849 )
4950 from xandikos.vcard import VCardFile
202203 elif resource_types == {carddav.ADDRESSBOOK_RESOURCE_TYPE,
203204 webdav.COLLECTION_RESOURCE_TYPE}:
204205 self.store.set_type(STORE_TYPE_ADDRESSBOOK)
206 elif resource_types == {webdav.PRINCIPAL_RESOURCE_TYPE}:
207 self.store.set_type(STORE_TYPE_PRINCIPAL)
205208 elif resource_types == {webdav.COLLECTION_RESOURCE_TYPE}:
206209 self.store.set_type(STORE_TYPE_OTHER)
207210 else:
352355 """A generic WebDAV collection."""
353356
354357
355 class CalendarResource(StoreBasedCollection, caldav.Calendar):
358 class CalendarCollection(StoreBasedCollection, caldav.Calendar):
356359
357360 def get_calendar_description(self):
358361 return self.store.get_description()
401404 raise KeyError
402405
403406
404 class AddressbookResource(StoreBasedCollection, carddav.Addressbook):
407 class AddressbookCollection(StoreBasedCollection, carddav.Addressbook):
405408
406409 def get_addressbook_description(self):
407410 return self.store.get_description()
592595 raise KeyError
593596
594597
595 class Principal(CollectionSetResource):
596 """Principal user resource."""
597
598 resource_types = (webdav.Collection.resource_types +
599 [webdav.PRINCIPAL_RESOURCE_TYPE])
598 class Principal(webdav.Principal):
600599
601600 def get_principal_url(self):
602601 return '.'
628627 """Get group membership URLs."""
629628 return []
630629
630 def get_calendar_user_type(self):
631 # TODO(jelmer)
632 return "INDIVIDUAL"
633
634 def get_calendar_proxy_read_for(self):
635 # TODO(jelmer)
636 return []
637
638 def get_calendar_proxy_write_for(self):
639 # TODO(jelmer)
640 return []
641
642
643 class PrincipalBare(CollectionSetResource, Principal):
644 """Principal user resource."""
645
646 resource_types = [webdav.PRINCIPAL_RESOURCE_TYPE]
647
631648 @classmethod
632649 def create(cls, backend, relpath):
633 p = super(Principal, cls).create(backend, relpath)
650 p = super(PrincipalBare, cls).create(backend, relpath)
634651 to_create = set()
635652 to_create.update(p.get_addressbook_home_set())
636653 to_create.update(p.get_calendar_home_set())
641658 pass
642659 return p
643660
644 def get_calendar_user_type(self):
645 # TODO(jelmer)
646 return "INDIVIDUAL"
647
648 def get_calendar_proxy_read_for(self):
649 # TODO(jelmer)
650 return []
651
652 def get_calendar_proxy_write_for(self):
653 # TODO(jelmer)
654 return []
655
656 def get_ctag(self):
657 raise KeyError
661
662 class PrincipalCollection(Collection, Principal):
663 """Principal user resource."""
664
665 resource_types = (webdav.Collection.resource_types +
666 [webdav.PRINCIPAL_RESOURCE_TYPE])
667
668 @classmethod
669 def create(cls, backend, relpath):
670 p = super(PrincipalCollection, cls).create(backend, relpath)
671 p.store.set_type(STORE_TYPE_PRINCIPAL)
672 to_create = set()
673 to_create.update(p.get_addressbook_home_set())
674 to_create.update(p.get_calendar_home_set())
675 for n in to_create:
676 try:
677 backend.create_collection(posixpath.join(relpath, n))
678 except FileExistsError:
679 pass
680 return p
658681
659682
660683 @functools.lru_cache(maxsize=STORE_CACHE_SIZE)
682705 return Collection(self, relpath, TreeGitStore.create(p))
683706
684707 def create_principal(self, relpath, create_defaults=False):
685 principal = Principal.create(self, relpath)
708 principal = PrincipalBare.create(self, relpath)
686709 self._mark_as_principal(relpath)
687710 if create_defaults:
688711 create_principal_defaults(self, principal)
695718 if p is None:
696719 return None
697720 if os.path.isdir(p):
698 if relpath in self._user_principals:
699 return Principal(self, relpath)
700721 try:
701722 store = open_store_from_path(p)
702723 except NotStoreError:
724 if relpath in self._user_principals:
725 return PrincipalBare(self, relpath)
703726 return CollectionSetResource(self, relpath)
704727 else:
705728 return {
706 STORE_TYPE_CALENDAR: CalendarResource,
707 STORE_TYPE_ADDRESSBOOK: AddressbookResource,
729 STORE_TYPE_CALENDAR: CalendarCollection,
730 STORE_TYPE_ADDRESSBOOK: AddressbookCollection,
731 STORE_TYPE_PRINCIPAL: PrincipalCollection,
708732 STORE_TYPE_OTHER: Collection
709733 }[store.get_type()](self, relpath, store)
710734 else: