From 94088a829e4261196768f2ccb543f51c61f03e55 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 25 Jul 2017 11:38:09 +0100 Subject: [PATCH] Implement retrieval in /sync --- .../clientapi/auth/authtypes/account_data.go | 22 --------- .../storage/accounts/account_data_table.go | 47 +++++++++---------- .../auth/storage/accounts/storage.go | 14 ++++++ .../cmd/dendrite-sync-api-server/main.go | 8 +++- .../dendrite/syncapi/sync/requestpool.go | 46 +++++++++++++++--- 5 files changed, 83 insertions(+), 54 deletions(-) delete mode 100644 src/github.com/matrix-org/dendrite/clientapi/auth/authtypes/account_data.go diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/authtypes/account_data.go b/src/github.com/matrix-org/dendrite/clientapi/auth/authtypes/account_data.go deleted file mode 100644 index 4579b562a..000000000 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/authtypes/account_data.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 Vector Creations Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package authtypes - -// AccountData represents data specific to a given account -type AccountData struct { - Localpart string - Type string - Content string -} diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/account_data_table.go b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/account_data_table.go index 7a7dbe9c4..db7983701 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/account_data_table.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/account_data_table.go @@ -16,7 +16,8 @@ package accounts import ( "database/sql" - "github.com/matrix-org/dendrite/clientapi/auth/authtypes" + + "github.com/matrix-org/gomatrixserverlib" ) const accountDataSchema = ` @@ -77,56 +78,54 @@ func (s *accountDataStatements) insertAccountData(localpart string, roomID strin return } -func (s *accountDataStatements) selectGlobalAccountData(localpart string) ([]authtypes.AccountData, error) { - var data []authtypes.AccountData +func (s *accountDataStatements) selectGlobalAccountData(localpart string) ([]gomatrixserverlib.ClientEvent, error) { + var events []gomatrixserverlib.ClientEvent rows, err := s.selectGlobalAccountDataStmt.Query(localpart) if err != nil { - return data, err + return events, err } for rows.Next() { var dataType string - var content string + var content []byte if err := rows.Scan(&dataType, &content); err != nil && err != sql.ErrNoRows { - return data, err + return events, err } - ac := authtypes.AccountData{ - Localpart: localpart, - Type: dataType, - Content: content, + ac := gomatrixserverlib.ClientEvent{ + Type: dataType, + Content: content, } - data = append(data, ac) + events = append(events, ac) } - return data, nil + return events, nil } -func (s *accountDataStatements) selectRoomAccountData(localpart string, roomID string) ([]authtypes.AccountData, error) { - var data []authtypes.AccountData +func (s *accountDataStatements) selectRoomAccountData(localpart string, roomID string) ([]gomatrixserverlib.ClientEvent, error) { + var events []gomatrixserverlib.ClientEvent - rows, err := s.selectRoomAccountDataStmt.Query(localpart) + rows, err := s.selectRoomAccountDataStmt.Query(localpart, roomID) if err != nil { - return data, err + return events, err } for rows.Next() { var dataType string - var content string + var content []byte if err := rows.Scan(&dataType, &content); err != nil && err != sql.ErrNoRows { - return data, err + return events, err } - ac := authtypes.AccountData{ - Localpart: localpart, - Type: dataType, - Content: content, + ac := gomatrixserverlib.ClientEvent{ + Type: dataType, + Content: content, } - data = append(data, ac) + events = append(events, ac) } - return data, nil + return events, nil } diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go index 0f86256e3..75e4ccc58 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go @@ -198,6 +198,20 @@ func (d *Database) SaveAccountData(localpart string, roomID string, dataType str return d.accountDatas.insertAccountData(localpart, roomID, dataType, content) } +// GetAccountData returns account data related to a given localpart +// If a non-empty string is provided as the room ID, returns all account data +// related to the room +// If an empty string is provided as the room ID, returns all account data that +// aren't related to any room +// If no account data could be found, returns an empty arrays +// Returns an error if there was an issue with the retrieval +func (d *Database) GetAccountData(localpart string, roomID string) ([]gomatrixserverlib.ClientEvent, error) { + if len(roomID) > 0 { + return d.accountDatas.selectRoomAccountData(localpart, roomID) + } + return d.accountDatas.selectGlobalAccountData(localpart) +} + func hashPassword(plaintext string) (hash string, err error) { hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost) return string(hashBytes), err diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go index a8984c1d5..c7870684d 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go @@ -19,6 +19,7 @@ import ( "net/http" "os" + "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common/config" @@ -58,6 +59,11 @@ func main() { log.Panicf("startup: failed to create device database with data source %s : %s", cfg.Database.Device, err) } + adb, err := accounts.NewDatabase(string(cfg.Database.Account), cfg.Matrix.ServerName) + if err != nil { + log.Panicf("startup: failed to create account database with data source %s : %s", cfg.Database.Account, err) + } + pos, err := db.SyncStreamPosition() if err != nil { log.Panicf("startup: failed to get latest sync stream position : %s", err) @@ -76,6 +82,6 @@ func main() { } log.Info("Starting sync server on ", cfg.Listen.SyncAPI) - routing.SetupSyncServerListeners(http.DefaultServeMux, http.DefaultClient, sync.NewRequestPool(db, n), deviceDB) + routing.SetupSyncServerListeners(http.DefaultServeMux, http.DefaultClient, sync.NewRequestPool(db, n, adb), deviceDB) log.Fatal(http.ListenAndServe(string(cfg.Listen.SyncAPI), nil)) } diff --git a/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go b/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go index 08bad334a..f2dd4e586 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go @@ -20,22 +20,25 @@ import ( log "github.com/Sirupsen/logrus" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" + "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/syncapi/storage" "github.com/matrix-org/dendrite/syncapi/types" + "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" ) // RequestPool manages HTTP long-poll connections for /sync type RequestPool struct { - db *storage.SyncServerDatabase - notifier *Notifier + db *storage.SyncServerDatabase + accountDB *accounts.Database + notifier *Notifier } // NewRequestPool makes a new RequestPool -func NewRequestPool(db *storage.SyncServerDatabase, n *Notifier) *RequestPool { - return &RequestPool{db, n} +func NewRequestPool(db *storage.SyncServerDatabase, n *Notifier, adb *accounts.Database) *RequestPool { + return &RequestPool{db, adb, n} } // OnIncomingSyncRequest is called when a client makes a /sync request. This function MUST be @@ -77,9 +80,14 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *authtype if err != nil { res = httputil.LogThenError(req, err) } else { - res = util.JSONResponse{ - Code: 200, - JSON: syncData, + syncData, err = rp.appendAccountData(syncData, device.UserID) + if err != nil { + res = httputil.LogThenError(req, err) + } else { + res = util.JSONResponse{ + Code: 200, + JSON: syncData, + } } } done <- res @@ -104,3 +112,27 @@ func (rp *RequestPool) currentSyncForUser(req syncRequest, currentPos types.Stre } return rp.db.IncrementalSync(req.userID, req.since, currentPos, req.limit) } + +func (rp *RequestPool) appendAccountData(data *types.Response, userID string) (*types.Response, error) { + localpart, _, err := gomatrixserverlib.SplitID('@', userID) + if err != nil { + return nil, err + } + + events, err := rp.accountDB.GetAccountData(localpart, "") + if err != nil { + return nil, err + } + data.AccountData.Events = events + + for r, j := range data.Rooms.Join { + events, err := rp.accountDB.GetAccountData(localpart, r) + if err != nil { + return nil, err + } + j.AccountData.Events = events + data.Rooms.Join[r] = j + } + + return data, nil +}