emailvalidator.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import logging
  16. import urllib
  17. from sydent.db.valsession import ThreePidValSessionStore
  18. from sydent.util.emailutils import sendEmail
  19. from sydent.validators import ValidationSession
  20. from sydent.util import time_msec
  21. from sydent.validators import IncorrectClientSecretException, SessionExpiredException
  22. logger = logging.getLogger(__name__)
  23. class EmailValidator:
  24. def __init__(self, sydent):
  25. self.sydent = sydent
  26. def requestToken(self, emailAddress, clientSecret, sendAttempt, nextLink, ipaddress=None):
  27. valSessionStore = ThreePidValSessionStore(self.sydent)
  28. valSession = valSessionStore.getOrCreateTokenSession(medium='email', address=emailAddress,
  29. clientSecret=clientSecret)
  30. valSessionStore.setMtime(valSession.id, time_msec())
  31. if int(valSession.sendAttemptNumber) >= int(sendAttempt):
  32. logger.info("Not mailing code because current send attempt (%d) is not less than given send attempt (%s)", int(sendAttempt), int(valSession.sendAttemptNumber))
  33. return valSession.id
  34. ipstring = ipaddress if ipaddress else u"an unknown location"
  35. substitutions = {
  36. 'ipaddress': ipstring,
  37. 'link': self.makeValidateLink(valSession, clientSecret, nextLink),
  38. 'token': valSession.token,
  39. }
  40. logger.info(
  41. "Attempting to mail code %s (nextLink: %s) to %s",
  42. valSession.token, nextLink, emailAddress,
  43. )
  44. sendEmail(self.sydent, 'email.template', emailAddress, substitutions)
  45. valSessionStore.setSendAttemptNumber(valSession.id, sendAttempt)
  46. return valSession.id
  47. def makeValidateLink(self, valSession, clientSecret, nextLink):
  48. base = self.sydent.cfg.get('http', 'client_http_base')
  49. link = "%s/_matrix/identity/api/v1/validate/email/submitToken?token=%s&client_secret=%s&sid=%d" % (
  50. base,
  51. urllib.quote(valSession.token),
  52. urllib.quote(clientSecret),
  53. valSession.id,
  54. )
  55. if nextLink:
  56. # manipulate the nextLink to add the sid, because
  57. # the caller won't get it until we send a response,
  58. # by which time we've sent the mail.
  59. if '?' in nextLink:
  60. nextLink += '&'
  61. else:
  62. nextLink += '?'
  63. nextLink += "sid=" + urllib.quote(str(valSession.id))
  64. link += "&nextLink=%s" % (urllib.quote(nextLink))
  65. return link
  66. def validateSessionWithToken(self, sid, clientSecret, token):
  67. valSessionStore = ThreePidValSessionStore(self.sydent)
  68. s = valSessionStore.getTokenSessionById(sid)
  69. if not s:
  70. logger.info("Session ID %s not found", (sid))
  71. return False
  72. if not clientSecret == s.clientSecret:
  73. logger.info("Incorrect client secret", (sid))
  74. raise IncorrectClientSecretException()
  75. if s.mtime + ValidationSession.THREEPID_SESSION_VALIDATION_TIMEOUT_MS < time_msec():
  76. logger.info("Session expired")
  77. raise SessionExpiredException()
  78. # TODO once we can validate the token oob
  79. #if tokenObj.validated and clientSecret == tokenObj.clientSecret:
  80. # return True
  81. if s.token == token:
  82. logger.info("Setting session %s as validated", (s.id))
  83. valSessionStore.setValidated(s.id, True)
  84. return {'success': True}
  85. else:
  86. logger.info("Incorrect token submitted")
  87. return False