Support inhibit_login registration option

This commit is contained in:
Andrew Morgan 2018-06-29 15:37:17 +01:00
parent d2b349a75a
commit 1333cacb4c

View file

@ -16,7 +16,6 @@
package routing package routing
import ( import (
"context"
"crypto/hmac" "crypto/hmac"
"crypto/sha1" "crypto/sha1"
"encoding/json" "encoding/json"
@ -116,7 +115,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 int `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 +165,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
@ -552,8 +554,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, 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
@ -588,8 +592,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, accountDB, deviceDB, r.Username, r.Password, "",
r.InhibitLogin, r.InitialDisplayName,
)
} }
// There are still more stages to complete. // There are still more stages to complete.
@ -639,10 +645,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, accountDB, deviceDB, r.Username, r.Password, "", 0, 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, accountDB, deviceDB, r.Username, r.Password, "", 0, nil)
default: default:
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotImplemented, Code: http.StatusNotImplemented,
@ -681,11 +687,11 @@ func parseAndValidateLegacyLogin(req *http.Request, r *legacyRegisterRequest) *u
} }
func completeRegistration( func completeRegistration(
ctx context.Context, req *http.Request,
accountDB *accounts.Database, accountDB *accounts.Database,
deviceDB *devices.Database, deviceDB *devices.Database,
username, password, appserviceID string, username, password, appserviceID string,
displayName *string, inhibitLogin int, displayName *string,
) util.JSONResponse { ) util.JSONResponse {
if username == "" { if username == "" {
return util.JSONResponse{ return util.JSONResponse{
@ -701,7 +707,7 @@ func completeRegistration(
} }
} }
acc, err := accountDB.CreateAccount(ctx, username, password, appserviceID) acc, err := accountDB.CreateAccount(req.Context(), username, password, appserviceID)
if err != nil { if err != nil {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
@ -714,6 +720,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 != 0 {
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{
@ -722,8 +740,8 @@ 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(req.Context(), username, nil, token, displayName)
if err != nil { if err != nil {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,