From 633dbe09006f702f2387a99c13d93cd1c20d8276 Mon Sep 17 00:00:00 2001 From: Dan Peleg Date: Sun, 25 Apr 2021 17:42:36 +0300 Subject: [PATCH] WIP - Implementing /_matrix/client/r0/pushers/set --- clientapi/routing/pusher.go | 25 +++++++++ clientapi/routing/routing.go | 10 ++++ .../storage/pushers/postgres/pushers_table.go | 50 +++++++++++++++++- userapi/storage/pushers/postgres/storage.go | 6 +++ .../storage/pushers/sqlite3/pushers_table.go | 52 +++++++++++++++++-- userapi/storage/pushers/sqlite3/storage.go | 8 ++- 6 files changed, 146 insertions(+), 5 deletions(-) diff --git a/clientapi/routing/pusher.go b/clientapi/routing/pusher.go index c657497a..e1550cda 100644 --- a/clientapi/routing/pusher.go +++ b/clientapi/routing/pusher.go @@ -78,3 +78,28 @@ func GetPushersByLocalpart( JSON: res, } } + +// SetPushersByLocalpart handles /_matrix/client/r0/pushers/set +// This endpoint allows the creation, modification and deletion of pushers for this user ID. +// The behaviour of this endpoint varies depending on the values in the JSON body. +func SetPusherByLocalpart( + req *http.Request, userAPI userapi.UserInternalAPI, device *api.Device, +) util.JSONResponse { + + body := pusherJSON{} + + if resErr := httputil.UnmarshalJSONRequest(req, &body); resErr != nil { + return *resErr + } + + // TODO: + // 1. if kind == null, GetPusherByPushkey and delete it! 🗑 + // 2. if GetPusherByPushkey returns existing Pusher, update it with the received body + // 3. if GetPusherByPushkey returns nothing, create a new Pusher with the received body + + res := body + return util.JSONResponse{ + Code: http.StatusOK, + JSON: res, + } +} diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index b8b7c978..84f5891b 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -808,6 +808,16 @@ func Setup( return GetPushersByLocalpart(req, userAPI, device) }), ).Methods(http.MethodGet, http.MethodOptions) + + r0mux.Handle("/pushers/set", + httputil.MakeAuthAPI("set_pushers", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { + if r := rateLimits.rateLimit(req); r != nil { + return *r + } + return SetPushersByLocalpart(req, userAPI, device) + }), + ).Methods(http.MethodPost, http.MethodOptions) + // Stub implementations for sytest r0mux.Handle("/events", httputil.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse { diff --git a/userapi/storage/pushers/postgres/pushers_table.go b/userapi/storage/pushers/postgres/pushers_table.go index d0843fbb..5452853b 100644 --- a/userapi/storage/pushers/postgres/pushers_table.go +++ b/userapi/storage/pushers/postgres/pushers_table.go @@ -61,8 +61,12 @@ CREATE UNIQUE INDEX IF NOT EXISTS pusher_localpart_pushkey_idx ON pusher_pushers const selectPushersByLocalpartSQL = "" + "SELECT pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format FROM pusher_pushers WHERE localpart = $1" +const selectPusherByPushkeySQL = "" + + "SELECT pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format FROM pusher_pushers WHERE localpart = $1 AND pushkey = $2" + type pushersStatements struct { selectPushersByLocalpartStmt *sql.Stmt + selectPusherByPushkeyStmt *sql.Stmt serverName gomatrixserverlib.ServerName } @@ -75,7 +79,7 @@ func (s *pushersStatements) prepare(db *sql.DB, server gomatrixserverlib.ServerN if s.selectPushersByLocalpartStmt, err = db.Prepare(selectPushersByLocalpartSQL); err != nil { return } - if s.selectPushersByPushkeyStmt, err = db.Prepare(selectPushersByPushkeySQL); err != nil { + if s.selectPusherByPushkeyStmt, err = db.Prepare(selectPusherByPushkeySQL); err != nil { return } s.serverName = server @@ -134,3 +138,47 @@ func (s *pushersStatements) selectPushersByLocalpart( return pushers, rows.Err() } + +func (s *pushersStatements) selectPusherByPushkey( + ctx context.Context, localpart, pushkey string, +) (*api.Pusher, error) { + var pusher api.Pusher + var id, key, kind, appid, appdisplayname, devicedisplayname, profiletag, lang, url, format sql.NullString + + stmt := s.selectPusherByPushkeyStmt + err := stmt.QueryRowContext(ctx, localpart, pushkey).Scan(&id, &key, &kind, &appid, &appdisplayname, &devicedisplayname, &profiletag, &lang, &url, &format) + + if err == nil { + if key.Valid { + pusher.PushKey = key.String + } + if kind.Valid { + pusher.Kind = kind.String + } + if appid.Valid { + pusher.AppID = appid.String + } + if appdisplayname.Valid { + pusher.AppDisplayName = appdisplayname.String + } + if devicedisplayname.Valid { + pusher.DeviceDisplayName = devicedisplayname.String + } + if profiletag.Valid { + pusher.ProfileTag = profiletag.String + } + if lang.Valid { + pusher.Language = lang.String + } + if url.Valid && format.Valid { + pusher.Data = api.PusherData{ + URL: url.String, + Format: format.String, + } + } + + pusher.UserID = userutil.MakeUserID(localpart, s.serverName) + } + + return &pusher, err +} diff --git a/userapi/storage/pushers/postgres/storage.go b/userapi/storage/pushers/postgres/storage.go index 76f0f89f..ca45b80f 100644 --- a/userapi/storage/pushers/postgres/storage.go +++ b/userapi/storage/pushers/postgres/storage.go @@ -61,4 +61,10 @@ func (d *Database) GetPushersByLocalpart( ) ([]api.Pusher, error) { return d.pushers.selectPushersByLocalpart(ctx, nil, localpart) } + +// GetPushersByPushkey returns the pusers matching the given localpart. +func (d *Database) GetPushersByPushkey( + ctx context.Context, localpart, pushkey string, +) (*api.Pusher, error) { + return d.pushers.selectPushersByPushkey(ctx, localpart, pushkey) } diff --git a/userapi/storage/pushers/sqlite3/pushers_table.go b/userapi/storage/pushers/sqlite3/pushers_table.go index 8eda4c5a..31c2fa1c 100644 --- a/userapi/storage/pushers/sqlite3/pushers_table.go +++ b/userapi/storage/pushers/sqlite3/pushers_table.go @@ -1,4 +1,4 @@ -// Copyright 2017 Vector Creations Ltd +// Copyright 2021 Dan Peleg // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import ( "github.com/matrix-org/dendrite/internal/sqlutil" "github.com/matrix-org/dendrite/userapi/api" - "github.com/sirupsen/logrus" "github.com/matrix-org/dendrite/clientapi/userutil" "github.com/matrix-org/gomatrixserverlib" @@ -46,10 +45,14 @@ CREATE TABLE IF NOT EXISTS pusher_pushers ( const selectPushersByLocalpartSQL = "" + "SELECT pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format FROM pusher_pushers WHERE localpart = $1" +const selectPusherByPushkeySQL = "" + + "SELECT pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format FROM pusher_pushers WHERE localpart = $1 AND pushkey = $2" + type pushersStatements struct { db *sql.DB writer sqlutil.Writer selectPushersByLocalpartStmt *sql.Stmt + selectPusherByPushkeyStmt *sql.Stmt serverName gomatrixserverlib.ServerName } @@ -62,8 +65,9 @@ func (s *pushersStatements) prepare(db *sql.DB, writer sqlutil.Writer, server go s.db = db s.writer = writer if s.selectPushersByLocalpartStmt, err = db.Prepare(selectPushersByLocalpartSQL); err != nil { - logrus.WithError(err).Debug("💥💥💥 Preparing selectPushersByLocalpartStmt...") return + } + if s.selectPusherByPushkeyStmt, err = db.Prepare(selectPusherByPushkeySQL); err != nil { return } s.serverName = server @@ -121,3 +125,45 @@ func (s *pushersStatements) selectPushersByLocalpart( return pushers, nil } + +// selectPusherByID retrieves a pusher from the database with the given user +// localpart and pusherID +func (s *pushersStatements) selectPusherByPushkey( + ctx context.Context, localpart, pushkey string, +) (*api.Pusher, error) { + var pusher api.Pusher + var id, key, kind, appid, appdisplayname, devicedisplayname, profiletag, lang, url, format sql.NullString + stmt := s.selectPusherByPushkeyStmt + err := stmt.QueryRowContext(ctx, localpart, pushkey).Scan(&id, &key, &kind, &appid, &appdisplayname, &devicedisplayname, &profiletag, &lang, &url, &format) + if err == nil { + pusher.UserID = userutil.MakeUserID(localpart, s.serverName) + if key.Valid { + pusher.PushKey = key.String + } + if kind.Valid { + pusher.Kind = kind.String + } + if appid.Valid { + pusher.AppID = appid.String + } + if appdisplayname.Valid { + pusher.AppDisplayName = appdisplayname.String + } + if devicedisplayname.Valid { + pusher.DeviceDisplayName = devicedisplayname.String + } + if profiletag.Valid { + pusher.ProfileTag = profiletag.String + } + if lang.Valid { + pusher.Language = lang.String + } + if url.Valid && format.Valid { + pusher.Data = api.PusherData{ + URL: url.String, + Format: format.String, + } + } + } + return &pusher, err +} diff --git a/userapi/storage/pushers/sqlite3/storage.go b/userapi/storage/pushers/sqlite3/storage.go index 8684f54b..43522528 100644 --- a/userapi/storage/pushers/sqlite3/storage.go +++ b/userapi/storage/pushers/sqlite3/storage.go @@ -1,4 +1,4 @@ -// Copyright 2017 Vector Creations Ltd +// Copyright 2021 Dan Peleg // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -63,4 +63,10 @@ func (d *Database) GetPushersByLocalpart( ) ([]api.Pusher, error) { return d.pushers.selectPushersByLocalpart(ctx, nil, localpart) } + +// GetPushersByLocalpart returns the pushers matching the given localpart. +func (d *Database) GetPushersByPushkey( + ctx context.Context, localpart, pushkey string, +) (*api.Pusher, error) { + return d.pushers.selectPusherByPushkey(ctx, localpart, pushkey) }