aboutsummaryrefslogtreecommitdiff
path: root/clientapi
diff options
context:
space:
mode:
authorTill <2353100+S7evinK@users.noreply.github.com>2023-04-28 17:49:38 +0200
committerGitHub <noreply@github.com>2023-04-28 17:49:38 +0200
commit9e9617ff84c3310fa3db6f32cdfc0207ec546963 (patch)
tree13fc5313e782f05c4569d7e49bcaea4bf8229dab /clientapi
parent6b47cf0f6ac9176b7e5a5bd6f357722ee0f5e384 (diff)
Add key backup tests (#3071)
Also slightly refactors the functions and methods to rely less on the req/res pattern we had for polylith. Returns `M_WRONG_ROOM_KEYS_VERSION` for some endpoints as per the spec
Diffstat (limited to 'clientapi')
-rw-r--r--clientapi/clientapi_test.go374
-rw-r--r--clientapi/jsonerror/jsonerror.go17
-rw-r--r--clientapi/routing/key_backup.go144
3 files changed, 451 insertions, 84 deletions
diff --git a/clientapi/clientapi_test.go b/clientapi/clientapi_test.go
index 09460ea1..2c34c109 100644
--- a/clientapi/clientapi_test.go
+++ b/clientapi/clientapi_test.go
@@ -1758,3 +1758,377 @@ func (d dummyStore) GetEncryptionEvent(roomID id.RoomID) *event.EncryptionEventC
func (d dummyStore) FindSharedRooms(userID id.UserID) []id.RoomID {
return []id.RoomID{}
}
+
+func TestKeyBackup(t *testing.T) {
+ alice := test.NewUser(t)
+
+ handleResponseCode := func(t *testing.T, rec *httptest.ResponseRecorder, expectedCode int) {
+ t.Helper()
+ if rec.Code != expectedCode {
+ t.Fatalf("expected HTTP %d, but got %d: %s", expectedCode, rec.Code, rec.Body.String())
+ }
+ }
+
+ testCases := []struct {
+ name string
+ request func(t *testing.T) *http.Request
+ validate func(t *testing.T, rec *httptest.ResponseRecorder)
+ }{
+ {
+ name: "can not create backup with invalid JSON",
+ request: func(t *testing.T) *http.Request {
+ reqBody := strings.NewReader(`{"algorithm":"m.megolm_backup.v1"`) // missing closing braces
+ return httptest.NewRequest(http.MethodPost, "/_matrix/client/v3/room_keys/version", reqBody)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusBadRequest)
+ },
+ },
+ {
+ name: "can not create backup with missing auth_data", // as this would result in MarshalJSON errors when querying again
+ request: func(t *testing.T) *http.Request {
+ reqBody := strings.NewReader(`{"algorithm":"m.megolm_backup.v1"}`)
+ return httptest.NewRequest(http.MethodPost, "/_matrix/client/v3/room_keys/version", reqBody)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusBadRequest)
+ },
+ },
+ {
+ name: "can create backup",
+ request: func(t *testing.T) *http.Request {
+ reqBody := strings.NewReader(`{"algorithm":"m.megolm_backup.v1","auth_data":{"data":"random"}}`)
+ return httptest.NewRequest(http.MethodPost, "/_matrix/client/v3/room_keys/version", reqBody)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ wantVersion := "1"
+ if gotVersion := gjson.GetBytes(rec.Body.Bytes(), "version").Str; gotVersion != wantVersion {
+ t.Fatalf("expected version '%s', got '%s'", wantVersion, gotVersion)
+ }
+ },
+ },
+ {
+ name: "can not query backup for invalid version",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodGet, "/_matrix/client/v3/room_keys/version/1337", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusNotFound)
+ },
+ },
+ {
+ name: "can not query backup for invalid version string",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodGet, "/_matrix/client/v3/room_keys/version/notanumber", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusNotFound)
+ },
+ },
+ {
+ name: "can query backup",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodGet, "/_matrix/client/v3/room_keys/version", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ wantVersion := "1"
+ if gotVersion := gjson.GetBytes(rec.Body.Bytes(), "version").Str; gotVersion != wantVersion {
+ t.Fatalf("expected version '%s', got '%s'", wantVersion, gotVersion)
+ }
+ },
+ },
+ {
+ name: "can query backup without returning rooms",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ if gotRooms := gjson.GetBytes(rec.Body.Bytes(), "rooms").Map(); len(gotRooms) > 0 {
+ t.Fatalf("expected no rooms in version, but got %#v", gotRooms)
+ }
+ },
+ },
+ {
+ name: "can query backup for invalid room",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys/!abc:test", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ if gotSessions := gjson.GetBytes(rec.Body.Bytes(), "sessions").Map(); len(gotSessions) > 0 {
+ t.Fatalf("expected no sessions in version, but got %#v", gotSessions)
+ }
+ },
+ },
+ {
+ name: "can not query backup for invalid session",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys/!abc:test/doesnotexist", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusNotFound)
+ },
+ },
+ {
+ name: "can not update backup with missing version",
+ request: func(t *testing.T) *http.Request {
+ return test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys")
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusBadRequest)
+ },
+ },
+ {
+ name: "can not update backup with invalid data",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, "")
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys", reqBody, test.WithQueryParams(map[string]string{
+ "version": "0",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusBadRequest)
+ },
+ },
+ {
+ name: "can not update backup with wrong version",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, map[string]interface{}{
+ "rooms": map[string]interface{}{
+ "!testroom:test": map[string]interface{}{
+ "sessions": map[string]uapi.KeyBackupSession{},
+ },
+ },
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys", reqBody, test.WithQueryParams(map[string]string{
+ "version": "5",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusForbidden)
+ },
+ },
+ {
+ name: "can update backup with correct version",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, map[string]interface{}{
+ "rooms": map[string]interface{}{
+ "!testroom:test": map[string]interface{}{
+ "sessions": map[string]uapi.KeyBackupSession{
+ "dummySession": {
+ FirstMessageIndex: 1,
+ },
+ },
+ },
+ },
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys", reqBody, test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ },
+ },
+ {
+ name: "can update backup with correct version for specific room",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, map[string]interface{}{
+ "sessions": map[string]uapi.KeyBackupSession{
+ "dummySession": {
+ FirstMessageIndex: 1,
+ IsVerified: true,
+ SessionData: json.RawMessage("{}"),
+ },
+ },
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys/!testroom:test", reqBody, test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ t.Logf("%#v", rec.Body.String())
+ },
+ },
+ {
+ name: "can update backup with correct version for specific room and session",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, uapi.KeyBackupSession{
+ FirstMessageIndex: 1,
+ SessionData: json.RawMessage("{}"),
+ IsVerified: true,
+ ForwardedCount: 0,
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/keys/!testroom:test/dummySession", reqBody, test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ },
+ },
+ {
+ name: "can update backup by version",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, uapi.KeyBackupSession{
+ FirstMessageIndex: 1,
+ SessionData: json.RawMessage("{}"),
+ IsVerified: true,
+ ForwardedCount: 0,
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/version/1", reqBody, test.WithQueryParams(map[string]string{"version": "1"}))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ t.Logf("%#v", rec.Body.String())
+ },
+ },
+ {
+ name: "can not update backup by version for invalid version",
+ request: func(t *testing.T) *http.Request {
+ reqBody := test.WithJSONBody(t, uapi.KeyBackupSession{
+ FirstMessageIndex: 1,
+ SessionData: json.RawMessage("{}"),
+ IsVerified: true,
+ ForwardedCount: 0,
+ })
+ req := test.NewRequest(t, http.MethodPut, "/_matrix/client/v3/room_keys/version/2", reqBody, test.WithQueryParams(map[string]string{"version": "1"}))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ },
+ },
+ {
+ name: "can query backup sessions",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ if gotRooms := gjson.GetBytes(rec.Body.Bytes(), "rooms").Map(); len(gotRooms) != 1 {
+ t.Fatalf("expected one room in response, but got %#v", rec.Body.String())
+ }
+ },
+ },
+ {
+ name: "can query backup sessions by room",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys/!testroom:test", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ if gotRooms := gjson.GetBytes(rec.Body.Bytes(), "sessions").Map(); len(gotRooms) != 1 {
+ t.Fatalf("expected one session in response, but got %#v", rec.Body.String())
+ }
+ },
+ },
+ {
+ name: "can query backup sessions by room and sessionID",
+ request: func(t *testing.T) *http.Request {
+ req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/room_keys/keys/!testroom:test/dummySession", test.WithQueryParams(map[string]string{
+ "version": "1",
+ }))
+ return req
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ if !gjson.GetBytes(rec.Body.Bytes(), "is_verified").Bool() {
+ t.Fatalf("expected session to be verified, but wasn't: %#v", rec.Body.String())
+ }
+ },
+ },
+ {
+ name: "can not delete invalid version backup",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodDelete, "/_matrix/client/v3/room_keys/version/2", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusNotFound)
+ },
+ },
+ {
+ name: "can delete version backup",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodDelete, "/_matrix/client/v3/room_keys/version/1", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ },
+ },
+ {
+ name: "deleting the same backup version twice doesn't error",
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodDelete, "/_matrix/client/v3/room_keys/version/1", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusOK)
+ },
+ },
+ {
+ name: "deleting an empty version doesn't work", // make sure we can't delete an empty backup version. Handled at the router level
+ request: func(t *testing.T) *http.Request {
+ return httptest.NewRequest(http.MethodDelete, "/_matrix/client/v3/room_keys/version/", nil)
+ },
+ validate: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ handleResponseCode(t, rec, http.StatusNotFound)
+ },
+ },
+ }
+
+ test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
+ cfg, processCtx, close := testrig.CreateConfig(t, dbType)
+ cfg.ClientAPI.RateLimiting.Enabled = false
+ caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
+ natsInstance := jetstream.NATSInstance{}
+ defer close()
+
+ routers := httputil.NewRouters()
+ cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
+ rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
+ userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
+
+ // We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
+ AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
+
+ accessTokens := map[*test.User]userDevice{
+ alice: {},
+ }
+ createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ rec := httptest.NewRecorder()
+ req := tc.request(t)
+ req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
+ routers.Client.ServeHTTP(rec, req)
+ tc.validate(t, rec)
+ })
+ }
+ })
+}
diff --git a/clientapi/jsonerror/jsonerror.go b/clientapi/jsonerror/jsonerror.go
index be7d13a9..436e168a 100644
--- a/clientapi/jsonerror/jsonerror.go
+++ b/clientapi/jsonerror/jsonerror.go
@@ -171,6 +171,23 @@ func LeaveServerNoticeError() *MatrixError {
}
}
+// ErrRoomKeysVersion is an error returned by `PUT /room_keys/keys`
+type ErrRoomKeysVersion struct {
+ MatrixError
+ CurrentVersion string `json:"current_version"`
+}
+
+// WrongBackupVersionError is an error returned by `PUT /room_keys/keys`
+func WrongBackupVersionError(currentVersion string) *ErrRoomKeysVersion {
+ return &ErrRoomKeysVersion{
+ MatrixError: MatrixError{
+ ErrCode: "M_WRONG_ROOM_KEYS_VERSION",
+ Err: "Wrong backup version.",
+ },
+ CurrentVersion: currentVersion,
+ }
+}
+
type IncompatibleRoomVersionError struct {
RoomVersion string `json:"room_version"`
Error string `json:"error"`
diff --git a/clientapi/routing/key_backup.go b/clientapi/routing/key_backup.go
index b6f8fe1b..56b05db1 100644
--- a/clientapi/routing/key_backup.go
+++ b/clientapi/routing/key_backup.go
@@ -61,28 +61,26 @@ func CreateKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
if resErr != nil {
return *resErr
}
- var performKeyBackupResp userapi.PerformKeyBackupResponse
- if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
+ if len(kb.AuthData) == 0 {
+ return util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: jsonerror.BadJSON("missing auth_data"),
+ }
+ }
+ version, err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: "",
AuthData: kb.AuthData,
Algorithm: kb.Algorithm,
- }, &performKeyBackupResp); err != nil {
- return jsonerror.InternalServerError()
- }
- if performKeyBackupResp.Error != "" {
- if performKeyBackupResp.BadInput {
- return util.JSONResponse{
- Code: 400,
- JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
- }
- }
- return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
+ })
+ if err != nil {
+ return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", err))
}
+
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionCreateResponse{
- Version: performKeyBackupResp.Version,
+ Version: version,
},
}
}
@@ -90,15 +88,12 @@ func CreateKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
// KeyBackupVersion returns the key backup version specified. If `version` is empty, the latest `keyBackupVersionResponse` is returned.
// Implements GET /_matrix/client/r0/room_keys/version and GET /_matrix/client/r0/room_keys/version/{version}
func KeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string) util.JSONResponse {
- var queryResp userapi.QueryKeyBackupResponse
- if err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
+ queryResp, err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
UserID: device.UserID,
Version: version,
- }, &queryResp); err != nil {
- return jsonerror.InternalAPIError(req.Context(), err)
- }
- if queryResp.Error != "" {
- return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
+ })
+ if err != nil {
+ return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", err))
}
if !queryResp.Exists {
return util.JSONResponse{
@@ -126,31 +121,29 @@ func ModifyKeyBackupVersionAuthData(req *http.Request, userAPI userapi.ClientUse
if resErr != nil {
return *resErr
}
- var performKeyBackupResp userapi.PerformKeyBackupResponse
- if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
+ performKeyBackupResp, err := userAPI.UpdateBackupKeyAuthData(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: version,
AuthData: kb.AuthData,
Algorithm: kb.Algorithm,
- }, &performKeyBackupResp); err != nil {
- return jsonerror.InternalServerError()
- }
- if performKeyBackupResp.Error != "" {
- if performKeyBackupResp.BadInput {
- return util.JSONResponse{
- Code: 400,
- JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
- }
+ })
+ switch e := err.(type) {
+ case *jsonerror.ErrRoomKeysVersion:
+ return util.JSONResponse{
+ Code: http.StatusForbidden,
+ JSON: e,
}
- return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
+ case nil:
+ default:
+ return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", e))
}
+
if !performKeyBackupResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("backup version not found"),
}
}
- // Unclear what the 200 body should be
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionCreateResponse{
@@ -162,35 +155,19 @@ func ModifyKeyBackupVersionAuthData(req *http.Request, userAPI userapi.ClientUse
// Delete a version of key backup. Version must not be empty. If the key backup was previously deleted, will return 200 OK.
// Implements DELETE /_matrix/client/r0/room_keys/version/{version}
func DeleteKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string) util.JSONResponse {
- var performKeyBackupResp userapi.PerformKeyBackupResponse
- if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
- UserID: device.UserID,
- Version: version,
- DeleteBackup: true,
- }, &performKeyBackupResp); err != nil {
- return jsonerror.InternalServerError()
+ exists, err := userAPI.DeleteKeyBackup(req.Context(), device.UserID, version)
+ if err != nil {
+ return util.ErrorResponse(fmt.Errorf("DeleteKeyBackup: %s", err))
}
- if performKeyBackupResp.Error != "" {
- if performKeyBackupResp.BadInput {
- return util.JSONResponse{
- Code: 400,
- JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
- }
- }
- return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
- }
- if !performKeyBackupResp.Exists {
+ if !exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("backup version not found"),
}
}
- // Unclear what the 200 body should be
return util.JSONResponse{
Code: 200,
- JSON: keyBackupVersionCreateResponse{
- Version: performKeyBackupResp.Version,
- },
+ JSON: struct{}{},
}
}
@@ -198,22 +175,21 @@ func DeleteKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
func UploadBackupKeys(
req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string, keys *keyBackupSessionRequest,
) util.JSONResponse {
- var performKeyBackupResp userapi.PerformKeyBackupResponse
- if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
+ performKeyBackupResp, err := userAPI.UpdateBackupKeyAuthData(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: version,
Keys: *keys,
- }, &performKeyBackupResp); err != nil && performKeyBackupResp.Error == "" {
- return jsonerror.InternalServerError()
- }
- if performKeyBackupResp.Error != "" {
- if performKeyBackupResp.BadInput {
- return util.JSONResponse{
- Code: 400,
- JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
- }
+ })
+
+ switch e := err.(type) {
+ case *jsonerror.ErrRoomKeysVersion:
+ return util.JSONResponse{
+ Code: http.StatusForbidden,
+ JSON: e,
}
- return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
+ case nil:
+ default:
+ return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", e))
}
if !performKeyBackupResp.Exists {
return util.JSONResponse{
@@ -234,18 +210,15 @@ func UploadBackupKeys(
func GetBackupKeys(
req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version, roomID, sessionID string,
) util.JSONResponse {
- var queryResp userapi.QueryKeyBackupResponse
- if err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
+ queryResp, err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
UserID: device.UserID,
Version: version,
ReturnKeys: true,
KeysForRoomID: roomID,
KeysForSessionID: sessionID,
- }, &queryResp); err != nil {
- return jsonerror.InternalAPIError(req.Context(), err)
- }
- if queryResp.Error != "" {
- return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
+ })
+ if err != nil {
+ return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %w", err))
}
if !queryResp.Exists {
return util.JSONResponse{
@@ -267,17 +240,20 @@ func GetBackupKeys(
}
} else if roomID != "" {
roomData, ok := queryResp.Keys[roomID]
- if ok {
- // wrap response in "sessions"
- return util.JSONResponse{
- Code: 200,
- JSON: struct {
- Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
- }{
- Sessions: roomData,
- },
- }
+ if !ok {
+ // If no keys are found, then an object with an empty sessions property will be returned
+ roomData = make(map[string]userapi.KeyBackupSession)
+ }
+ // wrap response in "sessions"
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct {
+ Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
+ }{
+ Sessions: roomData,
+ },
}
+
} else {
// response is the same as the upload request
var resp keyBackupSessionRequest