/lib/galaxy/webapps/demo_sequencer/controllers/common.py

https://bitbucket.org/cistrome/cistrome-harvard/ · Python · 227 lines · 179 code · 2 blank · 46 comment · 46 complexity · d87a546a2b37d1088848e68bc5ce5c0a MD5 · raw file

  1. from galaxy.web.base.controller import *
  2. from galaxy.web.framework.helpers import time_ago
  3. from galaxy import util
  4. import time, socket, urllib, urllib2, base64, copy
  5. from galaxy.util.json import *
  6. from urllib import quote_plus, unquote_plus
  7. import logging
  8. log = logging.getLogger( __name__ )
  9. class CommonController( BaseUIController ):
  10. @web.expose
  11. def index( self, trans, **kwd ):
  12. redirect_action = util.restore_text( kwd.get( 'redirect_action', '' ) )
  13. titles = util.restore_text( kwd.get( 'titles', '' ) )
  14. titles = util.listify( titles )
  15. JobId = util.restore_text( kwd.get( 'JobId', '' ) )
  16. sample_id = util.restore_text( kwd.get( 'sample_id', '' ) )
  17. message = util.restore_text( kwd.get( 'message', '' ) )
  18. status = kwd.get( 'status', 'done' )
  19. redirect_delay = trans.app.sequencer_actions_registry.redirect_delay
  20. sequencer_redirects = copy.deepcopy( trans.app.sequencer_actions_registry.sequencer_redirects )
  21. sequencer_requests = copy.deepcopy( trans.app.sequencer_actions_registry.sequencer_requests )
  22. requests = []
  23. if redirect_action == 'stop':
  24. # Handle any additional requests
  25. for request_tup in sequencer_requests:
  26. url, http_method, request_params, response_type = self.parse_request_tup( request_tup, **kwd )
  27. response = self.handle_request( trans, url, http_method, **request_params )
  28. # Handle response, currently only handles json
  29. if response_type == 'json':
  30. response = from_json_string( response )
  31. # Handle response that is an error, for example:
  32. # { "Success":false, "Message":"some error string" }
  33. if 'Success' in response and response[ 'Success' ] == 'false':
  34. message = response[ 'Message' ]
  35. return self.handle_failure( trans, url, message )
  36. if 'JobId' in response:
  37. JobId = str( response[ 'JobId' ] )
  38. kwd[ 'JobId' ] = JobId
  39. # Handle the final redirect, if any ( should only be 0 or 1 ).
  40. for request_tup in trans.app.sequencer_actions_registry.final_redirect:
  41. url, http_method, request_params, response_type = self.parse_request_tup( request_tup, **kwd )
  42. return trans.fill_template( 'webapps/demo_sequencer/redirect.mako', redirect_url=url )
  43. # Exit if we have no redirection
  44. redirect_action = 'exit'
  45. elif not redirect_action:
  46. # Specially handle the initial request to the demo sequencer by starting with the first defined redirect.
  47. redirect_action, action_dict = sequencer_redirects.items()[0]
  48. titles = [ action_dict[ 'title' ] ]
  49. if 'requests' in action_dict:
  50. requests = action_dict[ 'requests' ]
  51. else:
  52. for index, key in enumerate( sequencer_redirects.iterkeys() ):
  53. if redirect_action == key:
  54. try:
  55. # Move to the next action, if there is one.
  56. redirect_action = sequencer_redirects.keys()[ index + 1 ]
  57. action_dict = sequencer_redirects[ redirect_action ]
  58. titles.append( action_dict[ 'title' ] )
  59. except:
  60. # If we're done redirecting, stop.
  61. redirect_action = 'stop'
  62. break
  63. if not trans.app.sequencer_actions_registry.authenticated:
  64. # Support various types of authentication
  65. if trans.app.sequencer_actions_registry.browser_login:
  66. # We'll just build the URL here since authentication will be handled in the browser
  67. url = trans.app.sequencer_actions_registry.browser_login[ 'url' ]
  68. params = trans.app.sequencer_actions_registry.browser_login[ 'params' ]
  69. trans.app.sequencer_actions_registry.browser_login = '%s?%s' %( url, urllib.urlencode( params ) )
  70. if not trans.app.sequencer_actions_registry.final_redirect:
  71. # If we don't have a final_redirect tag, but we want our browser to authenticate,
  72. # do it ow. If we have a final_redirect tag, browser authentication will happen there.
  73. url = web.url_for( controller='common', action='index', **kwd )
  74. return trans.fill_template( 'webapps/demo_sequencer/redirect.mako', redirect_url=url )
  75. if trans.app.sequencer_actions_registry.basic_http_authentication:
  76. # Example tag:
  77. # <basic_http_authentication user="administrator" password="galaxy" url="http://127.0.0.1" realm="" />
  78. user, password, url, realm = trans.app.sequencer_actions_registry.basic_http_authentication
  79. # Create a password manager
  80. password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
  81. # Add the username, password and realm.
  82. if not realm:
  83. realm = None
  84. password_mgr.add_password( realm, url, user, password )
  85. handler = urllib2.HTTPBasicAuthHandler( password_mgr )
  86. # Create "opener" (OpenerDirector instance)
  87. opener = urllib2.build_opener( handler )
  88. # Install the opener, now all calls to urllib2.urlopen use our opener.
  89. urllib2.install_opener( opener )
  90. trans.app.sequencer_actions_registry.authenticated = True
  91. if trans.app.sequencer_actions_registry.http_headers_authorization:
  92. # Example tag:
  93. # <http_headers_authorization credentials="administrator:galaxy" url="http://127.0.0.1" />
  94. url, credentials = trans.app.sequencer_actions_registry.http_headers_authorization
  95. req = urllib2.Request( url )
  96. req.add_header( 'Authorization', 'Basic %s' % base64.b64encode( credentials ) )
  97. trans.app.sequencer_actions_registry.authenticated = True
  98. if trans.app.sequencer_actions_registry.http_cookie_processor_authentication:
  99. # Example tag:
  100. # <http_cookie_processor_authentication url="http://127.0.0.1/login">
  101. # <param name="user" value="administrator"/>
  102. # <param name="password" value="galaxy"/>
  103. # </http_cookie_processor_authentication>
  104. url = trans.app.sequencer_actions_registry.http_cookie_processor_authentication[ 'url' ]
  105. params = trans.app.sequencer_actions_registry.http_cookie_processor_authentication[ 'params' ]
  106. # Build opener with HTTPCookieProcessor
  107. opener = urllib2.build_opener( urllib2.HTTPCookieProcessor() )
  108. urllib2.install_opener( opener )
  109. # Perform login with params
  110. page = opener.open( url, urllib.urlencode( params ) )
  111. response = page.read()
  112. page.close()
  113. # Any additional requests should automatically pass back any
  114. # cookies received during login, thanks to the HTTPCookieProcessor
  115. trans.app.sequencer_actions_registry.authenticated = True
  116. # Handle requests, if there are any
  117. for request_tup in requests:
  118. url, http_method, request_params, response_type = self.parse_request_tup( request_tup, **kwd )
  119. response = self.handle_request( trans, url, http_method, **request_params )
  120. # Handle response, currently only handles json
  121. if response_type == 'json':
  122. response = from_json_string( response )
  123. # Handle response that is an error, for example:
  124. # { "Success":false, "Message":"some error string" }
  125. if 'Success' in response and response[ 'Success' ] == 'false':
  126. message = response[ 'Message' ]
  127. return self.handle_failure( trans, url, message )
  128. if 'JobId' in response:
  129. JobId = str( response[ 'JobId' ] )
  130. kwd[ 'JobId' ] = JobId
  131. titles = ','.join( titles )
  132. return trans.fill_template( "webapps/demo_sequencer/index.mako",
  133. redirect_action=redirect_action,
  134. redirect_delay=redirect_delay,
  135. titles=titles,
  136. sample_id=sample_id,
  137. JobId=JobId,
  138. message=message,
  139. status=status )
  140. def parse_request_tup( self, request_tup, **kwd ):
  141. redirect_action = util.restore_text( kwd.get( 'redirect_action', '' ) )
  142. titles = util.restore_text( kwd.get( 'titles', '' ) )
  143. JobId = util.restore_text( kwd.get( 'JobId', '' ) )
  144. sample_id = util.restore_text( kwd.get( 'sample_id', '' ) )
  145. message = util.restore_text( kwd.get( 'message', '' ) )
  146. status = kwd.get( 'status', 'done' )
  147. url, http_method, request_params, response_type = request_tup
  148. url = unquote_plus( url )
  149. # Handle URLs in which we replace param values, which will look something like:
  150. # http://127.0.0.1/getinfo/{id}.
  151. replace_with_param = url.find( '{' ) > 0
  152. if replace_with_param:
  153. # Handle the special-case {JobId} param.
  154. if url.find( '{JobId}' ) > 0:
  155. if JobId:
  156. url = url.replace( '{JobId}', str( JobId ) )
  157. for key, value in kwd.items():
  158. # Don't attempt to replace if there is nothing with which to do it
  159. # or if the value itself should be replaced with something.
  160. if value and not value.startswith( '{' ):
  161. replace_str = '{%s}' % key
  162. if url.find( replace_str ) > 0:
  163. url = url.replace( replace_str, value )
  164. # Handle request parameters in which we replace param values.
  165. for key, val in request_params.items():
  166. if val and val.startswith( '{' ):
  167. replace_key = val.lstrip( '{' ).rstrip( '}' )
  168. if replace_key in kwd:
  169. request_params[ key ] = kwd[ replace_key ]
  170. return url, http_method, request_params, response_type
  171. def handle_request( self, trans, url, http_method=None, **kwd ):
  172. if 'Name' in kwd and not kwd[ 'Name' ]:
  173. # Hack: specially handle parameters named "Name" if no param_value is given
  174. # by providing a date / time string - guarantees uniqueness, if required.
  175. kwd[ 'Name' ] = time.strftime( "%a, %d %b %Y %H:%M:%S", time.gmtime() )
  176. if 'Comments' in kwd and not kwd[ 'Comments' ]:
  177. # Hack: specially handle parameters named "Comments" if no param_value is given
  178. # by providing a date / time string.
  179. kwd[ 'Comments' ] = time.strftime( "%a, %d %b %Y %H:%M:%S", time.gmtime() )
  180. socket.setdefaulttimeout( 600 )
  181. # The following calls to urllib2.urlopen() will use the above default timeout.
  182. try:
  183. if not http_method or http_method == 'get':
  184. page = urllib2.urlopen( url )
  185. response = page.read()
  186. page.close()
  187. return response
  188. elif http_method == 'post':
  189. page = urllib2.urlopen( url, urllib.urlencode( kwd ) )
  190. response = page.read()
  191. page.close()
  192. return response
  193. elif http_method == 'put':
  194. url += '/' + str( kwd.pop( 'id' ) ) + '?key=' + kwd.pop( 'key' )
  195. output = self.put( url, **kwd )
  196. except Exception, e:
  197. raise
  198. message = 'Problem sending request to the web application: %s. URL: %s. kwd: %s. Http method: %s' % \
  199. ( str( e ), str( url ), str( kwd ), str( http_method ) )
  200. return self.handle_failure( trans, url, message )
  201. def handle_failure( self, trans, url, message ):
  202. message = '%s, URL: %s' % ( message, url )
  203. params = dict( message = message,
  204. status = 'error',
  205. redirect_action = 'exit',
  206. titles = 'Error' )
  207. return trans.response.send_redirect( web.url_for( controller='common',
  208. action='index',
  209. **params ) )
  210. def put( self, url, **kwd ):
  211. opener = urllib2.build_opener( urllib2.HTTPHandler )
  212. request = urllib2.Request( url, data=to_json_string( kwd ) )
  213. request.add_header( 'Content-Type', 'application/json' )
  214. request.get_method = lambda: 'PUT'
  215. url = opener.open( request )
  216. output = url.read()
  217. return from_json_string( output )
  218. @web.expose
  219. def login( self, trans, **kwd ):
  220. trans.app.sequencer_actions_registry.authenticated = True
  221. return trans.fill_template( "webapps/demo_sequencer/login.mako" )
  222. @web.expose
  223. def empty_page( self, trans, **kwd ):
  224. # Hack to not display responses in the browser - src for a hidden iframe.
  225. return trans.fill_template( "webapps/demo_sequencer/empty.mako" )