PageRenderTime 77ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/applications/admin/controllers/appadmin.py

https://github.com/goldenboy/skiheilw2p
Python | 408 lines | 351 code | 40 blank | 17 comment | 37 complexity | ff0ac871b411712bf0148ca2337b97a0 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. # ##########################################################
  3. # ## make sure administrator is on localhost
  4. # ###########################################################
  5. import os
  6. import socket
  7. import datetime
  8. import copy
  9. import gluon.contenttype
  10. import gluon.fileutils
  11. # ## critical --- make a copy of the environment
  12. global_env = copy.copy(globals())
  13. global_env['datetime'] = datetime
  14. http_host = request.env.http_host.split(':')[0]
  15. remote_addr = request.env.remote_addr
  16. try:
  17. hosts = (http_host, socket.gethostname(),
  18. socket.gethostbyname(http_host),
  19. '::1','127.0.0.1','::ffff:127.0.0.1')
  20. except:
  21. hosts = (http_host, )
  22. if request.env.http_x_forwarded_for or request.env.wsgi_url_scheme\
  23. in ['https', 'HTTPS']:
  24. session.secure()
  25. elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
  26. raise HTTP(200, T('appadmin is disabled because insecure channel'))
  27. if (request.application=='admin' and not session.authorized) or \
  28. (request.application!='admin' and not gluon.fileutils.check_credentials(request)):
  29. redirect(URL('admin', 'default', 'index'))
  30. ignore_rw = True
  31. response.view = 'appadmin.html'
  32. response.menu = [[T('design'), False, URL('admin', 'default', 'design',
  33. args=[request.application])], [T('db'), False,
  34. URL('index')], [T('state'), False,
  35. URL('state')], [T('cache'), False,
  36. URL('ccache')]]
  37. # ##########################################################
  38. # ## auxiliary functions
  39. # ###########################################################
  40. def get_databases(request):
  41. dbs = {}
  42. for (key, value) in global_env.items():
  43. cond = False
  44. try:
  45. cond = isinstance(value, GQLDB)
  46. except:
  47. cond = isinstance(value, SQLDB)
  48. if cond:
  49. dbs[key] = value
  50. return dbs
  51. databases = get_databases(None)
  52. def eval_in_global_env(text):
  53. exec ('_ret=%s' % text, {}, global_env)
  54. return global_env['_ret']
  55. def get_database(request):
  56. if request.args and request.args[0] in databases:
  57. return eval_in_global_env(request.args[0])
  58. else:
  59. session.flash = T('invalid request')
  60. redirect(URL('index'))
  61. def get_table(request):
  62. db = get_database(request)
  63. if len(request.args) > 1 and request.args[1] in db.tables:
  64. return (db, request.args[1])
  65. else:
  66. session.flash = T('invalid request')
  67. redirect(URL('index'))
  68. def get_query(request):
  69. try:
  70. return eval_in_global_env(request.vars.query)
  71. except Exception:
  72. return None
  73. def query_by_table_type(tablename,db,request=request):
  74. keyed = hasattr(db[tablename],'_primarykey')
  75. if keyed:
  76. firstkey = db[tablename][db[tablename]._primarykey[0]]
  77. cond = '>0'
  78. if firstkey.type in ['string', 'text']:
  79. cond = '!=""'
  80. qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond)
  81. else:
  82. qry = '%s.%s.id>0' % tuple(request.args[:2])
  83. return qry
  84. # ##########################################################
  85. # ## list all databases and tables
  86. # ###########################################################
  87. def index():
  88. return dict(databases=databases)
  89. # ##########################################################
  90. # ## insert a new record
  91. # ###########################################################
  92. def insert():
  93. (db, table) = get_table(request)
  94. form = SQLFORM(db[table], ignore_rw=ignore_rw)
  95. if form.accepts(request.vars, session):
  96. response.flash = T('new record inserted')
  97. return dict(form=form,table=db[table])
  98. # ##########################################################
  99. # ## list all records in table and insert new record
  100. # ###########################################################
  101. def download():
  102. import os
  103. db = get_database(request)
  104. return response.download(request,db)
  105. def csv():
  106. import gluon.contenttype
  107. response.headers['Content-Type'] = \
  108. gluon.contenttype.contenttype('.csv')
  109. db = get_database(request)
  110. query = get_query(request)
  111. if not query:
  112. return None
  113. response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
  114. % tuple(request.vars.query.split('.')[:2])
  115. return str(db(query).select())
  116. def import_csv(table, file):
  117. table.import_from_csv_file(file)
  118. def select():
  119. import re
  120. db = get_database(request)
  121. dbname = request.args[0]
  122. regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
  123. if len(request.args)>1 and hasattr(db[request.args[1]],'_primarykey'):
  124. regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
  125. if request.vars.query:
  126. match = regex.match(request.vars.query)
  127. if match:
  128. request.vars.query = '%s.%s.%s==%s' % (request.args[0],
  129. match.group('table'), match.group('field'),
  130. match.group('value'))
  131. else:
  132. request.vars.query = session.last_query
  133. query = get_query(request)
  134. if request.vars.start:
  135. start = int(request.vars.start)
  136. else:
  137. start = 0
  138. nrows = 0
  139. stop = start + 100
  140. table = None
  141. rows = []
  142. orderby = request.vars.orderby
  143. if orderby:
  144. orderby = dbname + '.' + orderby
  145. if orderby == session.last_orderby:
  146. if orderby[0] == '~':
  147. orderby = orderby[1:]
  148. else:
  149. orderby = '~' + orderby
  150. session.last_orderby = orderby
  151. session.last_query = request.vars.query
  152. form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
  153. _name='query', _value=request.vars.query or '',
  154. requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'),
  155. INPUT(_name='update_check', _type='checkbox',
  156. value=False), INPUT(_style='width:400px',
  157. _name='update_fields', _value=request.vars.update_fields
  158. or '')), TR(T('Delete:'), INPUT(_name='delete_check',
  159. _class='delete', _type='checkbox', value=False), ''),
  160. TR('', '', INPUT(_type='submit', _value='submit'))),
  161. _action=URL(r=request,args=request.args))
  162. if request.vars.csvfile != None:
  163. try:
  164. import_csv(db[request.vars.table],
  165. request.vars.csvfile.file)
  166. response.flash = T('data uploaded')
  167. except Exception, e:
  168. response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
  169. if form.accepts(request.vars, formname=None):
  170. # regex = re.compile(request.args[0] + '\.(?P<table>\w+)\.id\>0')
  171. regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
  172. match = regex.match(form.vars.query.strip())
  173. if match:
  174. table = match.group('table')
  175. try:
  176. nrows = db(query).count()
  177. if form.vars.update_check and form.vars.update_fields:
  178. db(query).update(**eval_in_global_env('dict(%s)'
  179. % form.vars.update_fields))
  180. response.flash = T('%s rows updated', nrows)
  181. elif form.vars.delete_check:
  182. db(query).delete()
  183. response.flash = T('%s rows deleted', nrows)
  184. nrows = db(query).count()
  185. if orderby:
  186. rows = db(query).select(limitby=(start, stop),
  187. orderby=eval_in_global_env(orderby))
  188. else:
  189. rows = db(query).select(limitby=(start, stop))
  190. except Exception, e:
  191. (rows, nrows) = ([], 0)
  192. response.flash = DIV(T('Invalid Query'),PRE(str(e)))
  193. return dict(
  194. form=form,
  195. table=table,
  196. start=start,
  197. stop=stop,
  198. nrows=nrows,
  199. rows=rows,
  200. query=request.vars.query,
  201. )
  202. # ##########################################################
  203. # ## edit delete one record
  204. # ###########################################################
  205. def update():
  206. (db, table) = get_table(request)
  207. keyed = hasattr(db[table],'_primarykey')
  208. record = None
  209. if keyed:
  210. key = [f for f in request.vars if f in db[table]._primarykey]
  211. if key:
  212. record = db(db[table][key[0]] == request.vars[key[0]]).select().first()
  213. else:
  214. record = db(db[table].id == request.args(2)).select().first()
  215. if not record:
  216. qry = query_by_table_type(table, db)
  217. session.flash = T('record does not exist')
  218. redirect(URL('select', args=request.args[:1],
  219. vars=dict(query=qry)))
  220. if keyed:
  221. for k in db[table]._primarykey:
  222. db[table][k].writable=False
  223. form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'),
  224. ignore_rw=ignore_rw and not keyed,
  225. linkto=URL('select',
  226. args=request.args[:1]), upload=URL(r=request,
  227. f='download', args=request.args[:1]))
  228. if form.accepts(request.vars, session):
  229. session.flash = T('done!')
  230. qry = query_by_table_type(table, db)
  231. redirect(URL('select', args=request.args[:1],
  232. vars=dict(query=qry)))
  233. return dict(form=form,table=db[table])
  234. # ##########################################################
  235. # ## get global variables
  236. # ###########################################################
  237. def state():
  238. return dict()
  239. def ccache():
  240. form = FORM(
  241. P(TAG.BUTTON("Clear CACHE?", _type="submit", _name="yes", _value="yes")),
  242. P(TAG.BUTTON("Clear RAM", _type="submit", _name="ram", _value="ram")),
  243. P(TAG.BUTTON("Clear DISK", _type="submit", _name="disk", _value="disk")),
  244. )
  245. if form.accepts(request.vars, session):
  246. clear_ram = False
  247. clear_disk = False
  248. session.flash = ""
  249. if request.vars.yes:
  250. clear_ram = clear_disk = True
  251. if request.vars.ram:
  252. clear_ram = True
  253. if request.vars.disk:
  254. clear_disk = True
  255. if clear_ram:
  256. cache.ram.clear()
  257. session.flash += "Ram Cleared "
  258. if clear_disk:
  259. cache.disk.clear()
  260. session.flash += "Disk Cleared"
  261. redirect(URL(r=request))
  262. try:
  263. from guppy import hpy; hp=hpy()
  264. except ImportError:
  265. hp = False
  266. import shelve, os, copy, time, math
  267. from gluon import portalocker
  268. ram = {
  269. 'bytes': 0,
  270. 'objects': 0,
  271. 'hits': 0,
  272. 'misses': 0,
  273. 'ratio': 0,
  274. 'oldest': time.time()
  275. }
  276. disk = copy.copy(ram)
  277. total = copy.copy(ram)
  278. for key, value in cache.ram.storage.items():
  279. if isinstance(value, dict):
  280. ram['hits'] = value['hit_total'] - value['misses']
  281. ram['misses'] = value['misses']
  282. try:
  283. ram['ratio'] = ram['hits'] * 100 / value['hit_total']
  284. except (KeyError, ZeroDivisionError):
  285. ram['ratio'] = 0
  286. else:
  287. if hp:
  288. ram['bytes'] += hp.iso(value[1]).size
  289. ram['objects'] += hp.iso(value[1]).count
  290. if value[0] < ram['oldest']:
  291. ram['oldest'] = value[0]
  292. locker = open(os.path.join(request.folder,
  293. 'cache/cache.lock'), 'a')
  294. portalocker.lock(locker, portalocker.LOCK_EX)
  295. disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve'))
  296. try:
  297. for key, value in disk_storage.items():
  298. if isinstance(value, dict):
  299. disk['hits'] = value['hit_total'] - value['misses']
  300. disk['misses'] = value['misses']
  301. try:
  302. disk['ratio'] = disk['hits'] * 100 / value['hit_total']
  303. except (KeyError, ZeroDivisionError):
  304. disk['ratio'] = 0
  305. else:
  306. if hp:
  307. disk['bytes'] += hp.iso(value[1]).size
  308. disk['objects'] += hp.iso(value[1]).count
  309. if value[0] < disk['oldest']:
  310. disk['oldest'] = value[0]
  311. finally:
  312. portalocker.unlock(locker)
  313. locker.close()
  314. disk_storage.close()
  315. total['bytes'] = ram['bytes'] + disk['bytes']
  316. total['objects'] = ram['objects'] + disk['objects']
  317. total['hits'] = ram['hits'] + disk['hits']
  318. total['misses'] = ram['misses'] + disk['misses']
  319. try:
  320. total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses'])
  321. except (KeyError, ZeroDivisionError):
  322. total['ratio'] = 0
  323. if disk['oldest'] < ram['oldest']:
  324. total['oldest'] = disk['oldest']
  325. else:
  326. total['oldest'] = ram['oldest']
  327. def GetInHMS(seconds):
  328. hours = math.floor(seconds / 3600)
  329. seconds -= hours * 3600
  330. minutes = math.floor(seconds / 60)
  331. seconds -= minutes * 60
  332. seconds = math.floor(seconds)
  333. return (hours, minutes, seconds)
  334. ram['oldest'] = GetInHMS(time.time() - ram['oldest'])
  335. disk['oldest'] = GetInHMS(time.time() - disk['oldest'])
  336. total['oldest'] = GetInHMS(time.time() - total['oldest'])
  337. return dict(form=form, total=total,
  338. ram=ram, disk=disk)