Initial pass at refactoring config (not finished)

This commit is contained in:
Neil Alexander 2020-07-28 17:43:32 +01:00
parent acc8e80a51
commit d8eb0e1b4f
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
92 changed files with 1066 additions and 710 deletions

View file

@ -48,7 +48,7 @@ func NewInternalAPI(
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
) appserviceAPI.AppServiceQueryAPI { ) appserviceAPI.AppServiceQueryAPI {
// Create a connection to the appservice postgres DB // Create a connection to the appservice postgres DB
appserviceDB, err := storage.NewDatabase(string(base.Cfg.Database.AppService), base.Cfg.DbProperties()) appserviceDB, err := storage.NewDatabase(string(base.Cfg.AppServiceAPI.Database), base.Cfg.AppServiceAPI.DatabaseOptions)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to appservice db") logrus.WithError(err).Panicf("failed to connect to appservice db")
} }

View file

@ -48,7 +48,7 @@ func NewOutputRoomEventConsumer(
workerStates []types.ApplicationServiceWorkerState, workerStates []types.ApplicationServiceWorkerState,
) *OutputRoomEventConsumer { ) *OutputRoomEventConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputRoomEvent), Topic: string(cfg.Global.Kafka.Topics.OutputRoomEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: appserviceDB, PartitionStore: appserviceDB,
} }
@ -56,7 +56,7 @@ func NewOutputRoomEventConsumer(
roomServerConsumer: &consumer, roomServerConsumer: &consumer,
asDB: appserviceDB, asDB: appserviceDB,
rsAPI: rsAPI, rsAPI: rsAPI,
serverName: string(cfg.Matrix.ServerName), serverName: string(cfg.Global.ServerName),
workerStates: workerStates, workerStates: workerStates,
} }
consumer.ProcessMessage = s.onMessage consumer.ProcessMessage = s.onMessage

View file

