galaxy-dev
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10008 discussions

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/4ee481a4b235
changeset: 3655:4ee481a4b235
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Thu Apr 15 10:06:40 2010 -0400
description:
Drop the unique constraint on the username colum in the Community model's galaxy_user table, and fix a bug theat kept users from being logged in immediately after registering in the Community Space.
diffstat:
lib/galaxy/web/controllers/user.py | 14 +++++++--
lib/galaxy/webapps/community/model/mapping.py | 3 +-
lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py | 2 +-
3 files changed, 12 insertions(+), 7 deletions(-)
diffs (64 lines):
diff -r b402fca44934 -r 4ee481a4b235 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Wed Apr 14 17:51:36 2010 -0400
+++ b/lib/galaxy/web/controllers/user.py Thu Apr 15 10:06:40 2010 -0400
@@ -118,11 +118,14 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
referer = kwd.get( 'referer', trans.request.referer )
- if not refresh_frames and webapp == 'galaxy':
- if trans.app.config.require_login:
- refresh_frames = [ 'masthead', 'history', 'tools' ]
+ if not refresh_frames:
+ if webapp == 'galaxy':
+ if trans.app.config.require_login:
+ refresh_frames = [ 'masthead', 'history', 'tools' ]
+ else:
+ refresh_frames = [ 'masthead', 'history' ]
else:
- refresh_frames = [ 'masthead', 'history' ]
+ refresh_frames = [ 'masthead' ]
error = ''
if not trans.app.config.allow_user_creation and not trans.user_is_admin():
error = 'User registration is disabled. Please contact your Galaxy administrator for an account.'
@@ -162,6 +165,9 @@
action='users',
message='Created new user account (%s)' % user.email,
status='done' ) )
+ else:
+ # Must be logging into the community space webapp
+ trans.handle_user_login( user, webapp )
if not error:
redirect_url = referer
if error:
diff -r b402fca44934 -r 4ee481a4b235 lib/galaxy/webapps/community/model/mapping.py
--- a/lib/galaxy/webapps/community/model/mapping.py Wed Apr 14 17:51:36 2010 -0400
+++ b/lib/galaxy/webapps/community/model/mapping.py Thu Apr 15 10:06:40 2010 -0400
@@ -44,7 +44,7 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", String( 255 ), index=True, unique=True, default=False ),
+ Column( "username", String( 255 ), index=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
@@ -193,7 +193,6 @@
def init( file_path, url, engine_options={}, create_tables=False ):
"""Connect mappings to the database"""
- log.debug("###In init, file_path: %s" % str( file_path ))
# Connect dataset to the file path
Tool.file_path = file_path
# Load the appropriate db module
diff -r b402fca44934 -r 4ee481a4b235 lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py
--- a/lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py Wed Apr 14 17:51:36 2010 -0400
+++ b/lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py Thu Apr 15 10:06:40 2010 -0400
@@ -21,7 +21,7 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", String( 255 ), index=True, unique=True, default=False ),
+ Column( "username", String( 255 ), index=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/b402fca44934
changeset: 3654:b402fca44934
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Wed Apr 14 17:51:36 2010 -0400
description:
Remove tags from dataset's 'Edit Attributes' form.
diffstat:
templates/dataset/edit_attributes.mako | 20 ++------------------
1 files changed, 2 insertions(+), 18 deletions(-)
diffs (41 lines):
diff -r 6e0fc1622959 -r b402fca44934 templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Wed Apr 14 15:16:03 2010 -0400
+++ b/templates/dataset/edit_attributes.mako Wed Apr 14 17:51:36 2010 -0400
@@ -4,12 +4,12 @@
<%def name="title()">${_('Edit Dataset Attributes')}</%def>
<%def name="stylesheets()">
- ${h.css( "base", "autocomplete_tagging" )}
+ ${h.css( "base" )}
</%def>
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "galaxy.base", "jquery.autocomplete", "autocomplete_tagging" )}
+ ${h.js( "galaxy.base" )}
</%def>
<%def name="datatype( dataset, datatypes )">
@@ -52,22 +52,6 @@
<div style="clear: both"></div>
</div>
%if trans.get_user() is not None:
- <%namespace file="../tagging_common.mako" import="render_individual_tagging_element" />
- <div class="form-row">
- <label>
- Tags:
- </label>
- <div style="float: left; width: 295px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px">
- <style>
- .tag-area {
- border: none;
- }
- </style>
- ${render_individual_tagging_element(user=trans.get_user(), tagged_item=data, elt_context="edit_attributes.mako", use_toggle_link=False, in_form=True, input_size="30")}
- </div>
- <div style="clear: both"></div>
- <div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div>
- </div>
<div class="form-row">
<label>
Annotation / Notes:
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/6e0fc1622959
changeset: 3653:6e0fc1622959
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Apr 14 15:16:03 2010 -0400
description:
Allow non-admin users that have the LIBRARY_MODIFY permission to delete / undelete library items as well as display / hide deleted library items.
diffstat:
lib/galaxy/web/controllers/library_admin.py | 74 --------------------------
lib/galaxy/web/controllers/library_common.py | 78 ++++++++++++++++++++++++++++
templates/library/common/browse_library.mako | 30 +++++-----
templates/library/common/library_info.mako | 8 +-
test/base/twilltestcase.py | 12 ++--
test/functional/test_library_features.py | 27 ++++++---
test/functional/test_library_security.py | 3 +-
7 files changed, 122 insertions(+), 110 deletions(-)
diffs (388 lines):
diff -r 1486617bfae8 -r 6e0fc1622959 lib/galaxy/web/controllers/library_admin.py
--- a/lib/galaxy/web/controllers/library_admin.py Wed Apr 14 14:09:01 2010 -0400
+++ b/lib/galaxy/web/controllers/library_admin.py Wed Apr 14 15:16:03 2010 -0400
@@ -161,77 +161,3 @@
action='browse_libraries',
message=util.sanitize_text( message ),
status='done' ) )
- @web.expose
- @web.require_admin
- def delete_library_item( self, trans, library_id, item_id, item_type, **kwd ):
- # This action will handle deleting all types of library items. State is saved for libraries and
- # folders ( i.e., if undeleted, the state of contents of the library or folder will remain, so previously
- # deleted / purged contents will have the same state ). When a library or folder has been deleted for
- # the amount of time defined in the cleanup_datasets.py script, the library or folder and all of its
- # contents will be purged. The association between this method and the cleanup_datasets.py script
- # enables clean maintenance of libraries and library dataset disk files. This is also why the item_types
- # are not any of the associations ( the cleanup_datasets.py script handles everything ).
- show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
- item_types = { 'library': trans.app.model.Library,
- 'folder': trans.app.model.LibraryFolder,
- 'library_dataset': trans.app.model.LibraryDataset }
- if item_type not in item_types:
- message = 'Bad item_type specified: %s' % str( item_type )
- status = 'error'
- else:
- if item_type == 'library_dataset':
- item_desc = 'Dataset'
- else:
- item_desc = item_type.capitalize()
- library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
- library_item.deleted = True
- trans.sa_session.add( library_item )
- trans.sa_session.flush()
- message = util.sanitize_text( "%s '%s' has been marked deleted" % ( item_desc, library_item.name ) )
- status = 'done'
- if item_type == 'library':
- return self.browse_libraries( trans, message=message, status=status )
- else:
- return trans.response.send_redirect( web.url_for( controller='library_common',
- action='browse_library',
- cntrller='library_admin',
- id=library_id,
- show_deleted=show_deleted,
- message=message,
- status=status ) )
- @web.expose
- @web.require_admin
- def undelete_library_item( self, trans, library_id, item_id, item_type, **kwd ):
- # This action will handle undeleting all types of library items
- show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
- item_types = { 'library': trans.app.model.Library,
- 'folder': trans.app.model.LibraryFolder,
- 'library_dataset': trans.app.model.LibraryDataset }
- if item_type not in item_types:
- message = 'Bad item_type specified: %s' % str( item_type )
- status = ERROR
- else:
- if item_type == 'library_dataset':
- item_desc = 'Dataset'
- else:
- item_desc = item_type.capitalize()
- library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
- if library_item.purged:
- message = '%s %s has been purged, so it cannot be undeleted' % ( item_desc, library_item.name )
- status = ERROR
- else:
- library_item.deleted = False
- trans.sa_session.add( library_item )
- trans.sa_session.flush()
- message = util.sanitize_text( "%s '%s' has been marked undeleted" % ( item_desc, library_item.name ) )
- status = SUCCESS
- if item_type == 'library':
- return self.browse_libraries( trans, message=message, status=status )
- else:
- return trans.response.send_redirect( web.url_for( controller='library_common',
- action='browse_library',
- cntrller='library_admin',
- id=library_id,
- show_deleted=show_deleted,
- message=message,
- status=status ) )
diff -r 1486617bfae8 -r 6e0fc1622959 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Wed Apr 14 14:09:01 2010 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Wed Apr 14 15:16:03 2010 -0400
@@ -1733,6 +1733,84 @@
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status=status ) )
+ @web.expose
+ def delete_library_item( self, trans, cntrller, library_id, item_id, item_type, **kwd ):
+ # This action will handle deleting all types of library items. State is saved for libraries and
+ # folders ( i.e., if undeleted, the state of contents of the library or folder will remain, so previously
+ # deleted / purged contents will have the same state ). When a library or folder has been deleted for
+ # the amount of time defined in the cleanup_datasets.py script, the library or folder and all of its
+ # contents will be purged. The association between this method and the cleanup_datasets.py script
+ # enables clean maintenance of libraries and library dataset disk files. This is also why the item_types
+ # are not any of the associations ( the cleanup_datasets.py script handles everything ).
+ show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
+ item_types = { 'library': trans.app.model.Library,
+ 'folder': trans.app.model.LibraryFolder,
+ 'library_dataset': trans.app.model.LibraryDataset }
+ if item_type not in item_types:
+ message = 'Bad item_type specified: %s' % str( item_type )
+ status = 'error'
+ else:
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
+ else:
+ item_desc = item_type.capitalize()
+ library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
+ library_item.deleted = True
+ trans.sa_session.add( library_item )
+ trans.sa_session.flush()
+ message = util.sanitize_text( "%s '%s' has been marked deleted" % ( item_desc, library_item.name ) )
+ status = 'done'
+ if item_type == 'library':
+ return trans.response.send_redirect( web.url_for( controller=cntrller,
+ action='browse_libraries',
+ message=message,
+ status=status ) )
+ else:
+ return trans.response.send_redirect( web.url_for( controller='library_common',
+ action='browse_library',
+ cntrller=cntrller,
+ id=library_id,
+ show_deleted=show_deleted,
+ message=message,
+ status=status ) )
+ @web.expose
+ def undelete_library_item( self, trans, cntrller, library_id, item_id, item_type, **kwd ):
+ # This action will handle undeleting all types of library items
+ show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
+ item_types = { 'library': trans.app.model.Library,
+ 'folder': trans.app.model.LibraryFolder,
+ 'library_dataset': trans.app.model.LibraryDataset }
+ if item_type not in item_types:
+ message = 'Bad item_type specified: %s' % str( item_type )
+ status = ERROR
+ else:
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
+ else:
+ item_desc = item_type.capitalize()
+ library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
+ if library_item.purged:
+ message = '%s %s has been purged, so it cannot be undeleted' % ( item_desc, library_item.name )
+ status = ERROR
+ else:
+ library_item.deleted = False
+ trans.sa_session.add( library_item )
+ trans.sa_session.flush()
+ message = util.sanitize_text( "%s '%s' has been marked undeleted" % ( item_desc, library_item.name ) )
+ status = SUCCESS
+ if item_type == 'library':
+ return trans.response.send_redirect( web.url_for( controller=cntrller,
+ action='browse_libraries',
+ message=message,
+ status=status ) )
+ else:
+ return trans.response.send_redirect( web.url_for( controller='library_common',
+ action='browse_library',
+ cntrller=cntrller,
+ id=library_id,
+ show_deleted=show_deleted,
+ message=message,
+ status=status ) )
# ---- Utility methods -------------------------------------------------------
diff -r 1486617bfae8 -r 6e0fc1622959 templates/library/common/browse_library.mako
--- a/templates/library/common/browse_library.mako Wed Apr 14 14:09:01 2010 -0400
+++ b/templates/library/common/browse_library.mako Wed Apr 14 15:16:03 2010 -0400
@@ -232,11 +232,11 @@
<a class="action-button" href="${h.url_for( controller='library_common', action='act_on_multiple_datasets', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), ldda_ids=trans.security.encode_id( ldda.id ), do_action='import_to_history', use_panels=use_panels, show_deleted=show_deleted )}">Import this dataset into your current history</a>
<a class="action-button" href="${h.url_for( controller='library_common', action='download_dataset_from_folder', cntrller=cntrller, id=trans.security.encode_id( ldda.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels )}">Download this dataset</a>
%endif
- %if cntrller in [ 'library_admin', 'requests_admin' ]:
+ %if cntrller == 'library_admin' or can_modify:
%if not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.deleted:
- <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Delete this dataset</a>
+ <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Delete this dataset</a>
%elif not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.purged and ldda.library_dataset.deleted:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Undelete this dataset</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Undelete this dataset</a>
%endif
%endif
</div>
@@ -328,11 +328,11 @@
%if not branch_deleted( folder ) and ( cntrller == 'library_admin' or can_manage ):
<a class="action-button" href="${h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if cntrller in [ 'library_admin', 'requests_admin' ]:
+ %if cntrller == 'library_admin' or can_modify:
%if not library.deleted and not folder.deleted:
- <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a>
+ <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a>
%elif not library.deleted and folder.deleted and not folder.purged:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
%endif
%endif
</div>
@@ -435,6 +435,12 @@
%if not library.deleted:
%if cntrller == 'library_admin' or can_modify:
<a class="action-button" href="${h.url_for( controller='library_common', action='library_info', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
+ <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
+ %if show_deleted:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=False )}">Hide deleted items</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=True )}">Show deleted items</a>
+ %endif
%endif
%if ( cntrller == 'library_admin' or can_modify ) and not library.info_association:
<a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add template</a>
@@ -446,16 +452,8 @@
%if cntrller == 'library_admin' or can_manage:
<a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if cntrller == 'library_admin':
- <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
- %if show_deleted:
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=False )}">Hide deleted items</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=True )}">Show deleted items</a>
- %endif
- %endif
- %elif cntrller == 'library_admin' and not library.purged:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library', use_panels=use_panels )}">Undelete this data library</a>
+ %elif ( cntrller == 'library_admin' or can_modify ) and not library.purged:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library', use_panels=use_panels )}">Undelete this data library</a>
%elif library.purged:
<a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">This data library has been purged</a>
%endif
diff -r 1486617bfae8 -r 6e0fc1622959 templates/library/common/library_info.mako
--- a/templates/library/common/library_info.mako Wed Apr 14 14:09:01 2010 -0400
+++ b/templates/library/common/library_info.mako Wed Apr 14 15:16:03 2010 -0400
@@ -37,11 +37,11 @@
%if cntrller == 'library_admin' or can_manage:
<a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if cntrller == 'library_admin':
- <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
+ %if cntrller == 'library_admin' or can_modify:
+ <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
%endif
- %elif cntrller == 'library_admin' and not library.purged:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Undelete this data library</a>
+ %elif ( cntrller == 'library_admin' or can_modify ) and not library.purged:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Undelete this data library</a>
%elif library.purged:
<a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">This data library has been purged</a>
%endif
diff -r 1486617bfae8 -r 6e0fc1622959 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Wed Apr 14 14:09:01 2010 -0400
+++ b/test/base/twilltestcase.py Wed Apr 14 15:16:03 2010 -0400
@@ -2014,11 +2014,11 @@
errmsg += 'Unpacked archive remains in: %s\n' % tmpd
raise AssertionError( errmsg )
shutil.rmtree( tmpd )
- def delete_library_item( self, library_id, item_id, item_name, item_type='library_dataset' ):
+ def delete_library_item( self, cntrller, library_id, item_id, item_name, item_type='library_dataset' ):
"""Mark a library item as deleted"""
self.home()
- self.visit_url( "%s/library_admin/delete_library_item?library_id=%s&item_id=%s&item_type=%s" \
- % ( self.url, library_id, item_id, item_type ) )
+ self.visit_url( "%s/library_common/delete_library_item?cntrller=%s&library_id=%s&item_id=%s&item_type=%s" \
+ % ( self.url, cntrller, library_id, item_id, item_type ) )
if item_type == 'library_dataset':
item_desc = 'Dataset'
else:
@@ -2026,11 +2026,11 @@
check_str = "%s '%s' has been marked deleted" % ( item_desc, item_name )
self.check_page_for_string( check_str )
self.home()
- def undelete_library_item( self, library_id, item_id, item_name, item_type='library_dataset' ):
+ def undelete_library_item( self, cntrller, library_id, item_id, item_name, item_type='library_dataset' ):
"""Mark a library item as deleted"""
self.home()
- self.visit_url( "%s/library_admin/undelete_library_item?library_id=%s&item_id=%s&item_type=%s" \
- % ( self.url, library_id, item_id, item_type ) )
+ self.visit_url( "%s/library_common/undelete_library_item?cntrller=%s&library_id=%s&item_id=%s&item_type=%s" \
+ % ( self.url, cntrller, library_id, item_id, item_type ) )
if item_type == 'library_dataset':
item_desc = 'Dataset'
else:
diff -r 1486617bfae8 -r 6e0fc1622959 test/functional/test_library_features.py
--- a/test/functional/test_library_features.py Wed Apr 14 14:09:01 2010 -0400
+++ b/test/functional/test_library_features.py Wed Apr 14 15:16:03 2010 -0400
@@ -476,7 +476,8 @@
def test_080_mark_dataset_deleted( self ):
"""Testing marking a library dataset as deleted"""
# Logged in as admin_user
- self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( ldda_two.library_dataset.id ),
ldda_two.name,
item_type='library_dataset' )
@@ -496,7 +497,8 @@
def test_090_mark_folder_deleted( self ):
"""Testing marking a library folder as deleted"""
# Logged in as admin_user
- self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
item_type='folder' )
@@ -506,7 +508,8 @@
def test_095_mark_folder_undeleted( self ):
"""Testing marking a library folder as undeleted"""
# Logged in as admin_user
- self.undelete_library_item( self.security.encode_id( library_one.id ),
+ self.undelete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
item_type='folder' )
@@ -520,11 +523,13 @@
"""Testing marking a library as deleted"""
# Logged in as admin_user
# First mark folder_two as deleted to further test state saving when we undelete the library
- self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
item_type='folder' )
- self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
item_type='library' )
@@ -533,7 +538,8 @@
def test_105_mark_library_undeleted( self ):
"""Testing marking a library as undeleted"""
# Logged in as admin_user
- self.undelete_library_item( self.security.encode_id( library_one.id ),
+ self.undelete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
item_type='library' )
@@ -545,7 +551,8 @@
def test_110_purge_library( self ):
"""Testing purging a library"""
# Logged in as admin_user
- self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
item_type='library' )
@@ -612,7 +619,8 @@
# TODO: add a functional test to cover adding a library dataset via url_paste here...
# TODO: Add a functional test to cover checking the space_to_tab checkbox here...
# Delete and purge the library
- self.delete_library_item( self.security.encode_id( library_two.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library_two.id ),
self.security.encode_id( library_two.id ),
library_two.name,
item_type='library' )
@@ -625,7 +633,8 @@
# Purge all libraries
##################
for library in [ library_one, library_two ]:
- self.delete_library_item( self.security.encode_id( library.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library.id ),
self.security.encode_id( library.id ),
library.name,
item_type='library' )
diff -r 1486617bfae8 -r 6e0fc1622959 test/functional/test_library_security.py
--- a/test/functional/test_library_security.py Wed Apr 14 14:09:01 2010 -0400
+++ b/test/functional/test_library_security.py Wed Apr 14 15:16:03 2010 -0400
@@ -569,7 +569,8 @@
# Purge all libraries
##################
for library in [ library_one, library_two ]:
- self.delete_library_item( self.security.encode_id( library.id ),
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library.id ),
self.security.encode_id( library.id ),
library.name,
item_type='library' )
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/1486617bfae8
changeset: 3652:1486617bfae8
user: Nate Coraor <nate(a)bx.psu.edu>
date: Wed Apr 14 14:09:01 2010 -0400
description:
Don't display the divider in the user tab if using external authentication
diffstat:
templates/webapps/galaxy/base_panels.mako | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (13 lines):
diff -r 9de680276272 -r 1486617bfae8 templates/webapps/galaxy/base_panels.mako
--- a/templates/webapps/galaxy/base_panels.mako Wed Apr 14 14:04:03 2010 -0400
+++ b/templates/webapps/galaxy/base_panels.mako Wed Apr 14 14:09:01 2010 -0400
@@ -123,8 +123,8 @@
<li><a target="galaxy_main" href="${h.url_for( controller='/user', action='dbkeys' )}">Custom Builds</a></li>
%endif
<li><a target="_top" href="${logout_url}">Logout</a></li>
+ <li><hr style="color: inherit; background-color: gray"/></li>
%endif
- <li><hr style="color: inherit; background-color: gray"/></li>
<li><a target="galaxy_main" href="${h.url_for( controller='/history', action='list' )}">Histories</a></li>
<li><a target="galaxy_main" href="${h.url_for( controller='/dataset', action='list' )}">Datasets</a></li>
%if app.config.get_bool( 'enable_pages', False ):
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/9de680276272
changeset: 3651:9de680276272
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Apr 14 14:04:03 2010 -0400
description:
Somehow missed this necessary cleanup in my initial commit for the Galaxy Community framework.
diffstat:
community_wsgi.ini.sample | 2 +-
lib/galaxy/webapps/community/model/__init__.py | 26 +++++-
lib/galaxy/webapps/community/model/mapping.py | 36 +++++++++-
lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py | 34 ++++++--
lib/galaxy/webapps/community/security/__init__.py | 37 ++++++---
templates/webapps/community/base_panels.mako | 4 +-
6 files changed, 107 insertions(+), 32 deletions(-)
diffs (291 lines):
diff -r 3d8a7da23e46 -r 9de680276272 community_wsgi.ini.sample
--- a/community_wsgi.ini.sample Wed Apr 14 13:52:35 2010 -0400
+++ b/community_wsgi.ini.sample Wed Apr 14 14:04:03 2010 -0400
@@ -17,7 +17,7 @@
log_level = DEBUG
# Database connection
-database_file = database/universe.sqlite
+#database_file = database/community.sqlite
# You may use a SQLAlchemy connection string to specify an external database instead
#database_connection = postgres:///community_test?host=/var/run/postgresql
diff -r 3d8a7da23e46 -r 9de680276272 lib/galaxy/webapps/community/model/__init__.py
--- a/lib/galaxy/webapps/community/model/__init__.py Wed Apr 14 13:52:35 2010 -0400
+++ b/lib/galaxy/webapps/community/model/__init__.py Wed Apr 14 14:04:03 2010 -0400
@@ -29,6 +29,26 @@
"""Check if 'cleartext' matches 'self.password' when hashed."""
return self.password == new_secure_hash( text_type=cleartext )
+class UserRoleAssociation( object ):
+ def __init__( self, user, role ):
+ self.user = user
+ self.role = role
+
+class Role( object ):
+ private_id = None
+ types = Bunch(
+ PRIVATE = 'private',
+ SYSTEM = 'system',
+ USER = 'user',
+ ADMIN = 'admin',
+ SHARING = 'sharing'
+ )
+ def __init__( self, name="", description="", type="system", deleted=False ):
+ self.name = name
+ self.description = description
+ self.type = type
+ self.deleted = deleted
+
class GalaxySession( object ):
def __init__( self,
id=None,
@@ -49,12 +69,6 @@
self.session_key = session_key
self.is_valid = is_valid
self.prev_session_id = prev_session_id
- self.histories = []
- def add_history( self, history, association=None ):
- if association is None:
- self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
- else:
- self.histories.append( association )
class Tool( object ):
def __init__( self, guid=None, name=None, description=None, category=None, version=None, user_id=None, external_filename=None ):
diff -r 3d8a7da23e46 -r 9de680276272 lib/galaxy/webapps/community/model/mapping.py
--- a/lib/galaxy/webapps/community/model/mapping.py Wed Apr 14 13:52:35 2010 -0400
+++ b/lib/galaxy/webapps/community/model/mapping.py Wed Apr 14 14:04:03 2010 -0400
@@ -44,12 +44,28 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "username", String( 255 ), index=True, unique=True, default=False ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ) )
+UserRoleAssociation.table = Table( "user_role_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ) )
+
+Role.table = Table( "role", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", String( 255 ), index=True, unique=True ),
+ Column( "description", TEXT ),
+ Column( "type", String( 40 ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
GalaxySession.table = Table( "galaxy_session", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -121,7 +137,23 @@
properties=dict( tools=relation( Tool, order_by=desc( Tool.table.c.update_time ) ),
active_tools=relation( Tool, primaryjoin=( ( Tool.table.c.user_id == User.table.c.id ) & ( not_( Tool.table.c.deleted ) ) ), order_by=desc( Tool.table.c.update_time ) ),
galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ) ) )
-
+
+assign_mapper( context, UserRoleAssociation, UserRoleAssociation.table,
+ properties=dict(
+ user=relation( User, backref="roles" ),
+ non_private_roles=relation( User,
+ backref="non_private_roles",
+ primaryjoin=( ( User.table.c.id == UserRoleAssociation.table.c.user_id ) & ( UserRoleAssociation.table.c.role_id == Role.table.c.id ) & not_( Role.table.c.name == User.table.c.email ) ) ),
+ role=relation( Role )
+ )
+)
+
+assign_mapper( context, Role, Role.table,
+ properties=dict(
+ users=relation( UserRoleAssociation )
+ )
+)
+
assign_mapper( context, GalaxySession, GalaxySession.table,
properties=dict( user=relation( User.mapper ) ) )
diff -r 3d8a7da23e46 -r 9de680276272 lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py
--- a/lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py Wed Apr 14 13:52:35 2010 -0400
+++ b/lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py Wed Apr 14 14:04:03 2010 -0400
@@ -16,18 +16,34 @@
metadata = MetaData( migrate_engine )
-User.table = Table( "galaxy_user", metadata,
+User_table = Table( "galaxy_user", metadata,
Column( "id", Integer, primary_key=True),
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "username", String( 255 ), index=True, unique=True, default=False ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ) )
-
-GalaxySession.table = Table( "galaxy_session", metadata,
+
+UserRoleAssociation_table = Table( "user_role_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ) )
+
+Role_table = Table( "role", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", String( 255 ), index=True, unique=True ),
+ Column( "description", TEXT ),
+ Column( "type", String( 40 ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+GalaxySession_table = Table( "galaxy_session", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
@@ -40,7 +56,7 @@
Column( "prev_session_id", Integer ) # saves a reference to the previous session so we have a way to chain them together
)
-Tool.table = Table( "tool", metadata,
+Tool_table = Table( "tool", metadata,
Column( "id", Integer, primary_key=True ),
Column( "guid", TrimmedString( 255 ), index=True, unique=True ),
Column( "create_time", DateTime, default=now ),
@@ -53,7 +69,7 @@
Column( "external_filename" , TEXT ),
Column( "deleted", Boolean, default=False ) )
-Job.table = Table( "job", metadata,
+Job_table = Table( "job", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
@@ -70,14 +86,14 @@
Column( "job_runner_name", String( 255 ) ),
Column( "job_runner_external_id", String( 255 ) ) )
-Tag.table = Table( "tag", metadata,
+Tag_table = Table( "tag", metadata,
Column( "id", Integer, primary_key=True ),
Column( "type", Integer ),
Column( "parent_id", Integer, ForeignKey( "tag.id" ) ),
Column( "name", TrimmedString(255) ),
UniqueConstraint( "name" ) )
-ToolTagAssociation.table = Table( "tool_tag_association", metadata,
+ToolTagAssociation_table = Table( "tool_tag_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
@@ -86,7 +102,7 @@
Column( "value", TrimmedString(255), index=True),
Column( "user_value", TrimmedString(255), index=True) )
-ToolAnnotationAssociation.table = Table( "tool_annotation_association", metadata,
+ToolAnnotationAssociation_table = Table( "tool_annotation_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
diff -r 3d8a7da23e46 -r 9de680276272 lib/galaxy/webapps/community/security/__init__.py
--- a/lib/galaxy/webapps/community/security/__init__.py Wed Apr 14 13:52:35 2010 -0400
+++ b/lib/galaxy/webapps/community/security/__init__.py Wed Apr 14 14:04:03 2010 -0400
@@ -18,6 +18,18 @@
class RBACAgent:
"""Class that handles galaxy community space security"""
permitted_actions = Bunch()
+ def associate_components( self, **kwd ):
+ raise 'No valid method of associating provided components: %s' % kwd
+ def associate_user_role( self, user, role ):
+ raise 'No valid method of associating a user with a role'
+ def convert_permitted_action_strings( self, permitted_action_strings ):
+ """
+ When getting permitted actions from an untrusted source like a
+ form, ensure that they match our actual permitted actions.
+ """
+ return filter( lambda x: x is not None, [ self.permitted_actions.get( action_string ) for action_string in permitted_action_strings ] )
+ def create_private_user_role( self, user ):
+ raise "Unimplemented Method"
def get_action( self, name, default=None ):
"""Get a permitted action by its dict key or action name"""
for k, v in self.permitted_actions.items():
@@ -29,16 +41,8 @@
return self.permitted_actions.__dict__.values()
def get_item_actions( self, action, item ):
raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
- def create_private_user_role( self, user ):
- raise "Unimplemented Method"
def get_private_user_role( self, user ):
raise "Unimplemented Method"
- def convert_permitted_action_strings( self, permitted_action_strings ):
- """
- When getting permitted actions from an untrusted source like a
- form, ensure that they match our actual permitted actions.
- """
- return filter( lambda x: x is not None, [ self.permitted_actions.get( action_string ) for action_string in permitted_action_strings ] )
class CommunityRBACAgent( RBACAgent ):
def __init__( self, model, permitted_actions=None ):
@@ -49,7 +53,6 @@
def sa_session( self ):
"""Returns a SQLAlchemy session"""
return self.model.context
-
def allow_action( self, roles, action, item ):
"""
Method for checking a permission for the current user ( based on roles ) to perform a
@@ -64,9 +67,16 @@
ret_val = True
break
return ret_val
- def get_item_actions( self, action, item ):
- # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
- return [ permission for permission in item.actions if permission.action == action.action ]
+ def associate_components( self, **kwd ):
+ if 'user' in kwd:
+ if 'role' in kwd:
+ return self.associate_user_role( kwd['user'], kwd['role'] )
+ raise 'No valid method of associating provided components: %s' % kwd
+ def associate_user_role( self, user, role ):
+ assoc = self.model.UserRoleAssociation( user, role )
+ self.sa_session.add( assoc )
+ self.sa_session.flush()
+ return assoc
def create_private_user_role( self, user ):
# Create private role
role = self.model.Role( name=user.email, description='Private Role for ' + user.email, type=self.model.Role.types.PRIVATE )
@@ -75,6 +85,9 @@
# Add user to role
self.associate_components( role=role, user=user )
return role
+ def get_item_actions( self, action, item ):
+ # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
+ return [ permission for permission in item.actions if permission.action == action.action ]
def get_private_user_role( self, user, auto_create=False ):
role = self.sa_session.query( self.model.Role ) \
.filter( and_( self.model.Role.table.c.name == user.email,
diff -r 3d8a7da23e46 -r 9de680276272 templates/webapps/community/base_panels.mako
--- a/templates/webapps/community/base_panels.mako Wed Apr 14 13:52:35 2010 -0400
+++ b/templates/webapps/community/base_panels.mako Wed Apr 14 14:04:03 2010 -0400
@@ -60,9 +60,9 @@
%>
<div class="submenu">
<ul class="loggedout-only" style="${style1}">
- <li><a href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login</a></li>
+ <li><a target="galaxy_main" href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login</a></li>
%if app.config.allow_user_creation:
- <li><a href="${h.url_for( controller='/user', action='create', webapp='community' )}">Register</a></li>
+ <li><a target="galaxy_main" href="${h.url_for( controller='/user', action='create', webapp='community' )}">Register</a></li>
%endif
</ul>
<ul class="loggedin-only" style="${style2}">
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/3d8a7da23e46
changeset: 3650:3d8a7da23e46
user: Anton Nekrutenko <anton(a)bx.psu.edu>
date: Wed Apr 14 13:52:35 2010 -0400
description:
Fixed indel calling in pileup wrapper. TO DO: Write a separate wrapper for indels only.
diffstat:
tools/samtools/pileup_parser.pl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (12 lines):
diff -r cffa627364bb -r 3d8a7da23e46 tools/samtools/pileup_parser.pl
--- a/tools/samtools/pileup_parser.pl Wed Apr 14 11:27:15 2010 -0400
+++ b/tools/samtools/pileup_parser.pl Wed Apr 14 13:52:35 2010 -0400
@@ -60,7 +60,7 @@
my @qv = split //, $base_quality;
for my $base ( 0 .. @bases - 1 ) {
- if ( ord( $qv[ $base ] ) - 33 >= $quality_cutoff )
+ if ( ord( $qv[ $base ] ) - 33 >= $quality_cutoff and $bases[ $base ] ne '*')
{
++$above_qv_bases;
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/cffa627364bb
changeset: 3649:cffa627364bb
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Apr 14 11:27:15 2010 -0400
description:
Apply patch from Brad Chapman that resolves the following issue - resolves ticket # 319.
GFF and GFF3 sniffer functions in datatypes/intervals.py currently require the score column to be an integer between 0 and 1000 to assign a file as valid GFF. According to the GFF3 spec, the score values are not well defined and floating point values or numbers outside that range should also be valid.
The patch relaxes this requirement to allow detection of a wider range of GFF files.
diffstat:
lib/galaxy/datatypes/interval.py | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diffs (29 lines):
diff -r bb2f3963136d -r cffa627364bb lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py Wed Apr 14 11:21:00 2010 -0400
+++ b/lib/galaxy/datatypes/interval.py Wed Apr 14 11:27:15 2010 -0400
@@ -718,11 +718,9 @@
return False
if hdr[5] != '.':
try:
- score = int(hdr[5])
+ score = float( hdr[5] )
except:
return False
- if (score < 0 or score > 1000):
- return False
if hdr[6] not in data.valid_strand:
return False
return True
@@ -822,11 +820,9 @@
return False
if hdr[5] != '.':
try:
- score = int(hdr[5])
+ score = float( hdr[5] )
except:
return False
- if (score < 0 or score > 1000):
- return False
if hdr[6] not in self.valid_gff3_strand:
return False
if hdr[7] not in self.valid_gff3_phase:
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/bb2f3963136d
changeset: 3648:bb2f3963136d
user: rc
date: Wed Apr 14 11:21:00 2010 -0400
description:
lims: added email notification on request completion
diffstat:
lib/galaxy/model/__init__.py | 3 +-
lib/galaxy/model/mapping.py | 1 +
lib/galaxy/model/migrate/versions/0044_add_notify_column_to_request_table.py | 24 +++++++++
lib/galaxy/web/controllers/requests.py | 18 ++++++-
lib/galaxy/web/controllers/requests_admin.py | 26 +++++++++-
5 files changed, 69 insertions(+), 3 deletions(-)
diffs (205 lines):
diff -r f905e1415dd4 -r bb2f3963136d lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Wed Apr 14 10:20:32 2010 -0400
+++ b/lib/galaxy/model/__init__.py Wed Apr 14 11:21:00 2010 -0400
@@ -1402,12 +1402,13 @@
REJECTED = 'Rejected',
COMPLETE = 'Complete' )
def __init__(self, name=None, desc=None, request_type=None, user=None,
- form_values=None):
+ form_values=None, notify=None):
self.name = name
self.desc = desc
self.type = request_type
self.values = form_values
self.user = user
+ self.notify = notify
self.samples_list = []
def state(self):
if self.events:
diff -r f905e1415dd4 -r bb2f3963136d lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Wed Apr 14 10:20:32 2010 -0400
+++ b/lib/galaxy/model/mapping.py Wed Apr 14 11:21:00 2010 -0400
@@ -641,6 +641,7 @@
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "name", TrimmedString( 255 ), nullable=False ),
Column( "desc", TEXT ),
+ Column( "notify", Boolean, default=False ),
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
diff -r f905e1415dd4 -r bb2f3963136d lib/galaxy/model/migrate/versions/0044_add_notify_column_to_request_table.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0044_add_notify_column_to_request_table.py Wed Apr 14 11:21:00 2010 -0400
@@ -0,0 +1,24 @@
+"""
+Migration script to add a notify column to the request table.
+"""
+
+from sqlalchemy import *
+from migrate import *
+from migrate.changeset import *
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ Request_table = Table( "request", metadata, autoload=True )
+ c = Column( "notify", Boolean, default=False )
+ c.create( Request_table )
+ assert c is Request_table.c.notify
+
+def downgrade():
+ pass
diff -r f905e1415dd4 -r bb2f3963136d lib/galaxy/web/controllers/requests.py
--- a/lib/galaxy/web/controllers/requests.py Wed Apr 14 10:20:32 2010 -0400
+++ b/lib/galaxy/web/controllers/requests.py Wed Apr 14 11:21:00 2010 -0400
@@ -209,6 +209,7 @@
request_details.append(dict(label='Type',
value=request.type.name,
helptext=''))
+
request_details.append(dict(label='State',
value=request.state(),
helptext=''))
@@ -235,6 +236,13 @@
request_details.append(dict(label=field['label'],
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
+ if request.notify:
+ notify = 'Yes'
+ else:
+ notify = 'No'
+ request_details.append(dict(label='Send email notification once the sequencing request is complete',
+ value=notify,
+ helptext=''))
return request_details
def __show_request(self, trans, **kwd):
params = util.Params( kwd )
@@ -707,6 +715,9 @@
util.restore_text( params.get( 'desc', '' ) )),
helptext='(Optional)'))
widgets = widgets + request_type.request_form.get_widgets( trans.user, **kwd )
+ widgets.append(dict(label='Send email notification once the sequencing request is complete',
+ widget=CheckboxField('email_notify', False),
+ helptext=''))
return trans.fill_template( '/requests/new_request.mako',
select_request_type=select_request_type,
request_type=request_type,
@@ -755,6 +766,7 @@
request_type = trans.sa_session.query( trans.app.model.RequestType ).get( int( params.select_request_type ) )
name = util.restore_text(params.get('name', ''))
desc = util.restore_text(params.get('desc', ''))
+ notify = CheckboxField.is_checked( params.get('email_notify', '') )
# library
try:
library = trans.sa_session.query( trans.app.model.Library ).get( int( params.get( 'library_id', None ) ) )
@@ -801,7 +813,7 @@
trans.sa_session.flush()
if not request:
request = trans.app.model.Request(name, desc, request_type,
- trans.user, form_values)
+ trans.user, form_values, notify)
trans.sa_session.add( request )
trans.sa_session.flush()
trans.sa_session.refresh( request )
@@ -816,6 +828,7 @@
request.type = request_type
request.user = trans.user
request.values = form_values
+ request.notify = notify
trans.sa_session.add( request )
trans.sa_session.flush()
return request
@@ -896,6 +909,9 @@
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
widgets = widgets + request.type.request_form.get_widgets( trans.user, request.values.content, **kwd )
+ widgets.append(dict(label='Send email notification once the sequencing request is complete',
+ widget=CheckboxField('email_notify', request.notify),
+ helptext=''))
return trans.fill_template( '/requests/edit_request.mako',
select_request_type=select_request_type,
request_type=request.type,
diff -r f905e1415dd4 -r bb2f3963136d lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Wed Apr 14 10:20:32 2010 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Wed Apr 14 11:21:00 2010 -0400
@@ -362,6 +362,9 @@
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
widgets = widgets + request.type.request_form.get_widgets( request.user, request.values.content, **kwd )
+ widgets.append(dict(label='Send email notification once the sequencing request is complete',
+ widget=CheckboxField('email_notify', request.notify),
+ helptext=''))
return trans.fill_template( '/admin/requests/edit_request.mako',
select_request_type=select_request_type,
request_type=request.type,
@@ -633,6 +636,9 @@
util.restore_text( params.get( 'desc', '' ) )),
helptext='(Optional)'))
widgets = widgets + request_type.request_form.get_widgets( user, **kwd )
+ widgets.append(dict(label='Send email notification once the sequencing request is complete',
+ widget=CheckboxField('email_notify', False),
+ helptext='Email would be sent to the lab admin and the user for whom this request has been created.'))
return trans.fill_template( '/admin/requests/new_request.mako',
select_request_type=select_request_type,
request_type=request_type,
@@ -694,6 +700,7 @@
user = trans.sa_session.query( trans.app.model.User ).get( int( params.get( 'select_user', '' ) ) )
name = util.restore_text(params.get('name', ''))
desc = util.restore_text(params.get('desc', ''))
+ notify = CheckboxField.is_checked( params.get('email_notify', '') )
# fields
values = []
for index, field in enumerate(request_type.request_form.fields):
@@ -728,7 +735,7 @@
trans.sa_session.flush()
if not request:
request = trans.app.model.Request(name, desc, request_type,
- user, form_values)
+ user, form_values, notify)
trans.sa_session.add( request )
trans.sa_session.flush()
trans.sa_session.refresh( request )
@@ -745,6 +752,7 @@
request.desc = desc
request.type = request_type
request.user = user
+ request.notify = notify
request.values = form_values
trans.sa_session.add( request )
trans.sa_session.flush()
@@ -1183,6 +1191,13 @@
request_details.append(dict(label=field['label'],
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
+ if request.notify:
+ notify = 'Yes'
+ else:
+ notify = 'No'
+ request_details.append(dict(label='Send email notification once the sequencing request is complete',
+ value=notify,
+ helptext=''))
return request_details
def __validate_barcode(self, trans, sample, barcode):
'''
@@ -1333,6 +1348,15 @@
event = trans.app.model.RequestEvent(request, request.states.COMPLETE, comments)
trans.sa_session.add( event )
trans.sa_session.flush()
+ # now that the request is complete send the email notification to the
+ # the user
+ if request.notify:
+ mail = os.popen("%s -t" % trans.app.config.sendmail_path, 'w')
+ subject = "Galaxy Sample Tracking: '%s' sequencing request in complete." % request.name
+ body = "The '%s' sequencing request (type: %s) is now complete. Datasets from all the samples are now available for analysis or download from the respective data libraries in Galaxy." % (request.name, request.type.name)
+ email_content = "To: %s\nFrom: no-reply(a)nowhere.edu\nSubject: %s\n\n%s" % (request.user.email, subject, body)
+ mail.write( email_content )
+ x = mail.close()
def change_state(self, trans, sample):
possible_states = sample.request.type.states
curr_state = sample.current_state()
1
0

16 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/f905e1415dd4
changeset: 3647:f905e1415dd4
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Apr 14 10:20:32 2010 -0400
description:
Framework for the Galaxy Community Space.
diffstat:
community_wsgi.ini.sample | 71 +++
lib/galaxy/tags/tag_handler.py | 5 +
lib/galaxy/webapps/community/__init__.py | 3 +
lib/galaxy/webapps/community/app.py | 34 +
lib/galaxy/webapps/community/base/controller.py | 24 +
lib/galaxy/webapps/community/buildapp.py | 198 ++++++++++
lib/galaxy/webapps/community/config.py | 153 +++++++
lib/galaxy/webapps/community/controllers/__init__.py | 1 +
lib/galaxy/webapps/community/controllers/tool_browser.py | 100 +++++
lib/galaxy/webapps/community/model/__init__.py | 187 +++++++++
lib/galaxy/webapps/community/model/mapping.py | 186 +++++++++
lib/galaxy/webapps/community/model/migrate/check.py | 105 +++++
lib/galaxy/webapps/community/model/migrate/migrate.cfg | 20 +
lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py | 101 +++++
lib/galaxy/webapps/community/security/__init__.py | 96 ++++
run_community.sh | 4 +
setup.sh | 1 +
templates/webapps/community/base_panels.mako | 102 +++++
templates/webapps/community/index.mako | 57 ++
templates/webapps/community/message.mako | 1 +
templates/webapps/community/tool/browse_tool.mako | 37 +
templates/webapps/community/tool/grid.mako | 1 +
22 files changed, 1487 insertions(+), 0 deletions(-)
diffs (1587 lines):
diff -r 4c740255b9e7 -r f905e1415dd4 community_wsgi.ini.sample
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/community_wsgi.ini.sample Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,71 @@
+# ---- HTTP Server ----------------------------------------------------------
+
+[server:main]
+
+use = egg:Paste#http
+port = 9009
+host = 127.0.0.1
+use_threadpool = true
+threadpool_workers = 10
+
+# ---- Galaxy Webapps Community Interface -------------------------------------------------
+
+[app:main]
+
+# Specifies the factory for the universe WSGI application
+paste.app_factory = galaxy.webapps.community.buildapp:app_factory
+log_level = DEBUG
+
+# Database connection
+database_file = database/universe.sqlite
+# You may use a SQLAlchemy connection string to specify an external database instead
+#database_connection = postgres:///community_test?host=/var/run/postgresql
+
+# Where dataset files are saved
+file_path = database/files
+# Temporary storage for additional datasets, this should be shared through the cluster
+new_file_path = database/tmp
+
+# Where templates are stored
+template_path = lib/galaxy/webapps/community/templates
+
+# Session support (beaker)
+use_beaker_session = True
+session_type = memory
+session_data_dir = %(here)s/database/beaker_sessions
+session_key = galaxysessions
+session_secret = changethisinproduction
+
+# Galaxy session security
+id_secret = changethisinproductiontoo
+
+# Configuration for debugging middleware
+debug = true
+use_lint = false
+
+# NEVER enable this on a public site (even test or QA)
+# use_interactive = true
+
+# Force everyone to log in (disable anonymous access)
+require_login = False
+
+# path to sendmail
+sendmail_path = /usr/sbin/sendmail
+
+# Write thread status periodically to 'heartbeat.log' (careful, uses disk space rapidly!)
+## use_heartbeat = True
+
+# Profiling middleware (cProfile based)
+## use_profile = True
+
+# Use the new iframe / javascript based layout
+use_new_layout = true
+
+# Serving static files (needed if running standalone)
+static_enabled = True
+static_cache_time = 360
+static_dir = %(here)s/static/
+static_images_dir = %(here)s/static/images
+static_favicon_dir = %(here)s/static/favicon.ico
+static_scripts_dir = %(here)s/static/scripts/
+static_style_dir = %(here)s/static/june_2007_style/blue
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/tags/tag_handler.py
--- a/lib/galaxy/tags/tag_handler.py Wed Apr 14 10:14:43 2010 -0400
+++ b/lib/galaxy/tags/tag_handler.py Wed Apr 14 10:20:32 2010 -0400
@@ -258,3 +258,8 @@
self.item_tag_assoc_info["Visualization"] = ItemTagAssocInfo( model.Visualization,
model.VisualizationTagAssociation,
model.VisualizationTagAssociation.table.c.visualization_id )
+
+class CommunityTagHandler( TagHandler ):
+ def __init__( self ):
+ from galaxy.webapps.community import model
+ TagHandler.__init__( self )
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/__init__.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,3 @@
+"""The Galaxy Reports application."""
+
+from galaxy.web.framework import expose, url_for
\ No newline at end of file
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/app.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/app.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,34 @@
+import sys, config
+import galaxy.webapps.community.model
+from galaxy.web import security
+from galaxy.tags.tag_handler import CommunityTagHandler
+
+class UniverseApplication( object ):
+ """Encapsulates the state of a Universe application"""
+ def __init__( self, **kwargs ):
+ print >> sys.stderr, "python path is: " + ", ".join( sys.path )
+ # Read config file and check for errors
+ self.config = config.Configuration( **kwargs )
+ self.config.check()
+ config.configure_logging( self.config )
+ # Determine the database url
+ if self.config.database_connection:
+ db_url = self.config.database_connection
+ else:
+ db_url = "sqlite://%s?isolation_level=IMMEDIATE" % self.config.database
+ # Initialize database / check for appropriate schema version
+ from galaxy.webapps.community.model.migrate.check import create_or_verify_database
+ create_or_verify_database( db_url, self.config.database_engine_options )
+ # Setup the database engine and ORM
+ from galaxy.webapps.community.model import mapping
+ self.model = mapping.init( self.config.file_path,
+ db_url,
+ self.config.database_engine_options )
+ # Security helper
+ self.security = security.SecurityHelper( id_secret=self.config.id_secret )
+ # Tag handler
+ self.tag_handler = CommunityTagHandler()
+ # Load security policy
+ self.security_agent = self.model.security_agent
+ def shutdown( self ):
+ pass
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/base/controller.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/base/controller.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,24 @@
+"""Contains functionality needed in every webapp interface"""
+import os, time, logging
+# Pieces of Galaxy to make global in every controller
+from galaxy import config, tools, web, util
+from galaxy.web import error, form, url_for
+from galaxy.webapps.community import model
+from galaxy.model.orm import *
+
+from Cheetah.Template import Template
+
+log = logging.getLogger( __name__ )
+
+class BaseController( object ):
+ """Base class for Galaxy webapp application controllers."""
+ def __init__( self, app ):
+ """Initialize an interface for application 'app'"""
+ self.app = app
+ def get_class( self, class_name ):
+ """ Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """
+ if class_name == 'Tool':
+ item_class = model.Tool
+ else:
+ item_class = None
+ return item_class
\ No newline at end of file
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/buildapp.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/buildapp.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,198 @@
+"""
+Provides factory methods to assemble the Galaxy web application
+"""
+
+import logging, atexit
+import os, os.path, sys
+
+from inspect import isclass
+
+from paste.request import parse_formvars
+from paste.util import import_string
+from paste import httpexceptions
+from paste.deploy.converters import asbool
+import pkg_resources
+
+log = logging.getLogger( __name__ )
+
+import config
+import galaxy.webapps.community.model
+import galaxy.webapps.community.model.mapping
+import galaxy.web.framework
+
+def add_controllers( webapp, app ):
+ """
+ Search for controllers in the 'galaxy.webapps.controllers' module and add
+ them to the webapp.
+ """
+ from galaxy.webapps.community.base.controller import BaseController
+ import galaxy.webapps.community.controllers
+ controller_dir = galaxy.webapps.community.controllers.__path__[0]
+ for fname in os.listdir( controller_dir ):
+ if not fname.startswith( "_" ) and fname.endswith( ".py" ):
+ name = fname[:-3]
+ module_name = "galaxy.webapps.community.controllers." + name
+ module = __import__( module_name )
+ for comp in module_name.split( "." )[1:]:
+ module = getattr( module, comp )
+ # Look for a controller inside the modules
+ for key in dir( module ):
+ T = getattr( module, key )
+ if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
+ webapp.add_controller( name, T( app ) )
+ from galaxy.web.base.controller import BaseController
+ import galaxy.web.controllers
+ controller_dir = galaxy.web.controllers.__path__[0]
+ for fname in os.listdir( controller_dir ):
+ # TODO: fix this if we decide to use, we don't need to inspect all controllers...
+ if fname.startswith( 'user' ) and fname.endswith( ".py" ):
+ name = fname[:-3]
+ module_name = "galaxy.web.controllers." + name
+ module = __import__( module_name )
+ for comp in module_name.split( "." )[1:]:
+ module = getattr( module, comp )
+ # Look for a controller inside the modules
+ for key in dir( module ):
+ T = getattr( module, key )
+ if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
+ webapp.add_controller( name, T( app ) )
+
+def app_factory( global_conf, **kwargs ):
+ """Return a wsgi application serving the root object"""
+ # Create the Galaxy application unless passed in
+ if 'app' in kwargs:
+ app = kwargs.pop( 'app' )
+ else:
+ try:
+ from galaxy.webapps.community.app import UniverseApplication
+ app = UniverseApplication( global_conf = global_conf, **kwargs )
+ except:
+ import traceback, sys
+ traceback.print_exc()
+ sys.exit( 1 )
+ atexit.register( app.shutdown )
+ # Create the universe WSGI application
+ webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxycommunitysession' )
+ add_controllers( webapp, app )
+ # These two routes handle our simple needs at the moment
+ webapp.add_route( '/:controller/:action', action='index' )
+ webapp.add_route( '/:action', controller='tool_browser', action='index' )
+ webapp.finalize_config()
+ # Wrap the webapp in some useful middleware
+ if kwargs.get( 'middleware', True ):
+ webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
+ if kwargs.get( 'static_enabled', True ):
+ webapp = wrap_in_static( webapp, global_conf, **kwargs )
+ # Close any pooled database connections before forking
+ try:
+ galaxy.webapps.community.model.mapping.metadata.engine.connection_provider._pool.dispose()
+ except:
+ pass
+ # Return
+ return webapp
+
+def wrap_in_middleware( app, global_conf, **local_conf ):
+ """Based on the configuration wrap `app` in a set of common and useful middleware."""
+ # Merge the global and local configurations
+ conf = global_conf.copy()
+ conf.update(local_conf)
+ debug = asbool( conf.get( 'debug', False ) )
+ # First put into place httpexceptions, which must be most closely
+ # wrapped around the application (it can interact poorly with
+ # other middleware):
+ app = httpexceptions.make_middleware( app, conf )
+ log.debug( "Enabling 'httpexceptions' middleware" )
+ # The recursive middleware allows for including requests in other
+ # requests or forwarding of requests, all on the server side.
+ if asbool(conf.get('use_recursive', True)):
+ from paste import recursive
+ app = recursive.RecursiveMiddleware( app, conf )
+ log.debug( "Enabling 'recursive' middleware" )
+ # Various debug middleware that can only be turned on if the debug
+ # flag is set, either because they are insecure or greatly hurt
+ # performance
+ if debug:
+ # Middleware to check for WSGI compliance
+ if asbool( conf.get( 'use_lint', True ) ):
+ from paste import lint
+ app = lint.make_middleware( app, conf )
+ log.debug( "Enabling 'lint' middleware" )
+ # Middleware to run the python profiler on each request
+ if asbool( conf.get( 'use_profile', False ) ):
+ import profile
+ app = profile.ProfileMiddleware( app, conf )
+ log.debug( "Enabling 'profile' middleware" )
+ # Middleware that intercepts print statements and shows them on the
+ # returned page
+ if asbool( conf.get( 'use_printdebug', True ) ):
+ from paste.debug import prints
+ app = prints.PrintDebugMiddleware( app, conf )
+ log.debug( "Enabling 'print debug' middleware" )
+ if debug and asbool( conf.get( 'use_interactive', False ) ):
+ # Interactive exception debugging, scary dangerous if publicly
+ # accessible, if not enabled we'll use the regular error printing
+ # middleware.
+ pkg_resources.require( "WebError" )
+ from weberror import evalexception
+ app = evalexception.EvalException( app, conf,
+ templating_formatters=build_template_error_formatters() )
+ log.debug( "Enabling 'eval exceptions' middleware" )
+ else:
+ # Not in interactive debug mode, just use the regular error middleware
+ from paste.exceptions import errormiddleware
+ app = errormiddleware.ErrorMiddleware( app, conf )
+ log.debug( "Enabling 'error' middleware" )
+ # Transaction logging (apache access.log style)
+ if asbool( conf.get( 'use_translogger', True ) ):
+ from paste.translogger import TransLogger
+ app = TransLogger( app )
+ log.debug( "Enabling 'trans logger' middleware" )
+ # Config middleware just stores the paste config along with the request,
+ # not sure we need this but useful
+ from paste.deploy.config import ConfigMiddleware
+ app = ConfigMiddleware( app, conf )
+ log.debug( "Enabling 'config' middleware" )
+ # X-Forwarded-Host handling
+ from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware
+ app = XForwardedHostMiddleware( app )
+ log.debug( "Enabling 'x-forwarded-host' middleware" )
+ return app
+
+def wrap_in_static( app, global_conf, **local_conf ):
+ from paste.urlmap import URLMap
+ from galaxy.web.framework.middleware.static import CacheableStaticURLParser as Static
+ urlmap = URLMap()
+ # Merge the global and local configurations
+ conf = global_conf.copy()
+ conf.update(local_conf)
+ # Get cache time in seconds
+ cache_time = conf.get( "static_cache_time", None )
+ if cache_time is not None:
+ cache_time = int( cache_time )
+ # Send to dynamic app by default
+ urlmap["/"] = app
+ # Define static mappings from config
+ urlmap["/static"] = Static( conf.get( "static_dir" ), cache_time )
+ urlmap["/images"] = Static( conf.get( "static_images_dir" ), cache_time )
+ urlmap["/static/scripts"] = Static( conf.get( "static_scripts_dir" ), cache_time )
+ urlmap["/static/style"] = Static( conf.get( "static_style_dir" ), cache_time )
+ urlmap["/favicon.ico"] = Static( conf.get( "static_favicon_dir" ), cache_time )
+ # URL mapper becomes the root webapp
+ return urlmap
+
+def build_template_error_formatters():
+ """
+ Build a list of template error formatters for WebError. When an error
+ occurs, WebError pass the exception to each function in this list until
+ one returns a value, which will be displayed on the error page.
+ """
+ formatters = []
+ # Formatter for mako
+ import mako.exceptions
+ def mako_html_data( exc_value ):
+ if isinstance( exc_value, ( mako.exceptions.CompileException, mako.exceptions.SyntaxException ) ):
+ return mako.exceptions.html_error_template().render( full=False, css=False )
+ if isinstance( exc_value, AttributeError ) and exc_value.args[0].startswith( "'Undefined' object has no attribute" ):
+ return mako.exceptions.html_error_template().render( full=False, css=False )
+ formatters.append( mako_html_data )
+ return formatters
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/config.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/config.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,153 @@
+"""
+Universe configuration builder.
+"""
+
+import sys, os
+import logging, logging.config
+from optparse import OptionParser
+import ConfigParser
+from galaxy.util import string_as_bool
+
+from galaxy import eggs
+import pkg_resources
+
+log = logging.getLogger( __name__ )
+
+def resolve_path( path, root ):
+ """If 'path' is relative make absolute by prepending 'root'"""
+ if not( os.path.isabs( path ) ):
+ path = os.path.join( root, path )
+ return path
+
+class ConfigurationError( Exception ):
+ pass
+
+class Configuration( object ):
+ def __init__( self, **kwargs ):
+ self.config_dict = kwargs
+ self.root = kwargs.get( 'root_dir', '.' )
+ # Collect the umask and primary gid from the environment
+ self.umask = os.umask( 077 ) # get the current umask
+ os.umask( self.umask ) # can't get w/o set, so set it back
+ self.gid = os.getgid() # if running under newgrp(1) we'll need to fix the group of data created on the cluster
+ # Database related configuration
+ self.database = resolve_path( kwargs.get( "database_file", "database/universe.d" ), self.root )
+ self.database_connection = kwargs.get( "database_connection", False )
+ self.database_engine_options = get_database_engine_options( kwargs )
+ self.database_create_tables = string_as_bool( kwargs.get( "database_create_tables", "True" ) )
+ # Where dataset files are stored
+ self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root )
+ self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root )
+ self.cookie_path = kwargs.get( "cookie_path", "/" )
+ self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root )
+ self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" )
+ self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) )
+ self.remote_user_maildomain = kwargs.get( "remote_user_maildomain", None )
+ self.remote_user_logout_href = kwargs.get( "remote_user_logout_href", None )
+ self.require_login = string_as_bool( kwargs.get( "require_login", "False" ) )
+ self.allow_user_creation = string_as_bool( kwargs.get( "allow_user_creation", "True" ) )
+ self.template_path = resolve_path( kwargs.get( "template_path", "templates" ), self.root )
+ self.template_cache = resolve_path( kwargs.get( "template_cache_path", "database/compiled_templates/community" ), self.root )
+ self.admin_users = kwargs.get( "admin_users", "" )
+ self.sendmail_path = kwargs.get('sendmail_path',"/usr/sbin/sendmail")
+ self.mailing_join_addr = kwargs.get('mailing_join_addr',"galaxy-user-join(a)bx.psu.edu")
+ self.error_email_to = kwargs.get( 'error_email_to', None )
+ self.smtp_server = kwargs.get( 'smtp_server', None )
+ self.log_actions = string_as_bool( kwargs.get( 'log_actions', 'False' ) )
+ self.brand = kwargs.get( 'brand', None )
+ self.wiki_url = kwargs.get( 'wiki_url', 'http://g2.trac.bx.psu.edu/' )
+ self.bugs_email = kwargs.get( 'bugs_email', None )
+ self.blog_url = kwargs.get( 'blog_url', None )
+ self.screencasts_url = kwargs.get( 'screencasts_url', None )
+ self.log_events = False
+ self.cloud_controller_instance = False
+ # Parse global_conf and save the parser
+ global_conf = kwargs.get( 'global_conf', None )
+ global_conf_parser = ConfigParser.ConfigParser()
+ self.global_conf_parser = global_conf_parser
+ if global_conf and "__file__" in global_conf:
+ global_conf_parser.read(global_conf['__file__'])
+ def get( self, key, default ):
+ return self.config_dict.get( key, default )
+ def get_bool( self, key, default ):
+ if key in self.config_dict:
+ return string_as_bool( self.config_dict[key] )
+ else:
+ return default
+ def check( self ):
+ # Check that required directories exist
+ for path in self.root, self.file_path, self.template_path:
+ if not os.path.isdir( path ):
+ raise ConfigurationError("Directory does not exist: %s" % path )
+ def is_admin_user( self,user ):
+ """
+ Determine if the provided user is listed in `admin_users`.
+
+ NOTE: This is temporary, admin users will likely be specified in the
+ database in the future.
+ """
+ admin_users = self.get( "admin_users", "" ).split( "," )
+ return ( user is not None and user.email in admin_users )
+
+def get_database_engine_options( kwargs ):
+ """
+ Allow options for the SQLAlchemy database engine to be passed by using
+ the prefix "database_engine_option_".
+ """
+ conversions = {
+ 'convert_unicode': string_as_bool,
+ 'pool_timeout': int,
+ 'echo': string_as_bool,
+ 'echo_pool': string_as_bool,
+ 'pool_recycle': int,
+ 'pool_size': int,
+ 'max_overflow': int,
+ 'pool_threadlocal': string_as_bool,
+ 'server_side_cursors': string_as_bool
+ }
+ prefix = "database_engine_option_"
+ prefix_len = len( prefix )
+ rval = {}
+ for key, value in kwargs.iteritems():
+ if key.startswith( prefix ):
+ key = key[prefix_len:]
+ if key in conversions:
+ value = conversions[key](value)
+ rval[ key ] = value
+ return rval
+
+def configure_logging( config ):
+ """
+ Allow some basic logging configuration to be read from the cherrpy
+ config.
+ """
+ # PasteScript will have already configured the logger if the appropriate
+ # sections were found in the config file, so we do nothing if the
+ # config has a loggers section, otherwise we do some simple setup
+ # using the 'log_*' values from the config.
+ if config.global_conf_parser.has_section( "loggers" ):
+ return
+ format = config.get( "log_format", "%(name)s %(levelname)s %(asctime)s %(message)s" )
+ level = logging._levelNames[ config.get( "log_level", "DEBUG" ) ]
+ destination = config.get( "log_destination", "stdout" )
+ log.info( "Logging at '%s' level to '%s'" % ( level, destination ) )
+ # Get root logger
+ root = logging.getLogger()
+ # Set level
+ root.setLevel( level )
+ # Turn down paste httpserver logging
+ if level <= logging.DEBUG:
+ logging.getLogger( "paste.httpserver.ThreadPool" ).setLevel( logging.WARN )
+ # Remove old handlers
+ for h in root.handlers[:]:
+ root.removeHandler(h)
+ # Create handler
+ if destination == "stdout":
+ handler = logging.StreamHandler( sys.stdout )
+ else:
+ handler = logging.FileHandler( destination )
+ # Create formatter
+ formatter = logging.Formatter( format )
+ # Hook everything up
+ handler.setFormatter( formatter )
+ root.addHandler( handler )
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/controllers/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/controllers/__init__.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,1 @@
+"""Galaxy community space controllers."""
\ No newline at end of file
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/controllers/tool_browser.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/controllers/tool_browser.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,100 @@
+import sys, os, operator, string, shutil, re, socket, urllib, time, logging
+from cgi import escape, FieldStorage
+
+from galaxy.web.base.controller import *
+from galaxy.webapps.community.base.controller import *
+from galaxy.web.framework.helpers import time_ago, iff, grids
+from galaxy.model.orm import *
+
+log = logging.getLogger( __name__ )
+
+# States for passing messages
+SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
+
+class ToolListGrid( grids.Grid ):
+ class NameColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool ):
+ if tool.name:
+ return tool.name
+ return 'not set'
+ class CategoryColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool ):
+ if tool.category:
+ return tool.category
+ return 'not set'
+
+ # Grid definition
+ title = "Tools"
+ model_class = model.Tool
+ template='/webapps/community/tool/grid.mako'
+ default_sort_key = "category"
+ columns = [
+ NameColumn( "Name",
+ key="name",
+ model_class=model.Tool,
+ attach_popup=False,
+ filterable="advanced" ),
+ CategoryColumn( "Category",
+ key="category",
+ model_class=model.Tool,
+ attach_popup=False,
+ filterable="advanced" ),
+ # Columns that are valid for filtering but are not visible.
+ grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ global_actions = [
+ grids.GridAction( "Upload tool", dict( controller='tool_browwser', action='upload' ) )
+ ]
+ operations = [
+ grids.GridOperation( "View versions", condition=( lambda item: not item.deleted ), allow_multiple=False )
+ ]
+ standard_filters = [
+ grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
+ grids.GridColumnFilter( "All", args=dict( deleted='All' ) )
+ ]
+ default_filter = dict( name="All", category="All", deleted="False" )
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+ def build_initial_query( self, session ):
+ return session.query( self.model_class )
+ def apply_default_filter( self, trans, query, **kwargs ):
+ return query.filter( self.model_class.deleted==False )
+
+class ToolBrowserController( BaseController ):
+
+ tool_list_grid = ToolListGrid()
+
+ @web.expose
+ def index( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ return trans.fill_template( '/webapps/community/index.mako', message=message, status=status )
+ @web.expose
+ def browse_tools( self, trans, **kwargs ):
+ if 'operation' in kwargs:
+ operation = kwargs['operation'].lower()
+ if operation == "browse":
+ return trans.response.send_redirect( web.url_for( controller='tool_browser',
+ action='browse_tool',
+ **kwargs ) )
+ # Render the list view
+ return self.tool_list_grid( trans, **kwargs )
+ @web.expose
+ def browse_tool( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ return trans.fill_template( '/webapps/community/tool/browse_tool.mako',
+ tools=tools,
+ message=message,
+ status=status )
+ @web.expose
+ def upload( self, trans, **kwargs ):
+ pass
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/model/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/model/__init__.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,187 @@
+"""
+Galaxy Community Space data model classes
+
+Naming: try to use class names that have a distinct plural form so that
+the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
+"""
+import os.path, os, errno, sys, codecs, operator, tempfile, logging
+from galaxy.util.bunch import Bunch
+from galaxy import util
+from galaxy.util.hash_util import *
+from galaxy.web.form_builder import *
+log = logging.getLogger( __name__ )
+from sqlalchemy.orm import object_session
+
+class User( object ):
+ def __init__( self, email=None, password=None ):
+ self.email = email
+ self.password = password
+ self.external = False
+ self.deleted = False
+ self.purged = False
+ self.username = None
+ # Relationships
+ self.tools = []
+ def set_password_cleartext( self, cleartext ):
+ """Set 'self.password' to the digest of 'cleartext'."""
+ self.password = new_secure_hash( text_type=cleartext )
+ def check_password( self, cleartext ):
+ """Check if 'cleartext' matches 'self.password' when hashed."""
+ return self.password == new_secure_hash( text_type=cleartext )
+
+class GalaxySession( object ):
+ def __init__( self,
+ id=None,
+ user=None,
+ remote_host=None,
+ remote_addr=None,
+ referer=None,
+ current_history=None,
+ session_key=None,
+ is_valid=False,
+ prev_session_id=None ):
+ self.id = id
+ self.user = user
+ self.remote_host = remote_host
+ self.remote_addr = remote_addr
+ self.referer = referer
+ self.current_history = current_history
+ self.session_key = session_key
+ self.is_valid = is_valid
+ self.prev_session_id = prev_session_id
+ self.histories = []
+ def add_history( self, history, association=None ):
+ if association is None:
+ self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
+ else:
+ self.histories.append( association )
+
+class Tool( object ):
+ def __init__( self, guid=None, name=None, description=None, category=None, version=None, user_id=None, external_filename=None ):
+ self.guid = guid
+ self.name = name or "Unnamed tool"
+ self.description = description
+ self.category = category
+ self.version = version or "1.0.0"
+ self.user_id = user_id
+ self.external_filename = external_filename
+
+class Job( object ):
+ """
+ A job represents a request to run a tool given input datasets, tool
+ parameters, and output datasets.
+ """
+ states = Bunch( NEW = 'new',
+ UPLOAD = 'upload',
+ WAITING = 'waiting',
+ QUEUED = 'queued',
+ RUNNING = 'running',
+ OK = 'ok',
+ ERROR = 'error',
+ DELETED = 'deleted' )
+ def __init__( self ):
+ self.session_id = None
+ self.tool_id = None
+ self.tool_version = None
+ self.command_line = None
+ self.param_filename = None
+ self.parameters = []
+ self.input_datasets = []
+ self.output_datasets = []
+ self.output_library_datasets = []
+ self.state = Job.states.NEW
+ self.info = None
+ self.job_runner_name = None
+ self.job_runner_external_id = None
+ def add_parameter( self, name, value ):
+ self.parameters.append( JobParameter( name, value ) )
+ def add_input_dataset( self, name, dataset ):
+ self.input_datasets.append( JobToInputDatasetAssociation( name, dataset ) )
+ def add_output_dataset( self, name, dataset ):
+ self.output_datasets.append( JobToOutputDatasetAssociation( name, dataset ) )
+ def add_output_library_dataset( self, name, dataset ):
+ self.output_library_datasets.append( JobToOutputLibraryDatasetAssociation( name, dataset ) )
+ def set_state( self, state ):
+ self.state = state
+ # For historical reasons state propogates down to datasets
+ for da in self.output_datasets:
+ da.dataset.state = state
+ def get_param_values( self, app ):
+ """
+ Read encoded parameter values from the database and turn back into a
+ dict of tool parameter values.
+ """
+ param_dict = dict( [ ( p.name, p.value ) for p in self.parameters ] )
+ tool = app.toolbox.tools_by_id[self.tool_id]
+ param_dict = tool.params_from_strings( param_dict, app )
+ return param_dict
+ def check_if_output_datasets_deleted( self ):
+ """
+ Return true if all of the output datasets associated with this job are
+ in the deleted state
+ """
+ for dataset_assoc in self.output_datasets:
+ dataset = dataset_assoc.dataset
+ # only the originator of the job can delete a dataset to cause
+ # cancellation of the job, no need to loop through history_associations
+ if not dataset.deleted:
+ return False
+ return True
+ def mark_deleted( self ):
+ """
+ Mark this job as deleted, and mark any output datasets as discarded.
+ """
+ self.state = Job.states.DELETED
+ self.info = "Job output deleted by user before job completed."
+ for dataset_assoc in self.output_datasets:
+ dataset = dataset_assoc.dataset
+ dataset.deleted = True
+ dataset.state = dataset.states.DISCARDED
+ for dataset in dataset.dataset.history_associations:
+ # propagate info across shared datasets
+ dataset.deleted = True
+ dataset.blurb = 'deleted'
+ dataset.peek = 'Job deleted'
+ dataset.info = 'Job output deleted by user before job completed'
+
+class Tag ( object ):
+ def __init__( self, id=None, type=None, parent_id=None, name=None ):
+ self.id = id
+ self.type = type
+ self.parent_id = parent_id
+ self.name = name
+ def __str__ ( self ):
+ return "Tag(id=%s, type=%i, parent_id=%s, name=%s)" % ( self.id, self.type, self.parent_id, self.name )
+
+class ItemTagAssociation ( object ):
+ def __init__( self, id=None, user=None, item_id=None, tag_id=None, user_tname=None, value=None ):
+ self.id = id
+ self.user = user
+ self.item_id = item_id
+ self.tag_id = tag_id
+ self.user_tname = user_tname
+ self.value = None
+ self.user_value = None
+
+class ToolTagAssociation ( ItemTagAssociation ):
+ pass
+
+class ToolAnnotationAssociation( object ):
+ pass
+
+## ---- Utility methods -------------------------------------------------------
+
+def directory_hash_id( id ):
+ s = str( id )
+ l = len( s )
+ # Shortcut -- ids 0-999 go under ../000/
+ if l < 4:
+ return [ "000" ]
+ # Pad with zeros until a multiple of three
+ padded = ( ( 3 - len( s ) % 3 ) * "0" ) + s
+ # Drop the last three digits -- 1000 files per directory
+ padded = padded[:-3]
+ # Break into chunks of three
+ return [ padded[i*3:(i+1)*3] for i in range( len( padded ) // 3 ) ]
+
+
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/model/mapping.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/model/mapping.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,186 @@
+"""
+Details of how the data model objects are mapped onto the relational database
+are encapsulated here.
+"""
+import logging
+log = logging.getLogger( __name__ )
+
+import sys
+import datetime
+
+from galaxy.webapps.community.model import *
+from galaxy.model.orm import *
+from galaxy.model.orm.ext.assignmapper import *
+from galaxy.model.custom_types import *
+from galaxy.util.bunch import Bunch
+from galaxy.webapps.community.security import CommunityRBACAgent
+from sqlalchemy.orm.collections import attribute_mapped_collection
+from sqlalchemy.ext.associationproxy import association_proxy
+
+metadata = MetaData()
+context = Session = scoped_session( sessionmaker( autoflush=False, autocommit=True ) )
+
+# For backward compatibility with "context.current"
+context.current = Session
+
+dialect_to_egg = {
+ "sqlite" : "pysqlite>=2",
+ "postgres" : "psycopg2",
+ "mysql" : "MySQL_python"
+}
+
+# NOTE REGARDING TIMESTAMPS:
+# It is currently difficult to have the timestamps calculated by the
+# database in a portable way, so we're doing it in the client. This
+# also saves us from needing to postfetch on postgres. HOWEVER: it
+# relies on the client's clock being set correctly, so if clustering
+# web servers, use a time server to ensure synchronization
+
+# Return the current time in UTC without any timezone information
+now = datetime.datetime.utcnow
+
+User.table = Table( "galaxy_user", metadata,
+ Column( "id", Integer, primary_key=True),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "email", TrimmedString( 255 ), nullable=False ),
+ Column( "username", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "password", TrimmedString( 40 ), nullable=False ),
+ Column( "external", Boolean, default=False ),
+ Column( "deleted", Boolean, index=True, default=False ),
+ Column( "purged", Boolean, index=True, default=False ) )
+
+GalaxySession.table = Table( "galaxy_session", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=True ),
+ Column( "remote_host", String( 255 ) ),
+ Column( "remote_addr", String( 255 ) ),
+ Column( "referer", TEXT ),
+ Column( "session_key", TrimmedString( 255 ), index=True, unique=True ), # unique 128 bit random number coerced to a string
+ Column( "is_valid", Boolean, default=False ),
+ Column( "prev_session_id", Integer ) # saves a reference to the previous session so we have a way to chain them together
+ )
+
+Tool.table = Table( "tool", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "guid", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "description" , TEXT ),
+ Column( "category", TrimmedString( 255 ), index=True ),
+ Column( "version", TrimmedString( 255 ) ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "external_filename" , TEXT ),
+ Column( "deleted", Boolean, default=False ) )
+
+Job.table = Table( "job", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "state", String( 64 ), index=True ),
+ Column( "info", TrimmedString( 255 ) ),
+ Column( "command_line", TEXT ),
+ Column( "param_filename", String( 1024 ) ),
+ Column( "runner_name", String( 255 ) ),
+ Column( "stdout", TEXT ),
+ Column( "stderr", TEXT ),
+ Column( "traceback", TEXT ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True, nullable=True ),
+ Column( "job_runner_name", String( 255 ) ),
+ Column( "job_runner_external_id", String( 255 ) ) )
+
+Tag.table = Table( "tag", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "type", Integer ),
+ Column( "parent_id", Integer, ForeignKey( "tag.id" ) ),
+ Column( "name", TrimmedString(255) ),
+ UniqueConstraint( "name" ) )
+
+ToolTagAssociation.table = Table( "tool_tag_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
+ToolAnnotationAssociation.table = Table( "tool_annotation_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "annotation", TEXT, index=True) )
+
+# With the tables defined we can define the mappers and setup the
+# relationships between the model objects.
+assign_mapper( context, User, User.table,
+ properties=dict( tools=relation( Tool, order_by=desc( Tool.table.c.update_time ) ),
+ active_tools=relation( Tool, primaryjoin=( ( Tool.table.c.user_id == User.table.c.id ) & ( not_( Tool.table.c.deleted ) ) ), order_by=desc( Tool.table.c.update_time ) ),
+ galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ) ) )
+
+assign_mapper( context, GalaxySession, GalaxySession.table,
+ properties=dict( user=relation( User.mapper ) ) )
+
+assign_mapper( context, Job, Job.table,
+ properties=dict( galaxy_session=relation( GalaxySession ),
+ tool=relation( Tool ) ) )
+
+assign_mapper( context, Tag, Tag.table,
+ properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[Tag.table.c.id] ) ) ) )
+
+assign_mapper( context, ToolTagAssociation, ToolTagAssociation.table,
+ properties=dict( tag=relation(Tag, backref="tagged_tools"), user=relation( User ) ) )
+
+assign_mapper( context, ToolAnnotationAssociation, ToolAnnotationAssociation.table,
+ properties=dict( tool=relation( Tool ), user=relation( User ) ) )
+
+assign_mapper( context, Tool, Tool.table,
+ properties = dict( user=relation( User.mapper ) ) )
+
+def guess_dialect_for_url( url ):
+ return (url.split(':', 1))[0]
+
+def load_egg_for_url( url ):
+ # Load the appropriate db module
+ dialect = guess_dialect_for_url( url )
+ try:
+ egg = dialect_to_egg[dialect]
+ try:
+ pkg_resources.require( egg )
+ log.debug( "%s egg successfully loaded for %s dialect" % ( egg, dialect ) )
+ except:
+ # If the module's in the path elsewhere (i.e. non-egg), it'll still load.
+ log.warning( "%s egg not found, but an attempt will be made to use %s anyway" % ( egg, dialect ) )
+ except KeyError:
+ # Let this go, it could possibly work with db's we don't support
+ log.error( "database_connection contains an unknown SQLAlchemy database dialect: %s" % dialect )
+
+def init( file_path, url, engine_options={}, create_tables=False ):
+ """Connect mappings to the database"""
+ log.debug("###In init, file_path: %s" % str( file_path ))
+ # Connect dataset to the file path
+ Tool.file_path = file_path
+ # Load the appropriate db module
+ load_egg_for_url( url )
+ # Create the database engine
+ engine = create_engine( url, **engine_options )
+ # Connect the metadata to the database.
+ metadata.bind = engine
+ # Clear any existing contextual sessions and reconfigure
+ Session.remove()
+ Session.configure( bind=engine )
+ # Create tables if needed
+ if create_tables:
+ metadata.create_all()
+ # Pack everything into a bunch
+ result = Bunch( **globals() )
+ result.engine = engine
+ result.session = Session
+ result.create_tables = create_tables
+ #load local galaxy security policy
+ result.security_agent = CommunityRBACAgent( result )
+ return result
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/model/migrate/check.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/model/migrate/check.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,105 @@
+import sys, os.path, logging
+
+from galaxy import eggs
+
+import pkg_resources
+pkg_resources.require( "sqlalchemy-migrate" )
+
+from migrate.versioning import repository, schema
+from sqlalchemy import *
+from sqlalchemy.exc import NoSuchTableError
+
+log = logging.getLogger( __name__ )
+
+# path relative to galaxy
+migrate_repository_directory = os.path.dirname( __file__ ).replace( os.getcwd() + os.path.sep, '', 1 )
+migrate_repository = repository.Repository( migrate_repository_directory )
+dialect_to_egg = {
+ "sqlite" : "pysqlite>=2",
+ "postgres" : "psycopg2",
+ "mysql" : "MySQL_python"
+}
+
+def create_or_verify_database( url, engine_options={} ):
+ """
+ Check that the database is use-able, possibly creating it if empty (this is
+ the only time we automatically create tables, otherwise we force the
+ user to do it using the management script so they can create backups).
+
+ 1) Empty database --> initialize with latest version and return
+ 2) Database older than migration support --> fail and require manual update
+ 3) Database at state where migrate support introduced --> add version control information but make no changes (might still require manual update)
+ 4) Database versioned but out of date --> fail with informative message, user must run "sh manage_db.sh upgrade"
+
+ """
+ dialect = ( url.split( ':', 1 ) )[0]
+ try:
+ egg = dialect_to_egg[dialect]
+ try:
+ pkg_resources.require( egg )
+ log.debug( "%s egg successfully loaded for %s dialect" % ( egg, dialect ) )
+ except:
+ # If the module is in the path elsewhere (i.e. non-egg), it'll still load.
+ log.warning( "%s egg not found, but an attempt will be made to use %s anyway" % ( egg, dialect ) )
+ except KeyError:
+ # Let this go, it could possibly work with db's we don't support
+ log.error( "database_connection contains an unknown SQLAlchemy database dialect: %s" % dialect )
+ # Create engine and metadata
+ engine = create_engine( url, **engine_options )
+ meta = MetaData( bind=engine )
+ # Try to load dataset table
+ try:
+ galaxy_user_table = Table( "galaxy_user", meta, autoload=True )
+ except NoSuchTableError:
+ # No 'galaxy_user' table means a completely uninitialized database, which
+ # is fine, init the database in a versioned state
+ log.info( "No database, initializing" )
+ # Database might or might not be versioned
+ try:
+ # Declare the database to be under a repository's version control
+ db_schema = schema.ControlledSchema.create( engine, migrate_repository )
+ except:
+ # The database is already under version control
+ db_schema = schema.ControlledSchema( engine, migrate_repository )
+ # Apply all scripts to get to current version
+ migrate_to_current_version( engine, db_schema )
+ return
+ try:
+ version_table = Table( "migrate_version", meta, autoload=True )
+ except NoSuchTableError:
+ # The database exists but is not yet under migrate version control, so init with version 1
+ log.info( "Adding version control to existing database" )
+ try:
+ metadata_file_table = Table( "metadata_file", meta, autoload=True )
+ schema.ControlledSchema.create( engine, migrate_repository, version=2 )
+ except NoSuchTableError:
+ schema.ControlledSchema.create( engine, migrate_repository, version=1 )
+ # Verify that the code and the DB are in sync
+ db_schema = schema.ControlledSchema( engine, migrate_repository )
+ if migrate_repository.versions.latest != db_schema.version:
+ raise Exception( "Your database has version '%d' but this code expects version '%d'. Please backup your database and then migrate the schema by running 'sh manage_db.sh upgrade'."
+ % ( db_schema.version, migrate_repository.versions.latest ) )
+ else:
+ log.info( "At database version %d" % db_schema.version )
+
+def migrate_to_current_version( engine, schema ):
+ # Changes to get to current version
+ changeset = schema.changeset( None )
+ for ver, change in changeset:
+ nextver = ver + changeset.step
+ log.info( 'Migrating %s -> %s... ' % ( ver, nextver ) )
+ old_stdout = sys.stdout
+ class FakeStdout( object ):
+ def __init__( self ):
+ self.buffer = []
+ def write( self, s ):
+ self.buffer.append( s )
+ def flush( self ):
+ pass
+ sys.stdout = FakeStdout()
+ try:
+ schema.runchange( ver, change, changeset.step )
+ finally:
+ for message in "".join( sys.stdout.buffer ).split( "\n" ):
+ log.info( message )
+ sys.stdout = old_stdout
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/model/migrate/migrate.cfg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/model/migrate/migrate.cfg Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,20 @@
+[db_settings]
+# Used to identify which repository this database is versioned under.
+# You can use the name of your project.
+repository_id=Galaxy
+
+# The name of the database table used to track the schema version.
+# This name shouldn't already be used by your project.
+# If this is changed once a database is under version control, you'll need to
+# change the table name in each database too.
+version_table=migrate_version
+
+# When committing a change script, Migrate will attempt to generate the
+# sql for all supported databases; normally, if one of them fails - probably
+# because you don't have that database installed - it is ignored and the
+# commit continues, perhaps ending successfully.
+# Databases in this list MUST compile successfully during a commit, or the
+# entire commit will fail. List the databases your application will actually
+# be using to ensure your updates to that database work properly.
+# This must be a list; example: ['postgres','sqlite']
+required_dbs=[]
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/model/migrate/versions/0001_initial_tables.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,101 @@
+"""
+Migration script to create initial tables.
+"""
+
+from sqlalchemy import *
+from migrate import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+
+User.table = Table( "galaxy_user", metadata,
+ Column( "id", Integer, primary_key=True),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "email", TrimmedString( 255 ), nullable=False ),
+ Column( "username", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "password", TrimmedString( 40 ), nullable=False ),
+ Column( "external", Boolean, default=False ),
+ Column( "deleted", Boolean, index=True, default=False ),
+ Column( "purged", Boolean, index=True, default=False ) )
+
+GalaxySession.table = Table( "galaxy_session", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=True ),
+ Column( "remote_host", String( 255 ) ),
+ Column( "remote_addr", String( 255 ) ),
+ Column( "referer", TEXT ),
+ Column( "session_key", TrimmedString( 255 ), index=True, unique=True ), # unique 128 bit random number coerced to a string
+ Column( "is_valid", Boolean, default=False ),
+ Column( "prev_session_id", Integer ) # saves a reference to the previous session so we have a way to chain them together
+ )
+
+Tool.table = Table( "tool", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "guid", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", TrimmedString( 255 ), index=True, unique=True ),
+ Column( "description" , TEXT ),
+ Column( "category", TrimmedString( 255 ), index=True ),
+ Column( "version", TrimmedString( 255 ) ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "external_filename" , TEXT ),
+ Column( "deleted", Boolean, default=False ) )
+
+Job.table = Table( "job", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "state", String( 64 ), index=True ),
+ Column( "info", TrimmedString( 255 ) ),
+ Column( "command_line", TEXT ),
+ Column( "param_filename", String( 1024 ) ),
+ Column( "runner_name", String( 255 ) ),
+ Column( "stdout", TEXT ),
+ Column( "stderr", TEXT ),
+ Column( "traceback", TEXT ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True, nullable=True ),
+ Column( "job_runner_name", String( 255 ) ),
+ Column( "job_runner_external_id", String( 255 ) ) )
+
+Tag.table = Table( "tag", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "type", Integer ),
+ Column( "parent_id", Integer, ForeignKey( "tag.id" ) ),
+ Column( "name", TrimmedString(255) ),
+ UniqueConstraint( "name" ) )
+
+ToolTagAssociation.table = Table( "tool_tag_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
+ToolAnnotationAssociation.table = Table( "tool_annotation_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "tool_id", Integer, ForeignKey( "tool.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "annotation", TEXT, index=True) )
+
+def upgrade():
+ print __doc__
+ metadata.create_all()
+
+def downgrade():
+ # Operations to reverse the above upgrade go here.
+ pass
diff -r 4c740255b9e7 -r f905e1415dd4 lib/galaxy/webapps/community/security/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/webapps/community/security/__init__.py Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,96 @@
+"""
+Galaxy Community Space Security
+"""
+import logging, socket, operator
+from datetime import datetime, timedelta
+from galaxy.util.bunch import Bunch
+from galaxy.util import listify
+from galaxy.model.orm import *
+
+log = logging.getLogger(__name__)
+
+class Action( object ):
+ def __init__( self, action, description, model ):
+ self.action = action
+ self.description = description
+ self.model = model
+
+class RBACAgent:
+ """Class that handles galaxy community space security"""
+ permitted_actions = Bunch()
+ def get_action( self, name, default=None ):
+ """Get a permitted action by its dict key or action name"""
+ for k, v in self.permitted_actions.items():
+ if k == name or v.action == name:
+ return v
+ return default
+ def get_actions( self ):
+ """Get all permitted actions as a list of Action objects"""
+ return self.permitted_actions.__dict__.values()
+ def get_item_actions( self, action, item ):
+ raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
+ def create_private_user_role( self, user ):
+ raise "Unimplemented Method"
+ def get_private_user_role( self, user ):
+ raise "Unimplemented Method"
+ def convert_permitted_action_strings( self, permitted_action_strings ):
+ """
+ When getting permitted actions from an untrusted source like a
+ form, ensure that they match our actual permitted actions.
+ """
+ return filter( lambda x: x is not None, [ self.permitted_actions.get( action_string ) for action_string in permitted_action_strings ] )
+
+class CommunityRBACAgent( RBACAgent ):
+ def __init__( self, model, permitted_actions=None ):
+ self.model = model
+ if permitted_actions:
+ self.permitted_actions = permitted_actions
+ @property
+ def sa_session( self ):
+ """Returns a SQLAlchemy session"""
+ return self.model.context
+
+ def allow_action( self, roles, action, item ):
+ """
+ Method for checking a permission for the current user ( based on roles ) to perform a
+ specific action on an item
+ """
+ item_actions = self.get_item_actions( action, item )
+ if not item_actions:
+ return action.model == 'restrict'
+ ret_val = False
+ for item_action in item_actions:
+ if item_action.role in roles:
+ ret_val = True
+ break
+ return ret_val
+ def get_item_actions( self, action, item ):
+ # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
+ return [ permission for permission in item.actions if permission.action == action.action ]
+ def create_private_user_role( self, user ):
+ # Create private role
+ role = self.model.Role( name=user.email, description='Private Role for ' + user.email, type=self.model.Role.types.PRIVATE )
+ self.sa_session.add( role )
+ self.sa_session.flush()
+ # Add user to role
+ self.associate_components( role=role, user=user )
+ return role
+ def get_private_user_role( self, user, auto_create=False ):
+ role = self.sa_session.query( self.model.Role ) \
+ .filter( and_( self.model.Role.table.c.name == user.email,
+ self.model.Role.table.c.type == self.model.Role.types.PRIVATE ) ) \
+ .first()
+ if not role:
+ if auto_create:
+ return self.create_private_user_role( user )
+ else:
+ return None
+ return role
+
+def get_permitted_actions( filter=None ):
+ '''Utility method to return a subset of RBACAgent's permitted actions'''
+ if filter is None:
+ return RBACAgent.permitted_actions
+ tmp_bunch = Bunch()
+ [ tmp_bunch.__dict__.__setitem__(k, v) for k, v in RBACAgent.permitted_actions.items() if k.startswith( filter ) ]
+ return tmp_bunch
diff -r 4c740255b9e7 -r f905e1415dd4 run_community.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/run_community.sh Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cd `dirname $0`
+python ./scripts/paster.py serve community_wsgi.ini --pid-file=community_webapp.pid --log-file=community_webapp.log $@
diff -r 4c740255b9e7 -r f905e1415dd4 setup.sh
--- a/setup.sh Wed Apr 14 10:14:43 2010 -0400
+++ b/setup.sh Wed Apr 14 10:20:32 2010 -0400
@@ -31,6 +31,7 @@
DIRS="
database
database/files
+database/tools
database/tmp
database/compiled_templates
database/job_working_directory
diff -r 4c740255b9e7 -r f905e1415dd4 templates/webapps/community/base_panels.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/webapps/community/base_panels.mako Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,102 @@
+<%inherit file="/base_panels.mako"/>
+
+## Default title
+<%def name="title()">Galaxy Community Space</%def>
+
+## Masthead
+<%def name="masthead()">
+
+ ## Tab area, fills entire width
+ <div style="position: absolute; top: 0; left: 0; width: 100%; text-align: center">
+
+ <table class="tab-group" border="0" cellspacing="0" style="margin: auto;">
+ <tr>
+
+ <%def name="tab( id, display, href, target='_parent', visible=True, extra_class='' )">
+ <%
+ cls = "tab"
+ if extra_class:
+ cls += " " + extra_class
+ if self.active_view == id:
+ cls += " active"
+ style = ""
+ if not visible:
+ style = "display: none;"
+ %>
+ <td class="${cls}" style="${style}"><a target="${target}" href="${href}">${display}</a></td>
+ </%def>
+
+ ${tab( "admin", "Admin", h.url_for( controller='/webapps/community/admin', action='index' ), extra_class="admin-only", visible=( trans.user and app.config.is_admin_user( trans.user ) ) )}
+
+ <td class="tab">
+ <a>Help</a>
+ <div class="submenu">
+ <ul>
+ <li><a href="${app.config.get( "bugs_email", "mailto:galaxy-bugs@bx.psu.edu" )}">Email comments, bug reports, or suggestions</a></li>
+ <li><a target="_blank" href="${app.config.get( "wiki_url", "http://bitbucket.org/galaxy/galaxy-central/wiki" )}">Galaxy Wiki</a></li>
+ <li><a target="_blank" href="${app.config.get( "screencasts_url", "http://galaxycast.org" )}">Video tutorials (screencasts)</a></li>
+ <li><a target="_blank" href="${app.config.get( "citation_url", "http://bitbucket.org/galaxy/galaxy-central/wiki/Citations" )}">How to Cite Galaxy</a></li>
+ </ul>
+ </div>
+ </td>
+
+ ## User tab.
+ <%
+ cls = "tab"
+ if self.active_view == 'user':
+ cls += " active"
+ %>
+ <td class="${cls}">
+ <a>User</a>
+ <%
+ if trans.user:
+ user_email = trans.user.email
+ style1 = "display: none;"
+ style2 = "";
+ else:
+ user_email = ""
+ style1 = ""
+ style2 = "display: none;"
+ %>
+ <div class="submenu">
+ <ul class="loggedout-only" style="${style1}">
+ <li><a href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login</a></li>
+ %if app.config.allow_user_creation:
+ <li><a href="${h.url_for( controller='/user', action='create', webapp='community' )}">Register</a></li>
+ %endif
+ </ul>
+ <ul class="loggedin-only" style="${style2}">
+ %if app.config.use_remote_user:
+ %if app.config.remote_user_logout_href:
+ <li><a href="${app.config.remote_user_logout_href}" target="_top">Logout</a></li>
+ %endif
+ %else:
+ <li>Logged in as <span id="user-email">${user_email}</span></li>
+ <li><a target="galaxy_main" href="${h.url_for( controller='/user', action='index', webapp='community' )}">Preferences</a></li>
+ <%
+ if app.config.require_login:
+ logout_url = h.url_for( controller='/root', action='index', webapp='community', m_c='user', m_a='logout' )
+ else:
+ logout_url = h.url_for( controller='/user', action='logout', webapp='community' )
+ %>
+ <li><a target="_top" href="${logout_url}">Logout</a></li>
+ %endif
+ </ul>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ ## Logo, layered over tabs to be clickable
+ <div class="title" style="position: absolute; top: 0; left: 0;">
+ <a href="${app.config.get( 'logo_url', '/' )}">
+ <img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}" style="width: 26px; vertical-align: top;">
+ Galaxy
+ %if app.config.brand:
+ <span class='brand'>/ ${app.config.brand}</span>
+ %endif
+ </a>
+ </div>
+
+</%def>
diff -r 4c740255b9e7 -r f905e1415dd4 templates/webapps/community/index.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/webapps/community/index.mako Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,57 @@
+<%inherit file="/webapps/community/base_panels.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<%def name="init()">
+ <%
+ self.has_left_panel=True
+ self.has_right_panel=False
+ self.active_view="tools"
+ %>
+ %if trans.app.config.require_login and not trans.user:
+ <script type="text/javascript">
+ if ( window != top ) {
+ top.location.href = location.href;
+ }
+ </script>
+ %endif
+</%def>
+
+<%def name="left_panel()">
+ <div class="unified-panel-header" unselectable="on">
+ <div class='unified-panel-header-inner'>Community</div>
+ </div>
+ <div class="page-container" style="padding: 10px;">
+ <div class="toolMenu">
+ <div class="toolSectionList">
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ <span>Tools</span>
+ </div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='tool_browser', action='browse_tools' )}" target="galaxy_main">Browse tools</a></div>
+ </div>
+ </div>
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ <span>Forum</span>
+ </div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ <div class="toolTitle"><a href="${h.url_for( controller='forum', action='browse_forums' )}" target="galaxy_main">Forums</a></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</%def>
+
+<%def name="center_panel()">
+ <%
+ if trans.app.config.require_login and not trans.user:
+ center_url = h.url_for( controller='user', action='login', message=message, status=status )
+ else:
+ center_url = h.url_for( controller='tool_browser', action='browse_tools', message=message, status=status )
+ %>
+ <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"> </iframe>
+</%def>
diff -r 4c740255b9e7 -r f905e1415dd4 templates/webapps/community/message.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/webapps/community/message.mako Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,1 @@
+<%inherit file="/message.mako"/>
diff -r 4c740255b9e7 -r f905e1415dd4 templates/webapps/community/tool/browse_tool.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/webapps/community/tool/browse_tool.mako Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,37 @@
+<%namespace file="/message.mako" import="render_msg" />
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="title()">Browse Tool</%def>
+
+<h2>Galaxy Tool</h2>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+%if not tools:
+ There are no tools
+%else:
+ <table class="grid">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="formRow id="toolRow">
+ <td><a href="${h.url_for( controller='tool_browser', action='browse', id=trans.security.encode_id( tool.id ) )}">${tool.name}</a></td>
+ <td>${tool.description}</td>
+ </tr>
+ </tbody>
+ </table>
+%endif
diff -r 4c740255b9e7 -r f905e1415dd4 templates/webapps/community/tool/grid.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/webapps/community/tool/grid.mako Wed Apr 14 10:20:32 2010 -0400
@@ -0,0 +1,1 @@
+<%inherit file="/grid_base.mako"/>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/4c740255b9e7
changeset: 3646:4c740255b9e7
user: Nate Coraor <nate(a)bx.psu.edu>
date: Wed Apr 14 10:14:43 2010 -0400
description:
Remove the outdated "Revision" file
diffstat:
Revision | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
diffs (15 lines):
diff -r 46a391f2d696 -r 4c740255b9e7 Revision
--- a/Revision Wed Apr 14 10:14:26 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Path: .
-URL: svn+ssh://coltrane.bx.psu.edu/depot/projects/universe/svnroot/galaxy/trunk
-Repository UUID: 9bcadc22-80f8-0310-8a53-c8f022958886
-Revision: 1349
-Node Kind: directory
-Schedule: normal
-Last Changed Author: jbhe
-Last Changed Rev: 1349
-Last Changed Date: 2007-02-08 15:12:40 -0500 (Thu, 08 Feb 2007)
-Properties Last Updated: 2007-01-31 22:47:34 -0500 (Wed, 31 Jan 2007)
-
1
0