From dbbfd26be77b294ca00af36f94ef647ba8d3d190 Mon Sep 17 00:00:00 2001 From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Date: Tue, 17 Jul 2018 08:57:20 -0700 Subject: [PATCH] Support inhibit_login registration option (#532) * Support inhibit_login registration option * Fix completeRegistration func definition * Change InhibitLogin to a WeakBoolean --- .../dendrite/clientapi/routing/register.go | 41 ++++++++++++++----- .../matrix-org/dendrite/common/types.go | 23 +++++++++++ 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/github.com/matrix-org/dendrite/clientapi/routing/register.go b/src/github.com/matrix-org/dendrite/clientapi/routing/register.go index b546385e9..ee8259315 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/register.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/register.go @@ -40,6 +40,7 @@ import ( "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/userutil" + "github.com/matrix-org/dendrite/common" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" "github.com/prometheus/client_golang/prometheus" @@ -116,7 +117,10 @@ type registerRequest struct { InitialDisplayName *string `json:"initial_device_display_name"` - // Application services place Type in the root of their registration + // Prevent this user from logging in + InhibitLogin common.WeakBoolean `json:"inhibit_login"` + + // Application Services place Type in the root of their registration // request, whereas clients place it in the authDict struct. Type authtypes.LoginType `json:"type"` } @@ -163,9 +167,9 @@ func newUserInteractiveResponse( // http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register type registerResponse struct { UserID string `json:"user_id"` - AccessToken string `json:"access_token"` + AccessToken string `json:"access_token,omitempty"` HomeServer gomatrixserverlib.ServerName `json:"home_server"` - DeviceID string `json:"device_id"` + DeviceID string `json:"device_id,omitempty"` } // recaptchaResponse represents the HTTP response from a Google Recaptcha server @@ -569,8 +573,10 @@ func handleRegistrationFlow( // If no error, application service was successfully validated. // Don't need to worry about appending to registration stages as // application service registration is entirely separate. - return completeRegistration(req.Context(), accountDB, deviceDB, - r.Username, "", appserviceID, r.InitialDisplayName) + return completeRegistration( + req.Context(), accountDB, deviceDB, r.Username, "", appserviceID, + r.InhibitLogin, r.InitialDisplayName, + ) case authtypes.LoginTypeDummy: // there is nothing to do @@ -605,8 +611,10 @@ func checkAndCompleteFlow( ) util.JSONResponse { if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) { // This flow was completed, registration can continue - return completeRegistration(req.Context(), accountDB, deviceDB, - r.Username, r.Password, "", r.InitialDisplayName) + return completeRegistration( + req.Context(), accountDB, deviceDB, r.Username, r.Password, "", + r.InhibitLogin, r.InitialDisplayName, + ) } // There are still more stages to complete. @@ -656,10 +664,10 @@ func LegacyRegister( return util.MessageResponse(http.StatusForbidden, "HMAC incorrect") } - return completeRegistration(req.Context(), accountDB, deviceDB, r.Username, r.Password, "", nil) + return completeRegistration(req.Context(), accountDB, deviceDB, r.Username, r.Password, "", false, nil) case authtypes.LoginTypeDummy: // there is nothing to do - return completeRegistration(req.Context(), accountDB, deviceDB, r.Username, r.Password, "", nil) + return completeRegistration(req.Context(), accountDB, deviceDB, r.Username, r.Password, "", false, nil) default: return util.JSONResponse{ Code: http.StatusNotImplemented, @@ -702,6 +710,7 @@ func completeRegistration( accountDB *accounts.Database, deviceDB *devices.Database, username, password, appserviceID string, + inhibitLogin common.WeakBoolean, displayName *string, ) util.JSONResponse { if username == "" { @@ -731,6 +740,18 @@ func completeRegistration( } } + // Check whether inhibit_login option is set. If so, don't create an access + // token or a device for this user + if inhibitLogin { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: registerResponse{ + UserID: userutil.MakeUserID(username, acc.ServerName), + HomeServer: acc.ServerName, + }, + } + } + token, err := auth.GenerateAccessToken() if err != nil { return util.JSONResponse{ @@ -739,7 +760,7 @@ func completeRegistration( } } - // // TODO: Use the device ID in the request. + // TODO: Use the device ID in the request. dev, err := deviceDB.CreateDevice(ctx, username, nil, token, displayName) if err != nil { return util.JSONResponse{ diff --git a/src/github.com/matrix-org/dendrite/common/types.go b/src/github.com/matrix-org/dendrite/common/types.go index d8c5c5a7e..e539774e2 100644 --- a/src/github.com/matrix-org/dendrite/common/types.go +++ b/src/github.com/matrix-org/dendrite/common/types.go @@ -14,6 +14,10 @@ package common +import ( + "strconv" +) + // AccountData represents account data sent from the client API server to the // sync API server type AccountData struct { @@ -36,3 +40,22 @@ type AvatarURL struct { type DisplayName struct { DisplayName string `json:"displayname"` } + +// WeakBoolean is a type that will Unmarshal to true or false even if the encoded +// representation is "true"/1 or "false"/0, as well as whatever other forms are +// recognized by strconv.ParseBool +type WeakBoolean bool + +// UnmarshalJSON is overridden here to allow strings vaguely representing a true +// or false boolean to be set as their closest counterpart +func (b *WeakBoolean) UnmarshalJSON(data []byte) error { + result, err := strconv.ParseBool(string(data)) + if err != nil { + return err + } + + // Set boolean value based on string input + *b = WeakBoolean(result) + + return nil +}