aboutsummaryrefslogtreecommitdiff
path: root/clientapi/routing
diff options
context:
space:
mode:
authorAlex Chen <Cnly@users.noreply.github.com>2019-08-07 00:02:12 +0800
committerGitHub <noreply@github.com>2019-08-07 00:02:12 +0800
commit324ca22b358d53339b2971ec85a02de7282604e6 (patch)
tree0f70e622f8c2667cf9c53a897143d2afc0863938 /clientapi/routing
parent66bf615360cfe6eac11e901ffe34f70f97330a22 (diff)
Implement profile retrieval over federation (#726)
Diffstat (limited to 'clientapi/routing')
-rw-r--r--clientapi/routing/profile.go107
-rw-r--r--clientapi/routing/routing.go6
2 files changed, 91 insertions, 22 deletions
diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go
index 8d28b366..e8ea6cf1 100644
--- a/clientapi/routing/profile.go
+++ b/clientapi/routing/profile.go
@@ -30,43 +30,61 @@ import (
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrix"
"github.com/matrix-org/util"
)
// GetProfile implements GET /profile/{userID}
func GetProfile(
- req *http.Request, accountDB *accounts.Database, userID string, asAPI appserviceAPI.AppServiceQueryAPI,
+ req *http.Request, accountDB *accounts.Database, cfg *config.Dendrite,
+ userID string,
+ asAPI appserviceAPI.AppServiceQueryAPI,
+ federation *gomatrixserverlib.FederationClient,
) util.JSONResponse {
- profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
+ profile, err := getProfile(req.Context(), accountDB, cfg, userID, asAPI, federation)
if err != nil {
+ if err == common.ErrProfileNoExists {
+ return util.JSONResponse{
+ Code: http.StatusNotFound,
+ JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
+ }
+ }
+
return httputil.LogThenError(req, err)
}
- res := common.ProfileResponse{
- AvatarURL: profile.AvatarURL,
- DisplayName: profile.DisplayName,
- }
return util.JSONResponse{
Code: http.StatusOK,
- JSON: res,
+ JSON: common.ProfileResponse{
+ AvatarURL: profile.AvatarURL,
+ DisplayName: profile.DisplayName,
+ },
}
}
// GetAvatarURL implements GET /profile/{userID}/avatar_url
func GetAvatarURL(
- req *http.Request, accountDB *accounts.Database, userID string, asAPI appserviceAPI.AppServiceQueryAPI,
+ req *http.Request, accountDB *accounts.Database, cfg *config.Dendrite,
+ userID string, asAPI appserviceAPI.AppServiceQueryAPI,
+ federation *gomatrixserverlib.FederationClient,
) util.JSONResponse {
- profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
+ profile, err := getProfile(req.Context(), accountDB, cfg, userID, asAPI, federation)
if err != nil {
+ if err == common.ErrProfileNoExists {
+ return util.JSONResponse{
+ Code: http.StatusNotFound,
+ JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
+ }
+ }
+
return httputil.LogThenError(req, err)
}
- res := common.AvatarURL{
- AvatarURL: profile.AvatarURL,
- }
return util.JSONResponse{
Code: http.StatusOK,
- JSON: res,
+ JSON: common.AvatarURL{
+ AvatarURL: profile.AvatarURL,
+ },
}
}
@@ -152,18 +170,27 @@ func SetAvatarURL(
// GetDisplayName implements GET /profile/{userID}/displayname
func GetDisplayName(
- req *http.Request, accountDB *accounts.Database, userID string, asAPI appserviceAPI.AppServiceQueryAPI,
+ req *http.Request, accountDB *accounts.Database, cfg *config.Dendrite,
+ userID string, asAPI appserviceAPI.AppServiceQueryAPI,
+ federation *gomatrixserverlib.FederationClient,
) util.JSONResponse {
- profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
+ profile, err := getProfile(req.Context(), accountDB, cfg, userID, asAPI, federation)
if err != nil {
+ if err == common.ErrProfileNoExists {
+ return util.JSONResponse{
+ Code: http.StatusNotFound,
+ JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
+ }
+ }
+
return httputil.LogThenError(req, err)
}
- res := common.DisplayName{
- DisplayName: profile.DisplayName,
- }
+
return util.JSONResponse{
Code: http.StatusOK,
- JSON: res,
+ JSON: common.DisplayName{
+ DisplayName: profile.DisplayName,
+ },
}
}
@@ -247,6 +274,48 @@ func SetDisplayName(
}
}
+// getProfile gets the full profile of a user by querying the database or a
+// remote homeserver.
+// Returns an error when something goes wrong or specifically
+// common.ErrProfileNoExists when the profile doesn't exist.
+func getProfile(
+ ctx context.Context, accountDB *accounts.Database, cfg *config.Dendrite,
+ userID string,
+ asAPI appserviceAPI.AppServiceQueryAPI,
+ federation *gomatrixserverlib.FederationClient,
+) (*authtypes.Profile, error) {
+ localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
+ if err != nil {
+ return nil, err
+ }
+
+ if domain != cfg.Matrix.ServerName {
+ profile, fedErr := federation.LookupProfile(ctx, domain, userID, "")
+ if fedErr != nil {
+ if x, ok := fedErr.(gomatrix.HTTPError); ok {
+ if x.Code == http.StatusNotFound {
+ return nil, common.ErrProfileNoExists
+ }
+ }
+
+ return nil, fedErr
+ }
+
+ return &authtypes.Profile{
+ Localpart: localpart,
+ DisplayName: profile.DisplayName,
+ AvatarURL: profile.AvatarURL,
+ }, nil
+ }
+
+ profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID, asAPI, accountDB)
+ if err != nil {
+ return nil, err
+ }
+
+ return profile, nil
+}
+
func buildMembershipEvents(
ctx context.Context,
memberships []authtypes.Membership,
diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go
index c262db3d..825dd97a 100644
--- a/clientapi/routing/routing.go
+++ b/clientapi/routing/routing.go
@@ -283,7 +283,7 @@ func Setup(
if err != nil {
return util.ErrorResponse(err)
}
- return GetProfile(req, accountDB, vars["userID"], asAPI)
+ return GetProfile(req, accountDB, &cfg, vars["userID"], asAPI, federation)
}),
).Methods(http.MethodGet, http.MethodOptions)
@@ -293,7 +293,7 @@ func Setup(
if err != nil {
return util.ErrorResponse(err)
}
- return GetAvatarURL(req, accountDB, vars["userID"], asAPI)
+ return GetAvatarURL(req, accountDB, &cfg, vars["userID"], asAPI, federation)
}),
).Methods(http.MethodGet, http.MethodOptions)
@@ -315,7 +315,7 @@ func Setup(
if err != nil {
return util.ErrorResponse(err)
}
- return GetDisplayName(req, accountDB, vars["userID"], asAPI)
+ return GetDisplayName(req, accountDB, &cfg, vars["userID"], asAPI, federation)
}),
).Methods(http.MethodGet, http.MethodOptions)