comparison src/server/server.py @ 481:bbdc5357dc00

browser and server sides: refactor HTTP request result values + handle "NoReply" error
author souliane <souliane@mailoo.org>
date Sun, 15 Jun 2014 17:52:08 +0200
parents d6daa00ba564
children 437eefa53a01
comparison
equal deleted inserted replaced
480:50b286866739 481:bbdc5357dc00
178 self.session = request.getSession() 178 self.session = request.getSession()
179 profile = ISATSession(self.session).profile 179 profile = ISATSession(self.session).profile
180 if not profile: 180 if not profile:
181 #user is not identified, we return a jsonrpc fault 181 #user is not identified, we return a jsonrpc fault
182 parsed = jsonrpclib.loads(request.content.read()) 182 parsed = jsonrpclib.loads(request.content.read())
183 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia 183 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, C.NOT_ALLOWED) # FIXME: define some standard error codes for libervia
184 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 184 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
185 return jsonrpc.JSONRPC.render(self, request) 185 return jsonrpc.JSONRPC.render(self, request)
186 186
187 def jsonrpc_getProfileJid(self): 187 def jsonrpc_getProfileJid(self):
188 """Return the jid of the profile""" 188 """Return the jid of the profile"""
584 if method not in ['isRegistered', 'registerParams', 'getMenus']: 584 if method not in ['isRegistered', 'registerParams', 'getMenus']:
585 #if we don't call these methods, we need to be identified 585 #if we don't call these methods, we need to be identified
586 profile = ISATSession(_session).profile 586 profile = ISATSession(_session).profile
587 if not profile: 587 if not profile:
588 #user is not identified, we return a jsonrpc fault 588 #user is not identified, we return a jsonrpc fault
589 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia 589 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, C.NOT_ALLOWED) # FIXME: define some standard error codes for libervia
590 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 590 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
591 self.request = request 591 self.request = request
592 return jsonrpc.JSONRPC.render(self, request) 592 return jsonrpc.JSONRPC.render(self, request)
593 593
594 def loginOrRegister(self, request): 594 def loginOrRegister(self, request):
595 """This method is called with the POST information from the registering form. 595 """This method is called with the POST information from the registering form.
596 596
597 @param request: request of the register form 597 @param request: request of the register form
598 @return: a constant indicating the state: 598 @return: a constant indicating the state:
599 - BAD REQUEST: something is wrong in the request (bad arguments) 599 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
600 - a return value from self._loginAccount or self._registerNewAccount 600 - a return value from self._loginAccount or self._registerNewAccount
601 """ 601 """
602 try: 602 try:
603 submit_type = request.args['submit_type'][0] 603 submit_type = request.args['submit_type'][0]
604 except KeyError: 604 except KeyError:
605 return "BAD REQUEST" 605 return C.BAD_REQUEST
606 606
607 if submit_type == 'register': 607 if submit_type == 'register':
608 return self._registerNewAccount(request) 608 return self._registerNewAccount(request)
609 elif submit_type == 'login': 609 elif submit_type == 'login':
610 return self._loginAccount(request) 610 return self._loginAccount(request)
612 612
613 def _loginAccount(self, request): 613 def _loginAccount(self, request):
614 """Try to authenticate the user with the request information. 614 """Try to authenticate the user with the request information.
615 @param request: request of the register form 615 @param request: request of the register form
616 @return: a constant indicating the state: 616 @return: a constant indicating the state:
617 - BAD REQUEST: something is wrong in the request (bad arguments) 617 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
618 - PROFILE AUTH ERROR: either the profile (login) or the profile password is wrong 618 - C.PROFILE_AUTH_ERROR: either the profile (login) or the profile password is wrong
619 - XMPP AUTH ERROR: the profile is authenticated but the XMPP password is wrong 619 - C.XMPP_AUTH_ERROR: the profile is authenticated but the XMPP password is wrong
620 - ALREADY WAITING: a request has already been submitted for this profile 620 - C.ALREADY_WAITING: a request has already been submitted for this profile
621 - server.NOT_DONE_YET: the profile is being processed, the return 621 - server.NOT_DONE_YET: the profile is being processed, the return
622 value will be given by self._logged or auth_eb 622 value will be given by self._logged or auth_eb
623 """ 623 """
624 try: 624 try:
625 login_ = request.args['login'][0] 625 login_ = request.args['login'][0]
626 password_ = request.args['login_password'][0] 626 password_ = request.args['login_password'][0]
627 except KeyError: 627 except KeyError:
628 return "BAD REQUEST" 628 return C.BAD_REQUEST
629 629
630 if login_.startswith('@'): 630 if login_.startswith('@'):
631 raise Exception('No profile_key allowed') 631 raise Exception('No profile_key allowed')
632 632
633 profile_check = self.sat_host.bridge.getProfileName(login_) 633 profile_check = self.sat_host.bridge.getProfileName(login_)
634 if ((not profile_check or profile_check != login_) or 634 if ((not profile_check or profile_check != login_) or
635 (not password_ and profile_check not in self.sat_host.empty_password_allowed_warning_dangerous_list)): 635 (not password_ and profile_check not in self.sat_host.empty_password_allowed_warning_dangerous_list)):
636 return "PROFILE AUTH ERROR" 636 return C.PROFILE_AUTH_ERROR
637 # profiles with empty passwords are restricted to local frontends 637 # profiles with empty passwords are restricted to local frontends
638 638
639 if login_ in self.profiles_waiting: 639 if login_ in self.profiles_waiting:
640 return "ALREADY WAITING" 640 return C.ALREADY_WAITING
641 641
642 def auth_eb(failure): 642 def auth_eb(failure):
643 fault = failure.value.faultString 643 fault = failure.value.faultString
644 self.__cleanWaiting(login_) 644 self.__cleanWaiting(login_)
645 if fault == 'PasswordError': 645 if fault == 'PasswordError':
646 log.info("Profile %s doesn't exist or the submitted password is wrong" % login_) 646 log.info("Profile %s doesn't exist or the submitted password is wrong" % login_)
647 request.write("PROFILE AUTH ERROR") 647 request.write(C.PROFILE_AUTH_ERROR)
648 elif fault == 'SASLAuthError': 648 elif fault == 'SASLAuthError':
649 log.info("The XMPP password of profile %s is wrong" % login_) 649 log.info("The XMPP password of profile %s is wrong" % login_)
650 request.write("XMPP AUTH ERROR") 650 request.write(C.XMPP_AUTH_ERROR)
651 elif fault == 'NoReply':
652 log.info(_("Did not receive a reply (the timeout expired or the connection is broken)"))
653 request.write(C.NO_REPLY)
651 else: 654 else:
652 log.error('Unmanaged fault string %s in errback for the connection of profile %s' % (fault, login_)) 655 log.error('Unmanaged fault string %s in errback for the connection of profile %s' % (fault, login_))
653 request.write('UNMANAGED FAULT STRING: %s' % str(fault)) 656 request.write(C.UNKNOWN_ERROR % fault)
654 request.finish() 657 request.finish()
655 658
656 self.profiles_waiting[login_] = request 659 self.profiles_waiting[login_] = request
657 d = self.asyncBridgeCall("asyncConnect", login_, password_) 660 d = self.asyncBridgeCall("asyncConnect", login_, password_)
658 d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb) 661 d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb)
661 664
662 def _registerNewAccount(self, request): 665 def _registerNewAccount(self, request):
663 """Create a new account, or return error 666 """Create a new account, or return error
664 @param request: request of the register form 667 @param request: request of the register form
665 @return: a constant indicating the state: 668 @return: a constant indicating the state:
666 - BAD REQUEST: something is wrong in the request (bad arguments) 669 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
667 - REGISTRATION: new account has been successfully registered 670 - C.REGISTRATION_SUCCEED: new account has been successfully registered
668 - ALREADY EXISTS: the given profile already exists 671 - C.ALREADY_EXISTS: the given profile already exists
669 - INTERNAL or 'Unknown error (...)' 672 - C.INTERNAL_ERROR or C.UNKNOWN_ERROR
670 - server.NOT_DONE_YET: the profile is being processed, the return 673 - server.NOT_DONE_YET: the profile is being processed, the return
671 value will be given later (one of those previously described) 674 value will be given later (one of those previously described)
672 """ 675 """
673 try: 676 try:
674 profile = login = request.args['register_login'][0] 677 profile = login = request.args['register_login'][0]
675 password = request.args['register_password'][0] 678 password = request.args['register_password'][0]
676 email = request.args['email'][0] 679 email = request.args['email'][0]
677 except KeyError: 680 except KeyError:
678 return "BAD REQUEST" 681 return C.BAD_REQUEST
679 if not re.match(r'^[a-z0-9_-]+$', login, re.IGNORECASE) or \ 682 if not re.match(r'^[a-z0-9_-]+$', login, re.IGNORECASE) or \
680 not re.match(r'^.+@.+\..+', email, re.IGNORECASE) or \ 683 not re.match(r'^.+@.+\..+', email, re.IGNORECASE) or \
681 len(password) < C.PASSWORD_MIN_LENGTH: 684 len(password) < C.PASSWORD_MIN_LENGTH:
682 return "BAD REQUEST" 685 return C.BAD_REQUEST
683 686
684 def registered(result): 687 def registered(result):
685 request.write('REGISTRATION') 688 request.write(C.REGISTRATION_SUCCEED)
686 request.finish() 689 request.finish()
687 690
688 def registeringError(failure): 691 def registeringError(failure):
689 reason = failure.value.faultString 692 reason = failure.value.faultString
690 if reason == "ConflictError": 693 if reason == "ConflictError":
691 request.write('ALREADY EXISTS') 694 request.write(C.ALREADY_EXISTS)
692 elif reason == "InternalError": 695 elif reason == "InternalError":
693 request.write('INTERNAL') 696 request.write(C.INTERNAL_ERROR)
694 else: 697 else:
695 log.error('Unknown registering error: %s' % (reason,)) 698 log.error('Unknown registering error: %s' % (reason,))
696 request.write('Unknown error (%s)' % reason) 699 request.write(C.UNKNOWN_ERROR % reason)
697 request.finish() 700 request.finish()
698 701
699 d = self.asyncBridgeCall("registerSatAccount", email, password, profile) 702 d = self.asyncBridgeCall("registerSatAccount", email, password, profile)
700 d.addCallback(registered) 703 d.addCallback(registered)
701 d.addErrback(registeringError) 704 d.addErrback(registeringError)
712 """Set everything when a user just logged in 715 """Set everything when a user just logged in
713 716
714 @param profile 717 @param profile
715 @param request 718 @param request
716 @return: a constant indicating the state: 719 @return: a constant indicating the state:
717 - LOGGED 720 - C.PROFILE_LOGGED
718 - SESSION_ACTIVE 721 - C.SESSION_ACTIVE
719 """ 722 """
720 self.__cleanWaiting(profile) 723 self.__cleanWaiting(profile)
721 _session = request.getSession() 724 _session = request.getSession()
722 sat_session = ISATSession(_session) 725 sat_session = ISATSession(_session)
723 if sat_session.profile: 726 if sat_session.profile:
724 log.error(('/!\\ Session has already a profile, this should NEVER happen!')) 727 log.error(('/!\\ Session has already a profile, this should NEVER happen!'))
725 request.write('SESSION_ACTIVE') 728 request.write(C.SESSION_ACTIVE)
726 request.finish() 729 request.finish()
727 return 730 return
728 sat_session.profile = profile 731 sat_session.profile = profile
729 self.sat_host.prof_connected.add(profile) 732 self.sat_host.prof_connected.add(profile)
730 733
738 #and now we disconnect the profile 741 #and now we disconnect the profile
739 self.sat_host.bridge.disconnect(profile) 742 self.sat_host.bridge.disconnect(profile)
740 743
741 _session.notifyOnExpire(onExpire) 744 _session.notifyOnExpire(onExpire)
742 745
743 request.write('LOGGED') 746 request.write(C.PROFILE_LOGGED)
744 request.finish() 747 request.finish()
745 748
746 def jsonrpc_isConnected(self): 749 def jsonrpc_isConnected(self):
747 _session = self.request.getSession() 750 _session = self.request.getSession()
748 profile = ISATSession(_session).profile 751 profile = ISATSession(_session).profile
750 753
751 def jsonrpc_asyncConnect(self): 754 def jsonrpc_asyncConnect(self):
752 _session = self.request.getSession() 755 _session = self.request.getSession()
753 profile = ISATSession(_session).profile 756 profile = ISATSession(_session).profile
754 if profile in self.profiles_waiting: 757 if profile in self.profiles_waiting:
755 raise jsonrpclib.Fault(1, 'Already waiting') # FIXME: define some standard error codes for libervia 758 raise jsonrpclib.Fault(1, C.ALREADY_WAITING) # FIXME: define some standard error codes for libervia
756 self.profiles_waiting[profile] = self.request 759 self.profiles_waiting[profile] = self.request
757 self.sat_host.bridge.asyncConnect(profile) 760 self.sat_host.bridge.asyncConnect(profile)
758 return server.NOT_DONE_YET 761 return server.NOT_DONE_YET
759 762
760 def jsonrpc_isRegistered(self): 763 def jsonrpc_isRegistered(self):
886 _session = request.getSession() 889 _session = request.getSession()
887 parsed = jsonrpclib.loads(request.content.read()) 890 parsed = jsonrpclib.loads(request.content.read())
888 profile = ISATSession(_session).profile 891 profile = ISATSession(_session).profile
889 if not profile: 892 if not profile:
890 #user is not identified, we return a jsonrpc fault 893 #user is not identified, we return a jsonrpc fault
891 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia 894 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, C.NOT_ALLOWED) # FIXME: define some standard error codes for libervia
892 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 895 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
893 self.request = request 896 self.request = request
894 return jsonrpc.JSONRPC.render(self, request) 897 return jsonrpc.JSONRPC.render(self, request)
895 898
896 899
938 with open(filepath, 'w') as f: 941 with open(filepath, 'w') as f:
939 f.write(request.args[self.NAME][0]) 942 f.write(request.args[self.NAME][0])
940 943
941 def finish(d): 944 def finish(d):
942 error = isinstance(d, Exception) or isinstance(d, Failure) 945 error = isinstance(d, Exception) or isinstance(d, Failure)
943 request.write('KO' if error else 'OK') 946 request.write(C.UPLOAD_KO if error else C.UPLOAD_OK)
944 # TODO: would be great to re-use the original Exception class and message 947 # TODO: would be great to re-use the original Exception class and message
945 # but it is lost in the middle of the backtrace and encapsulated within 948 # but it is lost in the middle of the backtrace and encapsulated within
946 # a DBusException instance --> extract the data from the backtrace? 949 # a DBusException instance --> extract the data from the backtrace?
947 request.finish() 950 request.finish()
948 951