@ -35,7 +35,7 @@ type PasswordRequest struct {
// LoginTypePassword implements https://matrix.org/docs/spec/client_server/r0.6.1#password-based // LoginTypePassword implements https://matrix.org/docs/spec/client_server/r0.6.1#password-based
type LoginTypePassword struct { type LoginTypePassword struct {
GetAccountByPassword GetAccountByPassword GetAccountByPassword GetAccountByPassword
Config *config.Dendrite Config *config.ClientAPI
} }
func (t *LoginTypePassword) Name() string { func (t *LoginTypePassword) Name() string {

View file

@ -33,8 +33,11 @@ func getAccountByPassword(ctx context.Context, localpart, plaintextPassword stri
} }
func setup() *UserInteractive { func setup() *UserInteractive {
cfg := &config.Dendrite{} cfg := &config.ClientAPI{
cfg.Matrix.ServerName = serverName Matrix: &config.Global{
ServerName: serverName,
},
}
return NewUserInteractive(getAccountByPassword, cfg) return NewUserInteractive(getAccountByPassword, cfg)
} }

View file

@ -37,7 +37,7 @@ import (
// AddPublicRoutes sets up and registers HTTP handlers for the ClientAPI component. // AddPublicRoutes sets up and registers HTTP handlers for the ClientAPI component.
func AddPublicRoutes( func AddPublicRoutes(
router *mux.Router, router *mux.Router,
cfg *config.Dendrite, cfg *config.ClientAPI,
producer sarama.SyncProducer, producer sarama.SyncProducer,
deviceDB devices.Database, deviceDB devices.Database,
accountsDB accounts.Database, accountsDB accounts.Database,
@ -54,7 +54,7 @@ func AddPublicRoutes(
) { ) {
syncProducer := &producers.SyncAPIProducer{ syncProducer := &producers.SyncAPIProducer{
Producer: producer, Producer: producer,
Topic: string(cfg.Kafka.Topics.OutputClientData), Topic: string(cfg.Matrix.Kafka.Topics.OutputClientData),
} }
routing.Setup( routing.Setup(

View file

@ -101,7 +101,7 @@ func serveTemplate(w http.ResponseWriter, templateHTML string, data map[string]s
// AuthFallback implements GET and POST /auth/{authType}/fallback/web?session={sessionID} // AuthFallback implements GET and POST /auth/{authType}/fallback/web?session={sessionID}
func AuthFallback( func AuthFallback(
w http.ResponseWriter, req *http.Request, authType string, w http.ResponseWriter, req *http.Request, authType string,
cfg *config.Dendrite, cfg *config.ClientAPI,
) *util.JSONResponse { ) *util.JSONResponse {
sessionID := req.URL.Query().Get("session") sessionID := req.URL.Query().Get("session")
@ -116,7 +116,7 @@ func AuthFallback(
data := map[string]string{ data := map[string]string{
"myUrl": req.URL.String(), "myUrl": req.URL.String(),
"session": sessionID, "session": sessionID,
"siteKey": cfg.Matrix.RecaptchaPublicKey, "siteKey": cfg.RecaptchaPublicKey,
} }
serveTemplate(w, recaptchaTemplate, data) serveTemplate(w, recaptchaTemplate, data)
} }
@ -181,11 +181,11 @@ func AuthFallback(
// checkRecaptchaEnabled creates an error response if recaptcha is not usable on homeserver. // checkRecaptchaEnabled creates an error response if recaptcha is not usable on homeserver.
func checkRecaptchaEnabled( func checkRecaptchaEnabled(
cfg *config.Dendrite, cfg *config.ClientAPI,
w http.ResponseWriter, w http.ResponseWriter,
req *http.Request, req *http.Request,
) *util.JSONResponse { ) *util.JSONResponse {
if !cfg.Matrix.RecaptchaEnabled { if !cfg.RecaptchaEnabled {
return writeHTTPMessage(w, req, return writeHTTPMessage(w, req,
"Recaptcha login is disabled on this Homeserver", "Recaptcha login is disabled on this Homeserver",
http.StatusBadRequest, http.StatusBadRequest,

View file

@ -135,7 +135,7 @@ type fledglingEvent struct {
// CreateRoom implements /createRoom // CreateRoom implements /createRoom
func CreateRoom( func CreateRoom(
req *http.Request, device *api.Device, req *http.Request, device *api.Device,
cfg *config.Dendrite, cfg *config.ClientAPI,
accountDB accounts.Database, rsAPI roomserverAPI.RoomserverInternalAPI, accountDB accounts.Database, rsAPI roomserverAPI.RoomserverInternalAPI,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -149,7 +149,7 @@ func CreateRoom(
// nolint: gocyclo // nolint: gocyclo
func createRoom( func createRoom(
req *http.Request, device *api.Device, req *http.Request, device *api.Device,
cfg *config.Dendrite, roomID string, cfg *config.ClientAPI, roomID string,
accountDB accounts.Database, rsAPI roomserverAPI.RoomserverInternalAPI, accountDB accounts.Database, rsAPI roomserverAPI.RoomserverInternalAPI,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -438,7 +438,7 @@ func createRoom(
func buildEvent( func buildEvent(
builder *gomatrixserverlib.EventBuilder, builder *gomatrixserverlib.EventBuilder,
provider gomatrixserverlib.AuthEventProvider, provider gomatrixserverlib.AuthEventProvider,
cfg *config.Dendrite, cfg *config.ClientAPI,
evTime time.Time, evTime time.Time,
roomVersion gomatrixserverlib.RoomVersion, roomVersion gomatrixserverlib.RoomVersion,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {

View file

@ -47,7 +47,7 @@ func DirectoryRoom(
req *http.Request, req *http.Request,
roomAlias string, roomAlias string,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
cfg *config.Dendrite, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
fedSenderAPI federationSenderAPI.FederationSenderInternalAPI, fedSenderAPI federationSenderAPI.FederationSenderInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -116,7 +116,7 @@ func SetLocalAlias(
req *http.Request, req *http.Request,
device *api.Device, device *api.Device,
alias string, alias string,
cfg *config.Dendrite, cfg *config.ClientAPI,
aliasAPI roomserverAPI.RoomserverInternalAPI, aliasAPI roomserverAPI.RoomserverInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
_, domain, err := gomatrixserverlib.SplitID('#', alias) _, domain, err := gomatrixserverlib.SplitID('#', alias)
@ -139,22 +139,26 @@ func SetLocalAlias(
// TODO: This code should eventually be refactored with: // TODO: This code should eventually be refactored with:
// 1. The new method for checking for things matching an AS's namespace // 1. The new method for checking for things matching an AS's namespace
// 2. Using an overall Regex object for all AS's just like we did for usernames // 2. Using an overall Regex object for all AS's just like we did for usernames
for _, appservice := range cfg.Derived.ApplicationServices {
// Don't prevent AS from creating aliases in its own namespace // TODO: What to do with derived?
// Note that Dendrite uses SenderLocalpart as UserID for AS users /*
if device.UserID != appservice.SenderLocalpart { for _, appservice := range cfg.Derived.ApplicationServices {
if aliasNamespaces, ok := appservice.NamespaceMap["aliases"]; ok { // Don't prevent AS from creating aliases in its own namespace
for _, namespace := range aliasNamespaces { // Note that Dendrite uses SenderLocalpart as UserID for AS users
if namespace.Exclusive && namespace.RegexpObject.MatchString(alias) { if device.UserID != appservice.SenderLocalpart {
return util.JSONResponse{ if aliasNamespaces, ok := appservice.NamespaceMap["aliases"]; ok {
Code: http.StatusBadRequest, for _, namespace := range aliasNamespaces {
JSON: jsonerror.ASExclusive("Alias is reserved by an application service"), if namespace.Exclusive && namespace.RegexpObject.MatchString(alias) {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.ASExclusive("Alias is reserved by an application service"),
}
} }
} }
} }
} }
} }
} */
var r struct { var r struct {
RoomID string `json:"room_id"` RoomID string `json:"room_id"`

View file

@ -30,7 +30,7 @@ type getEventRequest struct {
device *userapi.Device device *userapi.Device
roomID string roomID string
eventID string eventID string
cfg *config.Dendrite cfg *config.ClientAPI
federation *gomatrixserverlib.FederationClient federation *gomatrixserverlib.FederationClient
requestedEvent gomatrixserverlib.Event requestedEvent gomatrixserverlib.Event
} }
@ -42,7 +42,7 @@ func GetEvent(
device *userapi.Device, device *userapi.Device,
roomID string, roomID string,
eventID string, eventID string,
cfg *config.Dendrite, cfg *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
) util.JSONResponse { ) util.JSONResponse {

View file

@ -58,7 +58,7 @@ func passwordLogin() flows {
// Login implements GET and POST /login // Login implements GET and POST /login
func Login( func Login(
req *http.Request, accountDB accounts.Database, deviceDB devices.Database, req *http.Request, accountDB accounts.Database, deviceDB devices.Database,
cfg *config.Dendrite, cfg *config.ClientAPI,
) util.JSONResponse { ) util.JSONResponse {
if req.Method == http.MethodGet { if req.Method == http.MethodGet {
// TODO: support other forms of login other than password, depending on config options // TODO: support other forms of login other than password, depending on config options

View file

@ -41,7 +41,7 @@ var errMissingUserID = errors.New("'user_id' must be supplied")
func SendBan( func SendBan(
req *http.Request, accountDB accounts.Database, device *userapi.Device, req *http.Request, accountDB accounts.Database, device *userapi.Device,
roomID string, cfg *config.Dendrite, roomID string, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse { ) util.JSONResponse {
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI) body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
@ -52,7 +52,7 @@ func SendBan(
} }
func sendMembership(ctx context.Context, accountDB accounts.Database, device *userapi.Device, func sendMembership(ctx context.Context, accountDB accounts.Database, device *userapi.Device,
roomID, membership, reason string, cfg *config.Dendrite, targetUserID string, evTime time.Time, roomID, membership, reason string, cfg *config.ClientAPI, targetUserID string, evTime time.Time,
roomVer gomatrixserverlib.RoomVersion, roomVer gomatrixserverlib.RoomVersion,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI) util.JSONResponse { rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI) util.JSONResponse {
@ -94,7 +94,7 @@ func sendMembership(ctx context.Context, accountDB accounts.Database, device *us
func SendKick( func SendKick(
req *http.Request, accountDB accounts.Database, device *userapi.Device, req *http.Request, accountDB accounts.Database, device *userapi.Device,
roomID string, cfg *config.Dendrite, roomID string, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI,
stateAPI currentstateAPI.CurrentStateInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -135,7 +135,7 @@ func SendKick(
func SendUnban( func SendUnban(
req *http.Request, accountDB accounts.Database, device *userapi.Device, req *http.Request, accountDB accounts.Database, device *userapi.Device,
roomID string, cfg *config.Dendrite, roomID string, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse { ) util.JSONResponse {
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI) body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
@ -170,7 +170,7 @@ func SendUnban(
func SendInvite( func SendInvite(
req *http.Request, accountDB accounts.Database, device *userapi.Device, req *http.Request, accountDB accounts.Database, device *userapi.Device,
roomID string, cfg *config.Dendrite, roomID string, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse { ) util.JSONResponse {
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI) body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
@ -236,7 +236,7 @@ func buildMembershipEvent(
targetUserID, reason string, accountDB accounts.Database, targetUserID, reason string, accountDB accounts.Database,
device *userapi.Device, device *userapi.Device,
membership, roomID string, isDirect bool, membership, roomID string, isDirect bool,
cfg *config.Dendrite, evTime time.Time, cfg *config.ClientAPI, evTime time.Time,
rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) (*gomatrixserverlib.HeaderedEvent, error) { ) (*gomatrixserverlib.HeaderedEvent, error) {
profile, err := loadProfile(ctx, targetUserID, cfg, accountDB, asAPI) profile, err := loadProfile(ctx, targetUserID, cfg, accountDB, asAPI)
@ -263,7 +263,7 @@ func buildMembershipEvent(
return nil, err return nil, err
} }
return eventutil.BuildEvent(ctx, &builder, cfg, evTime, rsAPI, nil) return eventutil.BuildEvent(ctx, &builder, cfg.Matrix, evTime, rsAPI, nil)
} }
// loadProfile lookups the profile of a given user from the database and returns // loadProfile lookups the profile of a given user from the database and returns
@ -273,7 +273,7 @@ func buildMembershipEvent(
func loadProfile( func loadProfile(
ctx context.Context, ctx context.Context,
userID string, userID string,
cfg *config.Dendrite, cfg *config.ClientAPI,
accountDB accounts.Database, accountDB accounts.Database,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
) (*authtypes.Profile, error) { ) (*authtypes.Profile, error) {
@ -326,7 +326,7 @@ func checkAndProcessThreepid(
req *http.Request, req *http.Request,
device *userapi.Device, device *userapi.Device,
body *threepid.MembershipRequest, body *threepid.MembershipRequest,
cfg *config.Dendrite, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
accountDB accounts.Database, accountDB accounts.Database,
roomID string, roomID string,

View file

@ -48,7 +48,7 @@ type joinedMember struct {
// GetMemberships implements GET /rooms/{roomId}/members // GetMemberships implements GET /rooms/{roomId}/members
func GetMemberships( func GetMemberships(
req *http.Request, device *userapi.Device, roomID string, joinedOnly bool, req *http.Request, device *userapi.Device, roomID string, joinedOnly bool,
_ *config.Dendrite, _ *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
queryReq := api.QueryMembershipsForRoomRequest{ queryReq := api.QueryMembershipsForRoomRequest{

View file

@ -37,7 +37,7 @@ import (
// GetProfile implements GET /profile/{userID} // GetProfile implements GET /profile/{userID}
func GetProfile( func GetProfile(
req *http.Request, accountDB accounts.Database, cfg *config.Dendrite, req *http.Request, accountDB accounts.Database, cfg *config.ClientAPI,
userID string, userID string,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
@ -66,7 +66,7 @@ func GetProfile(
// GetAvatarURL implements GET /profile/{userID}/avatar_url // GetAvatarURL implements GET /profile/{userID}/avatar_url
func GetAvatarURL( func GetAvatarURL(
req *http.Request, accountDB accounts.Database, cfg *config.Dendrite, req *http.Request, accountDB accounts.Database, cfg *config.ClientAPI,
userID string, asAPI appserviceAPI.AppServiceQueryAPI, userID string, asAPI appserviceAPI.AppServiceQueryAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
) util.JSONResponse { ) util.JSONResponse {
@ -95,7 +95,7 @@ func GetAvatarURL(
// nolint:gocyclo // nolint:gocyclo
func SetAvatarURL( func SetAvatarURL(
req *http.Request, accountDB accounts.Database, stateAPI currentstateAPI.CurrentStateInternalAPI, req *http.Request, accountDB accounts.Database, stateAPI currentstateAPI.CurrentStateInternalAPI,
device *userapi.Device, userID string, cfg *config.Dendrite, rsAPI api.RoomserverInternalAPI, device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
if userID != device.UserID { if userID != device.UserID {
return util.JSONResponse{ return util.JSONResponse{
@ -184,7 +184,7 @@ func SetAvatarURL(
// GetDisplayName implements GET /profile/{userID}/displayname // GetDisplayName implements GET /profile/{userID}/displayname
func GetDisplayName( func GetDisplayName(
req *http.Request, accountDB accounts.Database, cfg *config.Dendrite, req *http.Request, accountDB accounts.Database, cfg *config.ClientAPI,
userID string, asAPI appserviceAPI.AppServiceQueryAPI, userID string, asAPI appserviceAPI.AppServiceQueryAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
) util.JSONResponse { ) util.JSONResponse {
@ -213,7 +213,7 @@ func GetDisplayName(
// nolint:gocyclo // nolint:gocyclo
func SetDisplayName( func SetDisplayName(
req *http.Request, accountDB accounts.Database, stateAPI currentstateAPI.CurrentStateInternalAPI, req *http.Request, accountDB accounts.Database, stateAPI currentstateAPI.CurrentStateInternalAPI,
device *userapi.Device, userID string, cfg *config.Dendrite, rsAPI api.RoomserverInternalAPI, device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.RoomserverInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
if userID != device.UserID { if userID != device.UserID {
return util.JSONResponse{ return util.JSONResponse{
@ -305,7 +305,7 @@ func SetDisplayName(
// Returns an error when something goes wrong or specifically // Returns an error when something goes wrong or specifically
// eventutil.ErrProfileNoExists when the profile doesn't exist. // eventutil.ErrProfileNoExists when the profile doesn't exist.
func getProfile( func getProfile(
ctx context.Context, accountDB accounts.Database, cfg *config.Dendrite, ctx context.Context, accountDB accounts.Database, cfg *config.ClientAPI,
userID string, userID string,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
@ -345,7 +345,7 @@ func getProfile(
func buildMembershipEvents( func buildMembershipEvents(
ctx context.Context, ctx context.Context,
roomIDs []string, roomIDs []string,
newProfile authtypes.Profile, userID string, cfg *config.Dendrite, newProfile authtypes.Profile, userID string, cfg *config.ClientAPI,
evTime time.Time, rsAPI api.RoomserverInternalAPI, evTime time.Time, rsAPI api.RoomserverInternalAPI,
) ([]gomatrixserverlib.HeaderedEvent, error) { ) ([]gomatrixserverlib.HeaderedEvent, error) {
evs := []gomatrixserverlib.HeaderedEvent{} evs := []gomatrixserverlib.HeaderedEvent{}
@ -375,7 +375,7 @@ func buildMembershipEvents(
return nil, err return nil, err
} }
event, err := eventutil.BuildEvent(ctx, &builder, cfg, evTime, rsAPI, nil) event, err := eventutil.BuildEvent(ctx, &builder, cfg.Matrix, evTime, rsAPI, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -40,7 +40,7 @@ type redactionResponse struct {
} }
func SendRedaction( func SendRedaction(
req *http.Request, device *userapi.Device, roomID, eventID string, cfg *config.Dendrite, req *http.Request, device *userapi.Device, roomID, eventID string, cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
resErr := checkMemberInRoom(req.Context(), stateAPI, device.UserID, roomID) resErr := checkMemberInRoom(req.Context(), stateAPI, device.UserID, roomID)
@ -115,7 +115,7 @@ func SendRedaction(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
e, err := eventutil.BuildEvent(req.Context(), &builder, cfg, time.Now(), rsAPI, &queryRes) e, err := eventutil.BuildEvent(req.Context(), &builder, cfg.Matrix, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { if err == eventutil.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View file

@ -255,11 +255,11 @@ func validatePassword(password string) *util.JSONResponse {
// validateRecaptcha returns an error response if the captcha response is invalid // validateRecaptcha returns an error response if the captcha response is invalid
func validateRecaptcha( func validateRecaptcha(
cfg *config.Dendrite, cfg *config.ClientAPI,
response string, response string,
clientip string, clientip string,
) *util.JSONResponse { ) *util.JSONResponse {
if !cfg.Matrix.RecaptchaEnabled { if !cfg.RecaptchaEnabled {
return &util.JSONResponse{ return &util.JSONResponse{
Code: http.StatusConflict, Code: http.StatusConflict,
JSON: jsonerror.Unknown("Captcha registration is disabled"), JSON: jsonerror.Unknown("Captcha registration is disabled"),
@ -274,9 +274,9 @@ func validateRecaptcha(
} }
// Make a POST request to Google's API to check the captcha response // Make a POST request to Google's API to check the captcha response
resp, err := http.PostForm(cfg.Matrix.RecaptchaSiteVerifyAPI, resp, err := http.PostForm(cfg.RecaptchaSiteVerifyAPI,
url.Values{ url.Values{
"secret": {cfg.Matrix.RecaptchaPrivateKey}, "secret": {cfg.RecaptchaPrivateKey},
"response": {response}, "response": {response},
"remoteip": {clientip}, "remoteip": {clientip},
}, },
@ -324,7 +324,7 @@ func validateRecaptcha(
// Application Service is given, it will check to see if it matches any // Application Service is given, it will check to see if it matches any
// Application Service's namespace. // Application Service's namespace.
func UserIDIsWithinApplicationServiceNamespace( func UserIDIsWithinApplicationServiceNamespace(
cfg *config.Dendrite, cfg *config.ClientAPI,
userID string, userID string,
appservice *config.ApplicationService, appservice *config.ApplicationService,
) bool { ) bool {
@ -354,7 +354,7 @@ func UserIDIsWithinApplicationServiceNamespace(
// UsernameMatchesMultipleExclusiveNamespaces will check if a given username matches // UsernameMatchesMultipleExclusiveNamespaces will check if a given username matches
// more than one exclusive namespace. More than one is not allowed // more than one exclusive namespace. More than one is not allowed
func UsernameMatchesMultipleExclusiveNamespaces( func UsernameMatchesMultipleExclusiveNamespaces(
cfg *config.Dendrite, cfg *config.ClientAPI,
username string, username string,
) bool { ) bool {
userID := userutil.MakeUserID(username, cfg.Matrix.ServerName) userID := userutil.MakeUserID(username, cfg.Matrix.ServerName)
@ -374,7 +374,7 @@ func UsernameMatchesMultipleExclusiveNamespaces(
// UsernameMatchesExclusiveNamespaces will check if a given username matches any // UsernameMatchesExclusiveNamespaces will check if a given username matches any
// application service's exclusive users namespace // application service's exclusive users namespace
func UsernameMatchesExclusiveNamespaces( func UsernameMatchesExclusiveNamespaces(
cfg *config.Dendrite, cfg *config.ClientAPI,
username string, username string,
) bool { ) bool {
userID := userutil.MakeUserID(username, cfg.Matrix.ServerName) userID := userutil.MakeUserID(username, cfg.Matrix.ServerName)
@ -386,7 +386,7 @@ func UsernameMatchesExclusiveNamespaces(
// username is within that application service's namespace. As long as these // username is within that application service's namespace. As long as these
// two requirements are met, no error will be returned. // two requirements are met, no error will be returned.
func validateApplicationService( func validateApplicationService(
cfg *config.Dendrite, cfg *config.ClientAPI,
username string, username string,
accessToken string, accessToken string,
) (string, *util.JSONResponse) { ) (string, *util.JSONResponse) {
@ -442,7 +442,7 @@ func Register(
req *http.Request, req *http.Request,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
accountDB accounts.Database, accountDB accounts.Database,
cfg *config.Dendrite, cfg *config.ClientAPI,
) util.JSONResponse { ) util.JSONResponse {
var r registerRequest var r registerRequest
resErr := httputil.UnmarshalJSONRequest(req, &r) resErr := httputil.UnmarshalJSONRequest(req, &r)
@ -512,7 +512,7 @@ func Register(
func handleGuestRegistration( func handleGuestRegistration(
req *http.Request, req *http.Request,
r registerRequest, r registerRequest,
cfg *config.Dendrite, cfg *config.ClientAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
var res userapi.PerformAccountCreationResponse var res userapi.PerformAccountCreationResponse
@ -568,7 +568,7 @@ func handleRegistrationFlow(
req *http.Request, req *http.Request,
r registerRequest, r registerRequest,
sessionID string, sessionID string,
cfg *config.Dendrite, cfg *config.ClientAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
// TODO: Shared secret registration (create new user scripts) // TODO: Shared secret registration (create new user scripts)
@ -580,7 +580,7 @@ func handleRegistrationFlow(
// TODO: email / msisdn auth types. // TODO: email / msisdn auth types.
if cfg.Matrix.RegistrationDisabled && r.Auth.Type != authtypes.LoginTypeSharedSecret { if cfg.RegistrationDisabled && r.Auth.Type != authtypes.LoginTypeSharedSecret {
return util.MessageResponse(http.StatusForbidden, "Registration has been disabled") return util.MessageResponse(http.StatusForbidden, "Registration has been disabled")
} }
@ -666,7 +666,7 @@ func handleApplicationServiceRegistration(
tokenErr error, tokenErr error,
req *http.Request, req *http.Request,
r registerRequest, r registerRequest,
cfg *config.Dendrite, cfg *config.ClientAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
// Check if we previously had issues extracting the access token from the // Check if we previously had issues extracting the access token from the
@ -704,7 +704,7 @@ func checkAndCompleteFlow(
req *http.Request, req *http.Request,
r registerRequest, r registerRequest,
sessionID string, sessionID string,
cfg *config.Dendrite, cfg *config.ClientAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) { if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) {
@ -728,7 +728,7 @@ func checkAndCompleteFlow(
func LegacyRegister( func LegacyRegister(
req *http.Request, req *http.Request,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
cfg *config.Dendrite, cfg *config.ClientAPI,
) util.JSONResponse { ) util.JSONResponse {
var r legacyRegisterRequest var r legacyRegisterRequest
resErr := parseAndValidateLegacyLogin(req, &r) resErr := parseAndValidateLegacyLogin(req, &r)
@ -742,13 +742,13 @@ func LegacyRegister(
"auth.type": r.Type, "auth.type": r.Type,
}).Info("Processing registration request") }).Info("Processing registration request")
if cfg.Matrix.RegistrationDisabled && r.Type != authtypes.LoginTypeSharedSecret { if cfg.RegistrationDisabled && r.Type != authtypes.LoginTypeSharedSecret {
return util.MessageResponse(http.StatusForbidden, "Registration has been disabled") return util.MessageResponse(http.StatusForbidden, "Registration has been disabled")
} }
switch r.Type { switch r.Type {
case authtypes.LoginTypeSharedSecret: case authtypes.LoginTypeSharedSecret:
if cfg.Matrix.RegistrationSharedSecret == "" { if cfg.RegistrationSharedSecret == "" {
return util.MessageResponse(http.StatusBadRequest, "Shared secret registration is disabled") return util.MessageResponse(http.StatusBadRequest, "Shared secret registration is disabled")
} }
@ -902,15 +902,15 @@ func completeRegistration(
// Used for shared secret registration. // Used for shared secret registration.
// Checks if the username, password and isAdmin flag matches the given mac. // Checks if the username, password and isAdmin flag matches the given mac.
func isValidMacLogin( func isValidMacLogin(
cfg *config.Dendrite, cfg *config.ClientAPI,
username, password string, username, password string,
isAdmin bool, isAdmin bool,
givenMac []byte, givenMac []byte,
) (bool, error) { ) (bool, error) {
sharedSecret := cfg.Matrix.RegistrationSharedSecret sharedSecret := cfg.RegistrationSharedSecret
// Check that shared secret registration isn't disabled. // Check that shared secret registration isn't disabled.
if cfg.Matrix.RegistrationSharedSecret == "" { if cfg.RegistrationSharedSecret == "" {
return false, errors.New("Shared secret registration is disabled") return false, errors.New("Shared secret registration is disabled")
} }
@ -1001,7 +1001,7 @@ type availableResponse struct {
// RegisterAvailable checks if the username is already taken or invalid. // RegisterAvailable checks if the username is already taken or invalid.
func RegisterAvailable( func RegisterAvailable(
req *http.Request, req *http.Request,
cfg *config.Dendrite, cfg *config.ClientAPI,
accountDB accounts.Database, accountDB accounts.Database,
) util.JSONResponse { ) util.JSONResponse {
username := req.URL.Query().Get("username") username := req.URL.Query().Get("username")

View file

@ -179,7 +179,7 @@ func TestValidationOfApplicationServices(t *testing.T) {
} }
// Set up a config // Set up a config
fakeConfig := config.Dendrite{} fakeConfig := config.ClientAPI{}
fakeConfig.Matrix.ServerName = "localhost" fakeConfig.Matrix.ServerName = "localhost"
fakeConfig.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService} fakeConfig.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService}

View file

@ -51,7 +51,7 @@ const pathPrefixUnstable = "/client/unstable"
// applied: // applied:
// nolint: gocyclo // nolint: gocyclo
func Setup( func Setup(
publicAPIMux *mux.Router, cfg *config.Dendrite, publicAPIMux *mux.Router, cfg *config.ClientAPI,
eduAPI eduServerAPI.EDUServerInputAPI, eduAPI eduServerAPI.EDUServerInputAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
asAPI appserviceAPI.AppServiceQueryAPI, asAPI appserviceAPI.AppServiceQueryAPI,

View file

@ -43,7 +43,7 @@ func SendEvent(
req *http.Request, req *http.Request,
device *userapi.Device, device *userapi.Device,
roomID, eventType string, txnID, stateKey *string, roomID, eventType string, txnID, stateKey *string,
cfg *config.Dendrite, cfg *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
txnCache *transactions.Cache, txnCache *transactions.Cache,
) util.JSONResponse { ) util.JSONResponse {
@ -112,7 +112,7 @@ func generateSendEvent(
req *http.Request, req *http.Request,
device *userapi.Device, device *userapi.Device,
roomID, eventType string, stateKey *string, roomID, eventType string, stateKey *string,
cfg *config.Dendrite, cfg *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
) (*gomatrixserverlib.Event, *util.JSONResponse) { ) (*gomatrixserverlib.Event, *util.JSONResponse) {
// parse the incoming http request // parse the incoming http request
@ -146,7 +146,7 @@ func generateSendEvent(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
e, err := eventutil.BuildEvent(req.Context(), &builder, cfg, evTime, rsAPI, &queryRes) e, err := eventutil.BuildEvent(req.Context(), &builder, cfg.Matrix, evTime, rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { if err == eventutil.ErrRoomNoExists {
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View file

@ -40,7 +40,7 @@ type threePIDsResponse struct {
// RequestEmailToken implements: // RequestEmailToken implements:
// POST /account/3pid/email/requestToken // POST /account/3pid/email/requestToken
// POST /register/email/requestToken // POST /register/email/requestToken
func RequestEmailToken(req *http.Request, accountDB accounts.Database, cfg *config.Dendrite) util.JSONResponse { func RequestEmailToken(req *http.Request, accountDB accounts.Database, cfg *config.ClientAPI) util.JSONResponse {
var body threepid.EmailAssociationRequest var body threepid.EmailAssociationRequest
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil { if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
return *reqErr return *reqErr
@ -86,7 +86,7 @@ func RequestEmailToken(req *http.Request, accountDB accounts.Database, cfg *conf
// CheckAndSave3PIDAssociation implements POST /account/3pid // CheckAndSave3PIDAssociation implements POST /account/3pid
func CheckAndSave3PIDAssociation( func CheckAndSave3PIDAssociation(
req *http.Request, accountDB accounts.Database, device *api.Device, req *http.Request, accountDB accounts.Database, device *api.Device,
cfg *config.Dendrite, cfg *config.ClientAPI,
) util.JSONResponse { ) util.JSONResponse {
var body threepid.EmailAssociationCheckRequest var body threepid.EmailAssociationCheckRequest
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil { if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {

View file

@ -31,7 +31,7 @@ import (
// RequestTurnServer implements: // RequestTurnServer implements:
// GET /voip/turnServer // GET /voip/turnServer
func RequestTurnServer(req *http.Request, device *api.Device, cfg *config.Dendrite) util.JSONResponse { func RequestTurnServer(req *http.Request, device *api.Device, cfg *config.ClientAPI) util.JSONResponse {
turnConfig := cfg.TURN turnConfig := cfg.TURN
// TODO Guest Support // TODO Guest Support

View file

@ -86,7 +86,7 @@ var (
// can be emitted. // can be emitted.
func CheckAndProcessInvite( func CheckAndProcessInvite(
ctx context.Context, ctx context.Context,
device *userapi.Device, body *MembershipRequest, cfg *config.Dendrite, device *userapi.Device, body *MembershipRequest, cfg *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, db accounts.Database, rsAPI api.RoomserverInternalAPI, db accounts.Database,
roomID string, roomID string,
evTime time.Time, evTime time.Time,
@ -137,7 +137,7 @@ func CheckAndProcessInvite(
// Returns an error if a check or a request failed. // Returns an error if a check or a request failed.
func queryIDServer( func queryIDServer(
ctx context.Context, ctx context.Context,
db accounts.Database, cfg *config.Dendrite, device *userapi.Device, db accounts.Database, cfg *config.ClientAPI, device *userapi.Device,
body *MembershipRequest, roomID string, body *MembershipRequest, roomID string,
) (lookupRes *idServerLookupResponse, storeInviteRes *idServerStoreInviteResponse, err error) { ) (lookupRes *idServerLookupResponse, storeInviteRes *idServerStoreInviteResponse, err error) {
if err = isTrusted(body.IDServer, cfg); err != nil { if err = isTrusted(body.IDServer, cfg); err != nil {
@ -206,7 +206,7 @@ func queryIDServerLookup(ctx context.Context, body *MembershipRequest) (*idServe
// Returns an error if the request failed to send or if the response couldn't be parsed. // Returns an error if the request failed to send or if the response couldn't be parsed.
func queryIDServerStoreInvite( func queryIDServerStoreInvite(
ctx context.Context, ctx context.Context,
db accounts.Database, cfg *config.Dendrite, device *userapi.Device, db accounts.Database, cfg *config.ClientAPI, device *userapi.Device,
body *MembershipRequest, roomID string, body *MembershipRequest, roomID string,
) (*idServerStoreInviteResponse, error) { ) (*idServerStoreInviteResponse, error) {
// Retrieve the sender's profile to get their display name // Retrieve the sender's profile to get their display name
@ -330,7 +330,7 @@ func checkIDServerSignatures(
func emit3PIDInviteEvent( func emit3PIDInviteEvent(
ctx context.Context, ctx context.Context,
body *MembershipRequest, res *idServerStoreInviteResponse, body *MembershipRequest, res *idServerStoreInviteResponse,
device *userapi.Device, roomID string, cfg *config.Dendrite, device *userapi.Device, roomID string, cfg *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
evTime time.Time, evTime time.Time,
) error { ) error {
@ -354,7 +354,7 @@ func emit3PIDInviteEvent(
} }
queryRes := api.QueryLatestEventsAndStateResponse{} queryRes := api.QueryLatestEventsAndStateResponse{}
event, err := eventutil.BuildEvent(ctx, builder, cfg, evTime, rsAPI, &queryRes) event, err := eventutil.BuildEvent(ctx, builder, cfg.Matrix, evTime, rsAPI, &queryRes)
if err != nil { if err != nil {
return err return err
} }

View file

@ -53,7 +53,7 @@ type Credentials struct {
// Returns an error if there was a problem sending the request or decoding the // Returns an error if there was a problem sending the request or decoding the
// response, or if the identity server responded with a non-OK status. // response, or if the identity server responded with a non-OK status.
func CreateSession( func CreateSession(
ctx context.Context, req EmailAssociationRequest, cfg *config.Dendrite, ctx context.Context, req EmailAssociationRequest, cfg *config.ClientAPI,
) (string, error) { ) (string, error) {
if err := isTrusted(req.IDServer, cfg); err != nil { if err := isTrusted(req.IDServer, cfg); err != nil {
return "", err return "", err
@ -101,7 +101,7 @@ func CreateSession(
// Returns an error if there was a problem sending the request or decoding the // Returns an error if there was a problem sending the request or decoding the
// response, or if the identity server responded with a non-OK status. // response, or if the identity server responded with a non-OK status.
func CheckAssociation( func CheckAssociation(
ctx context.Context, creds Credentials, cfg *config.Dendrite, ctx context.Context, creds Credentials, cfg *config.ClientAPI,
) (bool, string, string, error) { ) (bool, string, string, error) {
if err := isTrusted(creds.IDServer, cfg); err != nil { if err := isTrusted(creds.IDServer, cfg); err != nil {
return false, "", "", err return false, "", "", err
@ -142,7 +142,7 @@ func CheckAssociation(
// identifier and a Matrix ID. // identifier and a Matrix ID.
// Returns an error if there was a problem sending the request or decoding the // Returns an error if there was a problem sending the request or decoding the
// response, or if the identity server responded with a non-OK status. // response, or if the identity server responded with a non-OK status.
func PublishAssociation(creds Credentials, userID string, cfg *config.Dendrite) error { func PublishAssociation(creds Credentials, userID string, cfg *config.ClientAPI) error {
if err := isTrusted(creds.IDServer, cfg); err != nil { if err := isTrusted(creds.IDServer, cfg); err != nil {
return err return err
} }
@ -177,7 +177,7 @@ func PublishAssociation(creds Credentials, userID string, cfg *config.Dendrite)
// isTrusted checks if a given identity server is part of the list of trusted // isTrusted checks if a given identity server is part of the list of trusted
// identity servers in the configuration file. // identity servers in the configuration file.
// Returns an error if the server isn't trusted. // Returns an error if the server isn't trusted.
func isTrusted(idServer string, cfg *config.Dendrite) error { func isTrusted(idServer string, cfg *config.ClientAPI) error {
for _, server := range cfg.Matrix.TrustedIDServers { for _, server := range cfg.Matrix.TrustedIDServers {
if idServer == server { if idServer == server {
return nil return nil

View file

@ -30,6 +30,6 @@ func main() {
intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
appservice.AddInternalRoutes(base.InternalAPIMux, intAPI) appservice.AddInternalRoutes(base.InternalAPIMux, intAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.AppServiceAPI), string(base.Cfg.Listen.AppServiceAPI)) base.SetupAndServeHTTP(string(base.Cfg.AppServiceAPI.Bind), string(base.Cfg.AppServiceAPI.Listen))
} }

View file

@ -39,10 +39,10 @@ func main() {
keyAPI := base.KeyServerHTTPClient() keyAPI := base.KeyServerHTTPClient()
clientapi.AddPublicRoutes( clientapi.AddPublicRoutes(
base.PublicAPIMux, base.Cfg, base.KafkaProducer, deviceDB, accountDB, federation, base.PublicAPIMux, &base.Cfg.ClientAPI, base.KafkaProducer, deviceDB, accountDB, federation,
rsAPI, eduInputAPI, asQuery, stateAPI, transactions.New(), fsAPI, userAPI, keyAPI, nil, rsAPI, eduInputAPI, asQuery, stateAPI, transactions.New(), fsAPI, userAPI, keyAPI, nil,
) )
base.SetupAndServeHTTP(string(base.Cfg.Bind.ClientAPI), string(base.Cfg.Listen.ClientAPI)) base.SetupAndServeHTTP(string(base.Cfg.ClientAPI.Bind), string(base.Cfg.ClientAPI.Listen))
} }

View file

@ -24,10 +24,10 @@ func main() {
base := setup.NewBaseDendrite(cfg, "CurrentStateServer", true) base := setup.NewBaseDendrite(cfg, "CurrentStateServer", true)
defer base.Close() // nolint: errcheck defer base.Close() // nolint: errcheck
stateAPI := currentstateserver.NewInternalAPI(cfg, base.KafkaConsumer) stateAPI := currentstateserver.NewInternalAPI(&cfg.CurrentStateServer, base.KafkaConsumer)
currentstateserver.AddInternalRoutes(base.InternalAPIMux, stateAPI) currentstateserver.AddInternalRoutes(base.InternalAPIMux, stateAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.CurrentState), string(base.Cfg.Listen.CurrentState)) base.SetupAndServeHTTP(string(base.Cfg.CurrentStateServer.Bind), string(base.Cfg.CurrentStateServer.Listen))
} }

View file

@ -33,6 +33,6 @@ func main() {
intAPI := eduserver.NewInternalAPI(base, cache.New(), base.UserAPIClient()) intAPI := eduserver.NewInternalAPI(base, cache.New(), base.UserAPIClient())
eduserver.AddInternalRoutes(base.InternalAPIMux, intAPI) eduserver.AddInternalRoutes(base.InternalAPIMux, intAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.EDUServer), string(base.Cfg.Listen.EDUServer)) base.SetupAndServeHTTP(string(base.Cfg.EDUServer.Bind), string(base.Cfg.EDUServer.Listen))
} }

View file

@ -33,10 +33,10 @@ func main() {
keyAPI := base.KeyServerHTTPClient() keyAPI := base.KeyServerHTTPClient()
federationapi.AddPublicRoutes( federationapi.AddPublicRoutes(
base.PublicAPIMux, base.Cfg, userAPI, federation, keyRing, base.PublicAPIMux, &base.Cfg.FederationAPI, userAPI, federation, keyRing,
rsAPI, fsAPI, base.EDUServerClient(), base.CurrentStateAPIClient(), keyAPI, rsAPI, fsAPI, base.EDUServerClient(), base.CurrentStateAPIClient(), keyAPI,
) )
base.SetupAndServeHTTP(string(base.Cfg.Bind.FederationAPI), string(base.Cfg.Listen.FederationAPI)) base.SetupAndServeHTTP(string(base.Cfg.FederationAPI.Bind), string(base.Cfg.FederationAPI.Listen))
} }

View file

@ -35,6 +35,6 @@ func main() {
) )
federationsender.AddInternalRoutes(base.InternalAPIMux, fsAPI) federationsender.AddInternalRoutes(base.InternalAPIMux, fsAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.FederationSender), string(base.Cfg.Listen.FederationSender)) base.SetupAndServeHTTP(string(base.Cfg.FederationSender.Bind), string(base.Cfg.FederationSender.Listen))
} }

View file

@ -24,10 +24,10 @@ func main() {
base := setup.NewBaseDendrite(cfg, "KeyServer", true) base := setup.NewBaseDendrite(cfg, "KeyServer", true)
defer base.Close() // nolint: errcheck defer base.Close() // nolint: errcheck
intAPI := keyserver.NewInternalAPI(base.Cfg, base.CreateFederationClient(), base.UserAPIClient(), base.KafkaProducer) intAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, base.CreateFederationClient(), base.UserAPIClient(), base.KafkaProducer)
keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI) keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.KeyServer), string(base.Cfg.Listen.KeyServer)) base.SetupAndServeHTTP(string(base.Cfg.KeyServer.Bind), string(base.Cfg.KeyServer.Listen))
} }

View file

@ -28,8 +28,8 @@ func main() {
userAPI := base.UserAPIClient() userAPI := base.UserAPIClient()
client := gomatrixserverlib.NewClient() client := gomatrixserverlib.NewClient()
mediaapi.AddPublicRoutes(base.PublicAPIMux, base.Cfg, userAPI, client) mediaapi.AddPublicRoutes(base.PublicAPIMux, &base.Cfg.MediaAPI, userAPI, client)
base.SetupAndServeHTTP(string(base.Cfg.Bind.MediaAPI), string(base.Cfg.Listen.MediaAPI)) base.SetupAndServeHTTP(string(base.Cfg.MediaAPI.Bind), string(base.Cfg.MediaAPI.Listen))
} }

View file

@ -54,11 +54,13 @@ func main() {
// the API endpoints. They'll listen on the same port as the monolith // the API endpoints. They'll listen on the same port as the monolith
// itself. // itself.
addr := config.Address(*httpBindAddr) addr := config.Address(*httpBindAddr)
cfg.Listen.RoomServer = addr cfg.RoomServer.Listen = addr
cfg.Listen.EDUServer = addr cfg.EDUServer.Listen = addr
cfg.Listen.AppServiceAPI = addr cfg.AppServiceAPI.Listen = addr
cfg.Listen.FederationSender = addr cfg.FederationSender.Listen = addr
cfg.Listen.ServerKeyAPI = addr cfg.ServerKeyAPI.Listen = addr
cfg.CurrentStateServer.Listen = addr
cfg.KeyServer.Listen = addr
} }
base := setup.NewBaseDendrite(cfg, "Monolith", *enableHTTPAPIs) base := setup.NewBaseDendrite(cfg, "Monolith", *enableHTTPAPIs)
@ -69,14 +71,14 @@ func main() {
federation := base.CreateFederationClient() federation := base.CreateFederationClient()
serverKeyAPI := serverkeyapi.NewInternalAPI( serverKeyAPI := serverkeyapi.NewInternalAPI(
base.Cfg, federation, base.Caches, &base.Cfg.ServerKeyAPI, federation, base.Caches,
) )
if base.UseHTTPAPIs { if base.UseHTTPAPIs {
serverkeyapi.AddInternalRoutes(base.InternalAPIMux, serverKeyAPI, base.Caches) serverkeyapi.AddInternalRoutes(base.InternalAPIMux, serverKeyAPI, base.Caches)
serverKeyAPI = base.ServerKeyAPIClient() serverKeyAPI = base.ServerKeyAPIClient()
} }
keyRing := serverKeyAPI.KeyRing() keyRing := serverKeyAPI.KeyRing()
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices) userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Global.ServerName, cfg.Derived.ApplicationServices)
rsImpl := roomserver.NewInternalAPI( rsImpl := roomserver.NewInternalAPI(
base, keyRing, federation, base, keyRing, federation,
@ -118,8 +120,8 @@ func main() {
// This is different to rsAPI which can be the http client which doesn't need this dependency // This is different to rsAPI which can be the http client which doesn't need this dependency
rsImpl.SetFederationSenderAPI(fsAPI) rsImpl.SetFederationSenderAPI(fsAPI)
stateAPI := currentstateserver.NewInternalAPI(base.Cfg, base.KafkaConsumer) stateAPI := currentstateserver.NewInternalAPI(&base.Cfg.CurrentStateServer, base.KafkaConsumer)
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, userAPI, base.KafkaProducer) keyAPI := keyserver.NewInternalAPI(&base.Cfg.KeyServer, federation, userAPI, base.KafkaProducer)
monolith := setup.Monolith{ monolith := setup.Monolith{
Config: base.Cfg, Config: base.Cfg,
@ -146,7 +148,7 @@ func main() {
base.BaseMux, base.BaseMux,
base.PublicAPIMux, base.PublicAPIMux,
base.InternalAPIMux, base.InternalAPIMux,
cfg, &cfg.Global,
base.UseHTTPAPIs, base.UseHTTPAPIs,
) )

View file

@ -33,6 +33,6 @@ func main() {
rsAPI.SetFederationSenderAPI(fsAPI) rsAPI.SetFederationSenderAPI(fsAPI)
roomserver.AddInternalRoutes(base.InternalAPIMux, rsAPI) roomserver.AddInternalRoutes(base.InternalAPIMux, rsAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.RoomServer), string(base.Cfg.Listen.RoomServer)) base.SetupAndServeHTTP(string(base.Cfg.RoomServer.Bind), string(base.Cfg.RoomServer.Listen))
} }

View file

@ -26,8 +26,8 @@ func main() {
federation := base.CreateFederationClient() federation := base.CreateFederationClient()
intAPI := serverkeyapi.NewInternalAPI(base.Cfg, federation, base.Caches) intAPI := serverkeyapi.NewInternalAPI(&base.Cfg.ServerKeyAPI, federation, base.Caches)
serverkeyapi.AddInternalRoutes(base.InternalAPIMux, intAPI, base.Caches) serverkeyapi.AddInternalRoutes(base.InternalAPIMux, intAPI, base.Caches)
base.SetupAndServeHTTP(string(base.Cfg.Bind.ServerKeyAPI), string(base.Cfg.Listen.ServerKeyAPI)) base.SetupAndServeHTTP(string(base.Cfg.ServerKeyAPI.Bind), string(base.Cfg.ServerKeyAPI.Listen))
} }

View file

@ -29,8 +29,8 @@ func main() {
rsAPI := base.RoomserverHTTPClient() rsAPI := base.RoomserverHTTPClient()
syncapi.AddPublicRoutes(base.PublicAPIMux, base.KafkaConsumer, userAPI, rsAPI, federation, cfg) syncapi.AddPublicRoutes(base.PublicAPIMux, base.KafkaConsumer, userAPI, rsAPI, federation, &cfg.SyncAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.SyncAPI), string(base.Cfg.Listen.SyncAPI)) base.SetupAndServeHTTP(string(base.Cfg.SyncAPI.Bind), string(base.Cfg.SyncAPI.Listen))
} }

View file

@ -27,9 +27,9 @@ func main() {
accountDB := base.CreateAccountsDB() accountDB := base.CreateAccountsDB()
deviceDB := base.CreateDeviceDB() deviceDB := base.CreateDeviceDB()
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices) userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Global.ServerName, cfg.Derived.ApplicationServices)
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI) userapi.AddInternalRoutes(base.InternalAPIMux, userAPI)
base.SetupAndServeHTTP(string(base.Cfg.Bind.UserAPI), string(base.Cfg.Listen.UserAPI)) base.SetupAndServeHTTP(string(base.Cfg.UserAPI.Bind), string(base.Cfg.UserAPI.Listen))
} }

View file

@ -0,0 +1,20 @@
package main
import (
"fmt"
"github.com/matrix-org/dendrite/internal/config"
"gopkg.in/yaml.v2"
)
func main() {
config := &config.Dendrite{}
config.Defaults()
j, err := yaml.Marshal(config)
if err != nil {
panic(err)
}
fmt.Println(string(j))
}

View file

@ -88,9 +88,9 @@ func startMediaAPI(suffix string, dynamicThumbnails bool) (*exec.Cmd, chan error
if err != nil { if err != nil {
panic(err) panic(err)
} }
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(proxyAddr) cfg.Global.ServerName = gomatrixserverlib.ServerName(proxyAddr)
cfg.Media.DynamicThumbnails = dynamicThumbnails cfg.MediaAPI.DynamicThumbnails = dynamicThumbnails
if err = yaml.Unmarshal([]byte(thumbnailSizes), &cfg.Media.ThumbnailSizes); err != nil { if err = yaml.Unmarshal([]byte(thumbnailSizes), &cfg.MediaAPI.ThumbnailSizes); err != nil {
panic(err) panic(err)
} }

View file

@ -240,7 +240,7 @@ func testRoomserver(input []string, wantOutput []string, checkQueries func(api.R
panic(err) panic(err)
} }
outputTopic := string(cfg.Kafka.Topics.OutputRoomEvent) outputTopic := string(cfg.Global.Kafka.Topics.OutputRoomEvent)
err = exe.DeleteTopic(outputTopic) err = exe.DeleteTopic(outputTopic)
if err != nil { if err != nil {

View file

@ -132,10 +132,10 @@ func startSyncServer() (*exec.Cmd, chan error) {
panic(err) panic(err)
} }
// TODO use the address assigned by the config generator rather than clobbering. // TODO use the address assigned by the config generator rather than clobbering.
cfg.Matrix.ServerName = "localhost" cfg.Global.ServerName = "localhost"
cfg.Listen.SyncAPI = config.Address(syncserverAddr) cfg.Listen.SyncAPI = config.Address(syncserverAddr)
cfg.Kafka.Topics.OutputRoomEvent = config.Topic(inputTopic) cfg.Global.Kafka.Topics.OutputRoomEvent = config.Topic(inputTopic)
cfg.Kafka.Topics.OutputClientData = config.Topic(clientTopic) cfg.Global.Kafka.Topics.OutputClientData = config.Topic(clientTopic)
if err := test.WriteConfig(cfg, dir); err != nil { if err := test.WriteConfig(cfg, dir); err != nil {
panic(err) panic(err)

View file

@ -31,7 +31,7 @@ import (
// AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component. // AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component.
func AddPublicRoutes( func AddPublicRoutes(
router *mux.Router, router *mux.Router,
cfg *config.Dendrite, cfg *config.FederationAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
keyRing gomatrixserverlib.JSONVerifier, keyRing gomatrixserverlib.JSONVerifier,

View file

@ -19,31 +19,37 @@ import (
// Relevant for v3 rooms and a cause of flakey sytests as the IDs are randomly generated. // Relevant for v3 rooms and a cause of flakey sytests as the IDs are randomly generated.
func TestRoomsV3URLEscapeDoNot404(t *testing.T) { func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
_, privKey, _ := ed25519.GenerateKey(nil) _, privKey, _ := ed25519.GenerateKey(nil)
cfg := &config.Dendrite{} cfg := &config.Dendrite{
cfg.Matrix.KeyID = gomatrixserverlib.KeyID("ed25519:auto") Global: config.Global{
cfg.Matrix.ServerName = gomatrixserverlib.ServerName("localhost") KeyID: gomatrixserverlib.KeyID("ed25519:auto"),
cfg.Matrix.PrivateKey = privKey ServerName: gomatrixserverlib.ServerName("localhost"),
cfg.Kafka.UseNaffka = true PrivateKey: privKey,
cfg.Database.Naffka = "file::memory:" },
cfg.SetDefaults() FederationSender: config.FederationSender{
Database: "file::memory:",
},
}
cfg.FederationSender.Matrix = &cfg.Global
cfg.Global.Kafka.UseNaffka = true
// TODO: cfg.SetDefaults()
base := setup.NewBaseDendrite(cfg, "Test", false) base := setup.NewBaseDendrite(cfg, "Test", false)
keyRing := &test.NopJSONVerifier{} keyRing := &test.NopJSONVerifier{}
fsAPI := base.FederationSenderHTTPClient() fsAPI := base.FederationSenderHTTPClient()
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break. // TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing. // Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.
federationapi.AddPublicRoutes(base.PublicAPIMux, cfg, nil, nil, keyRing, nil, fsAPI, nil, nil, nil) federationapi.AddPublicRoutes(base.PublicAPIMux, &cfg.FederationAPI, nil, nil, keyRing, nil, fsAPI, nil, nil, nil)
httputil.SetupHTTPAPI( httputil.SetupHTTPAPI(
base.BaseMux, base.BaseMux,
base.PublicAPIMux, base.PublicAPIMux,
base.InternalAPIMux, base.InternalAPIMux,
cfg, &cfg.Global,
base.UseHTTPAPIs, base.UseHTTPAPIs,
) )
baseURL, cancel := test.ListenAndServe(t, base.BaseMux, true) baseURL, cancel := test.ListenAndServe(t, base.BaseMux, true)
defer cancel() defer cancel()
serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://")) serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://"))
fedCli := gomatrixserverlib.NewFederationClient(serverName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) fedCli := gomatrixserverlib.NewFederationClient(serverName, cfg.Global.KeyID, cfg.Global.PrivateKey)
testCases := []struct { testCases := []struct {
roomVer gomatrixserverlib.RoomVersion roomVer gomatrixserverlib.RoomVersion

View file

@ -35,7 +35,7 @@ func Backfill(
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
roomID string, roomID string,
cfg *config.Dendrite, cfg *config.FederationAPI,
) util.JSONResponse { ) util.JSONResponse {
var res api.PerformBackfillResponse var res api.PerformBackfillResponse
var eIDs []string var eIDs []string

View file

@ -34,7 +34,7 @@ func InviteV2(
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
roomID string, roomID string,
eventID string, eventID string,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,
) util.JSONResponse { ) util.JSONResponse {
@ -56,7 +56,7 @@ func InviteV1(
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
roomID string, roomID string,
eventID string, eventID string,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,
) util.JSONResponse { ) util.JSONResponse {
@ -86,7 +86,7 @@ func processInvite(
strippedState []gomatrixserverlib.InviteV2StrippedState, strippedState []gomatrixserverlib.InviteV2StrippedState,
roomID string, roomID string,
eventID string, eventID string,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,
) util.JSONResponse { ) util.JSONResponse {

View file

@ -32,7 +32,7 @@ import (
func MakeJoin( func MakeJoin(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
roomID, userID string, roomID, userID string,
remoteVersions []gomatrixserverlib.RoomVersion, remoteVersions []gomatrixserverlib.RoomVersion,
@ -95,7 +95,7 @@ func MakeJoin(
queryRes := api.QueryLatestEventsAndStateResponse{ queryRes := api.QueryLatestEventsAndStateResponse{
RoomVersion: verRes.RoomVersion, RoomVersion: verRes.RoomVersion,
} }
event, err := eventutil.BuildEvent(httpReq.Context(), &builder, cfg, time.Now(), rsAPI, &queryRes) event, err := eventutil.BuildEvent(httpReq.Context(), &builder, cfg.Matrix, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { if err == eventutil.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -141,7 +141,7 @@ func MakeJoin(
func SendJoin( func SendJoin(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,
roomID, eventID string, roomID, eventID string,

View file

@ -121,7 +121,7 @@ func ClaimOneTimeKeys(
// LocalKeys returns the local keys for the server. // LocalKeys returns the local keys for the server.
// See https://matrix.org/docs/spec/server_server/unstable.html#publishing-keys // See https://matrix.org/docs/spec/server_server/unstable.html#publishing-keys
func LocalKeys(cfg *config.Dendrite) util.JSONResponse { func LocalKeys(cfg *config.FederationAPI) util.JSONResponse {
keys, err := localKeys(cfg, time.Now().Add(cfg.Matrix.KeyValidityPeriod)) keys, err := localKeys(cfg, time.Now().Add(cfg.Matrix.KeyValidityPeriod))
if err != nil { if err != nil {
return util.ErrorResponse(err) return util.ErrorResponse(err)
@ -129,7 +129,7 @@ func LocalKeys(cfg *config.Dendrite) util.JSONResponse {
return util.JSONResponse{Code: http.StatusOK, JSON: keys} return util.JSONResponse{Code: http.StatusOK, JSON: keys}
} }
func localKeys(cfg *config.Dendrite, validUntil time.Time) (*gomatrixserverlib.ServerKeys, error) { func localKeys(cfg *config.FederationAPI, validUntil time.Time) (*gomatrixserverlib.ServerKeys, error) {
var keys gomatrixserverlib.ServerKeys var keys gomatrixserverlib.ServerKeys
keys.ServerName = cfg.Matrix.ServerName keys.ServerName = cfg.Matrix.ServerName
@ -142,7 +142,7 @@ func localKeys(cfg *config.Dendrite, validUntil time.Time) (*gomatrixserverlib.S
}, },
} }
keys.TLSFingerprints = cfg.Matrix.TLSFingerPrints keys.TLSFingerprints = cfg.TLSFingerPrints
keys.OldVerifyKeys = map[gomatrixserverlib.KeyID]gomatrixserverlib.OldVerifyKey{} keys.OldVerifyKeys = map[gomatrixserverlib.KeyID]gomatrixserverlib.OldVerifyKey{}
keys.ValidUntilTS = gomatrixserverlib.AsTimestamp(validUntil) keys.ValidUntilTS = gomatrixserverlib.AsTimestamp(validUntil)

View file

@ -28,7 +28,7 @@ import (
func MakeLeave( func MakeLeave(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
roomID, userID string, roomID, userID string,
) util.JSONResponse { ) util.JSONResponse {
@ -60,7 +60,7 @@ func MakeLeave(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
event, err := eventutil.BuildEvent(httpReq.Context(), &builder, cfg, time.Now(), rsAPI, &queryRes) event, err := eventutil.BuildEvent(httpReq.Context(), &builder, cfg.Matrix, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { if err == eventutil.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -102,7 +102,7 @@ func MakeLeave(
func SendLeave( func SendLeave(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,
roomID, eventID string, roomID, eventID string,

View file

@ -30,7 +30,7 @@ import (
func GetProfile( func GetProfile(
httpReq *http.Request, httpReq *http.Request,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
cfg *config.Dendrite, cfg *config.FederationAPI,
) util.JSONResponse { ) util.JSONResponse {
userID, field := httpReq.FormValue("user_id"), httpReq.FormValue("field") userID, field := httpReq.FormValue("user_id"), httpReq.FormValue("field")

View file

@ -31,7 +31,7 @@ import (
func RoomAliasToID( func RoomAliasToID(
httpReq *http.Request, httpReq *http.Request,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
senderAPI federationSenderAPI.FederationSenderInternalAPI, senderAPI federationSenderAPI.FederationSenderInternalAPI,
) util.JSONResponse { ) util.JSONResponse {

View file

@ -47,7 +47,7 @@ const (
// nolint: gocyclo // nolint: gocyclo
func Setup( func Setup(
publicAPIMux *mux.Router, publicAPIMux *mux.Router,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
eduAPI eduserverAPI.EDUServerInputAPI, eduAPI eduserverAPI.EDUServerInputAPI,
fsAPI federationSenderAPI.FederationSenderInternalAPI, fsAPI federationSenderAPI.FederationSenderInternalAPI,

View file

@ -34,7 +34,7 @@ func Send(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
txnID gomatrixserverlib.TransactionID, txnID gomatrixserverlib.TransactionID,
cfg *config.Dendrite, cfg *config.FederationAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
eduAPI eduserverAPI.EDUServerInputAPI, eduAPI eduserverAPI.EDUServerInputAPI,
keys gomatrixserverlib.JSONVerifier, keys gomatrixserverlib.JSONVerifier,

View file

@ -56,7 +56,7 @@ var (
// CreateInvitesFrom3PIDInvites implements POST /_matrix/federation/v1/3pid/onbind // CreateInvitesFrom3PIDInvites implements POST /_matrix/federation/v1/3pid/onbind
func CreateInvitesFrom3PIDInvites( func CreateInvitesFrom3PIDInvites(
req *http.Request, rsAPI api.RoomserverInternalAPI, req *http.Request, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.FederationAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -106,7 +106,7 @@ func ExchangeThirdPartyInvite(
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
roomID string, roomID string,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.FederationAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
) util.JSONResponse { ) util.JSONResponse {
var builder gomatrixserverlib.EventBuilder var builder gomatrixserverlib.EventBuilder
@ -196,7 +196,7 @@ func ExchangeThirdPartyInvite(
// necessary data to do so. // necessary data to do so.
func createInviteFrom3PIDInvite( func createInviteFrom3PIDInvite(
ctx context.Context, rsAPI api.RoomserverInternalAPI, ctx context.Context, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.FederationAPI,
inv invite, federation *gomatrixserverlib.FederationClient, inv invite, federation *gomatrixserverlib.FederationClient,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
@ -263,7 +263,7 @@ func createInviteFrom3PIDInvite(
func buildMembershipEvent( func buildMembershipEvent(
ctx context.Context, ctx context.Context,
builder *gomatrixserverlib.EventBuilder, rsAPI api.RoomserverInternalAPI, builder *gomatrixserverlib.EventBuilder, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.FederationAPI,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
if err != nil { if err != nil {
@ -327,7 +327,7 @@ func buildMembershipEvent(
// them responded with an error. // them responded with an error.
func sendToRemoteServer( func sendToRemoteServer(
ctx context.Context, inv invite, ctx context.Context, inv invite,
federation *gomatrixserverlib.FederationClient, _ *config.Dendrite, federation *gomatrixserverlib.FederationClient, _ *config.FederationAPI,
builder gomatrixserverlib.EventBuilder, builder gomatrixserverlib.EventBuilder,
) (err error) { ) (err error) {
remoteServers := make([]gomatrixserverlib.ServerName, 2) remoteServers := make([]gomatrixserverlib.ServerName, 2)

View file

@ -41,27 +41,27 @@ type OutputEDUConsumer struct {
// NewOutputEDUConsumer creates a new OutputEDUConsumer. Call Start() to begin consuming from EDU servers. // NewOutputEDUConsumer creates a new OutputEDUConsumer. Call Start() to begin consuming from EDU servers.
func NewOutputEDUConsumer( func NewOutputEDUConsumer(
cfg *config.Dendrite, cfg *config.FederationSender,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
queues *queue.OutgoingQueues, queues *queue.OutgoingQueues,
store storage.Database, store storage.Database,
) *OutputEDUConsumer { ) *OutputEDUConsumer {
c := &OutputEDUConsumer{ c := &OutputEDUConsumer{
typingConsumer: &internal.ContinualConsumer{ typingConsumer: &internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputTypingEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputTypingEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
}, },
sendToDeviceConsumer: &internal.ContinualConsumer{ sendToDeviceConsumer: &internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputSendToDeviceEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputSendToDeviceEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
}, },
queues: queues, queues: queues,
db: store, db: store,
ServerName: cfg.Matrix.ServerName, ServerName: cfg.Matrix.ServerName,
TypingTopic: string(cfg.Kafka.Topics.OutputTypingEvent), TypingTopic: string(cfg.Matrix.Kafka.Topics.OutputTypingEvent),
SendToDeviceTopic: string(cfg.Kafka.Topics.OutputSendToDeviceEvent), SendToDeviceTopic: string(cfg.Matrix.Kafka.Topics.OutputSendToDeviceEvent),
} }
c.typingConsumer.ProcessMessage = c.onTypingEvent c.typingConsumer.ProcessMessage = c.onTypingEvent
c.sendToDeviceConsumer.ProcessMessage = c.onSendToDeviceEvent c.sendToDeviceConsumer.ProcessMessage = c.onSendToDeviceEvent

View file

@ -33,7 +33,7 @@ import (
// OutputRoomEventConsumer consumes events that originated in the room server. // OutputRoomEventConsumer consumes events that originated in the room server.
type OutputRoomEventConsumer struct { type OutputRoomEventConsumer struct {
cfg *config.Dendrite cfg *config.FederationSender
rsAPI api.RoomserverInternalAPI rsAPI api.RoomserverInternalAPI
rsConsumer *internal.ContinualConsumer rsConsumer *internal.ContinualConsumer
db storage.Database db storage.Database
@ -42,14 +42,14 @@ type OutputRoomEventConsumer struct {
// NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers. // NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers.
func NewOutputRoomEventConsumer( func NewOutputRoomEventConsumer(
cfg *config.Dendrite, cfg *config.FederationSender,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
queues *queue.OutgoingQueues, queues *queue.OutgoingQueues,
store storage.Database, store storage.Database,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
) *OutputRoomEventConsumer { ) *OutputRoomEventConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputRoomEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputRoomEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
} }

View file

@ -43,27 +43,29 @@ func NewInternalAPI(
rsAPI roomserverAPI.RoomserverInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
keyRing *gomatrixserverlib.KeyRing, keyRing *gomatrixserverlib.KeyRing,
) api.FederationSenderInternalAPI { ) api.FederationSenderInternalAPI {
federationSenderDB, err := storage.NewDatabase(string(base.Cfg.Database.FederationSender), base.Cfg.DbProperties()) cfg := &base.Cfg.FederationSender
federationSenderDB, err := storage.NewDatabase(string(cfg.Database), cfg.DatabaseOptions)
if err != nil { if err != nil {
logrus.WithError(err).Panic("failed to connect to federation sender db") logrus.WithError(err).Panic("failed to connect to federation sender db")
} }
stats := &statistics.Statistics{ stats := &statistics.Statistics{
DB: federationSenderDB, DB: federationSenderDB,
FailuresUntilBlacklist: base.Cfg.Matrix.FederationMaxRetries, FailuresUntilBlacklist: cfg.FederationMaxRetries,
} }
queues := queue.NewOutgoingQueues( queues := queue.NewOutgoingQueues(
federationSenderDB, base.Cfg.Matrix.ServerName, federation, rsAPI, stats, federationSenderDB, cfg.Matrix.ServerName, federation, rsAPI, stats,
&queue.SigningInfo{ &queue.SigningInfo{
KeyID: base.Cfg.Matrix.KeyID, KeyID: cfg.Matrix.KeyID,
PrivateKey: base.Cfg.Matrix.PrivateKey, PrivateKey: cfg.Matrix.PrivateKey,
ServerName: base.Cfg.Matrix.ServerName, ServerName: cfg.Matrix.ServerName,
}, },
) )
rsConsumer := consumers.NewOutputRoomEventConsumer( rsConsumer := consumers.NewOutputRoomEventConsumer(
base.Cfg, base.KafkaConsumer, queues, cfg, base.KafkaConsumer, queues,
federationSenderDB, rsAPI, federationSenderDB, rsAPI,
) )
if err = rsConsumer.Start(); err != nil { if err = rsConsumer.Start(); err != nil {
@ -71,11 +73,11 @@ func NewInternalAPI(
} }
tsConsumer := consumers.NewOutputEDUConsumer( tsConsumer := consumers.NewOutputEDUConsumer(
base.Cfg, base.KafkaConsumer, queues, federationSenderDB, cfg, base.KafkaConsumer, queues, federationSenderDB,
) )
if err := tsConsumer.Start(); err != nil { if err := tsConsumer.Start(); err != nil {
logrus.WithError(err).Panic("failed to start typing server consumer") logrus.WithError(err).Panic("failed to start typing server consumer")
} }
return internal.NewFederationSenderInternalAPI(federationSenderDB, base.Cfg, rsAPI, federation, keyRing, stats, queues) return internal.NewFederationSenderInternalAPI(federationSenderDB, cfg, rsAPI, federation, keyRing, stats, queues)
} }

View file

@ -12,7 +12,7 @@ import (
// FederationSenderInternalAPI is an implementation of api.FederationSenderInternalAPI // FederationSenderInternalAPI is an implementation of api.FederationSenderInternalAPI
type FederationSenderInternalAPI struct { type FederationSenderInternalAPI struct {
db storage.Database db storage.Database
cfg *config.Dendrite cfg *config.FederationSender
statistics *statistics.Statistics statistics *statistics.Statistics
rsAPI api.RoomserverInternalAPI rsAPI api.RoomserverInternalAPI
federation *gomatrixserverlib.FederationClient federation *gomatrixserverlib.FederationClient
@ -21,7 +21,7 @@ type FederationSenderInternalAPI struct {
} }
func NewFederationSenderInternalAPI( func NewFederationSenderInternalAPI(
db storage.Database, cfg *config.Dendrite, db storage.Database, cfg *config.FederationSender,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
keyRing *gomatrixserverlib.KeyRing, keyRing *gomatrixserverlib.KeyRing,

View file

@ -24,7 +24,6 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
@ -38,7 +37,7 @@ import (
// Version is the current version of the config format. // Version is the current version of the config format.
// This will change whenever we make breaking changes to the config format. // This will change whenever we make breaking changes to the config format.
const Version = 0 const Version = 1
// Dendrite contains all the config used by a dendrite process. // Dendrite contains all the config used by a dendrite process.
// Relative paths are resolved relative to the current working directory // Relative paths are resolved relative to the current working directory
@ -51,214 +50,19 @@ type Dendrite struct {
// been a breaking change to the config file format. // been a breaking change to the config file format.
Version int `yaml:"version"` Version int `yaml:"version"`
// The configuration required for a matrix server. Global Global `yaml:"global"`
Matrix struct { AppServiceAPI AppServiceAPI `yaml:"app_service_api"`
// The name of the server. This is usually the domain name, e.g 'matrix.org', 'localhost'. ClientAPI ClientAPI `yaml:"client_api"`
ServerName gomatrixserverlib.ServerName `yaml:"server_name"` CurrentStateServer CurrentStateServer `yaml:"current_state_server"`
// Path to the private key which will be used to sign requests and events. EDUServer EDUServer `yaml:"edu_server"`
PrivateKeyPath Path `yaml:"private_key"` FederationAPI FederationAPI `yaml:"federation_api"`
// The private key which will be used to sign requests and events. FederationSender FederationSender `yaml:"federation_sender"`
PrivateKey ed25519.PrivateKey `yaml:"-"` KeyServer KeyServer `yaml:"key_server"`
// An arbitrary string used to uniquely identify the PrivateKey. Must start with the MediaAPI MediaAPI `yaml:"media_api"`
// prefix "ed25519:". RoomServer RoomServer `yaml:"room_server"`
KeyID gomatrixserverlib.KeyID `yaml:"-"` ServerKeyAPI ServerKeyAPI `yaml:"server_key_api"`
// List of paths to X509 certificates used by the external federation listeners. SyncAPI SyncAPI `yaml:"sync_api"`
// These are used to calculate the TLS fingerprints to publish for this server. UserAPI UserAPI `yaml:"user_api"`
// Other matrix servers talking to this server will expect the x509 certificate
// to match one of these certificates.
// The certificates should be in PEM format.
FederationCertificatePaths []Path `yaml:"federation_certificates"`
// A list of SHA256 TLS fingerprints for the X509 certificates used by the
// federation listener for this server.
TLSFingerPrints []gomatrixserverlib.TLSFingerprint `yaml:"-"`
// How long a remote server can cache our server key for before requesting it again.
// Increasing this number will reduce the number of requests made by remote servers
// for our key, but increases the period a compromised key will be considered valid
// by remote servers.
// Defaults to 24 hours.
KeyValidityPeriod time.Duration `yaml:"key_validity_period"`
// List of domains that the server will trust as identity servers to
// verify third-party identifiers.
// Defaults to an empty array.
TrustedIDServers []string `yaml:"trusted_third_party_id_servers"`
// If set, allows registration by anyone who also has the shared
// secret, even if registration is otherwise disabled.
RegistrationSharedSecret string `yaml:"registration_shared_secret"`
// This Home Server's ReCAPTCHA public key.
RecaptchaPublicKey string `yaml:"recaptcha_public_key"`
// This Home Server's ReCAPTCHA private key.
RecaptchaPrivateKey string `yaml:"recaptcha_private_key"`
// Boolean stating whether catpcha registration is enabled
// and required
RecaptchaEnabled bool `yaml:"enable_registration_captcha"`
// Secret used to bypass the captcha registration entirely
RecaptchaBypassSecret string `yaml:"captcha_bypass_secret"`
// HTTP API endpoint used to verify whether the captcha response
// was successful
RecaptchaSiteVerifyAPI string `yaml:"recaptcha_siteverify_api"`
// If set disables new users from registering (except via shared
// secrets)
RegistrationDisabled bool `yaml:"registration_disabled"`
// Perspective keyservers, to use as a backup when direct key fetch
// requests don't succeed
KeyPerspectives KeyPerspectives `yaml:"key_perspectives"`
// Federation failure threshold. How many consecutive failures that we should
// tolerate when sending federation requests to a specific server. The backoff
// is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds, etc.
// The default value is 16 if not specified, which is circa 18 hours.
FederationMaxRetries uint32 `yaml:"federation_max_retries"`
} `yaml:"matrix"`
// The configuration specific to the media repostitory.
Media struct {
// The base path to where the media files will be stored. May be relative or absolute.
BasePath Path `yaml:"base_path"`
// The absolute base path to where media files will be stored.
AbsBasePath Path `yaml:"-"`
// The maximum file size in bytes that is allowed to be stored on this server.
// Note: if max_file_size_bytes is set to 0, the size is unlimited.
// Note: if max_file_size_bytes is not set, it will default to 10485760 (10MB)
MaxFileSizeBytes *FileSizeBytes `yaml:"max_file_size_bytes,omitempty"`
// Whether to dynamically generate thumbnails on-the-fly if the requested resolution is not already generated
DynamicThumbnails bool `yaml:"dynamic_thumbnails"`
// The maximum number of simultaneous thumbnail generators. default: 10
MaxThumbnailGenerators int `yaml:"max_thumbnail_generators"`
// A list of thumbnail sizes to be pre-generated for downloaded remote / uploaded content
ThumbnailSizes []ThumbnailSize `yaml:"thumbnail_sizes"`
} `yaml:"media"`
// The configuration to use for Prometheus metrics
Metrics struct {
// Whether or not the metrics are enabled
Enabled bool `yaml:"enabled"`
// Use BasicAuth for Authorization
BasicAuth struct {
// Authorization via Static Username & Password
// Hardcoded Username and Password
Username string `yaml:"username"`
Password string `yaml:"password"`
} `yaml:"basic_auth"`
} `yaml:"metrics"`
// The configuration for talking to kafka.
Kafka struct {
// A list of kafka addresses to connect to.
Addresses []string `yaml:"addresses"`
// Whether to use naffka instead of kafka.
// Naffka can only be used when running dendrite as a single monolithic server.
// Kafka can be used both with a monolithic server and when running the
// components as separate servers.
UseNaffka bool `yaml:"use_naffka,omitempty"`
// The names of the topics to use when reading and writing from kafka.
Topics struct {
// Topic for roomserver/api.OutputRoomEvent events.
OutputRoomEvent Topic `yaml:"output_room_event"`
// Topic for sending account data from client API to sync API
OutputClientData Topic `yaml:"output_client_data"`
// Topic for eduserver/api.OutputTypingEvent events.
OutputTypingEvent Topic `yaml:"output_typing_event"`
// Topic for eduserver/api.OutputSendToDeviceEvent events.
OutputSendToDeviceEvent Topic `yaml:"output_send_to_device_event"`
// Topic for keyserver when new device keys are added.
OutputKeyChangeEvent Topic `yaml:"output_key_change_event"`
}
} `yaml:"kafka"`
// Postgres Config
Database struct {
// The Account database stores the login details and account information
// for local users. It is accessed by the UserAPI.
Account DataSource `yaml:"account"`
// The CurrentState database stores the current state of all rooms.
// It is accessed by the CurrentStateServer.
CurrentState DataSource `yaml:"current_state"`
// The Device database stores session information for the devices of logged
// in local users. It is accessed by the UserAPI.
Device DataSource `yaml:"device"`
// The MediaAPI database stores information about files uploaded and downloaded
// by local users. It is only accessed by the MediaAPI.
MediaAPI DataSource `yaml:"media_api"`
// The ServerKey database caches the public keys of remote servers.
// It may be accessed by the FederationAPI, the ClientAPI, and the MediaAPI.
ServerKey DataSource `yaml:"server_key"`
// The E2EKey database stores one-time public keys for devices in addition to
// signed device keys. Used for E2E.
E2EKey DataSource `yaml:"e2e_key"`
// The SyncAPI stores information used by the SyncAPI server.
// It is only accessed by the SyncAPI server.
SyncAPI DataSource `yaml:"sync_api"`
// The RoomServer database stores information about matrix rooms.
// It is only accessed by the RoomServer.
RoomServer DataSource `yaml:"room_server"`
// The FederationSender database stores information used by the FederationSender
// It is only accessed by the FederationSender.
FederationSender DataSource `yaml:"federation_sender"`
// The AppServices database stores information used by the AppService component.
// It is only accessed by the AppService component.
AppService DataSource `yaml:"appservice"`
// The Naffka database is used internally by the naffka library, if used.
Naffka DataSource `yaml:"naffka,omitempty"`
// Maximum open connections to the DB (0 = use default, negative means unlimited)
MaxOpenConns int `yaml:"max_open_conns"`
// Maximum idle connections to the DB (0 = use default, negative means unlimited)
MaxIdleConns int `yaml:"max_idle_conns"`
// maximum amount of time (in seconds) a connection may be reused (<= 0 means unlimited)
ConnMaxLifetimeSec int `yaml:"conn_max_lifetime"`
} `yaml:"database"`
// TURN Server Config
TURN struct {
// TODO Guest Support
// Whether or not guests can request TURN credentials
//AllowGuests bool `yaml:"turn_allow_guests"`
// How long the authorization should last
UserLifetime string `yaml:"turn_user_lifetime"`
// The list of TURN URIs to pass to clients
URIs []string `yaml:"turn_uris"`
// Authorization via Shared Secret
// The shared secret from coturn
SharedSecret string `yaml:"turn_shared_secret"`
// Authorization via Static Username & Password
// Hardcoded Username and Password
Username string `yaml:"turn_username"`
Password string `yaml:"turn_password"`
} `yaml:"turn"`
// The internal addresses the components will listen on.
// These should not be exposed externally as they expose metrics and debugging APIs.
// Falls back to addresses listed in Listen if not specified
Bind struct {
MediaAPI Address `yaml:"media_api"`
ClientAPI Address `yaml:"client_api"`
CurrentState Address `yaml:"current_state_server"`
FederationAPI Address `yaml:"federation_api"`
ServerKeyAPI Address `yaml:"server_key_api"`
AppServiceAPI Address `yaml:"appservice_api"`
SyncAPI Address `yaml:"sync_api"`
UserAPI Address `yaml:"user_api"`
RoomServer Address `yaml:"room_server"`
FederationSender Address `yaml:"federation_sender"`
EDUServer Address `yaml:"edu_server"`
KeyServer Address `yaml:"key_server"`
} `yaml:"bind"`
// The addresses for talking to other microservices.
Listen struct {
MediaAPI Address `yaml:"media_api"`
ClientAPI Address `yaml:"client_api"`
CurrentState Address `yaml:"current_state_server"`
FederationAPI Address `yaml:"federation_api"`
ServerKeyAPI Address `yaml:"server_key_api"`
AppServiceAPI Address `yaml:"appservice_api"`
SyncAPI Address `yaml:"sync_api"`
UserAPI Address `yaml:"user_api"`
RoomServer Address `yaml:"room_server"`
FederationSender Address `yaml:"federation_sender"`
EDUServer Address `yaml:"edu_server"`
KeyServer Address `yaml:"key_server"`
} `yaml:"listen"`
// The config for tracing the dendrite servers. // The config for tracing the dendrite servers.
Tracing struct { Tracing struct {
@ -268,56 +72,42 @@ type Dendrite struct {
Jaeger jaegerconfig.Configuration `yaml:"jaeger"` Jaeger jaegerconfig.Configuration `yaml:"jaeger"`
} `yaml:"tracing"` } `yaml:"tracing"`
// Application Services
// https://matrix.org/docs/spec/application_service/unstable.html
ApplicationServices struct {
// Configuration files for various application services
ConfigFiles []string `yaml:"config_files"`
} `yaml:"application_services"`
// The config for logging informations. Each hook will be added to logrus. // The config for logging informations. Each hook will be added to logrus.
Logging []LogrusHook `yaml:"logging"` Logging []LogrusHook `yaml:"logging"`
// The config for setting a proxy to use for server->server requests
Proxy *struct {
// The protocol for the proxy (http / https / socks5)
Protocol string `yaml:"protocol"`
// The host where the proxy is listening
Host string `yaml:"host"`
// The port on which the proxy is listening
Port uint16 `yaml:"port"`
} `yaml:"proxy"`
// Any information derived from the configuration options for later use. // Any information derived from the configuration options for later use.
Derived struct { Derived Derived `yaml:"-"`
Registration struct { }
// Flows is a slice of flows, which represent one possible way that the client can authenticate a request.
// http://matrix.org/docs/spec/HEAD/client_server/r0.3.0.html#user-interactive-authentication-api
// As long as the generated flows only rely on config file options,
// we can generate them on startup and store them until needed
Flows []authtypes.Flow `json:"flows"`
// Params that need to be returned to the client during // TODO: Kill Derived
// registration in order to complete registration stages. type Derived struct {
Params map[string]interface{} `json:"params"` Registration struct {
} // Flows is a slice of flows, which represent one possible way that the client can authenticate a request.
// http://matrix.org/docs/spec/HEAD/client_server/r0.3.0.html#user-interactive-authentication-api
// As long as the generated flows only rely on config file options,
// we can generate them on startup and store them until needed
Flows []authtypes.Flow `json:"flows"`
// Application services parsed from their config files // Params that need to be returned to the client during
// The paths of which were given above in the main config file // registration in order to complete registration stages.
ApplicationServices []ApplicationService Params map[string]interface{} `json:"params"`
}
// Meta-regexes compiled from all exclusive application service // Application services parsed from their config files
// Regexes. // The paths of which were given above in the main config file
// ApplicationServices []ApplicationService
// When a user registers, we check that their username does not match any
// exclusive application service namespaces // Meta-regexes compiled from all exclusive application service
ExclusiveApplicationServicesUsernameRegexp *regexp.Regexp // Regexes.
// When a user creates a room alias, we check that it isn't already //
// reserved by an application service // When a user registers, we check that their username does not match any
ExclusiveApplicationServicesAliasRegexp *regexp.Regexp // exclusive application service namespaces
// Note: An Exclusive Regex for room ID isn't necessary as we aren't blocking ExclusiveApplicationServicesUsernameRegexp *regexp.Regexp
// servers from creating RoomIDs in exclusive application service namespaces // When a user creates a room alias, we check that it isn't already
} `yaml:"-"` // reserved by an application service
ExclusiveApplicationServicesAliasRegexp *regexp.Regexp
// Note: An Exclusive Regex for room ID isn't necessary as we aren't blocking
// servers from creating RoomIDs in exclusive application service namespaces
} }
// KeyPerspectives are used to configure perspective key servers for // KeyPerspectives are used to configure perspective key servers for
@ -402,29 +192,29 @@ func loadConfig(
readFile func(string) ([]byte, error), readFile func(string) ([]byte, error),
monolithic bool, monolithic bool,
) (*Dendrite, error) { ) (*Dendrite, error) {
var config Dendrite var c Dendrite
c.Defaults()
var err error var err error
if err = yaml.Unmarshal(configData, &config); err != nil { if err = yaml.Unmarshal(configData, &c); err != nil {
return nil, err return nil, err
} }
config.SetDefaults() if err = c.check(monolithic); err != nil {
if err = config.check(monolithic); err != nil {
return nil, err return nil, err
} }
privateKeyPath := absPath(basePath, config.Matrix.PrivateKeyPath) privateKeyPath := absPath(basePath, c.Global.PrivateKeyPath)
privateKeyData, err := readFile(privateKeyPath) privateKeyData, err := readFile(privateKeyPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if config.Matrix.KeyID, config.Matrix.PrivateKey, err = readKeyPEM(privateKeyPath, privateKeyData); err != nil { if c.Global.KeyID, c.Global.PrivateKey, err = readKeyPEM(privateKeyPath, privateKeyData); err != nil {
return nil, err return nil, err
} }
for _, certPath := range config.Matrix.FederationCertificatePaths { for _, certPath := range c.FederationAPI.FederationCertificatePaths {
absCertPath := absPath(basePath, certPath) absCertPath := absPath(basePath, certPath)
var pemData []byte var pemData []byte
pemData, err = readFile(absCertPath) pemData, err = readFile(absCertPath)
@ -435,18 +225,19 @@ func loadConfig(
if fingerprint == nil { if fingerprint == nil {
return nil, fmt.Errorf("no certificate PEM data in %q", absCertPath) return nil, fmt.Errorf("no certificate PEM data in %q", absCertPath)
} }
config.Matrix.TLSFingerPrints = append(config.Matrix.TLSFingerPrints, *fingerprint) c.FederationAPI.TLSFingerPrints = append(c.FederationAPI.TLSFingerPrints, *fingerprint)
} }
config.Media.AbsBasePath = Path(absPath(basePath, config.Media.BasePath)) c.MediaAPI.AbsBasePath = Path(absPath(basePath, c.MediaAPI.BasePath))
// Generate data from config options // Generate data from config options
err = config.Derive() err = c.Derive()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &config, nil c.Wiring()
return &c, nil
} }
// Derive generates data that is derived from various values provided in // Derive generates data that is derived from various values provided in
@ -459,8 +250,8 @@ func (config *Dendrite) Derive() error {
// TODO: Add email auth type // TODO: Add email auth type
// TODO: Add MSISDN auth type // TODO: Add MSISDN auth type
if config.Matrix.RecaptchaEnabled { if config.ClientAPI.RecaptchaEnabled {
config.Derived.Registration.Params[authtypes.LoginTypeRecaptcha] = map[string]string{"public_key": config.Matrix.RecaptchaPublicKey} config.Derived.Registration.Params[authtypes.LoginTypeRecaptcha] = map[string]string{"public_key": config.ClientAPI.RecaptchaPublicKey}
config.Derived.Registration.Flows = append(config.Derived.Registration.Flows, config.Derived.Registration.Flows = append(config.Derived.Registration.Flows,
authtypes.Flow{Stages: []authtypes.LoginType{authtypes.LoginTypeRecaptcha}}) authtypes.Flow{Stages: []authtypes.LoginType{authtypes.LoginTypeRecaptcha}})
} else { } else {
@ -469,44 +260,65 @@ func (config *Dendrite) Derive() error {
} }
// Load application service configuration files // Load application service configuration files
if err := loadAppServices(config); err != nil { //if err := loadAppServices(config); err != nil {
return err // return err
} //}
return nil return nil
} }
// SetDefaults sets default config values if they are not explicitly set. // SetDefaults sets default config values if they are not explicitly set.
func (config *Dendrite) SetDefaults() { func (c *Dendrite) Defaults() {
if config.Matrix.KeyValidityPeriod == 0 { c.Version = 1
config.Matrix.KeyValidityPeriod = 24 * time.Hour
}
if config.Matrix.TrustedIDServers == nil { c.Global.Defaults()
config.Matrix.TrustedIDServers = []string{} c.ClientAPI.Defaults()
} c.CurrentStateServer.Defaults()
c.EDUServer.Defaults()
c.FederationAPI.Defaults()
c.FederationSender.Defaults()
c.KeyServer.Defaults()
c.MediaAPI.Defaults()
c.RoomServer.Defaults()
c.ServerKeyAPI.Defaults()
c.SyncAPI.Defaults()
c.UserAPI.Defaults()
c.AppServiceAPI.Defaults()
if config.Matrix.FederationMaxRetries == 0 { c.Wiring()
config.Matrix.FederationMaxRetries = 16 }
}
if config.Media.MaxThumbnailGenerators == 0 { func (c *Dendrite) Verify(configErrs *configErrors) {
config.Media.MaxThumbnailGenerators = 10 type verifiable interface {
Verify(configErrs *configErrors)
} }
for _, c := range []verifiable{
if config.Media.MaxFileSizeBytes == nil { &c.Global, &c.ClientAPI, &c.CurrentStateServer,
defaultMaxFileSizeBytes := FileSizeBytes(10485760) &c.EDUServer, &c.FederationAPI, &c.FederationSender,
config.Media.MaxFileSizeBytes = &defaultMaxFileSizeBytes &c.KeyServer, &c.MediaAPI, &c.RoomServer,
&c.ServerKeyAPI, &c.SyncAPI, &c.UserAPI,
&c.AppServiceAPI,
} {
c.Verify(configErrs)
} }
}
if config.Database.MaxIdleConns == 0 { func (c *Dendrite) Wiring() {
config.Database.MaxIdleConns = 2 c.ClientAPI.Matrix = &c.Global
} c.CurrentStateServer.Matrix = &c.Global
c.EDUServer.Matrix = &c.Global
if config.Database.MaxOpenConns == 0 { c.FederationAPI.Matrix = &c.Global
config.Database.MaxOpenConns = 100 c.FederationSender.Matrix = &c.Global
} c.KeyServer.Matrix = &c.Global
c.MediaAPI.Matrix = &c.Global
c.RoomServer.Matrix = &c.Global
c.ServerKeyAPI.Matrix = &c.Global
c.SyncAPI.Matrix = &c.Global
c.UserAPI.Matrix = &c.Global
c.AppServiceAPI.Matrix = &c.Global
c.ClientAPI.Derived = &c.Derived
c.AppServiceAPI.Derived = &c.Derived
} }
// Error returns a string detailing how many errors were contained within a // Error returns a string detailing how many errors were contained within a
@ -553,88 +365,6 @@ func checkPositive(configErrs *configErrors, key string, value int64) {
} }
} }
// checkTurn verifies the parameters turn.* are valid.
func (config *Dendrite) checkTurn(configErrs *configErrors) {
value := config.TURN.UserLifetime
if value != "" {
if _, err := time.ParseDuration(value); err != nil {
configErrs.Add(fmt.Sprintf("invalid duration for config key %q: %s", "turn.turn_user_lifetime", value))
}
}
}
// checkMatrix verifies the parameters matrix.* are valid.
func (config *Dendrite) checkMatrix(configErrs *configErrors) {
checkNotEmpty(configErrs, "matrix.server_name", string(config.Matrix.ServerName))
checkNotEmpty(configErrs, "matrix.private_key", string(config.Matrix.PrivateKeyPath))
checkNotZero(configErrs, "matrix.federation_certificates", int64(len(config.Matrix.FederationCertificatePaths)))
if config.Matrix.RecaptchaEnabled {
checkNotEmpty(configErrs, "matrix.recaptcha_public_key", string(config.Matrix.RecaptchaPublicKey))
checkNotEmpty(configErrs, "matrix.recaptcha_private_key", string(config.Matrix.RecaptchaPrivateKey))
checkNotEmpty(configErrs, "matrix.recaptcha_siteverify_api", string(config.Matrix.RecaptchaSiteVerifyAPI))
}
}
// checkMedia verifies the parameters media.* are valid.
func (config *Dendrite) checkMedia(configErrs *configErrors) {
checkNotEmpty(configErrs, "media.base_path", string(config.Media.BasePath))
checkPositive(configErrs, "media.max_file_size_bytes", int64(*config.Media.MaxFileSizeBytes))
checkPositive(configErrs, "media.max_thumbnail_generators", int64(config.Media.MaxThumbnailGenerators))
for i, size := range config.Media.ThumbnailSizes {
checkPositive(configErrs, fmt.Sprintf("media.thumbnail_sizes[%d].width", i), int64(size.Width))
checkPositive(configErrs, fmt.Sprintf("media.thumbnail_sizes[%d].height", i), int64(size.Height))
}
}
// checkKafka verifies the parameters kafka.* and the related
// database.naffka are valid.
func (config *Dendrite) checkKafka(configErrs *configErrors, monolithic bool) {
if config.Kafka.UseNaffka {
if !monolithic {
configErrs.Add(fmt.Sprintf("naffka can only be used in a monolithic server"))
}
checkNotEmpty(configErrs, "database.naffka", string(config.Database.Naffka))
} else {
// If we aren't using naffka then we need to have at least one kafka
// server to talk to.
checkNotZero(configErrs, "kafka.addresses", int64(len(config.Kafka.Addresses)))
}
checkNotEmpty(configErrs, "kafka.topics.output_room_event", string(config.Kafka.Topics.OutputRoomEvent))
checkNotEmpty(configErrs, "kafka.topics.output_client_data", string(config.Kafka.Topics.OutputClientData))
checkNotEmpty(configErrs, "kafka.topics.output_typing_event", string(config.Kafka.Topics.OutputTypingEvent))
checkNotEmpty(configErrs, "kafka.topics.output_send_to_device_event", string(config.Kafka.Topics.OutputSendToDeviceEvent))
checkNotEmpty(configErrs, "kafka.topics.output_key_change_event", string(config.Kafka.Topics.OutputKeyChangeEvent))
}
// checkDatabase verifies the parameters database.* are valid.
func (config *Dendrite) checkDatabase(configErrs *configErrors) {
checkNotEmpty(configErrs, "database.account", string(config.Database.Account))
checkNotEmpty(configErrs, "database.device", string(config.Database.Device))
checkNotEmpty(configErrs, "database.server_key", string(config.Database.ServerKey))
checkNotEmpty(configErrs, "database.media_api", string(config.Database.MediaAPI))
checkNotEmpty(configErrs, "database.sync_api", string(config.Database.SyncAPI))
checkNotEmpty(configErrs, "database.room_server", string(config.Database.RoomServer))
checkNotEmpty(configErrs, "database.current_state", string(config.Database.CurrentState))
checkNotEmpty(configErrs, "database.e2e_key", string(config.Database.E2EKey))
}
// checkListen verifies the parameters listen.* are valid.
func (config *Dendrite) checkListen(configErrs *configErrors) {
checkNotEmpty(configErrs, "listen.media_api", string(config.Listen.MediaAPI))
checkNotEmpty(configErrs, "listen.client_api", string(config.Listen.ClientAPI))
checkNotEmpty(configErrs, "listen.federation_api", string(config.Listen.FederationAPI))
checkNotEmpty(configErrs, "listen.sync_api", string(config.Listen.SyncAPI))
checkNotEmpty(configErrs, "listen.room_server", string(config.Listen.RoomServer))
checkNotEmpty(configErrs, "listen.edu_server", string(config.Listen.EDUServer))
checkNotEmpty(configErrs, "listen.server_key_api", string(config.Listen.EDUServer))
checkNotEmpty(configErrs, "listen.user_api", string(config.Listen.UserAPI))
checkNotEmpty(configErrs, "listen.current_state_server", string(config.Listen.CurrentState))
checkNotEmpty(configErrs, "listen.key_server", string(config.Listen.KeyServer))
}
// checkLogging verifies the parameters logging.* are valid. // checkLogging verifies the parameters logging.* are valid.
func (config *Dendrite) checkLogging(configErrs *configErrors) { func (config *Dendrite) checkLogging(configErrs *configErrors) {
for _, logrusHook := range config.Logging { for _, logrusHook := range config.Logging {
@ -645,7 +375,7 @@ func (config *Dendrite) checkLogging(configErrs *configErrors) {
// check returns an error type containing all errors found within the config // check returns an error type containing all errors found within the config
// file. // file.
func (config *Dendrite) check(monolithic bool) error { func (config *Dendrite) check(_ bool) error { // monolithic
var configErrs configErrors var configErrs configErrors
if config.Version != Version { if config.Version != Version {
@ -655,17 +385,8 @@ func (config *Dendrite) check(monolithic bool) error {
return configErrs return configErrs
} }
config.checkMatrix(&configErrs)
config.checkMedia(&configErrs)
config.checkTurn(&configErrs)
config.checkKafka(&configErrs, monolithic)
config.checkDatabase(&configErrs)
config.checkLogging(&configErrs) config.checkLogging(&configErrs)
if !monolithic {
config.checkListen(&configErrs)
}
// Due to how Golang manages its interface types, this condition is not redundant. // Due to how Golang manages its interface types, this condition is not redundant.
// In order to get the proper behaviour, it is necessary to return an explicit nil // In order to get the proper behaviour, it is necessary to return an explicit nil
// and not a nil configErrors. // and not a nil configErrors.
@ -734,7 +455,7 @@ func (config *Dendrite) AppServiceURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.AppServiceAPI) return "http://" + string(config.AppServiceAPI.Listen)
} }
// RoomServerURL returns an HTTP URL for where the roomserver is listening. // RoomServerURL returns an HTTP URL for where the roomserver is listening.
@ -743,7 +464,7 @@ func (config *Dendrite) RoomServerURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.RoomServer) return "http://" + string(config.RoomServer.Listen)
} }
// UserAPIURL returns an HTTP URL for where the userapi is listening. // UserAPIURL returns an HTTP URL for where the userapi is listening.
@ -752,7 +473,7 @@ func (config *Dendrite) UserAPIURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.UserAPI) return "http://" + string(config.UserAPI.Listen)
} }
// CurrentStateAPIURL returns an HTTP URL for where the currentstateserver is listening. // CurrentStateAPIURL returns an HTTP URL for where the currentstateserver is listening.
@ -761,7 +482,7 @@ func (config *Dendrite) CurrentStateAPIURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.CurrentState) return "http://" + string(config.CurrentStateServer.Listen)
} }
// EDUServerURL returns an HTTP URL for where the EDU server is listening. // EDUServerURL returns an HTTP URL for where the EDU server is listening.
@ -770,7 +491,7 @@ func (config *Dendrite) EDUServerURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.EDUServer) return "http://" + string(config.EDUServer.Listen)
} }
// FederationSenderURL returns an HTTP URL for where the federation sender is listening. // FederationSenderURL returns an HTTP URL for where the federation sender is listening.
@ -779,7 +500,7 @@ func (config *Dendrite) FederationSenderURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.FederationSender) return "http://" + string(config.FederationSender.Listen)
} }
// ServerKeyAPIURL returns an HTTP URL for where the server key API is listening. // ServerKeyAPIURL returns an HTTP URL for where the server key API is listening.
@ -788,7 +509,7 @@ func (config *Dendrite) ServerKeyAPIURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.ServerKeyAPI) return "http://" + string(config.ServerKeyAPI.Listen)
} }
// KeyServerURL returns an HTTP URL for where the key server is listening. // KeyServerURL returns an HTTP URL for where the key server is listening.
@ -797,7 +518,7 @@ func (config *Dendrite) KeyServerURL() string {
// If we support HTTPS we need to think of a practical way to do certificate validation. // If we support HTTPS we need to think of a practical way to do certificate validation.
// People setting up servers shouldn't need to get a certificate valid for the public // People setting up servers shouldn't need to get a certificate valid for the public
// internet for an internal API. // internet for an internal API.
return "http://" + string(config.Listen.KeyServer) return "http://" + string(config.KeyServer.Listen)
} }
// SetupTracing configures the opentracing using the supplied configuration. // SetupTracing configures the opentracing using the supplied configuration.
@ -812,33 +533,6 @@ func (config *Dendrite) SetupTracing(serviceName string) (closer io.Closer, err
) )
} }
// MaxIdleConns returns maximum idle connections to the DB
func (config Dendrite) MaxIdleConns() int {
return config.Database.MaxIdleConns
}
// MaxOpenConns returns maximum open connections to the DB
func (config Dendrite) MaxOpenConns() int {
return config.Database.MaxOpenConns
}
// ConnMaxLifetime returns maximum amount of time a connection may be reused
func (config Dendrite) ConnMaxLifetime() time.Duration {
return time.Duration(config.Database.ConnMaxLifetimeSec) * time.Second
}
// DbProperties functions return properties used by database/sql/DB
type DbProperties interface {
MaxIdleConns() int
MaxOpenConns() int
ConnMaxLifetime() time.Duration
}
// DbProperties returns cfg as a DbProperties interface
func (config Dendrite) DbProperties() DbProperties {
return config
}
// logrusLogger is a small wrapper that implements jaeger.Logger using logrus. // logrusLogger is a small wrapper that implements jaeger.Logger using logrus.
type logrusLogger struct { type logrusLogger struct {
l *logrus.Logger l *logrus.Logger

View file

@ -25,6 +25,32 @@ import (
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
type AppServiceAPI struct {
Matrix *Global `yaml:"-"`
Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
ConfigFiles []string `yaml:"config_files"`
}
func (c *AppServiceAPI) Defaults() {
c.Listen = "localhost:7777"
c.Bind = "localhost:7777"
c.Database = "file:appservice.db"
c.DatabaseOptions.Defaults()
}
func (c *AppServiceAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "app_service_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "app_service_api.bind", string(c.Bind))
checkNotEmpty(configErrs, "app_service_api.database", string(c.Database))
}
// ApplicationServiceNamespace is the namespace that a specific application // ApplicationServiceNamespace is the namespace that a specific application
// service has management over. // service has management over.
type ApplicationServiceNamespace struct { type ApplicationServiceNamespace struct {
@ -132,8 +158,8 @@ func (a *ApplicationService) IsInterestedInRoomAlias(
// loadAppServices iterates through all application service config files // loadAppServices iterates through all application service config files
// and loads their data into the config object for later access. // and loads their data into the config object for later access.
func loadAppServices(config *Dendrite) error { func loadAppServices(config *AppServiceAPI, derived *Derived) error {
for _, configPath := range config.ApplicationServices.ConfigFiles { for _, configPath := range config.ConfigFiles {
// Create a new application service with default options // Create a new application service with default options
appservice := ApplicationService{ appservice := ApplicationService{
RateLimited: true, RateLimited: true,
@ -157,26 +183,26 @@ func loadAppServices(config *Dendrite) error {
} }
// Append the parsed application service to the global config // Append the parsed application service to the global config
config.Derived.ApplicationServices = append( derived.ApplicationServices = append(
config.Derived.ApplicationServices, appservice, derived.ApplicationServices, appservice,
) )
} }
// Check for any errors in the loaded application services // Check for any errors in the loaded application services
return checkErrors(config) return checkErrors(config, derived)
} }
// 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(cfg *Dendrite) (err error) { func setupRegexps(cfg *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
// If an application service's regex is marked as exclusive, add // If an application service's regex is marked as exclusive, add
// 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 cfg.Derived.ApplicationServices { for _, appservice := range derived.ApplicationServices {
for key, namespaceSlice := range appservice.NamespaceMap { for key, namespaceSlice := range appservice.NamespaceMap {
switch key { switch key {
case "users": case "users":
@ -204,10 +230,10 @@ func setupRegexps(cfg *Dendrite) (err error) {
} }
// Store compiled Regex // Store compiled Regex
if cfg.Derived.ExclusiveApplicationServicesUsernameRegexp, err = regexp.Compile(exclusiveUsernames); err != nil { if derived.ExclusiveApplicationServicesUsernameRegexp, err = regexp.Compile(exclusiveUsernames); err != nil {
return err return err
} }
if cfg.Derived.ExclusiveApplicationServicesAliasRegexp, err = regexp.Compile(exclusiveAliases); err != nil { if derived.ExclusiveApplicationServicesAliasRegexp, err = regexp.Compile(exclusiveAliases); err != nil {
return err return err
} }
@ -234,7 +260,7 @@ func appendExclusiveNamespaceRegexs(
// checkErrors checks for any configuration errors amongst the loaded // checkErrors checks for any configuration errors amongst the loaded
// application services according to the application service spec. // application services according to the application service spec.
func checkErrors(config *Dendrite) (err error) { func checkErrors(config *AppServiceAPI, derived *Derived) (err error) {
var idMap = make(map[string]bool) var idMap = make(map[string]bool)
var tokenMap = make(map[string]bool) var tokenMap = make(map[string]bool)
@ -242,7 +268,7 @@ func checkErrors(config *Dendrite) (err error) {
groupIDRegexp := regexp.MustCompile(`\+.*:.*`) groupIDRegexp := regexp.MustCompile(`\+.*:.*`)
// Check each application service for any config errors // Check each application service for any config errors
for _, appservice := range config.Derived.ApplicationServices { for _, appservice := range derived.ApplicationServices {
// Namespace-related checks // Namespace-related checks
for key, namespaceSlice := range appservice.NamespaceMap { for key, namespaceSlice := range appservice.NamespaceMap {
for _, namespace := range namespaceSlice { for _, namespace := range namespaceSlice {
@ -284,7 +310,7 @@ func checkErrors(config *Dendrite) (err error) {
} }
} }
return setupRegexps(config) return setupRegexps(config, derived)
} }
// validateNamespace returns nil or an error based on whether a given // validateNamespace returns nil or an error based on whether a given

View file

@ -0,0 +1,87 @@
package config
import (
"fmt"
"time"
)
type ClientAPI struct {
Matrix *Global `yaml:"-"`
Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// If set, allows registration by anyone who also has the shared
// secret, even if registration is otherwise disabled.
RegistrationSharedSecret string `yaml:"registration_shared_secret"`
// This Home Server's ReCAPTCHA public key.
RecaptchaPublicKey string `yaml:"recaptcha_public_key"`
// This Home Server's ReCAPTCHA private key.
RecaptchaPrivateKey string `yaml:"recaptcha_private_key"`
// Boolean stating whether catpcha registration is enabled
// and required
RecaptchaEnabled bool `yaml:"enable_registration_captcha"`
// Secret used to bypass the captcha registration entirely
RecaptchaBypassSecret string `yaml:"captcha_bypass_secret"`
// HTTP API endpoint used to verify whether the captcha response
// was successful
RecaptchaSiteVerifyAPI string `yaml:"recaptcha_siteverify_api"`
// If set disables new users from registering (except via shared
// secrets)
RegistrationDisabled bool `yaml:"registration_disabled"`
// TURN options
TURN TURN `yaml:"turn"`
}
func (c *ClientAPI) Defaults() {
c.Listen = "localhost:7771"
c.Bind = "localhost:7771"
c.RegistrationSharedSecret = ""
c.RecaptchaPublicKey = ""
c.RecaptchaPrivateKey = ""
c.RecaptchaEnabled = false
c.RecaptchaBypassSecret = ""
c.RecaptchaSiteVerifyAPI = ""
c.RegistrationDisabled = false
}
func (c *ClientAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "client_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "client_api.bind", string(c.Bind))
if c.RecaptchaEnabled {
checkNotEmpty(configErrs, "client_api.recaptcha_public_key", string(c.RecaptchaPublicKey))
checkNotEmpty(configErrs, "client_api.recaptcha_private_key", string(c.RecaptchaPrivateKey))
checkNotEmpty(configErrs, "client_api.recaptcha_siteverify_api", string(c.RecaptchaSiteVerifyAPI))
}
c.TURN.Verify(configErrs)
}
type TURN struct {
// TODO Guest Support
// Whether or not guests can request TURN credentials
// AllowGuests bool `yaml:"turn_allow_guests"`
// How long the authorization should last
UserLifetime string `yaml:"turn_user_lifetime"`
// The list of TURN URIs to pass to clients
URIs []string `yaml:"turn_uris"`
// Authorization via Shared Secret
// The shared secret from coturn
SharedSecret string `yaml:"turn_shared_secret"`
// Authorization via Static Username & Password
// Hardcoded Username and Password
Username string `yaml:"turn_username"`
Password string `yaml:"turn_password"`
}
func (c *TURN) Verify(configErrs *configErrors) {
value := c.UserLifetime
if value != "" {
if _, err := time.ParseDuration(value); err != nil {
configErrs.Add(fmt.Sprintf("invalid duration for config key %q: %s", "client_api.turn.turn_user_lifetime", value))
}
}
}

View file

@ -0,0 +1,26 @@
package config
type CurrentStateServer struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// The CurrentState database stores the current state of all rooms.
// It is accessed by the CurrentStateServer.
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
}
func (c *CurrentStateServer) Defaults() {
c.Listen = "localhost:7782"
c.Bind = "localhost:7782"
c.Database = "file:currentstate.db"
c.DatabaseOptions.Defaults()
}
func (c *CurrentStateServer) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "current_state_server.listen", string(c.Listen))
checkNotEmpty(configErrs, "current_state_server.bind", string(c.Bind))
checkNotEmpty(configErrs, "current_state_server.database", string(c.Database))
}

View file

@ -0,0 +1,18 @@
package config
type EDUServer struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
}
func (c *EDUServer) Defaults() {
c.Listen = "localhost:7778"
c.Bind = "localhost:7778"
}
func (c *EDUServer) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "edu_server.listen", string(c.Listen))
checkNotEmpty(configErrs, "edu_server.bind", string(c.Bind))
}

View file

@ -0,0 +1,32 @@
package config
import "github.com/matrix-org/gomatrixserverlib"
type FederationAPI struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// List of paths to X509 certificates used by the external federation listeners.
// These are used to calculate the TLS fingerprints to publish for this server.
// Other matrix servers talking to this server will expect the x509 certificate
// to match one of these certificates.
// The certificates should be in PEM format.
FederationCertificatePaths []Path `yaml:"federation_certificates"`
// A list of SHA256 TLS fingerprints for the X509 certificates used by the
// federation listener for this server.
TLSFingerPrints []gomatrixserverlib.TLSFingerprint `yaml:"-"`
}
func (c *FederationAPI) Defaults() {
c.Listen = "localhost:7772"
c.Bind = "localhost:7772"
}
func (c *FederationAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "federation_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "federation_api.bind", string(c.Bind))
checkNotZero(configErrs, "federation_api.federation_certificates", int64(len(c.FederationCertificatePaths)))
}

View file

@ -0,0 +1,55 @@
package config
type FederationSender struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// The FederationSender database stores information used by the FederationSender
// It is only accessed by the FederationSender.
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
// Federation failure threshold. How many consecutive failures that we should
// tolerate when sending federation requests to a specific server. The backoff
// is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds, etc.
// The default value is 16 if not specified, which is circa 18 hours.
FederationMaxRetries uint32 `yaml:"federation_max_retries"`
Proxy Proxy `yaml:"proxy"`
}
func (c *FederationSender) Defaults() {
c.Listen = "localhost:7775"
c.Bind = "localhost:7775"
c.Database = "file:federationsender.db"
c.DatabaseOptions.Defaults()
c.FederationMaxRetries = 16
}
func (c *FederationSender) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "federation_sender.listen", string(c.Listen))
checkNotEmpty(configErrs, "federation_sender.bind", string(c.Bind))
checkNotEmpty(configErrs, "federation_sender.database", string(c.Database))
}
// The config for setting a proxy to use for server->server requests
type Proxy struct {
// The protocol for the proxy (http / https / socks5)
Protocol string `yaml:"protocol"`
// The host where the proxy is listening
Host string `yaml:"host"`
// The port on which the proxy is listening
Port uint16 `yaml:"port"`
}
func (c *Proxy) Defaults() {
c.Protocol = ""
c.Host = ""
c.Port = 0
}
func (c *Proxy) Verify(configErrs *configErrors) {
}

View file

@ -0,0 +1,174 @@
package config
import (
"math/rand"
"time"
"github.com/matrix-org/gomatrixserverlib"
"golang.org/x/crypto/ed25519"
)
type Global struct {
// The name of the server. This is usually the domain name, e.g 'matrix.org', 'localhost'.
ServerName gomatrixserverlib.ServerName `yaml:"server_name"`
// Path to the private key which will be used to sign requests and events.
PrivateKeyPath Path `yaml:"private_key"`
// The private key which will be used to sign requests and events.
PrivateKey ed25519.PrivateKey `yaml:"-"`
// An arbitrary string used to uniquely identify the PrivateKey. Must start with the
// prefix "ed25519:".
KeyID gomatrixserverlib.KeyID `yaml:"-"`
// How long a remote server can cache our server key for before requesting it again.
// Increasing this number will reduce the number of requests made by remote servers
// for our key, but increases the period a compromised key will be considered valid
// by remote servers.
// Defaults to 24 hours.
KeyValidityPeriod time.Duration `yaml:"key_validity_period"`
// List of domains that the server will trust as identity servers to
// verify third-party identifiers.
// Defaults to an empty array.
TrustedIDServers []string `yaml:"trusted_third_party_id_servers"`
// Kafka/Naffka configuration
Kafka Kafka `yaml:"kafka"`
// Metrics configuration
Metrics Metrics `yaml:"metrics"`
}
func (c *Global) Defaults() {
c.ServerName = "localhost"
c.PrivateKeyPath = "matrix.pem"
_, c.PrivateKey, _ = ed25519.GenerateKey(rand.New(rand.NewSource(0)))
c.KeyID = "ed25519:auto"
c.KeyValidityPeriod = time.Hour * 24 * 7
c.Kafka.Defaults()
c.Metrics.Defaults()
}
func (c *Global) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "global.server_name", string(c.ServerName))
checkNotEmpty(configErrs, "global.private_key", string(c.PrivateKeyPath))
c.Kafka.Verify(configErrs)
c.Metrics.Verify(configErrs)
}
type Kafka struct {
// A list of kafka addresses to connect to.
Addresses []string `yaml:"addresses"`
// Whether to use naffka instead of kafka.
// Naffka can only be used when running dendrite as a single monolithic server.
// Kafka can be used both with a monolithic server and when running the
// components as separate servers.
UseNaffka bool `yaml:"use_naffka"`
// The Naffka database is used internally by the naffka library, if used.
Database DataSource `yaml:"naffka_database"`
DatabaseOptions DatabaseOptions `yaml:"naffka_database_options"`
// The names of the topics to use when reading and writing from kafka.
Topics struct {
// Topic for roomserver/api.OutputRoomEvent events.
OutputRoomEvent Topic `yaml:"output_room_event"`
// Topic for sending account data from client API to sync API
OutputClientData Topic `yaml:"output_client_data"`
// Topic for eduserver/api.OutputTypingEvent events.
OutputTypingEvent Topic `yaml:"output_typing_event"`
// Topic for eduserver/api.OutputSendToDeviceEvent events.
OutputSendToDeviceEvent Topic `yaml:"output_send_to_device_event"`
// Topic for keyserver when new device keys are added.
OutputKeyChangeEvent Topic `yaml:"output_key_change_event"`
}
}
func (c *Kafka) Defaults() {
c.UseNaffka = true
c.Database = DataSource("file:naffka.db")
c.DatabaseOptions.Defaults()
c.Topics.OutputRoomEvent = "OutputRoomEventTopic"
c.Topics.OutputClientData = "OutputClientDataTopic"
c.Topics.OutputTypingEvent = "OutputTypingEventTopic"
c.Topics.OutputSendToDeviceEvent = "OutputSendToDeviceEventTopic"
c.Topics.OutputKeyChangeEvent = "OutputKeyChangeEventTopic"
}
func (c *Kafka) Verify(configErrs *configErrors) {
if c.UseNaffka {
// TODO: monolithic check
/*
if !monolithic {
configErrs.Add(fmt.Sprintf("naffka can only be used in a monolithic server"))
}
*/
checkNotEmpty(configErrs, "global.kafka.database", string(c.Database))
} else {
// If we aren't using naffka then we need to have at least one kafka
// server to talk to.
checkNotZero(configErrs, "global.kafka.addresses", int64(len(c.Addresses)))
}
checkNotEmpty(configErrs, "global.kafka.topics.output_room_event", string(c.Topics.OutputRoomEvent))
checkNotEmpty(configErrs, "global.kafka.topics.output_client_data", string(c.Topics.OutputClientData))
checkNotEmpty(configErrs, "global.kafka.topics.output_typing_event", string(c.Topics.OutputTypingEvent))
checkNotEmpty(configErrs, "global.kafka.topics.output_send_to_device_event", string(c.Topics.OutputSendToDeviceEvent))
checkNotEmpty(configErrs, "global.kafka.topics.output_key_change_event", string(c.Topics.OutputKeyChangeEvent))
}
// The configuration to use for Prometheus metrics
type Metrics struct {
// Whether or not the metrics are enabled
Enabled bool `yaml:"enabled"`
// Use BasicAuth for Authorization
BasicAuth struct {
// Authorization via Static Username & Password
// Hardcoded Username and Password
Username string `yaml:"username"`
Password string `yaml:"password"`
} `yaml:"basic_auth"`
}
func (c *Metrics) Defaults() {
c.Enabled = false
c.BasicAuth.Username = "metrics"
c.BasicAuth.Password = "metrics"
}
func (c *Metrics) Verify(configErrs *configErrors) {
}
type DatabaseOptions struct {
// Maximum open connections to the DB (0 = use default, negative means unlimited)
MaxOpenConnections int `yaml:"database_max_open_conns"`
// Maximum idle connections to the DB (0 = use default, negative means unlimited)
MaxIdleConnections int `yaml:"database_max_idle_conns"`
// maximum amount of time (in seconds) a connection may be reused (<= 0 means unlimited)
ConnMaxLifetimeSeconds int `yaml:"database_conn_max_lifetime"`
}
func (c *DatabaseOptions) Defaults() {
c.MaxOpenConnections = 0
c.MaxIdleConnections = 0
c.ConnMaxLifetimeSeconds = -1
}
func (c *DatabaseOptions) Verify(configErrs *configErrors) {
}
// MaxIdleConns returns maximum idle connections to the DB
func (c DatabaseOptions) MaxIdleConns() int {
return c.MaxIdleConnections
}
// MaxOpenConns returns maximum open connections to the DB
func (c DatabaseOptions) MaxOpenConns() int {
return c.MaxOpenConnections
}
// ConnMaxLifetime returns maximum amount of time a connection may be reused
func (c DatabaseOptions) ConnMaxLifetime() time.Duration {
return time.Duration(c.ConnMaxLifetimeSeconds) * time.Second
}

View file

@ -0,0 +1,24 @@
package config
type KeyServer struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
}
func (c *KeyServer) Defaults() {
c.Listen = "localhost:7779"
c.Bind = "localhost:7779"
c.Database = "file:keyserver.db"
c.DatabaseOptions.Defaults()
}
func (c *KeyServer) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "key_server.listen", string(c.Listen))
checkNotEmpty(configErrs, "key_server.bind", string(c.Bind))
checkNotEmpty(configErrs, "key_server.database", string(c.Database))
}

View file

@ -0,0 +1,63 @@
package config
import (
"fmt"
)
type MediaAPI struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// The MediaAPI database stores information about files uploaded and downloaded
// by local users. It is only accessed by the MediaAPI.
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
// The base path to where the media files will be stored. May be relative or absolute.
BasePath Path `yaml:"base_path"`
// The absolute base path to where media files will be stored.
AbsBasePath Path `yaml:"-"`
// The maximum file size in bytes that is allowed to be stored on this server.
// Note: if max_file_size_bytes is set to 0, the size is unlimited.
// Note: if max_file_size_bytes is not set, it will default to 10485760 (10MB)
MaxFileSizeBytes *FileSizeBytes `yaml:"max_file_size_bytes,omitempty"`
// Whether to dynamically generate thumbnails on-the-fly if the requested resolution is not already generated
DynamicThumbnails bool `yaml:"dynamic_thumbnails"`
// The maximum number of simultaneous thumbnail generators. default: 10
MaxThumbnailGenerators int `yaml:"max_thumbnail_generators"`
// A list of thumbnail sizes to be pre-generated for downloaded remote / uploaded content
ThumbnailSizes []ThumbnailSize `yaml:"thumbnail_sizes"`
}
func (c *MediaAPI) Defaults() {
c.Listen = "localhost:7774"
c.Bind = "localhost:7774"
c.Database = "file:mediaapi.db"
c.DatabaseOptions.Defaults()
defaultMaxFileSizeBytes := FileSizeBytes(10485760)
c.MaxFileSizeBytes = &defaultMaxFileSizeBytes
c.MaxThumbnailGenerators = 10
}
func (c *MediaAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "media_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "media_api.bind", string(c.Bind))
checkNotEmpty(configErrs, "media_api.database", string(c.Database))
checkNotEmpty(configErrs, "media_api.base_path", string(c.BasePath))
checkPositive(configErrs, "media_api.max_file_size_bytes", int64(*c.MaxFileSizeBytes))
checkPositive(configErrs, "media_api.max_thumbnail_generators", int64(c.MaxThumbnailGenerators))
for i, size := range c.ThumbnailSizes {
checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].width", i), int64(size.Width))
checkPositive(configErrs, fmt.Sprintf("media_api.thumbnail_sizes[%d].height", i), int64(size.Height))
}
}

View file

@ -0,0 +1,24 @@
package config
type RoomServer struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
}
func (c *RoomServer) Defaults() {
c.Listen = "localhost:7770"
c.Bind = "localhost:7770"
c.Database = "file:roomserver.db"
c.DatabaseOptions.Defaults()
}
func (c *RoomServer) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "room_server.listen", string(c.Listen))
checkNotEmpty(configErrs, "room_server.bind", string(c.Bind))
checkNotEmpty(configErrs, "room_server.database", string(c.Database))
}

View file

@ -0,0 +1,30 @@
package config
type ServerKeyAPI struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// The ServerKey database caches the public keys of remote servers.
// It may be accessed by the FederationAPI, the ClientAPI, and the MediaAPI.
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
// Perspective keyservers, to use as a backup when direct key fetch
// requests don't succeed
KeyPerspectives KeyPerspectives `yaml:"key_perspectives"`
}
func (c *ServerKeyAPI) Defaults() {
c.Listen = "localhost:7780"
c.Bind = "localhost:7780"
c.Database = "file:serverkeyapi.db"
c.DatabaseOptions.Defaults()
}
func (c *ServerKeyAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "server_key_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "server_key_api.bind", string(c.Bind))
checkNotEmpty(configErrs, "server_key_api.database", string(c.Database))
}

View file

@ -0,0 +1,24 @@
package config
type SyncAPI struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
Database DataSource `yaml:"database"`
DatabaseOptions DatabaseOptions `yaml:"database_options"`
}
func (c *SyncAPI) Defaults() {
c.Listen = "localhost:7773"
c.Bind = "localhost:7773"
c.Database = "file:syncapi.db"
c.DatabaseOptions.Defaults()
}
func (c *SyncAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "sync_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "sync_api.bind", string(c.Bind))
checkNotEmpty(configErrs, "sync_api.database", string(c.Database))
}

View file

@ -0,0 +1,33 @@
package config
type UserAPI struct {
Matrix *Global `yaml:"-"`
Listen Address `yaml:"listen"`
Bind Address `yaml:"bind"`
// The Account database stores the login details and account information
// for local users. It is accessed by the UserAPI.
AccountDatabase DataSource `yaml:"account_database"`
AccountDatabaseOptions DatabaseOptions `yaml:"account_database_options"`
// The Device database stores session information for the devices of logged
// in local users. It is accessed by the UserAPI.
DeviceDatabase DataSource `yaml:"device_database"`
DeviceDatabaseOptions DatabaseOptions `yaml:"device_database_options"`
}
func (c *UserAPI) Defaults() {
c.Listen = "localhost:7781"
c.Bind = "localhost:7781"
c.AccountDatabase = "file:userapi_accounts.db"
c.DeviceDatabase = "file:userapi_devices.db"
c.AccountDatabaseOptions.Defaults()
c.DeviceDatabaseOptions.Defaults()
}
func (c *UserAPI) Verify(configErrs *configErrors) {
checkNotEmpty(configErrs, "user_api.listen", string(c.Listen))
checkNotEmpty(configErrs, "user_api.bind", string(c.Bind))
checkNotEmpty(configErrs, "user_api.account_database", string(c.AccountDatabase))
checkNotEmpty(configErrs, "user_api.device_database", string(c.DeviceDatabase))
}

View file

@ -38,7 +38,7 @@ var ErrRoomNoExists = errors.New("Room does not exist")
// Returns an error if something else went wrong // Returns an error if something else went wrong
func BuildEvent( func BuildEvent(
ctx context.Context, ctx context.Context,
builder *gomatrixserverlib.EventBuilder, cfg *config.Dendrite, evTime time.Time, builder *gomatrixserverlib.EventBuilder, cfg *config.Global, evTime time.Time,
rsAPI api.RoomserverInternalAPI, queryRes *api.QueryLatestEventsAndStateResponse, rsAPI api.RoomserverInternalAPI, queryRes *api.QueryLatestEventsAndStateResponse,
) (*gomatrixserverlib.HeaderedEvent, error) { ) (*gomatrixserverlib.HeaderedEvent, error) {
if queryRes == nil { if queryRes == nil {
@ -52,8 +52,8 @@ func BuildEvent(
} }
event, err := builder.Build( event, err := builder.Build(
evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, evTime, cfg.ServerName, cfg.KeyID,
cfg.Matrix.PrivateKey, queryRes.RoomVersion, cfg.PrivateKey, queryRes.RoomVersion,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -234,7 +234,7 @@ func (f *FederationWakeups) Wakeup(ctx context.Context, origin gomatrixserverlib
} }
// SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics listener // SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics listener
func SetupHTTPAPI(servMux, publicApiMux, internalApiMux *mux.Router, cfg *config.Dendrite, enableHTTPAPIs bool) { func SetupHTTPAPI(servMux, publicApiMux, internalApiMux *mux.Router, cfg *config.Global, enableHTTPAPIs bool) {
if cfg.Metrics.Enabled { if cfg.Metrics.Enabled {
servMux.Handle("/metrics", WrapHandlerInBasicAuth(promhttp.Handler(), cfg.Metrics.BasicAuth)) servMux.Handle("/metrics", WrapHandlerInBasicAuth(promhttp.Handler(), cfg.Metrics.BasicAuth))
} }

View file

@ -16,7 +16,6 @@ package setup
import ( import (
"database/sql" "database/sql"
"fmt"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@ -96,7 +95,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, useHTTPAPIs boo
var kafkaConsumer sarama.Consumer var kafkaConsumer sarama.Consumer
var kafkaProducer sarama.SyncProducer var kafkaProducer sarama.SyncProducer
if cfg.Kafka.UseNaffka { if cfg.Global.Kafka.UseNaffka {
kafkaConsumer, kafkaProducer = setupNaffka(cfg) kafkaConsumer, kafkaProducer = setupNaffka(cfg)
} else { } else {
kafkaConsumer, kafkaProducer = setupKafka(cfg) kafkaConsumer, kafkaProducer = setupKafka(cfg)
@ -108,12 +107,15 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, useHTTPAPIs boo
} }
client := http.Client{Timeout: HTTPClientTimeout} client := http.Client{Timeout: HTTPClientTimeout}
if cfg.Proxy != nil { // TODO: fix this
client.Transport = &http.Transport{Proxy: http.ProxyURL(&url.URL{ /*
Scheme: cfg.Proxy.Protocol, if cfg.Proxy != nil {
Host: fmt.Sprintf("%s:%d", cfg.Proxy.Host, cfg.Proxy.Port), client.Transport = &http.Transport{Proxy: http.ProxyURL(&url.URL{
})} Scheme: cfg.Proxy.Protocol,
} Host: fmt.Sprintf("%s:%d", cfg.Proxy.Host, cfg.Proxy.Port),
})}
}
*/
// Ideally we would only use SkipClean on routes which we know can allow '/' but due to // Ideally we would only use SkipClean on routes which we know can allow '/' but due to
// https://github.com/gorilla/mux/issues/460 we have to attach this at the top router. // https://github.com/gorilla/mux/issues/460 we have to attach this at the top router.
@ -228,7 +230,7 @@ func (b *BaseDendrite) KeyServerHTTPClient() keyserverAPI.KeyInternalAPI {
// CreateDeviceDB creates a new instance of the device database. Should only be // CreateDeviceDB creates a new instance of the device database. Should only be
// called once per component. // called once per component.
func (b *BaseDendrite) CreateDeviceDB() devices.Database { func (b *BaseDendrite) CreateDeviceDB() devices.Database {
db, err := devices.NewDatabase(string(b.Cfg.Database.Device), b.Cfg.DbProperties(), b.Cfg.Matrix.ServerName) db, err := devices.NewDatabase(string(b.Cfg.UserAPI.DeviceDatabase), &b.Cfg.UserAPI.DeviceDatabaseOptions, b.Cfg.Global.ServerName)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to devices db") logrus.WithError(err).Panicf("failed to connect to devices db")
} }
@ -239,7 +241,7 @@ func (b *BaseDendrite) CreateDeviceDB() devices.Database {
// 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(string(b.Cfg.Database.Account), b.Cfg.DbProperties(), b.Cfg.Matrix.ServerName) db, err := accounts.NewDatabase(string(b.Cfg.UserAPI.AccountDatabase), &b.Cfg.UserAPI.AccountDatabaseOptions, b.Cfg.Global.ServerName)
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")
} }
@ -251,7 +253,7 @@ func (b *BaseDendrite) CreateAccountsDB() accounts.Database {
// once per component. // once per component.
func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient { func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient {
return gomatrixserverlib.NewFederationClient( return gomatrixserverlib.NewFederationClient(
b.Cfg.Matrix.ServerName, b.Cfg.Matrix.KeyID, b.Cfg.Matrix.PrivateKey, b.Cfg.Global.ServerName, b.Cfg.Global.KeyID, b.Cfg.Global.PrivateKey,
) )
} }
@ -276,7 +278,7 @@ func (b *BaseDendrite) SetupAndServeHTTP(bindaddr string, listenaddr string) {
b.BaseMux, b.BaseMux,
b.PublicAPIMux, b.PublicAPIMux,
b.InternalAPIMux, b.InternalAPIMux,
b.Cfg, &b.Cfg.Global,
b.UseHTTPAPIs, b.UseHTTPAPIs,
) )
serv.Handler = b.BaseMux serv.Handler = b.BaseMux
@ -292,12 +294,12 @@ func (b *BaseDendrite) SetupAndServeHTTP(bindaddr string, listenaddr string) {
// setupKafka creates kafka consumer/producer pair from the config. // setupKafka creates kafka consumer/producer pair from the config.
func setupKafka(cfg *config.Dendrite) (sarama.Consumer, sarama.SyncProducer) { func setupKafka(cfg *config.Dendrite) (sarama.Consumer, sarama.SyncProducer) {
consumer, err := sarama.NewConsumer(cfg.Kafka.Addresses, nil) consumer, err := sarama.NewConsumer(cfg.Global.Kafka.Addresses, nil)
if err != nil { if err != nil {
logrus.WithError(err).Panic("failed to start kafka consumer") logrus.WithError(err).Panic("failed to start kafka consumer")
} }
producer, err := sarama.NewSyncProducer(cfg.Kafka.Addresses, nil) producer, err := sarama.NewSyncProducer(cfg.Global.Kafka.Addresses, nil)
if err != nil { if err != nil {
logrus.WithError(err).Panic("failed to setup kafka producers") logrus.WithError(err).Panic("failed to setup kafka producers")
} }
@ -311,10 +313,10 @@ func setupNaffka(cfg *config.Dendrite) (sarama.Consumer, sarama.SyncProducer) {
var db *sql.DB var db *sql.DB
var naffkaDB *naffka.DatabaseImpl var naffkaDB *naffka.DatabaseImpl
uri, err := url.Parse(string(cfg.Database.Naffka)) uri, err := url.Parse(string(cfg.Global.Kafka.Database))
if err != nil || uri.Scheme == "file" { if err != nil || uri.Scheme == "file" {
var cs string var cs string
cs, err = sqlutil.ParseFileURI(string(cfg.Database.Naffka)) cs, err = sqlutil.ParseFileURI(string(cfg.Global.Kafka.Database))
if err != nil { if err != nil {
logrus.WithError(err).Panic("Failed to parse naffka database file URI") logrus.WithError(err).Panic("Failed to parse naffka database file URI")
} }
@ -328,7 +330,7 @@ func setupNaffka(cfg *config.Dendrite) (sarama.Consumer, sarama.SyncProducer) {
logrus.WithError(err).Panic("Failed to setup naffka database") logrus.WithError(err).Panic("Failed to setup naffka database")
} }
} else { } else {
db, err = sqlutil.Open("postgres", string(cfg.Database.Naffka), nil) db, err = sqlutil.Open("postgres", string(cfg.Global.Kafka.Database), nil)
if err != nil { if err != nil {
logrus.WithError(err).Panic("Failed to open naffka database") logrus.WithError(err).Panic("Failed to open naffka database")
} }

View file

@ -65,18 +65,18 @@ type Monolith struct {
// AddAllPublicRoutes attaches all public paths to the given router // AddAllPublicRoutes attaches all public paths to the given router
func (m *Monolith) AddAllPublicRoutes(publicMux *mux.Router) { func (m *Monolith) AddAllPublicRoutes(publicMux *mux.Router) {
clientapi.AddPublicRoutes( clientapi.AddPublicRoutes(
publicMux, m.Config, m.KafkaProducer, m.DeviceDB, m.AccountDB, publicMux, &m.Config.ClientAPI, m.KafkaProducer, m.DeviceDB, m.AccountDB,
m.FedClient, m.RoomserverAPI, m.FedClient, m.RoomserverAPI,
m.EDUInternalAPI, m.AppserviceAPI, m.StateAPI, transactions.New(), m.EDUInternalAPI, m.AppserviceAPI, m.StateAPI, transactions.New(),
m.FederationSenderAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider, m.FederationSenderAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider,
) )
federationapi.AddPublicRoutes( federationapi.AddPublicRoutes(
publicMux, m.Config, m.UserAPI, m.FedClient, publicMux, &m.Config.FederationAPI, m.UserAPI, m.FedClient,
m.KeyRing, m.RoomserverAPI, m.FederationSenderAPI, m.KeyRing, m.RoomserverAPI, m.FederationSenderAPI,
m.EDUInternalAPI, m.StateAPI, m.KeyAPI, m.EDUInternalAPI, m.StateAPI, m.KeyAPI,
) )
mediaapi.AddPublicRoutes(publicMux, m.Config, m.UserAPI, m.Client) mediaapi.AddPublicRoutes(publicMux, &m.Config.MediaAPI, m.UserAPI, m.Client)
syncapi.AddPublicRoutes( syncapi.AddPublicRoutes(
publicMux, m.KafkaConsumer, m.UserAPI, m.RoomserverAPI, m.FedClient, m.Config, publicMux, m.KafkaConsumer, m.UserAPI, m.RoomserverAPI, m.FedClient, &m.Config.SyncAPI,
) )
} }

View file

@ -37,17 +37,14 @@ func AddInternalRoutes(router *mux.Router, intAPI api.KeyInternalAPI) {
// NewInternalAPI returns a concerete implementation of the internal API. Callers // NewInternalAPI returns a concerete implementation of the internal API. Callers
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
func NewInternalAPI( func NewInternalAPI(
cfg *config.Dendrite, fedClient *gomatrixserverlib.FederationClient, userAPI userapi.UserInternalAPI, producer sarama.SyncProducer, cfg *config.KeyServer, fedClient *gomatrixserverlib.FederationClient, userAPI userapi.UserInternalAPI, producer sarama.SyncProducer,
) api.KeyInternalAPI { ) api.KeyInternalAPI {
db, err := storage.NewDatabase( db, err := storage.NewDatabase(string(cfg.Database), cfg.DatabaseOptions)
string(cfg.Database.E2EKey),
cfg.DbProperties(),
)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to key server database") logrus.WithError(err).Panicf("failed to connect to key server database")
} }
keyChangeProducer := &producers.KeyChange{ keyChangeProducer := &producers.KeyChange{
Topic: string(cfg.Kafka.Topics.OutputKeyChangeEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputKeyChangeEvent),
Producer: producer, Producer: producer,
} }
return &internal.KeyInternalAPI{ return &internal.KeyInternalAPI{

View file

@ -26,11 +26,11 @@ import (
// AddPublicRoutes sets up and registers HTTP handlers for the MediaAPI component. // AddPublicRoutes sets up and registers HTTP handlers for the MediaAPI component.
func AddPublicRoutes( func AddPublicRoutes(
router *mux.Router, cfg *config.Dendrite, router *mux.Router, cfg *config.MediaAPI,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
) { ) {
mediaDB, err := storage.Open(string(cfg.Database.MediaAPI), cfg.DbProperties()) mediaDB, err := storage.Open(string(cfg.Database), cfg.DatabaseOptions)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to media db") logrus.WithError(err).Panicf("failed to connect to media db")
} }

View file

@ -73,7 +73,7 @@ func Download(
req *http.Request, req *http.Request,
origin gomatrixserverlib.ServerName, origin gomatrixserverlib.ServerName,
mediaID types.MediaID, mediaID types.MediaID,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
activeRemoteRequests *types.ActiveRemoteRequests, activeRemoteRequests *types.ActiveRemoteRequests,
@ -203,7 +203,7 @@ func (r *downloadRequest) Validate() *util.JSONResponse {
func (r *downloadRequest) doDownload( func (r *downloadRequest) doDownload(
ctx context.Context, ctx context.Context,
w http.ResponseWriter, w http.ResponseWriter,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
activeRemoteRequests *types.ActiveRemoteRequests, activeRemoteRequests *types.ActiveRemoteRequests,
@ -233,9 +233,9 @@ func (r *downloadRequest) doDownload(
r.MediaMetadata = mediaMetadata r.MediaMetadata = mediaMetadata
} }
return r.respondFromLocalFile( return r.respondFromLocalFile(
ctx, w, cfg.Media.AbsBasePath, activeThumbnailGeneration, ctx, w, cfg.AbsBasePath, activeThumbnailGeneration,
cfg.Media.MaxThumbnailGenerators, db, cfg.MaxThumbnailGenerators, db,
cfg.Media.DynamicThumbnails, cfg.Media.ThumbnailSizes, cfg.DynamicThumbnails, cfg.ThumbnailSizes,
) )
} }
@ -514,7 +514,7 @@ func (r *downloadRequest) generateThumbnail(
func (r *downloadRequest) getRemoteFile( func (r *downloadRequest) getRemoteFile(
ctx context.Context, ctx context.Context,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
activeRemoteRequests *types.ActiveRemoteRequests, activeRemoteRequests *types.ActiveRemoteRequests,
activeThumbnailGeneration *types.ActiveThumbnailGeneration, activeThumbnailGeneration *types.ActiveThumbnailGeneration,
@ -550,9 +550,9 @@ func (r *downloadRequest) getRemoteFile(
// If we do not have a record, we need to fetch the remote file first and then respond from the local file // If we do not have a record, we need to fetch the remote file first and then respond from the local file
err := r.fetchRemoteFileAndStoreMetadata( err := r.fetchRemoteFileAndStoreMetadata(
ctx, client, ctx, client,
cfg.Media.AbsBasePath, *cfg.Media.MaxFileSizeBytes, db, cfg.AbsBasePath, *cfg.MaxFileSizeBytes, db,
cfg.Media.ThumbnailSizes, activeThumbnailGeneration, cfg.ThumbnailSizes, activeThumbnailGeneration,
cfg.Media.MaxThumbnailGenerators, cfg.MaxThumbnailGenerators,
) )
if err != nil { if err != nil {
return errors.Wrap(err, "error querying the database.") return errors.Wrap(err, "error querying the database.")

View file

@ -42,7 +42,7 @@ const pathPrefixV1 = "/media/v1" // TODO: remove when synapse is fixed
// nolint: gocyclo // nolint: gocyclo
func Setup( func Setup(
publicAPIMux *mux.Router, publicAPIMux *mux.Router,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
@ -81,7 +81,7 @@ func Setup(
func makeDownloadAPI( func makeDownloadAPI(
name string, name string,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
client *gomatrixserverlib.Client, client *gomatrixserverlib.Client,
activeRemoteRequests *types.ActiveRemoteRequests, activeRemoteRequests *types.ActiveRemoteRequests,

View file

@ -54,7 +54,7 @@ type uploadResponse struct {
// This implementation supports a configurable maximum file size limit in bytes. If a user tries to upload more than this, they will receive an error that their upload is too large. // This implementation supports a configurable maximum file size limit in bytes. If a user tries to upload more than this, they will receive an error that their upload is too large.
// Uploaded files are processed piece-wise to avoid DoS attacks which would starve the server of memory. // Uploaded files are processed piece-wise to avoid DoS attacks which would starve the server of memory.
// TODO: We should time out requests if they have not received any data within a configured timeout period. // TODO: We should time out requests if they have not received any data within a configured timeout period.
func Upload(req *http.Request, cfg *config.Dendrite, db storage.Database, activeThumbnailGeneration *types.ActiveThumbnailGeneration) util.JSONResponse { func Upload(req *http.Request, cfg *config.MediaAPI, db storage.Database, activeThumbnailGeneration *types.ActiveThumbnailGeneration) util.JSONResponse {
r, resErr := parseAndValidateRequest(req, cfg) r, resErr := parseAndValidateRequest(req, cfg)
if resErr != nil { if resErr != nil {
return *resErr return *resErr
@ -75,7 +75,7 @@ func Upload(req *http.Request, cfg *config.Dendrite, db storage.Database, active
// parseAndValidateRequest parses the incoming upload request to validate and extract // parseAndValidateRequest parses the incoming upload request to validate and extract
// all the metadata about the media being uploaded. // all the metadata about the media being uploaded.
// Returns either an uploadRequest or an error formatted as a util.JSONResponse // Returns either an uploadRequest or an error formatted as a util.JSONResponse
func parseAndValidateRequest(req *http.Request, cfg *config.Dendrite) (*uploadRequest, *util.JSONResponse) { func parseAndValidateRequest(req *http.Request, cfg *config.MediaAPI) (*uploadRequest, *util.JSONResponse) {
r := &uploadRequest{ r := &uploadRequest{
MediaMetadata: &types.MediaMetadata{ MediaMetadata: &types.MediaMetadata{
Origin: cfg.Matrix.ServerName, Origin: cfg.Matrix.ServerName,
@ -86,7 +86,7 @@ func parseAndValidateRequest(req *http.Request, cfg *config.Dendrite) (*uploadRe
Logger: util.GetLogger(req.Context()).WithField("Origin", cfg.Matrix.ServerName), Logger: util.GetLogger(req.Context()).WithField("Origin", cfg.Matrix.ServerName),
} }
if resErr := r.Validate(*cfg.Media.MaxFileSizeBytes); resErr != nil { if resErr := r.Validate(*cfg.MaxFileSizeBytes); resErr != nil {
return nil, resErr return nil, resErr
} }
@ -96,7 +96,7 @@ func parseAndValidateRequest(req *http.Request, cfg *config.Dendrite) (*uploadRe
func (r *uploadRequest) doUpload( func (r *uploadRequest) doUpload(
ctx context.Context, ctx context.Context,
reqReader io.Reader, reqReader io.Reader,
cfg *config.Dendrite, cfg *config.MediaAPI,
db storage.Database, db storage.Database,
activeThumbnailGeneration *types.ActiveThumbnailGeneration, activeThumbnailGeneration *types.ActiveThumbnailGeneration,
) *util.JSONResponse { ) *util.JSONResponse {
@ -110,10 +110,10 @@ func (r *uploadRequest) doUpload(
// method of deduplicating files to save storage, as well as a way to conduct // method of deduplicating files to save storage, as well as a way to conduct
// integrity checks on the file data in the repository. // integrity checks on the file data in the repository.
// Data is truncated to maxFileSizeBytes. Content-Length was reported as 0 < Content-Length <= maxFileSizeBytes so this is OK. // Data is truncated to maxFileSizeBytes. Content-Length was reported as 0 < Content-Length <= maxFileSizeBytes so this is OK.
hash, bytesWritten, tmpDir, err := fileutils.WriteTempFile(reqReader, *cfg.Media.MaxFileSizeBytes, cfg.Media.AbsBasePath) hash, bytesWritten, tmpDir, err := fileutils.WriteTempFile(reqReader, *cfg.MaxFileSizeBytes, cfg.AbsBasePath)
if err != nil { if err != nil {
r.Logger.WithError(err).WithFields(log.Fields{ r.Logger.WithError(err).WithFields(log.Fields{
"MaxFileSizeBytes": *cfg.Media.MaxFileSizeBytes, "MaxFileSizeBytes": *cfg.MaxFileSizeBytes,
}).Warn("Error while transferring file") }).Warn("Error while transferring file")
fileutils.RemoveDir(tmpDir, r.Logger) fileutils.RemoveDir(tmpDir, r.Logger)
return &util.JSONResponse{ return &util.JSONResponse{
@ -159,8 +159,8 @@ func (r *uploadRequest) doUpload(
} }
return r.storeFileAndMetadata( return r.storeFileAndMetadata(
ctx, tmpDir, cfg.Media.AbsBasePath, db, cfg.Media.ThumbnailSizes, ctx, tmpDir, cfg.AbsBasePath, db, cfg.ThumbnailSizes,
activeThumbnailGeneration, cfg.Media.MaxThumbnailGenerators, activeThumbnailGeneration, cfg.MaxThumbnailGenerators,
) )
} }

View file

@ -14,7 +14,7 @@ import (
// RoomserverInternalAPI is an implementation of api.RoomserverInternalAPI // RoomserverInternalAPI is an implementation of api.RoomserverInternalAPI
type RoomserverInternalAPI struct { type RoomserverInternalAPI struct {
DB storage.Database DB storage.Database
Cfg *config.Dendrite Cfg *config.RoomServer
Producer sarama.SyncProducer Producer sarama.SyncProducer
Cache caching.RoomVersionCache Cache caching.RoomVersionCache
ServerName gomatrixserverlib.ServerName ServerName gomatrixserverlib.ServerName

View file

@ -189,12 +189,12 @@ func (r *RoomserverInternalAPI) performJoinRoomByID(
// but everyone has since left. I suspect it does the wrong thing. // but everyone has since left. I suspect it does the wrong thing.
buildRes := api.QueryLatestEventsAndStateResponse{} buildRes := api.QueryLatestEventsAndStateResponse{}
event, err := eventutil.BuildEvent( event, err := eventutil.BuildEvent(
ctx, // the request context ctx, // the request context
&eb, // the template join event &eb, // the template join event
r.Cfg, // the server configuration r.Cfg.Matrix, // the server configuration
time.Now(), // the event timestamp to use time.Now(), // the event timestamp to use
r, // the roomserver API to use r, // the roomserver API to use
&buildRes, // the query response &buildRes, // the query response
) )
switch err { switch err {

View file

@ -99,12 +99,12 @@ func (r *RoomserverInternalAPI) performLeaveRoomByID(
// but everyone has since left. I suspect it does the wrong thing. // but everyone has since left. I suspect it does the wrong thing.
buildRes := api.QueryLatestEventsAndStateResponse{} buildRes := api.QueryLatestEventsAndStateResponse{}
event, err := eventutil.BuildEvent( event, err := eventutil.BuildEvent(
ctx, // the request context ctx, // the request context
&eb, // the template leave event &eb, // the template leave event
r.Cfg, // the server configuration r.Cfg.Matrix, // the server configuration
time.Now(), // the event timestamp to use time.Now(), // the event timestamp to use
r, // the roomserver API to use r, // the roomserver API to use
&buildRes, // the query response &buildRes, // the query response
) )
if err != nil { if err != nil {
return fmt.Errorf("eventutil.BuildEvent: %w", err) return fmt.Errorf("eventutil.BuildEvent: %w", err)

View file

@ -39,18 +39,20 @@ func NewInternalAPI(
keyRing gomatrixserverlib.JSONVerifier, keyRing gomatrixserverlib.JSONVerifier,
fedClient *gomatrixserverlib.FederationClient, fedClient *gomatrixserverlib.FederationClient,
) api.RoomserverInternalAPI { ) api.RoomserverInternalAPI {
roomserverDB, err := storage.Open(string(base.Cfg.Database.RoomServer), base.Cfg.DbProperties()) cfg := &base.Cfg.RoomServer
roomserverDB, err := storage.Open(string(cfg.Database), cfg.DatabaseOptions)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to room server db") logrus.WithError(err).Panicf("failed to connect to room server db")
} }
return &internal.RoomserverInternalAPI{ return &internal.RoomserverInternalAPI{
DB: roomserverDB, DB: roomserverDB,
Cfg: base.Cfg, Cfg: cfg,
Producer: base.KafkaProducer, Producer: base.KafkaProducer,
OutputRoomEventTopic: string(base.Cfg.Kafka.Topics.OutputRoomEvent), OutputRoomEventTopic: string(cfg.Matrix.Kafka.Topics.OutputRoomEvent),
Cache: base.Caches, Cache: base.Caches,
ServerName: base.Cfg.Matrix.ServerName, ServerName: cfg.Matrix.ServerName,
FedClient: fedClient, FedClient: fedClient,
KeyRing: keyRing, KeyRing: keyRing,
} }

View file

@ -94,13 +94,19 @@ func mustLoadEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []js
} }
func mustSendEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []json.RawMessage) (api.RoomserverInternalAPI, *dummyProducer, []gomatrixserverlib.HeaderedEvent) { func mustSendEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []json.RawMessage) (api.RoomserverInternalAPI, *dummyProducer, []gomatrixserverlib.HeaderedEvent) {
cfg := &config.Dendrite{} cfg := &config.Dendrite{
cfg.Database.RoomServer = roomserverDBFileURI Global: config.Global{
cfg.Kafka.Topics.OutputRoomEvent = "output_room_event" ServerName: testOrigin,
cfg.Matrix.ServerName = testOrigin Kafka: config.Kafka{
cfg.Kafka.UseNaffka = true UseNaffka: true,
},
},
RoomServer: config.RoomServer{},
}
cfg.RoomServer.Database = roomserverDBFileURI
cfg.Global.Kafka.Topics.OutputRoomEvent = "output_room_event"
dp := &dummyProducer{ dp := &dummyProducer{
topic: string(cfg.Kafka.Topics.OutputRoomEvent), topic: string(cfg.Global.Kafka.Topics.OutputRoomEvent),
} }
cache, err := caching.NewInMemoryLRUCache(true) cache, err := caching.NewInMemoryLRUCache(true)
if err != nil { if err != nil {

View file

@ -25,13 +25,13 @@ func AddInternalRoutes(router *mux.Router, intAPI api.ServerKeyInternalAPI, cach
// NewInternalAPI returns a concerete implementation of the internal API. Callers // NewInternalAPI returns a concerete implementation of the internal API. Callers
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
func NewInternalAPI( func NewInternalAPI(
cfg *config.Dendrite, cfg *config.ServerKeyAPI,
fedClient *gomatrixserverlib.FederationClient, fedClient *gomatrixserverlib.FederationClient,
caches *caching.Caches, caches *caching.Caches,
) api.ServerKeyInternalAPI { ) api.ServerKeyInternalAPI {
innerDB, err := storage.NewDatabase( innerDB, err := storage.NewDatabase(
string(cfg.Database.ServerKey), string(cfg.Database),
cfg.DbProperties(), cfg.DatabaseOptions,
cfg.Matrix.ServerName, cfg.Matrix.ServerName,
cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey), cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey),
cfg.Matrix.KeyID, cfg.Matrix.KeyID,
@ -62,7 +62,7 @@ func NewInternalAPI(
} }
var b64e = base64.StdEncoding.WithPadding(base64.NoPadding) var b64e = base64.StdEncoding.WithPadding(base64.NoPadding)
for _, ps := range cfg.Matrix.KeyPerspectives { for _, ps := range cfg.KeyPerspectives {
perspective := &gomatrixserverlib.PerspectiveKeyFetcher{ perspective := &gomatrixserverlib.PerspectiveKeyFetcher{
PerspectiveServerName: ps.ServerName, PerspectiveServerName: ps.ServerName,
PerspectiveServerKeys: map[gomatrixserverlib.KeyID]ed25519.PublicKey{}, PerspectiveServerKeys: map[gomatrixserverlib.KeyID]ed25519.PublicKey{},

View file

@ -23,7 +23,7 @@ import (
type server struct { type server struct {
name gomatrixserverlib.ServerName // server name name gomatrixserverlib.ServerName // server name
validity time.Duration // key validity duration from now validity time.Duration // key validity duration from now
config *config.Dendrite // skeleton config, from TestMain config *config.ServerKeyAPI // skeleton config, from TestMain
fedclient *gomatrixserverlib.FederationClient // uses MockRoundTripper fedclient *gomatrixserverlib.FederationClient // uses MockRoundTripper
cache *caching.Caches // server-specific cache cache *caching.Caches // server-specific cache
api api.ServerKeyInternalAPI // server-specific server key API api api.ServerKeyInternalAPI // server-specific server key API
@ -69,13 +69,15 @@ func TestMain(m *testing.M) {
// Draw up just enough Dendrite config for the server key // Draw up just enough Dendrite config for the server key
// API to work. // API to work.
s.config = &config.Dendrite{} s.config = &config.ServerKeyAPI{
s.config.SetDefaults() Matrix: &config.Global{
s.config.Matrix.ServerName = gomatrixserverlib.ServerName(s.name) ServerName: gomatrixserverlib.ServerName(s.name),
s.config.Matrix.PrivateKey = testPriv PrivateKey: testPriv,
s.config.Matrix.KeyID = serverKeyID KeyID: serverKeyID,
s.config.Matrix.KeyValidityPeriod = s.validity KeyValidityPeriod: s.validity,
s.config.Database.ServerKey = config.DataSource("file::memory:") },
Database: config.DataSource("file::memory:"),
}
// Create a transport which redirects federation requests to // Create a transport which redirects federation requests to
// the mock round tripper. Since we're not *really* listening for // the mock round tripper. Since we're not *really* listening for

View file

@ -37,14 +37,14 @@ type OutputClientDataConsumer struct {
// NewOutputClientDataConsumer creates a new OutputClientData consumer. Call Start() to begin consuming from room servers. // NewOutputClientDataConsumer creates a new OutputClientData consumer. Call Start() to begin consuming from room servers.
func NewOutputClientDataConsumer( func NewOutputClientDataConsumer(
cfg *config.Dendrite, cfg *config.SyncAPI,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
n *sync.Notifier, n *sync.Notifier,
store storage.Database, store storage.Database,
) *OutputClientDataConsumer { ) *OutputClientDataConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputClientData), Topic: string(cfg.Matrix.Kafka.Topics.OutputClientData),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
} }

View file

@ -41,14 +41,14 @@ type OutputSendToDeviceEventConsumer struct {
// NewOutputSendToDeviceEventConsumer creates a new OutputSendToDeviceEventConsumer. // NewOutputSendToDeviceEventConsumer creates a new OutputSendToDeviceEventConsumer.
// Call Start() to begin consuming from the EDU server. // Call Start() to begin consuming from the EDU server.
func NewOutputSendToDeviceEventConsumer( func NewOutputSendToDeviceEventConsumer(
cfg *config.Dendrite, cfg *config.SyncAPI,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
n *sync.Notifier, n *sync.Notifier,
store storage.Database, store storage.Database,
) *OutputSendToDeviceEventConsumer { ) *OutputSendToDeviceEventConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputSendToDeviceEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputSendToDeviceEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
} }

View file

@ -37,14 +37,14 @@ type OutputTypingEventConsumer struct {
// NewOutputTypingEventConsumer creates a new OutputTypingEventConsumer. // NewOutputTypingEventConsumer creates a new OutputTypingEventConsumer.
// Call Start() to begin consuming from the EDU server. // Call Start() to begin consuming from the EDU server.
func NewOutputTypingEventConsumer( func NewOutputTypingEventConsumer(
cfg *config.Dendrite, cfg *config.SyncAPI,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
n *sync.Notifier, n *sync.Notifier,
store storage.Database, store storage.Database,
) *OutputTypingEventConsumer { ) *OutputTypingEventConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputTypingEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputTypingEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
} }

View file

@ -39,7 +39,7 @@ type OutputRoomEventConsumer struct {
// NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers. // NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers.
func NewOutputRoomEventConsumer( func NewOutputRoomEventConsumer(
cfg *config.Dendrite, cfg *config.SyncAPI,
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
n *sync.Notifier, n *sync.Notifier,
store storage.Database, store storage.Database,
@ -47,7 +47,7 @@ func NewOutputRoomEventConsumer(
) *OutputRoomEventConsumer { ) *OutputRoomEventConsumer {
consumer := internal.ContinualConsumer{ consumer := internal.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputRoomEvent), Topic: string(cfg.Matrix.Kafka.Topics.OutputRoomEvent),
Consumer: kafkaConsumer, Consumer: kafkaConsumer,
PartitionStore: store, PartitionStore: store,
} }

View file

@ -36,7 +36,7 @@ type messagesReq struct {
db storage.Database db storage.Database
rsAPI api.RoomserverInternalAPI rsAPI api.RoomserverInternalAPI
federation *gomatrixserverlib.FederationClient federation *gomatrixserverlib.FederationClient
cfg *config.Dendrite cfg *config.SyncAPI
roomID string roomID string
from *types.TopologyToken from *types.TopologyToken
to *types.TopologyToken to *types.TopologyToken
@ -61,7 +61,7 @@ func OnIncomingMessagesRequest(
req *http.Request, db storage.Database, roomID string, req *http.Request, db storage.Database, roomID string,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.SyncAPI,
) util.JSONResponse { ) util.JSONResponse {
var err error var err error

View file

@ -39,7 +39,7 @@ func Setup(
publicAPIMux *mux.Router, srp *sync.RequestPool, syncDB storage.Database, publicAPIMux *mux.Router, srp *sync.RequestPool, syncDB storage.Database,
userAPI userapi.UserInternalAPI, federation *gomatrixserverlib.FederationClient, userAPI userapi.UserInternalAPI, federation *gomatrixserverlib.FederationClient,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite, cfg *config.SyncAPI,
) { ) {
r0mux := publicAPIMux.PathPrefix(pathPrefixR0).Subrouter() r0mux := publicAPIMux.PathPrefix(pathPrefixR0).Subrouter()

View file

@ -40,9 +40,9 @@ func AddPublicRoutes(
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
cfg *config.Dendrite, cfg *config.SyncAPI,
) { ) {
syncDB, err := storage.NewSyncServerDatasource(string(cfg.Database.SyncAPI), cfg.DbProperties()) syncDB, err := storage.NewSyncServerDatasource(string(cfg.Database), cfg.DatabaseOptions)
if err != nil { if err != nil {
logrus.WithError(err).Panicf("failed to connect to sync db") logrus.WithError(err).Panicf("failed to connect to sync db")
} }