mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-15 08:03:51 +01:00
Merge pull request #2589 from matrix-org/rav/as_deactivate_account
Allow ASes to deactivate their own users
This commit is contained in:
commit
110b373e9c
2 changed files with 33 additions and 17 deletions
|
@ -82,7 +82,7 @@ class AuthHandler(BaseHandler):
|
||||||
def check_auth(self, flows, clientdict, clientip):
|
def check_auth(self, flows, clientdict, clientip):
|
||||||
"""
|
"""
|
||||||
Takes a dictionary sent by the client in the login / registration
|
Takes a dictionary sent by the client in the login / registration
|
||||||
protocol and handles the login flow.
|
protocol and handles the User-Interactive Auth flow.
|
||||||
|
|
||||||
As a side effect, this function fills in the 'creds' key on the user's
|
As a side effect, this function fills in the 'creds' key on the user's
|
||||||
session with a map, which maps each auth-type (str) to the relevant
|
session with a map, which maps each auth-type (str) to the relevant
|
||||||
|
|
|
@ -13,22 +13,21 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
import logging
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
|
from synapse.api.auth import has_access_token
|
||||||
from synapse.api.constants import LoginType
|
from synapse.api.constants import LoginType
|
||||||
from synapse.api.errors import LoginError, SynapseError, Codes
|
from synapse.api.errors import Codes, LoginError, SynapseError
|
||||||
from synapse.http.servlet import (
|
from synapse.http.servlet import (
|
||||||
RestServlet, parse_json_object_from_request, assert_params_in_request
|
RestServlet, assert_params_in_request,
|
||||||
|
parse_json_object_from_request,
|
||||||
)
|
)
|
||||||
from synapse.util.async import run_on_reactor
|
from synapse.util.async import run_on_reactor
|
||||||
from synapse.util.msisdn import phone_number_to_msisdn
|
from synapse.util.msisdn import phone_number_to_msisdn
|
||||||
|
|
||||||
from ._base import client_v2_patterns
|
from ._base import client_v2_patterns
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,6 +171,18 @@ class DeactivateAccountRestServlet(RestServlet):
|
||||||
def on_POST(self, request):
|
def on_POST(self, request):
|
||||||
body = parse_json_object_from_request(request)
|
body = parse_json_object_from_request(request)
|
||||||
|
|
||||||
|
# if the caller provides an access token, it ought to be valid.
|
||||||
|
requester = None
|
||||||
|
if has_access_token(request):
|
||||||
|
requester = yield self.auth.get_user_by_req(
|
||||||
|
request,
|
||||||
|
) # type: synapse.types.Requester
|
||||||
|
|
||||||
|
# allow ASes to dectivate their own users
|
||||||
|
if requester and requester.app_service:
|
||||||
|
yield self._deactivate_account(requester.user.to_string())
|
||||||
|
defer.returnValue((200, {}))
|
||||||
|
|
||||||
authed, result, params, _ = yield self.auth_handler.check_auth([
|
authed, result, params, _ = yield self.auth_handler.check_auth([
|
||||||
[LoginType.PASSWORD],
|
[LoginType.PASSWORD],
|
||||||
], body, self.hs.get_ip_from_request(request))
|
], body, self.hs.get_ip_from_request(request))
|
||||||
|
@ -179,27 +190,32 @@ class DeactivateAccountRestServlet(RestServlet):
|
||||||
if not authed:
|
if not authed:
|
||||||
defer.returnValue((401, result))
|
defer.returnValue((401, result))
|
||||||
|
|
||||||
user_id = None
|
|
||||||
requester = None
|
|
||||||
|
|
||||||
if LoginType.PASSWORD in result:
|
if LoginType.PASSWORD in result:
|
||||||
|
user_id = result[LoginType.PASSWORD]
|
||||||
# if using password, they should also be logged in
|
# if using password, they should also be logged in
|
||||||
requester = yield self.auth.get_user_by_req(request)
|
if requester is None:
|
||||||
user_id = requester.user.to_string()
|
raise SynapseError(
|
||||||
if user_id != result[LoginType.PASSWORD]:
|
400,
|
||||||
|
"Deactivate account requires an access_token",
|
||||||
|
errcode=Codes.MISSING_TOKEN
|
||||||
|
)
|
||||||
|
if requester.user.to_string() != user_id:
|
||||||
raise LoginError(400, "", Codes.UNKNOWN)
|
raise LoginError(400, "", Codes.UNKNOWN)
|
||||||
else:
|
else:
|
||||||
logger.error("Auth succeeded but no known type!", result.keys())
|
logger.error("Auth succeeded but no known type!", result.keys())
|
||||||
raise SynapseError(500, "", Codes.UNKNOWN)
|
raise SynapseError(500, "", Codes.UNKNOWN)
|
||||||
|
|
||||||
# FIXME: Theoretically there is a race here wherein user resets password
|
yield self._deactivate_account(user_id)
|
||||||
# using threepid.
|
defer.returnValue((200, {}))
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def _deactivate_account(self, user_id):
|
||||||
|
# FIXME: Theoretically there is a race here wherein user resets
|
||||||
|
# password using threepid.
|
||||||
yield self.store.user_delete_access_tokens(user_id)
|
yield self.store.user_delete_access_tokens(user_id)
|
||||||
yield self.store.user_delete_threepids(user_id)
|
yield self.store.user_delete_threepids(user_id)
|
||||||
yield self.store.user_set_password_hash(user_id, None)
|
yield self.store.user_set_password_hash(user_id, None)
|
||||||
|
|
||||||
defer.returnValue((200, {}))
|
|
||||||
|
|
||||||
|
|
||||||
class EmailThreepidRequestTokenRestServlet(RestServlet):
|
class EmailThreepidRequestTokenRestServlet(RestServlet):
|
||||||
PATTERNS = client_v2_patterns("/account/3pid/email/requestToken$")
|
PATTERNS = client_v2_patterns("/account/3pid/email/requestToken$")
|
||||||
|
|
Loading…
Reference in a new issue