Allow "registration is idempotent, with username specified" to pass

This commit is contained in:
Till Faelligen 2022-05-25 12:22:23 +02:00
parent 81843e8836
commit 43708f23e4
2 changed files with 40 additions and 20 deletions

View file

@ -29,9 +29,10 @@ import (
"sync" "sync"
"time" "time"
"github.com/tidwall/gjson"
"github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/internal/eventutil"
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
"github.com/tidwall/gjson"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/tokens" "github.com/matrix-org/gomatrixserverlib/tokens"
@ -69,6 +70,7 @@ const (
type sessionsDict struct { type sessionsDict struct {
sync.RWMutex sync.RWMutex
sessions map[string][]authtypes.LoginType sessions map[string][]authtypes.LoginType
sessionCompletedResult map[string]registerResponse
params map[string]registerRequest params map[string]registerRequest
timer map[string]*time.Timer timer map[string]*time.Timer
// deleteSessionToDeviceID protects requests to DELETE /devices/{deviceID} from being abused. // deleteSessionToDeviceID protects requests to DELETE /devices/{deviceID} from being abused.
@ -115,6 +117,7 @@ func (d *sessionsDict) deleteSession(sessionID string) {
delete(d.params, sessionID) delete(d.params, sessionID)
delete(d.sessions, sessionID) delete(d.sessions, sessionID)
delete(d.deleteSessionToDeviceID, sessionID) delete(d.deleteSessionToDeviceID, sessionID)
delete(d.sessionCompletedResult, sessionID)
// stop the timer, e.g. because the registration was completed // stop the timer, e.g. because the registration was completed
if t, ok := d.timer[sessionID]; ok { if t, ok := d.timer[sessionID]; ok {
if !t.Stop() { if !t.Stop() {
@ -130,6 +133,7 @@ func (d *sessionsDict) deleteSession(sessionID string) {
func newSessionsDict() *sessionsDict { func newSessionsDict() *sessionsDict {
return &sessionsDict{ return &sessionsDict{
sessions: make(map[string][]authtypes.LoginType), sessions: make(map[string][]authtypes.LoginType),
sessionCompletedResult: make(map[string]registerResponse),
params: make(map[string]registerRequest), params: make(map[string]registerRequest),
timer: make(map[string]*time.Timer), timer: make(map[string]*time.Timer),
deleteSessionToDeviceID: make(map[string]string), deleteSessionToDeviceID: make(map[string]string),
@ -173,6 +177,19 @@ func (d *sessionsDict) addDeviceToDelete(sessionID, deviceID string) {
d.deleteSessionToDeviceID[sessionID] = deviceID d.deleteSessionToDeviceID[sessionID] = deviceID
} }
func (d *sessionsDict) addCompletedRegistration(sessionID string, response registerResponse) {
d.Lock()
defer d.Unlock()
d.sessionCompletedResult[sessionID] = response
}
func (d *sessionsDict) getCompletedRegistration(sessionID string) (registerResponse, bool) {
d.RLock()
defer d.RUnlock()
result, ok := d.sessionCompletedResult[sessionID]
return result, ok
}
func (d *sessionsDict) getDeviceToDelete(sessionID string) (string, bool) { func (d *sessionsDict) getDeviceToDelete(sessionID string) (string, bool) {
d.RLock() d.RLock()
defer d.RUnlock() defer d.RUnlock()
@ -544,6 +561,14 @@ func Register(
r.DeviceID = data.DeviceID r.DeviceID = data.DeviceID
r.InitialDisplayName = data.InitialDisplayName r.InitialDisplayName = data.InitialDisplayName
r.InhibitLogin = data.InhibitLogin r.InhibitLogin = data.InhibitLogin
// Check if the user already registered using this session, if so, return that result
if response, ok := sessions.getCompletedRegistration(sessionID); ok {
return util.JSONResponse{
Code: http.StatusOK,
JSON: response,
}
}
} }
if resErr := httputil.UnmarshalJSON(reqBody, &r); resErr != nil { if resErr := httputil.UnmarshalJSON(reqBody, &r); resErr != nil {
return *resErr return *resErr
@ -839,13 +864,6 @@ func completeRegistration(
displayName, deviceID *string, displayName, deviceID *string,
accType userapi.AccountType, accType userapi.AccountType,
) util.JSONResponse { ) util.JSONResponse {
var registrationOK bool
defer func() {
if registrationOK {
sessions.deleteSession(sessionID)
}
}()
if username == "" { if username == "" {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
@ -886,7 +904,6 @@ func completeRegistration(
// Check whether inhibit_login option is set. If so, don't create an access // Check whether inhibit_login option is set. If so, don't create an access
// token or a device for this user // token or a device for this user
if inhibitLogin { if inhibitLogin {
registrationOK = true
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
JSON: registerResponse{ JSON: registerResponse{
@ -920,15 +937,17 @@ func completeRegistration(
} }
} }
registrationOK = true result := registerResponse{
return util.JSONResponse{
Code: http.StatusOK,
JSON: registerResponse{
UserID: devRes.Device.UserID, UserID: devRes.Device.UserID,
AccessToken: devRes.Device.AccessToken, AccessToken: devRes.Device.AccessToken,
HomeServer: accRes.Account.ServerName, HomeServer: accRes.Account.ServerName,
DeviceID: devRes.Device.ID, DeviceID: devRes.Device.ID,
}, }
sessions.addCompletedRegistration(sessionID, result)
return util.JSONResponse{
Code: http.StatusOK,
JSON: result,
} }
} }

View file

@ -716,3 +716,4 @@ PUT /rooms/:room_id/redact/:event_id/:txn_id is idempotent
Unnamed room comes with a name summary Unnamed room comes with a name summary
Named room comes with just joined member count summary Named room comes with just joined member count summary
Room summary only has 5 heroes Room summary only has 5 heroes
registration is idempotent, with username specified