Make federationapi use userapi (#1135)

Removes dependencies on account DB, device DB and ASAPI.
This commit is contained in:
Kegsay 2020-06-16 14:53:19 +01:00 committed by GitHub
parent 45011579eb
commit 1942928ee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 102 additions and 66 deletions

View File

@ -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))

View File

@ -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,
)
}

View File

@ -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,

View File

@ -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,

View File

@ -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,
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)
}

View File

@ -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}
}),
)
}