diff --git a/synapse/rest/client/v1/__init__.py b/synapse/rest/client/v1/__init__.py index cc9b49d539..600428400c 100644 --- a/synapse/rest/client/v1/__init__.py +++ b/synapse/rest/client/v1/__init__.py @@ -15,7 +15,7 @@ from . import ( room, events, register, login, profile, presence, initial_sync, directory, - voip, admin, pusher, push_rule + voip, admin, pusher, push_rule, login_qr ) from synapse.http.server import JsonResource @@ -42,3 +42,4 @@ class ClientV1RestResource(JsonResource): admin.register_servlets(hs, client_resource) pusher.register_servlets(hs, client_resource) push_rule.register_servlets(hs, client_resource) + login_qr.register_servlets(hs, client_resource) diff --git a/synapse/rest/media/v1/login_qr_resource.py b/synapse/rest/media/v1/login_qr_resource.py deleted file mode 100644 index b4d7040181..0000000000 --- a/synapse/rest/media/v1/login_qr_resource.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2015 OpenMarket 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 twisted.web.resource import Resource -from twisted.web.server import NOT_DONE_YET -from twisted.internet import defer, threads - -from synapse.api.errors import CodeMessageException -from synapse.util.stringutils import random_string - -import simplejson -import logging - -from unpaddedbase64 import encode_base64 -from hashlib import sha256 -from OpenSSL import crypto - -logger = logging.getLogger(__name__) - - -class LoginQRResource(Resource): - isLeaf = True - - def __init__(self, hs): - Resource.__init__(self) - self.hs = hs - self.auth = hs.get_auth() - self.handlers = hs.get_handlers() - self.config = hs.get_config() - - def render_GET(self, request): - self._async_render_GET(request) - return NOT_DONE_YET - - @defer.inlineCallbacks - def _async_render_GET(self, request): - try: - auth_user, _ = yield self.auth.get_user_by_req(request) - - nonce = request.path.split("/")[-1] - - if not nonce: - nonce = random_string(10) - - image = yield self.make_short_term_qr_code( - auth_user.to_string(), nonce - ) - - request.setHeader(b"Content-Type", b"image/png") - - image.save(request) - request.finish() - except CodeMessageException as e: - logger.info("Returning: %s", e) - request.setResponseCode(e.code) - request.write("%s: %s" % (e.code, e.message)) - request.finish() - except Exception: - logger.exception("Exception while generating token") - request.setResponseCode(500) - request.write("Internal server error") - request.finish() - - @defer.inlineCallbacks - def make_short_term_qr_code(self, user_id, nonce): - h = self.handlers.auth_handler - token = h.make_short_term_token(user_id, nonce) - - x509_certificate_bytes = crypto.dump_certificate( - crypto.FILETYPE_ASN1, - self.config.tls_certificate - ) - - sha256_fingerprint = sha256(x509_certificate_bytes).digest() - - def gen(): - import qrcode - qr = qrcode.QRCode( - version=1, - error_correction=qrcode.constants.ERROR_CORRECT_L, - box_size=5, - ) - qr.add_data(simplejson.dumps({ - "user_id": user_id, - "token": token, - "homeserver_url": self.config.client_addr, - "fingerprints": [{ - "hash_type": "SHA256", - "bytes": encode_base64(sha256_fingerprint), - }], - })) - qr.make(fit=True) - return qr.make_image() - - res = yield threads.deferToThread(gen) - defer.returnValue(res) diff --git a/synapse/rest/media/v1/media_repository.py b/synapse/rest/media/v1/media_repository.py index 5dcd7b659c..9ca4d884dd 100644 --- a/synapse/rest/media/v1/media_repository.py +++ b/synapse/rest/media/v1/media_repository.py @@ -17,7 +17,6 @@ from .upload_resource import UploadResource from .download_resource import DownloadResource from .thumbnail_resource import ThumbnailResource from .identicon_resource import IdenticonResource -from .login_qr_resource import LoginQRResource from .filepath import MediaFilePaths from twisted.web.resource import Resource @@ -79,4 +78,3 @@ class MediaRepositoryResource(Resource): self.putChild("download", DownloadResource(hs, filepaths)) self.putChild("thumbnail", ThumbnailResource(hs, filepaths)) self.putChild("identicon", IdenticonResource()) - self.putChild("login_qr", LoginQRResource(hs))