-
-
Notifications
You must be signed in to change notification settings - Fork 677
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix
/login
issue causing wrong device list updates (#2922)
- Loading branch information
Showing
3 changed files
with
160 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package routing | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" | ||
"github.com/matrix-org/dendrite/keyserver" | ||
"github.com/matrix-org/dendrite/roomserver" | ||
"github.com/matrix-org/dendrite/setup/config" | ||
"github.com/matrix-org/gomatrixserverlib" | ||
"github.com/matrix-org/util" | ||
|
||
"github.com/matrix-org/dendrite/test" | ||
"github.com/matrix-org/dendrite/test/testrig" | ||
"github.com/matrix-org/dendrite/userapi" | ||
uapi "github.com/matrix-org/dendrite/userapi/api" | ||
) | ||
|
||
func TestLogin(t *testing.T) { | ||
aliceAdmin := test.NewUser(t, test.WithAccountType(uapi.AccountTypeAdmin)) | ||
bobUser := &test.User{ID: "@bob:test", AccountType: uapi.AccountTypeUser} | ||
charlie := &test.User{ID: "@Charlie:test", AccountType: uapi.AccountTypeUser} | ||
vhUser := &test.User{ID: "@vhuser:vh1"} | ||
|
||
ctx := context.Background() | ||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) { | ||
base, baseClose := testrig.CreateBaseDendrite(t, dbType) | ||
defer baseClose() | ||
base.Cfg.ClientAPI.RateLimiting.Enabled = false | ||
// add a vhost | ||
base.Cfg.Global.VirtualHosts = append(base.Cfg.Global.VirtualHosts, &config.VirtualHost{ | ||
SigningIdentity: gomatrixserverlib.SigningIdentity{ServerName: "vh1"}, | ||
}) | ||
|
||
rsAPI := roomserver.NewInternalAPI(base) | ||
// Needed for /login | ||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI) | ||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil) | ||
keyAPI.SetUserAPI(userAPI) | ||
|
||
// We mostly need the userAPI for this test, so nil for other APIs/caches etc. | ||
Setup(base, &base.Cfg.ClientAPI, nil, nil, userAPI, nil, nil, nil, nil, nil, keyAPI, nil, &base.Cfg.MSCs, nil) | ||
|
||
// Create password | ||
password := util.RandomString(8) | ||
|
||
// create the users | ||
for _, u := range []*test.User{aliceAdmin, bobUser, vhUser, charlie} { | ||
localpart, serverName, _ := gomatrixserverlib.SplitID('@', u.ID) | ||
userRes := &uapi.PerformAccountCreationResponse{} | ||
|
||
if err := userAPI.PerformAccountCreation(ctx, &uapi.PerformAccountCreationRequest{ | ||
AccountType: u.AccountType, | ||
Localpart: localpart, | ||
ServerName: serverName, | ||
Password: password, | ||
}, userRes); err != nil { | ||
t.Errorf("failed to create account: %s", err) | ||
} | ||
if !userRes.AccountCreated { | ||
t.Fatalf("account not created") | ||
} | ||
} | ||
|
||
testCases := []struct { | ||
name string | ||
userID string | ||
wantOK bool | ||
}{ | ||
{ | ||
name: "aliceAdmin can login", | ||
userID: aliceAdmin.ID, | ||
wantOK: true, | ||
}, | ||
{ | ||
name: "bobUser can login", | ||
userID: bobUser.ID, | ||
wantOK: true, | ||
}, | ||
{ | ||
name: "vhuser can login", | ||
userID: vhUser.ID, | ||
wantOK: true, | ||
}, | ||
{ | ||
name: "bob with uppercase can login", | ||
userID: "@Bob:test", | ||
wantOK: true, | ||
}, | ||
{ | ||
name: "Charlie can login (existing uppercase)", | ||
userID: charlie.ID, | ||
wantOK: true, | ||
}, | ||
{ | ||
name: "Charlie can not login with lowercase userID", | ||
userID: strings.ToLower(charlie.ID), | ||
wantOK: false, | ||
}, | ||
} | ||
|
||
ctx := context.Background() | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
req := test.NewRequest(t, http.MethodPost, "/_matrix/client/v3/login", test.WithJSONBody(t, map[string]interface{}{ | ||
"type": authtypes.LoginTypePassword, | ||
"identifier": map[string]interface{}{ | ||
"type": "m.id.user", | ||
"user": tc.userID, | ||
}, | ||
"password": password, | ||
})) | ||
rec := httptest.NewRecorder() | ||
base.PublicClientAPIMux.ServeHTTP(rec, req) | ||
if tc.wantOK && rec.Code != http.StatusOK { | ||
t.Fatalf("failed to login: %s", rec.Body.String()) | ||
} | ||
|
||
t.Logf("Response: %s", rec.Body.String()) | ||
// get the response | ||
resp := loginResponse{} | ||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { | ||
t.Fatal(err) | ||
} | ||
// everything OK | ||
if !tc.wantOK && resp.AccessToken == "" { | ||
return | ||
} | ||
if tc.wantOK && resp.AccessToken == "" { | ||
t.Fatalf("expected accessToken after successful login but got none: %+v", resp) | ||
} | ||
|
||
devicesResp := &uapi.QueryDevicesResponse{} | ||
if err := userAPI.QueryDevices(ctx, &uapi.QueryDevicesRequest{UserID: resp.UserID}, devicesResp); err != nil { | ||
t.Fatal(err) | ||
} | ||
for _, dev := range devicesResp.Devices { | ||
// We expect the userID on the device to be the same as resp.UserID | ||
if dev.UserID != resp.UserID { | ||
t.Fatalf("unexpected userID on device: %s", dev.UserID) | ||
} | ||
} | ||
}) | ||
} | ||
}) | ||
} |