mirror of
https://github.com/Kozea/Radicale.git
synced 2025-06-26 16:45:52 +00:00
Ability to create predefined calendar or(and) addressbook for new user
This commit is contained in:
parent
7340ddc9d2
commit
f7e01d55ed
4 changed files with 60 additions and 2 deletions
|
@ -870,6 +870,26 @@ Command that is run after changes to storage. Take a look at the
|
||||||
|
|
||||||
Default:
|
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
|
#### web
|
||||||
|
|
||||||
##### type
|
##### type
|
||||||
|
|
18
config
18
config
|
@ -103,6 +103,24 @@
|
||||||
# Example: ([ -d .git ] || git init) && git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
|
# Example: ([ -d .git ] || git init) && git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
|
||||||
#hook =
|
#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]
|
[web]
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ from radicale.app.propfind import ApplicationPartPropfind
|
||||||
from radicale.app.proppatch import ApplicationPartProppatch
|
from radicale.app.proppatch import ApplicationPartProppatch
|
||||||
from radicale.app.put import ApplicationPartPut
|
from radicale.app.put import ApplicationPartPut
|
||||||
from radicale.app.report import ApplicationPartReport
|
from radicale.app.report import ApplicationPartReport
|
||||||
|
from radicale.item import check_and_sanitize_props
|
||||||
from radicale.log import logger
|
from radicale.log import logger
|
||||||
|
|
||||||
# Combination of types.WSGIStartResponse and WSGI application return value
|
# 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):
|
if "W" in self._rights.authorization(user, principal_path):
|
||||||
with self._storage.acquire_lock("w", user):
|
with self._storage.acquire_lock("w", user):
|
||||||
try:
|
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:
|
except ValueError as e:
|
||||||
logger.warning("Failed to create principal "
|
logger.warning("Failed to create principal "
|
||||||
"collection %r: %s", user, e)
|
"collection %r: %s", user, e)
|
||||||
|
|
|
@ -26,6 +26,7 @@ Use ``load()`` to obtain an instance of ``Configuration`` for use with
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
@ -101,6 +102,12 @@ def _convert_to_bool(value: Any) -> bool:
|
||||||
return RawConfigParser.BOOLEAN_STATES[value.lower()]
|
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",)
|
INTERNAL_OPTIONS: Sequence[str] = ("_allow_extra",)
|
||||||
# Default configuration
|
# Default configuration
|
||||||
DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
||||||
|
@ -217,7 +224,11 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
||||||
("_filesystem_fsync", {
|
("_filesystem_fsync", {
|
||||||
"value": "True",
|
"value": "True",
|
||||||
"help": "sync all changes to filesystem during requests",
|
"help": "sync all changes to filesystem during requests",
|
||||||
"type": bool})])),
|
"type": bool}),
|
||||||
|
("predefined_collections", {
|
||||||
|
"value": "",
|
||||||
|
"help": "predefined user collections",
|
||||||
|
"type": json_str})])),
|
||||||
("hook", OrderedDict([
|
("hook", OrderedDict([
|
||||||
("type", {
|
("type", {
|
||||||
"value": "none",
|
"value": "none",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue