瀏覽代碼

Ability to create predefined calendar or(and) addressbook for new user

IM 1 年之前
父節點
當前提交
f7e01d55ed
共有 4 個文件被更改,包括 60 次插入2 次删除
  1. 20 0
      DOCUMENTATION.md
  2. 18 0
      config
  3. 10 1
      radicale/app/__init__.py
  4. 12 1
      radicale/config.py

+ 20 - 0
DOCUMENTATION.md

@@ -870,6 +870,26 @@ Command that is run after changes to storage. Take a look at the
 
 Default:
 
+##### predefined_collections
+
+Create predefined user collections
+
+ Example:
+
+     {
+       "def-addressbook": {
+          "D:displayname": "Personal Address Book",
+          "tag": "VADDRESSBOOK"
+       },
+       "def-calendar": {
+          "C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO",
+          "D:displayname": "Personal Calendar",
+          "tag": "VCALENDAR"
+       }
+     }
+
+Default:
+
 #### web
 
 ##### type

+ 18 - 0
config

@@ -103,6 +103,24 @@
 # Example: ([ -d .git ] || git init) && git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
 #hook =
 
+# Create predefined user collections
+#
+# json format:
+#
+#  {
+#    "def-addressbook": {
+#       "D:displayname": "Personal Address Book",
+#       "tag": "VADDRESSBOOK"
+#    },
+#    "def-calendar": {
+#       "C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO",
+#       "D:displayname": "Personal Calendar",
+#       "tag": "VCALENDAR"
+#    }
+#  }
+#
+#predefined_collections =
+
 
 [web]
 

+ 10 - 1
radicale/app/__init__.py

@@ -48,6 +48,7 @@ from radicale.app.propfind import ApplicationPartPropfind
 from radicale.app.proppatch import ApplicationPartProppatch
 from radicale.app.put import ApplicationPartPut
 from radicale.app.report import ApplicationPartReport
+from radicale.item import check_and_sanitize_props
 from radicale.log import logger
 
 # Combination of types.WSGIStartResponse and WSGI application return value
@@ -268,7 +269,15 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
                 if "W" in self._rights.authorization(user, principal_path):
                     with self._storage.acquire_lock("w", user):
                         try:
-                            self._storage.create_collection(principal_path)
+                            new_coll = self._storage.create_collection(principal_path)
+                            if new_coll:
+                                jsn_coll = self.configuration.get("storage", "predefined_collections")
+                                for (name_coll, props) in jsn_coll.items():
+                                    try:
+                                        checked_props = check_and_sanitize_props(props)
+                                        self._storage.create_collection(principal_path + name_coll, props=checked_props)
+                                    except ValueError as e:
+                                        logger.warning("Failed to create predefined collection %r: %s", name_coll, e)
                         except ValueError as e:
                             logger.warning("Failed to create principal "
                                            "collection %r: %s", user, e)

+ 12 - 1
radicale/config.py

@@ -26,6 +26,7 @@ Use ``load()`` to obtain an instance of ``Configuration`` for use with
 """
 
 import contextlib
+import json
 import math
 import os
 import string
@@ -101,6 +102,12 @@ def _convert_to_bool(value: Any) -> bool:
     return RawConfigParser.BOOLEAN_STATES[value.lower()]
 
 
+def json_str(value: Any) -> dict:
+    if not value:
+        return {}
+    return json.loads(value)
+
+
 INTERNAL_OPTIONS: Sequence[str] = ("_allow_extra",)
 # Default configuration
 DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
@@ -217,7 +224,11 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
         ("_filesystem_fsync", {
             "value": "True",
             "help": "sync all changes to filesystem during requests",
-            "type": bool})])),
+            "type": bool}),
+        ("predefined_collections", {
+            "value": "",
+            "help": "predefined user collections",
+            "type": json_str})])),
     ("hook", OrderedDict([
         ("type", {
             "value": "none",