comparison src/server/server.py @ 554:471b6babe960

server_side: set a timeout to reset the waiting connection requests after 5 minutes
author souliane <souliane@mailoo.org>
date Sun, 21 Sep 2014 14:09:59 +0200
parents 8492c2bb463b
children db1b330c1eb1
comparison
equal deleted inserted replaced
553:8492c2bb463b 554:471b6babe960
562 """Tell the backend to leave OTR handling to Libervia.""" 562 """Tell the backend to leave OTR handling to Libervia."""
563 profile = ISATSession(self.session).profile 563 profile = ISATSession(self.session).profile
564 return self.sat_host.bridge.skipOTR(profile) 564 return self.sat_host.bridge.skipOTR(profile)
565 565
566 566
567 class WaitingRequests(dict):
568
569 def setRequest(self, request, profile):
570 """Add the given profile to the waiting list.
571
572 @param request (server.Request): the connection request
573 @param profile (str): %(doc_profile)s
574 """
575 dc = reactor.callLater(C.TIMEOUT, self.purgeRequest, profile)
576 self[profile] = (request, dc)
577
578 def purgeRequest(self, profile):
579 """Remove the given profile from the waiting list.
580
581 @param profile (str): %(doc_profile)s
582 """
583 try:
584 dc = self[profile][1]
585 except KeyError:
586 return
587 if dc.active():
588 dc.cancel()
589 del self[profile]
590
591 def getRequest(self, profile):
592 """Get the waiting request for the given profile.
593
594 @param profile (str): %(doc_profile)s
595 @return: the waiting request or None
596 """
597 return self[profile][0] if profile in self else None
598
599
567 class Register(JSONRPCMethodManager): 600 class Register(JSONRPCMethodManager):
568 """This class manage the registration procedure with SàT 601 """This class manage the registration procedure with SàT
569 It provide an api for the browser, check password and setup the web server""" 602 It provide an api for the browser, check password and setup the web server"""
570 603
571 def __init__(self, sat_host): 604 def __init__(self, sat_host):
572 JSONRPCMethodManager.__init__(self, sat_host) 605 JSONRPCMethodManager.__init__(self, sat_host)
573 self.profiles_waiting = {} 606 self.profiles_waiting = {}
574 self.request = None 607 self.request = None
575 608 self.waiting_profiles = WaitingRequests()
576 def getWaitingRequest(self, profile):
577 """Tell if a profile is trying to log in"""
578 if profile in self.profiles_waiting:
579 return self.profiles_waiting[profile]
580 else:
581 return None
582 609
583 def render(self, request): 610 def render(self, request):
584 """ 611 """
585 Render method with some hacks: 612 Render method with some hacks:
586 - if login is requested, try to login with form data 613 - if login is requested, try to login with form data
645 if ((not profile_check or profile_check != login_) or 672 if ((not profile_check or profile_check != login_) or
646 (not password_ and profile_check not in self.sat_host.empty_password_allowed_warning_dangerous_list)): 673 (not password_ and profile_check not in self.sat_host.empty_password_allowed_warning_dangerous_list)):
647 return C.PROFILE_AUTH_ERROR 674 return C.PROFILE_AUTH_ERROR
648 # profiles with empty passwords are restricted to local frontends 675 # profiles with empty passwords are restricted to local frontends
649 676
650 if login_ in self.profiles_waiting: 677 if self.waiting_profiles.getRequest(login_):
651 return C.ALREADY_WAITING 678 return C.ALREADY_WAITING
652 679
653 def auth_eb(failure): 680 def auth_eb(failure):
654 fault = failure.value.faultString 681 fault = failure.value.faultString
655 self.__cleanWaiting(login_) 682 self.waiting_profiles.purgeRequest(login_)
656 if fault == 'PasswordError': 683 if fault == 'PasswordError':
657 log.info("Profile %s doesn't exist or the submitted password is wrong" % login_) 684 log.info("Profile %s doesn't exist or the submitted password is wrong" % login_)
658 request.write(C.PROFILE_AUTH_ERROR) 685 request.write(C.PROFILE_AUTH_ERROR)
659 elif fault == 'SASLAuthError': 686 elif fault == 'SASLAuthError':
660 log.info("The XMPP password of profile %s is wrong" % login_) 687 log.info("The XMPP password of profile %s is wrong" % login_)
665 else: 692 else:
666 log.error('Unmanaged fault string %s in errback for the connection of profile %s' % (fault, login_)) 693 log.error('Unmanaged fault string %s in errback for the connection of profile %s' % (fault, login_))
667 request.write(C.UNKNOWN_ERROR % fault) 694 request.write(C.UNKNOWN_ERROR % fault)
668 request.finish() 695 request.finish()
669 696
670 self.profiles_waiting[login_] = request 697 self.waiting_profiles.setRequest(request, login_)
671 d = self.asyncBridgeCall("asyncConnect", login_, password_) 698 d = self.asyncBridgeCall("asyncConnect", login_, password_)
672 d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb) 699 d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb)
673 700
674 return server.NOT_DONE_YET 701 return server.NOT_DONE_YET
702
675 703
676 def _registerNewAccount(self, request): 704 def _registerNewAccount(self, request):
677 """Create a new account, or return error 705 """Create a new account, or return error
678 @param request: request of the register form 706 @param request: request of the register form
679 @return: a constant indicating the state: 707 @return: a constant indicating the state:
714 d = self.asyncBridgeCall("registerSatAccount", email, password, profile) 742 d = self.asyncBridgeCall("registerSatAccount", email, password, profile)
715 d.addCallback(registered) 743 d.addCallback(registered)
716 d.addErrback(registeringError) 744 d.addErrback(registeringError)
717 return server.NOT_DONE_YET 745 return server.NOT_DONE_YET
718 746
719 def __cleanWaiting(self, login):
720 """Remove login from waiting queue"""
721 try:
722 del self.profiles_waiting[login]
723 except KeyError:
724 pass
725
726 def _logged(self, profile, request): 747 def _logged(self, profile, request):
727 """Set everything when a user just logged in 748 """Set everything when a user just logged in
728 749
729 @param profile 750 @param profile
730 @param request 751 @param request
731 @return: a constant indicating the state: 752 @return: a constant indicating the state:
732 - C.PROFILE_LOGGED 753 - C.PROFILE_LOGGED
733 - C.SESSION_ACTIVE 754 - C.SESSION_ACTIVE
734 """ 755 """
735 self.__cleanWaiting(profile) 756 self.waiting_profiles.purgeRequest(profile)
736 _session = request.getSession() 757 _session = request.getSession()
737 sat_session = ISATSession(_session) 758 sat_session = ISATSession(_session)
738 if sat_session.profile: 759 if sat_session.profile:
739 log.error(('/!\\ Session has already a profile, this should NEVER happen!')) 760 log.error(('/!\\ Session has already a profile, this should NEVER happen!'))
740 request.write(C.SESSION_ACTIVE) 761 request.write(C.SESSION_ACTIVE)
764 return self.sat_host.bridge.isConnected(profile) 785 return self.sat_host.bridge.isConnected(profile)
765 786
766 def jsonrpc_asyncConnect(self): 787 def jsonrpc_asyncConnect(self):
767 _session = self.request.getSession() 788 _session = self.request.getSession()
768 profile = ISATSession(_session).profile 789 profile = ISATSession(_session).profile
769 if profile in self.profiles_waiting: 790 if self.waiting_profiles.getRequest(profile):
770 raise jsonrpclib.Fault(1, C.ALREADY_WAITING) # FIXME: define some standard error codes for libervia 791 raise jsonrpclib.Fault(1, C.ALREADY_WAITING) # FIXME: define some standard error codes for libervia
771 self.profiles_waiting[profile] = self.request 792 self.waiting_profiles.setRequest(self.request, profile)
772 self.sat_host.bridge.asyncConnect(profile) 793 self.sat_host.bridge.asyncConnect(profile)
773 return server.NOT_DONE_YET 794 return server.NOT_DONE_YET
774 795
775 def jsonrpc_isRegistered(self): 796 def jsonrpc_isRegistered(self):
776 """ 797 """
875 self.queue[profile].append((function_name, args[:-1])) 896 self.queue[profile].append((function_name, args[:-1]))
876 return genericCb 897 return genericCb
877 898
878 def connected(self, profile): 899 def connected(self, profile):
879 assert(self.register) # register must be plugged 900 assert(self.register) # register must be plugged
880 request = self.register.getWaitingRequest(profile) 901 request = self.register.waiting_profiles.getRequest(profile)
881 if request: 902 if request:
882 self.register._logged(profile, request) 903 self.register._logged(profile, request)
883 904
884 def disconnected(self, profile): 905 def disconnected(self, profile):
885 if not profile in self.sat_host.prof_connected: 906 if not profile in self.sat_host.prof_connected: