sharing: add property overlay and update support
This commit is contained in:
@@ -28,6 +28,7 @@ Types of supported sharing configuration:
|
|||||||
* `HiddenByUser`: control by user
|
* `HiddenByUser`: control by user
|
||||||
* `TimestampCreated`: unixtime of creation
|
* `TimestampCreated`: unixtime of creation
|
||||||
* `TimestampUpdated`: unixtime of last update
|
* `TimestampUpdated`: unixtime of last update
|
||||||
|
* `Properties`: overlay properties (limited set whitelisted)
|
||||||
|
|
||||||
`Enabled*`: owner AND user have to enable a share to become usable
|
`Enabled*`: owner AND user have to enable a share to become usable
|
||||||
|
|
||||||
@@ -250,7 +251,9 @@ Update a share selected by `PathOrToken`
|
|||||||
| - | - | - |
|
| - | - | - |
|
||||||
| PathOrToken | yes | n/a |
|
| PathOrToken | yes | n/a |
|
||||||
| PathMapped | no | |
|
| PathMapped | no | |
|
||||||
|
| OwnerOrUser | yes | n/a |
|
||||||
| User | no | |
|
| User | no | |
|
||||||
|
| Properties | no | |
|
||||||
|
|
||||||
* Output: result status
|
* Output: result status
|
||||||
|
|
||||||
|
|||||||
@@ -345,6 +345,10 @@ def xml_propfind_response(
|
|||||||
human_tag = xmlutils.make_human_tag(tag)
|
human_tag = xmlutils.make_human_tag(tag)
|
||||||
tag_text = collection.get_meta(human_tag)
|
tag_text = collection.get_meta(human_tag)
|
||||||
if tag_text is not None:
|
if tag_text is not None:
|
||||||
|
if sharing:
|
||||||
|
# map from overlay
|
||||||
|
if sharing['Properties'][human_tag] is not None:
|
||||||
|
tag_text = sharing['Properties'][human_tag]
|
||||||
element.text = tag_text
|
element.text = tag_text
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from radicale.log import logger
|
|||||||
|
|
||||||
INTERNAL_TYPES: Sequence[str] = ("csv", "files", "none")
|
INTERNAL_TYPES: Sequence[str] = ("csv", "files", "none")
|
||||||
|
|
||||||
DB_FIELDS_V1: Sequence[str] = ('ShareType', 'PathOrToken', 'PathMapped', 'Owner', 'User', 'Permissions', 'EnabledByOwner', 'EnabledByUser', 'HiddenByOwner', 'HiddenByUser', 'TimestampCreated', 'TimestampUpdated')
|
DB_FIELDS_V1: Sequence[str] = ('ShareType', 'PathOrToken', 'PathMapped', 'Owner', 'User', 'Permissions', 'EnabledByOwner', 'EnabledByUser', 'HiddenByOwner', 'HiddenByUser', 'TimestampCreated', 'TimestampUpdated', 'Properties')
|
||||||
DB_FIELDS_V1_BOOL: Sequence[str] = ('EnabledByOwner', 'EnabledByUser', 'HiddenByOwner', 'HiddenByUser')
|
DB_FIELDS_V1_BOOL: Sequence[str] = ('EnabledByOwner', 'EnabledByUser', 'HiddenByOwner', 'HiddenByUser')
|
||||||
DB_FIELDS_V1_INT: Sequence[str] = ('TimestampCreated', 'TimestampUpdated')
|
DB_FIELDS_V1_INT: Sequence[str] = ('TimestampCreated', 'TimestampUpdated')
|
||||||
# ShareType: <token|map>
|
# ShareType: <token|map>
|
||||||
@@ -76,6 +76,7 @@ PATH_PATTERN: str = "([a-zA-Z0-9/.\\-]+)" # TODO: extend or find better source
|
|||||||
|
|
||||||
USER_PATTERN: str = "([a-zA-Z0-9@]+)" # TODO: extend or find better source
|
USER_PATTERN: str = "([a-zA-Z0-9@]+)" # TODO: extend or find better source
|
||||||
|
|
||||||
|
OVERLAY_PROPERTIES_WHITELIST: Sequence[str] = ("C:calendar-description", "ICAL:calendar-color", "CR:addressbook-description", "INF:addressbook-color")
|
||||||
|
|
||||||
def load(configuration: "config.Configuration") -> "BaseSharing":
|
def load(configuration: "config.Configuration") -> "BaseSharing":
|
||||||
"""Load the sharing database module chosen in configuration."""
|
"""Load the sharing database module chosen in configuration."""
|
||||||
@@ -178,20 +179,22 @@ class BaseSharing:
|
|||||||
Permissions: str = "r",
|
Permissions: str = "r",
|
||||||
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
||||||
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" create sharing """
|
""" create sharing """
|
||||||
return {"status": "not-implemented"}
|
return {"status": "not-implemented"}
|
||||||
|
|
||||||
def update_sharing(self,
|
def update_sharing(self,
|
||||||
ShareType: str,
|
ShareType: str,
|
||||||
PathOrToken: str,
|
PathOrToken: str,
|
||||||
Owner: Union[str, None] = None,
|
OwnerOrUser: str,
|
||||||
User: Union[str, None] = None,
|
User: Union[str, None] = None,
|
||||||
PathMapped: Union[str, None] = None,
|
PathMapped: Union[str, None] = None,
|
||||||
Permissions: Union[str, None] = None,
|
Permissions: Union[str, None] = None,
|
||||||
EnabledByOwner: Union[bool, None] = None,
|
EnabledByOwner: Union[bool, None] = None,
|
||||||
HiddenByOwner: Union[bool, None] = None,
|
HiddenByOwner: Union[bool, None] = None,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" update sharing """
|
""" update sharing """
|
||||||
return {"status": "not-implemented"}
|
return {"status": "not-implemented"}
|
||||||
|
|
||||||
@@ -391,6 +394,8 @@ class BaseSharing:
|
|||||||
PathOrToken: <path> (mandatory)
|
PathOrToken: <path> (mandatory)
|
||||||
User: <target_user> (mandatory)
|
User: <target_user> (mandatory)
|
||||||
|
|
||||||
|
action: (token|map)/update
|
||||||
|
|
||||||
action: (token|map)/(delete|disable|enable|hide|unhide)
|
action: (token|map)/(delete|disable|enable|hide|unhide)
|
||||||
PathOrToken: <path|token> (mandatory)
|
PathOrToken: <path|token> (mandatory)
|
||||||
|
|
||||||
@@ -481,7 +486,21 @@ class BaseSharing:
|
|||||||
# convert arrays into single value
|
# convert arrays into single value
|
||||||
request_data = {}
|
request_data = {}
|
||||||
for key in request_parsed:
|
for key in request_parsed:
|
||||||
request_data[key] = request_parsed[key][0]
|
if key == "Properties":
|
||||||
|
# Properties key value parser
|
||||||
|
properties_dict: dict = {}
|
||||||
|
for entry in request_parsed[key]:
|
||||||
|
m = re.search('^([^=]+)=([^=]+)$', entry)
|
||||||
|
if not m:
|
||||||
|
return httputils.bad_request("Invalid properties format in form")
|
||||||
|
token = m.group(1).lstrip('"\'').rstrip('"\'')
|
||||||
|
value = m.group(2).lstrip('"\'').rstrip('"\'')
|
||||||
|
properties_dict[token] = value
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("TRACE/sharing/API: converted Properties from form into dict: %r", properties_dict)
|
||||||
|
request_data[key] = properties_dict
|
||||||
|
else:
|
||||||
|
request_data[key] = request_parsed[key][0]
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/" + api_info + " (form): %r", f"{request_data}")
|
logger.debug("TRACE/" + api_info + " (form): %r", f"{request_data}")
|
||||||
else:
|
else:
|
||||||
@@ -518,6 +537,7 @@ class BaseSharing:
|
|||||||
HiddenByOwner: Union[bool, None] = None
|
HiddenByOwner: Union[bool, None] = None
|
||||||
EnabledByUser: Union[bool, None] = None
|
EnabledByUser: Union[bool, None] = None
|
||||||
HiddenByUser: Union[bool, None] = None
|
HiddenByUser: Union[bool, None] = None
|
||||||
|
Properties: Union[str, None] = None
|
||||||
|
|
||||||
# parameters sanity check
|
# parameters sanity check
|
||||||
for key in request_data:
|
for key in request_data:
|
||||||
@@ -552,12 +572,9 @@ class BaseSharing:
|
|||||||
|
|
||||||
# check for mandatory parameters
|
# check for mandatory parameters
|
||||||
if 'PathMapped' not in request_data:
|
if 'PathMapped' not in request_data:
|
||||||
if action == 'info':
|
if action in ['info', 'list', 'update']:
|
||||||
# ignored
|
# ignored
|
||||||
pass
|
pass
|
||||||
elif action == "list":
|
|
||||||
# optional
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
if ShareType == "token" and action != 'create':
|
if ShareType == "token" and action != 'create':
|
||||||
# optional
|
# optional
|
||||||
@@ -588,6 +605,13 @@ class BaseSharing:
|
|||||||
if 'Permissions' in request_data:
|
if 'Permissions' in request_data:
|
||||||
Permissions = request_data['Permissions']
|
Permissions = request_data['Permissions']
|
||||||
|
|
||||||
|
if 'Properties' in request_data:
|
||||||
|
# verify against whitelist
|
||||||
|
for entry in request_data['Properties']:
|
||||||
|
if entry not in OVERLAY_PROPERTIES_WHITELIST:
|
||||||
|
return httputils.bad_request("Property not supported to overlay: %r" % entry)
|
||||||
|
Properties = request_data['Properties']
|
||||||
|
|
||||||
if ShareType == "map":
|
if ShareType == "map":
|
||||||
if action == 'info':
|
if action == 'info':
|
||||||
# ignored
|
# ignored
|
||||||
@@ -691,7 +715,8 @@ class BaseSharing:
|
|||||||
Owner=Owner, User=Owner,
|
Owner=Owner, User=Owner,
|
||||||
Permissions=str(Permissions), # mandantory
|
Permissions=str(Permissions), # mandantory
|
||||||
EnabledByOwner=EnabledByOwner, HiddenByOwner=HiddenByOwner,
|
EnabledByOwner=EnabledByOwner, HiddenByOwner=HiddenByOwner,
|
||||||
Timestamp=Timestamp)
|
Timestamp=Timestamp,
|
||||||
|
Properties=Properties)
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/" + api_info + ": result=%r", result)
|
logger.debug("TRACE/" + api_info + ": result=%r", result)
|
||||||
|
|
||||||
@@ -747,7 +772,8 @@ class BaseSharing:
|
|||||||
Permissions=str(Permissions), # mandatory
|
Permissions=str(Permissions), # mandatory
|
||||||
EnabledByOwner=EnabledByOwner, HiddenByOwner=HiddenByOwner,
|
EnabledByOwner=EnabledByOwner, HiddenByOwner=HiddenByOwner,
|
||||||
EnabledByUser=EnabledByUser, HiddenByUser=HiddenByUser,
|
EnabledByUser=EnabledByUser, HiddenByUser=HiddenByUser,
|
||||||
Timestamp=Timestamp)
|
Timestamp=Timestamp,
|
||||||
|
Properties=Properties)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(api_info + ": unsupported for ShareType=%r", ShareType)
|
logger.error(api_info + ": unsupported for ShareType=%r", ShareType)
|
||||||
@@ -784,8 +810,10 @@ class BaseSharing:
|
|||||||
EnabledByOwner=EnabledByOwner,
|
EnabledByOwner=EnabledByOwner,
|
||||||
HiddenByOwner=HiddenByOwner,
|
HiddenByOwner=HiddenByOwner,
|
||||||
PathOrToken=str(PathOrToken), # verification above that it is not None
|
PathOrToken=str(PathOrToken), # verification above that it is not None
|
||||||
Owner=Owner,
|
OwnerOrUser=Owner,
|
||||||
Timestamp=Timestamp)
|
User=User,
|
||||||
|
Timestamp=Timestamp,
|
||||||
|
Properties=Properties)
|
||||||
|
|
||||||
elif ShareType == "map":
|
elif ShareType == "map":
|
||||||
result = self.update_sharing(
|
result = self.update_sharing(
|
||||||
@@ -795,8 +823,10 @@ class BaseSharing:
|
|||||||
EnabledByOwner=EnabledByOwner,
|
EnabledByOwner=EnabledByOwner,
|
||||||
HiddenByOwner=HiddenByOwner,
|
HiddenByOwner=HiddenByOwner,
|
||||||
PathOrToken=str(PathOrToken), # verification above that it is not None
|
PathOrToken=str(PathOrToken), # verification above that it is not None
|
||||||
Owner=Owner,
|
OwnerOrUser=Owner,
|
||||||
Timestamp=Timestamp)
|
User=User,
|
||||||
|
Timestamp=Timestamp,
|
||||||
|
Properties=Properties)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(api_info + ": unsupported for ShareType=%r", ShareType)
|
logger.error(api_info + ": unsupported for ShareType=%r", ShareType)
|
||||||
|
|||||||
@@ -128,8 +128,9 @@ class Sharing(sharing.BaseSharing):
|
|||||||
UserShare = row['User']
|
UserShare = row['User']
|
||||||
Permissions = row['Permissions']
|
Permissions = row['Permissions']
|
||||||
Hidden: bool = (row['HiddenByOwner'] or row['HiddenByUser'])
|
Hidden: bool = (row['HiddenByOwner'] or row['HiddenByUser'])
|
||||||
|
Properties = row['Properties']
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing: map %r to %r (Owner=%r User=%r Permissions=%r Hidden=%s)", PathOrToken, PathMapped, Owner, UserShare, Permissions, Hidden)
|
logger.debug("TRACE/sharing: map %r to %r (Owner=%r User=%r Permissions=%r Hidden=%s Properties=%r)", PathOrToken, PathMapped, Owner, UserShare, Permissions, Hidden, Properties)
|
||||||
return {
|
return {
|
||||||
"mapped": True,
|
"mapped": True,
|
||||||
"PathOrToken": PathOrToken,
|
"PathOrToken": PathOrToken,
|
||||||
@@ -137,7 +138,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
"Owner": Owner,
|
"Owner": Owner,
|
||||||
"User": UserShare,
|
"User": UserShare,
|
||||||
"Hidden": Hidden,
|
"Hidden": Hidden,
|
||||||
"Permissions": Permissions}
|
"Permissions": Permissions,
|
||||||
|
"Properties": Properties}
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def list_sharing(self,
|
def list_sharing(self,
|
||||||
@@ -205,7 +207,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
Permissions: str = "r",
|
Permissions: str = "r",
|
||||||
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
||||||
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" create sharing """
|
""" create sharing """
|
||||||
row: dict
|
row: dict
|
||||||
|
|
||||||
@@ -263,16 +266,17 @@ class Sharing(sharing.BaseSharing):
|
|||||||
def update_sharing(self,
|
def update_sharing(self,
|
||||||
ShareType: str,
|
ShareType: str,
|
||||||
PathOrToken: str,
|
PathOrToken: str,
|
||||||
Owner: Union[str, None] = None,
|
OwnerOrUser: str,
|
||||||
User: Union[str, None] = None,
|
User: Union[str, None] = None,
|
||||||
PathMapped: Union[str, None] = None,
|
PathMapped: Union[str, None] = None,
|
||||||
Permissions: Union[str, None] = None,
|
Permissions: Union[str, None] = None,
|
||||||
EnabledByOwner: Union[bool, None] = None,
|
EnabledByOwner: Union[bool, None] = None,
|
||||||
HiddenByOwner: Union[bool, None] = None,
|
HiddenByOwner: Union[bool, None] = None,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" update sharing """
|
""" update sharing """
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: PathOrToken=%r Owner=%r PathMapped=%r", ShareType, PathOrToken, Owner, PathMapped)
|
logger.debug("TRACE/sharing/%s/update: PathOrToken=%r OwnerOrUser=%r PathMapped=%r Properties=%r", ShareType, PathOrToken, OwnerOrUser, PathMapped, Properties)
|
||||||
|
|
||||||
# lookup token
|
# lookup token
|
||||||
found = False
|
found = False
|
||||||
@@ -293,12 +297,23 @@ class Sharing(sharing.BaseSharing):
|
|||||||
if found:
|
if found:
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: found index=%d", ShareType, index)
|
logger.debug("TRACE/sharing/%s/update: found index=%d", ShareType, index)
|
||||||
if Owner is not None and row['Owner'] != Owner:
|
|
||||||
return {"status": "permission-denied"}
|
if row['Owner'] != OwnerOrUser:
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("TRACE/sharing/%s/update: OwnerOrUser=%r not matching Owner=%r -> check now for matching User=%r", ShareType, OwnerOrUser, row['Owner'], row['User'])
|
||||||
|
if row['User'] == OwnerOrUser and PathMapped is None and Permissions is None and EnabledByOwner is None and HiddenByOwner is None and Properties is not None:
|
||||||
|
# user is only permitted to update Properties
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("TRACE/sharing/%s/update: OwnerOrUser=%r PathOrToken=%r index=%d is permitted to update Properties", ShareType, OwnerOrUser, PathOrToken, index)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return {"status": "permission-denied"}
|
||||||
|
|
||||||
if User is not None and row['User'] != User:
|
if User is not None and row['User'] != User:
|
||||||
return {"status": "permission-denied"}
|
return {"status": "permission-denied"}
|
||||||
|
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: Owner=%r PathOrToken=%r index=%d", ShareType, Owner, PathOrToken, index)
|
logger.debug("TRACE/sharing/%s/update: OwnerOrUser=%r PathOrToken=%r index=%d", ShareType, OwnerOrUser, PathOrToken, index)
|
||||||
logger.debug("TRACE/sharing/%s/update: orig row=%r", ShareType, row)
|
logger.debug("TRACE/sharing/%s/update: orig row=%r", ShareType, row)
|
||||||
|
|
||||||
# CSV: remove+adjust+readd
|
# CSV: remove+adjust+readd
|
||||||
@@ -312,6 +327,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
row["EnabledByOwner"] = EnabledByOwner
|
row["EnabledByOwner"] = EnabledByOwner
|
||||||
if HiddenByOwner is not None:
|
if HiddenByOwner is not None:
|
||||||
row["HiddenByOwner"] = HiddenByOwner
|
row["HiddenByOwner"] = HiddenByOwner
|
||||||
|
if Properties is not None:
|
||||||
|
row["Properties"] = Properties
|
||||||
# update timestamp
|
# update timestamp
|
||||||
row["TimestampUpdated"] = Timestamp
|
row["TimestampUpdated"] = Timestamp
|
||||||
|
|
||||||
@@ -322,7 +339,7 @@ class Sharing(sharing.BaseSharing):
|
|||||||
self._sharing_cache.pop(index)
|
self._sharing_cache.pop(index)
|
||||||
self._sharing_cache.append(row)
|
self._sharing_cache.append(row)
|
||||||
|
|
||||||
with self._storage.acquire_lock("w", Owner, path=self._sharing_db_file):
|
with self._storage.acquire_lock("w", OwnerOrUser, path=self._sharing_db_file):
|
||||||
if self._write_csv(self._sharing_db_file):
|
if self._write_csv(self._sharing_db_file):
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: write CSV done", ShareType)
|
logger.debug("TRACE/sharing/%s/update: write CSV done", ShareType)
|
||||||
|
|||||||
@@ -122,8 +122,9 @@ class Sharing(sharing.BaseSharing):
|
|||||||
UserShare = row['User']
|
UserShare = row['User']
|
||||||
Permissions = row['Permissions']
|
Permissions = row['Permissions']
|
||||||
Hidden: bool = (row['HiddenByOwner'] or row['HiddenByUser'])
|
Hidden: bool = (row['HiddenByOwner'] or row['HiddenByUser'])
|
||||||
|
Properties = row['Properties']
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing: map %r to %r (Owner=%r User=%r Permissions=%r Hidden=%s)", PathOrToken, PathMapped, Owner, UserShare, Permissions, Hidden)
|
logger.debug("TRACE/sharing: map %r to %r (Owner=%r User=%r Permissions=%r Hidden=%s Properties=%r)", PathOrToken, PathMapped, Owner, UserShare, Permissions, Hidden, Properties)
|
||||||
return {
|
return {
|
||||||
"mapped": True,
|
"mapped": True,
|
||||||
"PathOrToken": PathOrToken,
|
"PathOrToken": PathOrToken,
|
||||||
@@ -131,7 +132,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
"Owner": Owner,
|
"Owner": Owner,
|
||||||
"User": UserShare,
|
"User": UserShare,
|
||||||
"Hidden": Hidden,
|
"Hidden": Hidden,
|
||||||
"Permissions": Permissions}
|
"Permissions": Permissions,
|
||||||
|
"Properties": Properties}
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -214,7 +216,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
Permissions: str = "r",
|
Permissions: str = "r",
|
||||||
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
EnabledByOwner: bool = False, EnabledByUser: bool = False,
|
||||||
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
HiddenByOwner: bool = True, HiddenByUser: bool = True,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" create sharing """
|
""" create sharing """
|
||||||
row: dict
|
row: dict
|
||||||
|
|
||||||
@@ -258,16 +261,17 @@ class Sharing(sharing.BaseSharing):
|
|||||||
def update_sharing(self,
|
def update_sharing(self,
|
||||||
ShareType: str,
|
ShareType: str,
|
||||||
PathOrToken: str,
|
PathOrToken: str,
|
||||||
Owner: Union[str, None] = None,
|
OwnerOrUser: str,
|
||||||
User: Union[str, None] = None,
|
User: Union[str, None] = None,
|
||||||
PathMapped: Union[str, None] = None,
|
PathMapped: Union[str, None] = None,
|
||||||
Permissions: Union[str, None] = None,
|
Permissions: Union[str, None] = None,
|
||||||
EnabledByOwner: Union[bool, None] = None,
|
EnabledByOwner: Union[bool, None] = None,
|
||||||
HiddenByOwner: Union[bool, None] = None,
|
HiddenByOwner: Union[bool, None] = None,
|
||||||
Timestamp: int = 0) -> dict:
|
Timestamp: int = 0,
|
||||||
|
Properties: Union[str, None] = None) -> dict:
|
||||||
""" update sharing """
|
""" update sharing """
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: PathOrToken=%r Owner=%r User=%r", ShareType, PathOrToken, Owner, User)
|
logger.debug("TRACE/sharing/%s/update: PathOrToken=%r OwnerOrUser=%r User=%r Properties=%r", ShareType, PathOrToken, OwnerOrUser, User, Properties)
|
||||||
|
|
||||||
sharing_config_file = os.path.join(self._sharing_db_path_ShareType[ShareType], self._encode_path(PathOrToken))
|
sharing_config_file = os.path.join(self._sharing_db_path_ShareType[ShareType], self._encode_path(PathOrToken))
|
||||||
|
|
||||||
@@ -275,7 +279,7 @@ class Sharing(sharing.BaseSharing):
|
|||||||
return {"status": "not-found"}
|
return {"status": "not-found"}
|
||||||
|
|
||||||
# read content
|
# read content
|
||||||
with self._storage.acquire_lock("w", Owner, path=sharing_config_file):
|
with self._storage.acquire_lock("w", OwnerOrUser, path=sharing_config_file):
|
||||||
# read file
|
# read file
|
||||||
with open(sharing_config_file, "rb") as fb:
|
with open(sharing_config_file, "rb") as fb:
|
||||||
(version, row) = pickle.load(fb)
|
(version, row) = pickle.load(fb)
|
||||||
@@ -286,8 +290,17 @@ class Sharing(sharing.BaseSharing):
|
|||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("TRACE/sharing/%s/update: check: %r", ShareType, row)
|
logger.debug("TRACE/sharing/%s/update: check: %r", ShareType, row)
|
||||||
|
|
||||||
if Owner is not None and row['Owner'] != Owner:
|
if row['Owner'] != OwnerOrUser:
|
||||||
return {"status": "permission-denied"}
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("TRACE/sharing/%s/update: OwnerOrUser=%r not matching Owner=%r -> check now for matching User=%r", ShareType, OwnerOrUser, row['Owner'], row['User'])
|
||||||
|
if row['User'] == OwnerOrUser and PathMapped is None and Permissions is None and EnabledByOwner is None and HiddenByOwner is None and Properties is not None:
|
||||||
|
# user is only permitted to update Properties
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("TRACE/sharing/%s/update: OwnerOrUser=%r PathOrToken=%r is permitted to update Properties", ShareType, OwnerOrUser, PathOrToken)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return {"status": "permission-denied"}
|
||||||
|
|
||||||
if User is not None and row['User'] != User:
|
if User is not None and row['User'] != User:
|
||||||
return {"status": "permission-denied"}
|
return {"status": "permission-denied"}
|
||||||
|
|
||||||
@@ -304,6 +317,8 @@ class Sharing(sharing.BaseSharing):
|
|||||||
row["EnabledByOwner"] = EnabledByOwner
|
row["EnabledByOwner"] = EnabledByOwner
|
||||||
if HiddenByOwner is not None:
|
if HiddenByOwner is not None:
|
||||||
row["HiddenByOwner"] = HiddenByOwner
|
row["HiddenByOwner"] = HiddenByOwner
|
||||||
|
if Properties is not None:
|
||||||
|
row["Properties"] = Properties
|
||||||
# update timestamp
|
# update timestamp
|
||||||
row["TimestampUpdated"] = Timestamp
|
row["TimestampUpdated"] = Timestamp
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user