Make federationapi use userapi
Removes dependencies on account DB, device DB and ASAPI.
MODIFY
cmd/dendrite-federation-api-server/main.go
cmd/dendrite-federation-api-server/main.go
@@ -24,18 +24,16 @@ func main() {
base := setup.NewBaseDendrite(cfg, "FederationAPI", true)
defer base.Close() // nolint: errcheck
- accountDB := base.CreateAccountsDB()
- deviceDB := base.CreateDeviceDB()
+ userAPI := base.UserAPIClient()
federation := base.CreateFederationClient()
serverKeyAPI := base.ServerKeyAPIClient()
keyRing := serverKeyAPI.KeyRing()
fsAPI := base.FederationSenderHTTPClient()
rsAPI := base.RoomserverHTTPClient()
- asAPI := base.AppserviceHTTPClient()
federationapi.AddPublicRoutes(
- base.PublicAPIMux, base.Cfg, accountDB, deviceDB, federation, keyRing,
- rsAPI, asAPI, fsAPI, base.EDUServerClient(),
+ base.PublicAPIMux, base.Cfg, userAPI, federation, keyRing,
+ rsAPI, fsAPI, base.EDUServerClient(),
)
base.SetupAndServeHTTP(string(base.Cfg.Bind.FederationAPI), string(base.Cfg.Listen.FederationAPI))

MODIFY
federationapi/federationapi.go
federationapi/federationapi.go
@@ -16,13 +16,11 @@ package federationapi
import (
"github.com/gorilla/mux"
- appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
eduserverAPI "github.com/matrix-org/dendrite/eduserver/api"
federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
"github.com/matrix-org/dendrite/internal/config"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
+ userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/dendrite/federationapi/routing"
"github.com/matrix-org/gomatrixserverlib"
@@ -32,19 +30,17 @@ import (
func AddPublicRoutes(
router *mux.Router,
cfg *config.Dendrite,
- accountsDB accounts.Database,
- deviceDB devices.Database,
+ userAPI userapi.UserInternalAPI,
federation *gomatrixserverlib.FederationClient,
keyRing gomatrixserverlib.JSONVerifier,
rsAPI roomserverAPI.RoomserverInternalAPI,
- asAPI appserviceAPI.AppServiceQueryAPI,
federationSenderAPI federationSenderAPI.FederationSenderInternalAPI,
eduAPI eduserverAPI.EDUServerInputAPI,
) {
routing.Setup(
- router, cfg, rsAPI, asAPI,
+ router, cfg, rsAPI,
eduAPI, federationSenderAPI, keyRing,
- federation, accountsDB, deviceDB,
+ federation, userAPI,
)
}

MODIFY
federationapi/federationapi_test.go
federationapi/federationapi_test.go
@@ -31,7 +31,7 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
fsAPI := base.FederationSenderHTTPClient()
// 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.
- federationapi.AddPublicRoutes(base.PublicAPIMux, cfg, nil, nil, nil, keyRing, nil, nil, fsAPI, nil)
+ federationapi.AddPublicRoutes(base.PublicAPIMux, cfg, nil, nil, keyRing, nil, fsAPI, nil)
httputil.SetupHTTPAPI(
base.BaseMux,
base.PublicAPIMux,

MODIFY
federationapi/routing/devices.go
federationapi/routing/devices.go
@@ -15,9 +15,8 @@ package routing
import (
"net/http"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
- "github.com/matrix-org/dendrite/clientapi/userutil"
+ userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
@@ -25,17 +24,9 @@ import (
// GetUserDevices for the given user id
func GetUserDevices(
req *http.Request,
- deviceDB devices.Database,
+ userAPI userapi.UserInternalAPI,
userID string,
) util.JSONResponse {
- localpart, err := userutil.ParseUsernameParam(userID, nil)
- if err != nil {
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: jsonerror.InvalidArgumentValue("Invalid user ID"),
- }
- }
-
response := gomatrixserverlib.RespUserDevices{
UserID: userID,
// TODO: we should return an incrementing stream ID each time the device
@@ -43,13 +34,16 @@ func GetUserDevices(
StreamID: 0,
}
- devs, err := deviceDB.GetDevicesByLocalpart(req.Context(), localpart)
+ var res userapi.QueryDevicesResponse
+ err := userAPI.QueryDevices(req.Context(), &userapi.QueryDevicesRequest{
+ UserID: userID,
+ }, &res)
if err != nil {
- util.GetLogger(req.Context()).WithError(err).Error("deviceDB.GetDevicesByLocalPart failed")
+ util.GetLogger(req.Context()).WithError(err).Error("userAPI.QueryDevices failed")
return jsonerror.InternalServerError()
}
- for _, dev := range devs {
+ for _, dev := range res.Devices {
device := gomatrixserverlib.RespUserDevice{
DeviceID: dev.ID,
DisplayName: dev.DisplayName,

MODIFY
federationapi/routing/profile.go
federationapi/routing/profile.go
@@ -18,11 +18,10 @@ import (
"fmt"
"net/http"
- appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/internal/config"
"github.com/matrix-org/dendrite/internal/eventutil"
+ userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
@@ -30,9 +29,8 @@ import (
// GetProfile implements GET /_matrix/federation/v1/query/profile
func GetProfile(
httpReq *http.Request,
- accountDB accounts.Database,
+ userAPI userapi.UserInternalAPI,
cfg *config.Dendrite,
- asAPI appserviceAPI.AppServiceQueryAPI,
) util.JSONResponse {
userID, field := httpReq.FormValue("user_id"), httpReq.FormValue("field")
@@ -60,9 +58,12 @@ func GetProfile(
}
}
- profile, err := appserviceAPI.RetrieveUserProfile(httpReq.Context(), userID, asAPI, accountDB)
+ var profileRes userapi.QueryProfileResponse
+ err = userAPI.QueryProfile(httpReq.Context(), &userapi.QueryProfileRequest{
+ UserID: userID,
+ }, &profileRes)
if err != nil {
- util.GetLogger(httpReq.Context()).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
+ util.GetLogger(httpReq.Context()).WithError(err).Error("userAPI.QueryProfile failed")
return jsonerror.InternalServerError()
}
@@ -73,11 +74,11 @@ func GetProfile(
switch field {
case "displayname":
res = eventutil.DisplayName{
- DisplayName: profile.DisplayName,
+ DisplayName: profileRes.DisplayName,
}
case "avatar_url":
res = eventutil.AvatarURL{
- AvatarURL: profile.AvatarURL,
+ AvatarURL: profileRes.AvatarURL,
}
default:
code = http.StatusBadRequest
@@ -85,8 +86,8 @@ func GetProfile(
}
} else {
res = eventutil.ProfileResponse{
- AvatarURL: profile.AvatarURL,
- DisplayName: profile.DisplayName,
+ AvatarURL: profileRes.AvatarURL,
+ DisplayName: profileRes.DisplayName,
}
}

MODIFY
federationapi/routing/routing.go
federationapi/routing/routing.go
@@ -18,14 +18,12 @@ import (
"net/http"
"github.com/gorilla/mux"
- appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
eduserverAPI "github.com/matrix-org/dendrite/eduserver/api"
federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
"github.com/matrix-org/dendrite/internal/config"
"github.com/matrix-org/dendrite/internal/httputil"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
+ userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
@@ -48,13 +46,11 @@ func Setup(
publicAPIMux *mux.Router,
cfg *config.Dendrite,
rsAPI roomserverAPI.RoomserverInternalAPI,
- asAPI appserviceAPI.AppServiceQueryAPI,
eduAPI eduserverAPI.EDUServerInputAPI,
fsAPI federationSenderAPI.FederationSenderInternalAPI,
keys gomatrixserverlib.JSONVerifier,
federation *gomatrixserverlib.FederationClient,
- accountDB accounts.Database,
- deviceDB devices.Database,
+ userAPI userapi.UserInternalAPI,
) {
v2keysmux := publicAPIMux.PathPrefix(pathPrefixV2Keys).Subrouter()
v1fedmux := publicAPIMux.PathPrefix(pathPrefixV1Federation).Subrouter()
@@ -98,7 +94,7 @@ func Setup(
v1fedmux.Handle("/3pid/onbind", httputil.MakeExternalAPI("3pid_onbind",
func(req *http.Request) util.JSONResponse {
- return CreateInvitesFrom3PIDInvites(req, rsAPI, asAPI, cfg, federation, accountDB)
+ return CreateInvitesFrom3PIDInvites(req, rsAPI, cfg, federation, userAPI)
},
)).Methods(http.MethodPost, http.MethodOptions)
@@ -160,7 +156,7 @@ func Setup(
"federation_query_profile", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetProfile(
- httpReq, accountDB, cfg, asAPI,
+ httpReq, userAPI, cfg,
)
},
)).Methods(http.MethodGet)
@@ -169,7 +165,7 @@ func Setup(
"federation_user_devices", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetUserDevices(
- httpReq, deviceDB, vars["userID"],
+ httpReq, userAPI, vars["userID"],
)
},
)).Methods(http.MethodGet)

MODIFY
federationapi/routing/threepid.go
federationapi/routing/threepid.go
@@ -21,13 +21,11 @@ import (
"net/http"
"time"
- appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
- "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/internal/config"
"github.com/matrix-org/dendrite/roomserver/api"
- roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
+ userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@@ -57,10 +55,10 @@ var (
// CreateInvitesFrom3PIDInvites implements POST /_matrix/federation/v1/3pid/onbind
func CreateInvitesFrom3PIDInvites(
- req *http.Request, rsAPI roomserverAPI.RoomserverInternalAPI,
- asAPI appserviceAPI.AppServiceQueryAPI, cfg *config.Dendrite,
+ req *http.Request, rsAPI api.RoomserverInternalAPI,
+ cfg *config.Dendrite,
federation *gomatrixserverlib.FederationClient,
- accountDB accounts.Database,
+ userAPI userapi.UserInternalAPI,
) util.JSONResponse {
var body invites
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
@@ -79,7 +77,7 @@ func CreateInvitesFrom3PIDInvites(
}
event, err := createInviteFrom3PIDInvite(
- req.Context(), rsAPI, asAPI, cfg, inv, federation, accountDB,
+ req.Context(), rsAPI, cfg, inv, federation, userAPI,
)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("createInviteFrom3PIDInvite failed")
@@ -107,7 +105,7 @@ func ExchangeThirdPartyInvite(
httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
roomID string,
- rsAPI roomserverAPI.RoomserverInternalAPI,
+ rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite,
federation *gomatrixserverlib.FederationClient,
) util.JSONResponse {
@@ -197,10 +195,10 @@ func ExchangeThirdPartyInvite(
// Returns an error if there was a problem building the event or fetching the
// necessary data to do so.
func createInviteFrom3PIDInvite(
- ctx context.Context, rsAPI roomserverAPI.RoomserverInternalAPI,
- asAPI appserviceAPI.AppServiceQueryAPI, cfg *config.Dendrite,
+ ctx context.Context, rsAPI api.RoomserverInternalAPI,
+ cfg *config.Dendrite,
inv invite, federation *gomatrixserverlib.FederationClient,
- accountDB accounts.Database,
+ userAPI userapi.UserInternalAPI,
) (*gomatrixserverlib.Event, error) {
verReq := api.QueryRoomVersionForRoomRequest{RoomID: inv.RoomID}
verRes := api.QueryRoomVersionForRoomResponse{}
@@ -225,14 +223,17 @@ func createInviteFrom3PIDInvite(
StateKey: &inv.MXID,
}
- profile, err := appserviceAPI.RetrieveUserProfile(ctx, inv.MXID, asAPI, accountDB)
+ var res userapi.QueryProfileResponse
+ err = userAPI.QueryProfile(ctx, &userapi.QueryProfileRequest{
+ UserID: inv.MXID,
+ }, &res)
if err != nil {
return nil, err
}
content := gomatrixserverlib.MemberContent{
- AvatarURL: profile.AvatarURL,
- DisplayName: profile.DisplayName,
+ AvatarURL: res.AvatarURL,
+ DisplayName: res.DisplayName,
Membership: gomatrixserverlib.Invite,
ThirdPartyInvite: &gomatrixserverlib.MemberThirdPartyInvite{
Signed: inv.Signed,
@@ -261,7 +262,7 @@ func createInviteFrom3PIDInvite(
// Returns an error if something failed during the process.
func buildMembershipEvent(
ctx context.Context,
- builder *gomatrixserverlib.EventBuilder, rsAPI roomserverAPI.RoomserverInternalAPI,
+ builder *gomatrixserverlib.EventBuilder, rsAPI api.RoomserverInternalAPI,
cfg *config.Dendrite,
) (*gomatrixserverlib.Event, error) {
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
@@ -274,11 +275,11 @@ func buildMembershipEvent(
}
// Ask the roomserver for information about this room
- queryReq := roomserverAPI.QueryLatestEventsAndStateRequest{
+ queryReq := api.QueryLatestEventsAndStateRequest{
RoomID: builder.RoomID,
StateToFetch: eventsNeeded.Tuples(),
}
- var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
+ var queryRes api.QueryLatestEventsAndStateResponse
if err = rsAPI.QueryLatestEventsAndState(ctx, &queryReq, &queryRes); err != nil {
return nil, err
}

MODIFY
internal/setup/monolith.go
internal/setup/monolith.go
@@ -77,8 +77,8 @@ func (m *Monolith) AddAllPublicRoutes(publicMux *mux.Router) {
keyserver.AddPublicRoutes(publicMux, m.Config, m.UserAPI)
federationapi.AddPublicRoutes(
- publicMux, m.Config, m.AccountDB, m.DeviceDB, m.FedClient,
- m.KeyRing, m.RoomserverAPI, m.AppserviceAPI, m.FederationSenderAPI,
+ publicMux, m.Config, m.UserAPI, m.FedClient,
+ m.KeyRing, m.RoomserverAPI, m.FederationSenderAPI,
m.EDUInternalAPI,
)
mediaapi.AddPublicRoutes(publicMux, m.Config, m.UserAPI, m.Client)

MODIFY
userapi/api/api.go
userapi/api/api.go
@@ -20,6 +20,7 @@ import "context"
type UserInternalAPI interface {
QueryProfile(ctx context.Context, req *QueryProfileRequest, res *QueryProfileResponse) error
QueryAccessToken(ctx context.Context, req *QueryAccessTokenRequest, res *QueryAccessTokenResponse) error
+ QueryDevices(ctx context.Context, req *QueryDevicesRequest, res *QueryDevicesResponse) error
}
// QueryAccessTokenRequest is the request for QueryAccessToken
@@ -36,6 +37,17 @@ type QueryAccessTokenResponse struct {
Err error // e.g ErrorForbidden
}
+// QueryDevicesRequest is the request for QueryDevices
+type QueryDevicesRequest struct {
+ UserID string
+}
+
+// QueryDevicesResponse is the response for QueryDevices
+type QueryDevicesResponse struct {
+ UserExists bool
+ Devices []Device
+}
+
// QueryProfileRequest is the request for QueryProfile
type QueryProfileRequest struct {
// The user ID to query

MODIFY
userapi/internal/api.go
userapi/internal/api.go
@@ -57,6 +57,22 @@ func (a *UserInternalAPI) QueryProfile(ctx context.Context, req *api.QueryProfil
return nil
}
+func (a *UserInternalAPI) QueryDevices(ctx context.Context, req *api.QueryDevicesRequest, res *api.QueryDevicesResponse) error {
+ local, domain, err := gomatrixserverlib.SplitID('@', req.UserID)
+ if err != nil {
+ return err
+ }
+ if domain != a.ServerName {
+ return fmt.Errorf("cannot query devices of remote users: got %s want %s", domain, a.ServerName)
+ }
+ devs, err := a.DeviceDB.GetDevicesByLocalpart(ctx, local)
+ if err != nil {
+ return err
+ }
+ res.Devices = devs
+ return nil
+}
+
func (a *UserInternalAPI) QueryAccessToken(ctx context.Context, req *api.QueryAccessTokenRequest, res *api.QueryAccessTokenResponse) error {
if req.AppServiceUserID != "" {
appServiceDevice, err := a.queryAppServiceToken(ctx, req.AccessToken, req.AppServiceUserID)

MODIFY
userapi/inthttp/client.go
userapi/inthttp/client.go
@@ -28,6 +28,7 @@ import (
const (
QueryProfilePath = "/userapi/queryProfile"
QueryAccessTokenPath = "/userapi/queryAccessToken"
+ QueryDevicesPath = "/userapi/queryDevices"
)
// NewUserAPIClient creates a UserInternalAPI implemented by talking to a HTTP POST API.
@@ -73,3 +74,11 @@ func (h *httpUserInternalAPI) QueryAccessToken(
apiURL := h.apiURL + QueryAccessTokenPath
return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
}
+
+func (h *httpUserInternalAPI) QueryDevices(ctx context.Context, req *api.QueryDevicesRequest, res *api.QueryDevicesResponse) error {
+ span, ctx := opentracing.StartSpanFromContext(ctx, "QueryDevices")
+ defer span.Finish()
+
+ apiURL := h.apiURL + QueryDevicesPath
+ return httputil.PostJSON(ctx, span, h.httpClient, apiURL, req, res)
+}

MODIFY
userapi/inthttp/server.go
userapi/inthttp/server.go
@@ -51,4 +51,17 @@ func AddRoutes(internalAPIMux *mux.Router, s api.UserInternalAPI) {
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
)
+ internalAPIMux.Handle(QueryDevicesPath,
+ httputil.MakeInternalAPI("queryDevices", func(req *http.Request) util.JSONResponse {
+ request := api.QueryDevicesRequest{}
+ response := api.QueryDevicesResponse{}
+ if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
+ return util.MessageResponse(http.StatusBadRequest, err.Error())
+ }
+ if err := s.QueryDevices(req.Context(), &request, &response); err != nil {
+ return util.ErrorResponse(err)
+ }
+ return util.JSONResponse{Code: http.StatusOK, JSON: &response}
+ }),
+ )
}

Make federationapi use userapi (#1135)

Removes dependencies on account DB, device DB and ASAPI.