-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Server capabilities support #4472
Changes from 9 commits
53ef4da
a3f0556
95f871f
893107b
327b992
a124025
4eeb2fb
f03b3a7
19259d9
e4bef9d
c7837dc
2f46804
9c850d9
c5a0f82
ee4df7f
f834d98
b37e8c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Support exposing server capabilities in CS API (MSC1753, MSC1804) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2019 New Vector | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
import logging | ||
|
||
from twisted.internet import defer | ||
|
||
from synapse.http.servlet import RestServlet | ||
|
||
from ._base import client_v2_patterns | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class CapabilitiesRestServlet(RestServlet): | ||
"""End point to expose the capabilities of the server.""" | ||
|
||
PATTERNS = client_v2_patterns("/capabilities$") | ||
|
||
def __init__(self, hs): | ||
""" | ||
Args: | ||
hs (synapse.server.HomeServer): server | ||
""" | ||
super(CapabilitiesRestServlet, self).__init__() | ||
self.hs = hs | ||
self.auth = hs.get_auth() | ||
self.store = hs.get_datastore() | ||
|
||
@defer.inlineCallbacks | ||
def on_GET(self, request): | ||
requester = yield self.auth.get_user_by_req(request, allow_guest=True) | ||
user = yield self.store.get_user_by_id(requester.user.to_string()) | ||
change_password = bool(user['password_hash']) | ||
|
||
defer.returnValue( | ||
(200, { | ||
"capabilities": { | ||
"m.room_versions": { | ||
"default": "1", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should pull this in from |
||
"available": { | ||
"1": "stable", | ||
"2": "stable", | ||
"state-v2-test": "unstable", | ||
} | ||
}, | ||
"m.change_password": change_password, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. err, spec wants this to be
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
}) | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be nicer if you could move this out of the response = {
...
}
defer.returnValue((200, response)) it just makes it a lot easier to see what's going on |
||
|
||
|
||
def register_servlets(hs, http_server): | ||
CapabilitiesRestServlet(hs).register(http_server) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2019 New Vector Ltd | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from synapse.api.constants import DEFAULT_ROOM_VERSION, KNOWN_ROOM_VERSIONS | ||
from synapse.rest.client.v1 import admin, login | ||
from synapse.rest.client.v2_alpha import capabilities | ||
|
||
from tests import unittest | ||
|
||
|
||
class CapabilitiesTestCase(unittest.HomeserverTestCase): | ||
|
||
servlets = [ | ||
admin.register_servlets, | ||
capabilities.register_servlets, | ||
login.register_servlets, | ||
] | ||
|
||
def make_homeserver(self, reactor, clock): | ||
self.url = b"/_matrix/client/r0/capabilities" | ||
hs = self.setup_test_homeserver() | ||
self.store = hs.get_datastore() | ||
return hs | ||
|
||
def test_check_auth_required(self): | ||
request, channel = self.make_request("GET", self.url) | ||
self.render(request) | ||
|
||
self.assertEqual(channel.code, 401) | ||
|
||
def test_get_room_version_capabilities(self): | ||
self.register_user("user", "pass") | ||
access_token = self.login("user", "pass") | ||
|
||
request, channel = self.make_request("GET", self.url, access_token=access_token) | ||
self.render(request) | ||
capabilities = channel.json_body['capabilities'] | ||
|
||
self.assertEqual(channel.code, 200) | ||
for room_version in capabilities['m.room_versions']['available'].keys(): | ||
self.assertTrue(room_version in KNOWN_ROOM_VERSIONS, "" + room_version) | ||
self.assertEqual( | ||
DEFAULT_ROOM_VERSION, capabilities['m.room_versions']['default'] | ||
) | ||
|
||
def test_get_change_password_capabilities(self): | ||
localpart = "user" | ||
password = "pass" | ||
user = self.register_user(localpart, password) | ||
access_token = self.login(user, password) | ||
|
||
request, channel = self.make_request("GET", self.url, access_token=access_token) | ||
self.render(request) | ||
capabilities = channel.json_body['capabilities'] | ||
|
||
self.assertEqual(channel.code, 200) | ||
|
||
# Test case where password is handled outside of Synapse | ||
self.assertTrue(capabilities['m.change_password']) | ||
self.get_success(self.store.user_set_password_hash(user, None)) | ||
request, channel = self.make_request("GET", self.url, access_token=access_token) | ||
self.render(request) | ||
capabilities = channel.json_body['capabilities'] | ||
|
||
self.assertEqual(channel.code, 200) | ||
self.assertFalse(capabilities['m.change_password']) |
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 don't think it matters, but I'm a bit surprised this is still in 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.
This comment is now updated due to #4515