comparison src/server/server.py @ 961:22fe06569b1a

server: moved logging worflow in separated method, so it can be used by Libervia Pages
author Goffi <goffi@goffi.org>
date Fri, 27 Oct 2017 18:35:23 +0200
parents 968eda9e982a
children c7fba7709d05
comparison
equal deleted inserted replaced
960:e59edcae4c18 961:22fe06569b1a
887 887
888 def __init__(self, sat_host): 888 def __init__(self, sat_host):
889 JSONRPCMethodManager.__init__(self, sat_host) 889 JSONRPCMethodManager.__init__(self, sat_host)
890 self.profiles_waiting = {} 890 self.profiles_waiting = {}
891 self.request = None 891 self.request = None
892 self.waiting_profiles = WaitingRequests()
893 892
894 def render(self, request): 893 def render(self, request):
895 """ 894 """
896 Render method with some hacks: 895 Render method with some hacks:
897 - if login is requested, try to login with form data 896 - if login is requested, try to login with form data
925 submit_type = request.args['submit_type'][0] 924 submit_type = request.args['submit_type'][0]
926 except KeyError: 925 except KeyError:
927 return C.BAD_REQUEST 926 return C.BAD_REQUEST
928 927
929 if submit_type == 'register': 928 if submit_type == 'register':
930 if not self.sat_host.options["allow_registration"]: 929 self._registerNewAccount(request)
931 log.warning(u"Registration received while it is not allowed, hack attempt?") 930 return server.NOT_DONE_YET
932 return exceptions.PermissionError(u"Registration is not allowed on this server")
933 return self._registerNewAccount(request)
934 elif submit_type == 'login': 931 elif submit_type == 'login':
935 d = self.asyncBridgeCall("getNewAccountDomain") 932 self._loginAccount(request)
936 d.addCallback(lambda domain: self._loginAccount(request, domain))
937 return server.NOT_DONE_YET 933 return server.NOT_DONE_YET
938 return Exception('Unknown submit type') 934 return Exception('Unknown submit type')
939 935
940 def _loginAccount(self, request, new_account_domain): 936 @defer.inlineCallbacks
937 def _registerNewAccount(self, request):
938 try:
939 login = request.args['register_login'][0]
940 password = request.args['register_password'][0]
941 email = request.args['email'][0]
942 except KeyError:
943 request.write(C.BAD_REQUEST)
944 request.finish()
945 return
946 status = yield self.sat_host.registerNewAccount(request, login, password, email)
947 request.write(status)
948 request.finish()
949
950 @defer.inlineCallbacks
951 def _loginAccount(self, request):
941 """Try to authenticate the user with the request information. 952 """Try to authenticate the user with the request information.
942 953
943 @param request: request of the register form 954 will write to request a constant indicating the state:
944 @param new_account_domain (unicode): host corresponding to the local domain 955 - C.PROFILE_LOGGED: profile is connected
945 @return: a constant indicating the state: 956 - C.PROFILE_LOGGED_EXT_JID: profile is connected and an external jid has been used
957 - C.SESSION_ACTIVE: session was already active
946 - C.BAD_REQUEST: something is wrong in the request (bad arguments) 958 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
947 - C.PROFILE_AUTH_ERROR: either the profile (login) or the profile password is wrong 959 - C.PROFILE_AUTH_ERROR: either the profile (login) or the profile password is wrong
948 - C.XMPP_AUTH_ERROR: the profile is authenticated but the XMPP password is wrong 960 - C.XMPP_AUTH_ERROR: the profile is authenticated but the XMPP password is wrong
949 - C.ALREADY_WAITING: a request has already been submitted for this profile 961 - C.ALREADY_WAITING: a request has already been submitted for this profil, C.PROFILE_LOGGED_EXT_JID)e
950 - server.NOT_DONE_YET: the profile is being processed, the return 962 - C.NOT_CONNECTED: connection has not been established
951 value will be given by self._logged or auth_eb 963 the request will then be finished
964 @param request: request of the register form
952 """ 965 """
953 try: 966 try:
954 login = request.args['login'][0] 967 login = request.args['login'][0]
955 password = request.args['login_password'][0] 968 password = request.args['login_password'][0]
956 except KeyError: 969 except KeyError:
958 request.finish() 971 request.finish()
959 return 972 return
960 973
961 assert login 974 assert login
962 975
963 if login.startswith('@'): # this is checked by javascript but also here for security reason
964 # FIXME: return an error instead of an Exception?
965 raise Exception('No profile_key allowed')
966
967 if '@' in login:
968 try:
969 login_jid = jid.JID(login)
970 except (RuntimeError, jid.InvalidFormat, AttributeError):
971 request.write(C.PROFILE_AUTH_ERROR)
972 request.finish()
973 return
974
975 if login_jid.host == new_account_domain:
976 # redirect "user@libervia.org" to the "user" profile
977 login = login_jid.user
978 login_jid = None
979 else:
980 login_jid = None
981
982 try: 976 try:
983 profile = self.sat_host.bridge.profileNameGet(login) 977 status = yield self.sat_host.connect(request, login, password)
984 except Exception: # XXX: ProfileUnknownError wouldn't work, it's encapsulated 978 except (exceptions.DataError,
985 if login_jid is not None and login_jid.user: # try to create a new sat profile using the XMPP credentials 979 exceptions.ProfileUnknownError,
986 if not self.sat_host.options["allow_registration"]: 980 exceptions.PermissionError):
987 log.warning(u"Trying to register JID account while registration is not allowed") 981 request.write(C.PROFILE_AUTH_ERROR)
988 request.write(C.PROFILE_AUTH_ERROR) 982 request.finish()
989 request.finish() 983 return
990 return 984 except exceptions.NotReady:
991 profile = login # FIXME: what if there is a resource?
992 connect_method = "asyncConnectWithXMPPCredentials"
993 register_with_ext_jid = True
994 else: # non existing username
995 request.write(C.PROFILE_AUTH_ERROR)
996 request.finish()
997 return
998 else:
999 if profile != login or (not password and profile not in self.sat_host.options['empty_password_allowed_warning_dangerous_list']):
1000 # profiles with empty passwords are restricted to local frontends
1001 request.write(C.PROFILE_AUTH_ERROR)
1002 request.finish()
1003 return
1004 register_with_ext_jid = False
1005
1006 connect_method = "connect"
1007
1008 if self.waiting_profiles.getRequest(profile):
1009 request.write(C.ALREADY_WAITING) 985 request.write(C.ALREADY_WAITING)
1010 request.finish() 986 request.finish()
1011 return 987 return
1012 988 except exceptions.TimeOutError:
1013 def auth_eb(failure): 989 request.write(C.NO_REPLY)
1014 fault = failure.value.faultString
1015 self.waiting_profiles.purgeRequest(profile)
1016 if fault in ('PasswordError', 'ProfileUnknownError'):
1017 log.info(u"Profile %s doesn't exist or the submitted password is wrong" % profile)
1018 request.write(C.PROFILE_AUTH_ERROR)
1019 elif fault == 'SASLAuthError':
1020 log.info(u"The XMPP password of profile %s is wrong" % profile)
1021 request.write(C.XMPP_AUTH_ERROR)
1022 elif fault == 'NoReply':
1023 log.info(_("Did not receive a reply (the timeout expired or the connection is broken)"))
1024 request.write(C.NO_REPLY)
1025 else:
1026 log.error(u'Unmanaged fault string "%s" in errback for the connection of profile %s' % (fault, profile))
1027 request.write(fault)
1028 request.finish() 990 request.finish()
1029 991 return
1030 self.waiting_profiles.setRequest(request, profile, register_with_ext_jid) 992 except exceptions.InternalError as e:
1031 d = self.asyncBridgeCall(connect_method, profile, password) 993 request.write(e.message)
1032 d.addCallbacks(lambda connected: self._logged(profile, request) if connected else None, auth_eb)
1033
1034 def _registerNewAccount(self, request):
1035 """Create a new account, or return error
1036 @param request: request of the register form
1037 @return: a constant indicating the state:
1038 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
1039 - C.REGISTRATION_SUCCEED: new account has been successfully registered
1040 - C.ALREADY_EXISTS: the given profile already exists
1041 - C.INTERNAL_ERROR or any unmanaged fault string
1042 - server.NOT_DONE_YET: the profile is being processed, the return
1043 value will be given later (one of those previously described)
1044 """
1045 try:
1046 # XXX: for now libervia forces the creation to lower case
1047 profile = login = request.args['register_login'][0].lower()
1048 password = request.args['register_password'][0]
1049 email = request.args['email'][0]
1050 except KeyError:
1051 return C.BAD_REQUEST
1052 if not re.match(r'^[a-z0-9_-]+$', login, re.IGNORECASE) or \
1053 not re.match(r'^.+@.+\..+', email, re.IGNORECASE) or \
1054 len(password) < C.PASSWORD_MIN_LENGTH:
1055 return C.BAD_REQUEST
1056
1057 def registered(result):
1058 request.write(C.REGISTRATION_SUCCEED)
1059 request.finish() 994 request.finish()
1060 995 return
1061 def registeringError(failure): 996 except exceptions.ConflictError:
1062 reason = failure.value.faultString
1063 if reason == "ConflictError":
1064 request.write(C.ALREADY_EXISTS)
1065 elif reason == "InternalError":
1066 request.write(C.INTERNAL_ERROR)
1067 else:
1068 log.error(u'Unknown registering error: %s' % (reason,))
1069 request.write(reason)
1070 request.finish()
1071
1072 d = self.asyncBridgeCall("registerSatAccount", email, password, profile)
1073 d.addCallback(registered)
1074 d.addErrback(registeringError)
1075 return server.NOT_DONE_YET
1076
1077 def _logged(self, profile, request):
1078 """Set everything when a user just logged in
1079
1080 @param profile
1081 @param request
1082 @return: a constant indicating the state:
1083 - C.PROFILE_LOGGED
1084 - C.SESSION_ACTIVE
1085 """
1086 register_with_ext_jid = self.waiting_profiles.getRegisterWithExtJid(profile)
1087 self.waiting_profiles.purgeRequest(profile)
1088 _session = request.getSession()
1089 sat_session = session_iface.ISATSession(_session)
1090 if sat_session.profile:
1091 log.error(_(u'/!\\ Session has already a profile, this should NEVER happen!'))
1092 request.write(C.SESSION_ACTIVE) 997 request.write(C.SESSION_ACTIVE)
1093 request.finish() 998 request.finish()
1094 return 999 return
1095 # we manage profile server side to avoid profile spoofing 1000 except ValueError as e:
1096 sat_session.profile = profile 1001 if e.message in (C.PROFILE_AUTH_ERROR, C.XMPP_AUTH_ERROR):
1097 self.sat_host.prof_connected.add(profile) 1002 request.write(e.message)
1098 cache_dir = os.path.join(self.sat_host.cache_root_dir, regex.pathEscape(profile)) 1003 request.finish()
1099 # FIXME: would be better to have a global /cache URL which redirect to profile's cache directory, without uuid 1004 return
1100 self.sat_host.cache_resource.putChild(sat_session.uuid, ProtectedFile(cache_dir)) 1005 else:
1101 log.debug(_(u"profile cache resource added from {uuid} to {path}").format(uuid=sat_session.uuid, path=cache_dir)) 1006 raise e
1102 1007
1103 def onExpire(): 1008 assert status
1104 log.info(u"Session expired (profile=%s)" % (profile,)) 1009 request.write(status)
1105 self.sat_host.cache_resource.delEntity(sat_session.uuid)
1106 log.debug(_(u"profile cache resource {uuid} deleted").format(uuid = sat_session.uuid))
1107 try:
1108 #We purge the queue
1109 del self.sat_host.signal_handler.queue[profile]
1110 except KeyError:
1111 pass
1112 #and now we disconnect the profile
1113 self.sat_host.bridge.disconnect(profile)
1114
1115 _session.notifyOnExpire(onExpire)
1116
1117 request.write(C.PROFILE_LOGGED_REGISTERED_WITH_EXT_JID if register_with_ext_jid else C.PROFILE_LOGGED)
1118 request.finish() 1010 request.finish()
1119 1011
1120 def jsonrpc_isConnected(self): 1012 def jsonrpc_isConnected(self):
1121 _session = self.request.getSession() 1013 _session = self.request.getSession()
1122 profile = session_iface.ISATSession(_session).profile 1014 profile = session_iface.ISATSession(_session).profile
1213 _session.unlock() 1105 _session.unlock()
1214 try: 1106 try:
1215 source_defer = self.signalDeferred[profile] 1107 source_defer = self.signalDeferred[profile]
1216 if source_defer.called and source_defer.result[0] == "disconnected": 1108 if source_defer.called and source_defer.result[0] == "disconnected":
1217 log.info(u"[%s] disconnected" % (profile,)) 1109 log.info(u"[%s] disconnected" % (profile,))
1218 _session.expire() 1110 try:
1111 _session.expire()
1112 except KeyError:
1113 # FIXME: happen if session is ended using login page
1114 # when pyjamas page is also launched
1115 log.warning(u'session is already expired')
1219 except IndexError: 1116 except IndexError:
1220 log.error("Deferred result should be a tuple with fonction name first") 1117 log.error("Deferred result should be a tuple with fonction name first")
1221 1118
1222 self.signalDeferred[profile] = defer.Deferred() 1119 self.signalDeferred[profile] = defer.Deferred()
1223 self.request.notifyFinish().addBoth(unlock, profile) 1120 self.request.notifyFinish().addBoth(unlock, profile)
1270 """Connection is done. 1167 """Connection is done.
1271 1168
1272 @param profile (unicode): %(doc_profile)s 1169 @param profile (unicode): %(doc_profile)s
1273 @param jid_s (unicode): the JID that we were assigned by the server, as the resource might differ from the JID we asked for. 1170 @param jid_s (unicode): the JID that we were assigned by the server, as the resource might differ from the JID we asked for.
1274 """ 1171 """
1172 # FIXME: _logged should not be called from here, check this code
1173 # FIXME: check if needed to connect with external jid
1275 # jid_s is handled in QuickApp.connectionHandler already 1174 # jid_s is handled in QuickApp.connectionHandler already
1276 assert(self.register) # register must be plugged 1175 # assert self.register # register must be plugged
1277 request = self.register.waiting_profiles.getRequest(profile) 1176 # request = self.sat_host.waiting_profiles.getRequest(profile)
1278 if request: 1177 # if request:
1279 self.register._logged(profile, request) 1178 # self.sat_host._logged(profile, request)
1280 1179
1281 def disconnected(self, profile): 1180 def disconnected(self, profile):
1282 if not profile in self.sat_host.prof_connected: 1181 if not profile in self.sat_host.prof_connected:
1283 log.error("'disconnected' signal received for a not connected profile") 1182 log.error("'disconnected' signal received for a not connected profile")
1284 return 1183 return
1872 class Libervia(service.Service): 1771 class Libervia(service.Service):
1873 1772
1874 def __init__(self, options): 1773 def __init__(self, options):
1875 self.options = options 1774 self.options = options
1876 self.initialised = defer.Deferred() 1775 self.initialised = defer.Deferred()
1776 self.waiting_profiles = WaitingRequests() # FIXME: should be removed
1877 1777
1878 if self.options['base_url_ext']: 1778 if self.options['base_url_ext']:
1879 self.base_url_ext = self.options.pop('base_url_ext') 1779 self.base_url_ext = self.options.pop('base_url_ext')
1880 if self.base_url_ext[-1] != '/': 1780 if self.base_url_ext[-1] != '/':
1881 self.base_url_ext += '/' 1781 self.base_url_ext += '/'
2020 kwargs["callback"] = _callback 1920 kwargs["callback"] = _callback
2021 kwargs["errback"] = _errback 1921 kwargs["errback"] = _errback
2022 getattr(self.bridge, method_name)(*args, **kwargs) 1922 getattr(self.bridge, method_name)(*args, **kwargs)
2023 return d 1923 return d
2024 1924
1925 def _logged(self, profile, request):
1926 """Set everything when a user just logged in
1927
1928 @param profile
1929 @param request
1930 @return: a constant indicating the state:
1931 - C.PROFILE_LOGGED
1932 - C.PROFILE_LOGGED_EXT_JID
1933 @raise exceptions.ConflictError: session is already active
1934 """
1935 register_with_ext_jid = self.waiting_profiles.getRegisterWithExtJid(profile)
1936 self.waiting_profiles.purgeRequest(profile)
1937 _session = request.getSession()
1938 sat_session = session_iface.ISATSession(_session)
1939 if sat_session.profile:
1940 log.error(_(u'/!\\ Session has already a profile, this should NEVER happen!'))
1941 raise failure.Failure(exceptions.ConflictError("Already active"))
1942
1943 sat_session.profile = profile
1944 self.prof_connected.add(profile)
1945 cache_dir = os.path.join(self.cache_root_dir, regex.pathEscape(profile))
1946 # FIXME: would be better to have a global /cache URL which redirect to profile's cache directory, without uuid
1947 self.cache_resource.putChild(sat_session.uuid, ProtectedFile(cache_dir))
1948 log.debug(_(u"profile cache resource added from {uuid} to {path}").format(uuid=sat_session.uuid, path=cache_dir))
1949
1950 def onExpire():
1951 log.info(u"Session expired (profile={profile})".format(profile=profile,))
1952 self.cache_resource.delEntity(sat_session.uuid)
1953 log.debug(_(u"profile cache resource {uuid} deleted").format(uuid = sat_session.uuid))
1954 try:
1955 #We purge the queue
1956 del self.signal_handler.queue[profile]
1957 except KeyError:
1958 pass
1959 #and now we disconnect the profile
1960 self.bridge.disconnect(profile)
1961
1962 _session.notifyOnExpire(onExpire)
1963
1964 return C.PROFILE_LOGGED_EXT_JID if register_with_ext_jid else C.PROFILE_LOGGED
1965
1966 @defer.inlineCallbacks
1967 def connect(self, request, login, password):
1968 """log user in
1969
1970 If an other user was already logged, it will be unlogged first
1971 @param request(server.Request): request linked to the session
1972 @param login(unicode): user login
1973 can be profile name
1974 can be profile@[libervia_domain.ext]
1975 can be a jid (a new profile will be created with this jid if needed)
1976 @param password(unicode): user password
1977 @return (unicode, None): C.SESSION_ACTIVE: if session was aleady active else self._logged value
1978 @raise exceptions.DataError: invalid login
1979 @raise exceptions.ProfileUnknownError: this login doesn't exist
1980 @raise exceptions.PermissionError: a login is not accepted (e.g. empty password not allowed)
1981 @raise exceptions.NotReady: a profile connection is already waiting
1982 @raise exceptions.TimeoutError: didn't received and answer from Bridge
1983 @raise exceptions.InternalError: unknown error
1984 @raise ValueError(C.PROFILE_AUTH_ERROR): invalid login and/or password
1985 @raise ValueError(C.XMPP_AUTH_ERROR): invalid XMPP account password
1986 """
1987
1988 # XXX: all security checks must be done here, even if present in javascript
1989 if login.startswith('@'):
1990 raise failure.Failure(exceptions.DataError('No profile_key allowed'))
1991
1992 if '@' in login:
1993 try:
1994 login_jid = jid.JID(login)
1995 except (RuntimeError, jid.InvalidFormat, AttributeError):
1996 raise failure.Failure(exceptions.DataError('No profile_key allowed'))
1997
1998 # FIXME: should it be cached?
1999 new_account_domain = yield self.bridgeCall("getNewAccountDomain")
2000
2001 if login_jid.host == new_account_domain:
2002 # redirect "user@libervia.org" to the "user" profile
2003 login = login_jid.user
2004 login_jid = None
2005 else:
2006 login_jid = None
2007
2008 try:
2009 profile = yield self.bridgeCall("profileNameGet", login)
2010 except Exception: # XXX: ProfileUnknownError wouldn't work, it's encapsulated
2011 # FIXME: find a better way to handle bridge errors
2012 if login_jid is not None and login_jid.user: # try to create a new sat profile using the XMPP credentials
2013 if not self.options["allow_registration"]:
2014 log.warning(u"Trying to register JID account while registration is not allowed")
2015 raise failure.Failure(exceptions.DataError(u"JID login while registration is not allowed"))
2016 profile = login # FIXME: what if there is a resource?
2017 connect_method = "asyncConnectWithXMPPCredentials"
2018 register_with_ext_jid = True
2019 else: # non existing username
2020 raise failure.Failure(exceptions.ProfileUnknownError())
2021 else:
2022 if profile != login or (not password and profile not in self.options['empty_password_allowed_warning_dangerous_list']):
2023 # profiles with empty passwords are restricted to local frontends
2024 raise exceptions.PermissionError
2025 register_with_ext_jid = False
2026
2027 connect_method = "connect"
2028
2029 # we check if there is not already an active session
2030 sat_session = session_iface.ISATSession(request.getSession())
2031 if sat_session.profile:
2032 # yes, there is
2033 if sat_session.profile != profile:
2034 # it's a different profile, we need to disconnect it
2035 log.warning(_(u"{new_profile} requested login, but {old_profile} was already connected, disconnecting {old_profile}").format(
2036 old_profile = sat_session.profile,
2037 new_profile = profile))
2038 self.purgeSession(request)
2039
2040 if self.waiting_profiles.getRequest(profile):
2041 # FIXME: check if and when this can happen
2042 raise failure.Failure(exceptions.NotReady("Already waiting"))
2043
2044 self.waiting_profiles.setRequest(request, profile, register_with_ext_jid)
2045 try:
2046 connected = yield self.bridgeCall(connect_method, profile, password)
2047 except Exception as failure_:
2048 fault = failure_.faultString
2049 self.waiting_profiles.purgeRequest(profile)
2050 if fault in ('PasswordError', 'ProfileUnknownError'):
2051 log.info(u"Profile {profile} doesn't exist or the submitted password is wrong".format(profile=profile))
2052 raise failure.Failure(ValueError(C.PROFILE_AUTH_ERROR))
2053 elif fault == 'SASLAuthError':
2054 log.info(u"The XMPP password of profile {profile} is wrong".format(profile=profile))
2055 raise failure.Failure(ValueError(C.XMPP_AUTH_ERROR))
2056 elif fault == 'NoReply':
2057 log.info(_("Did not receive a reply (the timeout expired or the connection is broken)"))
2058 raise exceptions.TimeOutError
2059 else:
2060 log.error(u'Unmanaged fault string "{fault}" in errback for the connection of profile {profile}'.format(
2061 fault=fault, profile=profile))
2062 raise failure.Failure(exceptions.InternalError(fault))
2063
2064 if connected:
2065 # profile is already connected in backend
2066 # do we have a corresponding session in Libervia?
2067 sat_session = session_iface.ISATSession(request.getSession())
2068 if sat_session.profile:
2069 # yes, session is active
2070 if sat_session.profile != profile:
2071 # existing session should have been ended above
2072 # so this line should never be reached
2073 log.error(_(u'session profile [{session_profile}] differs from login profile [{profile}], this should not happen!').format(
2074 session_profile = sat_session.profile,
2075 profile = profile
2076 ))
2077 raise exceptions.InternalError("profile mismatch")
2078 defer.returnValue(C.SESSION_ACTIVE)
2079 log.info(_(u"profile {profile} was already connected in backend".format(profile=profile)))
2080 # no, we have to create it
2081 defer.returnValue(self._logged(profile, request))
2082
2083 def registerNewAccount(self, request, login, password, email):
2084 """Create a new account, or return error
2085 @param request(server.Request): request linked to the session
2086 @param login(unicode): new account requested login
2087 @param email(unicode): new account email
2088 @param password(unicode): new account password
2089 @return(unicode): a constant indicating the state:
2090 - C.BAD_REQUEST: something is wrong in the request (bad arguments)
2091 - C.INVALID_INPUT: one of the data is not valid
2092 - C.REGISTRATION_SUCCEED: new account has been successfully registered
2093 - C.ALREADY_EXISTS: the given profile already exists
2094 - C.INTERNAL_ERROR or any unmanaged fault string
2095 @raise PermissionError: registration is now allowed in server configuration
2096 """
2097 if not self.options["allow_registration"]:
2098 log.warning(_(u"Registration received while it is not allowed, hack attempt?"))
2099 raise failure.Failure(exceptions.PermissionError(u"Registration is not allowed on this server"))
2100
2101 if not re.match(C.REG_LOGIN_RE, login) or \
2102 not re.match(C.REG_EMAIL_RE, email, re.IGNORECASE) or \
2103 len(password) < C.PASSWORD_MIN_LENGTH:
2104 return C.INVALID_INPUT
2105
2106 def registered(result):
2107 return C.REGISTRATION_SUCCEED
2108
2109 def registeringError(failure):
2110 status = failure.value.faultString
2111 if status == "ConflictError":
2112 return C.ALREADY_EXISTS
2113 elif status == "InternalError":
2114 return C.INTERNAL_ERROR
2115 else:
2116 log.error(_(u'Unknown registering error status: {status }').format(
2117 status = status))
2118 return status
2119
2120 d = self.bridgeCall("registerSatAccount", email, password, login)
2121 d.addCallback(registered)
2122 d.addErrback(registeringError)
2123 return d
2124
2025 def addCleanup(self, callback, *args, **kwargs): 2125 def addCleanup(self, callback, *args, **kwargs):
2026 """Add cleaning method to call when service is stopped 2126 """Add cleaning method to call when service is stopped
2127
2027 cleaning method will be called in reverse order of they insertion 2128 cleaning method will be called in reverse order of they insertion
2028 @param callback: callable to call on service stop 2129 @param callback: callable to call on service stop
2029 @param *args: list of arguments of the callback 2130 @param *args: list of arguments of the callback
2030 @param **kwargs: list of keyword arguments of the callback""" 2131 @param **kwargs: list of keyword arguments of the callback"""
2031 self._cleanup.insert(0, (callback, args, kwargs)) 2132 self._cleanup.insert(0, (callback, args, kwargs))