mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-12 01:13:10 -06:00
Add database table and functions for tracking 3PIDs
This commit is contained in:
parent
1226209403
commit
91c36d5b0f
|
|
@ -16,6 +16,7 @@ package accounts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/common"
|
"github.com/matrix-org/dendrite/common"
|
||||||
|
|
@ -33,6 +34,7 @@ type Database struct {
|
||||||
profiles profilesStatements
|
profiles profilesStatements
|
||||||
memberships membershipStatements
|
memberships membershipStatements
|
||||||
accountDatas accountDataStatements
|
accountDatas accountDataStatements
|
||||||
|
threepids threepidStatements
|
||||||
serverName gomatrixserverlib.ServerName
|
serverName gomatrixserverlib.ServerName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +65,11 @@ func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName)
|
||||||
if err = ac.prepare(db); err != nil {
|
if err = ac.prepare(db); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Database{db, partitions, a, p, m, ac, serverName}, nil
|
t := threepidStatements{}
|
||||||
|
if err = t.prepare(db); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Database{db, partitions, a, p, m, ac, t, serverName}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountByPassword returns the account associated with the given localpart and password.
|
// GetAccountByPassword returns the account associated with the given localpart and password.
|
||||||
|
|
@ -233,3 +239,51 @@ func hashPassword(plaintext string) (hash string, err error) {
|
||||||
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
|
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
|
||||||
return string(hashBytes), err
|
return string(hashBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err3PIDInUse is the error returned when trying to save an association involving
|
||||||
|
// a third-party identifier which is already associated to a local user.
|
||||||
|
var Err3PIDInUse = errors.New("This third-party identifier is already in use")
|
||||||
|
|
||||||
|
// SaveThreePIDAssociation saves the association between a third party identifier
|
||||||
|
// and a local Matrix user (identified by the user's ID's local part).
|
||||||
|
// If the third-party identifier is already part of an association, returns Err3PIDInUse.
|
||||||
|
// Returns an error if there was a problem talking to the database.
|
||||||
|
func (d *Database) SaveThreePIDAssociation(threepid string, localpart string) (err error) {
|
||||||
|
return common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||||
|
user, err := d.threepids.selectLocalpartForThreePID(txn, threepid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user) > 0 {
|
||||||
|
return Err3PIDInUse
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.threepids.insertThreePID(txn, threepid, localpart)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveThreePIDAssociation removes the association involving a given third-party
|
||||||
|
// identifier.
|
||||||
|
// If no association exists involving this third-party identifier, returns nothing.
|
||||||
|
// If there was a problem talking to the database, returns an error.
|
||||||
|
func (d *Database) RemoveThreePIDAssociation(threepid string) (err error) {
|
||||||
|
return d.threepids.deleteThreePID(threepid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocalpartForThreePID looks up the localpart associated with a given third-party
|
||||||
|
// identifier.
|
||||||
|
// If no association involves the given third-party idenfitier, returns an empty
|
||||||
|
// string.
|
||||||
|
// Returns an error if there was a problem talking to the database.
|
||||||
|
func (d *Database) GetLocalpartForThreePID(threepid string) (localpart string, err error) {
|
||||||
|
return d.threepids.selectLocalpartForThreePID(nil, threepid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetThreePIDsForLocalpart looks up the third-party identifiers associated with
|
||||||
|
// a given local user.
|
||||||
|
// If no association is known for this user, returns an empty slice.
|
||||||
|
// Returns an error if there was an issue talking to the database.
|
||||||
|
func (d *Database) GetThreePIDsForLocalpart(localpart string) (threepids map[string]string, err error) {
|
||||||
|
return d.threepids.selectThreePIDsForLocalpart(localpart)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
// 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 accounts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
const threepidSchema = `
|
||||||
|
-- Stores data about third party identifiers
|
||||||
|
CREATE TABLE IF NOT EXISTS account_threepid (
|
||||||
|
-- The third party identifier
|
||||||
|
threepid TEXT NOT NULL,
|
||||||
|
-- The 3PID medium
|
||||||
|
medium TEXT NOT NULL DEFAULT 'email',
|
||||||
|
-- The localpart of the Matrix user ID associated to this 3PID
|
||||||
|
localpart TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY(threepid, medium)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS account_threepid_localpart ON account_threepid(localpart);
|
||||||
|
`
|
||||||
|
|
||||||
|
const selectLocalpartForThreePIDSQL = "" +
|
||||||
|
"SELECT localpart FROM account_threepid WHERE threepid = $1"
|
||||||
|
|
||||||
|
const selectThreePIDsForLocalpartSQL = "" +
|
||||||
|
"SELECT threepid, medium FROM account_threepid WHERE localpart = $1"
|
||||||
|
|
||||||
|
const insertThreePIDSQL = "" +
|
||||||
|
"INSERT INTO account_threepid (threepid, localpart) VALUES ($1, $2)"
|
||||||
|
|
||||||
|
const deleteThreePIDSQL = "" +
|
||||||
|
"DELETE FROM account_threepid WHERE threepid = $1"
|
||||||
|
|
||||||
|
type threepidStatements struct {
|
||||||
|
selectLocalpartForThreePIDStmt *sql.Stmt
|
||||||
|
selectThreePIDsForLocalpartStmt *sql.Stmt
|
||||||
|
insertThreePIDStmt *sql.Stmt
|
||||||
|
deleteThreePIDStmt *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *threepidStatements) prepare(db *sql.DB) (err error) {
|
||||||
|
_, err = db.Exec(threepidSchema)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.selectLocalpartForThreePIDStmt, err = db.Prepare(selectLocalpartForThreePIDSQL); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.selectThreePIDsForLocalpartStmt, err = db.Prepare(selectThreePIDsForLocalpartSQL); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.insertThreePIDStmt, err = db.Prepare(insertThreePIDSQL); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.deleteThreePIDStmt, err = db.Prepare(deleteThreePIDSQL); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *threepidStatements) selectLocalpartForThreePID(txn *sql.Tx, threepid string) (localpart string, err error) {
|
||||||
|
var stmt *sql.Stmt
|
||||||
|
if txn != nil {
|
||||||
|
stmt = txn.Stmt(s.selectLocalpartForThreePIDStmt)
|
||||||
|
} else {
|
||||||
|
stmt = s.selectLocalpartForThreePIDStmt
|
||||||
|
}
|
||||||
|
err = stmt.QueryRow(threepid).Scan(&localpart)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *threepidStatements) selectThreePIDsForLocalpart(localpart string) (threepids map[string]string, err error) {
|
||||||
|
rows, err := s.selectThreePIDsForLocalpartStmt.Query(localpart)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
threepids = make(map[string]string)
|
||||||
|
for rows.Next() {
|
||||||
|
var threepid string
|
||||||
|
var medium string
|
||||||
|
if err = rows.Scan(&threepid, &medium); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
threepids[threepid] = medium
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *threepidStatements) insertThreePID(txn *sql.Tx, threepid string, localpart string) (err error) {
|
||||||
|
_, err = txn.Stmt(s.insertThreePIDStmt).Exec(threepid, localpart)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *threepidStatements) deleteThreePID(threepid string) (err error) {
|
||||||
|
_, err = s.deleteThreePIDStmt.Exec(threepid)
|
||||||
|
return
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue