From 2c47959600fd3df21f122023c7757e3048af8999 Mon Sep 17 00:00:00 2001 From: Roman Isaev Date: Sun, 22 Dec 2024 00:23:25 +0000 Subject: [PATCH] mas: added username_available endpoint --- clientapi/routing/admin.go | 21 +++++++++++++++++++++ clientapi/routing/routing.go | 7 ++++++- internal/httputil/httpapi.go | 32 ++++++++++++++++++++++++++++++++ setup/mscs/mscs.go | 2 +- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/clientapi/routing/admin.go b/clientapi/routing/admin.go index 48e58209..40881166 100644 --- a/clientapi/routing/admin.go +++ b/clientapi/routing/admin.go @@ -496,6 +496,27 @@ func AdminDownloadState(req *http.Request, device *api.Device, rsAPI roomserverA } } +func AdminCheckUsernameAvailable( + req *http.Request, + userAPI userapi.ClientUserAPI, + cfg *config.ClientAPI, +) util.JSONResponse { + username := req.URL.Query().Get("username") + if username == "" { + return util.MessageResponse(http.StatusBadRequest, "Query parameter 'username' is missing or empty") + } + rq := userapi.QueryAccountAvailabilityRequest{Localpart: username, ServerName: cfg.Matrix.ServerName} + rs := userapi.QueryAccountAvailabilityResponse{} + if err := userAPI.QueryAccountAvailability(req.Context(), &rq, &rs); err != nil { + return util.ErrorResponse(err) + } + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: map[string]bool{"available": rs.Available}, + } +} + // GetEventReports returns reported events for a given user/room. func GetEventReports( req *http.Request, diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index 373fa03f..0544c3c2 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -334,7 +334,12 @@ func Setup( return util.JSONResponse{Code: http.StatusOK, JSON: map[string]string{ "issuer": m.Issuer, }} - })) + })).Methods(http.MethodGet) + + synapseAdminRouter.Handle("/admin/v1/username_available", + httputil.MakeServiceAdminAPI("admin_username_available", m.AdminToken, func(r *http.Request) util.JSONResponse { + return AdminCheckUsernameAvailable(r, userAPI, cfg) + })).Methods(http.MethodGet) } if mscCfg.Enabled("msc2753") { diff --git a/internal/httputil/httpapi.go b/internal/httputil/httpapi.go index d3255767..5a332d6f 100644 --- a/internal/httputil/httpapi.go +++ b/internal/httputil/httpapi.go @@ -136,6 +136,38 @@ func MakeAdminAPI( }) } +// MakeServiceAdminAPI is a wrapper around MakeAuthAPI which enforces that the request can only be +// completed by a trusted service e.g. Matrix Auth Service. +func MakeServiceAdminAPI( + metricsName, serviceToken string, + f func(*http.Request) util.JSONResponse, +) http.Handler { + h := func(req *http.Request) util.JSONResponse { + logger := util.GetLogger(req.Context()) + token, err := auth.ExtractAccessToken(req) + + if err != nil { + logger.Debugf("ExtractAccessToken %s -> HTTP %d", req.RemoteAddr, http.StatusUnauthorized) + return util.JSONResponse{ + Code: http.StatusUnauthorized, + JSON: spec.MissingToken(err.Error()), + } + } + if token != serviceToken { + logger.Debugf("Invalid service token '%s'", token) + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.UnknownToken(token), + } + } + // add the service addr to the logger + logger = logger.WithField("service_useragent", req.UserAgent()) + req = req.WithContext(util.ContextWithLogger(req.Context(), logger)) + return f(req) + } + return MakeExternalAPI(metricsName, h) +} + // MakeExternalAPI turns a util.JSONRequestHandler function into an http.Handler. // This is used for APIs that are called from the internet. func MakeExternalAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler { diff --git a/setup/mscs/mscs.go b/setup/mscs/mscs.go index 91bc1a82..6a220e62 100644 --- a/setup/mscs/mscs.go +++ b/setup/mscs/mscs.go @@ -37,7 +37,7 @@ func EnableMSC(cfg *config.Dendrite, cm *sqlutil.Connections, routers httputil.R return msc2836.Enable(cfg, cm, routers, monolith.RoomserverAPI, monolith.FederationAPI, monolith.UserAPI, monolith.KeyRing) case "msc2444": // enabled inside federationapi case "msc2753": // enabled inside clientapi - case "msc2965": // enabled inside clientapi + case "msc2965": // enabled inside clientapi default: logrus.Warnf("EnableMSC: unknown MSC '%s', this MSC is either not supported or is natively supported by Dendrite", msc) }