2015-03-23 14:20:28 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2016-01-07 04:26:29 +00:00
|
|
|
# Copyright 2015, 2016 OpenMarket Ltd
|
2017-03-13 17:27:51 +00:00
|
|
|
# Copyright 2017 Vector Creations Ltd
|
2018-06-25 12:42:55 +00:00
|
|
|
# Copyright 2018 New Vector Ltd
|
2015-03-23 14:20:28 +00:00
|
|
|
#
|
|
|
|
# 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.
|
2017-10-26 23:01:00 +00:00
|
|
|
import logging
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2018-06-25 12:42:55 +00:00
|
|
|
from six.moves import http_client
|
2018-07-09 06:09:20 +00:00
|
|
|
|
2015-03-23 14:20:28 +00:00
|
|
|
from twisted.internet import defer
|
|
|
|
|
|
|
|
from synapse.api.constants import LoginType
|
2019-09-20 14:21:30 +00:00
|
|
|
from synapse.api.errors import (
|
|
|
|
Codes,
|
|
|
|
HttpResponseException,
|
|
|
|
SynapseError,
|
|
|
|
ThreepidValidationError,
|
|
|
|
)
|
2019-09-06 10:35:28 +00:00
|
|
|
from synapse.config.emailconfig import ThreepidBehaviour
|
2019-06-06 16:34:07 +00:00
|
|
|
from synapse.http.server import finish_request
|
2017-03-13 17:27:51 +00:00
|
|
|
from synapse.http.servlet import (
|
2018-07-09 06:09:20 +00:00
|
|
|
RestServlet,
|
2018-07-13 19:53:01 +00:00
|
|
|
assert_params_in_dict,
|
2017-10-26 23:01:00 +00:00
|
|
|
parse_json_object_from_request,
|
2019-06-06 16:34:07 +00:00
|
|
|
parse_string,
|
2017-03-13 17:27:51 +00:00
|
|
|
)
|
2019-09-06 10:35:28 +00:00
|
|
|
from synapse.push.mailer import Mailer, load_jinja2_templates
|
2017-03-13 17:27:51 +00:00
|
|
|
from synapse.util.msisdn import phone_number_to_msisdn
|
2018-01-19 15:33:55 +00:00
|
|
|
from synapse.util.threepids import check_3pid_allowed
|
2018-07-09 06:09:20 +00:00
|
|
|
|
2019-06-03 11:28:59 +00:00
|
|
|
from ._base import client_patterns, interactive_auth_handler
|
2015-03-23 14:20:28 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2017-03-13 17:27:51 +00:00
|
|
|
class EmailPasswordRequestTokenRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/password/email/requestToken$")
|
2016-07-11 08:57:07 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
2017-03-13 17:27:51 +00:00
|
|
|
super(EmailPasswordRequestTokenRestServlet, self).__init__()
|
2016-07-11 08:57:07 +00:00
|
|
|
self.hs = hs
|
2019-06-06 16:34:07 +00:00
|
|
|
self.datastore = hs.get_datastore()
|
|
|
|
self.config = hs.config
|
2016-07-11 08:57:07 +00:00
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
|
|
|
|
template_html, template_text = load_jinja2_templates(
|
|
|
|
self.config.email_template_dir,
|
|
|
|
[
|
|
|
|
self.config.email_password_reset_template_html,
|
|
|
|
self.config.email_password_reset_template_text,
|
|
|
|
],
|
|
|
|
apply_format_ts_filter=True,
|
|
|
|
apply_mxc_to_http_filter=True,
|
|
|
|
public_baseurl=self.config.public_baseurl,
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
|
|
|
self.mailer = Mailer(
|
|
|
|
hs=self.hs,
|
|
|
|
app_name=self.config.email_app_name,
|
2019-09-06 10:35:28 +00:00
|
|
|
template_html=template_html,
|
|
|
|
template_text=template_text,
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
|
|
|
|
2016-07-11 08:57:07 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
2019-09-06 10:35:28 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.OFF:
|
|
|
|
if self.config.local_threepid_handling_disabled_due_to_email_config:
|
2019-06-10 23:25:07 +00:00
|
|
|
logger.warn(
|
|
|
|
"User password resets have been disabled due to lack of email config"
|
|
|
|
)
|
|
|
|
raise SynapseError(
|
2019-06-20 09:32:02 +00:00
|
|
|
400, "Email-based password resets have been disabled on this server"
|
2019-06-10 23:25:07 +00:00
|
|
|
)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
2016-07-11 08:57:07 +00:00
|
|
|
body = parse_json_object_from_request(request)
|
|
|
|
|
2019-06-20 09:32:02 +00:00
|
|
|
assert_params_in_dict(body, ["client_secret", "email", "send_attempt"])
|
2016-07-11 08:57:07 +00:00
|
|
|
|
2019-06-06 16:34:07 +00:00
|
|
|
# Extract params from body
|
|
|
|
client_secret = body["client_secret"]
|
|
|
|
email = body["email"]
|
|
|
|
send_attempt = body["send_attempt"]
|
|
|
|
next_link = body.get("next_link") # Optional param
|
|
|
|
|
|
|
|
if not check_3pid_allowed(self.hs, "email", email):
|
2018-01-19 00:53:58 +00:00
|
|
|
raise SynapseError(
|
2018-09-04 11:03:17 +00:00
|
|
|
403,
|
|
|
|
"Your email domain is not authorized on this server",
|
|
|
|
Codes.THREEPID_DENIED,
|
2018-01-19 00:53:58 +00:00
|
|
|
)
|
2018-01-19 00:19:58 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
existing_user_id = yield self.hs.get_datastore().get_user_id_by_threepid(
|
2019-06-20 09:32:02 +00:00
|
|
|
"email", email
|
2016-07-11 08:57:07 +00:00
|
|
|
)
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if existing_user_id is None:
|
2016-07-11 08:57:07 +00:00
|
|
|
raise SynapseError(400, "Email not found", Codes.THREEPID_NOT_FOUND)
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
|
2019-09-20 14:21:30 +00:00
|
|
|
assert self.hs.config.account_threepid_delegate_email
|
2019-06-06 16:34:07 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
# Have the configured identity server handle the request
|
2019-06-06 16:34:07 +00:00
|
|
|
ret = yield self.identity_handler.requestEmailToken(
|
2019-09-06 10:35:28 +00:00
|
|
|
self.hs.config.account_threepid_delegate_email,
|
|
|
|
email,
|
|
|
|
client_secret,
|
|
|
|
send_attempt,
|
|
|
|
next_link,
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
# Send password reset emails from Synapse
|
2019-09-06 10:35:28 +00:00
|
|
|
sid = yield self.identity_handler.send_threepid_validation(
|
|
|
|
email,
|
|
|
|
client_secret,
|
|
|
|
send_attempt,
|
|
|
|
self.mailer.send_password_reset_mail,
|
|
|
|
next_link,
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# Wrap the session id in a JSON object
|
|
|
|
ret = {"sid": sid}
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, ret
|
2016-07-11 08:57:07 +00:00
|
|
|
|
|
|
|
|
2017-03-13 17:27:51 +00:00
|
|
|
class MsisdnPasswordRequestTokenRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/password/msisdn/requestToken$")
|
2017-03-13 17:27:51 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
super(MsisdnPasswordRequestTokenRestServlet, self).__init__()
|
|
|
|
self.hs = hs
|
|
|
|
self.datastore = self.hs.get_datastore()
|
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
|
|
|
body = parse_json_object_from_request(request)
|
|
|
|
|
2019-06-20 09:32:02 +00:00
|
|
|
assert_params_in_dict(
|
2019-09-06 10:35:28 +00:00
|
|
|
body, ["client_secret", "country", "phone_number", "send_attempt"]
|
2019-06-20 09:32:02 +00:00
|
|
|
)
|
2019-09-06 10:35:28 +00:00
|
|
|
client_secret = body["client_secret"]
|
|
|
|
country = body["country"]
|
|
|
|
phone_number = body["phone_number"]
|
|
|
|
send_attempt = body["send_attempt"]
|
|
|
|
next_link = body.get("next_link") # Optional param
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
msisdn = phone_number_to_msisdn(country, phone_number)
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2018-01-19 00:19:58 +00:00
|
|
|
if not check_3pid_allowed(self.hs, "msisdn", msisdn):
|
2018-01-19 00:53:58 +00:00
|
|
|
raise SynapseError(
|
2018-09-04 11:03:17 +00:00
|
|
|
403,
|
|
|
|
"Account phone numbers are not authorized on this server",
|
|
|
|
Codes.THREEPID_DENIED,
|
2018-01-19 00:53:58 +00:00
|
|
|
)
|
2018-01-19 00:19:58 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
existing_user_id = yield self.datastore.get_user_id_by_threepid(
|
|
|
|
"msisdn", msisdn
|
|
|
|
)
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if existing_user_id is None:
|
2017-03-13 17:27:51 +00:00
|
|
|
raise SynapseError(400, "MSISDN not found", Codes.THREEPID_NOT_FOUND)
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if not self.hs.config.account_threepid_delegate_msisdn:
|
|
|
|
logger.warn(
|
|
|
|
"No upstream msisdn account_threepid_delegate configured on the server to "
|
|
|
|
"handle this request"
|
|
|
|
)
|
|
|
|
raise SynapseError(
|
|
|
|
400,
|
|
|
|
"Password reset by phone number is not supported on this homeserver",
|
|
|
|
)
|
|
|
|
|
|
|
|
ret = yield self.identity_handler.requestMsisdnToken(
|
|
|
|
self.hs.config.account_threepid_delegate_msisdn,
|
|
|
|
country,
|
|
|
|
phone_number,
|
|
|
|
client_secret,
|
|
|
|
send_attempt,
|
|
|
|
next_link,
|
|
|
|
)
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, ret
|
2017-03-13 17:27:51 +00:00
|
|
|
|
|
|
|
|
2019-06-06 16:34:07 +00:00
|
|
|
class PasswordResetSubmitTokenServlet(RestServlet):
|
|
|
|
"""Handles 3PID validation token submission"""
|
2019-06-20 09:32:02 +00:00
|
|
|
|
2019-06-11 10:31:12 +00:00
|
|
|
PATTERNS = client_patterns(
|
2019-09-20 13:58:37 +00:00
|
|
|
"/password_reset/(?P<medium>[^/]*)/submit_token$", releases=(), unstable=True
|
2019-06-11 10:31:12 +00:00
|
|
|
)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
"""
|
|
|
|
Args:
|
|
|
|
hs (synapse.server.HomeServer): server
|
|
|
|
"""
|
|
|
|
super(PasswordResetSubmitTokenServlet, self).__init__()
|
|
|
|
self.hs = hs
|
|
|
|
self.auth = hs.get_auth()
|
|
|
|
self.config = hs.config
|
|
|
|
self.clock = hs.get_clock()
|
2019-09-06 10:35:28 +00:00
|
|
|
self.store = hs.get_datastore()
|
2019-09-20 14:21:30 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
|
|
|
|
self.failure_email_template, = load_jinja2_templates(
|
|
|
|
self.config.email_template_dir,
|
|
|
|
[self.config.email_password_reset_template_failure_html],
|
|
|
|
)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_GET(self, request, medium):
|
2019-09-06 10:35:28 +00:00
|
|
|
# We currently only handle threepid token submissions for email
|
2019-06-06 16:34:07 +00:00
|
|
|
if medium != "email":
|
|
|
|
raise SynapseError(
|
2019-06-20 09:32:02 +00:00
|
|
|
400, "This medium is currently not supported for password resets"
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
2019-09-06 10:35:28 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.OFF:
|
|
|
|
if self.config.local_threepid_handling_disabled_due_to_email_config:
|
2019-06-10 23:25:07 +00:00
|
|
|
logger.warn(
|
2019-09-06 10:35:28 +00:00
|
|
|
"Password reset emails have been disabled due to lack of an email config"
|
2019-06-10 23:25:07 +00:00
|
|
|
)
|
|
|
|
raise SynapseError(
|
2019-09-06 10:35:28 +00:00
|
|
|
400, "Email-based password resets are disabled on this server"
|
2019-06-10 23:25:07 +00:00
|
|
|
)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
sid = parse_string(request, "sid", required=True)
|
|
|
|
client_secret = parse_string(request, "client_secret", required=True)
|
|
|
|
token = parse_string(request, "token", required=True)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
# Attempt to validate a 3PID session
|
2019-06-06 16:34:07 +00:00
|
|
|
try:
|
|
|
|
# Mark the session as valid
|
2019-09-06 10:35:28 +00:00
|
|
|
next_link = yield self.store.validate_threepid_session(
|
2019-06-20 09:32:02 +00:00
|
|
|
sid, client_secret, token, self.clock.time_msec()
|
2019-06-06 16:34:07 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# 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)
|
2019-07-23 13:00:55 +00:00
|
|
|
return None
|
2019-06-06 16:34:07 +00:00
|
|
|
|
|
|
|
# Otherwise show the success template
|
2019-09-06 10:35:28 +00:00
|
|
|
html = self.config.email_password_reset_template_success_html
|
2019-06-06 16:34:07 +00:00
|
|
|
request.setResponseCode(200)
|
|
|
|
except ThreepidValidationError as e:
|
2019-09-06 10:35:28 +00:00
|
|
|
request.setResponseCode(e.code)
|
|
|
|
|
2019-06-06 16:34:07 +00:00
|
|
|
# Show a failure page with a reason
|
2019-09-06 10:35:28 +00:00
|
|
|
template_vars = {"failure_reason": e.msg}
|
2019-09-20 14:21:30 +00:00
|
|
|
html = self.failure_email_template.render(**template_vars)
|
2019-06-06 16:34:07 +00:00
|
|
|
|
2019-06-20 09:32:02 +00:00
|
|
|
request.write(html.encode("utf-8"))
|
2019-06-06 16:34:07 +00:00
|
|
|
finish_request(request)
|
|
|
|
|
|
|
|
|
2015-03-23 14:20:28 +00:00
|
|
|
class PasswordRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/password$")
|
2015-03-23 14:20:28 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
super(PasswordRestServlet, self).__init__()
|
|
|
|
self.hs = hs
|
|
|
|
self.auth = hs.get_auth()
|
2016-06-02 12:31:45 +00:00
|
|
|
self.auth_handler = hs.get_auth_handler()
|
2017-03-13 17:27:51 +00:00
|
|
|
self.datastore = self.hs.get_datastore()
|
2017-11-29 14:10:46 +00:00
|
|
|
self._set_password_handler = hs.get_set_password_handler()
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2017-12-04 15:47:27 +00:00
|
|
|
@interactive_auth_handler
|
2015-03-23 14:20:28 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
2016-03-09 11:26:26 +00:00
|
|
|
body = parse_json_object_from_request(request)
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2017-12-04 16:38:10 +00:00
|
|
|
# there are two possibilities here. Either the user does not have an
|
|
|
|
# access token, and needs to do a password reset; or they have one and
|
|
|
|
# need to validate their identity.
|
|
|
|
#
|
|
|
|
# In the first case, we offer a couple of means of identifying
|
|
|
|
# themselves (email and msisdn, though it's unclear if msisdn actually
|
|
|
|
# works).
|
|
|
|
#
|
|
|
|
# In the second case, we require a password to confirm their identity.
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2018-07-13 21:34:49 +00:00
|
|
|
if self.auth.has_access_token(request):
|
2016-01-11 15:29:57 +00:00
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
2017-12-04 16:38:10 +00:00
|
|
|
params = yield self.auth_handler.validate_user_via_ui_auth(
|
2019-06-20 09:32:02 +00:00
|
|
|
requester, body, self.hs.get_ip_from_request(request)
|
2015-04-17 18:53:47 +00:00
|
|
|
)
|
2017-12-04 16:38:10 +00:00
|
|
|
user_id = requester.user.to_string()
|
2015-03-23 14:20:28 +00:00
|
|
|
else:
|
2017-12-04 16:38:10 +00:00
|
|
|
requester = None
|
|
|
|
result, params, _ = yield self.auth_handler.check_auth(
|
|
|
|
[[LoginType.EMAIL_IDENTITY], [LoginType.MSISDN]],
|
2019-06-20 09:32:02 +00:00
|
|
|
body,
|
|
|
|
self.hs.get_ip_from_request(request),
|
2017-12-04 16:38:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if LoginType.EMAIL_IDENTITY in result:
|
|
|
|
threepid = result[LoginType.EMAIL_IDENTITY]
|
2019-06-20 09:32:02 +00:00
|
|
|
if "medium" not in threepid or "address" not in threepid:
|
2017-12-04 16:38:10 +00:00
|
|
|
raise SynapseError(500, "Malformed threepid")
|
2019-06-20 09:32:02 +00:00
|
|
|
if threepid["medium"] == "email":
|
2017-12-04 16:38:10 +00:00
|
|
|
# For emails, transform the address to lowercase.
|
|
|
|
# We store all email addreses as lowercase in the DB.
|
|
|
|
# (See add_threepid in synapse/handlers/auth.py)
|
2019-06-20 09:32:02 +00:00
|
|
|
threepid["address"] = threepid["address"].lower()
|
2017-12-04 16:38:10 +00:00
|
|
|
# if using email, we must know about the email they're authing with!
|
|
|
|
threepid_user_id = yield self.datastore.get_user_id_by_threepid(
|
2019-06-20 09:32:02 +00:00
|
|
|
threepid["medium"], threepid["address"]
|
2017-12-04 16:38:10 +00:00
|
|
|
)
|
|
|
|
if not threepid_user_id:
|
|
|
|
raise SynapseError(404, "Email address not found", Codes.NOT_FOUND)
|
|
|
|
user_id = threepid_user_id
|
|
|
|
else:
|
2018-07-13 19:40:14 +00:00
|
|
|
logger.error("Auth succeeded but no known type! %r", result.keys())
|
2017-12-04 16:38:10 +00:00
|
|
|
raise SynapseError(500, "", Codes.UNKNOWN)
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2018-07-13 19:53:01 +00:00
|
|
|
assert_params_in_dict(params, ["new_password"])
|
2019-06-20 09:32:02 +00:00
|
|
|
new_password = params["new_password"]
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2019-06-20 09:32:02 +00:00
|
|
|
yield self._set_password_handler.set_password(user_id, new_password, requester)
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {}
|
2015-03-23 14:20:28 +00:00
|
|
|
|
2016-07-11 08:57:07 +00:00
|
|
|
def on_OPTIONS(self, _):
|
|
|
|
return 200, {}
|
|
|
|
|
|
|
|
|
2016-07-14 08:56:53 +00:00
|
|
|
class DeactivateAccountRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/deactivate$")
|
2016-07-14 08:56:53 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
2017-11-29 11:48:43 +00:00
|
|
|
super(DeactivateAccountRestServlet, self).__init__()
|
2016-07-14 09:25:52 +00:00
|
|
|
self.hs = hs
|
2016-07-14 08:56:53 +00:00
|
|
|
self.auth = hs.get_auth()
|
|
|
|
self.auth_handler = hs.get_auth_handler()
|
2017-11-29 11:48:43 +00:00
|
|
|
self._deactivate_account_handler = hs.get_deactivate_account_handler()
|
2016-07-14 08:56:53 +00:00
|
|
|
|
2017-12-04 15:47:27 +00:00
|
|
|
@interactive_auth_handler
|
2016-07-14 08:56:53 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
|
|
|
body = parse_json_object_from_request(request)
|
2018-06-25 12:42:55 +00:00
|
|
|
erase = body.get("erase", False)
|
|
|
|
if not isinstance(erase, bool):
|
|
|
|
raise SynapseError(
|
|
|
|
http_client.BAD_REQUEST,
|
|
|
|
"Param 'erase' must be a boolean, if given",
|
|
|
|
Codes.BAD_JSON,
|
|
|
|
)
|
2016-07-14 08:56:53 +00:00
|
|
|
|
2017-12-04 16:38:10 +00:00
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
2017-10-26 23:01:00 +00:00
|
|
|
|
|
|
|
# allow ASes to dectivate their own users
|
2017-12-04 16:38:10 +00:00
|
|
|
if requester.app_service:
|
2017-11-29 11:48:43 +00:00
|
|
|
yield self._deactivate_account_handler.deactivate_account(
|
2019-06-20 09:32:02 +00:00
|
|
|
requester.user.to_string(), erase
|
2017-11-01 10:29:34 +00:00
|
|
|
)
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {}
|
2017-10-26 23:01:00 +00:00
|
|
|
|
2017-12-04 16:38:10 +00:00
|
|
|
yield self.auth_handler.validate_user_via_ui_auth(
|
2019-06-20 09:32:02 +00:00
|
|
|
requester, body, self.hs.get_ip_from_request(request)
|
2017-12-04 16:38:10 +00:00
|
|
|
)
|
2018-08-08 10:54:55 +00:00
|
|
|
result = yield self._deactivate_account_handler.deactivate_account(
|
2019-06-20 09:32:02 +00:00
|
|
|
requester.user.to_string(), erase, id_server=body.get("id_server")
|
2017-12-04 16:38:10 +00:00
|
|
|
)
|
2018-08-08 10:54:55 +00:00
|
|
|
if result:
|
|
|
|
id_server_unbind_result = "success"
|
|
|
|
else:
|
|
|
|
id_server_unbind_result = "no-support"
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {"id_server_unbind_result": id_server_unbind_result}
|
2017-10-26 23:01:00 +00:00
|
|
|
|
2016-07-14 08:56:53 +00:00
|
|
|
|
2017-03-13 17:27:51 +00:00
|
|
|
class EmailThreepidRequestTokenRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/3pid/email/requestToken$")
|
2016-07-11 08:57:07 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
2017-03-13 17:27:51 +00:00
|
|
|
super(EmailThreepidRequestTokenRestServlet, self).__init__()
|
2019-09-06 10:35:28 +00:00
|
|
|
self.hs = hs
|
|
|
|
self.config = hs.config
|
2016-07-11 08:57:07 +00:00
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
2019-09-06 10:35:28 +00:00
|
|
|
self.store = self.hs.get_datastore()
|
2016-07-11 08:57:07 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
|
|
|
|
template_html, template_text = load_jinja2_templates(
|
|
|
|
self.config.email_template_dir,
|
|
|
|
[
|
|
|
|
self.config.email_add_threepid_template_html,
|
|
|
|
self.config.email_add_threepid_template_text,
|
|
|
|
],
|
|
|
|
public_baseurl=self.config.public_baseurl,
|
|
|
|
)
|
|
|
|
self.mailer = Mailer(
|
|
|
|
hs=self.hs,
|
|
|
|
app_name=self.config.email_app_name,
|
|
|
|
template_html=template_html,
|
|
|
|
template_text=template_text,
|
|
|
|
)
|
|
|
|
|
2016-07-08 16:42:48 +00:00
|
|
|
@defer.inlineCallbacks
|
2016-07-11 08:57:07 +00:00
|
|
|
def on_POST(self, request):
|
2019-09-20 14:21:30 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.OFF:
|
|
|
|
if self.config.local_threepid_handling_disabled_due_to_email_config:
|
|
|
|
logger.warn(
|
|
|
|
"Adding emails have been disabled due to lack of an email config"
|
|
|
|
)
|
|
|
|
raise SynapseError(
|
|
|
|
400, "Adding an email to your account is disabled on this server"
|
|
|
|
)
|
|
|
|
|
2016-07-08 16:42:48 +00:00
|
|
|
body = parse_json_object_from_request(request)
|
2019-09-20 14:21:30 +00:00
|
|
|
assert_params_in_dict(body, ["client_secret", "email", "send_attempt"])
|
2019-09-06 10:35:28 +00:00
|
|
|
client_secret = body["client_secret"]
|
|
|
|
email = body["email"]
|
|
|
|
send_attempt = body["send_attempt"]
|
|
|
|
next_link = body.get("next_link") # Optional param
|
2016-07-08 16:42:48 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if not check_3pid_allowed(self.hs, "email", email):
|
2018-01-19 00:53:58 +00:00
|
|
|
raise SynapseError(
|
2018-09-04 11:03:17 +00:00
|
|
|
403,
|
|
|
|
"Your email domain is not authorized on this server",
|
|
|
|
Codes.THREEPID_DENIED,
|
2018-01-19 00:53:58 +00:00
|
|
|
)
|
2018-01-19 00:19:58 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
existing_user_id = yield self.store.get_user_id_by_threepid(
|
2019-06-20 09:32:02 +00:00
|
|
|
"email", body["email"]
|
2016-07-08 16:42:48 +00:00
|
|
|
)
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if existing_user_id is not None:
|
2016-07-11 08:57:07 +00:00
|
|
|
raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE)
|
2016-07-08 16:42:48 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
|
|
|
|
assert self.hs.config.account_threepid_delegate_email
|
|
|
|
|
|
|
|
# Have the configured identity server handle the request
|
|
|
|
ret = yield self.identity_handler.requestEmailToken(
|
|
|
|
self.hs.config.account_threepid_delegate_email,
|
|
|
|
email,
|
|
|
|
client_secret,
|
|
|
|
send_attempt,
|
|
|
|
next_link,
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
# Send threepid validation emails from Synapse
|
|
|
|
sid = yield self.identity_handler.send_threepid_validation(
|
|
|
|
email,
|
|
|
|
client_secret,
|
|
|
|
send_attempt,
|
|
|
|
self.mailer.send_add_threepid_mail,
|
|
|
|
next_link,
|
|
|
|
)
|
|
|
|
|
|
|
|
# Wrap the session id in a JSON object
|
|
|
|
ret = {"sid": sid}
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, ret
|
2016-07-08 16:42:48 +00:00
|
|
|
|
2015-03-23 14:23:51 +00:00
|
|
|
|
2017-03-13 17:27:51 +00:00
|
|
|
class MsisdnThreepidRequestTokenRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/3pid/msisdn/requestToken$")
|
2017-03-13 17:27:51 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
self.hs = hs
|
|
|
|
super(MsisdnThreepidRequestTokenRestServlet, self).__init__()
|
2019-09-06 10:35:28 +00:00
|
|
|
self.store = self.hs.get_datastore()
|
2017-03-13 17:27:51 +00:00
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
|
|
|
body = parse_json_object_from_request(request)
|
2019-06-20 09:32:02 +00:00
|
|
|
assert_params_in_dict(
|
|
|
|
body,
|
|
|
|
["id_server", "client_secret", "country", "phone_number", "send_attempt"],
|
|
|
|
)
|
2019-09-06 10:35:28 +00:00
|
|
|
id_server = "https://" + body["id_server"] # Assume https
|
|
|
|
client_secret = body["client_secret"]
|
|
|
|
country = body["country"]
|
|
|
|
phone_number = body["phone_number"]
|
|
|
|
send_attempt = body["send_attempt"]
|
|
|
|
next_link = body.get("next_link") # Optional param
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
msisdn = phone_number_to_msisdn(country, phone_number)
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2018-01-19 00:19:58 +00:00
|
|
|
if not check_3pid_allowed(self.hs, "msisdn", msisdn):
|
2018-01-19 00:53:58 +00:00
|
|
|
raise SynapseError(
|
2018-09-04 11:03:17 +00:00
|
|
|
403,
|
|
|
|
"Account phone numbers are not authorized on this server",
|
|
|
|
Codes.THREEPID_DENIED,
|
2018-01-19 00:53:58 +00:00
|
|
|
)
|
2018-01-19 00:19:58 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
existing_user_id = yield self.store.get_user_id_by_threepid("msisdn", msisdn)
|
2017-03-13 17:27:51 +00:00
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
if existing_user_id is not None:
|
2017-03-13 17:27:51 +00:00
|
|
|
raise SynapseError(400, "MSISDN is already in use", Codes.THREEPID_IN_USE)
|
|
|
|
|
2019-09-06 10:35:28 +00:00
|
|
|
ret = yield self.identity_handler.requestMsisdnToken(
|
|
|
|
id_server, country, phone_number, client_secret, send_attempt, next_link
|
|
|
|
)
|
2019-09-20 14:21:30 +00:00
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, ret
|
2017-03-13 17:27:51 +00:00
|
|
|
|
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
class AddThreepidSubmitTokenServlet(RestServlet):
|
|
|
|
"""Handles 3PID validation token submission for adding an email to a user's account"""
|
|
|
|
|
|
|
|
PATTERNS = client_patterns(
|
|
|
|
"/add_threepid/email/submit_token$", releases=(), unstable=True
|
|
|
|
)
|
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
"""
|
|
|
|
Args:
|
|
|
|
hs (synapse.server.HomeServer): server
|
|
|
|
"""
|
|
|
|
super().__init__()
|
|
|
|
self.config = hs.config
|
|
|
|
self.clock = hs.get_clock()
|
|
|
|
self.store = hs.get_datastore()
|
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
|
|
|
|
self.failure_email_template, = load_jinja2_templates(
|
|
|
|
self.config.email_template_dir,
|
|
|
|
[self.config.email_add_threepid_template_failure_html],
|
|
|
|
)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_GET(self, request):
|
|
|
|
if self.config.threepid_behaviour_email == ThreepidBehaviour.OFF:
|
|
|
|
if self.config.local_threepid_handling_disabled_due_to_email_config:
|
|
|
|
logger.warn(
|
|
|
|
"Adding emails have been disabled due to lack of an email config"
|
|
|
|
)
|
|
|
|
raise SynapseError(
|
|
|
|
400, "Adding an email to your account is disabled on this server"
|
|
|
|
)
|
|
|
|
elif self.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
|
|
|
|
raise SynapseError(
|
|
|
|
400,
|
|
|
|
"This homeserver is not validating threepids. Use an identity server "
|
|
|
|
"instead.",
|
|
|
|
)
|
|
|
|
|
|
|
|
sid = parse_string(request, "sid", required=True)
|
|
|
|
client_secret = parse_string(request, "client_secret", required=True)
|
|
|
|
token = parse_string(request, "token", required=True)
|
|
|
|
|
|
|
|
# Attempt to validate a 3PID session
|
|
|
|
try:
|
|
|
|
# Mark the session as valid
|
|
|
|
next_link = yield self.store.validate_threepid_session(
|
|
|
|
sid, client_secret, token, self.clock.time_msec()
|
|
|
|
)
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
return None
|
|
|
|
|
|
|
|
# Otherwise show the success template
|
|
|
|
html = self.config.email_add_threepid_template_success_html_content
|
|
|
|
request.setResponseCode(200)
|
|
|
|
except ThreepidValidationError as e:
|
|
|
|
request.setResponseCode(e.code)
|
|
|
|
|
|
|
|
# Show a failure page with a reason
|
|
|
|
template_vars = {"failure_reason": e.msg}
|
|
|
|
html = self.failure_email_template.render(**template_vars)
|
|
|
|
|
|
|
|
request.write(html.encode("utf-8"))
|
|
|
|
finish_request(request)
|
|
|
|
|
|
|
|
|
2015-04-17 12:44:55 +00:00
|
|
|
class ThreepidRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/3pid$")
|
2015-04-17 12:44:12 +00:00
|
|
|
|
2015-04-17 15:44:49 +00:00
|
|
|
def __init__(self, hs):
|
|
|
|
super(ThreepidRestServlet, self).__init__()
|
|
|
|
self.hs = hs
|
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
|
|
|
self.auth = hs.get_auth()
|
2016-06-02 12:31:45 +00:00
|
|
|
self.auth_handler = hs.get_auth_handler()
|
2017-03-13 17:27:51 +00:00
|
|
|
self.datastore = self.hs.get_datastore()
|
2015-04-17 15:44:49 +00:00
|
|
|
|
2015-04-17 16:20:18 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_GET(self, request):
|
2016-01-11 15:29:57 +00:00
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
2015-04-17 16:20:18 +00:00
|
|
|
|
2019-06-20 09:32:02 +00:00
|
|
|
threepids = yield self.datastore.user_get_threepids(requester.user.to_string())
|
2015-04-17 16:20:18 +00:00
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {"threepids": threepids}
|
2015-04-17 16:20:18 +00:00
|
|
|
|
2015-04-17 12:44:12 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
2019-09-20 14:21:30 +00:00
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
|
|
|
user_id = requester.user.to_string()
|
2016-03-09 11:26:26 +00:00
|
|
|
body = parse_json_object_from_request(request)
|
2015-04-17 12:44:12 +00:00
|
|
|
|
2019-09-05 13:31:22 +00:00
|
|
|
threepid_creds = body.get("threePidCreds") or body.get("three_pid_creds")
|
|
|
|
if threepid_creds is None:
|
|
|
|
raise SynapseError(
|
|
|
|
400, "Missing param three_pid_creds", Codes.MISSING_PARAM
|
|
|
|
)
|
2019-09-20 14:21:30 +00:00
|
|
|
assert_params_in_dict(threepid_creds, ["client_secret", "sid"])
|
2015-04-17 12:44:12 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
client_secret = threepid_creds["client_secret"]
|
|
|
|
sid = threepid_creds["sid"]
|
2015-04-17 12:44:12 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
# We don't actually know which medium this 3PID is. Thus we first assume it's email,
|
|
|
|
# and if validation fails we try msisdn
|
|
|
|
validation_session = None
|
2015-04-17 12:44:12 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
# Try to validate as email
|
|
|
|
if self.hs.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
|
|
|
|
# Ask our delegated email identity server
|
|
|
|
try:
|
|
|
|
validation_session = yield self.identity_handler.threepid_from_creds(
|
|
|
|
self.hs.config.account_threepid_delegate_email, threepid_creds
|
|
|
|
)
|
|
|
|
except HttpResponseException:
|
|
|
|
logger.debug(
|
|
|
|
"%s reported non-validated threepid: %s",
|
|
|
|
self.hs.config.account_threepid_delegate_email,
|
|
|
|
threepid_creds,
|
|
|
|
)
|
|
|
|
elif self.hs.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
|
|
|
|
# Get a validated session matching these details
|
|
|
|
validation_session = yield self.datastore.get_threepid_validation_session(
|
|
|
|
"email", client_secret, sid=sid, validated=True
|
|
|
|
)
|
2015-04-17 15:44:49 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
# Old versions of Sydent return a 200 http code even on a failed validation check.
|
|
|
|
# Thus, in addition to the HttpResponseException check above (which checks for
|
|
|
|
# non-200 errors), we need to make sure validation_session isn't actually an error,
|
|
|
|
# identified by containing an "error" key
|
|
|
|
# See https://github.com/matrix-org/sydent/issues/215 for details
|
|
|
|
if validation_session and "error" not in validation_session:
|
|
|
|
yield self._add_threepid_to_account(user_id, validation_session)
|
|
|
|
return 200, {}
|
2015-04-17 15:44:49 +00:00
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
# Try to validate as msisdn
|
|
|
|
if self.hs.config.account_threepid_delegate_msisdn:
|
|
|
|
# Ask our delegated msisdn identity server
|
|
|
|
try:
|
|
|
|
validation_session = yield self.identity_handler.threepid_from_creds(
|
|
|
|
self.hs.config.account_threepid_delegate_msisdn, threepid_creds
|
|
|
|
)
|
|
|
|
except HttpResponseException:
|
|
|
|
logger.debug(
|
|
|
|
"%s reported non-validated threepid: %s",
|
|
|
|
self.hs.config.account_threepid_delegate_email,
|
|
|
|
threepid_creds,
|
|
|
|
)
|
|
|
|
|
|
|
|
# Check that validation_session isn't actually an error due to old Sydent instances
|
|
|
|
# See explanatory comment above
|
|
|
|
if validation_session and "error" not in validation_session:
|
|
|
|
yield self._add_threepid_to_account(user_id, validation_session)
|
|
|
|
return 200, {}
|
|
|
|
|
|
|
|
raise SynapseError(
|
|
|
|
400, "No validated 3pid session found", Codes.THREEPID_AUTH_FAILED
|
2015-04-17 15:44:49 +00:00
|
|
|
)
|
|
|
|
|
2019-09-20 14:21:30 +00:00
|
|
|
@defer.inlineCallbacks
|
|
|
|
def _add_threepid_to_account(self, user_id, validation_session):
|
|
|
|
"""Add a threepid wrapped in a validation_session dict to an account
|
|
|
|
|
|
|
|
Args:
|
|
|
|
user_id (str): The mxid of the user to add this 3PID to
|
|
|
|
|
|
|
|
validation_session (dict): A dict containing the following:
|
|
|
|
* medium - medium of the threepid
|
|
|
|
* address - address of the threepid
|
|
|
|
* validated_at - timestamp of when the validation occurred
|
|
|
|
"""
|
|
|
|
yield self.auth_handler.add_threepid(
|
|
|
|
user_id,
|
|
|
|
validation_session["medium"],
|
|
|
|
validation_session["address"],
|
|
|
|
validation_session["validated_at"],
|
|
|
|
)
|
2015-04-17 12:44:12 +00:00
|
|
|
|
|
|
|
|
2019-09-05 13:00:30 +00:00
|
|
|
class ThreepidUnbindRestServlet(RestServlet):
|
2019-09-19 21:28:30 +00:00
|
|
|
PATTERNS = client_patterns("/account/3pid/unbind$", releases=(), unstable=True)
|
2019-09-05 13:00:30 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
super(ThreepidUnbindRestServlet, self).__init__()
|
|
|
|
self.hs = hs
|
|
|
|
self.identity_handler = hs.get_handlers().identity_handler
|
|
|
|
self.auth = hs.get_auth()
|
|
|
|
self.datastore = self.hs.get_datastore()
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
|
|
|
"""Unbind the given 3pid from a specific identity server, or identity servers that are
|
|
|
|
known to have this 3pid bound
|
|
|
|
"""
|
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
|
|
|
body = parse_json_object_from_request(request)
|
|
|
|
assert_params_in_dict(body, ["medium", "address"])
|
|
|
|
|
|
|
|
medium = body.get("medium")
|
|
|
|
address = body.get("address")
|
|
|
|
id_server = body.get("id_server")
|
|
|
|
|
|
|
|
# Attempt to unbind the threepid from an identity server. If id_server is None, try to
|
|
|
|
# unbind from all identity servers this threepid has been added to in the past
|
|
|
|
result = yield self.identity_handler.try_unbind_threepid(
|
|
|
|
requester.user.to_string(),
|
|
|
|
{"address": address, "medium": medium, "id_server": id_server},
|
|
|
|
)
|
|
|
|
return 200, {"id_server_unbind_result": "success" if result else "no-support"}
|
|
|
|
|
|
|
|
|
2016-12-20 18:27:30 +00:00
|
|
|
class ThreepidDeleteRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/3pid/delete$")
|
2016-12-20 18:27:30 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
super(ThreepidDeleteRestServlet, self).__init__()
|
|
|
|
self.auth = hs.get_auth()
|
|
|
|
self.auth_handler = hs.get_auth_handler()
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_POST(self, request):
|
|
|
|
body = parse_json_object_from_request(request)
|
2019-06-20 09:32:02 +00:00
|
|
|
assert_params_in_dict(body, ["medium", "address"])
|
2016-12-20 18:27:30 +00:00
|
|
|
|
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
|
|
|
user_id = requester.user.to_string()
|
|
|
|
|
2018-05-24 10:08:05 +00:00
|
|
|
try:
|
2018-08-08 10:54:55 +00:00
|
|
|
ret = yield self.auth_handler.delete_threepid(
|
2019-06-20 09:32:02 +00:00
|
|
|
user_id, body["medium"], body["address"], body.get("id_server")
|
2018-05-24 10:08:05 +00:00
|
|
|
)
|
2018-05-24 10:23:15 +00:00
|
|
|
except Exception:
|
2018-05-24 10:08:05 +00:00
|
|
|
# NB. This endpoint should succeed if there is nothing to
|
|
|
|
# delete, so it should only throw if something is wrong
|
|
|
|
# that we ought to care about.
|
|
|
|
logger.exception("Failed to remove threepid")
|
|
|
|
raise SynapseError(500, "Failed to remove threepid")
|
2016-12-20 18:27:30 +00:00
|
|
|
|
2018-08-08 10:54:55 +00:00
|
|
|
if ret:
|
|
|
|
id_server_unbind_result = "success"
|
|
|
|
else:
|
|
|
|
id_server_unbind_result = "no-support"
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {"id_server_unbind_result": id_server_unbind_result}
|
2016-12-20 18:27:30 +00:00
|
|
|
|
|
|
|
|
2017-11-13 06:30:23 +00:00
|
|
|
class WhoamiRestServlet(RestServlet):
|
2019-06-03 11:28:59 +00:00
|
|
|
PATTERNS = client_patterns("/account/whoami$")
|
2017-11-13 06:30:23 +00:00
|
|
|
|
|
|
|
def __init__(self, hs):
|
|
|
|
super(WhoamiRestServlet, self).__init__()
|
|
|
|
self.auth = hs.get_auth()
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def on_GET(self, request):
|
|
|
|
requester = yield self.auth.get_user_by_req(request)
|
|
|
|
|
2019-08-30 15:28:26 +00:00
|
|
|
return 200, {"user_id": requester.user.to_string()}
|
2017-11-13 06:30:23 +00:00
|
|
|
|
|
|
|
|
2015-03-23 14:20:28 +00:00
|
|
|
def register_servlets(hs, http_server):
|
2017-03-13 17:27:51 +00:00
|
|
|
EmailPasswordRequestTokenRestServlet(hs).register(http_server)
|
|
|
|
MsisdnPasswordRequestTokenRestServlet(hs).register(http_server)
|
2019-06-06 16:34:07 +00:00
|
|
|
PasswordResetSubmitTokenServlet(hs).register(http_server)
|
2015-03-23 14:23:51 +00:00
|
|
|
PasswordRestServlet(hs).register(http_server)
|
2016-07-14 08:56:53 +00:00
|
|
|
DeactivateAccountRestServlet(hs).register(http_server)
|
2017-03-13 17:27:51 +00:00
|
|
|
EmailThreepidRequestTokenRestServlet(hs).register(http_server)
|
|
|
|
MsisdnThreepidRequestTokenRestServlet(hs).register(http_server)
|
2019-09-20 14:21:30 +00:00
|
|
|
AddThreepidSubmitTokenServlet(hs).register(http_server)
|
2015-04-17 12:44:55 +00:00
|
|
|
ThreepidRestServlet(hs).register(http_server)
|
2019-09-05 13:00:30 +00:00
|
|
|
ThreepidUnbindRestServlet(hs).register(http_server)
|
2016-12-20 18:27:30 +00:00
|
|
|
ThreepidDeleteRestServlet(hs).register(http_server)
|
2017-11-13 06:30:23 +00:00
|
|
|
WhoamiRestServlet(hs).register(http_server)
|