1
2
3 __doc__ = """GNUmed web user interface server launcher.
4 """
5
6 __version__ = "$Revision: 0.1 $"
7 __author__ = "S. Hilbert <Sebastian.Hilbert@gmx.net>"
8 __license__ = "GPL (details at http://www.gnu.org)"
9
10
11 import re, sys, time, os, cPickle, zlib, locale, os.path, datetime as pyDT, webbrowser, shutil, logging, urllib2
12
13
14 from jsonserver import SimpleForkingJSONRPCServer
15
16
17 from Gnumed.pycommon import gmI18N, gmTools, gmDateTime, gmHooks
18 from Gnumed.pycommon import gmLoginInfo, gmBackendListener, gmTools, gmCfg2, gmI18N, gmDispatcher, gmBusinessDBObject
19 from Gnumed.pycommon.gmBusinessDBObject import jsonclasshintify
20 from Gnumed.pycommon import gmPG2
21 from Gnumed.business import gmDocuments
22
23
24
25
26
27
28 _cfg = gmCfg2.gmCfgData()
29 _provider = None
30 _scripting_listener = None
31
32 _log = logging.getLogger('gm.main')
33 _log.info(__version__)
34 _log.info('web GUI framework')
35
36
37
38
39 -def connect_to_database(login_info=None, max_attempts=3, expected_version=None, require_version=True):
40 """Display the login dialog and try to log into the backend.
41
42 - up to max_attempts times
43 - returns True/False
44 """
45 from Gnumed.pycommon import gmPG2
46
47 expected_hash = gmPG2.known_schema_hashes[expected_version]
48 client_version = _cfg.get(option = u'client_version')
49 global current_db_name
50 current_db_name = u'gnumed_%s' % expected_version
51
52 attempt = 0
53
54 while attempt < max_attempts:
55
56 _log.debug('login attempt %s of %s', (attempt+1), max_attempts)
57
58 connected = False
59
60 login = login_info
61 if login is None:
62 _log.info("did not provide a login information")
63
64
65 dsn = gmPG2.make_psycopg2_dsn (
66 database = login.database,
67 host = login.host,
68 port = login.port,
69 user = login.user,
70 password = login.password
71 )
72 try:
73
74 conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
75 connected = True
76
77 except gmPG2.cAuthenticationError, e:
78 attempt += 1
79 _log.error(u"login attempt failed: %s", e)
80 if attempt < max_attempts:
81 if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)):
82 msg = _(
83 'Unable to connect to database:\n\n'
84 '%s\n\n'
85 "Are you sure you have got a local database installed ?\n"
86 '\n'
87 "Please retry with proper credentials or cancel.\n"
88 '\n'
89 'You may also need to check the PostgreSQL client\n'
90 'authentication configuration in pg_hba.conf. For\n'
91 'details see:\n'
92 '\n'
93 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
94 )
95 else:
96 msg = _(
97 "Unable to connect to database:\n\n"
98 "%s\n\n"
99 "Please retry with proper credentials or cancel.\n"
100 "\n"
101 'You may also need to check the PostgreSQL client\n'
102 'authentication configuration in pg_hba.conf. For\n'
103 'details see:\n'
104 '\n'
105 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
106 )
107 msg = msg % e
108 msg = re.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
109 gmGuiHelpers.gm_show_error (
110 msg,
111 _('Connecting to backend')
112 )
113 del e
114 continue
115
116 except gmPG2.dbapi.OperationalError, e:
117 _log.error(u"login attempt failed: %s", e)
118 msg = _(
119 "Unable to connect to database:\n\n"
120 "%s\n\n"
121 "Please retry another backend / user / password combination !\n"
122 ) % gmPG2.extract_msg_from_pg_exception(e)
123 msg = re.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
124 gmGuiHelpers.gm_show_error (
125 msg,
126 _('Connecting to backend')
127 )
128 del e
129 continue
130
131
132 gmPG2.set_default_login(login = login)
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 listener = gmBackendListener.gmBackendListener(conn = conn)
177 break
178
179
180
181 return connected
182
183
184
185
187 """Get server profiles from the configuration files.
188
189 1) from system-wide file
190 2) from user file
191
192 Profiles in the user file which have the same name
193 as a profile in the system file will override the
194 system file.
195 """
196
197 src_order = [
198 (u'explicit', u'extend'),
199 (u'system', u'extend'),
200 (u'user', u'extend'),
201 (u'workbase', u'extend')
202 ]
203
204 profile_names = gmTools.coalesce (
205 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order),
206 []
207 )
208
209
210 src_order = [
211 (u'explicit', u'return'),
212 (u'workbase', u'return'),
213 (u'user', u'return'),
214 (u'system', u'return')
215 ]
216
217 profiles = {}
218
219 for profile_name in profile_names:
220
221
222 profile = cBackendProfile()
223 profile_section = 'profile %s' % profile_name
224
225 profile.name = profile_name
226 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip()
227 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432)
228 try:
229 profile.port = int(port)
230 if profile.port < 1024:
231 raise ValueError('refusing to use priviledged port (< 1024)')
232 except ValueError:
233 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
234 continue
235 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip()
236 if profile.database == u'':
237 _log.warning('database name not specified, skipping profile [%s]', profile_name)
238 continue
239 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8')
240 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order))
241 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order)
242
243 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host)
244 profiles[label] = profile
245
246
247
248 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
249 profiles2remove = []
250 for label in profiles:
251 if profiles[label].database != current_db_name:
252 profiles2remove.append(label)
253 for label in profiles2remove:
254 del profiles[label]
255
256 if len(profiles) == 0:
257 host = u'salaam.homeunix.com'
258 label = u'public GNUmed database (%s@%s)' % (current_db_name, host)
259 profiles[label] = cBackendProfile()
260 profiles[label].name = label
261 profiles[label].host = host
262 profiles[label].port = 5432
263 profiles[label].database = current_db_name
264 profiles[label].encoding = u'UTF8'
265 profiles[label].public_db = True
266 profiles[label].helpdesk = u'http://wiki.gnumed.de'
267
268 return profiles
269
270
271 -def GetLoginInfo(username=None, password=None, backend=None ):
272
273
274
275
276
277 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
278 from Gnumed.pycommon import gmLoginInfo
279
280
281
282
283 __backend_profiles = __get_backend_profiles()
284 profile = __backend_profiles[backend.encode('utf8').strip()]
285
286 _log.debug(u'backend profile "%s" selected', profile.name)
287 _log.debug(u' details: <%s> on %s@%s:%s (%s, %s)',
288 username,
289 profile.database,
290 profile.host,
291 profile.port,
292 profile.encoding,
293 gmTools.bool2subst(profile.public_db, u'public', u'private')
294 )
295
296 login = gmLoginInfo.LoginInfo (
297 user = username,
298 password = password,
299 host = profile.host,
300 database = profile.database,
301 port = profile.port
302 )
303
304
305 return login
306
307
309 try:
310 kwargs['originated_in_database']
311 print '==> got notification from database "%s":' % kwargs['signal']
312 except KeyError:
313 print '==> received signal from client: "%s"' % kwargs['signal']
314
315 del kwargs['signal']
316 for key in kwargs.keys():
317 print ' [%s]: %s' % (key, kwargs[key])
318
319
322
323
324
325
326 PYJSDIR = sys._getframe().f_code.co_filename
327 PYJSDIR = os.path.split(os.path.dirname(PYJSDIR))[0]
328 PYJSDIR = os.path.join(PYJSDIR, 'pyjamas')
329
330 DEFAULT_BACKEND = "GNUmed database on this machine (Linux/Mac) (gnumed_v15@)"
331
333 '''An application instance containing any number of streams. Except for constructor all methods are generators.'''
334 count = 0
344
345 - def echo(self, text):
353
354 - def login(self, username=None, password=None, backend=None):
369
372
376
379
387
388
389
390
391
392
394
395 if _cfg.get(option = 'debug'):
396 gmDispatcher.connect(receiver = _signal_debugging_monitor)
397 _log.debug('gmDispatcher signal monitor activated')
398
399 server = HTTPServer()
400 server.serve_forever()
401