mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-27 07:28:27 +00:00
Merge branch 'master' into neilalexander/rsconcurrency
This commit is contained in:
commit
5fe9872290
68 changed files with 251 additions and 158 deletions
|
@ -102,7 +102,7 @@ linters-settings:
|
||||||
#local-prefixes: github.com/org/project
|
#local-prefixes: github.com/org/project
|
||||||
gocyclo:
|
gocyclo:
|
||||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||||
min-complexity: 13
|
min-complexity: 25
|
||||||
maligned:
|
maligned:
|
||||||
# print struct with more effective memory layout or not, false by default
|
# print struct with more effective memory layout or not, false by default
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
|
|
|
@ -16,6 +16,7 @@ package appservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -48,6 +49,15 @@ func NewInternalAPI(
|
||||||
userAPI userapi.UserInternalAPI,
|
userAPI userapi.UserInternalAPI,
|
||||||
rsAPI roomserverAPI.RoomserverInternalAPI,
|
rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
) appserviceAPI.AppServiceQueryAPI {
|
) appserviceAPI.AppServiceQueryAPI {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 30,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: base.Cfg.AppServiceAPI.DisableTLSValidation,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
consumer, _ := kafka.SetupConsumerProducer(&base.Cfg.Global.Kafka)
|
consumer, _ := kafka.SetupConsumerProducer(&base.Cfg.Global.Kafka)
|
||||||
|
|
||||||
// Create a connection to the appservice postgres DB
|
// Create a connection to the appservice postgres DB
|
||||||
|
@ -79,9 +89,7 @@ func NewInternalAPI(
|
||||||
// Create appserivce query API with an HTTP client that will be used for all
|
// Create appserivce query API with an HTTP client that will be used for all
|
||||||
// outbound and inbound requests (inbound only for the internal API)
|
// outbound and inbound requests (inbound only for the internal API)
|
||||||
appserviceQueryAPI := &query.AppServiceQueryAPI{
|
appserviceQueryAPI := &query.AppServiceQueryAPI{
|
||||||
HTTPClient: &http.Client{
|
HTTPClient: client,
|
||||||
Timeout: time.Second * 30,
|
|
||||||
},
|
|
||||||
Cfg: base.Cfg,
|
Cfg: base.Cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +106,7 @@ func NewInternalAPI(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create application service transaction workers
|
// Create application service transaction workers
|
||||||
if err := workers.SetupTransactionWorkers(appserviceDB, workerStates); err != nil {
|
if err := workers.SetupTransactionWorkers(client, appserviceDB, workerStates); err != nil {
|
||||||
logrus.WithError(err).Panicf("failed to start app service transaction workers")
|
logrus.WithError(err).Panicf("failed to start app service transaction workers")
|
||||||
}
|
}
|
||||||
return appserviceQueryAPI
|
return appserviceQueryAPI
|
||||||
|
|
|
@ -85,9 +85,6 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if output.Type != api.OutputTypeNewRoomEvent {
|
if output.Type != api.OutputTypeNewRoomEvent {
|
||||||
log.WithField("type", output.Type).Debug(
|
|
||||||
"roomserver output log: ignoring unknown output type",
|
|
||||||
)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +111,7 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(
|
||||||
// Queue this event to be sent off to the application service
|
// Queue this event to be sent off to the application service
|
||||||
if err := s.asDB.StoreEvent(ctx, ws.AppService.ID, event); err != nil {
|
if err := s.asDB.StoreEvent(ctx, ws.AppService.ID, event); err != nil {
|
||||||
log.WithError(err).Warn("failed to insert incoming event into appservices database")
|
log.WithError(err).Warn("failed to insert incoming event into appservices database")
|
||||||
|
return err
|
||||||
} else {
|
} else {
|
||||||
// Tell our worker to send out new messages by updating remaining message
|
// Tell our worker to send out new messages by updating remaining message
|
||||||
// count and waking them up with a broadcast
|
// count and waking them up with a broadcast
|
||||||
|
@ -126,8 +124,43 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appserviceJoinedAtEvent returns a boolean depending on whether a given
|
||||||
|
// appservice has membership at the time a given event was created.
|
||||||
|
func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, appservice config.ApplicationService) bool {
|
||||||
|
// TODO: This is only checking the current room state, not the state at
|
||||||
|
// the event in question. Pretty sure this is what Synapse does too, but
|
||||||
|
// until we have a lighter way of checking the state before the event that
|
||||||
|
// doesn't involve state res, then this is probably OK.
|
||||||
|
membershipReq := &api.QueryMembershipsForRoomRequest{
|
||||||
|
RoomID: event.RoomID(),
|
||||||
|
JoinedOnly: true,
|
||||||
|
}
|
||||||
|
membershipRes := &api.QueryMembershipsForRoomResponse{}
|
||||||
|
|
||||||
|
// XXX: This could potentially race if the state for the event is not known yet
|
||||||
|
// e.g. the event came over federation but we do not have the full state persisted.
|
||||||
|
if err := s.rsAPI.QueryMembershipsForRoom(ctx, membershipReq, membershipRes); err == nil {
|
||||||
|
for _, ev := range membershipRes.JoinEvents {
|
||||||
|
var membership gomatrixserverlib.MemberContent
|
||||||
|
if err = json.Unmarshal(ev.Content, &membership); err != nil || ev.StateKey == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if appservice.IsInterestedInUserID(*ev.StateKey) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"room_id": event.RoomID(),
|
||||||
|
}).WithError(err).Errorf("Unable to get membership for room")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// appserviceIsInterestedInEvent returns a boolean depending on whether a given
|
// appserviceIsInterestedInEvent returns a boolean depending on whether a given
|
||||||
// event falls within one of a given application service's namespaces.
|
// event falls within one of a given application service's namespaces.
|
||||||
|
//
|
||||||
|
// TODO: This should be cached, see https://github.com/matrix-org/dendrite/issues/1682
|
||||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, 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
|
// No reason to queue events if they'll never be sent to the application
|
||||||
// service
|
// service
|
||||||
|
@ -162,5 +195,6 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
||||||
}).WithError(err).Errorf("Unable to get aliases for room")
|
}).WithError(err).Errorf("Unable to get aliases for room")
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
// Check if any of the members in the room match the appservice
|
||||||
|
return s.appserviceJoinedAtEvent(ctx, event, appservice)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice/api"
|
"github.com/matrix-org/dendrite/appservice/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
@ -47,11 +46,6 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceRoomAlias")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceRoomAlias")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
// Create an HTTP client if one does not already exist
|
|
||||||
if a.HTTPClient == nil {
|
|
||||||
a.HTTPClient = makeHTTPClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which application service should handle this request
|
// Determine which application service should handle this request
|
||||||
for _, appservice := range a.Cfg.Derived.ApplicationServices {
|
for _, appservice := range a.Cfg.Derived.ApplicationServices {
|
||||||
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
|
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
|
||||||
|
@ -115,11 +109,6 @@ func (a *AppServiceQueryAPI) UserIDExists(
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceUserID")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceUserID")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
// Create an HTTP client if one does not already exist
|
|
||||||
if a.HTTPClient == nil {
|
|
||||||
a.HTTPClient = makeHTTPClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which application service should handle this request
|
// Determine which application service should handle this request
|
||||||
for _, appservice := range a.Cfg.Derived.ApplicationServices {
|
for _, appservice := range a.Cfg.Derived.ApplicationServices {
|
||||||
if appservice.URL != "" && appservice.IsInterestedInUserID(request.UserID) {
|
if appservice.URL != "" && appservice.IsInterestedInUserID(request.UserID) {
|
||||||
|
@ -169,10 +158,3 @@ func (a *AppServiceQueryAPI) UserIDExists(
|
||||||
response.UserIDExists = false
|
response.UserIDExists = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeHTTPClient creates an HTTP client with certain options that will be used for all query requests to application services
|
|
||||||
func makeHTTPClient() *http.Client {
|
|
||||||
return &http.Client{
|
|
||||||
Timeout: time.Second * 30,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ import (
|
||||||
var (
|
var (
|
||||||
// Maximum size of events sent in each transaction.
|
// Maximum size of events sent in each transaction.
|
||||||
transactionBatchSize = 50
|
transactionBatchSize = 50
|
||||||
// Timeout for sending a single transaction to an application service.
|
|
||||||
transactionTimeout = time.Second * 60
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupTransactionWorkers spawns a separate goroutine for each application
|
// SetupTransactionWorkers spawns a separate goroutine for each application
|
||||||
|
@ -44,6 +42,7 @@ var (
|
||||||
// size), then send that off to the AS's /transactions/{txnID} endpoint. It also
|
// size), then send that off to the AS's /transactions/{txnID} endpoint. It also
|
||||||
// handles exponentially backing off in case the AS isn't currently available.
|
// handles exponentially backing off in case the AS isn't currently available.
|
||||||
func SetupTransactionWorkers(
|
func SetupTransactionWorkers(
|
||||||
|
client *http.Client,
|
||||||
appserviceDB storage.Database,
|
appserviceDB storage.Database,
|
||||||
workerStates []types.ApplicationServiceWorkerState,
|
workerStates []types.ApplicationServiceWorkerState,
|
||||||
) error {
|
) error {
|
||||||
|
@ -51,7 +50,7 @@ func SetupTransactionWorkers(
|
||||||
for _, workerState := range workerStates {
|
for _, workerState := range workerStates {
|
||||||
// Don't create a worker if this AS doesn't want to receive events
|
// Don't create a worker if this AS doesn't want to receive events
|
||||||
if workerState.AppService.URL != "" {
|
if workerState.AppService.URL != "" {
|
||||||
go worker(appserviceDB, workerState)
|
go worker(client, appserviceDB, workerState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -59,17 +58,12 @@ func SetupTransactionWorkers(
|
||||||
|
|
||||||
// worker is a goroutine that sends any queued events to the application service
|
// worker is a goroutine that sends any queued events to the application service
|
||||||
// it is given.
|
// it is given.
|
||||||
func worker(db storage.Database, ws types.ApplicationServiceWorkerState) {
|
func worker(client *http.Client, db storage.Database, ws types.ApplicationServiceWorkerState) {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice": ws.AppService.ID,
|
"appservice": ws.AppService.ID,
|
||||||
}).Info("starting application service")
|
}).Info("Starting application service")
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Create a HTTP client for sending requests to app services
|
|
||||||
client := &http.Client{
|
|
||||||
Timeout: transactionTimeout,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial check for any leftover events to send from last time
|
// Initial check for any leftover events to send from last time
|
||||||
eventCount, err := db.CountEventsWithAppServiceID(ctx, ws.AppService.ID)
|
eventCount, err := db.CountEventsWithAppServiceID(ctx, ws.AppService.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -218,6 +218,7 @@ func createRoom(
|
||||||
// check it's free TODO: This races but is better than nothing
|
// check it's free TODO: This races but is better than nothing
|
||||||
hasAliasReq := roomserverAPI.GetRoomIDForAliasRequest{
|
hasAliasReq := roomserverAPI.GetRoomIDForAliasRequest{
|
||||||
Alias: roomAlias,
|
Alias: roomAlias,
|
||||||
|
IncludeAppservices: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
var aliasResp roomserverAPI.GetRoomIDForAliasResponse
|
var aliasResp roomserverAPI.GetRoomIDForAliasResponse
|
||||||
|
|
|
@ -61,9 +61,12 @@ func DirectoryRoom(
|
||||||
var res roomDirectoryResponse
|
var res roomDirectoryResponse
|
||||||
|
|
||||||
// Query the roomserver API to check if the alias exists locally.
|
// Query the roomserver API to check if the alias exists locally.
|
||||||
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
|
queryReq := &roomserverAPI.GetRoomIDForAliasRequest{
|
||||||
var queryRes roomserverAPI.GetRoomIDForAliasResponse
|
Alias: roomAlias,
|
||||||
if err = rsAPI.GetRoomIDForAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
IncludeAppservices: true,
|
||||||
|
}
|
||||||
|
queryRes := &roomserverAPI.GetRoomIDForAliasResponse{}
|
||||||
|
if err = rsAPI.GetRoomIDForAlias(req.Context(), queryReq, queryRes); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.GetRoomIDForAlias failed")
|
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.GetRoomIDForAlias failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,22 @@ func GetEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var appService *config.ApplicationService
|
||||||
|
if device.AppserviceID != "" {
|
||||||
|
for _, as := range cfg.Derived.ApplicationServices {
|
||||||
|
if as.ID == device.AppserviceID {
|
||||||
|
appService = &as
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, stateEvent := range stateResp.StateEvents {
|
for _, stateEvent := range stateResp.StateEvents {
|
||||||
if !stateEvent.StateKeyEquals(device.UserID) {
|
if appService != nil {
|
||||||
|
if !appService.IsInterestedInUserID(*stateEvent.StateKey()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if !stateEvent.StateKeyEquals(device.UserID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
membership, err := stateEvent.Membership()
|
membership, err := stateEvent.Membership()
|
||||||
|
|
|
@ -91,7 +91,6 @@ func GetAvatarURL(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAvatarURL implements PUT /profile/{userID}/avatar_url
|
// SetAvatarURL implements PUT /profile/{userID}/avatar_url
|
||||||
// nolint:gocyclo
|
|
||||||
func SetAvatarURL(
|
func SetAvatarURL(
|
||||||
req *http.Request, accountDB accounts.Database,
|
req *http.Request, accountDB accounts.Database,
|
||||||
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
|
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
|
||||||
|
@ -209,7 +208,6 @@ func GetDisplayName(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDisplayName implements PUT /profile/{userID}/displayname
|
// SetDisplayName implements PUT /profile/{userID}/displayname
|
||||||
// nolint:gocyclo
|
|
||||||
func SetDisplayName(
|
func SetDisplayName(
|
||||||
req *http.Request, accountDB accounts.Database,
|
req *http.Request, accountDB accounts.Database,
|
||||||
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
|
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
|
||||||
|
|
|
@ -496,12 +496,21 @@ func Register(
|
||||||
r.Username = strconv.FormatInt(id, 10)
|
r.Username = strconv.FormatInt(id, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this an appservice registration? It will be if the access
|
||||||
|
// token is supplied
|
||||||
|
accessToken, accessTokenErr := auth.ExtractAccessToken(req)
|
||||||
|
|
||||||
// Squash username to all lowercase letters
|
// Squash username to all lowercase letters
|
||||||
r.Username = strings.ToLower(r.Username)
|
r.Username = strings.ToLower(r.Username)
|
||||||
|
if r.Type == authtypes.LoginTypeApplicationService && accessTokenErr == nil {
|
||||||
|
if resErr = validateApplicationServiceUsername(r.Username); resErr != nil {
|
||||||
|
return *resErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if resErr = validateUsername(r.Username); resErr != nil {
|
if resErr = validateUsername(r.Username); resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if resErr = validatePassword(r.Password); resErr != nil {
|
if resErr = validatePassword(r.Password); resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
@ -513,7 +522,7 @@ func Register(
|
||||||
"session_id": r.Auth.Session,
|
"session_id": r.Auth.Session,
|
||||||
}).Info("Processing registration request")
|
}).Info("Processing registration request")
|
||||||
|
|
||||||
return handleRegistrationFlow(req, r, sessionID, cfg, userAPI)
|
return handleRegistrationFlow(req, r, sessionID, cfg, userAPI, accessToken, accessTokenErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGuestRegistration(
|
func handleGuestRegistration(
|
||||||
|
@ -579,6 +588,8 @@ func handleRegistrationFlow(
|
||||||
sessionID string,
|
sessionID string,
|
||||||
cfg *config.ClientAPI,
|
cfg *config.ClientAPI,
|
||||||
userAPI userapi.UserInternalAPI,
|
userAPI userapi.UserInternalAPI,
|
||||||
|
accessToken string,
|
||||||
|
accessTokenErr error,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
// TODO: Shared secret registration (create new user scripts)
|
// TODO: Shared secret registration (create new user scripts)
|
||||||
// TODO: Enable registration config flag
|
// TODO: Enable registration config flag
|
||||||
|
@ -588,12 +599,12 @@ func handleRegistrationFlow(
|
||||||
// TODO: Handle mapping registrationRequest parameters into session parameters
|
// TODO: Handle mapping registrationRequest parameters into session parameters
|
||||||
|
|
||||||
// TODO: email / msisdn auth types.
|
// TODO: email / msisdn auth types.
|
||||||
accessToken, accessTokenErr := auth.ExtractAccessToken(req)
|
|
||||||
|
|
||||||
// Appservices are special and are not affected by disabled
|
// Appservices are special and are not affected by disabled
|
||||||
// registration or user exclusivity.
|
// registration or user exclusivity. We'll go onto the appservice
|
||||||
if r.Auth.Type == authtypes.LoginTypeApplicationService ||
|
// registration flow if a valid access token was provided or if
|
||||||
(r.Auth.Type == "" && accessTokenErr == nil) {
|
// the login type specifically requests it.
|
||||||
|
if r.Type == authtypes.LoginTypeApplicationService && accessTokenErr == nil {
|
||||||
return handleApplicationServiceRegistration(
|
return handleApplicationServiceRegistration(
|
||||||
accessToken, accessTokenErr, req, r, cfg, userAPI,
|
accessToken, accessTokenErr, req, r, cfg, userAPI,
|
||||||
)
|
)
|
||||||
|
|
|
@ -161,7 +161,6 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
||||||
// state to see if there is an event with that type and state key, if there
|
// state to see if there is an event with that type and state key, if there
|
||||||
// is then (by default) we return the content, otherwise a 404.
|
// is then (by default) we return the content, otherwise a 404.
|
||||||
// If eventFormat=true, sends the whole event else just the content.
|
// If eventFormat=true, sends the whole event else just the content.
|
||||||
// nolint:gocyclo
|
|
||||||
func OnIncomingStateTypeRequest(
|
func OnIncomingStateTypeRequest(
|
||||||
ctx context.Context, device *userapi.Device, rsAPI api.RoomserverInternalAPI,
|
ctx context.Context, device *userapi.Device, rsAPI api.RoomserverInternalAPI,
|
||||||
roomID, evType, stateKey string, eventFormat bool,
|
roomID, evType, stateKey string, eventFormat bool,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const usage = `Usage: %s
|
const usage = `Usage: %s
|
||||||
|
@ -57,7 +58,7 @@ func main() {
|
||||||
|
|
||||||
accountDB, err := accounts.NewDatabase(&config.DatabaseOptions{
|
accountDB, err := accounts.NewDatabase(&config.DatabaseOptions{
|
||||||
ConnectionString: cfg.UserAPI.AccountDatabase.ConnectionString,
|
ConnectionString: cfg.UserAPI.AccountDatabase.ConnectionString,
|
||||||
}, cfg.Global.ServerName)
|
}, cfg.Global.ServerName, bcrypt.DefaultCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatalln("Failed to connect to the database:", err.Error())
|
logrus.Fatalln("Failed to connect to the database:", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ var (
|
||||||
instancePeer = flag.String("peer", "", "an internet Yggdrasil peer to connect to")
|
instancePeer = flag.String("peer", "", "an internet Yggdrasil peer to connect to")
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
internal.SetupPprof()
|
internal.SetupPprof()
|
||||||
|
|
|
@ -73,7 +73,6 @@ func (n *Node) DialerContext(ctx context.Context, network, address string) (net.
|
||||||
return n.Dialer(network, address)
|
return n.Dialer(network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func Setup(instanceName, storageDirectory string) (*Node, error) {
|
func Setup(instanceName, storageDirectory string) (*Node, error) {
|
||||||
n := &Node{
|
n := &Node{
|
||||||
core: &yggdrasil.Core{},
|
core: &yggdrasil.Core{},
|
||||||
|
|
|
@ -128,7 +128,6 @@ func (n *Node) Dial(network, address string) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements http.Transport.DialContext
|
// Implements http.Transport.DialContext
|
||||||
// nolint:gocyclo
|
|
||||||
func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
s, ok1 := n.sessions.Load(address)
|
s, ok1 := n.sessions.Load(address)
|
||||||
session, ok2 := s.(*session)
|
session, ok2 := s.(*session)
|
||||||
|
|
|
@ -20,7 +20,6 @@ var requestFrom = flag.String("from", "", "the server name that the request shou
|
||||||
var requestKey = flag.String("key", "matrix_key.pem", "the private key to use when signing the request")
|
var requestKey = flag.String("key", "matrix_key.pem", "the private key to use when signing the request")
|
||||||
var requestPost = flag.Bool("post", false, "send a POST request instead of GET (pipe input into stdin or type followed by Ctrl-D)")
|
var requestPost = flag.Bool("post", false, "send a POST request instead of GET (pipe input into stdin or type followed by Ctrl-D)")
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,12 +62,14 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *defaultsForCI {
|
if *defaultsForCI {
|
||||||
|
cfg.AppServiceAPI.DisableTLSValidation = true
|
||||||
cfg.ClientAPI.RateLimiting.Enabled = false
|
cfg.ClientAPI.RateLimiting.Enabled = false
|
||||||
cfg.FederationSender.DisableTLSValidation = true
|
cfg.FederationSender.DisableTLSValidation = true
|
||||||
cfg.MSCs.MSCs = []string{"msc2836", "msc2946", "msc2444", "msc2753"}
|
cfg.MSCs.MSCs = []string{"msc2836", "msc2946", "msc2444", "msc2753"}
|
||||||
cfg.Logging[0].Level = "trace"
|
cfg.Logging[0].Level = "trace"
|
||||||
// don't hit matrix.org when running tests!!!
|
// don't hit matrix.org when running tests!!!
|
||||||
cfg.SigningKeyServer.KeyPerspectives = config.KeyPerspectives{}
|
cfg.SigningKeyServer.KeyPerspectives = config.KeyPerspectives{}
|
||||||
|
cfg.UserAPI.BCryptCost = bcrypt.MinCost
|
||||||
}
|
}
|
||||||
|
|
||||||
j, err := yaml.Marshal(cfg)
|
j, err := yaml.Marshal(cfg)
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
|
|
||||||
var roomVersion = flag.String("roomversion", "5", "the room version to parse events as")
|
var roomVersion = flag.String("roomversion", "5", "the room version to parse events as")
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func main() {
|
func main() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cfg := setup.ParseFlags(true)
|
cfg := setup.ParseFlags(true)
|
||||||
|
|
|
@ -125,6 +125,11 @@ app_service_api:
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
conn_max_lifetime: -1
|
conn_max_lifetime: -1
|
||||||
|
|
||||||
|
# Disable the validation of TLS certificates of appservices. This is
|
||||||
|
# not recommended in production since it may allow appservice traffic
|
||||||
|
# to be sent to an unverified endpoint.
|
||||||
|
disable_tls_validation: false
|
||||||
|
|
||||||
# Appservice configuration files to load into this homeserver.
|
# Appservice configuration files to load into this homeserver.
|
||||||
config_files: []
|
config_files: []
|
||||||
|
|
||||||
|
@ -235,7 +240,7 @@ media_api:
|
||||||
listen: http://[::]:8074
|
listen: http://[::]:8074
|
||||||
database:
|
database:
|
||||||
connection_string: file:mediaapi.db
|
connection_string: file:mediaapi.db
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
conn_max_lifetime: -1
|
conn_max_lifetime: -1
|
||||||
|
|
||||||
|
@ -273,7 +278,7 @@ mscs:
|
||||||
mscs: []
|
mscs: []
|
||||||
database:
|
database:
|
||||||
connection_string: file:mscs.db
|
connection_string: file:mscs.db
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
conn_max_lifetime: -1
|
conn_max_lifetime: -1
|
||||||
|
|
||||||
|
@ -335,6 +340,13 @@ sync_api:
|
||||||
|
|
||||||
# Configuration for the User API.
|
# Configuration for the User API.
|
||||||
user_api:
|
user_api:
|
||||||
|
# The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31
|
||||||
|
# See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information.
|
||||||
|
# Setting this lower makes registration/login consume less CPU resources at the cost of security
|
||||||
|
# should the database be compromised. Setting this higher makes registration/login consume more
|
||||||
|
# CPU resources but makes it harder to brute force password hashes.
|
||||||
|
# This value can be low if performing tests or on embedded Dendrite instances (e.g WASM builds)
|
||||||
|
# bcrypt_cost: 10
|
||||||
internal_api:
|
internal_api:
|
||||||
listen: http://localhost:7781
|
listen: http://localhost:7781
|
||||||
connect: http://localhost:7781
|
connect: http://localhost:7781
|
||||||
|
|
|
@ -29,7 +29,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeJoin implements the /make_join API
|
// MakeJoin implements the /make_join API
|
||||||
// nolint:gocyclo
|
|
||||||
func MakeJoin(
|
func MakeJoin(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
request *gomatrixserverlib.FederationRequest,
|
request *gomatrixserverlib.FederationRequest,
|
||||||
|
@ -161,7 +160,6 @@ func MakeJoin(
|
||||||
// SendJoin implements the /send_join API
|
// SendJoin implements the /send_join API
|
||||||
// The make-join send-join dance makes much more sense as a single
|
// The make-join send-join dance makes much more sense as a single
|
||||||
// flow so the cyclomatic complexity is high:
|
// flow so the cyclomatic complexity is high:
|
||||||
// nolint:gocyclo
|
|
||||||
func SendJoin(
|
func SendJoin(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
request *gomatrixserverlib.FederationRequest,
|
request *gomatrixserverlib.FederationRequest,
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeLeave implements the /make_leave API
|
// MakeLeave implements the /make_leave API
|
||||||
// nolint:gocyclo
|
|
||||||
func MakeLeave(
|
func MakeLeave(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
request *gomatrixserverlib.FederationRequest,
|
request *gomatrixserverlib.FederationRequest,
|
||||||
|
@ -118,7 +117,6 @@ func MakeLeave(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendLeave implements the /send_leave API
|
// SendLeave implements the /send_leave API
|
||||||
// nolint:gocyclo
|
|
||||||
func SendLeave(
|
func SendLeave(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
request *gomatrixserverlib.FederationRequest,
|
request *gomatrixserverlib.FederationRequest,
|
||||||
|
|
|
@ -111,7 +111,6 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
||||||
}
|
}
|
||||||
|
|
||||||
// due to lots of switches
|
// due to lots of switches
|
||||||
// nolint:gocyclo
|
|
||||||
func fillInRooms(ctx context.Context, roomIDs []string, rsAPI roomserverAPI.RoomserverInternalAPI) ([]gomatrixserverlib.PublicRoom, error) {
|
func fillInRooms(ctx context.Context, roomIDs []string, rsAPI roomserverAPI.RoomserverInternalAPI) ([]gomatrixserverlib.PublicRoom, error) {
|
||||||
avatarTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.avatar", StateKey: ""}
|
avatarTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.avatar", StateKey: ""}
|
||||||
nameTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.name", StateKey: ""}
|
nameTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.name", StateKey: ""}
|
||||||
|
|
|
@ -53,9 +53,12 @@ func RoomAliasToID(
|
||||||
var resp gomatrixserverlib.RespDirectory
|
var resp gomatrixserverlib.RespDirectory
|
||||||
|
|
||||||
if domain == cfg.Matrix.ServerName {
|
if domain == cfg.Matrix.ServerName {
|
||||||
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
|
queryReq := &roomserverAPI.GetRoomIDForAliasRequest{
|
||||||
var queryRes roomserverAPI.GetRoomIDForAliasResponse
|
Alias: roomAlias,
|
||||||
if err = rsAPI.GetRoomIDForAlias(httpReq.Context(), &queryReq, &queryRes); err != nil {
|
IncludeAppservices: true,
|
||||||
|
}
|
||||||
|
queryRes := &roomserverAPI.GetRoomIDForAliasResponse{}
|
||||||
|
if err = rsAPI.GetRoomIDForAlias(httpReq.Context(), queryReq, queryRes); err != nil {
|
||||||
util.GetLogger(httpReq.Context()).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
|
util.GetLogger(httpReq.Context()).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,7 +279,6 @@ func (t *txnReq) haveEventIDs() map[string]bool {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (t *txnReq) processEDUs(ctx context.Context) {
|
func (t *txnReq) processEDUs(ctx context.Context) {
|
||||||
for _, e := range t.EDUs {
|
for _, e := range t.EDUs {
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
|
@ -540,7 +539,6 @@ func checkAllowedByState(e *gomatrixserverlib.Event, stateEvents []*gomatrixserv
|
||||||
return gomatrixserverlib.Allowed(e, &authUsingState)
|
return gomatrixserverlib.Allowed(e, &authUsingState)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (t *txnReq) processEventWithMissingState(ctx context.Context, e *gomatrixserverlib.Event, roomVersion gomatrixserverlib.RoomVersion) error {
|
func (t *txnReq) processEventWithMissingState(ctx context.Context, e *gomatrixserverlib.Event, roomVersion gomatrixserverlib.RoomVersion) error {
|
||||||
// Do this with a fresh context, so that we keep working even if the
|
// Do this with a fresh context, so that we keep working even if the
|
||||||
// original request times out. With any luck, by the time the remote
|
// original request times out. With any luck, by the time the remote
|
||||||
|
@ -832,7 +830,6 @@ retryAllowedState:
|
||||||
// begin from. Returns an error only if we should terminate the transaction which initiated /get_missing_events
|
// begin from. Returns an error only if we should terminate the transaction which initiated /get_missing_events
|
||||||
// This function recursively calls txnReq.processEvent with the missing events, which will be processed before this function returns.
|
// This function recursively calls txnReq.processEvent with the missing events, which will be processed before this function returns.
|
||||||
// This means that we may recursively call this function, as we spider back up prev_events.
|
// This means that we may recursively call this function, as we spider back up prev_events.
|
||||||
// nolint:gocyclo
|
|
||||||
func (t *txnReq) getMissingEvents(ctx context.Context, e *gomatrixserverlib.Event, roomVersion gomatrixserverlib.RoomVersion) (newEvents []*gomatrixserverlib.Event, err error) {
|
func (t *txnReq) getMissingEvents(ctx context.Context, e *gomatrixserverlib.Event, roomVersion gomatrixserverlib.RoomVersion) (newEvents []*gomatrixserverlib.Event, err error) {
|
||||||
logger := util.GetLogger(ctx).WithField("event_id", e.EventID()).WithField("room_id", e.RoomID())
|
logger := util.GetLogger(ctx).WithField("event_id", e.EventID()).WithField("room_id", e.RoomID())
|
||||||
needed := gomatrixserverlib.StateNeededForAuth([]*gomatrixserverlib.Event{e})
|
needed := gomatrixserverlib.StateNeededForAuth([]*gomatrixserverlib.Event{e})
|
||||||
|
@ -935,7 +932,6 @@ func (t *txnReq) lookupMissingStateViaState(ctx context.Context, roomID, eventID
|
||||||
return &state, nil
|
return &state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (t *txnReq) lookupMissingStateViaStateIDs(ctx context.Context, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion) (
|
func (t *txnReq) lookupMissingStateViaStateIDs(ctx context.Context, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion) (
|
||||||
*gomatrixserverlib.RespState, error) {
|
*gomatrixserverlib.RespState, error) {
|
||||||
util.GetLogger(ctx).Infof("lookupMissingStateViaStateIDs %s", eventID)
|
util.GetLogger(ctx).Infof("lookupMissingStateViaStateIDs %s", eventID)
|
||||||
|
|
|
@ -173,7 +173,6 @@ func (oq *destinationQueue) wakeQueueIfNeeded() {
|
||||||
// getPendingFromDatabase will look at the database and see if
|
// getPendingFromDatabase will look at the database and see if
|
||||||
// there are any persisted events that haven't been sent to this
|
// there are any persisted events that haven't been sent to this
|
||||||
// destination yet. If so, they will be queued up.
|
// destination yet. If so, they will be queued up.
|
||||||
// nolint:gocyclo
|
|
||||||
func (oq *destinationQueue) getPendingFromDatabase() {
|
func (oq *destinationQueue) getPendingFromDatabase() {
|
||||||
// Check to see if there's anything to do for this server
|
// Check to see if there's anything to do for this server
|
||||||
// in the database.
|
// in the database.
|
||||||
|
@ -238,7 +237,6 @@ func (oq *destinationQueue) getPendingFromDatabase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// backgroundSend is the worker goroutine for sending events.
|
// backgroundSend is the worker goroutine for sending events.
|
||||||
// nolint:gocyclo
|
|
||||||
func (oq *destinationQueue) backgroundSend() {
|
func (oq *destinationQueue) backgroundSend() {
|
||||||
// Check if a worker is already running, and if it isn't, then
|
// Check if a worker is already running, and if it isn't, then
|
||||||
// mark it as started.
|
// mark it as started.
|
||||||
|
@ -353,7 +351,6 @@ func (oq *destinationQueue) backgroundSend() {
|
||||||
// nextTransaction creates a new transaction from the pending event
|
// nextTransaction creates a new transaction from the pending event
|
||||||
// queue and sends it. Returns true if a transaction was sent or
|
// queue and sends it. Returns true if a transaction was sent or
|
||||||
// false otherwise.
|
// false otherwise.
|
||||||
// nolint:gocyclo
|
|
||||||
func (oq *destinationQueue) nextTransaction(
|
func (oq *destinationQueue) nextTransaction(
|
||||||
pdus []*queuedPDU,
|
pdus []*queuedPDU,
|
||||||
edus []*queuedEDU,
|
edus []*queuedEDU,
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -866,8 +866,6 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
|
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
|
||||||
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
|
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
|
|
@ -34,6 +34,9 @@ type SetRoomAliasResponse struct {
|
||||||
type GetRoomIDForAliasRequest struct {
|
type GetRoomIDForAliasRequest struct {
|
||||||
// Alias we want to lookup
|
// Alias we want to lookup
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
|
// Should we ask appservices for their aliases as a part of
|
||||||
|
// the request?
|
||||||
|
IncludeAppservices bool `json:"include_appservices"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRoomIDForAliasResponse is a response to GetRoomIDForAlias
|
// GetRoomIDForAliasResponse is a response to GetRoomIDForAlias
|
||||||
|
|
|
@ -151,7 +151,9 @@ type QueryMembershipsForRoomRequest struct {
|
||||||
JoinedOnly bool `json:"joined_only"`
|
JoinedOnly bool `json:"joined_only"`
|
||||||
// ID of the room to fetch memberships from
|
// ID of the room to fetch memberships from
|
||||||
RoomID string `json:"room_id"`
|
RoomID string `json:"room_id"`
|
||||||
// ID of the user sending the request
|
// Optional - ID of the user sending the request, for checking if the
|
||||||
|
// user is allowed to see the memberships. If not specified then all
|
||||||
|
// room memberships will be returned.
|
||||||
Sender string `json:"sender"`
|
Sender string `json:"sender"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,6 @@ func IsServerBannedFromRoom(ctx context.Context, rsAPI RoomserverInternalAPI, ro
|
||||||
// PopulatePublicRooms extracts PublicRoom information for all the provided room IDs. The IDs are not checked to see if they are visible in the
|
// PopulatePublicRooms extracts PublicRoom information for all the provided room IDs. The IDs are not checked to see if they are visible in the
|
||||||
// published room directory.
|
// published room directory.
|
||||||
// due to lots of switches
|
// due to lots of switches
|
||||||
// nolint:gocyclo
|
|
||||||
func PopulatePublicRooms(ctx context.Context, roomIDs []string, rsAPI RoomserverInternalAPI) ([]gomatrixserverlib.PublicRoom, error) {
|
func PopulatePublicRooms(ctx context.Context, roomIDs []string, rsAPI RoomserverInternalAPI) ([]gomatrixserverlib.PublicRoom, error) {
|
||||||
avatarTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.avatar", StateKey: ""}
|
avatarTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.avatar", StateKey: ""}
|
||||||
nameTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.name", StateKey: ""}
|
nameTuple := gomatrixserverlib.StateKeyTuple{EventType: "m.room.name", StateKey: ""}
|
||||||
|
|
|
@ -88,31 +88,35 @@ func (r *RoomserverInternalAPI) GetRoomIDForAlias(
|
||||||
) error {
|
) error {
|
||||||
// Look up the room ID in the database
|
// Look up the room ID in the database
|
||||||
roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
||||||
if err != nil {
|
if err == nil && roomID != "" {
|
||||||
return err
|
response.RoomID = roomID
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.asAPI != nil { // appservice component is wired in
|
// Check appservice on err, but only if the appservice API is
|
||||||
if roomID == "" {
|
// wired in and no room ID was found.
|
||||||
|
if r.asAPI != nil && request.IncludeAppservices && roomID == "" {
|
||||||
// No room found locally, try our application services by making a call to
|
// No room found locally, try our application services by making a call to
|
||||||
// the appservice component
|
// the appservice component
|
||||||
aliasReq := asAPI.RoomAliasExistsRequest{Alias: request.Alias}
|
aliasReq := &asAPI.RoomAliasExistsRequest{
|
||||||
var aliasResp asAPI.RoomAliasExistsResponse
|
Alias: request.Alias,
|
||||||
if err = r.asAPI.RoomAliasExists(ctx, &aliasReq, &aliasResp); err != nil {
|
}
|
||||||
|
aliasRes := &asAPI.RoomAliasExistsResponse{}
|
||||||
|
if err = r.asAPI.RoomAliasExists(ctx, aliasReq, aliasRes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if aliasResp.AliasExists {
|
if aliasRes.AliasExists {
|
||||||
roomID, err = r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
roomID, err = r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
response.RoomID = roomID
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response.RoomID = roomID
|
return err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAliasesForRoomID implements alias.RoomserverInternalAPI
|
// GetAliasesForRoomID implements alias.RoomserverInternalAPI
|
||||||
|
|
|
@ -89,6 +89,7 @@ func (r *RoomserverInternalAPI) SetFederationSenderAPI(fsAPI fsAPI.FederationSen
|
||||||
Cfg: r.Cfg,
|
Cfg: r.Cfg,
|
||||||
DB: r.DB,
|
DB: r.DB,
|
||||||
FSAPI: r.fsAPI,
|
FSAPI: r.fsAPI,
|
||||||
|
RSAPI: r,
|
||||||
Inputer: r.Inputer,
|
Inputer: r.Inputer,
|
||||||
}
|
}
|
||||||
r.Peeker = &perform.Peeker{
|
r.Peeker = &perform.Peeker{
|
||||||
|
|
|
@ -270,7 +270,6 @@ func CheckServerAllowedToSeeEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this when we have tests to assert correctness of this function
|
// TODO: Remove this when we have tests to assert correctness of this function
|
||||||
// nolint:gocyclo
|
|
||||||
func ScanEventTree(
|
func ScanEventTree(
|
||||||
ctx context.Context, db storage.Database, info types.RoomInfo, front []string, visited map[string]bool, limit int,
|
ctx context.Context, db storage.Database, info types.RoomInfo, front []string, visited map[string]bool, limit int,
|
||||||
serverName gomatrixserverlib.ServerName,
|
serverName gomatrixserverlib.ServerName,
|
||||||
|
|
|
@ -381,7 +381,6 @@ func (b *backfillRequester) StateBeforeEvent(ctx context.Context, roomVer gomatr
|
||||||
// It returns a list of servers which can be queried for backfill requests. These servers
|
// It returns a list of servers which can be queried for backfill requests. These servers
|
||||||
// will be servers that are in the room already. The entries at the beginning are preferred servers
|
// will be servers that are in the room already. The entries at the beginning are preferred servers
|
||||||
// and will be tried first. An empty list will fail the request.
|
// and will be tried first. An empty list will fail the request.
|
||||||
// nolint:gocyclo
|
|
||||||
func (b *backfillRequester) ServersAtEvent(ctx context.Context, roomID, eventID string) []gomatrixserverlib.ServerName {
|
func (b *backfillRequester) ServersAtEvent(ctx context.Context, roomID, eventID string) []gomatrixserverlib.ServerName {
|
||||||
// eventID will be a prev_event ID of a backwards extremity, meaning we will not have a database entry for it. Instead, use
|
// eventID will be a prev_event ID of a backwards extremity, meaning we will not have a database entry for it. Instead, use
|
||||||
// its successor, so look it up.
|
// its successor, so look it up.
|
||||||
|
|
|
@ -37,7 +37,6 @@ type Inviter struct {
|
||||||
Inputer *input.Inputer
|
Inputer *input.Inputer
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (r *Inviter) PerformInvite(
|
func (r *Inviter) PerformInvite(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformInviteRequest,
|
req *api.PerformInviteRequest,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
fsAPI "github.com/matrix-org/dendrite/federationsender/api"
|
fsAPI "github.com/matrix-org/dendrite/federationsender/api"
|
||||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
|
rsAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
"github.com/matrix-org/dendrite/roomserver/internal/helpers"
|
||||||
"github.com/matrix-org/dendrite/roomserver/internal/input"
|
"github.com/matrix-org/dendrite/roomserver/internal/input"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage"
|
"github.com/matrix-org/dendrite/roomserver/storage"
|
||||||
|
@ -36,6 +37,7 @@ type Joiner struct {
|
||||||
ServerName gomatrixserverlib.ServerName
|
ServerName gomatrixserverlib.ServerName
|
||||||
Cfg *config.RoomServer
|
Cfg *config.RoomServer
|
||||||
FSAPI fsAPI.FederationSenderInternalAPI
|
FSAPI fsAPI.FederationSenderInternalAPI
|
||||||
|
RSAPI rsAPI.RoomserverInternalAPI
|
||||||
DB storage.Database
|
DB storage.Database
|
||||||
|
|
||||||
Inputer *input.Inputer
|
Inputer *input.Inputer
|
||||||
|
@ -121,11 +123,17 @@ func (r *Joiner) performJoinRoomByAlias(
|
||||||
roomID = dirRes.RoomID
|
roomID = dirRes.RoomID
|
||||||
req.ServerNames = append(req.ServerNames, dirRes.ServerNames...)
|
req.ServerNames = append(req.ServerNames, dirRes.ServerNames...)
|
||||||
} else {
|
} else {
|
||||||
|
var getRoomReq = rsAPI.GetRoomIDForAliasRequest{
|
||||||
|
Alias: req.RoomIDOrAlias,
|
||||||
|
IncludeAppservices: true,
|
||||||
|
}
|
||||||
|
var getRoomRes = rsAPI.GetRoomIDForAliasResponse{}
|
||||||
// Otherwise, look up if we know this room alias locally.
|
// Otherwise, look up if we know this room alias locally.
|
||||||
roomID, err = r.DB.GetRoomIDForAlias(ctx, req.RoomIDOrAlias)
|
err = r.RSAPI.GetRoomIDForAlias(ctx, &getRoomReq, &getRoomRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("Lookup room alias %q failed: %w", req.RoomIDOrAlias, err)
|
return "", "", fmt.Errorf("Lookup room alias %q failed: %w", req.RoomIDOrAlias, err)
|
||||||
}
|
}
|
||||||
|
roomID = getRoomRes.RoomID
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the room ID is empty then we failed to look up the alias.
|
// If the room ID is empty then we failed to look up the alias.
|
||||||
|
@ -139,7 +147,6 @@ func (r *Joiner) performJoinRoomByAlias(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Break this function up a bit
|
// TODO: Break this function up a bit
|
||||||
// nolint:gocyclo
|
|
||||||
func (r *Joiner) performJoinRoomByID(
|
func (r *Joiner) performJoinRoomByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformJoinRequest,
|
req *api.PerformJoinRequest,
|
||||||
|
|
|
@ -49,7 +49,6 @@ func (r *Queryer) QueryLatestEventsAndState(
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryStateAfterEvents implements api.RoomserverInternalAPI
|
// QueryStateAfterEvents implements api.RoomserverInternalAPI
|
||||||
// nolint:gocyclo
|
|
||||||
func (r *Queryer) QueryStateAfterEvents(
|
func (r *Queryer) QueryStateAfterEvents(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
request *api.QueryStateAfterEventsRequest,
|
request *api.QueryStateAfterEventsRequest,
|
||||||
|
@ -243,6 +242,27 @@ func (r *Queryer) QueryMembershipsForRoom(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no sender is specified then we will just return the entire
|
||||||
|
// set of memberships for the room, regardless of whether a specific
|
||||||
|
// user is allowed to see them or not.
|
||||||
|
if request.Sender == "" {
|
||||||
|
var events []types.Event
|
||||||
|
var eventNIDs []types.EventNID
|
||||||
|
eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.JoinedOnly, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err)
|
||||||
|
}
|
||||||
|
events, err = r.DB.Events(ctx, eventNIDs)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("r.DB.Events: %w", err)
|
||||||
|
}
|
||||||
|
for _, event := range events {
|
||||||
|
clientEvent := gomatrixserverlib.ToClientEvent(event.Event, gomatrixserverlib.FormatAll)
|
||||||
|
response.JoinEvents = append(response.JoinEvents, clientEvent)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
membershipEventNID, stillInRoom, isRoomforgotten, err := r.DB.GetMembership(ctx, info.RoomNID, request.Sender)
|
membershipEventNID, stillInRoom, isRoomforgotten, err := r.DB.GetMembership(ctx, info.RoomNID, request.Sender)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -372,7 +392,6 @@ func (r *Queryer) QueryServerAllowedToSeeEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryMissingEvents implements api.RoomserverInternalAPI
|
// QueryMissingEvents implements api.RoomserverInternalAPI
|
||||||
// nolint:gocyclo
|
|
||||||
func (r *Queryer) QueryMissingEvents(
|
func (r *Queryer) QueryMissingEvents(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
request *api.QueryMissingEventsRequest,
|
request *api.QueryMissingEventsRequest,
|
||||||
|
|
|
@ -770,7 +770,6 @@ func (v *StateResolution) resolveConflictsV1(
|
||||||
// Returns a list that combines the entries without conflicts with the result of state resolution for the entries with conflicts.
|
// Returns a list that combines the entries without conflicts with the result of state resolution for the entries with conflicts.
|
||||||
// The returned list is sorted by state key tuple.
|
// The returned list is sorted by state key tuple.
|
||||||
// Returns an error if there was a problem talking to the database.
|
// Returns an error if there was a problem talking to the database.
|
||||||
// nolint:gocyclo
|
|
||||||
func (v *StateResolution) resolveConflictsV2(
|
func (v *StateResolution) resolveConflictsV2(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
notConflicted, conflicted []types.StateEntry,
|
notConflicted, conflicted []types.StateEntry,
|
||||||
|
|
|
@ -412,7 +412,6 @@ func (d *Database) GetLatestEventsForUpdate(
|
||||||
return updater, err
|
return updater, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) StoreEvent(
|
func (d *Database) StoreEvent(
|
||||||
ctx context.Context, event *gomatrixserverlib.Event,
|
ctx context.Context, event *gomatrixserverlib.Event,
|
||||||
txnAndSessionID *api.TransactionID, authEventNIDs []types.EventNID, isRejected bool,
|
txnAndSessionID *api.TransactionID, authEventNIDs []types.EventNID, isRejected bool,
|
||||||
|
@ -672,7 +671,6 @@ func extractRoomVersionFromCreateEvent(event *gomatrixserverlib.Event) (
|
||||||
// to cross-reference with other tables when loading.
|
// to cross-reference with other tables when loading.
|
||||||
//
|
//
|
||||||
// Returns the redaction event and the event ID of the redacted event if this call resulted in a redaction.
|
// Returns the redaction event and the event ID of the redacted event if this call resulted in a redaction.
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) handleRedactions(
|
func (d *Database) handleRedactions(
|
||||||
ctx context.Context, txn *sql.Tx, eventNID types.EventNID, event *gomatrixserverlib.Event,
|
ctx context.Context, txn *sql.Tx, eventNID types.EventNID, event *gomatrixserverlib.Event,
|
||||||
) (*gomatrixserverlib.Event, string, error) {
|
) (*gomatrixserverlib.Event, string, error) {
|
||||||
|
@ -802,7 +800,6 @@ func (d *Database) loadEvent(ctx context.Context, eventID string) *types.Event {
|
||||||
// GetStateEvent returns the current state event of a given type for a given room with a given state key
|
// GetStateEvent returns the current state event of a given type for a given room with a given state key
|
||||||
// If no event could be found, returns nil
|
// If no event could be found, returns nil
|
||||||
// If there was an issue during the retrieval, returns an error
|
// If there was an issue during the retrieval, returns an error
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*gomatrixserverlib.HeaderedEvent, error) {
|
func (d *Database) GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*gomatrixserverlib.HeaderedEvent, error) {
|
||||||
roomInfo, err := d.RoomInfo(ctx, roomID)
|
roomInfo, err := d.RoomInfo(ctx, roomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -893,7 +890,6 @@ func (d *Database) GetRoomsByMembership(ctx context.Context, userID, membership
|
||||||
|
|
||||||
// GetBulkStateContent returns all state events which match a given room ID and a given state key tuple. Both must be satisfied for a match.
|
// GetBulkStateContent returns all state events which match a given room ID and a given state key tuple. Both must be satisfied for a match.
|
||||||
// If a tuple has the StateKey of '*' and allowWildcards=true then all state events with the EventType should be returned.
|
// If a tuple has the StateKey of '*' and allowWildcards=true then all state events with the EventType should be returned.
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) GetBulkStateContent(ctx context.Context, roomIDs []string, tuples []gomatrixserverlib.StateKeyTuple, allowWildcards bool) ([]tables.StrippedEvent, error) {
|
func (d *Database) GetBulkStateContent(ctx context.Context, roomIDs []string, tuples []gomatrixserverlib.StateKeyTuple, allowWildcards bool) ([]tables.StrippedEvent, error) {
|
||||||
eventTypes := make([]string, 0, len(tuples))
|
eventTypes := make([]string, 0, len(tuples))
|
||||||
for _, tuple := range tuples {
|
for _, tuple := range tuples {
|
||||||
|
|
|
@ -263,7 +263,7 @@ func (b *BaseDendrite) KeyServerHTTPClient() keyserverAPI.KeyInternalAPI {
|
||||||
// CreateAccountsDB creates a new instance of the accounts database. Should only
|
// CreateAccountsDB creates a new instance of the accounts database. Should only
|
||||||
// be called once per component.
|
// be called once per component.
|
||||||
func (b *BaseDendrite) CreateAccountsDB() accounts.Database {
|
func (b *BaseDendrite) CreateAccountsDB() accounts.Database {
|
||||||
db, err := accounts.NewDatabase(&b.Cfg.UserAPI.AccountDatabase, b.Cfg.Global.ServerName)
|
db, err := accounts.NewDatabase(&b.Cfg.UserAPI.AccountDatabase, b.Cfg.Global.ServerName, b.Cfg.UserAPI.BCryptCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Panicf("failed to connect to accounts db")
|
logrus.WithError(err).Panicf("failed to connect to accounts db")
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,6 @@ func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationCli
|
||||||
|
|
||||||
// SetupAndServeHTTP sets up the HTTP server to serve endpoints registered on
|
// SetupAndServeHTTP sets up the HTTP server to serve endpoints registered on
|
||||||
// ApiMux under /api/ and adds a prometheus handler under /metrics.
|
// ApiMux under /api/ and adds a prometheus handler under /metrics.
|
||||||
// nolint:gocyclo
|
|
||||||
func (b *BaseDendrite) SetupAndServeHTTP(
|
func (b *BaseDendrite) SetupAndServeHTTP(
|
||||||
internalHTTPAddr, externalHTTPAddr config.HTTPAddress,
|
internalHTTPAddr, externalHTTPAddr config.HTTPAddress,
|
||||||
certFile, keyFile *string,
|
certFile, keyFile *string,
|
||||||
|
|
|
@ -33,13 +33,17 @@ type AppServiceAPI struct {
|
||||||
|
|
||||||
Database DatabaseOptions `yaml:"database"`
|
Database DatabaseOptions `yaml:"database"`
|
||||||
|
|
||||||
|
// DisableTLSValidation disables the validation of X.509 TLS certs
|
||||||
|
// on appservice endpoints. This is not recommended in production!
|
||||||
|
DisableTLSValidation bool `yaml:"disable_tls_validation"`
|
||||||
|
|
||||||
ConfigFiles []string `yaml:"config_files"`
|
ConfigFiles []string `yaml:"config_files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AppServiceAPI) Defaults() {
|
func (c *AppServiceAPI) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7777"
|
c.InternalAPI.Listen = "http://localhost:7777"
|
||||||
c.InternalAPI.Connect = "http://localhost:7777"
|
c.InternalAPI.Connect = "http://localhost:7777"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:appservice.db"
|
c.Database.ConnectionString = "file:appservice.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +197,7 @@ func loadAppServices(config *AppServiceAPI, derived *Derived) error {
|
||||||
// setupRegexps will create regex objects for exclusive and non-exclusive
|
// setupRegexps will create regex objects for exclusive and non-exclusive
|
||||||
// usernames, aliases and rooms of all application services, so that other
|
// usernames, aliases and rooms of all application services, so that other
|
||||||
// methods can quickly check if a particular string matches any of them.
|
// methods can quickly check if a particular string matches any of them.
|
||||||
func setupRegexps(_ *AppServiceAPI, derived *Derived) (err error) {
|
func setupRegexps(asAPI *AppServiceAPI, derived *Derived) (err error) {
|
||||||
// Combine all exclusive namespaces for later string checking
|
// Combine all exclusive namespaces for later string checking
|
||||||
var exclusiveUsernameStrings, exclusiveAliasStrings []string
|
var exclusiveUsernameStrings, exclusiveAliasStrings []string
|
||||||
|
|
||||||
|
@ -201,6 +205,16 @@ func setupRegexps(_ *AppServiceAPI, derived *Derived) (err error) {
|
||||||
// its contents to the overall exlusive regex string. Room regex
|
// its contents to the overall exlusive regex string. Room regex
|
||||||
// not necessary as we aren't denying exclusive room ID creation
|
// not necessary as we aren't denying exclusive room ID creation
|
||||||
for _, appservice := range derived.ApplicationServices {
|
for _, appservice := range derived.ApplicationServices {
|
||||||
|
// The sender_localpart can be considered an exclusive regex for a single user, so let's do that
|
||||||
|
// to simplify the code
|
||||||
|
var senderUserIDSlice = []string{fmt.Sprintf("@%s:%s", appservice.SenderLocalpart, asAPI.Matrix.ServerName)}
|
||||||
|
usersSlice, found := appservice.NamespaceMap["users"]
|
||||||
|
if !found {
|
||||||
|
usersSlice = []ApplicationServiceNamespace{}
|
||||||
|
appservice.NamespaceMap["users"] = usersSlice
|
||||||
|
}
|
||||||
|
appendExclusiveNamespaceRegexs(&senderUserIDSlice, usersSlice)
|
||||||
|
|
||||||
for key, namespaceSlice := range appservice.NamespaceMap {
|
for key, namespaceSlice := range appservice.NamespaceMap {
|
||||||
switch key {
|
switch key {
|
||||||
case "users":
|
case "users":
|
||||||
|
|
|
@ -25,7 +25,7 @@ type FederationSender struct {
|
||||||
func (c *FederationSender) Defaults() {
|
func (c *FederationSender) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7775"
|
c.InternalAPI.Listen = "http://localhost:7775"
|
||||||
c.InternalAPI.Connect = "http://localhost:7775"
|
c.InternalAPI.Connect = "http://localhost:7775"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:federationsender.db"
|
c.Database.ConnectionString = "file:federationsender.db"
|
||||||
|
|
||||||
c.FederationMaxRetries = 16
|
c.FederationMaxRetries = 16
|
||||||
|
|
|
@ -122,8 +122,8 @@ type DatabaseOptions struct {
|
||||||
ConnMaxLifetimeSeconds int `yaml:"conn_max_lifetime"`
|
ConnMaxLifetimeSeconds int `yaml:"conn_max_lifetime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DatabaseOptions) Defaults() {
|
func (c *DatabaseOptions) Defaults(conns int) {
|
||||||
c.MaxOpenConnections = 100
|
c.MaxOpenConnections = conns
|
||||||
c.MaxIdleConnections = 2
|
c.MaxIdleConnections = 2
|
||||||
c.ConnMaxLifetimeSeconds = -1
|
c.ConnMaxLifetimeSeconds = -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ func (k *Kafka) TopicFor(name string) string {
|
||||||
|
|
||||||
func (c *Kafka) Defaults() {
|
func (c *Kafka) Defaults() {
|
||||||
c.UseNaffka = true
|
c.UseNaffka = true
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Addresses = []string{"localhost:2181"}
|
c.Addresses = []string{"localhost:2181"}
|
||||||
c.Database.ConnectionString = DataSource("file:naffka.db")
|
c.Database.ConnectionString = DataSource("file:naffka.db")
|
||||||
c.TopicPrefix = "Dendrite"
|
c.TopicPrefix = "Dendrite"
|
||||||
|
|
|
@ -11,7 +11,7 @@ type KeyServer struct {
|
||||||
func (c *KeyServer) Defaults() {
|
func (c *KeyServer) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7779"
|
c.InternalAPI.Listen = "http://localhost:7779"
|
||||||
c.InternalAPI.Connect = "http://localhost:7779"
|
c.InternalAPI.Connect = "http://localhost:7779"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:keyserver.db"
|
c.Database.ConnectionString = "file:keyserver.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ func (c *MediaAPI) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7774"
|
c.InternalAPI.Listen = "http://localhost:7774"
|
||||||
c.InternalAPI.Connect = "http://localhost:7774"
|
c.InternalAPI.Connect = "http://localhost:7774"
|
||||||
c.ExternalAPI.Listen = "http://[::]:8074"
|
c.ExternalAPI.Listen = "http://[::]:8074"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(5)
|
||||||
c.Database.ConnectionString = "file:mediaapi.db"
|
c.Database.ConnectionString = "file:mediaapi.db"
|
||||||
|
|
||||||
defaultMaxFileSizeBytes := FileSizeBytes(10485760)
|
defaultMaxFileSizeBytes := FileSizeBytes(10485760)
|
||||||
|
|
|
@ -14,7 +14,7 @@ type MSCs struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MSCs) Defaults() {
|
func (c *MSCs) Defaults() {
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(5)
|
||||||
c.Database.ConnectionString = "file:mscs.db"
|
c.Database.ConnectionString = "file:mscs.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ type RoomServer struct {
|
||||||
func (c *RoomServer) Defaults() {
|
func (c *RoomServer) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7770"
|
c.InternalAPI.Listen = "http://localhost:7770"
|
||||||
c.InternalAPI.Connect = "http://localhost:7770"
|
c.InternalAPI.Connect = "http://localhost:7770"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:roomserver.db"
|
c.Database.ConnectionString = "file:roomserver.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ type SigningKeyServer struct {
|
||||||
func (c *SigningKeyServer) Defaults() {
|
func (c *SigningKeyServer) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7780"
|
c.InternalAPI.Listen = "http://localhost:7780"
|
||||||
c.InternalAPI.Connect = "http://localhost:7780"
|
c.InternalAPI.Connect = "http://localhost:7780"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:signingkeyserver.db"
|
c.Database.ConnectionString = "file:signingkeyserver.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ func (c *SyncAPI) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7773"
|
c.InternalAPI.Listen = "http://localhost:7773"
|
||||||
c.InternalAPI.Connect = "http://localhost:7773"
|
c.InternalAPI.Connect = "http://localhost:7773"
|
||||||
c.ExternalAPI.Listen = "http://localhost:8073"
|
c.ExternalAPI.Listen = "http://localhost:8073"
|
||||||
c.Database.Defaults()
|
c.Database.Defaults(10)
|
||||||
c.Database.ConnectionString = "file:syncapi.db"
|
c.Database.ConnectionString = "file:syncapi.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
type UserAPI struct {
|
type UserAPI struct {
|
||||||
Matrix *Global `yaml:"-"`
|
Matrix *Global `yaml:"-"`
|
||||||
|
|
||||||
InternalAPI InternalAPIOptions `yaml:"internal_api"`
|
InternalAPI InternalAPIOptions `yaml:"internal_api"`
|
||||||
|
|
||||||
|
// The cost when hashing passwords.
|
||||||
|
BCryptCost int `yaml:"bcrypt_cost"`
|
||||||
|
|
||||||
// The Account database stores the login details and account information
|
// The Account database stores the login details and account information
|
||||||
// for local users. It is accessed by the UserAPI.
|
// for local users. It is accessed by the UserAPI.
|
||||||
AccountDatabase DatabaseOptions `yaml:"account_database"`
|
AccountDatabase DatabaseOptions `yaml:"account_database"`
|
||||||
|
@ -16,10 +21,11 @@ type UserAPI struct {
|
||||||
func (c *UserAPI) Defaults() {
|
func (c *UserAPI) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7781"
|
c.InternalAPI.Listen = "http://localhost:7781"
|
||||||
c.InternalAPI.Connect = "http://localhost:7781"
|
c.InternalAPI.Connect = "http://localhost:7781"
|
||||||
c.AccountDatabase.Defaults()
|
c.AccountDatabase.Defaults(10)
|
||||||
c.DeviceDatabase.Defaults()
|
c.DeviceDatabase.Defaults(10)
|
||||||
c.AccountDatabase.ConnectionString = "file:userapi_accounts.db"
|
c.AccountDatabase.ConnectionString = "file:userapi_accounts.db"
|
||||||
c.DeviceDatabase.ConnectionString = "file:userapi_devices.db"
|
c.DeviceDatabase.ConnectionString = "file:userapi_devices.db"
|
||||||
|
c.BCryptCost = bcrypt.DefaultCost
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
|
|
|
@ -238,7 +238,6 @@ func federatedEventRelationship(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (rc *reqCtx) process() (*gomatrixserverlib.MSC2836EventRelationshipsResponse, *util.JSONResponse) {
|
func (rc *reqCtx) process() (*gomatrixserverlib.MSC2836EventRelationshipsResponse, *util.JSONResponse) {
|
||||||
var res gomatrixserverlib.MSC2836EventRelationshipsResponse
|
var res gomatrixserverlib.MSC2836EventRelationshipsResponse
|
||||||
var returnEvents []*gomatrixserverlib.HeaderedEvent
|
var returnEvents []*gomatrixserverlib.HeaderedEvent
|
||||||
|
|
|
@ -217,7 +217,6 @@ func (w *walker) markSent(id string) {
|
||||||
w.inMemoryBatchCache[w.callerID()] = m
|
w.inMemoryBatchCache[w.callerID()] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (w *walker) walk() *gomatrixserverlib.MSC2946SpacesResponse {
|
func (w *walker) walk() *gomatrixserverlib.MSC2946SpacesResponse {
|
||||||
var res gomatrixserverlib.MSC2946SpacesResponse
|
var res gomatrixserverlib.MSC2946SpacesResponse
|
||||||
// Begin walking the graph starting with the room ID in the request in a queue of unvisited rooms
|
// Begin walking the graph starting with the room ID in the request in a queue of unvisited rooms
|
||||||
|
|
|
@ -46,7 +46,6 @@ func DeviceOTKCounts(ctx context.Context, keyAPI keyapi.KeyInternalAPI, userID,
|
||||||
// DeviceListCatchup fills in the given response for the given user ID to bring it up-to-date with device lists. hasNew=true if the response
|
// DeviceListCatchup fills in the given response for the given user ID to bring it up-to-date with device lists. hasNew=true if the response
|
||||||
// was filled in, else false if there are no new device list changes because there is nothing to catch up on. The response MUST
|
// was filled in, else false if there are no new device list changes because there is nothing to catch up on. The response MUST
|
||||||
// be already filled in with join/leave information.
|
// be already filled in with join/leave information.
|
||||||
// nolint:gocyclo
|
|
||||||
func DeviceListCatchup(
|
func DeviceListCatchup(
|
||||||
ctx context.Context, keyAPI keyapi.KeyInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
|
ctx context.Context, keyAPI keyapi.KeyInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
userID string, res *types.Response, from, to types.LogPosition,
|
userID string, res *types.Response, from, to types.LogPosition,
|
||||||
|
@ -137,7 +136,6 @@ func DeviceListCatchup(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackChangedUsers calculates the values of device_lists.changed|left in the /sync response.
|
// TrackChangedUsers calculates the values of device_lists.changed|left in the /sync response.
|
||||||
// nolint:gocyclo
|
|
||||||
func TrackChangedUsers(
|
func TrackChangedUsers(
|
||||||
ctx context.Context, rsAPI roomserverAPI.RoomserverInternalAPI, userID string, newlyJoinedRooms, newlyLeftRooms []string,
|
ctx context.Context, rsAPI roomserverAPI.RoomserverInternalAPI, userID string, newlyJoinedRooms, newlyLeftRooms []string,
|
||||||
) (changed, left []string, err error) {
|
) (changed, left []string, err error) {
|
||||||
|
|
|
@ -61,7 +61,6 @@ const defaultMessagesLimit = 10
|
||||||
// OnIncomingMessagesRequest implements the /messages endpoint from the
|
// OnIncomingMessagesRequest implements the /messages endpoint from the
|
||||||
// client-server API.
|
// client-server API.
|
||||||
// See: https://matrix.org/docs/spec/client_server/latest.html#get-matrix-client-r0-rooms-roomid-messages
|
// See: https://matrix.org/docs/spec/client_server/latest.html#get-matrix-client-r0-rooms-roomid-messages
|
||||||
// nolint:gocyclo
|
|
||||||
func OnIncomingMessagesRequest(
|
func OnIncomingMessagesRequest(
|
||||||
req *http.Request, db storage.Database, roomID string, device *userapi.Device,
|
req *http.Request, db storage.Database, roomID string, device *userapi.Device,
|
||||||
federation *gomatrixserverlib.FederationClient,
|
federation *gomatrixserverlib.FederationClient,
|
||||||
|
@ -306,7 +305,6 @@ func (r *messagesReq) retrieveEvents() (
|
||||||
return clientEvents, start, end, err
|
return clientEvents, start, end, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (r *messagesReq) filterHistoryVisible(events []*gomatrixserverlib.HeaderedEvent) []*gomatrixserverlib.HeaderedEvent {
|
func (r *messagesReq) filterHistoryVisible(events []*gomatrixserverlib.HeaderedEvent) []*gomatrixserverlib.HeaderedEvent {
|
||||||
// TODO FIXME: We don't fully implement history visibility yet. To avoid leaking events which the
|
// TODO FIXME: We don't fully implement history visibility yet. To avoid leaking events which the
|
||||||
// user shouldn't see, we check the recent events and remove any prior to the join event of the user
|
// user shouldn't see, we check the recent events and remove any prior to the join event of the user
|
||||||
|
|
|
@ -36,7 +36,6 @@ type SyncServerDatasource struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a new sync server database
|
// NewDatabase creates a new sync server database
|
||||||
// nolint:gocyclo
|
|
||||||
func NewDatabase(dbProperties *config.DatabaseOptions) (*SyncServerDatasource, error) {
|
func NewDatabase(dbProperties *config.DatabaseOptions) (*SyncServerDatasource, error) {
|
||||||
var d SyncServerDatasource
|
var d SyncServerDatasource
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -661,7 +661,6 @@ func (d *Database) fetchMissingStateEvents(
|
||||||
// exclusive of oldPos, inclusive of newPos, for the rooms in which
|
// exclusive of oldPos, inclusive of newPos, for the rooms in which
|
||||||
// the user has new membership events.
|
// the user has new membership events.
|
||||||
// A list of joined room IDs is also returned in case the caller needs it.
|
// A list of joined room IDs is also returned in case the caller needs it.
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) GetStateDeltas(
|
func (d *Database) GetStateDeltas(
|
||||||
ctx context.Context, device *userapi.Device,
|
ctx context.Context, device *userapi.Device,
|
||||||
r types.Range, userID string,
|
r types.Range, userID string,
|
||||||
|
@ -773,7 +772,6 @@ func (d *Database) GetStateDeltas(
|
||||||
// requests with full_state=true.
|
// requests with full_state=true.
|
||||||
// Fetches full state for all joined rooms and uses selectStateInRange to get
|
// Fetches full state for all joined rooms and uses selectStateInRange to get
|
||||||
// updates for other rooms.
|
// updates for other rooms.
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *Database) GetStateDeltasForFullStateSync(
|
func (d *Database) GetStateDeltasForFullStateSync(
|
||||||
ctx context.Context, device *userapi.Device,
|
ctx context.Context, device *userapi.Device,
|
||||||
r types.Range, userID string,
|
r types.Range, userID string,
|
||||||
|
|
|
@ -23,7 +23,6 @@ const (
|
||||||
// fields might come from either a StateFilter or an EventFilter,
|
// fields might come from either a StateFilter or an EventFilter,
|
||||||
// and it's easier just to have the caller extract the relevant
|
// and it's easier just to have the caller extract the relevant
|
||||||
// parts.
|
// parts.
|
||||||
// nolint:gocyclo
|
|
||||||
func prepareWithFilters(
|
func prepareWithFilters(
|
||||||
db *sql.DB, txn *sql.Tx, query string, params []interface{},
|
db *sql.DB, txn *sql.Tx, query string, params []interface{},
|
||||||
senders, notsenders, types, nottypes []string, excludeEventIDs []string,
|
senders, notsenders, types, nottypes []string, excludeEventIDs []string,
|
||||||
|
|
|
@ -52,7 +52,6 @@ func NewDatabase(dbProperties *config.DatabaseOptions) (*SyncServerDatasource, e
|
||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (d *SyncServerDatasource) prepare(dbProperties *config.DatabaseOptions) (err error) {
|
func (d *SyncServerDatasource) prepare(dbProperties *config.DatabaseOptions) (err error) {
|
||||||
if err = d.PartitionOffsetStatements.Prepare(d.db, d.writer, "syncapi"); err != nil {
|
if err = d.PartitionOffsetStatements.Prepare(d.db, d.writer, "syncapi"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -137,7 +137,6 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (p *PDUStreamProvider) IncrementalSync(
|
func (p *PDUStreamProvider) IncrementalSync(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *types.SyncRequest,
|
req *types.SyncRequest,
|
||||||
|
@ -254,7 +253,6 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
|
||||||
func (p *PDUStreamProvider) getJoinResponseForCompleteSync(
|
func (p *PDUStreamProvider) getJoinResponseForCompleteSync(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
roomID string,
|
roomID string,
|
||||||
|
|
|
@ -510,3 +510,10 @@ Can pass a JSON filter as a query parameter
|
||||||
Local room members can get room messages
|
Local room members can get room messages
|
||||||
Remote room members can get room messages
|
Remote room members can get room messages
|
||||||
Guest users can send messages to guest_access rooms if joined
|
Guest users can send messages to guest_access rooms if joined
|
||||||
|
AS can create a user
|
||||||
|
AS can create a user with an underscore
|
||||||
|
AS can create a user with inhibit_login
|
||||||
|
AS can set avatar for ghosted users
|
||||||
|
AS can set displayname for ghosted users
|
||||||
|
Ghost user must register before joining room
|
||||||
|
Inviting an AS-hosted user asks the AS server
|
||||||
|
|
|
@ -241,6 +241,9 @@ type Device struct {
|
||||||
LastSeenTS int64
|
LastSeenTS int64
|
||||||
LastSeenIP string
|
LastSeenIP string
|
||||||
UserAgent string
|
UserAgent string
|
||||||
|
// If the device is for an appservice user,
|
||||||
|
// this is the appservice ID.
|
||||||
|
AppserviceID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account represents a Matrix account on this home server.
|
// Account represents a Matrix account on this home server.
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (a *UserInternalAPI) PerformAccountCreation(ctx context.Context, req *api.P
|
||||||
ServerName: a.ServerName,
|
ServerName: a.ServerName,
|
||||||
UserID: fmt.Sprintf("@%s:%s", req.Localpart, a.ServerName),
|
UserID: fmt.Sprintf("@%s:%s", req.Localpart, a.ServerName),
|
||||||
}
|
}
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = a.AccountDB.SetDisplayName(ctx, req.Localpart, req.Localpart); err != nil {
|
if err = a.AccountDB.SetDisplayName(ctx, req.Localpart, req.Localpart); err != nil {
|
||||||
|
@ -382,6 +382,7 @@ func (a *UserInternalAPI) queryAppServiceToken(ctx context.Context, token, appSe
|
||||||
ID: types.AppServiceDeviceID,
|
ID: types.AppServiceDeviceID,
|
||||||
// AS dummy device has AS's token.
|
// AS dummy device has AS's token.
|
||||||
AccessToken: token,
|
AccessToken: token,
|
||||||
|
AppserviceID: appService.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
localpart, err := userutil.ParseUsernameParam(appServiceUserID, &a.ServerName)
|
localpart, err := userutil.ParseUsernameParam(appServiceUserID, &a.ServerName)
|
||||||
|
|
|
@ -44,10 +44,11 @@ type Database struct {
|
||||||
accountDatas accountDataStatements
|
accountDatas accountDataStatements
|
||||||
threepids threepidStatements
|
threepids threepidStatements
|
||||||
serverName gomatrixserverlib.ServerName
|
serverName gomatrixserverlib.ServerName
|
||||||
|
bcryptCost int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a new accounts and profiles database
|
// NewDatabase creates a new accounts and profiles database
|
||||||
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int) (*Database, error) {
|
||||||
db, err := sqlutil.Open(dbProperties)
|
db, err := sqlutil.Open(dbProperties)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -56,6 +57,7 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver
|
||||||
serverName: serverName,
|
serverName: serverName,
|
||||||
db: db,
|
db: db,
|
||||||
writer: sqlutil.NewDummyWriter(),
|
writer: sqlutil.NewDummyWriter(),
|
||||||
|
bcryptCost: bcryptCost,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create tables before executing migrations so we don't fail if the table is missing,
|
// Create tables before executing migrations so we don't fail if the table is missing,
|
||||||
|
@ -131,7 +133,7 @@ func (d *Database) SetDisplayName(
|
||||||
func (d *Database) SetPassword(
|
func (d *Database) SetPassword(
|
||||||
ctx context.Context, localpart, plaintextPassword string,
|
ctx context.Context, localpart, plaintextPassword string,
|
||||||
) error {
|
) error {
|
||||||
hash, err := hashPassword(plaintextPassword)
|
hash, err := d.hashPassword(plaintextPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -175,7 +177,7 @@ func (d *Database) createAccount(
|
||||||
// Generate a password hash if this is not a password-less user
|
// Generate a password hash if this is not a password-less user
|
||||||
hash := ""
|
hash := ""
|
||||||
if plaintextPassword != "" {
|
if plaintextPassword != "" {
|
||||||
hash, err = hashPassword(plaintextPassword)
|
hash, err = d.hashPassword(plaintextPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -246,8 +248,8 @@ func (d *Database) GetNewNumericLocalpart(
|
||||||
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashPassword(plaintext string) (hash string, err error) {
|
func (d *Database) hashPassword(plaintext string) (hash string, err error) {
|
||||||
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
|
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), d.bcryptCost)
|
||||||
return string(hashBytes), err
|
return string(hashBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ type Database struct {
|
||||||
accountDatas accountDataStatements
|
accountDatas accountDataStatements
|
||||||
threepids threepidStatements
|
threepids threepidStatements
|
||||||
serverName gomatrixserverlib.ServerName
|
serverName gomatrixserverlib.ServerName
|
||||||
|
bcryptCost int
|
||||||
|
|
||||||
accountsMu sync.Mutex
|
accountsMu sync.Mutex
|
||||||
profilesMu sync.Mutex
|
profilesMu sync.Mutex
|
||||||
|
@ -50,7 +51,7 @@ type Database struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a new accounts and profiles database
|
// NewDatabase creates a new accounts and profiles database
|
||||||
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int) (*Database, error) {
|
||||||
db, err := sqlutil.Open(dbProperties)
|
db, err := sqlutil.Open(dbProperties)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -59,6 +60,7 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver
|
||||||
serverName: serverName,
|
serverName: serverName,
|
||||||
db: db,
|
db: db,
|
||||||
writer: sqlutil.NewExclusiveWriter(),
|
writer: sqlutil.NewExclusiveWriter(),
|
||||||
|
bcryptCost: bcryptCost,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create tables before executing migrations so we don't fail if the table is missing,
|
// Create tables before executing migrations so we don't fail if the table is missing,
|
||||||
|
@ -143,7 +145,7 @@ func (d *Database) SetDisplayName(
|
||||||
func (d *Database) SetPassword(
|
func (d *Database) SetPassword(
|
||||||
ctx context.Context, localpart, plaintextPassword string,
|
ctx context.Context, localpart, plaintextPassword string,
|
||||||
) error {
|
) error {
|
||||||
hash, err := hashPassword(plaintextPassword)
|
hash, err := d.hashPassword(plaintextPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -208,7 +210,7 @@ func (d *Database) createAccount(
|
||||||
// Generate a password hash if this is not a password-less user
|
// Generate a password hash if this is not a password-less user
|
||||||
hash := ""
|
hash := ""
|
||||||
if plaintextPassword != "" {
|
if plaintextPassword != "" {
|
||||||
hash, err = hashPassword(plaintextPassword)
|
hash, err = d.hashPassword(plaintextPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -278,8 +280,8 @@ func (d *Database) GetNewNumericLocalpart(
|
||||||
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
return d.accounts.selectNewNumericLocalpart(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashPassword(plaintext string) (hash string, err error) {
|
func (d *Database) hashPassword(plaintext string) (hash string, err error) {
|
||||||
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
|
hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), d.bcryptCost)
|
||||||
return string(hashBytes), err
|
return string(hashBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@ import (
|
||||||
|
|
||||||
// NewDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme)
|
// NewDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme)
|
||||||
// and sets postgres connection parameters
|
// and sets postgres connection parameters
|
||||||
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName) (Database, error) {
|
func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int) (Database, error) {
|
||||||
switch {
|
switch {
|
||||||
case dbProperties.ConnectionString.IsSQLite():
|
case dbProperties.ConnectionString.IsSQLite():
|
||||||
return sqlite3.NewDatabase(dbProperties, serverName)
|
return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost)
|
||||||
case dbProperties.ConnectionString.IsPostgres():
|
case dbProperties.ConnectionString.IsPostgres():
|
||||||
return postgres.NewDatabase(dbProperties, serverName)
|
return postgres.NewDatabase(dbProperties, serverName, bcryptCost)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected database type")
|
return nil, fmt.Errorf("unexpected database type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,11 @@ import (
|
||||||
func NewDatabase(
|
func NewDatabase(
|
||||||
dbProperties *config.DatabaseOptions,
|
dbProperties *config.DatabaseOptions,
|
||||||
serverName gomatrixserverlib.ServerName,
|
serverName gomatrixserverlib.ServerName,
|
||||||
|
bcryptCost int,
|
||||||
) (Database, error) {
|
) (Database, error) {
|
||||||
switch {
|
switch {
|
||||||
case dbProperties.ConnectionString.IsSQLite():
|
case dbProperties.ConnectionString.IsSQLite():
|
||||||
return sqlite3.NewDatabase(dbProperties, serverName)
|
return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost)
|
||||||
case dbProperties.ConnectionString.IsPostgres():
|
case dbProperties.ConnectionString.IsPostgres():
|
||||||
return nil, fmt.Errorf("can't use Postgres implementation")
|
return nil, fmt.Errorf("can't use Postgres implementation")
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -37,7 +37,6 @@ func AddInternalRoutes(router *mux.Router, intAPI api.UserInternalAPI) {
|
||||||
func NewInternalAPI(
|
func NewInternalAPI(
|
||||||
accountDB accounts.Database, cfg *config.UserAPI, appServices []config.ApplicationService, keyAPI keyapi.KeyInternalAPI,
|
accountDB accounts.Database, cfg *config.UserAPI, appServices []config.ApplicationService, keyAPI keyapi.KeyInternalAPI,
|
||||||
) api.UserInternalAPI {
|
) api.UserInternalAPI {
|
||||||
|
|
||||||
deviceDB, err := devices.NewDatabase(&cfg.DeviceDatabase, cfg.Matrix.ServerName)
|
deviceDB, err := devices.NewDatabase(&cfg.DeviceDatabase, cfg.Matrix.ServerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Panicf("failed to connect to device db")
|
logrus.WithError(err).Panicf("failed to connect to device db")
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/userapi/inthttp"
|
"github.com/matrix-org/dendrite/userapi/inthttp"
|
||||||
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -25,7 +26,7 @@ const (
|
||||||
func MustMakeInternalAPI(t *testing.T) (api.UserInternalAPI, accounts.Database) {
|
func MustMakeInternalAPI(t *testing.T) (api.UserInternalAPI, accounts.Database) {
|
||||||
accountDB, err := accounts.NewDatabase(&config.DatabaseOptions{
|
accountDB, err := accounts.NewDatabase(&config.DatabaseOptions{
|
||||||
ConnectionString: "file::memory:",
|
ConnectionString: "file::memory:",
|
||||||
}, serverName)
|
}, serverName, bcrypt.MinCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create account DB: %s", err)
|
t.Fatalf("failed to create account DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue