2021-04-25 14:42:36 +00:00
// Copyright 2021 Dan Peleg <dan@globekeeper.com>
2021-04-23 18:28:38 +00:00
//
// 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 sqlite3
import (
"context"
"database/sql"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/dendrite/clientapi/userutil"
"github.com/matrix-org/gomatrixserverlib"
)
const pushersSchema = `
-- Stores data about pushers .
CREATE TABLE IF NOT EXISTS pusher_pushers (
2021-04-24 13:12:06 +00:00
localpart TEXT PRIMARY KEY ,
pushkey VARCHAR ( 512 ) ,
kind TEXT ,
app_id VARCHAR ( 64 ) ,
app_display_name TEXT ,
device_display_name TEXT ,
profile_tag TEXT ,
lang TEXT ,
url TEXT ,
format TEXT ,
2021-04-23 18:28:38 +00:00
2021-04-24 13:12:06 +00:00
UNIQUE ( localpart , pushkey )
2021-04-23 18:28:38 +00:00
) ;
`
2021-05-02 14:11:53 +00:00
const insertPusherSQL = "" +
"INSERT INTO pusher_pushers (localpart, pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format)" +
" VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9. $10)"
2021-04-23 18:28:38 +00:00
const selectPushersByLocalpartSQL = "" +
2021-04-24 13:12:06 +00:00
"SELECT pushkey, kind, app_id, app_display_name, device_display_name, profile_tag, lang, url, format FROM pusher_pushers WHERE localpart = $1"
2021-04-23 18:28:38 +00:00
2021-04-25 14:42:36 +00:00
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"
2021-05-02 14:10:40 +00:00
const deletePusherSQL = "" +
"DELETE FROM pusher_pushers WHERE pushkey = $1 AND localpart = $2"
2021-04-23 18:28:38 +00:00
type pushersStatements struct {
db * sql . DB
writer sqlutil . Writer
2021-05-02 14:11:53 +00:00
insertPusherStmt * sql . Stmt
2021-04-23 18:28:38 +00:00
selectPushersByLocalpartStmt * sql . Stmt
2021-04-25 14:42:36 +00:00
selectPusherByPushkeyStmt * sql . Stmt
2021-05-02 14:10:40 +00:00
deletePusherStmt * sql . Stmt
2021-04-23 18:28:38 +00:00
serverName gomatrixserverlib . ServerName
}
func ( s * pushersStatements ) execSchema ( db * sql . DB ) error {
_ , err := db . Exec ( pushersSchema )
return err
}
func ( s * pushersStatements ) prepare ( db * sql . DB , writer sqlutil . Writer , server gomatrixserverlib . ServerName ) ( err error ) {
s . db = db
s . writer = writer
2021-05-02 14:11:53 +00:00
if s . insertPusherStmt , err = db . Prepare ( insertPusherSQL ) ; err != nil {
return
}
2021-04-23 18:28:38 +00:00
if s . selectPushersByLocalpartStmt , err = db . Prepare ( selectPushersByLocalpartSQL ) ; err != nil {
2021-04-24 13:12:06 +00:00
return
2021-04-25 14:42:36 +00:00
}
if s . selectPusherByPushkeyStmt , err = db . Prepare ( selectPusherByPushkeySQL ) ; err != nil {
2021-04-23 18:28:38 +00:00
return
}
2021-05-02 14:10:40 +00:00
if s . deletePusherStmt , err = db . Prepare ( deletePusherSQL ) ; err != nil {
return
}
2021-04-23 18:28:38 +00:00
s . serverName = server
return
}
2021-05-02 14:11:53 +00:00
// insertPusher creates a new pusher.
// Returns an error if the user already has a pusher with the given pusher pushkey.
// Returns nil error success.
func ( s * pushersStatements ) insertPusher (
ctx context . Context , txn * sql . Tx , pushkey , kind , appid , appdisplayname , devicedisplayname , profiletag , lang , url , format , localpart string ,
) error {
stmt := sqlutil . TxStmt ( txn , s . insertPusherStmt )
_ , err := stmt . ExecContext ( ctx , localpart , pushkey , kind , appid , appdisplayname , devicedisplayname , profiletag , lang , url , format )
return err
}
2021-04-23 18:28:38 +00:00
func ( s * pushersStatements ) selectPushersByLocalpart (
2021-04-23 21:02:00 +00:00
ctx context . Context , txn * sql . Tx , localpart string ,
2021-04-23 18:28:38 +00:00
) ( [ ] api . Pusher , error ) {
pushers := [ ] api . Pusher { }
2021-04-23 21:02:00 +00:00
rows , err := sqlutil . TxStmt ( txn , s . selectPushersByLocalpartStmt ) . QueryContext ( ctx , localpart )
2021-04-23 18:28:38 +00:00
if err != nil {
return pushers , err
}
for rows . Next ( ) {
2021-04-23 21:02:00 +00:00
var pusher api . Pusher
2021-04-24 13:12:06 +00:00
var pushkey , kind , appid , appdisplayname , devicedisplayname , profiletag , lang , url , format sql . NullString
err = rows . Scan ( & pushkey , & kind , & appid , & appdisplayname , & devicedisplayname , & profiletag , & lang , & url , & format )
2021-04-23 18:28:38 +00:00
if err != nil {
return pushers , err
}
2021-04-23 21:02:00 +00:00
if pushkey . Valid {
pusher . PushKey = pushkey . 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
}
2021-04-24 13:12:06 +00:00
if lang . Valid {
pusher . Language = lang . String
2021-04-23 21:02:00 +00:00
}
if url . Valid && format . Valid {
pusher . Data = api . PusherData {
URL : url . String ,
Format : format . String ,
}
2021-04-23 18:28:38 +00:00
}
2021-04-23 21:02:00 +00:00
pusher . UserID = userutil . MakeUserID ( localpart , s . serverName )
pushers = append ( pushers , pusher )
2021-04-23 18:28:38 +00:00
}
return pushers , nil
}
2021-04-25 14:42:36 +00:00
// 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
}
2021-05-02 14:10:40 +00:00
func ( s * pushersStatements ) deletePusher (
ctx context . Context , txn * sql . Tx , id , localpart string ,
) error {
stmt := sqlutil . TxStmt ( txn , s . deletePusherStmt )
_ , err := stmt . ExecContext ( ctx , id , localpart )
return err
}