From d39bcb005e9284d5f767caca30c7e97deeabc936 Mon Sep 17 00:00:00 2001 From: "Andrew (anoa)" Date: Tue, 31 Oct 2017 14:48:21 -0700 Subject: [PATCH] Federation: Implement Query Profile API Implements the server portion of: `GET /_matrix/federation/v1/query/profile?user_id=...&field=...` Closes #278 Signed-off-by: Andrew (anoa) --- .../dendrite/clientapi/jsonerror/jsonerror.go | 12 +++ .../dendrite/federationapi/routing/profile.go | 93 +++++++++++++++++++ .../dendrite/federationapi/routing/routing.go | 9 ++ 3 files changed, 114 insertions(+) create mode 100644 src/github.com/matrix-org/dendrite/federationapi/routing/profile.go diff --git a/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go index 8f168f4fa..2ba9db328 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go +++ b/src/github.com/matrix-org/dendrite/clientapi/jsonerror/jsonerror.go @@ -67,6 +67,18 @@ func NotFound(msg string) *MatrixError { return &MatrixError{"M_NOT_FOUND", msg} } +// MissingArgument is an error when the client tries to access a resource +// without providing an argument that is required. +func MissingArgument(msg string) *MatrixError { + return &MatrixError{"M_MISSING_ARGUMENT", msg} +} + +// InvalidArgumentBody is an error when the client tries to provide an +// invalid body under a valid argument +func InvalidArgumentBody(msg string) *MatrixError { + return &MatrixError{"M_INVALID_ARGUMENT_BODY", msg} +} + // MissingToken is an error when the client tries to access a resource which // requires authentication without supplying credentials. func MissingToken(msg string) *MatrixError { diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/profile.go b/src/github.com/matrix-org/dendrite/federationapi/routing/profile.go new file mode 100644 index 000000000..04ed99657 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/profile.go @@ -0,0 +1,93 @@ +// Copyright 2017 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "net/http" + + "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/gomatrixserverlib" + "github.com/matrix-org/util" +) + +type profileResponse struct { + AvatarURL string `json:"avatar_url"` + DisplayName string `json:"displayname"` +} + +type avatarURL struct { + AvatarURL string `json:"avatar_url"` +} + +type displayName struct { + DisplayName string `json:"displayname"` +} + +// GetProfile implements /_matrix/federation/v1/query/profile +func GetProfile( + httpReq *http.Request, + accountDB *accounts.Database, +) util.JSONResponse { + userID, field := httpReq.FormValue("user_id"), httpReq.FormValue("field") + + // httpReq.FormValue will return an empty string if value is not found + if userID == "" { + return util.JSONResponse{ + Code: 400, + JSON: jsonerror.MissingArgument("The request body did not contain required argument 'user_id'."), + } + } + + localpart, _, err := gomatrixserverlib.SplitID('@', userID) + if err != nil { + return httputil.LogThenError(httpReq, err) + } + + profile, err := accountDB.GetProfileByLocalpart(httpReq.Context(), localpart) + if err != nil { + return httputil.LogThenError(httpReq, err) + } + + var res interface{} + code := 200 + + if field != "" { + switch field { + case "displayname": + res = displayName{ + profile.DisplayName, + } + case "avatar_url": + res = avatarURL{ + profile.AvatarURL, + } + default: + code = 400 + res = jsonerror.InvalidArgumentBody("The request body did not contain allowed values of argument 'field'. Allowed: 'avatar_url', 'displayname'.") + } + } else { + res = profileResponse{ + profile.AvatarURL, + profile.DisplayName, + } + } + + return util.JSONResponse{ + Code: code, + JSON: res, + } +} diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go index c22dd1879..d14e2192d 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go @@ -105,6 +105,15 @@ func Setup( }, )).Methods("GET") + v1fedmux.Handle("/query/profile", common.MakeFedAPI( + "federation_query_profile", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + return GetProfile( + httpReq, accountDB, + ) + }, + )).Methods("GET") + v1fedmux.Handle("/version", common.MakeExternalAPI( "federation_version", func(httpReq *http.Request) util.JSONResponse {