Support inhibit_login registration option (#532)

* Support inhibit_login registration option

* Fix completeRegistration func definition

* Change InhibitLogin to a WeakBoolean
This commit is contained in:
Andrew Morgan 2018-07-17 08:57:20 -07:00 committed by GitHub
parent a56752f3f6
commit dbbfd26be7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 10 deletions

View file

@ -40,6 +40,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/clientapi/userutil" "github.com/matrix-org/dendrite/clientapi/userutil"
"github.com/matrix-org/dendrite/common"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@ -116,7 +117,10 @@ type registerRequest struct {
InitialDisplayName *string `json:"initial_device_display_name"` 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. // request, whereas clients place it in the authDict struct.
Type authtypes.LoginType `json:"type"` 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 // http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register
type registerResponse struct { type registerResponse struct {
UserID string `json:"user_id"` UserID string `json:"user_id"`
AccessToken string `json:"access_token"` AccessToken string `json:"access_token,omitempty"`
HomeServer gomatrixserverlib.ServerName `json:"home_server"` 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 // recaptchaResponse represents the HTTP response from a Google Recaptcha server
@ -569,8 +573,10 @@ func handleRegistrationFlow(
// If no error, application service was successfully validated. // If no error, application service was successfully validated.
// Don't need to worry about appending to registration stages as // Don't need to worry about appending to registration stages as
// application service registration is entirely separate. // application service registration is entirely separate.
return completeRegistration(req.Context(), accountDB, deviceDB, return completeRegistration(
r.Username, "", appserviceID, r.InitialDisplayName) req.Context(), accountDB, deviceDB, r.Username, "", appserviceID,
r.InhibitLogin, r.InitialDisplayName,
)
case authtypes.LoginTypeDummy: case authtypes.LoginTypeDummy:
// there is nothing to do // there is nothing to do
@ -605,8 +611,10 @@ func checkAndCompleteFlow(
) util.JSONResponse { ) util.JSONResponse {
if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) { if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) {
// This flow was completed, registration can continue // This flow was completed, registration can continue
return completeRegistration(req.Context(), accountDB, deviceDB, return completeRegistration(
r.Username, r.Password, "", r.InitialDisplayName) req.Context(), accountDB, deviceDB, r.Username, r.Password, "",
r.InhibitLogin, r.InitialDisplayName,
)
} }
// There are still more stages to complete. // There are still more stages to complete.
@ -656,10 +664,10 @@ func LegacyRegister(
return util.MessageResponse(http.StatusForbidden, "HMAC incorrect") 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: case authtypes.LoginTypeDummy:
// there is nothing to do // 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: default:
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotImplemented, Code: http.StatusNotImplemented,
@ -702,6 +710,7 @@ func completeRegistration(
accountDB *accounts.Database, accountDB *accounts.Database,
deviceDB *devices.Database, deviceDB *devices.Database,
username, password, appserviceID string, username, password, appserviceID string,
inhibitLogin common.WeakBoolean,
displayName *string, displayName *string,
) util.JSONResponse { ) util.JSONResponse {
if username == "" { 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() token, err := auth.GenerateAccessToken()
if err != nil { if err != nil {
return util.JSONResponse{ 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) dev, err := deviceDB.CreateDevice(ctx, username, nil, token, displayName)
if err != nil { if err != nil {
return util.JSONResponse{ return util.JSONResponse{

View file

@ -14,6 +14,10 @@
package common package common
import (
"strconv"
)
// AccountData represents account data sent from the client API server to the // AccountData represents account data sent from the client API server to the
// sync API server // sync API server
type AccountData struct { type AccountData struct {
@ -36,3 +40,22 @@ type AvatarURL struct {
type DisplayName struct { type DisplayName struct {
DisplayName string `json:"displayname"` 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
}