sharing/bday/templating: default config rework
This commit is contained in:
@@ -595,11 +595,11 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
||||
"help": "default permissions for map-based sharing",
|
||||
"type": rights_permission}),
|
||||
("conversion_bday_summary_template", {
|
||||
"value": "[{n:f} {n:g} {n:a}|{fn}|{nickname}] (BDAY)",
|
||||
"value": sharing.SHARING_BDAY_SUMMARY_TEMPLATE_DEFAULT,
|
||||
"help": "conversion bday summary template",
|
||||
"type": sharing.check_template}),
|
||||
("conversion_bday_description_template", {
|
||||
"value": "BDAY={year}-{month}-{day}",
|
||||
"value": sharing.SHARING_BDAY_DESCRIPTION_TEMPLATE_DEFAULT,
|
||||
"help": "conversion bday description template",
|
||||
"type": sharing.check_template}),
|
||||
("conversion_bday_alarm_trigger_template", {
|
||||
@@ -607,11 +607,11 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
||||
"help": "conversion bday alarm trigger template",
|
||||
"type": sharing.check_template_alarm_trigger}),
|
||||
("conversion_bday_categories", {
|
||||
"value": "Birthday",
|
||||
"value": sharing.SHARING_BDAY_CATEGORIES_DEFAULT,
|
||||
"help": "conversion bday categories",
|
||||
"type": str}),
|
||||
("conversion_bday_age_max", {
|
||||
"value": "99",
|
||||
"value": str(sharing.SHARING_BDAY_AGE_MAX_DEFAULT),
|
||||
"help": "conversion bday age max",
|
||||
"type": sharing.check_bday_max_age}),
|
||||
])),
|
||||
|
||||
@@ -38,7 +38,7 @@ from typing import (Any, Callable, List, MutableMapping, Optional, Sequence,
|
||||
import vobject
|
||||
|
||||
from radicale import storage # noqa:F401
|
||||
from radicale import pathutils, utils
|
||||
from radicale import pathutils, sharing, utils
|
||||
from radicale.item import filter as radicale_filter
|
||||
from radicale.log import logger
|
||||
|
||||
@@ -594,7 +594,6 @@ class Item:
|
||||
placeholder_mapping: dict = {}
|
||||
|
||||
bdayS = match[1] + match[2] + match[3]
|
||||
bdaySdesc = match[1] + "-" + match[2] + "-" + match[3]
|
||||
bdayY = int(match[1])
|
||||
bdayM = int(match[2])
|
||||
bdayD = int(match[3])
|
||||
@@ -649,37 +648,49 @@ class Item:
|
||||
else:
|
||||
item_ics.add('prodid').value = PRODID_CONVERTED
|
||||
|
||||
# create SUMMARY
|
||||
summary = name + " (BDAY)" # default
|
||||
if ShareActions is not None and 'config' in ShareActions:
|
||||
if 'conversion_bday_summary_template' in ShareActions['config']:
|
||||
summary = ShareActions['config']['conversion_bday_summary_template']
|
||||
summary = replace_placeholders(summary, placeholder_mapping)
|
||||
# prepare SUMMARY
|
||||
if ShareActions is not None and 'config' in ShareActions and 'conversion_bday_summary_template' in ShareActions['config']:
|
||||
summary = ShareActions['config']['conversion_bday_summary_template']
|
||||
elif ShareActions is not None and 'config_default' in ShareActions and 'conversion_bday_summary_template' in ShareActions['config_default']:
|
||||
summary = ShareActions['config_default']['conversion_bday_summary_template']
|
||||
else:
|
||||
summary = sharing.SHARING_BDAY_SUMMARY_TEMPLATE_DEFAULT # fallback
|
||||
summary = replace_placeholders(summary, placeholder_mapping)
|
||||
|
||||
# create DESCRIPTION
|
||||
description = "BDAY=" + bdaySdesc # default
|
||||
if ShareActions is not None and 'config' in ShareActions:
|
||||
if 'conversion_bday_description_template' in ShareActions['config']:
|
||||
description = ShareActions['config']['conversion_bday_description_template']
|
||||
description = replace_placeholders(description, placeholder_mapping)
|
||||
# prepare DESCRIPTION
|
||||
if ShareActions is not None and 'config' in ShareActions and 'conversion_bday_description_template' in ShareActions['config']:
|
||||
description = ShareActions['config']['conversion_bday_description_template']
|
||||
elif ShareActions is not None and 'config_default' in ShareActions and 'conversion_bday_description_template' in ShareActions['config_default']:
|
||||
description = ShareActions['config_default']['conversion_bday_description_template']
|
||||
else:
|
||||
description = sharing.SHARING_BDAY_DESCRIPTION_TEMPLATE_DEFAULT # fallback
|
||||
description = replace_placeholders(description, placeholder_mapping)
|
||||
|
||||
# create CATEGORIES
|
||||
categories: list = ["Birthday"] # default
|
||||
if ShareActions is not None and 'config' in ShareActions:
|
||||
if 'conversion_bday_categories' in ShareActions['config']:
|
||||
categories = ShareActions['config']['conversion_bday_categories'].split(',')
|
||||
if ShareActions is not None and 'config' in ShareActions and 'conversion_bday_categories' in ShareActions['config']:
|
||||
categories = ShareActions['config']['conversion_bday_categories'].split(',')
|
||||
elif ShareActions is not None and 'config_default' in ShareActions and 'conversion_bday_categories' in ShareActions['config_default']:
|
||||
categories = ShareActions['config_default']['conversion_bday_categories'].split(',')
|
||||
else:
|
||||
categories = sharing.SHARING_BDAY_CATEGORIES_DEFAULT.split(',') # fallback
|
||||
|
||||
# check ALARM
|
||||
alarm_trigger = "" # default
|
||||
if ShareActions is not None and 'config' in ShareActions:
|
||||
if ShareActions is not None and 'config' in ShareActions and 'conversion_bday_alarm_trigger_template' in ShareActions['config']:
|
||||
alarm_trigger = ShareActions['config']['conversion_bday_alarm_trigger_template']
|
||||
elif ShareActions is not None and 'config_default' in ShareActions and 'conversion_bday_alarm_trigger_template' in ShareActions['config_default']:
|
||||
alarm_trigger = ShareActions['config_default']['conversion_bday_alarm_trigger_template']
|
||||
else:
|
||||
alarm_trigger = "" # default
|
||||
|
||||
vevent_enable_age = False
|
||||
age_max = 0
|
||||
if "{age}" in summary or "{age}" in description or "age" in alarm_trigger:
|
||||
if ShareActions is not None and 'config' in ShareActions:
|
||||
if 'conversion_bday_age_max' in ShareActions['config']:
|
||||
age_max = ShareActions['config']['conversion_bday_age_max']
|
||||
if ShareActions is not None and 'config' in ShareActions and 'conversion_bday_age_max' in ShareActions['config']:
|
||||
age_max = ShareActions['config']['conversion_bday_age_max']
|
||||
elif ShareActions is not None and 'config_default' in ShareActions and 'conversion_bday_age_max' in ShareActions['config_default']:
|
||||
age_max = ShareActions['config_default']['conversion_bday_age_max']
|
||||
else:
|
||||
age_max = sharing.SHARING_BDAY_AGE_MAX_DEFAULT # fallback
|
||||
vevent_enable_age = True
|
||||
|
||||
# create UID
|
||||
|
||||
@@ -123,15 +123,19 @@ TOKEN_PATTERN_V1: str = "v1/[a-zA-Z0-9_\\-]{44}"
|
||||
|
||||
OVERLAY_PROPERTIES_WHITELIST: Sequence[str] = ("C:calendar-description", "ICAL:calendar-color", "CR:addressbook-description", "INF:addressbook-color", "D:displayname", "ICAL:calendar-order")
|
||||
|
||||
SHARING_BDAY_AGE_MAX: int = 199 # maximum age to prevent unexpected DoS by config
|
||||
SHARING_BDAY_AGE_MAX_LIMIT: int = 199 # maximum age to prevent unexpected DoS by config
|
||||
SHARING_BDAY_AGE_MAX_DEFAULT: int = 99
|
||||
SHARING_BDAY_SUMMARY_TEMPLATE_DEFAULT: str = "[{n:f} {n:g} {n:a}|{fn}|{nickname}] ({year}) (BDAY)"
|
||||
SHARING_BDAY_DESCRIPTION_TEMPLATE_DEFAULT: str = "BDAY={year}-{month}-{day}"
|
||||
SHARING_BDAY_CATEGORIES_DEFAULT: str = 'Birthday'
|
||||
|
||||
|
||||
def check_bday_max_age(data: Any) -> int:
|
||||
value = int(data)
|
||||
if value < 0:
|
||||
raise ValueError("value is negative: %d" % value)
|
||||
if value > SHARING_BDAY_AGE_MAX:
|
||||
raise ValueError("value exceeds maximum (%d): %d" % (SHARING_BDAY_AGE_MAX, value))
|
||||
if value > SHARING_BDAY_AGE_MAX_LIMIT:
|
||||
raise ValueError("value exceeds maximum (%d): %d" % (SHARING_BDAY_AGE_MAX_LIMIT, value))
|
||||
return value
|
||||
|
||||
|
||||
@@ -478,7 +482,7 @@ class BaseSharing:
|
||||
# autogenerate Actions if not existing
|
||||
if share['Actions'] is None or 'config' not in share['Actions']:
|
||||
share['Actions'] = {
|
||||
'config': {
|
||||
'config_default': {
|
||||
'conversion_bday_summary_template': self.conversion_bday_summary_template,
|
||||
'conversion_bday_description_template': self.conversion_bday_description_template,
|
||||
'conversion_bday_alarm_trigger_template': self.conversion_bday_alarm_trigger_template,
|
||||
@@ -492,7 +496,9 @@ class BaseSharing:
|
||||
# nothing to do
|
||||
pass
|
||||
else:
|
||||
share['Actions']['config'].update(
|
||||
if 'config_default' not in share['Actions']:
|
||||
share['Actions'].update({'config_default': {}})
|
||||
share['Actions']['config_default'].update(
|
||||
{'conversion_bday_summary_template': self.conversion_bday_summary_template}
|
||||
)
|
||||
|
||||
@@ -500,7 +506,9 @@ class BaseSharing:
|
||||
# nothing to do
|
||||
pass
|
||||
else:
|
||||
share['Actions']['config'].update(
|
||||
if 'config_default' not in share['Actions']:
|
||||
share['Actions'].update({'config_default': {}})
|
||||
share['Actions']['config_default'].update(
|
||||
{'conversion_bday_description_template': self.conversion_bday_description_template}
|
||||
)
|
||||
|
||||
@@ -508,7 +516,9 @@ class BaseSharing:
|
||||
# nothing to do
|
||||
pass
|
||||
else:
|
||||
share['Actions']['config'].update(
|
||||
if 'config_default' not in share['Actions']:
|
||||
share['Actions'].update({'config_default': {}})
|
||||
share['Actions']['config_default'].update(
|
||||
{'conversion_bday_alarm_trigger_template': self.conversion_bday_alarm_trigger_template}
|
||||
)
|
||||
|
||||
@@ -516,7 +526,9 @@ class BaseSharing:
|
||||
# nothing to do
|
||||
pass
|
||||
else:
|
||||
share['Actions']['config'].update(
|
||||
if 'config_default' not in share['Actions']:
|
||||
share['Actions'].update({'config_default': {}})
|
||||
share['Actions']['config_default'].update(
|
||||
{'conversion_bday_categories': self.conversion_bday_categories}
|
||||
)
|
||||
|
||||
@@ -524,7 +536,9 @@ class BaseSharing:
|
||||
# nothing to do
|
||||
pass
|
||||
else:
|
||||
share['Actions']['config'].update(
|
||||
if 'config_default' not in share['Actions']:
|
||||
share['Actions'].update({'config_default': {}})
|
||||
share['Actions']['config_default'].update(
|
||||
{'conversion_bday_age_max': self.conversion_bday_age_max}
|
||||
)
|
||||
|
||||
|
||||
@@ -5008,7 +5008,7 @@ permissions: RrWw""")
|
||||
assert "SUMMARY:Test-FN (BDAY)" in answer
|
||||
|
||||
self.configure({"sharing": {"conversion_bday_summary_template": "[{fn}|{n:f} {n:g} {n:a}|{nickname}] (Birthday)"}})
|
||||
logging.info("\n*** GET collection user format:text -> ok")
|
||||
logging.info("\n*** GET collection user format with fn+Birthday -> ok")
|
||||
_, headers, answer = self.request("GET", path_shared_2, login="user:userpw")
|
||||
assert "SUMMARY:Test-FN (Birthday)" in answer
|
||||
|
||||
@@ -5244,7 +5244,7 @@ permissions: RrWw""")
|
||||
logging.info("\n*** configuration test: conversion_bday_age_max > MAX")
|
||||
try:
|
||||
self.configure({"sharing": {
|
||||
"conversion_bday_age_max": (sharing.SHARING_BDAY_AGE_MAX + 1),
|
||||
"conversion_bday_age_max": (sharing.SHARING_BDAY_AGE_MAX_LIMIT + 1),
|
||||
}})
|
||||
except RuntimeError:
|
||||
pass
|
||||
@@ -5349,7 +5349,7 @@ permissions: RrWw""")
|
||||
json_dict['PathMapped'] = path_mapped
|
||||
json_dict['PathOrToken'] = path_shared_r
|
||||
json_dict['Actions'] = {"config": {
|
||||
"conversion_bday_age_max": (sharing.SHARING_BDAY_AGE_MAX + 1),
|
||||
"conversion_bday_age_max": (sharing.SHARING_BDAY_AGE_MAX_LIMIT + 1),
|
||||
}}
|
||||
_, headers, answer = self._sharing_api_json("map", "update", check=400, login="owner:ownerpw", json_dict=json_dict)
|
||||
|
||||
@@ -5371,7 +5371,7 @@ permissions: RrWw""")
|
||||
json_dict['PathMapped'] = path_mapped
|
||||
json_dict['PathOrToken'] = path_shared_r
|
||||
json_dict['Actions'] = {"config": {
|
||||
"conversion_bday_age_max": sharing.SHARING_BDAY_AGE_MAX,
|
||||
"conversion_bday_age_max": sharing.SHARING_BDAY_AGE_MAX_LIMIT,
|
||||
}}
|
||||
_, headers, answer = self._sharing_api_json("map", "update", check=200, login="owner:ownerpw", json_dict=json_dict)
|
||||
|
||||
@@ -5952,8 +5952,8 @@ permissions: RrWw""")
|
||||
logging.info("\n*** GET bday with token")
|
||||
_, answer = self.get(path_shared)
|
||||
assert "VCARD" not in answer
|
||||
assert "Test-FN-C3 (BDAY)" in answer
|
||||
assert "Test-FN (BDAY)" in answer
|
||||
assert "Test-FN-C3 (BDAY)" in answer # contact2
|
||||
assert "Test-FN (BDAY)" in answer # contact1
|
||||
|
||||
# verify content as owner
|
||||
logging.info("\n*** GET collection owner -> ok")
|
||||
|
||||
Reference in New Issue
Block a user