Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add updating of backup versions #4580

Merged
merged 6 commits into from Feb 11, 2019
Merged
Diff settings

Always

Just for now

Copy path View file
@@ -0,0 +1 @@
Add ability to update backup versions
@@ -19,7 +19,13 @@

from twisted.internet import defer

from synapse.api.errors import NotFoundError, RoomKeysVersionError, StoreError
from synapse.api.errors import (
Codes,
NotFoundError,
RoomKeysVersionError,
StoreError,
SynapseError
)
from synapse.util.async_helpers import Linearizer

logger = logging.getLogger(__name__)
@@ -267,7 +273,7 @@ def get_version_info(self, user_id, version=None):
version(str): Optional; if None gives the most recent version
otherwise a historical one.
Raises:
StoreError: code 404 if the requested backup version doesn't exist
NotFoundError: if the requested backup version doesn't exist
Returns:
A deferred of a info dict that gives the info about the new version.
@@ -279,7 +285,13 @@ def get_version_info(self, user_id, version=None):
"""

with (yield self._upload_linearizer.queue(user_id)):
res = yield self.store.get_e2e_room_keys_version_info(user_id, version)
try:
res = yield self.store.get_e2e_room_keys_version_info(user_id, version)
except StoreError as e:
if e.code == 404:
raise NotFoundError("Unknown backup version")
else:
raise
defer.returnValue(res)

@defer.inlineCallbacks
@@ -290,8 +302,45 @@ def delete_version(self, user_id, version=None):
user_id(str): the user whose current backup version we're deleting
version(str): the version id of the backup being deleted
Raises:
StoreError: code 404 if this backup version doesn't exist
NotFoundError: if this backup version doesn't exist
"""

with (yield self._upload_linearizer.queue(user_id)):
yield self.store.delete_e2e_room_keys_version(user_id, version)
try:
yield self.store.delete_e2e_room_keys_version(user_id, version)
except StoreError as e:
if e.code == 404:
raise NotFoundError("Unknown backup version")
else:
raise

@defer.inlineCallbacks
def update_version(self, user_id, version, version_info):
"""Update the info about a given version of the user's backup
Args:
user_id(str): the user whose current backup version we're updating
version(str): the backup version we're updating
version_info(dict): the new information about the backup
Raises:
NotFoundError: if the requested backup version doesn't exist
Returns:
A deferred of an empty dict.
"""
try:
This conversation was marked as resolved by uhoreg

This comment has been minimized.

Copy link
@uhoreg

uhoreg Feb 7, 2019

Author Member

Other functions in this file are wrapped in with (yield self._upload_linearizer.queue(user_id)):. I don't know if this function needs it too.

This comment has been minimized.

Copy link
@erikjohnston

erikjohnston Feb 7, 2019

Member

I would probably do so, it may not be necessary but the fact that we do it elsewhere and we do two separate database queries makes me inclined to add it for consistency.

(FTR, all the function does is make sure only one set of code is being executed for a user at any given point)

old_info = yield self.store.get_e2e_room_keys_version_info(user_id, version)
except StoreError as e:
if e.code == 404:
raise NotFoundError("Unknown backup version")
else:
raise
if old_info["algorithm"] != version_info["algorithm"]:
raise SynapseError(
400,
"Algorithm does not match",
Codes.INVALID_PARAM
)

yield self.store.update_e2e_room_keys_version(user_id, version, version_info)

defer.returnValue({})
@@ -380,6 +380,39 @@ def on_DELETE(self, request, version):
)
defer.returnValue((200, {}))

@defer.inlineCallbacks
def on_PUT(self, request, version):
"""
Update the information about a given version of the user's room_keys backup.
POST /room_keys/version/12345 HTTP/1.1
Content-Type: application/json
{
"algorithm": "m.megolm_backup.v1",
"auth_data": {
"public_key": "abcdefg",
"signatures": {
"ed25519:something": "hijklmnop"
}
}
This conversation was marked as resolved by uhoreg

This comment has been minimized.

Copy link
@erikjohnston

erikjohnston Feb 7, 2019

Member

The spec PR has version field in the body

}
HTTP/1.1 200 OK
Content-Type: application/json
{}
"""
requester = yield self.auth.get_user_by_req(request, allow_guest=False)
user_id = requester.user.to_string()
info = parse_json_object_from_request(request)

if version is None:
raise SynapseError(400, "No version specified to update", Codes.MISSING_PARAM)

yield self.e2e_room_keys_handler.update_version(
user_id, version, info
)
defer.returnValue((200, {}))


def register_servlets(hs, http_server):
RoomKeysServlet(hs).register(http_server)
@@ -298,6 +298,27 @@ def _create_e2e_room_keys_version_txn(txn):
"create_e2e_room_keys_version_txn", _create_e2e_room_keys_version_txn
)

def update_e2e_room_keys_version(self, user_id, version, info):
"""Update a given backup version
Args:
user_id(str): the user whose backup version we're updating
version(str): the version ID of the backup version we're updating
info(dict): the new backup version info to store
"""

return self._simple_update(
table="e2e_room_keys_versions",
keyvalues={
"user_id": user_id,
"version": version,
},
updatevalues={
"auth_data": json.dumps(info["auth_data"]),
},
desc="update_e2e_room_keys_version"
)

def delete_e2e_room_keys_version(self, user_id, version=None):
"""Delete a given backup version of the user's room keys.
Doesn't delete their actual key data.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.