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):