123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- # -*- coding: utf-8 -*-
- # Copyright 2016 OpenMarket Ltd
- # Copyright 2017 Vector Creations 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
- from twisted.web.resource import Resource
- import phonenumbers
- from sydent.validators import (
- IncorrectClientSecretException, SessionExpiredException, DestinationRejectedException
- )
- from sydent.http.servlets import get_args, jsonwrap, send_cors
- logger = logging.getLogger(__name__)
- class MsisdnRequestCodeServlet(Resource):
- isLeaf = True
- def __init__(self, syd):
- self.sydent = syd
- @jsonwrap
- def render_POST(self, request):
- send_cors(request)
- error, args = get_args(request, ('phone_number', 'country', 'client_secret', 'send_attempt'))
- if error:
- request.setResponseCode(400)
- return error
- raw_phone_number = args['phone_number']
- country = args['country']
- clientSecret = args['client_secret']
- sendAttempt = args['send_attempt']
- try:
- phone_number_object = phonenumbers.parse(raw_phone_number, country)
- except Exception as e:
- logger.warn("Invalid phone number given: %r", e)
- request.setResponseCode(400)
- return {'errcode': 'M_INVALID_PHONE_NUMBER', 'error': "Invalid phone number" }
- msisdn = phonenumbers.format_number(
- phone_number_object, phonenumbers.PhoneNumberFormat.E164
- )[1:]
- # International formatted number. The same as an E164 but with spaces
- # in appropriate places to make it nicer for the humans.
- intl_fmt = phonenumbers.format_number(
- phone_number_object, phonenumbers.PhoneNumberFormat.INTERNATIONAL
- )
- resp = None
- try:
- sid = self.sydent.validators.msisdn.requestToken(
- phone_number_object, clientSecret, sendAttempt, None
- )
- except DestinationRejectedException:
- logger.error("Destination rejected for number: %s", msisdn);
- request.setResponseCode(400)
- resp = {'errcode': 'M_DESTINATION_REJECTED', 'error': 'Phone numbers in this country are not currently supported'}
- except Exception as e:
- logger.error("Exception sending SMS: %r", e);
- request.setResponseCode(500)
- resp = {'errcode': 'M_UNKNOWN', 'error':'Internal Server Error'}
- if not resp:
- resp = {
- 'success': True, 'sid': str(sid),
- 'msisdn': msisdn, 'intl_fmt': intl_fmt,
- }
- return resp
- @jsonwrap
- def render_OPTIONS(self, request):
- send_cors(request)
- request.setResponseCode(200)
- return {}
- class MsisdnValidateCodeServlet(Resource):
- isLeaf = True
- def __init__(self, syd):
- self.sydent = syd
- def render_GET(self, request):
- send_cors(request)
- err, args = get_args(request, ('token', 'sid', 'client_secret'))
- if err:
- return err
- resp = self.do_validate_request(args)
- if 'success' in resp and resp['success']:
- msg = "Verification successful! Please return to your Matrix client to continue."
- if 'next_link' in args:
- next_link = args['next_link']
- request.setResponseCode(302)
- request.setHeader("Location", next_link)
- else:
- msg = "Verification failed: you may need to request another verification text"
- templateFile = self.sydent.cfg.get('http', 'verify_response_template')
- request.setHeader("Content-Type", "text/html")
- return open(templateFile).read() % {'message': msg}
- @jsonwrap
- def render_POST(self, request):
- send_cors(request)
- err, args = get_args(request, ('token', 'sid', 'client_secret'))
- if err:
- return err
- return self.do_validate_request(args)
- def do_validate_request(self, args):
- sid = args['sid']
- tokenString = args['token']
- clientSecret = args['client_secret']
- try:
- resp = self.sydent.validators.msisdn.validateSessionWithToken(sid, clientSecret, tokenString)
- except IncorrectClientSecretException:
- return {'success': False, 'errcode': 'M_INCORRECT_CLIENT_SECRET',
- 'error': "Client secret does not match the one given when requesting the token"}
- except SessionExpiredException:
- return {'success': False, 'errcode': 'M_SESSION_EXPIRED',
- 'error': "This validation session has expired: call requestToken again"}
- if not resp:
- resp = {'success': False}
- return resp
- @jsonwrap
- def render_OPTIONS(self, request):
- send_cors(request)
- request.setResponseCode(200)
- return {}
|