mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-16 19:33:09 -06:00
Merge branch 'master' of https://github.com/matrix-org/dendrite into prateek
This commit is contained in:
commit
415c3bdd77
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -43,3 +43,9 @@ _testmain.go
|
|||
|
||||
# Default configuration file
|
||||
dendrite.yaml
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
|
||||
# Log files
|
||||
*.log*
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ linters-settings:
|
|||
#local-prefixes: github.com/org/project
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 12
|
||||
min-complexity: 13
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
|
|
|
|||
|
|
@ -28,3 +28,4 @@ discussion should happen in
|
|||
|
||||
There's plenty still to do to make Dendrite usable! We're tracking progress in a
|
||||
[project board](https://github.com/matrix-org/dendrite/projects/2).
|
||||
|
||||
|
|
|
|||
|
|
@ -114,19 +114,19 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error {
|
|||
// lookupMissingStateEvents looks up the state events that are added by a new event,
|
||||
// and returns any not already present.
|
||||
func (s *OutputRoomEventConsumer) lookupMissingStateEvents(
|
||||
addsStateEventIDs []string, event gomatrixserverlib.Event,
|
||||
) ([]gomatrixserverlib.Event, error) {
|
||||
addsStateEventIDs []string, event gomatrixserverlib.HeaderedEvent,
|
||||
) ([]gomatrixserverlib.HeaderedEvent, error) {
|
||||
// Fast path if there aren't any new state events.
|
||||
if len(addsStateEventIDs) == 0 {
|
||||
return []gomatrixserverlib.Event{}, nil
|
||||
return []gomatrixserverlib.HeaderedEvent{}, nil
|
||||
}
|
||||
|
||||
// Fast path if the only state event added is the event itself.
|
||||
if len(addsStateEventIDs) == 1 && addsStateEventIDs[0] == event.EventID() {
|
||||
return []gomatrixserverlib.Event{}, nil
|
||||
return []gomatrixserverlib.HeaderedEvent{}, nil
|
||||
}
|
||||
|
||||
result := []gomatrixserverlib.Event{}
|
||||
result := []gomatrixserverlib.HeaderedEvent{}
|
||||
missing := []string{}
|
||||
for _, id := range addsStateEventIDs {
|
||||
if id != event.EventID() {
|
||||
|
|
@ -155,7 +155,7 @@ func (s *OutputRoomEventConsumer) lookupMissingStateEvents(
|
|||
// application service.
|
||||
func (s *OutputRoomEventConsumer) filterRoomserverEvents(
|
||||
ctx context.Context,
|
||||
events []gomatrixserverlib.Event,
|
||||
events []gomatrixserverlib.HeaderedEvent,
|
||||
) error {
|
||||
for _, ws := range s.workerStates {
|
||||
for _, event := range events {
|
||||
|
|
@ -178,7 +178,7 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(
|
|||
|
||||
// appserviceIsInterestedInEvent returns a boolean depending on whether a given
|
||||
// event falls within one of a given application service's namespaces.
|
||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event gomatrixserverlib.Event, appservice config.ApplicationService) bool {
|
||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event gomatrixserverlib.HeaderedEvent, appservice config.ApplicationService) bool {
|
||||
// No reason to queue events if they'll never be sent to the application
|
||||
// service
|
||||
if appservice.URL == "" {
|
||||
|
|
@ -191,6 +191,12 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
|||
return true
|
||||
}
|
||||
|
||||
if event.Type() == gomatrixserverlib.MRoomMember && event.StateKey() != nil {
|
||||
if appservice.IsInterestedInUserID(*event.StateKey()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Check all known room aliases of the room the event came from
|
||||
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID()}
|
||||
var queryRes api.GetAliasesForRoomIDResponse
|
||||
|
|
|
|||
30
appservice/storage/interface.go
Normal file
30
appservice/storage/interface.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
StoreEvent(ctx context.Context, appServiceID string, event *gomatrixserverlib.HeaderedEvent) error
|
||||
GetEventsWithAppServiceID(ctx context.Context, appServiceID string, limit int) (int, int, []gomatrixserverlib.HeaderedEvent, bool, error)
|
||||
CountEventsWithAppServiceID(ctx context.Context, appServiceID string) (int, error)
|
||||
UpdateTxnIDForEvents(ctx context.Context, appserviceID string, maxID, txnID int) error
|
||||
RemoveEventsBeforeAndIncludingID(ctx context.Context, appserviceID string, eventTableID int) error
|
||||
GetLatestTxnID(ctx context.Context) (int, error)
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ CREATE TABLE IF NOT EXISTS appservice_events (
|
|||
-- The ID of the application service the event will be sent to
|
||||
as_id TEXT NOT NULL,
|
||||
-- JSON representation of the event
|
||||
event_json TEXT NOT NULL,
|
||||
headered_event_json TEXT NOT NULL,
|
||||
-- The ID of the transaction that this event is a part of
|
||||
txn_id BIGINT NOT NULL
|
||||
);
|
||||
|
|
@ -42,14 +42,14 @@ CREATE INDEX IF NOT EXISTS appservice_events_as_id ON appservice_events(as_id);
|
|||
`
|
||||
|
||||
const selectEventsByApplicationServiceIDSQL = "" +
|
||||
"SELECT id, event_json, txn_id " +
|
||||
"SELECT id, headered_event_json, txn_id " +
|
||||
"FROM appservice_events WHERE as_id = $1 ORDER BY txn_id DESC, id ASC"
|
||||
|
||||
const countEventsByApplicationServiceIDSQL = "" +
|
||||
"SELECT COUNT(id) FROM appservice_events WHERE as_id = $1"
|
||||
|
||||
const insertEventSQL = "" +
|
||||
"INSERT INTO appservice_events(as_id, event_json, txn_id) " +
|
||||
"INSERT INTO appservice_events(as_id, headered_event_json, txn_id) " +
|
||||
"VALUES ($1, $2, $3)"
|
||||
|
||||
const updateTxnIDForEventsSQL = "" +
|
||||
|
|
@ -107,7 +107,7 @@ func (s *eventsStatements) selectEventsByApplicationServiceID(
|
|||
limit int,
|
||||
) (
|
||||
txnID, maxID int,
|
||||
events []gomatrixserverlib.Event,
|
||||
events []gomatrixserverlib.HeaderedEvent,
|
||||
eventsRemaining bool,
|
||||
err error,
|
||||
) {
|
||||
|
|
@ -132,7 +132,7 @@ func (s *eventsStatements) selectEventsByApplicationServiceID(
|
|||
return
|
||||
}
|
||||
|
||||
func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.Event, maxID, txnID int, eventsRemaining bool, err error) {
|
||||
func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.HeaderedEvent, maxID, txnID int, eventsRemaining bool, err error) {
|
||||
// Get current time for use in calculating event age
|
||||
nowMilli := time.Now().UnixNano() / int64(time.Millisecond)
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.
|
|||
// new ones. Send back those events first.
|
||||
lastTxnID := invalidTxnID
|
||||
for eventsProcessed := 0; eventRows.Next(); {
|
||||
var event gomatrixserverlib.Event
|
||||
var event gomatrixserverlib.HeaderedEvent
|
||||
var eventJSON []byte
|
||||
var id int
|
||||
err = eventRows.Scan(
|
||||
|
|
@ -209,7 +209,7 @@ func (s *eventsStatements) countEventsByApplicationServiceID(
|
|||
func (s *eventsStatements) insertEvent(
|
||||
ctx context.Context,
|
||||
appServiceID string,
|
||||
event *gomatrixserverlib.Event,
|
||||
event *gomatrixserverlib.HeaderedEvent,
|
||||
) (err error) {
|
||||
// Convert event to JSON before inserting
|
||||
eventJSON, err := json.Marshal(event)
|
||||
|
|
|
|||
|
|
@ -52,12 +52,12 @@ func (d *Database) prepare() error {
|
|||
return d.txnID.prepare(d.db)
|
||||
}
|
||||
|
||||
// StoreEvent takes in a gomatrixserverlib.Event and stores it in the database
|
||||
// StoreEvent takes in a gomatrixserverlib.HeaderedEvent and stores it in the database
|
||||
// for a transaction worker to pull and later send to an application service.
|
||||
func (d *Database) StoreEvent(
|
||||
ctx context.Context,
|
||||
appServiceID string,
|
||||
event *gomatrixserverlib.Event,
|
||||
event *gomatrixserverlib.HeaderedEvent,
|
||||
) error {
|
||||
return d.events.insertEvent(ctx, appServiceID, event)
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ func (d *Database) GetEventsWithAppServiceID(
|
|||
ctx context.Context,
|
||||
appServiceID string,
|
||||
limit int,
|
||||
) (int, int, []gomatrixserverlib.Event, bool, error) {
|
||||
) (int, int, []gomatrixserverlib.HeaderedEvent, bool, error) {
|
||||
return d.events.selectEventsByApplicationServiceID(ctx, appServiceID, limit)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ CREATE TABLE IF NOT EXISTS appservice_events (
|
|||
-- The ID of the application service the event will be sent to
|
||||
as_id TEXT NOT NULL,
|
||||
-- JSON representation of the event
|
||||
event_json TEXT NOT NULL,
|
||||
headered_event_json TEXT NOT NULL,
|
||||
-- The ID of the transaction that this event is a part of
|
||||
txn_id INTEGER NOT NULL
|
||||
);
|
||||
|
|
@ -42,14 +42,14 @@ CREATE INDEX IF NOT EXISTS appservice_events_as_id ON appservice_events(as_id);
|
|||
`
|
||||
|
||||
const selectEventsByApplicationServiceIDSQL = "" +
|
||||
"SELECT id, event_json, txn_id " +
|
||||
"SELECT id, headered_event_json, txn_id " +
|
||||
"FROM appservice_events WHERE as_id = $1 ORDER BY txn_id DESC, id ASC"
|
||||
|
||||
const countEventsByApplicationServiceIDSQL = "" +
|
||||
"SELECT COUNT(id) FROM appservice_events WHERE as_id = $1"
|
||||
|
||||
const insertEventSQL = "" +
|
||||
"INSERT INTO appservice_events(as_id, event_json, txn_id) " +
|
||||
"INSERT INTO appservice_events(as_id, headered_event_json, txn_id) " +
|
||||
"VALUES ($1, $2, $3)"
|
||||
|
||||
const updateTxnIDForEventsSQL = "" +
|
||||
|
|
@ -107,7 +107,7 @@ func (s *eventsStatements) selectEventsByApplicationServiceID(
|
|||
limit int,
|
||||
) (
|
||||
txnID, maxID int,
|
||||
events []gomatrixserverlib.Event,
|
||||
events []gomatrixserverlib.HeaderedEvent,
|
||||
eventsRemaining bool,
|
||||
err error,
|
||||
) {
|
||||
|
|
@ -132,7 +132,7 @@ func (s *eventsStatements) selectEventsByApplicationServiceID(
|
|||
return
|
||||
}
|
||||
|
||||
func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.Event, maxID, txnID int, eventsRemaining bool, err error) {
|
||||
func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.HeaderedEvent, maxID, txnID int, eventsRemaining bool, err error) {
|
||||
// Get current time for use in calculating event age
|
||||
nowMilli := time.Now().UnixNano() / int64(time.Millisecond)
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ func retrieveEvents(eventRows *sql.Rows, limit int) (events []gomatrixserverlib.
|
|||
// new ones. Send back those events first.
|
||||
lastTxnID := invalidTxnID
|
||||
for eventsProcessed := 0; eventRows.Next(); {
|
||||
var event gomatrixserverlib.Event
|
||||
var event gomatrixserverlib.HeaderedEvent
|
||||
var eventJSON []byte
|
||||
var id int
|
||||
err = eventRows.Scan(
|
||||
|
|
@ -209,7 +209,7 @@ func (s *eventsStatements) countEventsByApplicationServiceID(
|
|||
func (s *eventsStatements) insertEvent(
|
||||
ctx context.Context,
|
||||
appServiceID string,
|
||||
event *gomatrixserverlib.Event,
|
||||
event *gomatrixserverlib.HeaderedEvent,
|
||||
) (err error) {
|
||||
// Convert event to JSON before inserting
|
||||
eventJSON, err := json.Marshal(event)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"database/sql"
|
||||
|
||||
// Import SQLite database driver
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
|
@ -35,7 +36,7 @@ type Database struct {
|
|||
func NewDatabase(dataSourceName string) (*Database, error) {
|
||||
var result Database
|
||||
var err error
|
||||
if result.db, err = sql.Open("sqlite3", dataSourceName); err != nil {
|
||||
if result.db, err = sql.Open(common.SQLiteDriverName(), dataSourceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = result.prepare(); err != nil {
|
||||
|
|
@ -52,12 +53,12 @@ func (d *Database) prepare() error {
|
|||
return d.txnID.prepare(d.db)
|
||||
}
|
||||
|
||||
// StoreEvent takes in a gomatrixserverlib.Event and stores it in the database
|
||||
// StoreEvent takes in a gomatrixserverlib.HeaderedEvent and stores it in the database
|
||||
// for a transaction worker to pull and later send to an application service.
|
||||
func (d *Database) StoreEvent(
|
||||
ctx context.Context,
|
||||
appServiceID string,
|
||||
event *gomatrixserverlib.Event,
|
||||
event *gomatrixserverlib.HeaderedEvent,
|
||||
) error {
|
||||
return d.events.insertEvent(ctx, appServiceID, event)
|
||||
}
|
||||
|
|
@ -68,7 +69,7 @@ func (d *Database) GetEventsWithAppServiceID(
|
|||
ctx context.Context,
|
||||
appServiceID string,
|
||||
limit int,
|
||||
) (int, int, []gomatrixserverlib.Event, bool, error) {
|
||||
) (int, int, []gomatrixserverlib.HeaderedEvent, bool, error) {
|
||||
return d.events.selectEventsByApplicationServiceID(ctx, appServiceID, limit)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,26 +12,17 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/appservice/storage/postgres"
|
||||
"github.com/matrix-org/dendrite/appservice/storage/sqlite3"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
StoreEvent(ctx context.Context, appServiceID string, event *gomatrixserverlib.Event) error
|
||||
GetEventsWithAppServiceID(ctx context.Context, appServiceID string, limit int) (int, int, []gomatrixserverlib.Event, bool, error)
|
||||
CountEventsWithAppServiceID(ctx context.Context, appServiceID string) (int, error)
|
||||
UpdateTxnIDForEvents(ctx context.Context, appserviceID string, maxID, txnID int) error
|
||||
RemoveEventsBeforeAndIncludingID(ctx context.Context, appserviceID string, eventTableID int) error
|
||||
GetLatestTxnID(ctx context.Context) (int, error)
|
||||
}
|
||||
|
||||
func NewDatabase(dataSourceName string) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
|
|
|
|||
37
appservice/storage/storage_wasm.go
Normal file
37
appservice/storage/storage_wasm.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/appservice/storage/sqlite3"
|
||||
)
|
||||
|
||||
func NewDatabase(dataSourceName string) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
switch uri.Scheme {
|
||||
case "postgres":
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
case "file":
|
||||
return sqlite3.NewDatabase(dataSourceName)
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
}
|
||||
|
|
@ -181,9 +181,14 @@ func createTransaction(
|
|||
}
|
||||
}
|
||||
|
||||
var ev []gomatrixserverlib.Event
|
||||
for _, e := range events {
|
||||
ev = append(ev, e.Event)
|
||||
}
|
||||
|
||||
// Create a transaction and store the events inside
|
||||
transaction := gomatrixserverlib.ApplicationServiceTransaction{
|
||||
Events: events,
|
||||
Events: ev,
|
||||
}
|
||||
|
||||
transactionJSON, err = json.Marshal(transaction)
|
||||
|
|
|
|||
7
build.sh
7
build.sh
|
|
@ -1,3 +1,6 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash -eu
|
||||
|
||||
GOBIN=$PWD/`dirname $0`/bin go install -v $PWD/`dirname $0`/cmd/...
|
||||
# Put installed packages into ./bin
|
||||
export GOBIN=$PWD/`dirname $0`/bin
|
||||
|
||||
go install -v $PWD/`dirname $0`/cmd/...
|
||||
|
|
@ -26,7 +26,6 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/appservice/types"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
|
|
@ -166,7 +165,8 @@ func verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *auth
|
|||
JSON: jsonerror.UnknownToken("Unknown token"),
|
||||
}
|
||||
} else {
|
||||
jsonErr := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDeviceByAccessToken failed")
|
||||
jsonErr := jsonerror.InternalServerError()
|
||||
resErr = &jsonErr
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,4 +26,5 @@ type Device struct {
|
|||
// associated with access tokens.
|
||||
SessionID int64
|
||||
// TODO: display name, last used timestamp, keys, etc
|
||||
DisplayName string
|
||||
}
|
||||
|
|
|
|||
54
clientapi/auth/storage/accounts/interface.go
Normal file
54
clientapi/auth/storage/accounts/interface.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
common.PartitionStorer
|
||||
GetAccountByPassword(ctx context.Context, localpart, plaintextPassword string) (*authtypes.Account, error)
|
||||
GetProfileByLocalpart(ctx context.Context, localpart string) (*authtypes.Profile, error)
|
||||
SetAvatarURL(ctx context.Context, localpart string, avatarURL string) error
|
||||
SetDisplayName(ctx context.Context, localpart string, displayName string) error
|
||||
CreateAccount(ctx context.Context, localpart, plaintextPassword, appserviceID string) (*authtypes.Account, error)
|
||||
CreateGuestAccount(ctx context.Context) (*authtypes.Account, error)
|
||||
UpdateMemberships(ctx context.Context, eventsToAdd []gomatrixserverlib.Event, idsToRemove []string) error
|
||||
GetMembershipInRoomByLocalpart(ctx context.Context, localpart, roomID string) (authtypes.Membership, error)
|
||||
GetRoomIDsByLocalPart(ctx context.Context, localpart string) ([]string, error)
|
||||
GetMembershipsByLocalpart(ctx context.Context, localpart string) (memberships []authtypes.Membership, err error)
|
||||
SaveAccountData(ctx context.Context, localpart, roomID, dataType, content string) error
|
||||
GetAccountData(ctx context.Context, localpart string) (global []gomatrixserverlib.ClientEvent, rooms map[string][]gomatrixserverlib.ClientEvent, err error)
|
||||
GetAccountDataByType(ctx context.Context, localpart, roomID, dataType string) (data *gomatrixserverlib.ClientEvent, err error)
|
||||
GetNewNumericLocalpart(ctx context.Context) (int64, error)
|
||||
SaveThreePIDAssociation(ctx context.Context, threepid, localpart, medium string) (err error)
|
||||
RemoveThreePIDAssociation(ctx context.Context, threepid string, medium string) (err error)
|
||||
GetLocalpartForThreePID(ctx context.Context, threepid string, medium string) (localpart string, err error)
|
||||
GetThreePIDsForLocalpart(ctx context.Context, localpart string) (threepids []authtypes.ThreePID, err error)
|
||||
GetFilter(ctx context.Context, localpart string, filterID string) (*gomatrixserverlib.Filter, error)
|
||||
PutFilter(ctx context.Context, localpart string, filter *gomatrixserverlib.Filter) (string, error)
|
||||
CheckAccountAvailability(ctx context.Context, localpart string) (bool, error)
|
||||
GetAccountByLocalpart(ctx context.Context, localpart string) (*authtypes.Account, error)
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
|
@ -18,6 +18,8 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
|
|
@ -72,9 +74,9 @@ func (s *accountDataStatements) prepare(db *sql.DB) (err error) {
|
|||
}
|
||||
|
||||
func (s *accountDataStatements) insertAccountData(
|
||||
ctx context.Context, localpart, roomID, dataType, content string,
|
||||
ctx context.Context, txn *sql.Tx, localpart, roomID, dataType, content string,
|
||||
) (err error) {
|
||||
stmt := s.insertAccountDataStmt
|
||||
stmt := txn.Stmt(s.insertAccountDataStmt)
|
||||
_, err = stmt.ExecContext(ctx, localpart, roomID, dataType, content)
|
||||
return
|
||||
}
|
||||
|
|
@ -90,7 +92,7 @@ func (s *accountDataStatements) selectAccountData(
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "selectAccountData: rows.close() failed")
|
||||
|
||||
global = []gomatrixserverlib.ClientEvent{}
|
||||
rooms = make(map[string][]gomatrixserverlib.ClientEvent)
|
||||
|
|
|
|||
|
|
@ -91,10 +91,10 @@ func (s *accountsStatements) prepare(db *sql.DB, server gomatrixserverlib.Server
|
|||
// this account will be passwordless. Returns an error if this account already exists. Returns the account
|
||||
// on success.
|
||||
func (s *accountsStatements) insertAccount(
|
||||
ctx context.Context, localpart, hash, appserviceID string,
|
||||
ctx context.Context, txn *sql.Tx, localpart, hash, appserviceID string,
|
||||
) (*authtypes.Account, error) {
|
||||
createdTimeMS := time.Now().UnixNano() / 1000000
|
||||
stmt := s.insertAccountStmt
|
||||
stmt := txn.Stmt(s.insertAccountStmt)
|
||||
|
||||
var err error
|
||||
if appserviceID == "" {
|
||||
|
|
@ -146,8 +146,12 @@ func (s *accountsStatements) selectAccountByLocalpart(
|
|||
}
|
||||
|
||||
func (s *accountsStatements) selectNewNumericLocalpart(
|
||||
ctx context.Context,
|
||||
ctx context.Context, txn *sql.Tx,
|
||||
) (id int64, err error) {
|
||||
err = s.selectNewNumericLocalpartStmt.QueryRowContext(ctx).Scan(&id)
|
||||
stmt := s.selectNewNumericLocalpartStmt
|
||||
if txn != nil {
|
||||
stmt = txn.Stmt(stmt)
|
||||
}
|
||||
err = stmt.QueryRowContext(ctx).Scan(&id)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
)
|
||||
|
|
@ -51,6 +53,9 @@ const selectMembershipsByLocalpartSQL = "" +
|
|||
const selectMembershipInRoomByLocalpartSQL = "" +
|
||||
"SELECT event_id FROM account_memberships WHERE localpart = $1 AND room_id = $2"
|
||||
|
||||
const selectRoomIDsByLocalPartSQL = "" +
|
||||
"SELECT room_id FROM account_memberships WHERE localpart = $1"
|
||||
|
||||
const deleteMembershipsByEventIDsSQL = "" +
|
||||
"DELETE FROM account_memberships WHERE event_id = ANY($1)"
|
||||
|
||||
|
|
@ -59,6 +64,7 @@ type membershipStatements struct {
|
|||
insertMembershipStmt *sql.Stmt
|
||||
selectMembershipInRoomByLocalpartStmt *sql.Stmt
|
||||
selectMembershipsByLocalpartStmt *sql.Stmt
|
||||
selectRoomIDsByLocalPartStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
||||
|
|
@ -78,6 +84,9 @@ func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
|||
if s.selectMembershipsByLocalpartStmt, err = db.Prepare(selectMembershipsByLocalpartSQL); err != nil {
|
||||
return
|
||||
}
|
||||
if s.selectRoomIDsByLocalPartStmt, err = db.Prepare(selectRoomIDsByLocalPartSQL); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +127,7 @@ func (s *membershipStatements) selectMembershipsByLocalpart(
|
|||
|
||||
memberships = []authtypes.Membership{}
|
||||
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "selectMembershipsByLocalpart: rows.close() failed")
|
||||
for rows.Next() {
|
||||
var m authtypes.Membership
|
||||
m.Localpart = localpart
|
||||
|
|
@ -129,3 +138,23 @@ func (s *membershipStatements) selectMembershipsByLocalpart(
|
|||
}
|
||||
return memberships, rows.Err()
|
||||
}
|
||||
|
||||
func (s *membershipStatements) selectRoomIDsByLocalPart(
|
||||
ctx context.Context, localPart string,
|
||||
) ([]string, error) {
|
||||
stmt := s.selectRoomIDsByLocalPartStmt
|
||||
rows, err := stmt.QueryContext(ctx, localPart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomIDs := []string{}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
for rows.Next() {
|
||||
var roomID string
|
||||
if err = rows.Scan(&roomID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomIDs = append(roomIDs, roomID)
|
||||
}
|
||||
return roomIDs, rows.Err()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ func (s *profilesStatements) prepare(db *sql.DB) (err error) {
|
|||
}
|
||||
|
||||
func (s *profilesStatements) insertProfile(
|
||||
ctx context.Context, localpart string,
|
||||
ctx context.Context, txn *sql.Tx, localpart string,
|
||||
) (err error) {
|
||||
_, err = s.insertProfileStmt.ExecContext(ctx, localpart, "", "")
|
||||
_, err = txn.Stmt(s.insertProfileStmt).ExecContext(ctx, localpart, "", "")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
|
@ -118,11 +119,37 @@ func (d *Database) SetDisplayName(
|
|||
return d.profiles.setDisplayName(ctx, localpart, displayName)
|
||||
}
|
||||
|
||||
// CreateGuestAccount makes a new guest account and creates an empty profile
|
||||
// for this account.
|
||||
func (d *Database) CreateGuestAccount(ctx context.Context) (acc *authtypes.Account, err error) {
|
||||
err = common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
var numLocalpart int64
|
||||
numLocalpart, err = d.accounts.selectNewNumericLocalpart(ctx, txn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localpart := strconv.FormatInt(numLocalpart, 10)
|
||||
acc, err = d.createAccount(ctx, txn, localpart, "", "")
|
||||
return err
|
||||
})
|
||||
return acc, err
|
||||
}
|
||||
|
||||
// CreateAccount makes a new account with the given login name and password, and creates an empty profile
|
||||
// for this account. If no password is supplied, the account will be a passwordless account. If the
|
||||
// account already exists, it will return nil, nil.
|
||||
func (d *Database) CreateAccount(
|
||||
ctx context.Context, localpart, plaintextPassword, appserviceID string,
|
||||
) (acc *authtypes.Account, err error) {
|
||||
err = common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
acc, err = d.createAccount(ctx, txn, localpart, plaintextPassword, appserviceID)
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Database) createAccount(
|
||||
ctx context.Context, txn *sql.Tx, localpart, plaintextPassword, appserviceID string,
|
||||
) (*authtypes.Account, error) {
|
||||
var err error
|
||||
|
||||
|
|
@ -134,13 +161,14 @@ func (d *Database) CreateAccount(
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := d.profiles.insertProfile(ctx, localpart); err != nil {
|
||||
if err := d.profiles.insertProfile(ctx, txn, localpart); err != nil {
|
||||
if common.IsUniqueConstraintViolationErr(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := d.SaveAccountData(ctx, localpart, "", "m.push_rules", `{
|
||||
|
||||
if err := d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", `{
|
||||
"global": {
|
||||
"content": [],
|
||||
"override": [],
|
||||
|
|
@ -151,7 +179,7 @@ func (d *Database) CreateAccount(
|
|||
}`); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.accounts.insertAccount(ctx, localpart, hash, appserviceID)
|
||||
return d.accounts.insertAccount(ctx, txn, localpart, hash, appserviceID)
|
||||
}
|
||||
|
||||
// SaveMembership saves the user matching a given localpart as a member of a given
|
||||
|
|
@ -206,6 +234,16 @@ func (d *Database) GetMembershipInRoomByLocalpart(
|
|||
return d.memberships.selectMembershipInRoomByLocalpart(ctx, localpart, roomID)
|
||||
}
|
||||
|
||||
// GetRoomIDsByLocalPart returns an array containing the room ids of all
|
||||
// the rooms a user matching a given localpart is a member of
|
||||
// If no membership match the given localpart, returns an empty array
|
||||
// If there was an issue during the retrieval, returns the SQL error
|
||||
func (d *Database) GetRoomIDsByLocalPart(
|
||||
ctx context.Context, localpart string,
|
||||
) ([]string, error) {
|
||||
return d.memberships.selectRoomIDsByLocalPart(ctx, localpart)
|
||||
}
|
||||
|
||||
// GetMembershipsByLocalpart returns an array containing the memberships for all
|
||||
// the rooms a user matching a given localpart is a member of
|
||||
// If no membership match the given localpart, returns an empty array
|
||||
|
|
@ -258,7 +296,9 @@ func (d *Database) newMembership(
|
|||
func (d *Database) SaveAccountData(
|
||||
ctx context.Context, localpart, roomID, dataType, content string,
|
||||
) error {
|
||||
return d.accountDatas.insertAccountData(ctx, localpart, roomID, dataType, content)
|
||||
return common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
return d.accountDatas.insertAccountData(ctx, txn, localpart, roomID, dataType, content)
|
||||
})
|
||||
}
|
||||
|
||||
// GetAccountData returns account data related to a given localpart
|
||||
|
|
@ -288,7 +328,7 @@ func (d *Database) GetAccountDataByType(
|
|||
func (d *Database) GetNewNumericLocalpart(
|
||||
ctx context.Context,
|
||||
) (int64, error) {
|
||||
return d.accounts.selectNewNumericLocalpart(ctx)
|
||||
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
||||
}
|
||||
|
||||
func hashPassword(plaintext string) (hash string, err error) {
|
||||
|
|
|
|||
|
|
@ -72,10 +72,9 @@ func (s *accountDataStatements) prepare(db *sql.DB) (err error) {
|
|||
}
|
||||
|
||||
func (s *accountDataStatements) insertAccountData(
|
||||
ctx context.Context, localpart, roomID, dataType, content string,
|
||||
ctx context.Context, txn *sql.Tx, localpart, roomID, dataType, content string,
|
||||
) (err error) {
|
||||
stmt := s.insertAccountDataStmt
|
||||
_, err = stmt.ExecContext(ctx, localpart, roomID, dataType, content)
|
||||
_, err = txn.Stmt(s.insertAccountDataStmt).ExecContext(ctx, localpart, roomID, dataType, content)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,16 +89,16 @@ func (s *accountsStatements) prepare(db *sql.DB, server gomatrixserverlib.Server
|
|||
// this account will be passwordless. Returns an error if this account already exists. Returns the account
|
||||
// on success.
|
||||
func (s *accountsStatements) insertAccount(
|
||||
ctx context.Context, localpart, hash, appserviceID string,
|
||||
ctx context.Context, txn *sql.Tx, localpart, hash, appserviceID string,
|
||||
) (*authtypes.Account, error) {
|
||||
createdTimeMS := time.Now().UnixNano() / 1000000
|
||||
stmt := s.insertAccountStmt
|
||||
|
||||
var err error
|
||||
if appserviceID == "" {
|
||||
_, err = stmt.ExecContext(ctx, localpart, createdTimeMS, hash, nil)
|
||||
_, err = txn.Stmt(stmt).ExecContext(ctx, localpart, createdTimeMS, hash, nil)
|
||||
} else {
|
||||
_, err = stmt.ExecContext(ctx, localpart, createdTimeMS, hash, appserviceID)
|
||||
_, err = txn.Stmt(stmt).ExecContext(ctx, localpart, createdTimeMS, hash, appserviceID)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -144,8 +144,12 @@ func (s *accountsStatements) selectAccountByLocalpart(
|
|||
}
|
||||
|
||||
func (s *accountsStatements) selectNewNumericLocalpart(
|
||||
ctx context.Context,
|
||||
ctx context.Context, txn *sql.Tx,
|
||||
) (id int64, err error) {
|
||||
err = s.selectNewNumericLocalpartStmt.QueryRowContext(ctx).Scan(&id)
|
||||
stmt := s.selectNewNumericLocalpartStmt
|
||||
if txn != nil {
|
||||
stmt = txn.Stmt(stmt)
|
||||
}
|
||||
err = stmt.QueryRowContext(ctx).Scan(&id)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ package sqlite3
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
)
|
||||
|
||||
const membershipSchema = `
|
||||
|
|
@ -50,14 +51,17 @@ const selectMembershipsByLocalpartSQL = "" +
|
|||
const selectMembershipInRoomByLocalpartSQL = "" +
|
||||
"SELECT event_id FROM account_memberships WHERE localpart = $1 AND room_id = $2"
|
||||
|
||||
const selectRoomIDsByLocalPartSQL = "" +
|
||||
"SELECT room_id FROM account_memberships WHERE localpart = $1"
|
||||
|
||||
const deleteMembershipsByEventIDsSQL = "" +
|
||||
"DELETE FROM account_memberships WHERE event_id IN ($1)"
|
||||
|
||||
type membershipStatements struct {
|
||||
deleteMembershipsByEventIDsStmt *sql.Stmt
|
||||
insertMembershipStmt *sql.Stmt
|
||||
selectMembershipInRoomByLocalpartStmt *sql.Stmt
|
||||
selectMembershipsByLocalpartStmt *sql.Stmt
|
||||
selectRoomIDsByLocalPartStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
||||
|
|
@ -65,9 +69,6 @@ func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if s.deleteMembershipsByEventIDsStmt, err = db.Prepare(deleteMembershipsByEventIDsSQL); err != nil {
|
||||
return
|
||||
}
|
||||
if s.insertMembershipStmt, err = db.Prepare(insertMembershipSQL); err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -77,6 +78,9 @@ func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
|||
if s.selectMembershipsByLocalpartStmt, err = db.Prepare(selectMembershipsByLocalpartSQL); err != nil {
|
||||
return
|
||||
}
|
||||
if s.selectRoomIDsByLocalPartStmt, err = db.Prepare(selectRoomIDsByLocalPartSQL); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -91,8 +95,12 @@ func (s *membershipStatements) insertMembership(
|
|||
func (s *membershipStatements) deleteMembershipsByEventIDs(
|
||||
ctx context.Context, txn *sql.Tx, eventIDs []string,
|
||||
) (err error) {
|
||||
stmt := txn.Stmt(s.deleteMembershipsByEventIDsStmt)
|
||||
_, err = stmt.ExecContext(ctx, pq.StringArray(eventIDs))
|
||||
sqlStr := strings.Replace(deleteMembershipsByEventIDsSQL, "($1)", common.QueryVariadic(len(eventIDs)), 1)
|
||||
iEventIDs := make([]interface{}, len(eventIDs))
|
||||
for i, e := range eventIDs {
|
||||
iEventIDs[i] = e
|
||||
}
|
||||
_, err = txn.ExecContext(ctx, sqlStr, iEventIDs...)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +125,7 @@ func (s *membershipStatements) selectMembershipsByLocalpart(
|
|||
|
||||
memberships = []authtypes.Membership{}
|
||||
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "selectMembershipsByLocalpart: rows.close() failed")
|
||||
for rows.Next() {
|
||||
var m authtypes.Membership
|
||||
m.Localpart = localpart
|
||||
|
|
@ -129,3 +137,22 @@ func (s *membershipStatements) selectMembershipsByLocalpart(
|
|||
|
||||
return
|
||||
}
|
||||
func (s *membershipStatements) selectRoomIDsByLocalPart(
|
||||
ctx context.Context, localPart string,
|
||||
) ([]string, error) {
|
||||
stmt := s.selectRoomIDsByLocalPartStmt
|
||||
rows, err := stmt.QueryContext(ctx, localPart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomIDs := []string{}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
for rows.Next() {
|
||||
var roomID string
|
||||
if err = rows.Scan(&roomID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomIDs = append(roomIDs, roomID)
|
||||
}
|
||||
return roomIDs, rows.Err()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ func (s *profilesStatements) prepare(db *sql.DB) (err error) {
|
|||
}
|
||||
|
||||
func (s *profilesStatements) insertProfile(
|
||||
ctx context.Context, localpart string,
|
||||
ctx context.Context, txn *sql.Tx, localpart string,
|
||||
) (err error) {
|
||||
_, err = s.insertProfileStmt.ExecContext(ctx, localpart, "", "")
|
||||
_, err = txn.Stmt(s.insertProfileStmt).ExecContext(ctx, localpart, "", "")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
|
@ -39,13 +41,15 @@ type Database struct {
|
|||
threepids threepidStatements
|
||||
filter filterStatements
|
||||
serverName gomatrixserverlib.ServerName
|
||||
|
||||
createGuestAccountMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDatabase creates a new accounts and profiles database
|
||||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
||||
var db *sql.DB
|
||||
var err error
|
||||
if db, err = sql.Open("sqlite3", dataSourceName); err != nil {
|
||||
if db, err = sql.Open(common.SQLiteDriverName(), dataSourceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
partitions := common.PartitionOffsetStatements{}
|
||||
|
|
@ -76,7 +80,7 @@ func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName)
|
|||
if err = f.prepare(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Database{db, partitions, a, p, m, ac, t, f, serverName}, nil
|
||||
return &Database{db, partitions, a, p, m, ac, t, f, serverName, sync.Mutex{}}, nil
|
||||
}
|
||||
|
||||
// GetAccountByPassword returns the account associated with the given localpart and password.
|
||||
|
|
@ -118,14 +122,46 @@ func (d *Database) SetDisplayName(
|
|||
return d.profiles.setDisplayName(ctx, localpart, displayName)
|
||||
}
|
||||
|
||||
// CreateGuestAccount makes a new guest account and creates an empty profile
|
||||
// for this account.
|
||||
func (d *Database) CreateGuestAccount(ctx context.Context) (acc *authtypes.Account, err error) {
|
||||
err = common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
// We need to lock so we sequentially create numeric localparts. If we don't, two calls to
|
||||
// this function will cause the same number to be selected and one will fail with 'database is locked'
|
||||
// when the first txn upgrades to a write txn.
|
||||
// We know we'll be the only process since this is sqlite ;) so a lock here will be all that is needed.
|
||||
d.createGuestAccountMu.Lock()
|
||||
defer d.createGuestAccountMu.Unlock()
|
||||
|
||||
var numLocalpart int64
|
||||
numLocalpart, err = d.accounts.selectNewNumericLocalpart(ctx, txn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localpart := strconv.FormatInt(numLocalpart, 10)
|
||||
acc, err = d.createAccount(ctx, txn, localpart, "", "")
|
||||
return err
|
||||
})
|
||||
return acc, err
|
||||
}
|
||||
|
||||
// CreateAccount makes a new account with the given login name and password, and creates an empty profile
|
||||
// for this account. If no password is supplied, the account will be a passwordless account. If the
|
||||
// account already exists, it will return nil, nil.
|
||||
func (d *Database) CreateAccount(
|
||||
ctx context.Context, localpart, plaintextPassword, appserviceID string,
|
||||
) (acc *authtypes.Account, err error) {
|
||||
err = common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
acc, err = d.createAccount(ctx, txn, localpart, plaintextPassword, appserviceID)
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Database) createAccount(
|
||||
ctx context.Context, txn *sql.Tx, localpart, plaintextPassword, appserviceID string,
|
||||
) (*authtypes.Account, error) {
|
||||
var err error
|
||||
|
||||
// Generate a password hash if this is not a password-less user
|
||||
hash := ""
|
||||
if plaintextPassword != "" {
|
||||
|
|
@ -134,13 +170,14 @@ func (d *Database) CreateAccount(
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := d.profiles.insertProfile(ctx, localpart); err != nil {
|
||||
if err := d.profiles.insertProfile(ctx, txn, localpart); err != nil {
|
||||
if common.IsUniqueConstraintViolationErr(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := d.SaveAccountData(ctx, localpart, "", "m.push_rules", `{
|
||||
|
||||
if err := d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", `{
|
||||
"global": {
|
||||
"content": [],
|
||||
"override": [],
|
||||
|
|
@ -151,7 +188,7 @@ func (d *Database) CreateAccount(
|
|||
}`); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.accounts.insertAccount(ctx, localpart, hash, appserviceID)
|
||||
return d.accounts.insertAccount(ctx, txn, localpart, hash, appserviceID)
|
||||
}
|
||||
|
||||
// SaveMembership saves the user matching a given localpart as a member of a given
|
||||
|
|
@ -216,6 +253,16 @@ func (d *Database) GetMembershipsByLocalpart(
|
|||
return d.memberships.selectMembershipsByLocalpart(ctx, localpart)
|
||||
}
|
||||
|
||||
// GetRoomIDsByLocalPart returns an array containing the room ids of all
|
||||
// the rooms a user matching a given localpart is a member of
|
||||
// If no membership match the given localpart, returns an empty array
|
||||
// If there was an issue during the retrieval, returns the SQL error
|
||||
func (d *Database) GetRoomIDsByLocalPart(
|
||||
ctx context.Context, localpart string,
|
||||
) ([]string, error) {
|
||||
return d.memberships.selectRoomIDsByLocalPart(ctx, localpart)
|
||||
}
|
||||
|
||||
// newMembership saves a new membership in the database.
|
||||
// If the event isn't a valid m.room.member event with type `join`, does nothing.
|
||||
// If an error occurred, returns the SQL error
|
||||
|
|
@ -258,7 +305,9 @@ func (d *Database) newMembership(
|
|||
func (d *Database) SaveAccountData(
|
||||
ctx context.Context, localpart, roomID, dataType, content string,
|
||||
) error {
|
||||
return d.accountDatas.insertAccountData(ctx, localpart, roomID, dataType, content)
|
||||
return common.WithTransaction(d.db, func(txn *sql.Tx) error {
|
||||
return d.accountDatas.insertAccountData(ctx, txn, localpart, roomID, dataType, content)
|
||||
})
|
||||
}
|
||||
|
||||
// GetAccountData returns account data related to a given localpart
|
||||
|
|
@ -288,7 +337,7 @@ func (d *Database) GetAccountDataByType(
|
|||
func (d *Database) GetNewNumericLocalpart(
|
||||
ctx context.Context,
|
||||
) (int64, error) {
|
||||
return d.accounts.selectNewNumericLocalpart(ctx)
|
||||
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
||||
}
|
||||
|
||||
func hashPassword(plaintext string) (hash string, err error) {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func (s *threepidStatements) selectThreePIDsForLocalpart(
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "selectThreePIDsForLocalpart: rows.close() failed")
|
||||
|
||||
threepids = []authtypes.ThreePID{}
|
||||
for rows.Next() {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,29 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/postgres"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/sqlite3"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
common.PartitionStorer
|
||||
GetAccountByPassword(ctx context.Context, localpart, plaintextPassword string) (*authtypes.Account, error)
|
||||
GetProfileByLocalpart(ctx context.Context, localpart string) (*authtypes.Profile, error)
|
||||
SetAvatarURL(ctx context.Context, localpart string, avatarURL string) error
|
||||
SetDisplayName(ctx context.Context, localpart string, displayName string) error
|
||||
CreateAccount(ctx context.Context, localpart, plaintextPassword, appserviceID string) (*authtypes.Account, error)
|
||||
UpdateMemberships(ctx context.Context, eventsToAdd []gomatrixserverlib.Event, idsToRemove []string) error
|
||||
GetMembershipInRoomByLocalpart(ctx context.Context, localpart, roomID string) (authtypes.Membership, error)
|
||||
GetMembershipsByLocalpart(ctx context.Context, localpart string) (memberships []authtypes.Membership, err error)
|
||||
SaveAccountData(ctx context.Context, localpart, roomID, dataType, content string) error
|
||||
GetAccountData(ctx context.Context, localpart string) (global []gomatrixserverlib.ClientEvent, rooms map[string][]gomatrixserverlib.ClientEvent, err error)
|
||||
GetAccountDataByType(ctx context.Context, localpart, roomID, dataType string) (data *gomatrixserverlib.ClientEvent, err error)
|
||||
GetNewNumericLocalpart(ctx context.Context) (int64, error)
|
||||
SaveThreePIDAssociation(ctx context.Context, threepid, localpart, medium string) (err error)
|
||||
RemoveThreePIDAssociation(ctx context.Context, threepid string, medium string) (err error)
|
||||
GetLocalpartForThreePID(ctx context.Context, threepid string, medium string) (localpart string, err error)
|
||||
GetThreePIDsForLocalpart(ctx context.Context, localpart string) (threepids []authtypes.ThreePID, err error)
|
||||
GetFilter(ctx context.Context, localpart string, filterID string) (*gomatrixserverlib.Filter, error)
|
||||
PutFilter(ctx context.Context, localpart string, filter *gomatrixserverlib.Filter) (string, error)
|
||||
CheckAccountAvailability(ctx context.Context, localpart string) (bool, error)
|
||||
GetAccountByLocalpart(ctx context.Context, localpart string) (*authtypes.Account, error)
|
||||
}
|
||||
|
||||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
|
|
@ -50,7 +38,3 @@ func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName)
|
|||
return postgres.NewDatabase(dataSourceName, serverName)
|
||||
}
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
|
|
|||
38
clientapi/auth/storage/accounts/storage_wasm.go
Normal file
38
clientapi/auth/storage/accounts/storage_wasm.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/sqlite3"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
switch uri.Scheme {
|
||||
case "postgres":
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
case "file":
|
||||
return sqlite3.NewDatabase(dataSourceName, serverName)
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
}
|
||||
32
clientapi/auth/storage/devices/interface.go
Normal file
32
clientapi/auth/storage/devices/interface.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 devices
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
GetDeviceByAccessToken(ctx context.Context, token string) (*authtypes.Device, error)
|
||||
GetDeviceByID(ctx context.Context, localpart, deviceID string) (*authtypes.Device, error)
|
||||
GetDevicesByLocalpart(ctx context.Context, localpart string) ([]authtypes.Device, error)
|
||||
CreateDevice(ctx context.Context, localpart string, deviceID *string, accessToken string, displayName *string) (dev *authtypes.Device, returnErr error)
|
||||
UpdateDevice(ctx context.Context, localpart, deviceID string, displayName *string) error
|
||||
RemoveDevice(ctx context.Context, deviceID, localpart string) error
|
||||
RemoveDevices(ctx context.Context, localpart string, devices []string) error
|
||||
RemoveAllDevices(ctx context.Context, localpart string) error
|
||||
}
|
||||
|
|
@ -226,11 +226,11 @@ func (s *devicesStatements) selectDevicesByLocalpart(
|
|||
if err != nil {
|
||||
return devices, err
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "selectDevicesByLocalpart: rows.close() failed")
|
||||
|
||||
for rows.Next() {
|
||||
var dev authtypes.Device
|
||||
err = rows.Scan(&dev.ID)
|
||||
err = rows.Scan(&dev.ID, &dev.DisplayName)
|
||||
if err != nil {
|
||||
return devices, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ func (s *devicesStatements) selectDevicesByLocalpart(
|
|||
|
||||
for rows.Next() {
|
||||
var dev authtypes.Device
|
||||
err = rows.Scan(&dev.ID)
|
||||
err = rows.Scan(&dev.ID, &dev.DisplayName)
|
||||
if err != nil {
|
||||
return devices, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ type Database struct {
|
|||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
||||
var db *sql.DB
|
||||
var err error
|
||||
if db, err = sql.Open("sqlite3", dataSourceName); err != nil {
|
||||
if db, err = sql.Open(common.SQLiteDriverName(), dataSourceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := devicesStatements{}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,29 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package devices
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices/postgres"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices/sqlite3"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
GetDeviceByAccessToken(ctx context.Context, token string) (*authtypes.Device, error)
|
||||
GetDeviceByID(ctx context.Context, localpart, deviceID string) (*authtypes.Device, error)
|
||||
GetDevicesByLocalpart(ctx context.Context, localpart string) ([]authtypes.Device, error)
|
||||
CreateDevice(ctx context.Context, localpart string, deviceID *string, accessToken string, displayName *string) (dev *authtypes.Device, returnErr error)
|
||||
UpdateDevice(ctx context.Context, localpart, deviceID string, displayName *string) error
|
||||
RemoveDevice(ctx context.Context, deviceID, localpart string) error
|
||||
RemoveDevices(ctx context.Context, localpart string, devices []string) error
|
||||
RemoveAllDevices(ctx context.Context, localpart string) error
|
||||
}
|
||||
|
||||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
|
|
|
|||
38
clientapi/auth/storage/devices/storage_wasm.go
Normal file
38
clientapi/auth/storage/devices/storage_wasm.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 devices
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices/sqlite3"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
switch uri.Scheme {
|
||||
case "postgres":
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
case "file":
|
||||
return sqlite3.NewDatabase(dataSourceName, serverName)
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ func SetupClientAPIComponent(
|
|||
transactionsCache *transactions.Cache,
|
||||
fedSenderAPI federationSenderAPI.FederationSenderQueryAPI,
|
||||
) {
|
||||
roomserverProducer := producers.NewRoomserverProducer(inputAPI)
|
||||
roomserverProducer := producers.NewRoomserverProducer(inputAPI, queryAPI)
|
||||
typingProducer := producers.NewTypingServerProducer(typingInputAPI)
|
||||
|
||||
userUpdateProducer := &producers.UserUpdateProducer{
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error {
|
|||
"type": ev.Type(),
|
||||
}).Info("received event from roomserver")
|
||||
|
||||
events, err := s.lookupStateEvents(output.NewRoomEvent.AddsStateEventIDs, ev)
|
||||
events, err := s.lookupStateEvents(output.NewRoomEvent.AddsStateEventIDs, ev.Event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -138,7 +138,9 @@ func (s *OutputRoomEventConsumer) lookupStateEvents(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
result = append(result, eventResp.Events...)
|
||||
for _, headeredEvent := range eventResp.Events {
|
||||
result = append(result, headeredEvent.Event)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,11 +36,3 @@ func UnmarshalJSONRequest(req *http.Request, iface interface{}) *util.JSONRespon
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogThenError logs the given error then returns a matrix-compliant 500 internal server error response.
|
||||
// This should be used to log fatal errors which require investigation. It should not be used
|
||||
// to log client validation errors, etc.
|
||||
func LogThenError(req *http.Request, err error) util.JSONResponse {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("request failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ func GuestAccessForbidden(msg string) *MatrixError {
|
|||
return &MatrixError{"M_GUEST_ACCESS_FORBIDDEN", msg}
|
||||
}
|
||||
|
||||
// UnsupportedRoomVersion is an error which is returned when the client
|
||||
// requests a room with a version that is unsupported.
|
||||
func UnsupportedRoomVersion(msg string) *MatrixError {
|
||||
return &MatrixError{"M_UNSUPPORTED_ROOM_VERSION", msg}
|
||||
}
|
||||
|
||||
// LimitExceededError is a rate-limiting error.
|
||||
type LimitExceededError struct {
|
||||
MatrixError
|
||||
|
|
|
|||
|
|
@ -24,18 +24,20 @@ import (
|
|||
// RoomserverProducer produces events for the roomserver to consume.
|
||||
type RoomserverProducer struct {
|
||||
InputAPI api.RoomserverInputAPI
|
||||
QueryAPI api.RoomserverQueryAPI
|
||||
}
|
||||
|
||||
// NewRoomserverProducer creates a new RoomserverProducer
|
||||
func NewRoomserverProducer(inputAPI api.RoomserverInputAPI) *RoomserverProducer {
|
||||
func NewRoomserverProducer(inputAPI api.RoomserverInputAPI, queryAPI api.RoomserverQueryAPI) *RoomserverProducer {
|
||||
return &RoomserverProducer{
|
||||
InputAPI: inputAPI,
|
||||
QueryAPI: queryAPI,
|
||||
}
|
||||
}
|
||||
|
||||
// SendEvents writes the given events to the roomserver input log. The events are written with KindNew.
|
||||
func (c *RoomserverProducer) SendEvents(
|
||||
ctx context.Context, events []gomatrixserverlib.Event, sendAsServer gomatrixserverlib.ServerName,
|
||||
ctx context.Context, events []gomatrixserverlib.HeaderedEvent, sendAsServer gomatrixserverlib.ServerName,
|
||||
txnID *api.TransactionID,
|
||||
) (string, error) {
|
||||
ires := make([]api.InputRoomEvent, len(events))
|
||||
|
|
@ -54,20 +56,20 @@ func (c *RoomserverProducer) SendEvents(
|
|||
// SendEventWithState writes an event with KindNew to the roomserver input log
|
||||
// with the state at the event as KindOutlier before it.
|
||||
func (c *RoomserverProducer) SendEventWithState(
|
||||
ctx context.Context, state gomatrixserverlib.RespState, event gomatrixserverlib.Event,
|
||||
ctx context.Context, state gomatrixserverlib.RespState, event gomatrixserverlib.HeaderedEvent,
|
||||
) error {
|
||||
outliers, err := state.Events()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ires := make([]api.InputRoomEvent, len(outliers)+1)
|
||||
for i, outlier := range outliers {
|
||||
ires[i] = api.InputRoomEvent{
|
||||
var ires []api.InputRoomEvent
|
||||
for _, outlier := range outliers {
|
||||
ires = append(ires, api.InputRoomEvent{
|
||||
Kind: api.KindOutlier,
|
||||
Event: outlier,
|
||||
Event: outlier.Headered(event.RoomVersion),
|
||||
AuthEventIDs: outlier.AuthEventIDs(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
stateEventIDs := make([]string, len(state.StateEvents))
|
||||
|
|
@ -75,13 +77,13 @@ func (c *RoomserverProducer) SendEventWithState(
|
|||
stateEventIDs[i] = state.StateEvents[i].EventID()
|
||||
}
|
||||
|
||||
ires[len(outliers)] = api.InputRoomEvent{
|
||||
ires = append(ires, api.InputRoomEvent{
|
||||
Kind: api.KindNew,
|
||||
Event: event,
|
||||
AuthEventIDs: event.AuthEventIDs(),
|
||||
HasState: true,
|
||||
StateEventIDs: stateEventIDs,
|
||||
}
|
||||
})
|
||||
|
||||
_, err = c.SendInputRoomEvents(ctx, ires)
|
||||
return err
|
||||
|
|
@ -104,8 +106,17 @@ func (c *RoomserverProducer) SendInputRoomEvents(
|
|||
func (c *RoomserverProducer) SendInvite(
|
||||
ctx context.Context, inviteEvent gomatrixserverlib.Event,
|
||||
) error {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: inviteEvent.RoomID()}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
err := c.QueryAPI.QueryRoomVersionForRoom(ctx, &verReq, &verRes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request := api.InputRoomEventsRequest{
|
||||
InputInviteEvents: []api.InputInviteEvent{{Event: inviteEvent}},
|
||||
InputInviteEvents: []api.InputInviteEvent{{
|
||||
Event: inviteEvent.Headered(verRes.RoomVersion),
|
||||
}},
|
||||
}
|
||||
var response api.InputRoomEventsResponse
|
||||
return c.InputAPI.InputRoomEvents(ctx, &request, &response)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
"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/clientapi/producers"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -43,7 +42,8 @@ func GetAccountData(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if data, err := accountDB.GetAccountDataByType(
|
||||
|
|
@ -75,7 +75,8 @@ func SaveAccountData(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
defer req.Body.Close() // nolint: errcheck
|
||||
|
|
@ -89,7 +90,8 @@ func SaveAccountData(
|
|||
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("ioutil.ReadAll failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !json.Valid(body) {
|
||||
|
|
@ -102,11 +104,13 @@ func SaveAccountData(
|
|||
if err := accountDB.SaveAccountData(
|
||||
req.Context(), localpart, roomID, dataType, string(body),
|
||||
); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.SaveAccountData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := syncProducer.SendData(userID, roomID, dataType); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("syncProducer.SendData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -151,7 +150,8 @@ func AuthFallback(
|
|||
clientIP := req.RemoteAddr
|
||||
err := req.ParseForm()
|
||||
if err != nil {
|
||||
res := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("req.ParseForm failed")
|
||||
res := jsonerror.InternalServerError()
|
||||
return &res
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +203,8 @@ func writeHTTPMessage(
|
|||
w.WriteHeader(header)
|
||||
_, err := w.Write([]byte(message))
|
||||
if err != nil {
|
||||
res := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("w.Write failed")
|
||||
res := jsonerror.InternalServerError()
|
||||
return &res
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -35,7 +35,8 @@ func GetCapabilities(
|
|||
&roomVersionsQueryReq,
|
||||
&roomVersionsQueryRes,
|
||||
); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("queryAPI.QueryRoomVersionCapabilities failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
response := map[string]interface{}{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
roomserverVersion "github.com/matrix-org/dendrite/roomserver/version"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
||||
|
|
@ -38,15 +39,16 @@ import (
|
|||
|
||||
// https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom
|
||||
type createRoomRequest struct {
|
||||
Invite []string `json:"invite"`
|
||||
Name string `json:"name"`
|
||||
Visibility string `json:"visibility"`
|
||||
Topic string `json:"topic"`
|
||||
Preset string `json:"preset"`
|
||||
CreationContent map[string]interface{} `json:"creation_content"`
|
||||
InitialState []fledglingEvent `json:"initial_state"`
|
||||
RoomAliasName string `json:"room_alias_name"`
|
||||
GuestCanJoin bool `json:"guest_can_join"`
|
||||
Invite []string `json:"invite"`
|
||||
Name string `json:"name"`
|
||||
Visibility string `json:"visibility"`
|
||||
Topic string `json:"topic"`
|
||||
Preset string `json:"preset"`
|
||||
CreationContent map[string]interface{} `json:"creation_content"`
|
||||
InitialState []fledglingEvent `json:"initial_state"`
|
||||
RoomAliasName string `json:"room_alias_name"`
|
||||
GuestCanJoin bool `json:"guest_can_join"`
|
||||
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -180,20 +182,34 @@ func createRoom(
|
|||
}
|
||||
|
||||
r.CreationContent["creator"] = userID
|
||||
r.CreationContent["room_version"] = "1" // TODO: We set this to 1 before we support Room versioning
|
||||
roomVersion := roomserverVersion.DefaultRoomVersion()
|
||||
if r.RoomVersion != "" {
|
||||
candidateVersion := gomatrixserverlib.RoomVersion(r.RoomVersion)
|
||||
_, roomVersionError := roomserverVersion.SupportedRoomVersion(candidateVersion)
|
||||
if roomVersionError != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(roomVersionError.Error()),
|
||||
}
|
||||
}
|
||||
roomVersion = candidateVersion
|
||||
}
|
||||
r.CreationContent["room_version"] = roomVersion
|
||||
|
||||
// TODO: visibility/presets/raw initial state
|
||||
// TODO: Create room alias association
|
||||
// Make sure this doesn't fall into an application service's namespace though!
|
||||
|
||||
logger.WithFields(log.Fields{
|
||||
"userID": userID,
|
||||
"roomID": roomID,
|
||||
"userID": userID,
|
||||
"roomID": roomID,
|
||||
"roomVersion": r.CreationContent["room_version"],
|
||||
}).Info("Creating new room")
|
||||
|
||||
profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
membershipContent := gomatrixserverlib.MemberContent{
|
||||
|
|
@ -221,7 +237,7 @@ func createRoom(
|
|||
historyVisibility = historyVisibilityShared
|
||||
}
|
||||
|
||||
var builtEvents []gomatrixserverlib.Event
|
||||
var builtEvents []gomatrixserverlib.HeaderedEvent
|
||||
|
||||
// send events into the room in order of:
|
||||
// 1- m.room.create
|
||||
|
|
@ -276,33 +292,38 @@ func createRoom(
|
|||
}
|
||||
err = builder.SetContent(e.Content)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("builder.SetContent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if i > 0 {
|
||||
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
||||
}
|
||||
var ev *gomatrixserverlib.Event
|
||||
ev, err = buildEvent(&builder, &authEvents, cfg, evTime)
|
||||
ev, err = buildEvent(&builder, &authEvents, cfg, evTime, roomVersion)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("buildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(*ev, &authEvents); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.Allowed failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Add the event to the list of auth events
|
||||
builtEvents = append(builtEvents, *ev)
|
||||
builtEvents = append(builtEvents, (*ev).Headered(roomVersion))
|
||||
err = authEvents.AddEvent(ev)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("authEvents.AddEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
}
|
||||
|
||||
// send events to the room server
|
||||
_, err = producer.SendEvents(req.Context(), builtEvents, cfg.Matrix.ServerName, nil)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// TODO(#269): Reserve room alias while we create the room. This stops us
|
||||
|
|
@ -321,7 +342,8 @@ func createRoom(
|
|||
var aliasResp roomserverAPI.SetRoomAliasResponse
|
||||
err = aliasAPI.SetRoomAlias(req.Context(), &aliasReq, &aliasResp)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if aliasResp.AliasExists {
|
||||
|
|
@ -346,6 +368,7 @@ func buildEvent(
|
|||
provider gomatrixserverlib.AuthEventProvider,
|
||||
cfg *config.Dendrite,
|
||||
evTime time.Time,
|
||||
roomVersion gomatrixserverlib.RoomVersion,
|
||||
) (*gomatrixserverlib.Event, error) {
|
||||
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
|
||||
if err != nil {
|
||||
|
|
@ -356,10 +379,12 @@ func buildEvent(
|
|||
return nil, err
|
||||
}
|
||||
builder.AuthEvents = refs
|
||||
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
|
||||
event, err := builder.Build(eventID, evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
|
||||
event, err := builder.Build(
|
||||
evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID,
|
||||
cfg.Matrix.PrivateKey, roomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot build event %s : Builder failed to build. %s", builder.Type, err)
|
||||
return nil, fmt.Errorf("cannot build event %s : Builder failed to build. %w", builder.Type, err)
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -51,7 +50,8 @@ func GetDeviceByID(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
ctx := req.Context()
|
||||
|
|
@ -62,7 +62,8 @@ func GetDeviceByID(
|
|||
JSON: jsonerror.NotFound("Unknown device"),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDeviceByID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -80,14 +81,16 @@ func GetDevicesByLocalpart(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
ctx := req.Context()
|
||||
deviceList, err := deviceDB.GetDevicesByLocalpart(ctx, localpart)
|
||||
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDevicesByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
res := devicesJSON{}
|
||||
|
|
@ -112,7 +115,8 @@ func UpdateDeviceByID(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
ctx := req.Context()
|
||||
|
|
@ -123,7 +127,8 @@ func UpdateDeviceByID(
|
|||
JSON: jsonerror.NotFound("Unknown device"),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDeviceByID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if dev.UserID != device.UserID {
|
||||
|
|
@ -138,11 +143,13 @@ func UpdateDeviceByID(
|
|||
payload := deviceUpdateJSON{}
|
||||
|
||||
if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("json.NewDecoder.Decode failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := deviceDB.UpdateDevice(ctx, localpart, deviceID, payload.DisplayName); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.UpdateDevice failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -158,14 +165,16 @@ func DeleteDeviceById(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
ctx := req.Context()
|
||||
|
||||
defer req.Body.Close() // nolint: errcheck
|
||||
|
||||
if err := deviceDB.RemoveDevice(ctx, deviceID, localpart); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.RemoveDevice failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -180,20 +189,23 @@ func DeleteDevices(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
ctx := req.Context()
|
||||
payload := devicesDeleteJSON{}
|
||||
|
||||
if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("json.NewDecoder.Decode failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
defer req.Body.Close() // nolint: errcheck
|
||||
|
||||
if err := deviceDB.RemoveDevices(ctx, localpart, payload.Devices); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.RemoveDevices failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@ func DirectoryRoom(
|
|||
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
|
||||
var queryRes roomserverAPI.GetRoomIDForAliasResponse
|
||||
if err = rsAPI.GetRoomIDForAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.GetRoomIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
res.RoomID = queryRes.RoomID
|
||||
|
|
@ -76,7 +77,8 @@ func DirectoryRoom(
|
|||
if fedErr != nil {
|
||||
// TODO: Return 502 if the remote server errored.
|
||||
// TODO: Return 504 if the remote server timed out.
|
||||
return httputil.LogThenError(req, fedErr)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("federation.LookupRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
res.RoomID = fedRes.RoomID
|
||||
res.fillServers(fedRes.Servers)
|
||||
|
|
@ -94,7 +96,8 @@ func DirectoryRoom(
|
|||
joinedHostsReq := federationSenderAPI.QueryJoinedHostServerNamesInRoomRequest{RoomID: res.RoomID}
|
||||
var joinedHostsRes federationSenderAPI.QueryJoinedHostServerNamesInRoomResponse
|
||||
if err = fedSenderAPI.QueryJoinedHostServerNamesInRoom(req.Context(), &joinedHostsReq, &joinedHostsRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("fedSenderAPI.QueryJoinedHostServerNamesInRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
res.fillServers(joinedHostsRes.ServerNames)
|
||||
}
|
||||
|
|
@ -165,7 +168,8 @@ func SetLocalAlias(
|
|||
}
|
||||
var queryRes roomserverAPI.SetRoomAliasResponse
|
||||
if err := aliasAPI.SetRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if queryRes.AliasExists {
|
||||
|
|
@ -194,7 +198,8 @@ func RemoveLocalAlias(
|
|||
}
|
||||
var creatorQueryRes roomserverAPI.GetCreatorIDForAliasResponse
|
||||
if err := aliasAPI.GetCreatorIDForAlias(req.Context(), &creatorQueryReq, &creatorQueryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.GetCreatorIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if creatorQueryRes.UserID == "" {
|
||||
|
|
@ -218,7 +223,8 @@ func RemoveLocalAlias(
|
|||
}
|
||||
var queryRes roomserverAPI.RemoveRoomAliasResponse
|
||||
if err := aliasAPI.RemoveRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ func GetFilter(
|
|||
}
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
filter, err := accountDB.GetFilter(req.Context(), localpart, filterID)
|
||||
|
|
@ -74,7 +75,8 @@ func PutFilter(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var filter gomatrixserverlib.Filter
|
||||
|
|
@ -93,7 +95,8 @@ func PutFilter(
|
|||
|
||||
filterID, err := accountDB.PutFilter(req.Context(), localpart, &filter)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.PutFilter failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
|
|
@ -55,7 +54,8 @@ func GetEvent(
|
|||
var eventsResp api.QueryEventsByIDResponse
|
||||
err := queryAPI.QueryEventsByID(req.Context(), &eventsReq, &eventsResp)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("queryAPI.QueryEventsByID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if len(eventsResp.Events) == 0 {
|
||||
|
|
@ -66,7 +66,7 @@ func GetEvent(
|
|||
}
|
||||
}
|
||||
|
||||
requestedEvent := eventsResp.Events[0]
|
||||
requestedEvent := eventsResp.Events[0].Event
|
||||
|
||||
r := getEventRequest{
|
||||
req: req,
|
||||
|
|
@ -89,7 +89,8 @@ func GetEvent(
|
|||
}
|
||||
var stateResp api.QueryStateAfterEventsResponse
|
||||
if err := queryAPI.QueryStateAfterEvents(req.Context(), &stateReq, &stateResp); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("queryAPI.QueryStateAfterEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !stateResp.RoomExists {
|
||||
|
|
@ -109,7 +110,8 @@ func GetEvent(
|
|||
if stateEvent.StateKeyEquals(r.device.UserID) {
|
||||
membership, err := stateEvent.Membership()
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("stateEvent.Membership failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if membership == gomatrixserverlib.Join {
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -62,12 +63,14 @@ func JoinRoomByIDOrAlias(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
profile, err := accountDB.GetProfileByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetProfileByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
content["membership"] = gomatrixserverlib.Join
|
||||
|
|
@ -119,7 +122,8 @@ func (r joinRoomReq) joinRoomByID(roomID string) util.JSONResponse {
|
|||
}
|
||||
var queryRes roomserverAPI.QueryInvitesForUserResponse
|
||||
if err := r.queryAPI.QueryInvitesForUser(r.req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("r.queryAPI.QueryInvitesForUser failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
servers := []gomatrixserverlib.ServerName{}
|
||||
|
|
@ -127,7 +131,8 @@ func (r joinRoomReq) joinRoomByID(roomID string) util.JSONResponse {
|
|||
for _, userID := range queryRes.InviteSenderUserIDs {
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if !seenInInviterIDs[domain] {
|
||||
servers = append(servers, domain)
|
||||
|
|
@ -141,7 +146,8 @@ func (r joinRoomReq) joinRoomByID(roomID string) util.JSONResponse {
|
|||
// Note: It's no guarantee we'll succeed because a room isn't bound to the domain in its ID
|
||||
_, domain, err := gomatrixserverlib.SplitID('!', roomID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if domain != r.cfg.Matrix.ServerName && !seenInInviterIDs[domain] {
|
||||
servers = append(servers, domain)
|
||||
|
|
@ -164,7 +170,8 @@ func (r joinRoomReq) joinRoomByAlias(roomAlias string) util.JSONResponse {
|
|||
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
|
||||
var queryRes roomserverAPI.GetRoomIDForAliasResponse
|
||||
if err = r.aliasAPI.GetRoomIDForAlias(r.req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("r.aliasAPI.GetRoomIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if len(queryRes.RoomID) > 0 {
|
||||
|
|
@ -194,7 +201,8 @@ func (r joinRoomReq) joinRoomByRemoteAlias(
|
|||
}
|
||||
}
|
||||
}
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("r.federation.LookupRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return r.joinRoomUsingServers(resp.RoomID, resp.Servers)
|
||||
|
|
@ -227,14 +235,23 @@ func (r joinRoomReq) joinRoomUsingServers(
|
|||
var eb gomatrixserverlib.EventBuilder
|
||||
err := r.writeToBuilder(&eb, roomID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("r.writeToBuilder failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
|
||||
queryRes := roomserverAPI.QueryLatestEventsAndStateResponse{}
|
||||
event, err := common.BuildEvent(r.req.Context(), &eb, r.cfg, r.evTime, r.queryAPI, &queryRes)
|
||||
if err == nil {
|
||||
if _, err = r.producer.SendEvents(r.req.Context(), []gomatrixserverlib.Event{*event}, r.cfg.Matrix.ServerName, nil); err != nil {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
if _, err = r.producer.SendEvents(
|
||||
r.req.Context(),
|
||||
[]gomatrixserverlib.HeaderedEvent{
|
||||
(*event).Headered(queryRes.RoomVersion),
|
||||
},
|
||||
r.cfg.Matrix.ServerName,
|
||||
nil,
|
||||
); err != nil {
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("r.producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -244,7 +261,8 @@ func (r joinRoomReq) joinRoomUsingServers(
|
|||
}
|
||||
}
|
||||
if err != common.ErrRoomNoExists {
|
||||
return httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("common.BuildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if len(servers) == 0 {
|
||||
|
|
@ -280,7 +298,8 @@ func (r joinRoomReq) joinRoomUsingServers(
|
|||
// 4) We couldn't fetch the public keys needed to verify the
|
||||
// signatures on the state events.
|
||||
// 5) ...
|
||||
return httputil.LogThenError(r.req, lastErr)
|
||||
util.GetLogger(r.req.Context()).WithError(lastErr).Error("failed to join through any server")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// joinRoomUsingServer tries to join a remote room using a given matrix server.
|
||||
|
|
@ -288,7 +307,17 @@ func (r joinRoomReq) joinRoomUsingServers(
|
|||
// server was invalid this returns an error.
|
||||
// Otherwise this returns a JSONResponse.
|
||||
func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib.ServerName) (*util.JSONResponse, error) {
|
||||
respMakeJoin, err := r.federation.MakeJoin(r.req.Context(), server, roomID, r.userID)
|
||||
// Ask the room server for information about room versions.
|
||||
var request api.QueryRoomVersionCapabilitiesRequest
|
||||
var response api.QueryRoomVersionCapabilitiesResponse
|
||||
if err := r.queryAPI.QueryRoomVersionCapabilities(r.req.Context(), &request, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var supportedVersions []gomatrixserverlib.RoomVersion
|
||||
for version := range response.AvailableRoomVersions {
|
||||
supportedVersions = append(supportedVersions, version)
|
||||
}
|
||||
respMakeJoin, err := r.federation.MakeJoin(r.req.Context(), server, roomID, r.userID, supportedVersions)
|
||||
if err != nil {
|
||||
// TODO: Check if the user was not allowed to join the room.
|
||||
return nil, err
|
||||
|
|
@ -301,16 +330,29 @@ func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib
|
|||
return nil, err
|
||||
}
|
||||
|
||||
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), r.cfg.Matrix.ServerName)
|
||||
if respMakeJoin.RoomVersion == "" {
|
||||
respMakeJoin.RoomVersion = gomatrixserverlib.RoomVersionV1
|
||||
}
|
||||
if _, err = respMakeJoin.RoomVersion.EventFormat(); err != nil {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(
|
||||
fmt.Sprintf("Room version '%s' is not supported", respMakeJoin.RoomVersion),
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
event, err := respMakeJoin.JoinEvent.Build(
|
||||
eventID, r.evTime, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey,
|
||||
r.evTime, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID,
|
||||
r.cfg.Matrix.PrivateKey, respMakeJoin.RoomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
res := httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("respMakeJoin.JoinEvent.Build failed")
|
||||
res := jsonerror.InternalServerError()
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
respSendJoin, err := r.federation.SendJoin(r.req.Context(), server, event)
|
||||
respSendJoin, err := r.federation.SendJoin(r.req.Context(), server, event, respMakeJoin.RoomVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -320,9 +362,12 @@ func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib
|
|||
}
|
||||
|
||||
if err = r.producer.SendEventWithState(
|
||||
r.req.Context(), gomatrixserverlib.RespState(respSendJoin.RespState), event,
|
||||
r.req.Context(),
|
||||
gomatrixserverlib.RespState(respSendJoin.RespState),
|
||||
event.Headered(respMakeJoin.RoomVersion),
|
||||
); err != nil {
|
||||
res := httputil.LogThenError(r.req, err)
|
||||
util.GetLogger(r.req.Context()).WithError(err).Error("gomatrixserverlib.RespState failed")
|
||||
res := jsonerror.InternalServerError()
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ func Login(
|
|||
|
||||
token, err := auth.GenerateAccessToken()
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("auth.GenerateAccessToken failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
dev, err := getDevice(req.Context(), r, deviceDB, acc, token)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
|
@ -30,11 +30,13 @@ func Logout(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := deviceDB.RemoveDevice(req.Context(), device.ID, localpart); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.RemoveDevice failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -49,11 +51,13 @@ func LogoutAll(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := deviceDB.RemoveAllDevices(req.Context(), localpart); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.RemoveAllDevices failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/threepid"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
|
|
@ -45,6 +46,15 @@ func SendMembership(
|
|||
queryAPI roomserverAPI.RoomserverQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
|
||||
producer *producers.RoomserverProducer,
|
||||
) util.JSONResponse {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := queryAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
var body threepid.MembershipRequest
|
||||
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
|
||||
return *reqErr
|
||||
|
|
@ -90,13 +100,18 @@ func SendMembership(
|
|||
JSON: jsonerror.NotFound(err.Error()),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("buildMembershipEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if _, err := producer.SendEvents(
|
||||
req.Context(), []gomatrixserverlib.Event{*event}, cfg.Matrix.ServerName, nil,
|
||||
req.Context(),
|
||||
[]gomatrixserverlib.HeaderedEvent{(*event).Headered(verRes.RoomVersion)},
|
||||
cfg.Matrix.ServerName,
|
||||
nil,
|
||||
); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var returnData interface{} = struct{}{}
|
||||
|
|
@ -242,7 +257,8 @@ func checkAndProcessThreepid(
|
|||
JSON: jsonerror.NotFound(err.Error()),
|
||||
}
|
||||
} else if err != nil {
|
||||
er := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
er := jsonerror.InternalServerError()
|
||||
return inviteStored, &er
|
||||
}
|
||||
return
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
|
|
@ -26,10 +27,14 @@ import (
|
|||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
type response struct {
|
||||
type getMembershipResponse struct {
|
||||
Chunk []gomatrixserverlib.ClientEvent `json:"chunk"`
|
||||
}
|
||||
|
||||
type getJoinedRoomsResponse struct {
|
||||
JoinedRooms []string `json:"joined_rooms"`
|
||||
}
|
||||
|
||||
// GetMemberships implements GET /rooms/{roomId}/members
|
||||
func GetMemberships(
|
||||
req *http.Request, device *authtypes.Device, roomID string, joinedOnly bool,
|
||||
|
|
@ -43,7 +48,8 @@ func GetMemberships(
|
|||
}
|
||||
var queryRes api.QueryMembershipsForRoomResponse
|
||||
if err := queryAPI.QueryMembershipsForRoom(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("queryAPI.QueryMembershipsForRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !queryRes.HasBeenInRoom {
|
||||
|
|
@ -55,6 +61,27 @@ func GetMemberships(
|
|||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: response{queryRes.JoinEvents},
|
||||
JSON: getMembershipResponse{queryRes.JoinEvents},
|
||||
}
|
||||
}
|
||||
|
||||
func GetJoinedRooms(
|
||||
req *http.Request,
|
||||
device *authtypes.Device,
|
||||
accountsDB accounts.Database,
|
||||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
joinedRooms, err := accountsDB.GetRoomIDsByLocalPart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountsDB.GetRoomIDsByLocalPart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: getJoinedRoomsResponse{joinedRooms},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ func GetProfile(
|
|||
}
|
||||
}
|
||||
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -77,7 +78,8 @@ func GetAvatarURL(
|
|||
}
|
||||
}
|
||||
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -116,7 +118,8 @@ func SetAvatarURL(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
evTime, err := httputil.ParseTSParam(req)
|
||||
|
|
@ -129,16 +132,19 @@ func SetAvatarURL(
|
|||
|
||||
oldProfile, err := accountDB.GetProfileByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetProfileByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err = accountDB.SetAvatarURL(req.Context(), localpart, r.AvatarURL); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.SetAvatarURL failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
memberships, err := accountDB.GetMembershipsByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetMembershipsByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
newProfile := authtypes.Profile{
|
||||
|
|
@ -151,15 +157,18 @@ func SetAvatarURL(
|
|||
req.Context(), memberships, newProfile, userID, cfg, evTime, queryAPI,
|
||||
)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("buildMembershipEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if _, err := rsProducer.SendEvents(req.Context(), events, cfg.Matrix.ServerName, nil); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsProducer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := producer.SendUpdate(userID, changedKey, oldProfile.AvatarURL, r.AvatarURL); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("producer.SendUpdate failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -183,7 +192,8 @@ func GetDisplayName(
|
|||
}
|
||||
}
|
||||
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -222,7 +232,8 @@ func SetDisplayName(
|
|||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
evTime, err := httputil.ParseTSParam(req)
|
||||
|
|
@ -235,16 +246,19 @@ func SetDisplayName(
|
|||
|
||||
oldProfile, err := accountDB.GetProfileByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetProfileByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err = accountDB.SetDisplayName(req.Context(), localpart, r.DisplayName); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.SetDisplayName failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
memberships, err := accountDB.GetMembershipsByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetMembershipsByLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
newProfile := authtypes.Profile{
|
||||
|
|
@ -257,15 +271,18 @@ func SetDisplayName(
|
|||
req.Context(), memberships, newProfile, userID, cfg, evTime, queryAPI,
|
||||
)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("buildMembershipEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if _, err := rsProducer.SendEvents(req.Context(), events, cfg.Matrix.ServerName, nil); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsProducer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err := producer.SendUpdate(userID, changedKey, oldProfile.DisplayName, r.DisplayName); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("producer.SendUpdate failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -321,10 +338,16 @@ func buildMembershipEvents(
|
|||
memberships []authtypes.Membership,
|
||||
newProfile authtypes.Profile, userID string, cfg *config.Dendrite,
|
||||
evTime time.Time, queryAPI api.RoomserverQueryAPI,
|
||||
) ([]gomatrixserverlib.Event, error) {
|
||||
evs := []gomatrixserverlib.Event{}
|
||||
) ([]gomatrixserverlib.HeaderedEvent, error) {
|
||||
evs := []gomatrixserverlib.HeaderedEvent{}
|
||||
|
||||
for _, membership := range memberships {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: membership.RoomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := queryAPI.QueryRoomVersionForRoom(ctx, &verReq, &verRes); err != nil {
|
||||
return []gomatrixserverlib.HeaderedEvent{}, err
|
||||
}
|
||||
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
Sender: userID,
|
||||
RoomID: membership.RoomID,
|
||||
|
|
@ -348,7 +371,7 @@ func buildMembershipEvents(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
evs = append(evs, *event)
|
||||
evs = append(evs, (*event).Headered(verRes.RoomVersion))
|
||||
}
|
||||
|
||||
return evs, nil
|
||||
|
|
|
|||
|
|
@ -444,7 +444,6 @@ func Register(
|
|||
deviceDB devices.Database,
|
||||
cfg *config.Dendrite,
|
||||
) util.JSONResponse {
|
||||
|
||||
var r registerRequest
|
||||
resErr := httputil.UnmarshalJSONRequest(req, &r)
|
||||
if resErr != nil {
|
||||
|
|
@ -472,7 +471,8 @@ func Register(
|
|||
if r.Username == "" {
|
||||
id, err := accountDB.GetNewNumericLocalpart(req.Context())
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetNewNumericLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
r.Username = strconv.FormatInt(id, 10)
|
||||
|
|
@ -516,15 +516,7 @@ func handleGuestRegistration(
|
|||
accountDB accounts.Database,
|
||||
deviceDB devices.Database,
|
||||
) util.JSONResponse {
|
||||
|
||||
//Generate numeric local part for guest user
|
||||
id, err := accountDB.GetNewNumericLocalpart(req.Context())
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
}
|
||||
|
||||
localpart := strconv.FormatInt(id, 10)
|
||||
acc, err := accountDB.CreateAccount(req.Context(), localpart, "", "")
|
||||
acc, err := accountDB.CreateGuestAccount(req.Context())
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
|
|
@ -602,7 +594,8 @@ func handleRegistrationFlow(
|
|||
valid, err := isValidMacLogin(cfg, r.Username, r.Password, r.Admin, r.Auth.Mac)
|
||||
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("isValidMacLogin failed")
|
||||
return jsonerror.InternalServerError()
|
||||
} else if !valid {
|
||||
return util.MessageResponse(http.StatusForbidden, "HMAC incorrect")
|
||||
}
|
||||
|
|
@ -758,7 +751,8 @@ func LegacyRegister(
|
|||
|
||||
valid, err := isValidMacLogin(cfg, r.Username, r.Password, r.Admin, r.Mac)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("isValidMacLogin failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !valid {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ func GetTags(
|
|||
|
||||
_, data, err := obtainSavedTags(req, userID, roomID, accountDB)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
|
|
@ -99,20 +100,23 @@ func PutTag(
|
|||
|
||||
localpart, data, err := obtainSavedTags(req, userID, roomID, accountDB)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var tagContent gomatrix.TagContent
|
||||
if data != nil {
|
||||
if err = json.Unmarshal(data.Content, &tagContent); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
} else {
|
||||
tagContent = newTag()
|
||||
}
|
||||
tagContent.Tags[tag] = properties
|
||||
if err = saveTagData(req, localpart, roomID, accountDB, tagContent); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("saveTagData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Send data to syncProducer in order to inform clients of changes
|
||||
|
|
@ -151,7 +155,8 @@ func DeleteTag(
|
|||
|
||||
localpart, data, err := obtainSavedTags(req, userID, roomID, accountDB)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// If there are no tags in the database, exit
|
||||
|
|
@ -166,7 +171,8 @@ func DeleteTag(
|
|||
var tagContent gomatrix.TagContent
|
||||
err = json.Unmarshal(data.Content, &tagContent)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Check whether the tag to be deleted exists
|
||||
|
|
@ -180,7 +186,8 @@ func DeleteTag(
|
|||
}
|
||||
}
|
||||
if err = saveTagData(req, localpart, roomID, accountDB, tagContent); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("saveTagData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Send data to syncProducer in order to inform clients of changes
|
||||
|
|
|
|||
|
|
@ -105,6 +105,12 @@ func Setup(
|
|||
)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
r0mux.Handle("/joined_rooms",
|
||||
common.MakeAuthAPI("joined_rooms", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||
return GetJoinedRooms(req, device, accountDB)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
r0mux.Handle("/rooms/{roomID}/{membership:(?:join|kick|ban|unban|leave|invite)}",
|
||||
common.MakeAuthAPI("membership", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||
|
|
@ -390,7 +396,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
unstableMux.Handle("/thirdparty/protocols",
|
||||
r0mux.Handle("/thirdparty/protocols",
|
||||
common.MakeExternalAPI("thirdparty_protocols", func(req *http.Request) util.JSONResponse {
|
||||
// TODO: Return the third party protcols
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
|
||||
|
|
@ -48,6 +49,15 @@ func SendEvent(
|
|||
producer *producers.RoomserverProducer,
|
||||
txnCache *transactions.Cache,
|
||||
) util.JSONResponse {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := queryAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
if txnID != nil {
|
||||
// Try to fetch response from transactionsCache
|
||||
if res, ok := txnCache.FetchTransaction(device.AccessToken, *txnID); ok {
|
||||
|
|
@ -71,11 +81,22 @@ func SendEvent(
|
|||
// pass the new event to the roomserver and receive the correct event ID
|
||||
// event ID in case of duplicate transaction is discarded
|
||||
eventID, err := producer.SendEvents(
|
||||
req.Context(), []gomatrixserverlib.Event{*e}, cfg.Matrix.ServerName, txnAndSessionID,
|
||||
req.Context(),
|
||||
[]gomatrixserverlib.HeaderedEvent{
|
||||
e.Headered(verRes.RoomVersion),
|
||||
},
|
||||
cfg.Matrix.ServerName,
|
||||
txnAndSessionID,
|
||||
)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
util.GetLogger(req.Context()).WithFields(logrus.Fields{
|
||||
"event_id": eventID,
|
||||
"room_id": roomID,
|
||||
"room_version": verRes.RoomVersion,
|
||||
}).Info("Sent event to roomserver")
|
||||
|
||||
res := util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -121,7 +142,8 @@ func generateSendEvent(
|
|||
}
|
||||
err = builder.SetContent(r)
|
||||
if err != nil {
|
||||
resErr := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("builder.SetContent failed")
|
||||
resErr := jsonerror.InternalServerError()
|
||||
return nil, &resErr
|
||||
}
|
||||
|
||||
|
|
@ -133,14 +155,15 @@ func generateSendEvent(
|
|||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
}
|
||||
} else if err != nil {
|
||||
resErr := httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("common.BuildEvent failed")
|
||||
resErr := jsonerror.InternalServerError()
|
||||
return nil, &resErr
|
||||
}
|
||||
|
||||
// check to see if this user can perform this operation
|
||||
stateEvents := make([]*gomatrixserverlib.Event, len(queryRes.StateEvents))
|
||||
for i := range queryRes.StateEvents {
|
||||
stateEvents[i] = &queryRes.StateEvents[i]
|
||||
stateEvents[i] = &queryRes.StateEvents[i].Event
|
||||
}
|
||||
provider := gomatrixserverlib.NewAuthEvents(stateEvents)
|
||||
if err = gomatrixserverlib.Allowed(*e, &provider); err != nil {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ func SendTyping(
|
|||
|
||||
localpart, err := userutil.ParseUsernameParam(userID, nil)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("userutil.ParseUsernameParam failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Verify that the user is a member of this room
|
||||
|
|
@ -57,7 +58,8 @@ func SendTyping(
|
|||
JSON: jsonerror.Forbidden("User not in this room"),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetMembershipInRoomByLocalPart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// parse the incoming http request
|
||||
|
|
@ -70,7 +72,8 @@ func SendTyping(
|
|||
if err = typingProducer.Send(
|
||||
req.Context(), userID, roomID, r.Typing, r.Timeout,
|
||||
); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("typingProducer.Send failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ func RequestEmailToken(req *http.Request, accountDB accounts.Database, cfg *conf
|
|||
// Check if the 3PID is already in use locally
|
||||
localpart, err := accountDB.GetLocalpartForThreePID(req.Context(), body.Email, "email")
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetLocalpartForThreePID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if len(localpart) > 0 {
|
||||
|
|
@ -71,7 +72,8 @@ func RequestEmailToken(req *http.Request, accountDB accounts.Database, cfg *conf
|
|||
JSON: jsonerror.NotTrusted(body.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -98,7 +100,8 @@ func CheckAndSave3PIDAssociation(
|
|||
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !verified {
|
||||
|
|
@ -120,18 +123,21 @@ func CheckAndSave3PIDAssociation(
|
|||
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.PublishAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
}
|
||||
|
||||
// Save the association in the database
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if err = accountDB.SaveThreePIDAssociation(req.Context(), address, localpart, medium); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountsDB.SaveThreePIDAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -146,12 +152,14 @@ func GetAssociated3PIDs(
|
|||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
threepids, err := accountDB.GetThreePIDsForLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.GetThreePIDsForLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -168,7 +176,8 @@ func Forget3PID(req *http.Request, accountDB accounts.Database) util.JSONRespons
|
|||
}
|
||||
|
||||
if err := accountDB.RemoveThreePIDAssociation(req.Context(), body.Address, body.Medium); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("accountDB.RemoveThreePIDAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -56,7 +56,8 @@ func RequestTurnServer(req *http.Request, device *authtypes.Device, cfg *config.
|
|||
_, err := mac.Write([]byte(resp.Username))
|
||||
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("mac.Write failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
resp.Username = fmt.Sprintf("%d:%s", expiry, device.UserID)
|
||||
|
|
|
|||
|
|
@ -353,12 +353,19 @@ func emit3PIDInviteEvent(
|
|||
return err
|
||||
}
|
||||
|
||||
var queryRes *api.QueryLatestEventsAndStateResponse
|
||||
event, err := common.BuildEvent(ctx, builder, cfg, evTime, queryAPI, queryRes)
|
||||
queryRes := api.QueryLatestEventsAndStateResponse{}
|
||||
event, err := common.BuildEvent(ctx, builder, cfg, evTime, queryAPI, &queryRes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = producer.SendEvents(ctx, []gomatrixserverlib.Event{*event}, cfg.Matrix.ServerName, nil)
|
||||
_, err = producer.SendEvents(
|
||||
ctx,
|
||||
[]gomatrixserverlib.HeaderedEvent{
|
||||
(*event).Headered(queryRes.RoomVersion),
|
||||
},
|
||||
cfg.Matrix.ServerName,
|
||||
nil,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,12 +103,14 @@ func main() {
|
|||
// Build an event and write the event to the output.
|
||||
func buildAndOutput() gomatrixserverlib.EventReference {
|
||||
eventID++
|
||||
id := fmt.Sprintf("$%d:%s", eventID, *serverName)
|
||||
now = time.Unix(0, 0)
|
||||
name := gomatrixserverlib.ServerName(*serverName)
|
||||
key := gomatrixserverlib.KeyID(*keyID)
|
||||
|
||||
event, err := b.Build(id, now, name, key, privateKey)
|
||||
event, err := b.Build(
|
||||
now, name, key, privateKey,
|
||||
gomatrixserverlib.RoomVersionV1,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -125,9 +127,9 @@ func writeEvent(event gomatrixserverlib.Event) {
|
|||
if *format == "InputRoomEvent" {
|
||||
var ire api.InputRoomEvent
|
||||
ire.Kind = api.KindNew
|
||||
ire.Event = event
|
||||
ire.Event = event.Headered(gomatrixserverlib.RoomVersionV1)
|
||||
authEventIDs := []string{}
|
||||
for _, ref := range b.AuthEvents {
|
||||
for _, ref := range b.AuthEvents.([]gomatrixserverlib.EventReference) {
|
||||
authEventIDs = append(authEventIDs, ref.EventID)
|
||||
}
|
||||
ire.AuthEventIDs = authEventIDs
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func main() {
|
|||
)
|
||||
federationapi.SetupFederationAPIComponent(base, accountDB, deviceDB, federation, &keyRing, alias, input, query, asQuery, fedSenderAPI)
|
||||
mediaapi.SetupMediaAPIComponent(base, deviceDB)
|
||||
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB, query)
|
||||
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB, query, federation, nil)
|
||||
syncapi.SetupSyncAPIComponent(base, deviceDB, accountDB, query, federation, cfg)
|
||||
|
||||
httpHandler := common.WrapHandlerInCORS(base.APIMux)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func main() {
|
|||
|
||||
_, _, query := base.CreateHTTPRoomserverAPIs()
|
||||
|
||||
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB, query)
|
||||
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB, query, nil, nil)
|
||||
|
||||
base.SetupAndServeHTTP(string(base.Cfg.Bind.PublicRoomsAPI), string(base.Cfg.Listen.PublicRoomsAPI))
|
||||
|
||||
|
|
|
|||
104
cmd/dendritejs/jsServer.go
Normal file
104
cmd/dendritejs/jsServer.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// JSServer exposes an HTTP-like server interface which allows JS to 'send' requests to it.
|
||||
type JSServer struct {
|
||||
// The router which will service requests
|
||||
Mux *http.ServeMux
|
||||
}
|
||||
|
||||
// OnRequestFromJS is the function that JS will invoke when there is a new request.
|
||||
// The JS function signature is:
|
||||
// function(reqString: string): Promise<{result: string, error: string}>
|
||||
// Usage is like:
|
||||
// const res = await global._go_js_server.fetch(reqString);
|
||||
// if (res.error) {
|
||||
// // handle error: this is a 'network' error, not a non-2xx error.
|
||||
// }
|
||||
// const rawHttpResponse = res.result;
|
||||
func (h *JSServer) OnRequestFromJS(this js.Value, args []js.Value) interface{} {
|
||||
// we HAVE to spawn a new goroutine and return immediately or else Go will deadlock
|
||||
// if this request blocks at all e.g for /sync calls
|
||||
httpStr := args[0].String()
|
||||
promise := js.Global().Get("Promise").New(js.FuncOf(func(pthis js.Value, pargs []js.Value) interface{} {
|
||||
// The initial callback code for new Promise() is also called on the critical path, which is why
|
||||
// we need to put this in an immediately invoked goroutine.
|
||||
go func() {
|
||||
resolve := pargs[0]
|
||||
fmt.Println("Received request:")
|
||||
fmt.Printf("%s\n", httpStr)
|
||||
resStr, err := h.handle(httpStr)
|
||||
errStr := ""
|
||||
if err != nil {
|
||||
errStr = err.Error()
|
||||
}
|
||||
fmt.Println("Sending response:")
|
||||
fmt.Printf("%s\n", resStr)
|
||||
resolve.Invoke(map[string]interface{}{
|
||||
"result": resStr,
|
||||
"error": errStr,
|
||||
})
|
||||
}()
|
||||
return nil
|
||||
}))
|
||||
return promise
|
||||
}
|
||||
|
||||
// handle invokes the http.ServeMux for this request and returns the raw HTTP response.
|
||||
func (h *JSServer) handle(httpStr string) (resStr string, err error) {
|
||||
req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(httpStr)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
h.Mux.ServeHTTP(w, req)
|
||||
|
||||
res := w.Result()
|
||||
var resBuffer strings.Builder
|
||||
err = res.Write(&resBuffer)
|
||||
return resBuffer.String(), err
|
||||
}
|
||||
|
||||
// ListenAndServe registers a variable in JS-land with the given namespace. This variable is
|
||||
// a function which JS-land can call to 'send' HTTP requests. The function is attached to
|
||||
// a global object called "_go_js_server". See OnRequestFromJS for more info.
|
||||
func (h *JSServer) ListenAndServe(namespace string) {
|
||||
globalName := "_go_js_server"
|
||||
// register a hook in JS-land for it to invoke stuff
|
||||
server := js.Global().Get(globalName)
|
||||
if !server.Truthy() {
|
||||
server = js.Global().Get("Object").New()
|
||||
js.Global().Set(globalName, server)
|
||||
}
|
||||
|
||||
server.Set(namespace, js.FuncOf(h.OnRequestFromJS))
|
||||
|
||||
fmt.Printf("Listening for requests from JS on function %s.%s\n", globalName, namespace)
|
||||
// Block forever to mimic http.ListenAndServe
|
||||
select {}
|
||||
}
|
||||
84
cmd/dendritejs/keyfetcher.go
Normal file
84
cmd/dendritejs/keyfetcher.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
const libp2pMatrixKeyID = "ed25519:libp2p-dendrite"
|
||||
|
||||
type libp2pKeyFetcher struct {
|
||||
}
|
||||
|
||||
// FetchKeys looks up a batch of public keys.
|
||||
// Takes a map from (server name, key ID) pairs to timestamp.
|
||||
// The timestamp is when the keys need to be vaild up to.
|
||||
// Returns a map from (server name, key ID) pairs to server key objects for
|
||||
// that server name containing that key ID
|
||||
// The result may have fewer (server name, key ID) pairs than were in the request.
|
||||
// The result may have more (server name, key ID) pairs than were in the request.
|
||||
// Returns an error if there was a problem fetching the keys.
|
||||
func (f *libp2pKeyFetcher) FetchKeys(
|
||||
ctx context.Context,
|
||||
requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
|
||||
) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) {
|
||||
res := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult)
|
||||
for req := range requests {
|
||||
if req.KeyID != libp2pMatrixKeyID {
|
||||
return nil, fmt.Errorf("FetchKeys: cannot fetch key with ID %s, should be %s", req.KeyID, libp2pMatrixKeyID)
|
||||
}
|
||||
|
||||
// The server name is a libp2p peer ID
|
||||
peerIDStr := string(req.ServerName)
|
||||
peerID, err := peer.Decode(peerIDStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to decode peer ID from server name '%s': %w", peerIDStr, err)
|
||||
}
|
||||
pubKey, err := peerID.ExtractPublicKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to extract public key from peer ID: %w", err)
|
||||
}
|
||||
pubKeyBytes, err := pubKey.Raw()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to extract raw bytes from public key: %w", err)
|
||||
}
|
||||
util.GetLogger(ctx).Info("libp2pKeyFetcher.FetchKeys: Using public key %v for server name %s", pubKeyBytes, req.ServerName)
|
||||
|
||||
b64Key := gomatrixserverlib.Base64String(pubKeyBytes)
|
||||
res[req] = gomatrixserverlib.PublicKeyLookupResult{
|
||||
VerifyKey: gomatrixserverlib.VerifyKey{
|
||||
Key: b64Key,
|
||||
},
|
||||
ExpiredTS: gomatrixserverlib.PublicKeyNotExpired,
|
||||
ValidUntilTS: gomatrixserverlib.AsTimestamp(time.Now().Add(24 * time.Hour * 365)),
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// FetcherName returns the name of this fetcher, which can then be used for
|
||||
// logging errors etc.
|
||||
func (f *libp2pKeyFetcher) FetcherName() string {
|
||||
return "libp2pKeyFetcher"
|
||||
}
|
||||
167
cmd/dendritejs/main.go
Normal file
167
cmd/dendritejs/main.go
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/appservice"
|
||||
"github.com/matrix-org/dendrite/clientapi"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/dendrite/common/basecomponent"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/common/transactions"
|
||||
"github.com/matrix-org/dendrite/federationapi"
|
||||
"github.com/matrix-org/dendrite/federationsender"
|
||||
"github.com/matrix-org/dendrite/mediaapi"
|
||||
"github.com/matrix-org/dendrite/publicroomsapi"
|
||||
"github.com/matrix-org/dendrite/roomserver"
|
||||
"github.com/matrix-org/dendrite/syncapi"
|
||||
"github.com/matrix-org/dendrite/typingserver"
|
||||
"github.com/matrix-org/dendrite/typingserver/cache"
|
||||
"github.com/matrix-org/go-http-js-libp2p/go_http_js_libp2p"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
_ "github.com/matrix-org/go-sqlite3-js"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fmt.Println("dendrite.js starting...")
|
||||
}
|
||||
|
||||
func generateKey() ed25519.PrivateKey {
|
||||
_, priv, err := ed25519.GenerateKey(nil)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to generate ed25519 key: %s", err)
|
||||
}
|
||||
return priv
|
||||
}
|
||||
|
||||
func createFederationClient(cfg *config.Dendrite, node *go_http_js_libp2p.P2pLocalNode) *gomatrixserverlib.FederationClient {
|
||||
fmt.Println("Running in js-libp2p federation mode")
|
||||
fmt.Println("Warning: Federation with non-libp2p homeservers will not work in this mode yet!")
|
||||
tr := go_http_js_libp2p.NewP2pTransport(node)
|
||||
|
||||
fed := gomatrixserverlib.NewFederationClient(
|
||||
cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey,
|
||||
)
|
||||
fed.Client = *gomatrixserverlib.NewClientWithTransport(tr)
|
||||
|
||||
return fed
|
||||
}
|
||||
|
||||
func createP2PNode(privKey ed25519.PrivateKey) (serverName string, node *go_http_js_libp2p.P2pLocalNode) {
|
||||
hosted := "/dns4/rendezvous.matrix.org/tcp/8443/wss/p2p-websocket-star/"
|
||||
node = go_http_js_libp2p.NewP2pLocalNode("org.matrix.p2p.experiment", privKey.Seed(), []string{hosted})
|
||||
serverName = node.Id
|
||||
fmt.Println("p2p assigned ServerName: ", serverName)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg := &config.Dendrite{}
|
||||
cfg.SetDefaults()
|
||||
cfg.Kafka.UseNaffka = true
|
||||
cfg.Database.Account = "file:dendritejs_account.db"
|
||||
cfg.Database.AppService = "file:dendritejs_appservice.db"
|
||||
cfg.Database.Device = "file:dendritejs_device.db"
|
||||
cfg.Database.FederationSender = "file:dendritejs_fedsender.db"
|
||||
cfg.Database.MediaAPI = "file:dendritejs_mediaapi.db"
|
||||
cfg.Database.Naffka = "file:dendritejs_naffka.db"
|
||||
cfg.Database.PublicRoomsAPI = "file:dendritejs_publicrooms.db"
|
||||
cfg.Database.RoomServer = "file:dendritejs_roomserver.db"
|
||||
cfg.Database.ServerKey = "file:dendritejs_serverkey.db"
|
||||
cfg.Database.SyncAPI = "file:dendritejs_syncapi.db"
|
||||
cfg.Kafka.Topics.UserUpdates = "user_updates"
|
||||
cfg.Kafka.Topics.OutputTypingEvent = "output_typing_event"
|
||||
cfg.Kafka.Topics.OutputClientData = "output_client_data"
|
||||
cfg.Kafka.Topics.OutputRoomEvent = "output_room_event"
|
||||
cfg.Matrix.TrustedIDServers = []string{
|
||||
"matrix.org", "vector.im",
|
||||
}
|
||||
cfg.Matrix.KeyID = libp2pMatrixKeyID
|
||||
cfg.Matrix.PrivateKey = generateKey()
|
||||
|
||||
serverName, node := createP2PNode(cfg.Matrix.PrivateKey)
|
||||
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(serverName)
|
||||
|
||||
if err := cfg.Derive(); err != nil {
|
||||
logrus.Fatalf("Failed to derive values from config: %s", err)
|
||||
}
|
||||
base := basecomponent.NewBaseDendrite(cfg, "Monolith")
|
||||
defer base.Close() // nolint: errcheck
|
||||
|
||||
accountDB := base.CreateAccountsDB()
|
||||
deviceDB := base.CreateDeviceDB()
|
||||
keyDB := base.CreateKeyDB()
|
||||
federation := createFederationClient(cfg, node)
|
||||
keyRing := gomatrixserverlib.KeyRing{
|
||||
KeyFetchers: []gomatrixserverlib.KeyFetcher{
|
||||
&libp2pKeyFetcher{},
|
||||
},
|
||||
KeyDatabase: keyDB,
|
||||
}
|
||||
p2pPublicRoomProvider := NewLibP2PPublicRoomsProvider(node)
|
||||
|
||||
alias, input, query := roomserver.SetupRoomServerComponent(base)
|
||||
typingInputAPI := typingserver.SetupTypingServerComponent(base, cache.NewTypingCache())
|
||||
asQuery := appservice.SetupAppServiceAPIComponent(
|
||||
base, accountDB, deviceDB, federation, alias, query, transactions.New(),
|
||||
)
|
||||
fedSenderAPI := federationsender.SetupFederationSenderComponent(base, federation, query)
|
||||
|
||||
clientapi.SetupClientAPIComponent(
|
||||
base, deviceDB, accountDB,
|
||||
federation, &keyRing, alias, input, query,
|
||||
typingInputAPI, asQuery, transactions.New(), fedSenderAPI,
|
||||
)
|
||||
federationapi.SetupFederationAPIComponent(base, accountDB, deviceDB, federation, &keyRing, alias, input, query, asQuery, fedSenderAPI)
|
||||
mediaapi.SetupMediaAPIComponent(base, deviceDB)
|
||||
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB, query, federation, p2pPublicRoomProvider)
|
||||
syncapi.SetupSyncAPIComponent(base, deviceDB, accountDB, query, federation, cfg)
|
||||
|
||||
httpHandler := common.WrapHandlerInCORS(base.APIMux)
|
||||
|
||||
http.Handle("/", httpHandler)
|
||||
|
||||
// Expose the matrix APIs via libp2p-js - for federation traffic
|
||||
if node != nil {
|
||||
go func() {
|
||||
logrus.Info("Listening on libp2p-js host ID ", node.Id)
|
||||
s := JSServer{
|
||||
Mux: http.DefaultServeMux,
|
||||
}
|
||||
s.ListenAndServe("p2p")
|
||||
}()
|
||||
}
|
||||
|
||||
// Expose the matrix APIs via fetch - for local traffic
|
||||
go func() {
|
||||
logrus.Info("Listening for service-worker fetch traffic")
|
||||
s := JSServer{
|
||||
Mux: http.DefaultServeMux,
|
||||
}
|
||||
s.ListenAndServe("fetch")
|
||||
}()
|
||||
|
||||
// We want to block forever to let the fetch and libp2p handler serve the APIs
|
||||
select {}
|
||||
}
|
||||
23
cmd/dendritejs/main_noop.go
Normal file
23
cmd/dendritejs/main_noop.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("dendritejs: no-op when not compiling for WebAssembly")
|
||||
}
|
||||
46
cmd/dendritejs/publicrooms.go
Normal file
46
cmd/dendritejs/publicrooms.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/matrix-org/go-http-js-libp2p/go_http_js_libp2p"
|
||||
)
|
||||
|
||||
type libp2pPublicRoomsProvider struct {
|
||||
node *go_http_js_libp2p.P2pLocalNode
|
||||
providers []go_http_js_libp2p.PeerInfo
|
||||
}
|
||||
|
||||
func NewLibP2PPublicRoomsProvider(node *go_http_js_libp2p.P2pLocalNode) *libp2pPublicRoomsProvider {
|
||||
p := &libp2pPublicRoomsProvider{
|
||||
node: node,
|
||||
}
|
||||
node.RegisterFoundProviders(p.foundProviders)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *libp2pPublicRoomsProvider) foundProviders(peerInfos []go_http_js_libp2p.PeerInfo) {
|
||||
p.providers = peerInfos
|
||||
}
|
||||
|
||||
func (p *libp2pPublicRoomsProvider) Homeservers() []string {
|
||||
result := make([]string, len(p.providers))
|
||||
for i := range p.providers {
|
||||
result[i] = p.providers[i].Id
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ func clientEventJSONForOutputRoomEvent(outputRoomEvent string) string {
|
|||
panic("failed to unmarshal output room event: " + err.Error())
|
||||
}
|
||||
clientEvs := gomatrixserverlib.ToClientEvents([]gomatrixserverlib.Event{
|
||||
out.NewRoomEvent.Event,
|
||||
out.NewRoomEvent.Event.Event,
|
||||
}, gomatrixserverlib.FormatSync)
|
||||
b, err := json.Marshal(clientEvs[0])
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ func setupNaffka(cfg *config.Dendrite) (sarama.Consumer, sarama.SyncProducer) {
|
|||
|
||||
uri, err := url.Parse(string(cfg.Database.Naffka))
|
||||
if err != nil || uri.Scheme == "file" {
|
||||
db, err = sql.Open("sqlite3", string(cfg.Database.Naffka))
|
||||
db, err = sql.Open(common.SQLiteDriverName(), string(cfg.Database.Naffka))
|
||||
if err != nil {
|
||||
logrus.WithError(err).Panic("Failed to open naffka database")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,6 +224,8 @@ type Dendrite struct {
|
|||
|
||||
// The config for tracing the dendrite servers.
|
||||
Tracing struct {
|
||||
// Set to true to enable tracer hooks. If false, no tracing is set up.
|
||||
Enabled bool `yaml:"enabled"`
|
||||
// The config for the jaeger opentracing reporter.
|
||||
Jaeger jaegerconfig.Configuration `yaml:"jaeger"`
|
||||
} `yaml:"tracing"`
|
||||
|
|
@ -365,7 +367,7 @@ func loadConfig(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
config.setDefaults()
|
||||
config.SetDefaults()
|
||||
|
||||
if err = config.check(monolithic); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -398,7 +400,7 @@ func loadConfig(
|
|||
config.Media.AbsBasePath = Path(absPath(basePath, config.Media.BasePath))
|
||||
|
||||
// Generate data from config options
|
||||
err = config.derive()
|
||||
err = config.Derive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -406,9 +408,9 @@ func loadConfig(
|
|||
return &config, nil
|
||||
}
|
||||
|
||||
// derive generates data that is derived from various values provided in
|
||||
// Derive generates data that is derived from various values provided in
|
||||
// the config file.
|
||||
func (config *Dendrite) derive() error {
|
||||
func (config *Dendrite) Derive() error {
|
||||
// Determine registrations flows based off config values
|
||||
|
||||
config.Derived.Registration.Params = make(map[string]interface{})
|
||||
|
|
@ -433,8 +435,8 @@ func (config *Dendrite) derive() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// setDefaults sets default config values if they are not explicitly set.
|
||||
func (config *Dendrite) setDefaults() {
|
||||
// SetDefaults sets default config values if they are not explicitly set.
|
||||
func (config *Dendrite) SetDefaults() {
|
||||
if config.Matrix.KeyValidityPeriod == 0 {
|
||||
config.Matrix.KeyValidityPeriod = 24 * time.Hour
|
||||
}
|
||||
|
|
@ -703,6 +705,9 @@ func (config *Dendrite) FederationSenderURL() string {
|
|||
|
||||
// SetupTracing configures the opentracing using the supplied configuration.
|
||||
func (config *Dendrite) SetupTracing(serviceName string) (closer io.Closer, err error) {
|
||||
if !config.Tracing.Enabled {
|
||||
return ioutil.NopCloser(bytes.NewReader([]byte{})), nil
|
||||
}
|
||||
return config.Tracing.Jaeger.InitGlobalTracer(
|
||||
serviceName,
|
||||
jaegerconfig.Logger(logrusLogger{logrus.StandardLogger()}),
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ func (c *ContinualConsumer) consumePartition(pc sarama.PartitionConsumer) {
|
|||
msgErr := c.ProcessMessage(message)
|
||||
// Advance our position in the stream so that we will start at the right position after a restart.
|
||||
if err := c.PartitionStore.SetPartitionOffset(context.TODO(), c.Topic, message.Partition, message.Offset); err != nil {
|
||||
panic(fmt.Errorf("the ContinualConsumer failed to SetPartitionOffset: %s", err))
|
||||
panic(fmt.Errorf("the ContinualConsumer failed to SetPartitionOffset: %w", err))
|
||||
}
|
||||
// Shutdown if we were told to do so.
|
||||
if msgErr == ErrShutdown {
|
||||
|
|
|
|||
|
|
@ -17,14 +17,12 @@ package common
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
// ErrRoomNoExists is returned when trying to lookup the state of a room that
|
||||
|
|
@ -42,13 +40,19 @@ func BuildEvent(
|
|||
builder *gomatrixserverlib.EventBuilder, cfg *config.Dendrite, evTime time.Time,
|
||||
queryAPI api.RoomserverQueryAPI, queryRes *api.QueryLatestEventsAndStateResponse,
|
||||
) (*gomatrixserverlib.Event, error) {
|
||||
if queryRes == nil {
|
||||
queryRes = &api.QueryLatestEventsAndStateResponse{}
|
||||
}
|
||||
|
||||
err := AddPrevEventsToEvent(ctx, builder, queryAPI, queryRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
|
||||
event, err := builder.Build(eventID, evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
|
||||
event, err := builder.Build(
|
||||
evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID,
|
||||
cfg.Matrix.PrivateKey, queryRes.RoomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -72,9 +76,6 @@ func AddPrevEventsToEvent(
|
|||
RoomID: builder.RoomID,
|
||||
StateToFetch: eventsNeeded.Tuples(),
|
||||
}
|
||||
if queryRes == nil {
|
||||
queryRes = &api.QueryLatestEventsAndStateResponse{}
|
||||
}
|
||||
if err = queryAPI.QueryLatestEventsAndState(ctx, &queryReq, queryRes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -83,13 +84,17 @@ func AddPrevEventsToEvent(
|
|||
return ErrRoomNoExists
|
||||
}
|
||||
|
||||
eventFormat, err := queryRes.RoomVersion.EventFormat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
builder.Depth = queryRes.Depth
|
||||
builder.PrevEvents = queryRes.LatestEvents
|
||||
|
||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||
|
||||
for i := range queryRes.StateEvents {
|
||||
err = authEvents.AddEvent(&queryRes.StateEvents[i])
|
||||
err = authEvents.AddEvent(&queryRes.StateEvents[i].Event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -99,7 +104,23 @@ func AddPrevEventsToEvent(
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builder.AuthEvents = refs
|
||||
|
||||
switch eventFormat {
|
||||
case gomatrixserverlib.EventFormatV1:
|
||||
builder.AuthEvents = refs
|
||||
builder.PrevEvents = queryRes.LatestEvents
|
||||
case gomatrixserverlib.EventFormatV2:
|
||||
v2AuthRefs := []string{}
|
||||
v2PrevRefs := []string{}
|
||||
for _, ref := range refs {
|
||||
v2AuthRefs = append(v2AuthRefs, ref.EventID)
|
||||
}
|
||||
for _, ref := range queryRes.LatestEvents {
|
||||
v2PrevRefs = append(v2PrevRefs, ref.EventID)
|
||||
}
|
||||
builder.AuthEvents = v2AuthRefs
|
||||
builder.PrevEvents = v2PrevRefs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ func MakeAuthAPI(
|
|||
if err != nil {
|
||||
return *err
|
||||
}
|
||||
// add the user ID to the logger
|
||||
logger := util.GetLogger((req.Context()))
|
||||
logger = logger.WithField("user_id", device.UserID)
|
||||
req = req.WithContext(util.ContextWithLogger(req.Context(), logger))
|
||||
|
||||
return f(req, device)
|
||||
}
|
||||
|
|
|
|||
13
common/keydb/interface.go
Normal file
13
common/keydb/interface.go
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package keydb
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
FetcherName() string
|
||||
FetchKeys(ctx context.Context, requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error)
|
||||
StoreKeys(ctx context.Context, keyMap map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) error
|
||||
}
|
||||
|
|
@ -12,10 +12,11 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package keydb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
|
@ -25,12 +26,6 @@ import (
|
|||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
type Database interface {
|
||||
FetcherName() string
|
||||
FetchKeys(ctx context.Context, requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error)
|
||||
StoreKeys(ctx context.Context, keyMap map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) error
|
||||
}
|
||||
|
||||
// NewDatabase opens a database connection.
|
||||
func NewDatabase(
|
||||
dataSourceName string,
|
||||
|
|
|
|||
46
common/keydb/keydb_wasm.go
Normal file
46
common/keydb/keydb_wasm.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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 keydb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
"github.com/matrix-org/dendrite/common/keydb/sqlite3"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
// NewDatabase opens a database connection.
|
||||
func NewDatabase(
|
||||
dataSourceName string,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
serverKey ed25519.PublicKey,
|
||||
serverKeyID gomatrixserverlib.KeyID,
|
||||
) (Database, error) {
|
||||
uri, err := url.Parse(dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch uri.Scheme {
|
||||
case "postgres":
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
case "file":
|
||||
return sqlite3.NewDatabase(dataSourceName, serverName, serverKey, serverKeyID)
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot use postgres implementation")
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,8 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
|
@ -91,7 +93,7 @@ func (s *serverKeyStatements) bulkSelectServerKeys(
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "bulkSelectServerKeys: rows.close() failed")
|
||||
results := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{}
|
||||
for rows.Next() {
|
||||
var serverName string
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
|
@ -43,7 +44,7 @@ func NewDatabase(
|
|||
serverKey ed25519.PublicKey,
|
||||
serverKeyID gomatrixserverlib.KeyID,
|
||||
) (*Database, error) {
|
||||
db, err := sql.Open("sqlite3", dataSourceName)
|
||||
db, err := sql.Open(common.SQLiteDriverName(), dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,12 @@ package sqlite3
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"github.com/lib/pq"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
const serverKeysSchema = `
|
||||
|
|
@ -60,11 +63,19 @@ const upsertServerKeysSQL = "" +
|
|||
" DO UPDATE SET valid_until_ts = $4, expired_ts = $5, server_key = $6"
|
||||
|
||||
type serverKeyStatements struct {
|
||||
db *sql.DB
|
||||
bulkSelectServerKeysStmt *sql.Stmt
|
||||
upsertServerKeysStmt *sql.Stmt
|
||||
|
||||
cache *lru.Cache // nameAndKeyID => gomatrixserverlib.PublicKeyLookupResult
|
||||
}
|
||||
|
||||
func (s *serverKeyStatements) prepare(db *sql.DB) (err error) {
|
||||
s.db = db
|
||||
s.cache, err = lru.New(64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = db.Exec(serverKeysSchema)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
@ -86,12 +97,34 @@ func (s *serverKeyStatements) bulkSelectServerKeys(
|
|||
for request := range requests {
|
||||
nameAndKeyIDs = append(nameAndKeyIDs, nameAndKeyID(request))
|
||||
}
|
||||
stmt := s.bulkSelectServerKeysStmt
|
||||
rows, err := stmt.QueryContext(ctx, pq.StringArray(nameAndKeyIDs))
|
||||
|
||||
// If we can satisfy all of the requests from the cache, do so. TODO: Allow partial matches with merges.
|
||||
cacheResults := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{}
|
||||
for request := range requests {
|
||||
r, ok := s.cache.Get(nameAndKeyID(request))
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
cacheResult := r.(gomatrixserverlib.PublicKeyLookupResult)
|
||||
cacheResults[request] = cacheResult
|
||||
}
|
||||
if len(cacheResults) == len(requests) {
|
||||
util.GetLogger(ctx).Infof("KeyDB cache hit for %d keys", len(cacheResults))
|
||||
return cacheResults, nil
|
||||
}
|
||||
|
||||
query := strings.Replace(bulkSelectServerKeysSQL, "($1)", common.QueryVariadic(len(nameAndKeyIDs)), 1)
|
||||
|
||||
iKeyIDs := make([]interface{}, len(nameAndKeyIDs))
|
||||
for i, v := range nameAndKeyIDs {
|
||||
iKeyIDs[i] = v
|
||||
}
|
||||
|
||||
rows, err := s.db.QueryContext(ctx, query, iKeyIDs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer common.CloseAndLogIfError(ctx, rows, "bulkSelectServerKeys: rows.close() failed")
|
||||
results := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{}
|
||||
for rows.Next() {
|
||||
var serverName string
|
||||
|
|
@ -125,6 +158,7 @@ func (s *serverKeyStatements) upsertServerKeys(
|
|||
request gomatrixserverlib.PublicKeyLookupRequest,
|
||||
key gomatrixserverlib.PublicKeyLookupResult,
|
||||
) error {
|
||||
s.cache.Add(nameAndKeyID(request), key)
|
||||
_, err := s.upsertServerKeysStmt.ExecContext(
|
||||
ctx,
|
||||
string(request.ServerName),
|
||||
|
|
|
|||
|
|
@ -15,13 +15,17 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dugong"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
@ -156,3 +160,17 @@ func setupFileHook(hook config.LogrusHook, level logrus.Level, componentName str
|
|||
),
|
||||
})
|
||||
}
|
||||
|
||||
//CloseAndLogIfError Closes io.Closer and logs the error if any
|
||||
func CloseAndLogIfError(ctx context.Context, closer io.Closer, message string) {
|
||||
if closer == nil {
|
||||
return
|
||||
}
|
||||
err := closer.Close()
|
||||
if ctx == nil {
|
||||
ctx = context.TODO()
|
||||
}
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error(message)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ func (s *PartitionOffsetStatements) selectPartitionOffsets(
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close() // nolint: errcheck
|
||||
defer CloseAndLogIfError(ctx, rows, "selectPartitionOffsets: rows.close() failed")
|
||||
var results []PartitionOffset
|
||||
for rows.Next() {
|
||||
var offset PartitionOffset
|
||||
|
|
|
|||
25
common/postgres.go
Normal file
25
common/postgres.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build !wasm
|
||||
|
||||
package common
|
||||
|
||||
import "github.com/lib/pq"
|
||||
|
||||
// IsUniqueConstraintViolationErr returns true if the error is a postgresql unique_violation error
|
||||
func IsUniqueConstraintViolationErr(err error) bool {
|
||||
pqErr, ok := err.(*pq.Error)
|
||||
return ok && pqErr.Code == "23505"
|
||||
}
|
||||
22
common/postgres_wasm.go
Normal file
22
common/postgres_wasm.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package common
|
||||
|
||||
// IsUniqueConstraintViolationErr no-ops for this architecture
|
||||
func IsUniqueConstraintViolationErr(err error) bool {
|
||||
return false
|
||||
}
|
||||
|
|
@ -17,8 +17,7 @@ package common
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// A Transaction is something that can be committed or rolledback.
|
||||
|
|
@ -77,12 +76,6 @@ func TxStmt(transaction *sql.Tx, statement *sql.Stmt) *sql.Stmt {
|
|||
return statement
|
||||
}
|
||||
|
||||
// IsUniqueConstraintViolationErr returns true if the error is a postgresql unique_violation error
|
||||
func IsUniqueConstraintViolationErr(err error) bool {
|
||||
pqErr, ok := err.(*pq.Error)
|
||||
return ok && pqErr.Code == "23505"
|
||||
}
|
||||
|
||||
// Hack of the century
|
||||
func QueryVariadic(count int) string {
|
||||
return QueryVariadicOffset(count, 0)
|
||||
|
|
@ -99,3 +92,10 @@ func QueryVariadicOffset(count, offset int) string {
|
|||
str += ")"
|
||||
return str
|
||||
}
|
||||
|
||||
func SQLiteDriverName() string {
|
||||
if runtime.GOOS == "js" {
|
||||
return "sqlite3_js"
|
||||
}
|
||||
return "sqlite3"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ and start working on dendrite.
|
|||
|
||||
### Configuration
|
||||
|
||||
Copy the `dendrite-docker.yaml` file to the root of the project and rename it to
|
||||
`dendrite.yaml`. It already contains the defaults used in `docker-compose` for
|
||||
networking so you will only have to change things like the `server_name` or to
|
||||
toggle `naffka`.
|
||||
Create a directory named `cfg` in the root of the project. Copy the
|
||||
`dendrite-docker.yaml` file into that directory and rename it to `dendrite.yaml`.
|
||||
It already contains the defaults used in `docker-compose` for networking so you will
|
||||
only have to change things like the `server_name` or to toggle `naffka`.
|
||||
|
||||
You can run the following `docker-compose` commands either from the top directory
|
||||
specifying the `docker-compose` file
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func SetupFederationAPIComponent(
|
|||
asAPI appserviceAPI.AppServiceQueryAPI,
|
||||
federationSenderAPI federationSenderAPI.FederationSenderQueryAPI,
|
||||
) {
|
||||
roomserverProducer := producers.NewRoomserverProducer(inputAPI)
|
||||
roomserverProducer := producers.NewRoomserverProducer(inputAPI, queryAPI)
|
||||
|
||||
routing.Setup(
|
||||
base.APIMux, base.Cfg, queryAPI, aliasAPI, asAPI,
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
|
|
@ -72,27 +72,34 @@ func Backfill(
|
|||
ServerName: request.Origin(),
|
||||
}
|
||||
if req.Limit, err = strconv.Atoi(limit); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("strconv.Atoi failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Query the roomserver.
|
||||
if err = query.QueryBackfill(httpReq.Context(), &req, &res); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("query.QueryBackfill failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Filter any event that's not from the requested room out.
|
||||
evs := make([]gomatrixserverlib.Event, 0)
|
||||
|
||||
var ev gomatrixserverlib.Event
|
||||
var ev gomatrixserverlib.HeaderedEvent
|
||||
for _, ev = range res.Events {
|
||||
if ev.RoomID() == roomID {
|
||||
evs = append(evs, ev)
|
||||
evs = append(evs, ev.Event)
|
||||
}
|
||||
}
|
||||
|
||||
var eventJSONs []json.RawMessage
|
||||
for _, e := range evs {
|
||||
eventJSONs = append(eventJSONs, e.JSON())
|
||||
}
|
||||
|
||||
txn := gomatrixserverlib.Transaction{
|
||||
Origin: cfg.Matrix.ServerName,
|
||||
PDUs: evs,
|
||||
PDUs: eventJSONs,
|
||||
OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -43,7 +42,8 @@ func GetUserDevices(
|
|||
|
||||
devs, err := deviceDB.GetDevicesByLocalpart(req.Context(), localpart)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDevicesByLocalPart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
43
federationapi/routing/eventauth.go
Normal file
43
federationapi/routing/eventauth.go
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// 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 routing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
// GetEventAuth returns event auth for the roomID and eventID
|
||||
func GetEventAuth(
|
||||
ctx context.Context,
|
||||
request *gomatrixserverlib.FederationRequest,
|
||||
query api.RoomserverQueryAPI,
|
||||
roomID string,
|
||||
eventID string,
|
||||
) util.JSONResponse {
|
||||
// TODO: Optimisation: we shouldn't be querying all the room state
|
||||
// that is in state.StateEvents - we just ignore it.
|
||||
state, err := getState(ctx, request, query, roomID, eventID)
|
||||
if err != nil {
|
||||
return *err
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: gomatrixserverlib.RespEventAuth{AuthEvents: state.AuthEvents},
|
||||
}
|
||||
}
|
||||
|
|
@ -80,5 +80,5 @@ func getEvent(
|
|||
return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil}
|
||||
}
|
||||
|
||||
return &eventsResponse.Events[0], nil
|
||||
return &eventsResponse.Events[0].Event, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
|
@ -36,10 +36,19 @@ func Invite(
|
|||
producer *producers.RoomserverProducer,
|
||||
keys gomatrixserverlib.KeyRing,
|
||||
) util.JSONResponse {
|
||||
// Look up the room version for the room.
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := producer.QueryAPI.QueryRoomVersionForRoom(context.Background(), &verReq, &verRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the event JSON from the request.
|
||||
var event gomatrixserverlib.Event
|
||||
if err := json.Unmarshal(request.Content(), &event); err != nil {
|
||||
event, err := gomatrixserverlib.NewEventFromUntrustedJSON(request.Content(), verRes.RoomVersion)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
|
|
@ -71,14 +80,16 @@ func Invite(
|
|||
}
|
||||
|
||||
// Check that the event is signed by the server sending the request.
|
||||
redacted := event.Redact()
|
||||
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
||||
ServerName: event.Origin(),
|
||||
Message: event.Redact().JSON(),
|
||||
Message: redacted.JSON(),
|
||||
AtTS: event.OriginServerTS(),
|
||||
}}
|
||||
verifyResults, err := keys.VerifyJSONs(httpReq.Context(), verifyRequests)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("keys.VerifyJSONs failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if verifyResults[0].Error != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -94,7 +105,8 @@ func Invite(
|
|||
|
||||
// Add the invite event to the roomserver.
|
||||
if err = producer.SendInvite(httpReq.Context(), signedEvent); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendInvite failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Return the signed event to the originating server, it should then tell
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
|
@ -37,6 +35,15 @@ func MakeJoin(
|
|||
query api.RoomserverQueryAPI,
|
||||
roomID, userID string,
|
||||
) util.JSONResponse {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := query.QueryRoomVersionForRoom(httpReq.Context(), &verReq, &verRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
}
|
||||
}
|
||||
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -60,10 +67,13 @@ func MakeJoin(
|
|||
}
|
||||
err = builder.SetContent(map[string]interface{}{"membership": gomatrixserverlib.Join})
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var queryRes api.QueryLatestEventsAndStateResponse
|
||||
queryRes := api.QueryLatestEventsAndStateResponse{
|
||||
RoomVersion: verRes.RoomVersion,
|
||||
}
|
||||
event, err := common.BuildEvent(httpReq.Context(), &builder, cfg, time.Now(), query, &queryRes)
|
||||
if err == common.ErrRoomNoExists {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -71,14 +81,16 @@ func MakeJoin(
|
|||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("common.BuildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Check that the join is allowed or not
|
||||
stateEvents := make([]*gomatrixserverlib.Event, len(queryRes.StateEvents))
|
||||
for i := range queryRes.StateEvents {
|
||||
stateEvents[i] = &queryRes.StateEvents[i]
|
||||
stateEvents[i] = &queryRes.StateEvents[i].Event
|
||||
}
|
||||
|
||||
provider := gomatrixserverlib.NewAuthEvents(stateEvents)
|
||||
if err = gomatrixserverlib.Allowed(*event, &provider); err != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -89,7 +101,10 @@ func MakeJoin(
|
|||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: map[string]interface{}{"event": builder},
|
||||
JSON: map[string]interface{}{
|
||||
"event": builder,
|
||||
"room_version": verRes.RoomVersion,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,8 +118,18 @@ func SendJoin(
|
|||
keys gomatrixserverlib.KeyRing,
|
||||
roomID, eventID string,
|
||||
) util.JSONResponse {
|
||||
var event gomatrixserverlib.Event
|
||||
if err := json.Unmarshal(request.Content(), &event); err != nil {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := query.QueryRoomVersionForRoom(httpReq.Context(), &verReq, &verRes); err != nil {
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("query.QueryRoomVersionForRoom failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
}
|
||||
}
|
||||
|
||||
event, err := gomatrixserverlib.NewEventFromUntrustedJSON(request.Content(), verRes.RoomVersion)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
|
|
@ -136,19 +161,21 @@ func SendJoin(
|
|||
}
|
||||
|
||||
// Check that the event is signed by the server sending the request.
|
||||
redacted := event.Redact()
|
||||
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
||||
ServerName: event.Origin(),
|
||||
Message: event.Redact().JSON(),
|
||||
Message: redacted.JSON(),
|
||||
AtTS: event.OriginServerTS(),
|
||||
}}
|
||||
verifyResults, err := keys.VerifyJSONs(httpReq.Context(), verifyRequests)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("keys.VerifyJSONs failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if verifyResults[0].Error != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("The join must be signed by the server it originated on"),
|
||||
JSON: jsonerror.Forbidden("Signature check failed: " + verifyResults[0].Error.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +188,8 @@ func SendJoin(
|
|||
RoomID: roomID,
|
||||
}, &stateAndAuthChainResponse)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("query.QueryStateAndAuthChain failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !stateAndAuthChainResponse.RoomExists {
|
||||
|
|
@ -175,17 +203,23 @@ func SendJoin(
|
|||
// We are responsible for notifying other servers that the user has joined
|
||||
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
||||
_, err = producer.SendEvents(
|
||||
httpReq.Context(), []gomatrixserverlib.Event{event}, cfg.Matrix.ServerName, nil,
|
||||
httpReq.Context(),
|
||||
[]gomatrixserverlib.HeaderedEvent{
|
||||
event.Headered(stateAndAuthChainResponse.RoomVersion),
|
||||
},
|
||||
cfg.Matrix.ServerName,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: map[string]interface{}{
|
||||
"state": stateAndAuthChainResponse.StateEvents,
|
||||
"auth_chain": stateAndAuthChainResponse.AuthChainEvents,
|
||||
"state": gomatrixserverlib.UnwrapEventHeaders(stateAndAuthChainResponse.StateEvents),
|
||||
"auth_chain": gomatrixserverlib.UnwrapEventHeaders(stateAndAuthChainResponse.AuthChainEvents),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,9 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
|
|
@ -58,7 +56,8 @@ func MakeLeave(
|
|||
}
|
||||
err = builder.SetContent(map[string]interface{}{"membership": gomatrixserverlib.Leave})
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var queryRes api.QueryLatestEventsAndStateResponse
|
||||
|
|
@ -69,13 +68,14 @@ func MakeLeave(
|
|||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("common.BuildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
// Check that the leave is allowed or not
|
||||
stateEvents := make([]*gomatrixserverlib.Event, len(queryRes.StateEvents))
|
||||
for i := range queryRes.StateEvents {
|
||||
stateEvents[i] = &queryRes.StateEvents[i]
|
||||
stateEvents[i] = &queryRes.StateEvents[i].Event
|
||||
}
|
||||
provider := gomatrixserverlib.NewAuthEvents(stateEvents)
|
||||
if err = gomatrixserverlib.Allowed(*event, &provider); err != nil {
|
||||
|
|
@ -100,8 +100,18 @@ func SendLeave(
|
|||
keys gomatrixserverlib.KeyRing,
|
||||
roomID, eventID string,
|
||||
) util.JSONResponse {
|
||||
var event gomatrixserverlib.Event
|
||||
if err := json.Unmarshal(request.Content(), &event); err != nil {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := producer.QueryAPI.QueryRoomVersionForRoom(httpReq.Context(), &verReq, &verRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the event JSON from the request.
|
||||
event, err := gomatrixserverlib.NewEventFromUntrustedJSON(request.Content(), verRes.RoomVersion)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
|
|
@ -133,14 +143,16 @@ func SendLeave(
|
|||
}
|
||||
|
||||
// Check that the event is signed by the server sending the request.
|
||||
redacted := event.Redact()
|
||||
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
||||
ServerName: event.Origin(),
|
||||
Message: event.Redact().JSON(),
|
||||
Message: redacted.JSON(),
|
||||
AtTS: event.OriginServerTS(),
|
||||
}}
|
||||
verifyResults, err := keys.VerifyJSONs(httpReq.Context(), verifyRequests)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("keys.VerifyJSONs failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if verifyResults[0].Error != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -152,7 +164,8 @@ func SendLeave(
|
|||
// check membership is set to leave
|
||||
mem, err := event.Membership()
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("event.Membership failed")
|
||||
return jsonerror.InternalServerError()
|
||||
} else if mem != gomatrixserverlib.Leave {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
|
|
@ -163,9 +176,17 @@ func SendLeave(
|
|||
// Send the events to the room server.
|
||||
// We are responsible for notifying other servers that the user has left
|
||||
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
||||
_, err = producer.SendEvents(httpReq.Context(), []gomatrixserverlib.Event{event}, cfg.Matrix.ServerName, nil)
|
||||
_, err = producer.SendEvents(
|
||||
httpReq.Context(),
|
||||
[]gomatrixserverlib.HeaderedEvent{
|
||||
event.Headered(verRes.RoomVersion),
|
||||
},
|
||||
cfg.Matrix.ServerName,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -56,7 +55,8 @@ func GetMissingEvents(
|
|||
},
|
||||
&eventsResponse,
|
||||
); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("query.QueryMissingEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
eventsResponse.Events = filterEvents(eventsResponse.Events, gme.MinDepth, roomID)
|
||||
|
|
@ -68,8 +68,8 @@ func GetMissingEvents(
|
|||
|
||||
// filterEvents returns only those events with matching roomID and having depth greater than minDepth
|
||||
func filterEvents(
|
||||
events []gomatrixserverlib.Event, minDepth int64, roomID string,
|
||||
) []gomatrixserverlib.Event {
|
||||
events []gomatrixserverlib.HeaderedEvent, minDepth int64, roomID string,
|
||||
) []gomatrixserverlib.HeaderedEvent {
|
||||
ref := events[:0]
|
||||
for _, ev := range events {
|
||||
if ev.Depth() >= minDepth && ev.RoomID() == roomID {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import (
|
|||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"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/common"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
|
|
@ -46,16 +45,19 @@ func GetProfile(
|
|||
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("domain != cfg.Matrix.ServerName failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
profile, err := appserviceAPI.RetrieveUserProfile(httpReq.Context(), userID, asAPI, accountDB)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
var res interface{}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
|
||||
|
|
@ -57,14 +56,16 @@ func RoomAliasToID(
|
|||
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
|
||||
var queryRes roomserverAPI.GetRoomIDForAliasResponse
|
||||
if err = aliasAPI.GetRoomIDForAlias(httpReq.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if queryRes.RoomID != "" {
|
||||
serverQueryReq := federationSenderAPI.QueryJoinedHostServerNamesInRoomRequest{RoomID: queryRes.RoomID}
|
||||
var serverQueryRes federationSenderAPI.QueryJoinedHostServerNamesInRoomResponse
|
||||
if err = senderAPI.QueryJoinedHostServerNamesInRoom(httpReq.Context(), &serverQueryReq, &serverQueryRes); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("senderAPI.QueryJoinedHostServerNamesInRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
resp = gomatrixserverlib.RespDirectory{
|
||||
|
|
@ -92,7 +93,8 @@ func RoomAliasToID(
|
|||
}
|
||||
// TODO: Return 502 if the remote server errored.
|
||||
// TODO: Return 504 if the remote server timed out.
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
util.GetLogger(httpReq.Context()).WithError(err).Error("federation.LookupRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/state/{roomID}", common.MakeFedAPI(
|
||||
"federation_get_event_auth", cfg.Matrix.ServerName, keys,
|
||||
"federation_get_state", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
vars, err := common.URLDecodeMapValues(mux.Vars(httpReq))
|
||||
if err != nil {
|
||||
|
|
@ -144,7 +144,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/state_ids/{roomID}", common.MakeFedAPI(
|
||||
"federation_get_event_auth", cfg.Matrix.ServerName, keys,
|
||||
"federation_get_state_ids", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
vars, err := common.URLDecodeMapValues(mux.Vars(httpReq))
|
||||
if err != nil {
|
||||
|
|
@ -156,6 +156,16 @@ func Setup(
|
|||
},
|
||||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/event_auth/{roomID}/{eventID}", common.MakeFedAPI(
|
||||
"federation_get_event_auth", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
vars := mux.Vars(httpReq)
|
||||
return GetEventAuth(
|
||||
httpReq.Context(), request, query, vars["roomID"], vars["eventID"],
|
||||
)
|
||||
},
|
||||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/query/directory", common.MakeFedAPI(
|
||||
"federation_query_room_alias", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue