Allow "registration is idempotent, with username specified" to pass (#2488)
Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
3cdefcf765
commit
289b3c5608
|
@ -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"
|
||||||
|
@ -68,9 +69,10 @@ const (
|
||||||
// It shouldn't be passed by value because it contains a mutex.
|
// It shouldn't be passed by value because it contains a mutex.
|
||||||
type sessionsDict struct {
|
type sessionsDict struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
sessions map[string][]authtypes.LoginType
|
sessions map[string][]authtypes.LoginType
|
||||||
params map[string]registerRequest
|
sessionCompletedResult map[string]registerResponse
|
||||||
timer map[string]*time.Timer
|
params map[string]registerRequest
|
||||||
|
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.
|
||||||
// If a UIA session is started by trying to delete device1, and then UIA is completed by deleting device2,
|
// If a UIA session is started by trying to delete device1, and then UIA is completed by deleting device2,
|
||||||
// the delete request will fail for device2 since the UIA was initiated by trying to delete device1.
|
// the delete request will fail for device2 since the UIA was initiated by trying to delete device1.
|
||||||
|
@ -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{
|
||||||
|
UserID: devRes.Device.UserID,
|
||||||
|
AccessToken: devRes.Device.AccessToken,
|
||||||
|
HomeServer: accRes.Account.ServerName,
|
||||||
|
DeviceID: devRes.Device.ID,
|
||||||
|
}
|
||||||
|
sessions.addCompletedRegistration(sessionID, result)
|
||||||
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: registerResponse{
|
JSON: result,
|
||||||
UserID: devRes.Device.UserID,
|
|
||||||
AccessToken: devRes.Device.AccessToken,
|
|
||||||
HomeServer: accRes.Account.ServerName,
|
|
||||||
DeviceID: devRes.Device.ID,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -716,6 +716,7 @@ 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
|
||||||
Setting state twice is idempotent
|
Setting state twice is idempotent
|
||||||
Joining room twice is idempotent
|
Joining room twice is idempotent
|
||||||
Inbound federation can return missing events for shared visibility
|
Inbound federation can return missing events for shared visibility
|
||||||
|
|
Loading…
Reference in a new issue