From 753c29b445e351972d9795ffa0175662665ef2d1 Mon Sep 17 00:00:00 2001 From: John Duddy Date: Fri, 18 Nov 2011 12:41:27 -0800 Subject: [PATCH 1/2] Allow command-line creation of initial database --- create_db.sh | 4 ++++ scripts/create_db.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100755 create_db.sh create mode 100755 scripts/create_db.py diff --git a/create_db.sh b/create_db.sh new file mode 100755 index 00000000000..857dc98feaf --- /dev/null +++ b/create_db.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd `dirname $0` +python ./scripts/create_db.py $@ diff --git a/scripts/create_db.py b/scripts/create_db.py new file mode 100755 index 00000000000..5466eae2349 --- /dev/null +++ b/scripts/create_db.py @@ -0,0 +1,36 @@ +import sys, os.path, logging + +new_path = [ os.path.join( os.getcwd(), "lib" ) ] +new_path.extend( sys.path[1:] ) # remove scripts/ from the path +sys.path = new_path + +from galaxy import eggs +from galaxy.model.migrate.check import create_or_verify_database as create_db + +import pkg_resources + +from ConfigParser import SafeConfigParser + +log = logging.getLogger( __name__ ) + +# Poor man's optparse +config_file = 'universe_wsgi.ini' +if '-c' in sys.argv: + pos = sys.argv.index( '-c' ) + sys.argv.pop(pos) + config_file = sys.argv.pop( pos ) +if not os.path.exists( config_file ): + print "Galaxy config file does not exist (hint: use '-c config.ini' for non-standard locations): %s" % config_file + sys.exit( 1 ) + +cp = SafeConfigParser() +cp.read( config_file ) + +if cp.has_option( "app:main", "database_connection" ): + db_url = cp.get( "app:main", "database_connection" ) +elif cp.has_option( "app:main", "database_file" ): + db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % cp.get( "app:main", "database_file" ) +else: + db_url = "sqlite:///./database/universe.sqlite?isolation_level=IMMEDIATE" + +create_db(db_url, config_file) From 065fae1095428e6a5852eae8c214dc80a05e6300 Mon Sep 17 00:00:00 2001 From: John Duddy Date: Fri, 18 Nov 2011 12:41:45 -0800 Subject: [PATCH 2/2] API fixes to import workflows from files --- lib/galaxy/web/api/histories.py | 2 +- lib/galaxy/web/api/users.py | 24 +++++++++++++++--------- lib/galaxy/web/api/workflows.py | 16 ++++++++++++++++ lib/galaxy/web/controllers/workflow.py | 15 ++++++++++++--- lib/galaxy/web/framework/__init__.py | 14 ++++++++------ 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/lib/galaxy/web/api/histories.py b/lib/galaxy/web/api/histories.py index e3ba32f97f4..819a509430e 100644 --- a/lib/galaxy/web/api/histories.py +++ b/lib/galaxy/web/api/histories.py @@ -88,8 +88,8 @@ class HistoriesController( BaseAPIController, UsesHistory ): state = states.QUEUED elif summary[states.OK] == num_sets: state = states.OK + item['contents_url'] = url_for( 'history_contents', history_id=history_id ) item['state_details'] = summary - item['contents_url'] = url_for( 'history_contents', history_id=history_id ) item['state'] = state except Exception, e: item = "Error in history API at showing history detail" diff --git a/lib/galaxy/web/api/users.py b/lib/galaxy/web/api/users.py index edd14d87de3..ce7f495169e 100644 --- a/lib/galaxy/web/api/users.py +++ b/lib/galaxy/web/api/users.py @@ -32,12 +32,11 @@ class UserAPIController( BaseAPIController ): # special case: user can see only their own user if not trans.user_is_admin(): item = trans.user.get_api_value( value_mapper={ 'id': trans.security.encode_id } ) - item['url'] = url_for( route, id=encoded_id ) + item['url'] = url_for( route, id=item['id'] ) return item for user in query: item = user.get_api_value( value_mapper={ 'id': trans.security.encode_id } ) - encoded_id = trans.security.encode_id( user.id ) - item['url'] = url_for( route, id=encoded_id ) + item['url'] = url_for( route, id=item['id'] ) rval.append( item ) return rval @@ -63,18 +62,25 @@ class UserAPIController( BaseAPIController ): 'total_disk_usage': float } ) return item - @web.expose - def create( self, trans, **kwd ): - raise HTTPNotImplemented() + @web.expose_api + def create( self, trans, payload, **kwd ): + """ + /api/users + Creates a remote user + """ + user = trans.get_or_create_remote_user(remote_user_email=payload['remote_user_email']) + item = user.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id, + 'total_disk_usage': float } ) + return item - @web.expose + @web.expose_api def update( self, trans, **kwd ): raise HTTPNotImplemented() - @web.expose + @web.expose_api def delete( self, trans, **kwd ): raise HTTPNotImplemented() - @web.expose + @web.expose_api def undelete( self, trans, **kwd ): raise HTTPNotImplemented() diff --git a/lib/galaxy/web/api/workflows.py b/lib/galaxy/web/api/workflows.py index 2eaa10a59ca..1422060ce5b 100644 --- a/lib/galaxy/web/api/workflows.py +++ b/lib/galaxy/web/api/workflows.py @@ -77,7 +77,23 @@ class WorkflowsAPIController(BaseAPIController): """ POST /api/workflows We're not creating workflows from the api. Just execute for now. + However, we will import them if installed_repository_file is specified """ + if 'workflow_id' not in payload: + # create new + if 'installed_repository_file' in payload: + workflow_controller = trans.webapp.controllers[ 'workflow' ] + result = workflow_controller.import_workflow( trans=trans, + cntrller='api', + **payload) + return result + trans.response.status = 403 + return "Either workflow_id or installed_repository_file must be specified" + + if 'installed_repository_file' in payload: + trans.response.status = 403 + return "installed_repository_file may not be specified with workflow_id" + stored_workflow = trans.sa_session.query(self.app.model.StoredWorkflow).get( trans.security.decode_id(payload['workflow_id'])) if stored_workflow.user != trans.user and not trans.user_is_admin(): diff --git a/lib/galaxy/web/controllers/workflow.py b/lib/galaxy/web/controllers/workflow.py index 8f67fc5b28e..d5183ec2d3c 100644 --- a/lib/galaxy/web/controllers/workflow.py +++ b/lib/galaxy/web/controllers/workflow.py @@ -1094,7 +1094,7 @@ class WorkflowController( BaseUIController, Sharable, UsesStoredWorkflow, UsesAn trans.response.set_content_type( 'application/galaxy-archive' ) return stored_dict @web.expose - def import_workflow( self, trans, **kwd ): + def import_workflow( self, trans, cntrller='workflow', **kwd ): """ Import a workflow by reading an url, uploading a file, opening and reading the contents of a local file, or receiving the textual representation of a workflow via http. @@ -1115,7 +1115,7 @@ class WorkflowController( BaseUIController, Sharable, UsesStoredWorkflow, UsesAn if workflow_name: workflow_name = tool_shed_decode( workflow_name ) # The following parameters will have a value only if the import originated - # from a tool shed repository installed locally. + # from a tool shed repository installed locally or from the API. installed_repository_file = kwd.get( 'installed_repository_file', '' ) repository_id = kwd.get( 'repository_id', '' ) if installed_repository_file and not import_button: @@ -1172,8 +1172,13 @@ class WorkflowController( BaseUIController, Sharable, UsesStoredWorkflow, UsesAn if data: # Create workflow if possible. If a required tool is not available in the local # Galaxy instance, the tool information will be available in the step_dict. - workflow, missing_tool_tups = self._workflow_from_dict( trans, data, source="uploaded file" ) + src = None + if cntrller != 'api': + src="uploaded file" + workflow, missing_tool_tups = self._workflow_from_dict( trans, data, source=src ) workflow = workflow.latest_workflow + if workflow_name: + workflow.name = workflow_name # Provide user feedback and show workflow list. if workflow.has_errors: message += "Imported, but some steps in this workflow have validation errors. " @@ -1231,12 +1236,16 @@ class WorkflowController( BaseUIController, Sharable, UsesStoredWorkflow, UsesAn elif installed_repository_file: # The workflow was read from a file included with an installed tool shed repository. message = "Workflow %s imported successfully." % workflow.name + if cntrller == 'api': + return status, message return trans.response.send_redirect( web.url_for( controller='admin', action='browse_tool_shed_repository', id=repository_id, message=message, status=status ) ) return self.list( trans ) + if cntrller == 'api': + return status, message return trans.fill_template( "workflow/import.mako", url=url, message=message, diff --git a/lib/galaxy/web/framework/__init__.py b/lib/galaxy/web/framework/__init__.py index fbc1283264d..555978732d3 100644 --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -359,17 +359,17 @@ class GalaxyWebTransaction( base.DefaultWebTransaction ): # An existing session, make sure correct association exists if galaxy_session.user is None: # No user, associate - galaxy_session.user = self.__get_or_create_remote_user( remote_user_email ) + galaxy_session.user = self.get_or_create_remote_user( remote_user_email ) galaxy_session_requires_flush = True elif galaxy_session.user.email != remote_user_email: # Session exists but is not associated with the correct remote user invalidate_existing_session = True - user_for_new_session = self.__get_or_create_remote_user( remote_user_email ) + user_for_new_session = self.get_or_create_remote_user( remote_user_email ) log.warning( "User logged in as '%s' externally, but has a cookie as '%s' invalidating session", remote_user_email, galaxy_session.user.email ) else: # No session exists, get/create user for new session - user_for_new_session = self.__get_or_create_remote_user( remote_user_email ) + user_for_new_session = self.get_or_create_remote_user( remote_user_email ) else: if galaxy_session is not None and galaxy_session.user and galaxy_session.user.external: # Remote user support is not enabled, but there is an existing @@ -448,11 +448,13 @@ class GalaxyWebTransaction( base.DefaultWebTransaction ): # The new session should be associated with the user galaxy_session.user = user_for_new_session return galaxy_session - def __get_or_create_remote_user( self, remote_user_email ): + def get_or_create_remote_user( self, remote_user_email ): """ - Return the user in $HTTP_REMOTE_USER and create if necessary + Create a remote user with the email remote_user_email and return it """ - # remote_user middleware ensures HTTP_REMOTE_USER exists + if not self.app.config.use_remote_user: + return None + user = self.sa_session.query( self.app.model.User ) \ .filter( self.app.model.User.table.c.email==remote_user_email ) \ .first()