1
2
3 __doc__ = """GNUmed web client launcher.
4 """
5
6
7
8 __version__ = "$Revision: 1 $"
9 __author__ = "S. Hilbert <Sebastian.Hilbert@gmx.net>"
10 __license__ = "GPL (details at http://www.gnu.org)"
11
12 import cherrypy
13
14
15 import sys, time, os, cPickle, zlib, locale, os.path, datetime as pyDT, webbrowser, shutil, logging, urllib2
16
17
18 from Gnumed.pycommon import gmI18N, gmTools, gmDateTime, gmHooks
19 from Gnumed.pycommon import gmLoginInfo, gmPG2, gmBackendListener, gmTools, gmCfg2, gmI18N, gmDispatcher
20
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
46 expected_hash = gmPG2.known_schema_hashes[expected_version]
47 client_version = _cfg.get(option = u'client_version')
48 global current_db_name
49 current_db_name = u'gnumed_%s' % expected_version
50
51 attempt = 0
52
53 while attempt < max_attempts:
54
55 _log.debug('login attempt %s of %s', (attempt+1), max_attempts)
56
57 connected = False
58
59 login = login_info
60 if login is None:
61 _log.info("did not provide a login information")
62
63
64 dsn = gmPG2.make_psycopg2_dsn (
65 database = login.database,
66 host = login.host,
67 port = login.port,
68 user = login.user,
69 password = login.password
70 )
71 try:
72 conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
73 connected = True
74
75 except gmPG2.cAuthenticationError, e:
76 attempt += 1
77 _log.error(u"login attempt failed: %s", e)
78 if attempt < max_attempts:
79 if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)):
80 msg = _(
81 'Unable to connect to database:\n\n'
82 '%s\n\n'
83 "Are you sure you have got a local database installed ?\n"
84 '\n'
85 "Please retry with proper credentials or cancel.\n"
86 '\n'
87 'You may also need to check the PostgreSQL client\n'
88 'authentication configuration in pg_hba.conf. For\n'
89 'details see:\n'
90 '\n'
91 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
92 )
93 else:
94 msg = _(
95 "Unable to connect to database:\n\n"
96 "%s\n\n"
97 "Please retry with proper credentials or cancel.\n"
98 "\n"
99 'You may also need to check the PostgreSQL client\n'
100 'authentication configuration in pg_hba.conf. For\n'
101 'details see:\n'
102 '\n'
103 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
104 )
105 msg = msg % e
106 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
107 gmGuiHelpers.gm_show_error (
108 msg,
109 _('Connecting to backend')
110 )
111 del e
112 continue
113
114 except gmPG2.dbapi.OperationalError, e:
115 _log.error(u"login attempt failed: %s", e)
116 msg = _(
117 "Unable to connect to database:\n\n"
118 "%s\n\n"
119 "Please retry another backend / user / password combination !\n"
120 ) % gmPG2.extract_msg_from_pg_exception(e)
121 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
122 gmGuiHelpers.gm_show_error (
123 msg,
124 _('Connecting to backend')
125 )
126 del e
127 continue
128
129
130 gmPG2.set_default_login(login = login)
131
132
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 listener = gmBackendListener.gmBackendListener(conn = conn)
175 break
176
177
178
179 return connected
180
181
182
183
185 """Get server profiles from the configuration files.
186
187 1) from system-wide file
188 2) from user file
189
190 Profiles in the user file which have the same name
191 as a profile in the system file will override the
192 system file.
193 """
194
195 src_order = [
196 (u'explicit', u'extend'),
197 (u'system', u'extend'),
198 (u'user', u'extend'),
199 (u'workbase', u'extend')
200 ]
201
202 profile_names = gmTools.coalesce (
203 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order),
204 []
205 )
206
207
208 src_order = [
209 (u'explicit', u'return'),
210 (u'workbase', u'return'),
211 (u'user', u'return'),
212 (u'system', u'return')
213 ]
214
215 profiles = {}
216
217 for profile_name in profile_names:
218
219
220 profile = cBackendProfile()
221 profile_section = 'profile %s' % profile_name
222
223 profile.name = profile_name
224 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip()
225 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432)
226 try:
227 profile.port = int(port)
228 if profile.port < 1024:
229 raise ValueError('refusing to use priviledged port (< 1024)')
230 except ValueError:
231 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
232 continue
233 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip()
234 if profile.database == u'':
235 _log.warning('database name not specified, skipping profile [%s]', profile_name)
236 continue
237 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8')
238 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order))
239 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order)
240
241 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host)
242 profiles[label] = profile
243
244
245
246 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
247 profiles2remove = []
248 for label in profiles:
249 if profiles[label].database != current_db_name:
250 profiles2remove.append(label)
251 for label in profiles2remove:
252 del profiles[label]
253
254 if len(profiles) == 0:
255 host = u'salaam.homeunix.com'
256 label = u'public GNUmed database (%s@%s)' % (current_db_name, host)
257 profiles[label] = cBackendProfile()
258 profiles[label].name = label
259 profiles[label].host = host
260 profiles[label].port = 5432
261 profiles[label].database = current_db_name
262 profiles[label].encoding = u'UTF8'
263 profiles[label].public_db = True
264 profiles[label].helpdesk = u'http://wiki.gnumed.de'
265
266 return profiles
267
268
269 -def GetLoginInfo(username=None, password=None, backend=None ):
270
271
272
273
274
275 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
276
277
278
279
280 __backend_profiles = __get_backend_profiles()
281 profile = __backend_profiles[backend.encode('utf8').strip()]
282
283 _log.debug(u'backend profile "%s" selected', profile.name)
284 _log.debug(u' details: <%s> on %s@%s:%s (%s, %s)',
285 username,
286 profile.database,
287 profile.host,
288 profile.port,
289 profile.encoding,
290 gmTools.bool2subst(profile.public_db, u'public', u'private')
291 )
292
293 login = gmLoginInfo.LoginInfo (
294 user = username,
295 password = password,
296 host = profile.host,
297 database = profile.database,
298 port = profile.port
299 )
300
301
302 return login
303
304
306 try:
307 kwargs['originated_in_database']
308 print '==> got notification from database "%s":' % kwargs['signal']
309 except KeyError:
310 print '==> received signal from client: "%s"' % kwargs['signal']
311
312 del kwargs['signal']
313 for key in kwargs.keys():
314 print ' [%s]: %s' % (key, kwargs[key])
315
316
319
320
322
330
331 - def doLogin(self, username=None, password=None, backend=None):
341
342 doLogin.exposed = True
343
344
346
347 return """
348 <form action="doLogin" method="post">
349 <p>Backend</p>
350 <input type="text" name="backend" value="GNUmed database on this machine (Linux/Mac) (gnumed_v14@)"
351 size="15" maxlength="40"/>
352 <p>Username</p>
353 <input type="text" name="username" value=""
354 size="15" maxlength="40"/>
355 <p>Password</p>
356 <input type="password" name="password" value=""
357 size="10" maxlength="40"/>
358 <p><input type="submit" value="Login"/></p>
359 <p><input type="reset" value="Clear"/></p>
360 </form>
361 """
362 index.exposed = True
363
364
365
366
367
369
370 if _cfg.get(option = 'debug'):
371 gmDispatcher.connect(receiver = _signal_debugging_monitor)
372 _log.debug('gmDispatcher signal monitor activated')
373
374 cherrypy.quickstart(gmApp())
375