/web/nwrsc/controllers/dbserve.py

https://github.com/adrianpike/wwscc
Python | 134 lines | 106 code | 26 blank | 2 comment | 17 complexity | bb4a7f1ab6a552081732de88cac461ba MD5 | raw file
  1. import logging
  2. import traceback
  3. import sys
  4. import glob
  5. import os
  6. import shutil
  7. from pylons import config, request, response
  8. from pylons.controllers.util import abort
  9. from sqlalchemy import create_engine
  10. from sqlalchemy.pool import NullPool
  11. from nwrsc.lib.base import BaseController
  12. from nwrsc.lib.codec import Codec, DataInput
  13. from nwrsc.controllers.dblib import UpdateClassResults
  14. from nwrsc.model import *
  15. log = logging.getLogger(__name__)
  16. def corename(file):
  17. base = os.path.basename(file)
  18. return os.path.splitext(base)[0]+"\n"
  19. class DbserveController(BaseController):
  20. def __before__(self):
  21. # Perform authentication (TBD: real authentication)
  22. action = self.routingargs.get('action', '')
  23. if action in ['available']:
  24. return
  25. password = request.environ.get('HTTP_X_SCOREKEEPER', '')
  26. if password != self.settings.password:
  27. log.warning("Incorrect password used for %s" % (self.database))
  28. abort(401)
  29. def download(self):
  30. if self.settings.locked:
  31. log.warning("Download request for %s, but it is locked" % (self.database))
  32. abort(404)
  33. self.settings.locked = True
  34. self.settings.save(self.session)
  35. self.session.commit()
  36. return self.copy()
  37. def copy(self):
  38. response.headers['Content-type'] = 'application/octet-stream'
  39. fp = open(self.databasePath(self.database), 'rb')
  40. data = fp.read()
  41. log.info("Read in database file of %d bytes", len(data))
  42. fp.close()
  43. return data
  44. def upload(self):
  45. dbpost = request.POST['db']
  46. out = open(self.databasePath(self.database), 'wb')
  47. shutil.copyfileobj(dbpost.file, out)
  48. dbpost.file.close()
  49. out.close()
  50. engine = create_engine('sqlite:///%s' % self.databasePath(self.database), poolclass=NullPool)
  51. self.session.bind = engine
  52. metadata.bind = engine
  53. self.settings = Settings()
  54. self.settings.load(self.session)
  55. self.settings.locked = False
  56. self.settings.save(self.session)
  57. self.session.commit()
  58. return ""
  59. def available(self):
  60. response.headers['Content-type'] = 'text/plain'
  61. data = ''
  62. for file in glob.glob('%s/*.db' % (config['seriesdir'])):
  63. try:
  64. engine = create_engine('sqlite:///%s' % file, poolclass=NullPool)
  65. metadata.bind = engine
  66. self.session.bind = engine
  67. self.settings = Settings()
  68. self.settings.load(self.session)
  69. name = os.path.splitext(os.path.basename(file))[0]
  70. data += "%s %s\n" % (name, self.settings.locked and "1" or "0")
  71. self.session.close()
  72. except Exception, e:
  73. log.error("available error with %s (%s) " % (file,e))
  74. return data
  75. def sqlmap(self):
  76. try:
  77. stream = DataInput(request.environ['wsgi.input'].read(int(request.environ['CONTENT_LENGTH'])))
  78. ret = ""
  79. while stream.dataAvailable() > 0:
  80. (type, key, values) = Codec.decodeRequest(stream)
  81. log.debug("sqlmap request %s" % (key))
  82. if type == Codec.SELECT:
  83. ret = Codec.encodeResults(self.session.sqlmap(key, values))
  84. elif type == Codec.UPDATE:
  85. ret = Codec.encodeLastId(self.session.sqlmap(key, values).lastrowid)
  86. elif type == Codec.FUNCTION:
  87. if hasattr(self, key):
  88. ret = getattr(self, key)(*values)
  89. else:
  90. raise Exception("Unknown FUNCTION call %s" % (key))
  91. else:
  92. raise Exception("Unknown call type %s" % (type))
  93. self.session.commit()
  94. return ret
  95. except Exception, e:
  96. self.session.rollback()
  97. msg = Exception.__str__(e)
  98. filename, lineno, name, line = traceback.extract_tb(sys.exc_info()[2])[-1]
  99. return Codec.encodeError(filename, lineno, msg)
  100. # FUNCTION calls
  101. def GetCarAttributes(self, attr):
  102. rs = self.session.connection().execute(
  103. "select distinct %s from cars where LOWER(%s)!=%s and UPPER(%s)!=%s order by %s collate nocase" \
  104. % tuple([attr]*6))
  105. return Codec.encodeResults(rs)
  106. def UpdateClass(self, eventid, classcode, carid):
  107. UpdateClassResults(self.session, eventid, classcode, carid)
  108. return Codec.encodeLastId(-1)