mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-18 17:10:43 +03:00
Move endpoint to _synapse
This commit is contained in:
parent
1a796cbd38
commit
f7395bbd0a
5 changed files with 109 additions and 173 deletions
|
@ -33,7 +33,6 @@ CONTENT_REPO_PREFIX = "/_matrix/content"
|
|||
SERVER_KEY_V2_PREFIX = "/_matrix/key/v2"
|
||||
MEDIA_PREFIX = "/_matrix/media/r0"
|
||||
LEGACY_MEDIA_PREFIX = "/_matrix/media/v1"
|
||||
IDENTITY_PREFIX = "/_matrix/identity/api/v1"
|
||||
|
||||
|
||||
class ConsentURIBuilder(object):
|
||||
|
|
|
@ -40,7 +40,6 @@ from synapse import events
|
|||
from synapse.api.urls import (
|
||||
CONTENT_REPO_PREFIX,
|
||||
FEDERATION_PREFIX,
|
||||
IDENTITY_PREFIX,
|
||||
LEGACY_MEDIA_PREFIX,
|
||||
MEDIA_PREFIX,
|
||||
SERVER_KEY_V2_PREFIX,
|
||||
|
@ -64,7 +63,6 @@ from synapse.replication.http import REPLICATION_PREFIX, ReplicationRestResource
|
|||
from synapse.replication.tcp.resource import ReplicationStreamProtocolFactory
|
||||
from synapse.rest import ClientRestResource
|
||||
from synapse.rest.admin import AdminRestResource
|
||||
from synapse.rest.identity import IdentityRestResource
|
||||
from synapse.rest.key.v2 import KeyApiV2Resource
|
||||
from synapse.rest.media.v0.content_repository import ContentRepoResource
|
||||
from synapse.rest.well_known import WellKnownResource
|
||||
|
@ -190,10 +188,6 @@ class SynapseHomeServer(HomeServer):
|
|||
from synapse.rest.saml2 import SAML2Resource
|
||||
resources["/_matrix/saml2"] = SAML2Resource(self)
|
||||
|
||||
resources.update({
|
||||
IDENTITY_PREFIX: IdentityRestResource(self),
|
||||
})
|
||||
|
||||
if name == "consent":
|
||||
from synapse.rest.consent.consent_resource import ConsentResource
|
||||
consent_resource = ConsentResource(self)
|
||||
|
|
|
@ -15,17 +15,22 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import logging
|
||||
import re
|
||||
|
||||
from six.moves import http_client
|
||||
|
||||
import jinja2
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.api.constants import LoginType
|
||||
from synapse.api.errors import Codes, SynapseError
|
||||
from synapse.api.errors import Codes, SynapseError, ThreepidValidationError
|
||||
from synapse.http.server import finish_request
|
||||
from synapse.http.servlet import (
|
||||
RestServlet,
|
||||
assert_params_in_dict,
|
||||
parse_json_object_from_request,
|
||||
parse_string,
|
||||
)
|
||||
from synapse.util.msisdn import phone_number_to_msisdn
|
||||
from synapse.util.stringutils import random_string
|
||||
|
@ -221,6 +226,109 @@ class MsisdnPasswordRequestTokenRestServlet(RestServlet):
|
|||
defer.returnValue((200, ret))
|
||||
|
||||
|
||||
class ThreepidSubmitTokenServlet(RestServlet):
|
||||
"""Handles 3PID validation token submission"""
|
||||
PATTERNS = [
|
||||
re.compile("/_synapse/password_reset/validate/(email|msisdn)/submitToken/*$"),
|
||||
]
|
||||
|
||||
def __init__(self, hs):
|
||||
"""
|
||||
Args:
|
||||
hs (synapse.server.HomeServer): server
|
||||
"""
|
||||
self.hs = hs
|
||||
self.auth = hs.get_auth()
|
||||
self.config = hs.config
|
||||
self.clock = hs.get_clock()
|
||||
self.datastore = hs.get_datastore()
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_GET(self, request):
|
||||
sid = parse_string(request, "sid")
|
||||
client_secret = parse_string(request, "client_secret")
|
||||
token = parse_string(request, "token")
|
||||
|
||||
# Attempt to validate a 3PID sesssion
|
||||
try:
|
||||
# Mark the session as valid
|
||||
next_link = yield self.datastore.validate_threepid_session(
|
||||
sid,
|
||||
client_secret,
|
||||
token,
|
||||
self.clock.time_msec(),
|
||||
)
|
||||
|
||||
# Delete associated session tokens from the db as we have no
|
||||
# further use for them
|
||||
yield self.datastore.delete_threepid_tokens(sid)
|
||||
|
||||
# Perform a 302 redirect if next_link is set
|
||||
if next_link:
|
||||
if next_link.startswith("file:///"):
|
||||
logger.warn(
|
||||
"Not redirecting to next_link as it is a local file: address"
|
||||
)
|
||||
else:
|
||||
request.setResponseCode(302)
|
||||
request.setHeader("Location", next_link)
|
||||
finish_request(request)
|
||||
defer.returnValue(None)
|
||||
|
||||
# Otherwise show the success template
|
||||
html = self.config.email_password_reset_success_html_content
|
||||
request.setResponseCode(200)
|
||||
except ThreepidValidationError as e:
|
||||
# Show a failure page with a reason
|
||||
html = self.load_jinja2_template(
|
||||
self.config.email_template_dir,
|
||||
self.config.email_password_reset_failure_template,
|
||||
template_vars={
|
||||
"failure_reason": e.msg,
|
||||
}
|
||||
)
|
||||
request.setResponseCode(e.code)
|
||||
|
||||
request.write(html.encode('utf-8'))
|
||||
finish_request(request)
|
||||
defer.returnValue(None)
|
||||
|
||||
def load_jinja2_template(self, template_dir, template_filename, template_vars):
|
||||
"""Loads a jinja2 template with variables to insert
|
||||
|
||||
Args:
|
||||
template_dir (str): The directory where templates are stored
|
||||
template_filename (str): The name of the template in the template_dir
|
||||
template_vars (Dict): Dictionary of keys in the template
|
||||
alongside their values to insert
|
||||
|
||||
Returns:
|
||||
str containing the contents of the rendered template
|
||||
"""
|
||||
loader = jinja2.FileSystemLoader(template_dir)
|
||||
env = jinja2.Environment(loader=loader)
|
||||
|
||||
template = env.get_template(template_filename)
|
||||
return template.render(**template_vars)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_POST(self, request):
|
||||
body = parse_json_object_from_request(request)
|
||||
assert_params_in_dict(body, [
|
||||
'sid', 'client_secret', 'token',
|
||||
])
|
||||
|
||||
valid, _ = yield self.datastore.validate_threepid_validation_token(
|
||||
body['sid'],
|
||||
body['client_secret'],
|
||||
body['token'],
|
||||
self.clock.time_msec(),
|
||||
)
|
||||
response_code = 200 if valid else 400
|
||||
|
||||
defer.returnValue((response_code, {"success": valid}))
|
||||
|
||||
|
||||
class PasswordRestServlet(RestServlet):
|
||||
PATTERNS = client_patterns("/account/password$")
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# 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.http.server import JsonResource
|
||||
from synapse.rest.identity.threepid_submit_token_servlet import (
|
||||
ThreepidSubmitTokenServlet,
|
||||
)
|
||||
|
||||
|
||||
class IdentityRestResource(JsonResource):
|
||||
"""The REST resource which gets mounted at /_matrix/identity/api/v1"""
|
||||
|
||||
def __init__(self, hs):
|
||||
JsonResource.__init__(self, hs, canonical_json=False)
|
||||
|
||||
ThreepidSubmitTokenServlet(hs).register(self)
|
|
@ -1,137 +0,0 @@
|
|||
# -*- 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.
|
||||
import logging
|
||||
import re
|
||||
|
||||
import jinja2
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.api.errors import ThreepidValidationError
|
||||
from synapse.http.server import finish_request
|
||||
from synapse.http.servlet import (
|
||||
RestServlet,
|
||||
assert_params_in_dict,
|
||||
parse_json_object_from_request,
|
||||
parse_string,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def make_identity_path_pattern(path_regex):
|
||||
prefix = "/_matrix/identity/api/v1"
|
||||
return [re.compile(prefix + path_regex)]
|
||||
|
||||
|
||||
class ThreepidSubmitTokenServlet(RestServlet):
|
||||
"""Servlet which will handle 3PID token validation"""
|
||||
PATTERNS = make_identity_path_pattern("/validate/(email|msisdn)/submitToken/*$")
|
||||
|
||||
def __init__(self, hs):
|
||||
"""
|
||||
Args:
|
||||
hs (synapse.server.HomeServer): server
|
||||
"""
|
||||
self.hs = hs
|
||||
self.auth = hs.get_auth()
|
||||
self.config = hs.config
|
||||
self.clock = hs.get_clock()
|
||||
self.datastore = hs.get_datastore()
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_GET(self, request):
|
||||
sid = parse_string(request, "sid")
|
||||
client_secret = parse_string(request, "client_secret")
|
||||
token = parse_string(request, "token")
|
||||
|
||||
# Attempt to validate a 3PID sesssion
|
||||
try:
|
||||
# Mark the session as valid
|
||||
next_link = yield self.datastore.validate_threepid_session(
|
||||
sid,
|
||||
client_secret,
|
||||
token,
|
||||
self.clock.time_msec(),
|
||||
)
|
||||
|
||||
# Delete associated session tokens from the db as we have no
|
||||
# further use for them
|
||||
yield self.datastore.delete_threepid_tokens(sid)
|
||||
|
||||
# Perform a 302 redirect if next_link is set
|
||||
if next_link:
|
||||
if next_link.startswith("file:///"):
|
||||
logger.warn(
|
||||
"Not redirecting to next_link as it is a local file: address"
|
||||
)
|
||||
else:
|
||||
request.setResponseCode(302)
|
||||
request.setHeader("Location", next_link)
|
||||
finish_request(request)
|
||||
defer.returnValue(None)
|
||||
|
||||
# Otherwise show the success template
|
||||
html = self.config.email_password_reset_success_html_content
|
||||
request.setResponseCode(200)
|
||||
except ThreepidValidationError as e:
|
||||
# Show a failure page with a reason
|
||||
html = self.load_jinja2_template(
|
||||
self.config.email_template_dir,
|
||||
self.config.email_password_reset_failure_template,
|
||||
template_vars={
|
||||
"failure_reason": e.msg,
|
||||
}
|
||||
)
|
||||
request.setResponseCode(e.code)
|
||||
|
||||
request.write(html.encode('utf-8'))
|
||||
finish_request(request)
|
||||
defer.returnValue(None)
|
||||
|
||||
def load_jinja2_template(self, template_dir, template_filename, template_vars):
|
||||
"""Loads a jinja2 template with variables to insert
|
||||
|
||||
Args:
|
||||
template_dir (str): The directory where templates are stored
|
||||
template_filename (str): The name of the template in the template_dir
|
||||
template_vars (Dict): Dictionary of keys in the template
|
||||
alongside their values to insert
|
||||
|
||||
Returns:
|
||||
str containing the contents of the rendered template
|
||||
"""
|
||||
loader = jinja2.FileSystemLoader(template_dir)
|
||||
env = jinja2.Environment(loader=loader)
|
||||
|
||||
template = env.get_template(template_filename)
|
||||
return template.render(**template_vars)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_POST(self, request):
|
||||
body = parse_json_object_from_request(request)
|
||||
assert_params_in_dict(body, [
|
||||
'sid', 'client_secret', 'token',
|
||||
])
|
||||
|
||||
valid, _ = yield self.datastore.validate_threepid_validation_token(
|
||||
body['sid'],
|
||||
body['client_secret'],
|
||||
body['token'],
|
||||
self.clock.time_msec(),
|
||||
)
|
||||
response_code = 200 if valid else 400
|
||||
|
||||
defer.returnValue((response_code, {"success": valid}))
|
Loading…
Reference in a new issue