Mercurial > libervia-web
comparison libervia/server/server.py @ 1362:45ebeea1bacd
server: improved service profile check + auto creation:
When service profile can't be connected, bridge exception is checked and if the profile
doesn't exists yet, Libervia tried to create it using in-band registration.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 14 Nov 2020 22:27:49 +0100 |
parents | 626b7bbb7f90 |
children | df40708c4c76 |
comparison
equal
deleted
inserted
replaced
1361:626b7bbb7f90 | 1362:45ebeea1bacd |
---|---|
52 from sat.tools.common import template | 52 from sat.tools.common import template |
53 from sat.tools.common import uri as common_uri | 53 from sat.tools.common import uri as common_uri |
54 from sat.tools.common.utils import recursive_update, OrderedSet | 54 from sat.tools.common.utils import recursive_update, OrderedSet |
55 from sat.tools.common import data_format | 55 from sat.tools.common import data_format |
56 from sat.tools.common import tls | 56 from sat.tools.common import tls |
57 from sat_frontends.bridge.bridge_frontend import BridgeException | |
57 import libervia | 58 import libervia |
58 from libervia.server import websockets | 59 from libervia.server import websockets |
59 from libervia.server.pages import LiberviaPage | 60 from libervia.server.pages import LiberviaPage |
60 from libervia.server.utils import quote, ProgressHandler | 61 from libervia.server.utils import quote, ProgressHandler |
61 from libervia.server.tasks.manager import TasksManager | 62 from libervia.server.tasks.manager import TasksManager |
930 for key in to_delete: | 931 for key in to_delete: |
931 del conf[key] | 932 del conf[key] |
932 if default_dict: | 933 if default_dict: |
933 conf[''] = default_dict | 934 conf[''] = default_dict |
934 | 935 |
936 async def checkAndConnectServiceProfile(self): | |
937 passphrase = self.options["passphrase"] | |
938 if not passphrase: | |
939 raise SysExit( | |
940 C.EXIT_BAD_ARG, | |
941 _("No passphrase set for service profile, please check installation " | |
942 "documentation.") | |
943 ) | |
944 try: | |
945 s_prof_connected = await self.bridgeCall("isConnected", C.SERVICE_PROFILE) | |
946 except BridgeException as e: | |
947 if e.classname == "ProfileUnknownError": | |
948 log.info("Service profile doesn't exist, creating it.") | |
949 try: | |
950 xmpp_domain = await self.bridgeCall("getConfig", "", "xmpp_domain") | |
951 xmpp_domain = xmpp_domain.strip() | |
952 if not xmpp_domain: | |
953 raise SysExit( | |
954 C.EXIT_BAD_ARG, | |
955 _('"xmpp_domain" must be set to create new accounts, please ' | |
956 'check documentation') | |
957 ) | |
958 service_profile_jid_s = f"{C.SERVICE_PROFILE}@{xmpp_domain}" | |
959 await self.bridgeCall( | |
960 "inBandAccountNew", | |
961 service_profile_jid_s, | |
962 passphrase, | |
963 "", | |
964 xmpp_domain, | |
965 0, | |
966 ) | |
967 except BridgeException as e: | |
968 if e.condition == "conflict": | |
969 log.info( | |
970 _("Service's profile JID {profile_jid} already exists") | |
971 .format(profile_jid=service_profile_jid_s) | |
972 ) | |
973 elif e.classname == "UnknownMethod": | |
974 raise SysExit( | |
975 C.EXIT_BRIDGE_ERROR, | |
976 _("Can't create service profile XMPP account, In-Band " | |
977 "Registration plugin is not activated, you'll have to " | |
978 "create the {profile!r} profile with {profile_jid!r} JID " | |
979 "manually.").format( | |
980 profile=C.SERVICE_PROFILE, | |
981 profile_jid=service_profile_jid_s) | |
982 ) | |
983 elif e.condition == "service-unavailable": | |
984 raise SysExit( | |
985 C.EXIT_BRIDGE_ERROR, | |
986 _("Can't create service profile XMPP account, In-Band " | |
987 "Registration is not activated on your server, you'll have " | |
988 "to create the {profile!r} profile with {profile_jid!r} JID " | |
989 "manually.\nNote that you'll need to activate In-Band " | |
990 "Registation on your server if you want users to be able " | |
991 "to create new account from {app_name}, please check " | |
992 "documentation.").format( | |
993 profile=C.SERVICE_PROFILE, | |
994 profile_jid=service_profile_jid_s, | |
995 app_name=C.APP_NAME) | |
996 ) | |
997 elif e.condition == "not-acceptable": | |
998 raise SysExit( | |
999 C.EXIT_BRIDGE_ERROR, | |
1000 _("Can't create service profile XMPP account, your XMPP " | |
1001 "server doesn't allow us to create new accounts with " | |
1002 "In-Band Registration please check XMPP server " | |
1003 "configuration: {reason}" | |
1004 ).format( | |
1005 profile=C.SERVICE_PROFILE, | |
1006 profile_jid=service_profile_jid_s, | |
1007 reason=e.message) | |
1008 ) | |
1009 | |
1010 else: | |
1011 raise SysExit( | |
1012 C.EXIT_BRIDGE_ERROR, | |
1013 _("Can't create service profile XMPP account, you'll have " | |
1014 "do to it manually: {reason}").format(reason=e.message) | |
1015 ) | |
1016 try: | |
1017 await self.bridgeCall("profileCreate", C.SERVICE_PROFILE, passphrase) | |
1018 await self.bridgeCall( | |
1019 "profileStartSession", passphrase, C.SERVICE_PROFILE) | |
1020 await self.bridgeCall( | |
1021 "setParam", "JabberID", service_profile_jid_s, "Connection", -1, | |
1022 C.SERVICE_PROFILE) | |
1023 await self.bridgeCall( | |
1024 "setParam", "Password", passphrase, "Connection", -1, | |
1025 C.SERVICE_PROFILE) | |
1026 except BridgeException as e: | |
1027 raise SysExit( | |
1028 C.EXIT_BRIDGE_ERROR, | |
1029 _("Can't create service profile XMPP account, you'll have " | |
1030 "do to it manually: {reason}").format(reason=e.message) | |
1031 ) | |
1032 log.info(_("Service profile has been successfully created")) | |
1033 s_prof_connected = False | |
1034 else: | |
1035 raise SysExit(C.EXIT_BRIDGE_ERROR, e.message) | |
1036 | |
1037 if not s_prof_connected: | |
1038 try: | |
1039 await self.bridgeCall( | |
1040 "connect", | |
1041 C.SERVICE_PROFILE, | |
1042 passphrase, | |
1043 {}, | |
1044 ) | |
1045 except BridgeException as e: | |
1046 raise SysExit( | |
1047 C.EXIT_BRIDGE_ERROR, | |
1048 _("Connection of service profile failed: {reason}").format(reason=e) | |
1049 ) | |
1050 | |
935 async def backendReady(self): | 1051 async def backendReady(self): |
936 log.info(f"Libervia v{self.full_version}") | 1052 log.info(f"Libervia v{self.full_version}") |
1053 | |
1054 # settings | |
937 if self.options['dev_mode']: | 1055 if self.options['dev_mode']: |
938 log.info(_("Developer mode activated")) | 1056 log.info(_("Developer mode activated")) |
939 self.media_dir = self.bridge.getConfig("", "media_dir") | 1057 self.media_dir = await self.bridgeCall("getConfig", "", "media_dir") |
940 self.local_dir = self.bridge.getConfig("", "local_dir") | 1058 self.local_dir = await self.bridgeCall("getConfig", "", "local_dir") |
941 self.cache_root_dir = os.path.join(self.local_dir, C.CACHE_DIR) | 1059 self.cache_root_dir = os.path.join(self.local_dir, C.CACHE_DIR) |
942 self.renderer = template.Renderer(self, self._front_url_filter) | 1060 self.renderer = template.Renderer(self, self._front_url_filter) |
943 sites_names = list(self.renderer.sites_paths.keys()) | 1061 sites_names = list(self.renderer.sites_paths.keys()) |
944 self.restricted_bridge = RestrictedBridge(self) | |
945 | 1062 |
946 self._moveFirstLevelToDict(self.options, "url_redirections_dict", sites_names) | 1063 self._moveFirstLevelToDict(self.options, "url_redirections_dict", sites_names) |
947 self._moveFirstLevelToDict(self.options, "menu_json", sites_names) | 1064 self._moveFirstLevelToDict(self.options, "menu_json", sites_names) |
948 self._moveFirstLevelToDict(self.options, "menu_extra_json", sites_names) | 1065 self._moveFirstLevelToDict(self.options, "menu_extra_json", sites_names) |
949 menu = self.options["menu_json"] | 1066 menu = self.options["menu_json"] |
950 if not '' in menu: | 1067 if not '' in menu: |
951 menu[''] = C.DEFAULT_MENU | 1068 menu[''] = C.DEFAULT_MENU |
952 for site, value in self.options["menu_extra_json"].items(): | 1069 for site, value in self.options["menu_extra_json"].items(): |
953 menu[site].extend(value) | 1070 menu[site].extend(value) |
1071 | |
1072 # service profile | |
1073 await self.checkAndConnectServiceProfile() | |
1074 | |
1075 # restricted bridge, the one used by browser code | |
1076 self.restricted_bridge = RestrictedBridge(self) | |
954 | 1077 |
955 # we create virtual hosts and import Libervia pages into them | 1078 # we create virtual hosts and import Libervia pages into them |
956 self.vhost_root = vhost.NameVirtualHost() | 1079 self.vhost_root = vhost.NameVirtualHost() |
957 default_site_path = Path(libervia.__file__).parent.resolve() | 1080 default_site_path = Path(libervia.__file__).parent.resolve() |
958 # self.sat_root is official Libervia site | 1081 # self.sat_root is official Libervia site |
1434 return failure | 1557 return failure |
1435 | 1558 |
1436 def startService(self): | 1559 def startService(self): |
1437 """Connect the profile for Libervia and start the HTTP(S) server(s)""" | 1560 """Connect the profile for Libervia and start the HTTP(S) server(s)""" |
1438 self._init() | 1561 self._init() |
1439 | 1562 self.initialised.addCallback(self._startService) |
1440 def eb(e): | |
1441 log.error(_("Connection failed: %s") % e) | |
1442 self.stop() | |
1443 | |
1444 def initOk(__): | |
1445 try: | |
1446 connected = self.bridge.isConnected(C.SERVICE_PROFILE) | |
1447 except Exception as e: | |
1448 # we don't want the traceback | |
1449 msg = [l for l in str(e).split("\n") if l][-1] | |
1450 log.error( | |
1451 "Can't check service profile ({profile}), are you sure it exists ?" | |
1452 "\n{error}".format(profile=C.SERVICE_PROFILE, error=msg)) | |
1453 self.stop() | |
1454 return | |
1455 if not connected: | |
1456 self.bridge.connect( | |
1457 C.SERVICE_PROFILE, | |
1458 self.options["passphrase"], | |
1459 {}, | |
1460 callback=self._startService, | |
1461 errback=eb, | |
1462 ) | |
1463 else: | |
1464 self._startService() | |
1465 | |
1466 self.initialised.addCallback(initOk) | |
1467 self.initialised.addErrback(self.initEb) | 1563 self.initialised.addErrback(self.initEb) |
1468 | 1564 |
1469 ## URLs ## | 1565 ## URLs ## |
1470 | 1566 |
1471 def putChildSAT(self, path, resource): | 1567 def putChildSAT(self, path, resource): |