diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 0bda1e488..ce6076a71 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -19,6 +19,7 @@ import ( "context" "encoding/json" "fmt" + rsAPI "github.com/matrix-org/dendrite/roomserver/api" "io" "net/http" "net/url" @@ -536,6 +537,7 @@ func validateApplicationService( func Register( req *http.Request, userAPI userapi.ClientUserAPI, + clientRsApi rsAPI.ClientRoomserverAPI, cfg *config.ClientAPI, ) util.JSONResponse { defer req.Body.Close() // nolint: errcheck @@ -632,7 +634,7 @@ func Register( "session_id": r.Auth.Session, }).Info("Processing registration request") - return handleRegistrationFlow(req, r, sessionID, cfg, userAPI, accessToken, accessTokenErr) + return handleRegistrationFlow(req, r, sessionID, cfg, userAPI, accessToken, accessTokenErr, clientRsApi) } func handleGuestRegistration( @@ -707,6 +709,7 @@ func handleRegistrationFlow( userAPI userapi.ClientUserAPI, accessToken string, accessTokenErr error, + clientRsApi rsAPI.ClientRoomserverAPI, ) util.JSONResponse { // TODO: Enable registration config flag // TODO: Guest account upgrading @@ -775,8 +778,7 @@ func handleRegistrationFlow( // Check if the user's registration flow has been completed successfully // A response with current registration flow and remaining available methods // will be returned if a flow has not been successfully completed yet - return checkAndCompleteFlow(sessions.getCompletedStages(sessionID), - req, r, sessionID, cfg, userAPI) + return checkAndCompleteFlow(sessions.getCompletedStages(sessionID), req, r, sessionID, cfg, userAPI, clientRsApi) } // handleApplicationServiceRegistration handles the registration of an @@ -825,15 +827,25 @@ func handleApplicationServiceRegistration( // checkAndCompleteFlow checks if a given registration flow is completed given // a set of allowed flows. If so, registration is completed, otherwise a // response with -func checkAndCompleteFlow( - flow []authtypes.LoginType, +func checkAndCompleteFlow(flow []authtypes.LoginType, req *http.Request, r registerRequest, sessionID string, cfg *config.ClientAPI, userAPI userapi.ClientUserAPI, -) util.JSONResponse { + clientRsApi rsAPI.ClientRoomserverAPI) util.JSONResponse { + if checkFlowCompleted(flow, cfg.Derived.Registration.Flows) { + // POST register behavior: add user to room + for room := range cfg.AutoJoinRooms { + err := addUserToRoom(req.Context(), clientRsApi, cfg.AutoJoinRooms[room], r.Username, + userutil.MakeUserID(r.Username, cfg.Matrix.ServerName)) + if err != nil { + log.Fatal(err) + return util.JSONResponse{Code: http.StatusInternalServerError, + JSON: errorResponse(req.Context(), err, "Cannot add user to room.")} + } + } // This flow was completed, registration can continue return completeRegistration( req.Context(), userAPI, r.Username, r.Password, "", req.RemoteAddr, req.UserAgent(), sessionID, @@ -850,6 +862,24 @@ func checkAndCompleteFlow( } } +func addUserToRoom( + ctx context.Context, + clientRsAPI rsAPI.ClientRoomserverAPI, + roomID string, + username string, + userID string, +) error { + addGroupContent := make(map[string]interface{}) + addGroupContent["displayname"] = username + joinReq := rsAPI.PerformJoinRequest{ + RoomIDOrAlias: roomID, + UserID: userID, + Content: addGroupContent, + } + joinRes := rsAPI.PerformJoinResponse{} + return clientRsAPI.PerformJoin(ctx, &joinReq, &joinRes) +} + // completeRegistration runs some rudimentary checks against the submitted // input, then if successful creates an account and a newly associated device // We pass in each individual part of the request here instead of just passing a diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index 4ca8e59c5..1a1ed05d0 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -432,7 +432,7 @@ func Setup( if r := rateLimits.Limit(req, nil); r != nil { return *r } - return Register(req, userAPI, cfg) + return Register(req, userAPI, rsAPI, cfg) })).Methods(http.MethodPost, http.MethodOptions) v3mux.Handle("/register/available", httputil.MakeExternalAPI("registerAvailable", func(req *http.Request) util.JSONResponse { diff --git a/dendrite-sample.monolith.yaml b/dendrite-sample.monolith.yaml index eadb74a2a..c0f6fe99f 100644 --- a/dendrite-sample.monolith.yaml +++ b/dendrite-sample.monolith.yaml @@ -181,6 +181,9 @@ client_api: recaptcha_bypass_secret: "" recaptcha_siteverify_api: "" +# auto_join_rooms: +# - "#main:matrix.org" + # TURN server information that this homeserver should send to clients. turn: turn_user_lifetime: "5m" diff --git a/setup/config/config_clientapi.go b/setup/config/config_clientapi.go index 56f4b3f92..76e062172 100644 --- a/setup/config/config_clientapi.go +++ b/setup/config/config_clientapi.go @@ -29,6 +29,10 @@ type ClientAPI struct { // is forbidden either way. GuestsDisabled bool `yaml:"guests_disabled"` + // Users who register on this homeserver will automatically + // be joined to the rooms listed under this option. + AutoJoinRooms []string `yaml:"auto_join_rooms"` + // Boolean stating whether catpcha registration is enabled // and required RecaptchaEnabled bool `yaml:"enable_registration_captcha"`