19
19
from twisted .internet import defer
20
20
21
21
from synapse import types
22
+ from synapse .api .constants import LoginType
22
23
from synapse .api .errors import (
23
24
AuthError ,
24
25
Codes ,
25
26
InvalidCaptchaError ,
26
27
RegistrationError ,
27
28
SynapseError ,
28
29
)
30
+ from synapse .config .server import is_threepid_reserved
29
31
from synapse .http .client import CaptchaServerHttpClient
32
+ from synapse .http .servlet import assert_params_in_dict
30
33
from synapse .replication .http .login import RegisterDeviceReplicationServlet
31
- from synapse .replication .http .register import ReplicationRegisterServlet
34
+ from synapse .replication .http .register import (
35
+ ReplicationPostRegisterActionsServlet ,
36
+ ReplicationRegisterServlet ,
37
+ )
32
38
from synapse .types import RoomAlias , RoomID , UserID , create_requester
33
39
from synapse .util .async_helpers import Linearizer
34
40
from synapse .util .threepids import check_3pid_allowed
@@ -53,6 +59,7 @@ def __init__(self, hs):
53
59
self .profile_handler = hs .get_profile_handler ()
54
60
self .user_directory_handler = hs .get_user_directory_handler ()
55
61
self .captcha_client = CaptchaServerHttpClient (hs )
62
+ self .identity_handler = self .hs .get_handlers ().identity_handler
56
63
57
64
self ._next_generated_user_id = None
58
65
@@ -68,8 +75,12 @@ def __init__(self, hs):
68
75
self ._register_device_client = (
69
76
RegisterDeviceReplicationServlet .make_client (hs )
70
77
)
78
+ self ._post_registration_client = (
79
+ ReplicationPostRegisterActionsServlet .make_client (hs )
80
+ )
71
81
else :
72
82
self .device_handler = hs .get_device_handler ()
83
+ self .pusher_pool = hs .get_pusherpool ()
73
84
74
85
@defer .inlineCallbacks
75
86
def check_username (self , localpart , guest_access_token = None ,
@@ -369,8 +380,7 @@ def register_email(self, threepidCreds):
369
380
logger .info ("validating threepidcred sid %s on id server %s" ,
370
381
c ['sid' ], c ['idServer' ])
371
382
try :
372
- identity_handler = self .hs .get_handlers ().identity_handler
373
- threepid = yield identity_handler .threepid_from_creds (c )
383
+ threepid = yield self .identity_handler .threepid_from_creds (c )
374
384
except Exception :
375
385
logger .exception ("Couldn't validate 3pid" )
376
386
raise RegistrationError (400 , "Couldn't validate 3pid" )
@@ -394,9 +404,8 @@ def bind_emails(self, user_id, threepidCreds):
394
404
395
405
# Now we have a matrix ID, bind it to the threepids we were given
396
406
for c in threepidCreds :
397
- identity_handler = self .hs .get_handlers ().identity_handler
398
407
# XXX: This should be a deferred list, shouldn't it?
399
- yield identity_handler .bind_threepid (c , user_id )
408
+ yield self . identity_handler .bind_threepid (c , user_id )
400
409
401
410
def check_user_id_not_appservice_exclusive (self , user_id , allowed_appservice = None ):
402
411
# don't allow people to register the server notices mxid
@@ -671,3 +680,184 @@ def register_device(self, user_id, device_id, initial_display_name,
671
680
)
672
681
673
682
defer .returnValue ((device_id , access_token ))
683
+
684
+ @defer .inlineCallbacks
685
+ def post_registration_actions (self , user_id , auth_result , access_token ,
686
+ bind_email , bind_msisdn ):
687
+ """A user has completed registration
688
+
689
+ Args:
690
+ user_id (str): The user ID that consented
691
+ auth_result (dict): The authenticated credentials of the newly
692
+ registered user.
693
+ access_token (str|None): The access token of the newly logged in
694
+ device, or None if `inhibit_login` enabled.
695
+ bind_email (bool): Whether to bind the email with the identity
696
+ server
697
+ bind_msisdn (bool): Whether to bind the msisdn with the identity
698
+ server
699
+ """
700
+ if self .hs .config .worker_app :
701
+ yield self ._post_registration_client (
702
+ user_id = user_id ,
703
+ auth_result = auth_result ,
704
+ access_token = access_token ,
705
+ bind_email = bind_email ,
706
+ bind_msisdn = bind_msisdn ,
707
+ )
708
+ return
709
+
710
+ if auth_result and LoginType .EMAIL_IDENTITY in auth_result :
711
+ threepid = auth_result [LoginType .EMAIL_IDENTITY ]
712
+ # Necessary due to auth checks prior to the threepid being
713
+ # written to the db
714
+ if is_threepid_reserved (
715
+ self .hs .config .mau_limits_reserved_threepids , threepid
716
+ ):
717
+ yield self .store .upsert_monthly_active_user (user_id )
718
+
719
+ yield self ._register_email_threepid (
720
+ user_id , threepid , access_token ,
721
+ bind_email ,
722
+ )
723
+
724
+ if auth_result and LoginType .MSISDN in auth_result :
725
+ threepid = auth_result [LoginType .MSISDN ]
726
+ yield self ._register_msisdn_threepid (
727
+ user_id , threepid , bind_msisdn ,
728
+ )
729
+
730
+ if auth_result and LoginType .TERMS in auth_result :
731
+ yield self ._on_user_consented (
732
+ user_id , self .hs .config .user_consent_version ,
733
+ )
734
+
735
+ @defer .inlineCallbacks
736
+ def _on_user_consented (self , user_id , consent_version ):
737
+ """A user consented to the terms on registration
738
+
739
+ Args:
740
+ user_id (str): The user ID that consented
741
+ consent_version (str): version of the policy the user has
742
+ consented to.
743
+ """
744
+ logger .info ("%s has consented to the privacy policy" , user_id )
745
+ yield self .store .user_set_consent_version (
746
+ user_id , consent_version ,
747
+ )
748
+ yield self .post_consent_actions (user_id )
749
+
750
+ @defer .inlineCallbacks
751
+ def _register_email_threepid (self , user_id , threepid , token , bind_email ):
752
+ """Add an email address as a 3pid identifier
753
+
754
+ Also adds an email pusher for the email address, if configured in the
755
+ HS config
756
+
757
+ Also optionally binds emails to the given user_id on the identity server
758
+
759
+ Must be called on master.
760
+
761
+ Args:
762
+ user_id (str): id of user
763
+ threepid (object): m.login.email.identity auth response
764
+ token (str|None): access_token for the user, or None if not logged
765
+ in.
766
+ bind_email (bool): true if the client requested the email to be
767
+ bound at the identity server
768
+ Returns:
769
+ defer.Deferred:
770
+ """
771
+ reqd = ('medium' , 'address' , 'validated_at' )
772
+ if any (x not in threepid for x in reqd ):
773
+ # This will only happen if the ID server returns a malformed response
774
+ logger .info ("Can't add incomplete 3pid" )
775
+ return
776
+
777
+ yield self ._auth_handler .add_threepid (
778
+ user_id ,
779
+ threepid ['medium' ],
780
+ threepid ['address' ],
781
+ threepid ['validated_at' ],
782
+ )
783
+
784
+ # And we add an email pusher for them by default, but only
785
+ # if email notifications are enabled (so people don't start
786
+ # getting mail spam where they weren't before if email
787
+ # notifs are set up on a home server)
788
+ if (self .hs .config .email_enable_notifs and
789
+ self .hs .config .email_notif_for_new_users
790
+ and token ):
791
+ # Pull the ID of the access token back out of the db
792
+ # It would really make more sense for this to be passed
793
+ # up when the access token is saved, but that's quite an
794
+ # invasive change I'd rather do separately.
795
+ user_tuple = yield self .store .get_user_by_access_token (
796
+ token
797
+ )
798
+ token_id = user_tuple ["token_id" ]
799
+
800
+ yield self .pusher_pool .add_pusher (
801
+ user_id = user_id ,
802
+ access_token = token_id ,
803
+ kind = "email" ,
804
+ app_id = "m.email" ,
805
+ app_display_name = "Email Notifications" ,
806
+ device_display_name = threepid ["address" ],
807
+ pushkey = threepid ["address" ],
808
+ lang = None , # We don't know a user's language here
809
+ data = {},
810
+ )
811
+
812
+ if bind_email :
813
+ logger .info ("bind_email specified: binding" )
814
+ logger .debug ("Binding emails %s to %s" % (
815
+ threepid , user_id
816
+ ))
817
+ yield self .identity_handler .bind_threepid (
818
+ threepid ['threepid_creds' ], user_id
819
+ )
820
+ else :
821
+ logger .info ("bind_email not specified: not binding email" )
822
+
823
+ @defer .inlineCallbacks
824
+ def _register_msisdn_threepid (self , user_id , threepid , bind_msisdn ):
825
+ """Add a phone number as a 3pid identifier
826
+
827
+ Also optionally binds msisdn to the given user_id on the identity server
828
+
829
+ Must be called on master.
830
+
831
+ Args:
832
+ user_id (str): id of user
833
+ threepid (object): m.login.msisdn auth response
834
+ token (str): access_token for the user
835
+ bind_email (bool): true if the client requested the email to be
836
+ bound at the identity server
837
+ Returns:
838
+ defer.Deferred:
839
+ """
840
+ try :
841
+ assert_params_in_dict (threepid , ['medium' , 'address' , 'validated_at' ])
842
+ except SynapseError as ex :
843
+ if ex .errcode == Codes .MISSING_PARAM :
844
+ # This will only happen if the ID server returns a malformed response
845
+ logger .info ("Can't add incomplete 3pid" )
846
+ defer .returnValue (None )
847
+ raise
848
+
849
+ yield self ._auth_handler .add_threepid (
850
+ user_id ,
851
+ threepid ['medium' ],
852
+ threepid ['address' ],
853
+ threepid ['validated_at' ],
854
+ )
855
+
856
+ if bind_msisdn :
857
+ logger .info ("bind_msisdn specified: binding" )
858
+ logger .debug ("Binding msisdn %s to %s" , threepid , user_id )
859
+ yield self .identity_handler .bind_threepid (
860
+ threepid ['threepid_creds' ], user_id
861
+ )
862
+ else :
863
+ logger .info ("bind_msisdn not specified: not binding msisdn" )
0 commit comments