-
-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MSC3861: MAS support #3493
base: main
Are you sure you want to change the base?
MSC3861: MAS support #3493
Conversation
i.e. /_synapse/admin/v1/users/{userID}/_allow_cross_signing_replacement_without_uia
If access token expires the client(i.e. element) expects a specific response with http code 401 and spec.UnknownToken
MAS requires this endpoint to fetch the data for the account management page
Extended logic of the endpoint in order to make it compatible with MAS
this change is based mostly on changes made in synapse https://github.com/element-hq/synapse/blob/develop/synapse/rest/client/keys.py#L392
Since MSC3861 is conflicting with standard reg/login flows, we require to disable them before running the server
…and related logic
@S7evinK the PR is ready for review again. I believe I have addressed all the comments. Please have another look when you have a moment. 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still didn't get around to finish this (sorry!), but as a first.
clientapi/admin_test.go
Outdated
if tc.wantOK { | ||
b := make(map[string]bool, 1) | ||
_ = json.NewDecoder(rec.Body).Decode(&b) | ||
available, ok := b["available"] | ||
if !ok { | ||
t.Fatal("'available' not found in body") | ||
} | ||
if available != tc.isAvailable { | ||
t.Fatalf("expected 'available' to be %t, got %t instead", tc.isAvailable, available) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go with the below, easier to read IMO.
if tc.wantOK { | |
b := make(map[string]bool, 1) | |
_ = json.NewDecoder(rec.Body).Decode(&b) | |
available, ok := b["available"] | |
if !ok { | |
t.Fatal("'available' not found in body") | |
} | |
if available != tc.isAvailable { | |
t.Fatalf("expected 'available' to be %t, got %t instead", tc.isAvailable, available) | |
} | |
} | |
// Nothing more to check, test is done. | |
if !tc.wantOK { | |
return | |
} | |
b := make(map[string]bool, 1) | |
_ = json.NewDecoder(rec.Body).Decode(&b) | |
available, ok := b["available"] | |
if !ok { | |
t.Fatal("'available' not found in body") | |
} | |
if available != tc.isAvailable { | |
t.Fatalf("expected 'available' to be %t, got %t instead", tc.isAvailable, available) | |
} |
clientapi/routing/routing.go
Outdated
default: | ||
return util.JSONResponse{Code: http.StatusMethodNotAllowed, JSON: nil} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that it matters much, but I think this is already handled at the router level. (i.e., we only accept PUT
and GET
, and have this for MethodNotAllowed
)
(No change required, as this makes it clearer here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I know it's dead code, but default is required by the compiler and I thought switch-case would be more readable than
if GET {
return this
}
return that
but anyway, I'll change this
internal/httputil/httpapi.go
Outdated
} | ||
} | ||
if token != serviceToken { | ||
logger.Debugf("Invalid service token '%s'", token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if it is invalid (maybe just a typo in the token at the end or such), better don't log it.
logger.Debugf("Invalid service token '%s'", token) | |
logger.Debugf("Invalid service token") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You’re right. I should have removed the variable from the message. I forgot to change it after debugging.
clientapi/admin_test.go
Outdated
} | ||
|
||
for _, tc := range testCase { | ||
t.Run("Retrieve existing account", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t.Run("Retrieve existing account", func(t *testing.T) { | |
t.Run(tc.Name, func(t *testing.T) { |
clientapi/routing/admin.go
Outdated
{ | ||
var rs api.QueryDevicesResponse | ||
if err = userAPI.QueryDevices(req.Context(), &api.QueryDevicesRequest{UserID: userID}, &rs); err != nil { | ||
logger.WithError(err).Error("QueryDevices") | ||
return util.JSONResponse{ | ||
Code: http.StatusInternalServerError, | ||
JSON: spec.InternalServerError{}, | ||
} | ||
} | ||
if !rs.UserExists { | ||
return util.JSONResponse{ | ||
Code: http.StatusNotFound, | ||
JSON: spec.NotFound("Given user ID does not exist"), | ||
} | ||
} | ||
for i := range rs.Devices { | ||
if d := rs.Devices[i]; d.ID == payload.DeviceID && d.UserID == userID { | ||
userDeviceExists = true | ||
break | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to put this in a block, I guess? (Or I missed something)
userapi/internal/key_api.go
Outdated
@@ -234,6 +234,19 @@ func (a *UserInternalAPI) PerformMarkAsStaleIfNeeded(ctx context.Context, req *a | |||
return a.Updater.ManualUpdate(ctx, req.Domain, req.UserID) | |||
} | |||
|
|||
func (a *UserInternalAPI) QueryMasterKeys(ctx context.Context, req *api.QueryMasterKeysRequest, res *api.QueryMasterKeysResponse) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May not be needed as noted elsewhere.
setup/monolith.go
Outdated
@@ -46,6 +50,8 @@ type Monolith struct { | |||
// Optional | |||
ExtPublicRoomsProvider api.ExtraPublicRoomsProvider | |||
ExtUserDirectoryProvider userapi.QuerySearchProfilesAPI | |||
|
|||
UserVerifierProvider *UserVerifierProvider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UserVerifierProvider *UserVerifierProvider | |
UserVerifierProvider httputil.UserVerifier |
setup/monolith.go
Outdated
type UserVerifierProvider struct { | ||
UserVerifier httputil.UserVerifier | ||
} | ||
|
||
func (u *UserVerifierProvider) VerifyUserFromRequest(req *http.Request) (*userapi.Device, *util.JSONResponse) { | ||
return u.UserVerifier.VerifyUserFromRequest(req) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type UserVerifierProvider struct { | |
UserVerifier httputil.UserVerifier | |
} | |
func (u *UserVerifierProvider) VerifyUserFromRequest(req *http.Request) (*userapi.Device, *util.JSONResponse) { | |
return u.UserVerifier.VerifyUserFromRequest(req) | |
} | |
type UserVerifierProvider struct { | |
httputil.UserVerifier | |
} | |
func (u *UserVerifierProvider) VerifyUserFromRequest(req *http.Request) (*userapi.Device, *util.JSONResponse) { | |
return u.VerifyUserFromRequest(req) | |
} |
IMHO this is easier to read and doesn't stutter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this is better, indeed. Didn't know about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have to keep return u.UserVerifier.VerifyUserFromRequest(req)
as it is because return u.VerifyUserFromRequest(req)
causes recursive calls
-- Stores data about connections between accounts and third-party auth providers | ||
CREATE TABLE IF NOT EXISTS userapi_localpart_external_ids ( | ||
-- The Matrix user ID for this account | ||
localpart TEXT NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given an initial implementation for vhosting in Dendrite, localpart
should either be user_id
(@test:example.com
) or use an additional server_name
column. (same for SQLite)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use this table to map local users with their MAS identifiers. Using localpart to identify local users is more than enough, whereas using the server name here does not make any sense because it will always be the same. It will be the same server name in each row.
Pull Request Checklist
Signed-off-by:
Roman Isaev <mdnight@riseup.net>