comparison twisted/plugins/libervia_server.py @ 1216:b2d067339de3

python 3 port: /!\ Python 3.6+ is now needed to use libervia /!\ instability may occur and features may not be working anymore, this will improve with time /!\ TxJSONRPC dependency has been removed The same procedure as in backend has been applied (check backend commit ab2696e34d29 logs for details). Removed now deprecated code (Pyjamas compiled browser part, legacy blog, JSON RPC related code). Adapted code to work without `html` and `themes` dirs.
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:12:31 +0200
parents b300eaec53b6
children 331ada56cdca
comparison
equal deleted inserted replaced
1215:f14ab8a25e8b 1216:b2d067339de3
39 from libervia.server.constants import Const as C 39 from libervia.server.constants import Const as C
40 40
41 from sat.core.i18n import _ 41 from sat.core.i18n import _
42 from sat.tools import config 42 from sat.tools import config
43 43
44 from zope.interface import implements 44 from zope.interface import implementer
45 45
46 from twisted.python import usage 46 from twisted.python import usage
47 from twisted.plugin import IPlugin 47 from twisted.plugin import IPlugin
48 from twisted.application.service import IServiceMaker 48 from twisted.application.service import IServiceMaker
49 import ConfigParser 49 import configparser
50 50
51 51
52 CONFIG_SECTION = C.APP_NAME.lower() 52 CONFIG_SECTION = C.APP_NAME.lower()
53 if libervia.__version__ != sat.__version__: 53 if libervia.__version__ != sat.__version__:
54 import sys 54 import sys
55 55
56 sys.stderr.write( 56 sys.stderr.write(
57 u"""sat module version ({sat_version}) and {current_app} version ({current_version}) mismatch 57 """sat module version ({sat_version}) and {current_app} version ({current_version}) mismatch
58 58
59 sat module is located at {sat_path} 59 sat module is located at {sat_path}
60 libervia module is located at {libervia_path} 60 libervia module is located at {libervia_path}
61 61
62 Please be sure to have the same version running 62 Please be sure to have the same version running
76 76
77 os._exit(1) 77 os._exit(1)
78 78
79 79
80 def coerceConnectionType(value): # called from Libervia.OPT_PARAMETERS 80 def coerceConnectionType(value): # called from Libervia.OPT_PARAMETERS
81 assert isinstance(value, str)
81 allowed_values = ("http", "https", "both") 82 allowed_values = ("http", "https", "both")
82 if value not in allowed_values: 83 if value not in allowed_values:
83 raise ValueError( 84 raise ValueError(
84 "%(given)s not in %(expected)s" 85 "%(given)s not in %(expected)s"
85 % {"given": value, "expected": str(allowed_values)} 86 % {"given": value, "expected": str(allowed_values)}
86 ) 87 )
87 return value 88 return value
88 89
89 90
90 def coerceDataDir(value): # called from Libervia.OPT_PARAMETERS
91 if not value:
92 # we ignore missing values
93 return u''
94 if isinstance(value, unicode):
95 # XXX: if value comes from sat.conf, it's unicode,
96 # and we need byte str here (for twisted)
97 value = value.encode("utf-8")
98 value = value.encode("utf-8")
99 html = os.path.join(value, C.HTML_DIR)
100 if not os.path.isfile(os.path.join(html, C.LIBERVIA_MAIN_PAGE)):
101 raise ValueError(
102 "%s is not a Libervia's browser HTML directory" % os.path.realpath(html)
103 )
104 themes_dir = os.path.join(value, C.THEMES_DIR)
105 if not os.path.isfile(os.path.join(themes_dir, "default/styles/blog.css")):
106 # XXX: we just display a message, as themes_dir is only used by legacy blog
107 # which will be removed entirely in 0.8
108 # TODO: remove entirely legacy blog and linked options
109 print "%s is not a Libervia's server data directory" % os.path.realpath(
110 themes_dir)
111 return value
112
113
114 def coerceBool(value): 91 def coerceBool(value):
115 return C.bool(value) 92 return C.bool(value)
116 93
117 94
118 def coerceUnicode(value): 95 def coerceUnicode(value):
96 assert isinstance(value, str)
119 # XXX: we use this method to check which value to convert to Unicode 97 # XXX: we use this method to check which value to convert to Unicode
120 # but we don't do the conversion here as Twisted expect str 98 # but we don't do the conversion here as Twisted expect str
121 return value 99 return value
122 100
123 101
124 DATA_DIR_DEFAULT = '' 102 DATA_DIR_DEFAULT = ''
125 # options which are in sat.conf and on command line, 103 # options which are in sat.conf and on command line,
126 # see https://twistedmatrix.com/documents/current/api/twisted.python.usage.Options.html 104 # see https://twistedmatrix.com/documents/current/api/twisted.python.usage.Options.html
127 OPT_PARAMETERS_BOTH = [['connection_type', 't', 'https', _(u"'http', 'https' or 'both' " 105 OPT_PARAMETERS_BOTH = [['connection_type', 't', 'https', _("'http', 'https' or 'both' "
128 "(to launch both servers).").encode('utf-8'), 106 "(to launch both servers).").encode('utf-8'),
129 coerceConnectionType], 107 coerceConnectionType],
130 ['port', 'p', 8080, 108 ['port', 'p', 8080,
131 _(u'The port number to listen HTTP on.').encode('utf-8'), int], 109 _('The port number to listen HTTP on.').encode('utf-8'), int],
132 ['port_https', 's', 8443, 110 ['port_https', 's', 8443,
133 _(u'The port number to listen HTTPS on.').encode('utf-8'), int], 111 _('The port number to listen HTTPS on.').encode('utf-8'), int],
134 ['port_https_ext', 'e', 0, _(u'The external port number used for ' 112 ['port_https_ext', 'e', 0, _('The external port number used for '
135 u'HTTPS (0 means port_https value).').encode('utf-8'), int], 113 'HTTPS (0 means port_https value).').encode('utf-8'), int],
136 ['tls_private_key', '', '', _(u'TLS certificate private key (PEM ' 114 ['tls_private_key', '', '', _('TLS certificate private key (PEM '
137 u'format)').encode('utf-8'), coerceUnicode], 115 'format)').encode('utf-8'), coerceUnicode],
138 ['tls_certificate', 'c', 'libervia.pem', _(u'TLS public ' 116 ['tls_certificate', 'c', 'libervia.pem', _('TLS public '
139 u'certificate or private key and public certificate combined ' 117 'certificate or private key and public certificate combined '
140 u'(PEM format)').encode('utf-8'), coerceUnicode], 118 '(PEM format)').encode('utf-8'), coerceUnicode],
141 ['tls_chain', '', '', _(u'TLS certificate intermediate chain (PEM ' 119 ['tls_chain', '', '', _('TLS certificate intermediate chain (PEM '
142 u'format)').encode('utf-8'), coerceUnicode], 120 'format)').encode('utf-8'), coerceUnicode],
143 ['redirect_to_https', 'r', True, _(u'Automatically redirect from ' 121 ['redirect_to_https', 'r', True, _('Automatically redirect from '
144 u'HTTP to HTTPS.').encode('utf-8'), coerceBool], 122 'HTTP to HTTPS.').encode('utf-8'), coerceBool],
145 ['security_warning', 'w', True, _(u'Warn user that he is about to ' 123 ['security_warning', 'w', True, _('Warn user that he is about to '
146 u'connect on HTTP.').encode('utf-8'), coerceBool], 124 'connect on HTTP.').encode('utf-8'), coerceBool],
147 ['passphrase', 'k', '', (_(u"Passphrase for the SàT profile " 125 ['passphrase', 'k', '', (_("Passphrase for the SàT profile "
148 u"named '%s'") % C.SERVICE_PROFILE).encode('utf-8'), 126 "named '%s'") % C.SERVICE_PROFILE).encode('utf-8'),
149 coerceUnicode], 127 coerceUnicode],
150 ['data_dir', 'd', DATA_DIR_DEFAULT, _(u'Data directory for ' 128 ['allow_registration', '', True, _('Allow user to register new '
151 u'Libervia legacy').encode('utf-8'), coerceDataDir], 129 'account').encode('utf-8'), coerceBool],
152 ['allow_registration', '', True, _(u'Allow user to register new '
153 u'account').encode('utf-8'), coerceBool],
154 ['base_url_ext', '', '', 130 ['base_url_ext', '', '',
155 _(u'The external URL to use as base URL').encode('utf-8'), 131 _('The external URL to use as base URL').encode('utf-8'),
156 coerceUnicode], 132 coerceUnicode],
157 ['dev_mode', 'D', False, _(u'Developer mode, automatically reload' 133 ['dev_mode', 'D', False, _('Developer mode, automatically reload'
158 u'modified pages').encode('utf-8'), coerceBool], 134 'modified pages').encode('utf-8'), coerceBool],
159 ] 135 ]
160 # Options which are in sat.conf only 136 # Options which are in sat.conf only
161 OPT_PARAMETERS_CFG = [ 137 OPT_PARAMETERS_CFG = [
162 ["empty_password_allowed_warning_dangerous_list", None, "", None], 138 ["empty_password_allowed_warning_dangerous_list", None, "", None],
163 ["vhosts_dict", None, {}, None], 139 ["vhosts_dict", None, {}, None],
164 ["url_redirections_dict", None, {}, None], 140 ["url_redirections_dict", None, {}, None],
165 ["menu_json", None, {u'': C.DEFAULT_MENU}, None], 141 ["menu_json", None, {'': C.DEFAULT_MENU}, None],
166 ["tickets_trackers_json", None, None, None], 142 ["tickets_trackers_json", None, None, None],
167 ["mr_handlers_json", None, None, None], 143 ["mr_handlers_json", None, None, None],
168 ] 144 ]
169 145
170 146
181 # (there is no __init__.py file, as required by twistd plugin system), so we set the 157 # (there is no __init__.py file, as required by twistd plugin system), so we set the
182 # global values from here 158 # global values from here
183 server.DATA_DIR_DEFAULT = DATA_DIR_DEFAULT 159 server.DATA_DIR_DEFAULT = DATA_DIR_DEFAULT
184 server.OPT_PARAMETERS_BOTH = OPT_PARAMETERS_BOTH 160 server.OPT_PARAMETERS_BOTH = OPT_PARAMETERS_BOTH
185 server.OPT_PARAMETERS_CFG = OPT_PARAMETERS_CFG 161 server.OPT_PARAMETERS_CFG = OPT_PARAMETERS_CFG
186 server.coerceDataDir = coerceDataDir
187 162
188 163
189 class Options(usage.Options): 164 class Options(usage.Options):
190 # optArgs is not really useful in our case, we need more than a flag 165 # optArgs is not really useful in our case, we need more than a flag
191 optParameters = OPT_PARAMETERS_BOTH 166 optParameters = OPT_PARAMETERS_BOTH
202 # there's no good way to know 177 # there's no good way to know
203 # if the options values are the hard-coded ones or if they have been passed 178 # if the options values are the hard-coded ones or if they have been passed
204 # on the command line. 179 # on the command line.
205 180
206 # FIXME: must be refactored + code can be factorised with backend 181 # FIXME: must be refactored + code can be factorised with backend
207 config_parser = ConfigParser.SafeConfigParser() 182 config_parser = configparser.SafeConfigParser()
208 config_parser.read(C.CONFIG_FILES) 183 config_parser.read(C.CONFIG_FILES)
209 self.handleDeprecated(config_parser) 184 self.handleDeprecated(config_parser)
210 for param in self.optParameters + OPT_PARAMETERS_CFG: 185 for param in self.optParameters + OPT_PARAMETERS_CFG:
211 name = param[0] 186 name = param[0]
212 try: 187 try:
213 value = config.getConfig(config_parser, CONFIG_SECTION, name, Exception) 188 value = config.getConfig(config_parser, CONFIG_SECTION, name, Exception)
214 if isinstance(value, unicode): 189 # if isinstance(value, str):
215 value = value.encode("utf-8") 190 # value = value.encode("utf-8")
216 try: 191 try:
217 param[2] = param[4](value) 192 param[2] = param[4](value)
218 except IndexError: # the coerce method is optional 193 except IndexError: # the coerce method is optional
219 param[2] = value 194 param[2] = value
220 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): 195 except (configparser.NoSectionError, configparser.NoOptionError):
221 pass 196 pass
222 usage.Options.__init__(self) 197 usage.Options.__init__(self)
223 for opt_data in OPT_PARAMETERS_CFG: 198 for opt_data in OPT_PARAMETERS_CFG:
224 self[opt_data[0]] = opt_data[2] 199 self[opt_data[0]] = opt_data[2]
225 200
230 """ 205 """
231 replacements = (("ssl_certificate", "tls_certificate"),) 206 replacements = (("ssl_certificate", "tls_certificate"),)
232 for old, new in replacements: 207 for old, new in replacements:
233 try: 208 try:
234 value = config.getConfig(config_parser, CONFIG_SECTION, old, Exception) 209 value = config.getConfig(config_parser, CONFIG_SECTION, old, Exception)
235 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): 210 except (configparser.NoSectionError, configparser.NoOptionError):
236 pass 211 pass
237 else: 212 else:
238 print(u"\n/!\\ Use of {old} is deprecated, please use {new} instead\n" 213 print(("\n/!\\ Use of {old} is deprecated, please use {new} instead\n"
239 .format(old=old, new=new)) 214 .format(old=old, new=new)))
240 config_parser.set(CONFIG_SECTION, new, value) 215 config_parser.set(CONFIG_SECTION, new, value)
241 216
242 217
218 @implementer(IServiceMaker, IPlugin)
243 class LiberviaMaker(object): 219 class LiberviaMaker(object):
244 implements(IServiceMaker, IPlugin)
245 220
246 tapname = C.APP_NAME_FILE 221 tapname = C.APP_NAME_FILE
247 description = _(u"The web frontend of Salut à Toi") 222 description = _("The web frontend of Salut à Toi")
248 options = Options 223 options = Options
249 224
250 def makeService(self, options): 225 def makeService(self, options):
251 from twisted.internet import gireactor 226 from twisted.internet import gireactor
252 gireactor.install() 227 gireactor.install()
257 try: 232 try:
258 coerce_cb = opt[4] 233 coerce_cb = opt[4]
259 except IndexError: 234 except IndexError:
260 continue 235 continue
261 if coerce_cb == coerceUnicode: 236 if coerce_cb == coerceUnicode:
262 options[opt[0]] = options[opt[0]].decode("utf-8") 237 if not isinstance(options[opt[0]], str):
238 print(f"FIXME: {opt[0]} is not unicode")
239 options[opt[0]] = options[opt[0]].decode("utf-8")
263 initialise(options.parent) 240 initialise(options.parent)
264 from libervia.server import server 241 from libervia.server import server
265 242
266 return server.Libervia(options) 243 return server.Libervia(options)
267 244