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

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/d776beca95f8
changeset: 3536:d776beca95f8
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Tue Mar 16 12:00:10 2010 -0400
description:
Fixes to item embedding in pages. In particular, fixed the editor color changes that were occurring when moving the cursor through embedded items.
diffstat:
static/june_2007_style/blue/embed_item.css | 16 ++++++++++------
static/june_2007_style/embed_item.css.tmpl | 25 ++++++++++++++++++++++++-
static/wymeditor/iframe/galaxy/wymiframe.css | 12 +++++++++---
templates/embed_base.mako | 2 +-
templates/page/editor.mako | 11 ++++++-----
templates/workflow/embed.mako | 1 +
6 files changed, 51 insertions(+), 16 deletions(-)
diffs (177 lines):
diff -r 15fd40238cef -r d776beca95f8 static/june_2007_style/blue/embed_item.css
--- a/static/june_2007_style/blue/embed_item.css Tue Mar 16 09:50:13 2010 -0400
+++ b/static/june_2007_style/blue/embed_item.css Tue Mar 16 12:00:10 2010 -0400
@@ -1,10 +1,14 @@
-.embedded-item{margin-left:auto;margin-right:auto;width:90%;padding: 0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;}
-.embedded-item.history{background-color:#C1C9E5}
-.embedded-item.dataset{background-color:#CFC}
-.embedded-item.workflow{background-color:#EBD9B2}
+.embedded-item{margin-left:auto;margin-right:auto;width:90%;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;}
+.embedded-item.display {padding: 0.5em;}
+.embedded-item.history{background-color:#C1C9E5}
+.embedded-item.history p{background:#C1C9E5 no-repeat 2px 2px;margin-top:0;margin-bottom:0;}
+.embedded-item.dataset{background-color:#CFC}
+.embedded-item.dataset p{background:#CFC no-repeat 2px 2px;margin-top:0;margin-bottom:0;}
+.embedded-item.workflow{background-color:#EBD9B2}
+.embedded-item.workflow p{background:#EBD9B2 no-repeat 2px 2px;margin-top:0;margin-bottom:0;}
.embedded-item.placeholder{}
-.embedded-item .item-content{max-height:25em;overflow:auto;}
-.embedded-item .title{vertical-align:top;text-align:center;}
+.embedded-item .item-content{max-height:25em;overflow:auto;display:none;}
+.embedded-item .title{vertical-align:top;text-align:center;font-weight:bold;}
.embedded-item.placeholder .content{padding: 1em 1em;font-style:italic;text-align:center;}
table.annotated-item{width:100%;border-collapse:collapse;}
table.annotated-item td,th{padding:0;}
diff -r 15fd40238cef -r d776beca95f8 static/june_2007_style/embed_item.css.tmpl
--- a/static/june_2007_style/embed_item.css.tmpl Tue Mar 16 09:50:13 2010 -0400
+++ b/static/june_2007_style/embed_item.css.tmpl Tue Mar 16 12:00:10 2010 -0400
@@ -1,35 +1,58 @@
+
.embedded-item {
margin-left:auto;
margin-right:auto;
width:90%;
- padding: 0.5em;
-moz-border-radius:0.5em;
-webkit-border-radius:0.5em;
border-radius:0.5em;
}
+.embedded-item.display {
+ padding: 0.5em;
+}
+
.embedded-item.history {
background-color:#C1C9E5
}
+.embedded-item.history p {
+ background:#C1C9E5 no-repeat 2px 2px;
+ margin-top:0;
+ margin-bottom:0;
+}
+
.embedded-item.dataset {
background-color:#CFC
}
+.embedded-item.dataset p {
+ background:#CFC no-repeat 2px 2px;
+ margin-top:0;margin-bottom:0;
+}
+
.embedded-item.workflow {
background-color:#EBD9B2
}
+.embedded-item.workflow p {
+ background:#EBD9B2 no-repeat 2px 2px;
+ margin-top:0;
+ margin-bottom:0;
+}
+
.embedded-item.placeholder{}
.embedded-item .item-content {
max-height: 25em;
overflow: auto;
+ display: none;
}
.embedded-item .title {
vertical-align:top;
text-align:center;
+ font-weight: bold;
}
.embedded-item.placeholder .content {
diff -r 15fd40238cef -r d776beca95f8 static/wymeditor/iframe/galaxy/wymiframe.css
--- a/static/wymeditor/iframe/galaxy/wymiframe.css Tue Mar 16 09:50:13 2010 -0400
+++ b/static/wymeditor/iframe/galaxy/wymiframe.css Tue Mar 16 12:00:10 2010 -0400
@@ -1,3 +1,7 @@
+/*
+ * JG: edited to remove '!important' from rules so that embedded Galaxy items can have unique background colors.
+ */
+
/*
* WYMeditor : what you see is What You Mean web-based editor
* Copyright (c) 2005 - 2009 Jean-Francois Hovinne, http://www.wymeditor.org/
@@ -33,9 +37,9 @@
ol,
table,
blockquote,
- pre { background: #FFFFFF no-repeat 2px 2px !important;
- padding:8px 5px 5px !important;
- margin:10px !important; }
+ pre { background: #FFFFFF no-repeat 2px 2px; /* JG removed: !important */
+ padding:8px 5px 5px; /* JG removed: !important */
+ margin:10px} /* JG removed: !important */
td { background: #F0F4F8; }
th { background: #ffffcc; }
ul,
@@ -52,6 +56,7 @@
td { height: 1.6em; }
/* labels */
+/* JG commented out:
p { background-image: url(lbl-p.png); }
h1 { background-image: url(lbl-h1.png); }
h2 { background-image: url(lbl-h2.png); }
@@ -61,6 +66,7 @@
h6 { background-image: url(lbl-h6.png); }
blockquote{ background-image: url(lbl-blockquote.png); }
pre { background-image: url(lbl-pre.png); }
+*/
/* specific HTML elements */
caption { text-align: left; }
diff -r 15fd40238cef -r d776beca95f8 templates/embed_base.mako
--- a/templates/embed_base.mako Tue Mar 16 09:50:13 2010 -0400
+++ b/templates/embed_base.mako Tue Mar 16 12:00:10 2010 -0400
@@ -6,7 +6,7 @@
<%namespace file="/display_common.mako" import="*" />
## HTML structure.
-<div class='embedded-item ${get_class_display_name( item.__class__ ).lower()}'>
+<div class='embedded-item display ${get_class_display_name( item.__class__ ).lower()}'>
<div class='title'>
${self.render_title( item )}
<hr/>
diff -r 15fd40238cef -r d776beca95f8 templates/page/editor.mako
--- a/templates/page/editor.mako Tue Mar 16 09:50:13 2010 -0400
+++ b/templates/page/editor.mako Tue Mar 16 12:00:10 2010 -0400
@@ -459,17 +459,18 @@
// all non-standard attributes when it returns its content (e.g. it will not return an element attribute of the form
// item_class='History').
var item_embed_html =
- "<p> \
+ "\
<div id='" + item_info.iclass + "-" + item_id + "' class='embedded-item " + item_info.singular.toLowerCase() +
" placeholder'> \
- <div class='title'> Embedded Galaxy " + item_info.singular + " '" + item_name + "'</div> \
- <div class='content'> \
+ <p class='title'>Embedded Galaxy " + item_info.singular + " '" + item_name + "'</p> \
+ <p class='content'> \
[Do not edit this block; Galaxy will fill it in with the annotated " +
item_info.singular.toLowerCase() + " when it is displayed.]</div> \
- </div> \
- </div></p>";
+ </p> \
+ </div><p></p>";
// Insert embedded representation into document.
+ // TODO: maybe try replace() instead to handle indenting?
wym.insert(item_embed_html);
});
hide_modal();
diff -r 15fd40238cef -r d776beca95f8 templates/workflow/embed.mako
--- a/templates/workflow/embed.mako Tue Mar 16 09:50:13 2010 -0400
+++ b/templates/workflow/embed.mako Tue Mar 16 12:00:10 2010 -0400
@@ -4,6 +4,7 @@
%>
<%def name="render_summary_content( workflow, steps )">
+
## <ul>
## <% num_steps = len ( steps ) %>
## <li>${num_steps} step${iff( num_steps != 1, "s", "" )}
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/447c059a096a
changeset: 3534:447c059a096a
user: Nate Coraor <nate(a)bx.psu.edu>
date: Mon Mar 15 15:06:14 2010 -0400
description:
Fix a bug in removing conflicts from the eggs directory
diffstat:
lib/galaxy/eggs/__init__.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diffs (21 lines):
diff -r ac60740712de -r 447c059a096a lib/galaxy/eggs/__init__.py
--- a/lib/galaxy/eggs/__init__.py Mon Mar 15 14:35:35 2010 -0400
+++ b/lib/galaxy/eggs/__init__.py Mon Mar 15 15:06:14 2010 -0400
@@ -2,7 +2,7 @@
Manage Galaxy eggs
"""
-import os, sys, glob, urllib, urllib2, ConfigParser, HTMLParser, zipimport, zipfile
+import os, sys, shutil, glob, urllib, urllib2, ConfigParser, HTMLParser, zipimport, zipfile
import logging
log = logging.getLogger( __name__ )
@@ -281,7 +281,7 @@
for egg in eggs:
try:
egg.resolve()
- except:
+ except EggNotFetchable:
missing.append( egg )
if missing:
raise EggNotFetchable( missing )
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/ac60740712de
changeset: 3533:ac60740712de
user: Nate Coraor <nate(a)bx.psu.edu>
date: Mon Mar 15 14:35:35 2010 -0400
description:
Add numpy egg, update bx_python egg (now with 100% more numpy) and include code that allows scrambling to depend on other eggs existing and being importable.
diffstat:
eggs.ini | 6 +-
lib/galaxy/eggs/dist.py | 5 +
lib/galaxy/eggs/scramble.py | 12 ++-
lib/pkg_resources.py | 148 ++++++++++++++++++++++------------
scripts/dist-scramble.py | 13 +++
scripts/scramble.py | 12 ++-
scripts/scramble/lib/scramble_lib.py | 36 +++-----
scripts/scramble/scripts/generic.py | 1 +
scripts/test_dist_egg.py | 53 ++++++++++++
9 files changed, 207 insertions(+), 79 deletions(-)
diffs (592 lines):
diff -r cfb0776875c0 -r ac60740712de eggs.ini
--- a/eggs.ini Mon Mar 15 14:05:25 2010 -0400
+++ b/eggs.ini Mon Mar 15 14:35:35 2010 -0400
@@ -16,6 +16,7 @@
Cheetah = 2.2.2
DRMAA_python = 0.2
MySQL_python = 1.2.3c1
+numpy = 1.3.0
pbs_python = 2.9.4
psycopg2 = 2.0.13
pycrypto = 2.0.1
@@ -59,7 +60,7 @@
psycopg2 = _8.4.2_static
pysqlite = _3.6.17_static
MySQL_python = _5.1.41_static
-bx_python = _dev_3b9d30e47619
+bx_python = _dev_f74aec067563
GeneTrack = _dev_48da9e998f0caf01c5be731e926f4b0481f658f0
SQLAlchemy = _dev_r6498
pysam = _kanwei_90e03180969d
@@ -70,3 +71,6 @@
MySQL_python = mysql-5.1.41
psycopg2 = postgresql-8.4.2
pysqlite = sqlite-amalgamation-3_6_17
+
+[dependencies]
+bx_python = numpy
diff -r cfb0776875c0 -r ac60740712de lib/galaxy/eggs/dist.py
--- a/lib/galaxy/eggs/dist.py Mon Mar 15 14:05:25 2010 -0400
+++ b/lib/galaxy/eggs/dist.py Mon Mar 15 14:35:35 2010 -0400
@@ -72,6 +72,10 @@
sources = self.config.get( 'source', name ).split()
except:
sources = []
+ try:
+ dependencies = self.config.get( 'dependencies', name ).split()
+ except:
+ dependencies = []
if full_platform:
platforms = self.platforms
else:
@@ -83,4 +87,5 @@
host_info = self.hosts[platform].split()
egg.build_host, egg.python = host_info[:2]
egg.sources = sources
+ egg.dependencies = dependencies
self.eggs[name].append( egg )
diff -r cfb0776875c0 -r ac60740712de lib/galaxy/eggs/scramble.py
--- a/lib/galaxy/eggs/scramble.py Mon Mar 15 14:05:25 2010 -0400
+++ b/lib/galaxy/eggs/scramble.py Mon Mar 15 14:35:35 2010 -0400
@@ -3,7 +3,7 @@
"""
import os, sys, shutil, tempfile, subprocess, urlparse, urllib
-from __init__ import Egg, Crate, URLRetriever, galaxy_dir, py, unpack_zipfile
+from __init__ import Egg, Crate, URLRetriever, galaxy_dir, py, unpack_zipfile, EggNotFetchable
from distutils.sysconfig import get_config_var
import tarfile, zipfile, zlib
@@ -37,6 +37,7 @@
def __init__( self, *args, **kwargs ):
Egg.__init__( self, *args, **kwargs )
self.sources = []
+ self.dependencies = []
self.buildpath = None
self.source_path = None
self.py = py
@@ -184,6 +185,11 @@
tagfile = open( os.path.join( self.buildpath, ".galaxy_tag" ), "w" )
tagfile.write( self.tag + '\n' )
tagfile.close()
+ if self.dependencies:
+ depfile = open( os.path.join( self.buildpath, ".galaxy_deps" ), "w" )
+ for dependency in self.dependencies:
+ depfile.write( dependency + '\n' )
+ depfile.close()
def run_scramble_script( self ):
log.warning( "%s(): Beginning build" % sys._getframe().f_code.co_name )
# subprocessed to sterilize the env
@@ -211,6 +217,10 @@
egg.sources = self.config.get( "source", egg.name ).split()
except:
egg.sources = []
+ try:
+ egg.dependencies = self.config.get( "dependencies", egg.name ).split()
+ except:
+ egg.dependencies = []
def parse_egg_section( self, *args, **kwargs ):
kwargs['egg_class'] = ScrambleEgg
Crate.parse_egg_section( self, *args, **kwargs )
diff -r cfb0776875c0 -r ac60740712de lib/pkg_resources.py
--- a/lib/pkg_resources.py Mon Mar 15 14:05:25 2010 -0400
+++ b/lib/pkg_resources.py Mon Mar 15 14:35:35 2010 -0400
@@ -13,26 +13,67 @@
method.
"""
-import sys, os, zipimport, time, re, imp, new
+import sys, os, zipimport, time, re, imp
try:
frozenset
except NameError:
from sets import ImmutableSet as frozenset
-from os import utime, rename, unlink # capture these to bypass sandboxing
+# capture these to bypass sandboxing
+from os import utime, rename, unlink, mkdir
from os import open as os_open
-
-
-
-
-
-
-
-
-
-
-
+from os.path import isdir, split
+
+
+def _bypass_ensure_directory(name, mode=0777):
+ # Sandbox-bypassing version of ensure_directory()
+ dirname, filename = split(name)
+ if dirname and filename and not isdir(dirname):
+ _bypass_ensure_directory(dirname)
+ mkdir(dirname, mode)
+
+
+
+
+
+
+
+_state_vars = {}
+
+def _declare_state(vartype, **kw):
+ g = globals()
+ for name, val in kw.iteritems():
+ g[name] = val
+ _state_vars[name] = vartype
+
+def __getstate__():
+ state = {}
+ g = globals()
+ for k, v in _state_vars.iteritems():
+ state[k] = g['_sget_'+v](g[k])
+ return state
+
+def __setstate__(state):
+ g = globals()
+ for k, v in state.iteritems():
+ g['_sset_'+_state_vars[k]](k, g[k], v)
+ return state
+
+def _sget_dict(val):
+ return val.copy()
+
+def _sset_dict(key, ob, state):
+ ob.clear()
+ ob.update(state)
+
+def _sget_object(val):
+ return val.__getstate__()
+
+def _sset_object(key, ob, state):
+ ob.__setstate__(state)
+
+_sget_none = _sset_none = lambda *args: None
@@ -164,14 +205,8 @@
def _macosx_vers(_cache=[]):
if not _cache:
- info = os.popen('/usr/bin/sw_vers').read().splitlines()
- for line in info:
- key, value = line.split(None, 1)
- if key == 'ProductVersion:':
- _cache.append(value.strip().split("."))
- break
- else:
- raise ValueError, "What?!"
+ from platform import mac_ver
+ _cache.append(mac_ver()[0].split('.'))
return _cache[0]
def _macosx_arch(machine):
@@ -203,6 +238,12 @@
+
+
+
+
+
+
def compatible_platforms(provided,required):
"""Can code for the `provided` platform run on the `required` platform?
@@ -387,7 +428,7 @@
def add_entry(self, entry):
"""Add a path item to ``.entries``, finding any distributions on it
- ``find_distributions(entry,False)`` is used to find distributions
+ ``find_distributions(entry, True)`` is used to find distributions
corresponding to the path entry, and they are added. `entry` is
always appended to ``.entries``, even if it is already present.
(This is because ``sys.path`` can contain the same value more than
@@ -622,7 +663,6 @@
activated to fulfill the requirements; all relevant distributions are
included, even if they were already activated in this working set.
"""
-
needed = self.resolve(parse_requirements(requirements))
for dist in needed:
@@ -630,7 +670,6 @@
return needed
-
def subscribe(self, callback):
"""Invoke `callback` for all distributions (including existing ones)"""
if callback in self.callbacks:
@@ -639,19 +678,21 @@
for dist in self:
callback(dist)
-
def _added_new(self, dist):
for callback in self.callbacks:
callback(dist)
-
-
-
-
-
-
-
-
+ def __getstate__(self):
+ return (
+ self.entries[:], self.entry_keys.copy(), self.by_key.copy(),
+ self.callbacks[:]
+ )
+
+ def __setstate__(self, (entries, keys, by_key, callbacks)):
+ self.entries = entries[:]
+ self.entry_keys = keys.copy()
+ self.by_key = by_key.copy()
+ self.callbacks = callbacks[:]
class Environment(object):
@@ -916,7 +957,7 @@
extract_path = self.extraction_path or get_default_cache()
target_path = os.path.join(extract_path, archive_name+'-tmp', *names)
try:
- ensure_directory(target_path)
+ _bypass_ensure_directory(target_path)
except:
self.extraction_error()
@@ -1188,7 +1229,9 @@
)
def _fn(self, base, resource_name):
- return os.path.join(base, *resource_name.split('/'))
+ if resource_name:
+ return os.path.join(base, *resource_name.split('/'))
+ return base
def _get(self, path):
if hasattr(self.loader, 'get_data'):
@@ -1226,8 +1269,6 @@
-
-
class DefaultProvider(EggProvider):
"""Provides access to package resources in the filesystem"""
@@ -1597,7 +1638,7 @@
-_distribution_finders = {}
+_declare_state('dict', _distribution_finders = {})
def register_finder(importer_type, distribution_finder):
"""Register `distribution_finder` to find distributions in sys.path items
@@ -1646,7 +1687,7 @@
"""Yield distributions accessible on a sys.path directory"""
path_item = _normalize_cached(path_item)
- if os.path.isdir(path_item):
+ if os.path.isdir(path_item) and os.access(path_item, os.R_OK):
if path_item.lower().endswith('.egg'):
# unpacked egg
yield Distribution.from_filename(
@@ -1679,8 +1720,8 @@
break
register_finder(ImpWrapper,find_on_path)
-_namespace_handlers = {}
-_namespace_packages = {}
+_declare_state('dict', _namespace_handlers = {})
+_declare_state('dict', _namespace_packages = {})
def register_namespace_handler(importer_type, namespace_handler):
"""Register `namespace_handler` to declare namespace packages
@@ -1709,7 +1750,7 @@
return None
module = sys.modules.get(packageName)
if module is None:
- module = sys.modules[packageName] = new.module(packageName)
+ module = sys.modules[packageName] = imp.new_module(packageName)
module.__path__ = []; _set_parent_ns(packageName)
elif not hasattr(module,'__path__'):
raise TypeError("Not a package:", packageName)
@@ -1862,7 +1903,7 @@
The algorithm assumes that strings like "-" and any alpha string that
alphabetically follows "final" represents a "patch level". So, "2.4-1"
is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
- considered newer than "2.4-1", whic in turn is newer than "2.4".
+ considered newer than "2.4-1", which in turn is newer than "2.4".
Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
come before "final" alphabetically) are assumed to be pre-release versions,
@@ -1871,7 +1912,8 @@
Finally, to handle miscellaneous cases, the strings "pre", "preview", and
"rc" are treated as if they were "c", i.e. as though they were release
candidates, and therefore are not as new as a version string that does not
- contain them.
+ contain them, and "dev" is replaced with an '@' so that it sorts lower than
+ than any other pre-release tag.
"""
parts = []
for part in _parse_version_parts(s.lower()):
@@ -2219,12 +2261,9 @@
if not loc:
return
- if path is sys.path:
- self.check_version_conflict()
-
nloc = _normalize_cached(loc)
bdir = os.path.dirname(nloc)
- npath= map(_normalize_cached, path)
+ npath= [(p and _normalize_cached(p) or p) for p in path]
bp = None
for p, item in enumerate(npath):
@@ -2232,10 +2271,14 @@
break
elif item==bdir and self.precedence==EGG_DIST:
# if it's an .egg, give it precedence over its directory
+ if path is sys.path:
+ self.check_version_conflict()
path.insert(p, loc)
npath.insert(p, nloc)
break
else:
+ if path is sys.path:
+ self.check_version_conflict()
path.append(loc)
return
@@ -2252,7 +2295,6 @@
return
-
def check_version_conflict(self):
if self.key=='setuptools':
return # ignore the inevitable setuptools self-conflicts :(
@@ -2266,7 +2308,7 @@
continue
fn = getattr(sys.modules[modname], '__file__', None)
- if fn and normalize_path(fn).startswith(loc):
+ if fn and (normalize_path(fn).startswith(loc) or fn.startswith(loc)):
continue
issue_warning(
"Module %s was already imported from %s, but %s is being added"
@@ -2443,7 +2485,7 @@
def __contains__(self,item):
if isinstance(item,Distribution):
- if item.key <> self.key: return False
+ if item.key != self.key: return False
if self.index: item = item.parsed_version # only get if we need it
elif isinstance(item,basestring):
item = parse_version(item)
@@ -2540,7 +2582,7 @@
os.open = old_open # and then put it back
-# Set up global resource manager
+# Set up global resource manager (deliberately not state-saved)
_manager = ResourceManager()
def _initialize(g):
for name in dir(_manager):
@@ -2549,7 +2591,7 @@
_initialize(globals())
# Prepare the master working set and make the ``require()`` API available
-working_set = WorkingSet()
+_declare_state('object', working_set = WorkingSet())
try:
# Does the main program list any requirements?
from __main__ import __requires__
diff -r cfb0776875c0 -r ac60740712de scripts/dist-scramble.py
--- a/scripts/dist-scramble.py Mon Mar 15 14:05:25 2010 -0400
+++ b/scripts/dist-scramble.py Mon Mar 15 14:35:35 2010 -0400
@@ -32,6 +32,19 @@
failed = []
for egg in eggs:
try:
+ for dependency in egg.dependencies:
+ print "Checking %s dependency: %s" % ( egg.name, dependency )
+ # this could be in a better data structure...
+ dep = filter( lambda x: x.platform == egg.platform, c[dependency] )[0]
+ dep.resolve()
+ except EggNotFetchable, e:
+ degg = e.eggs[0]
+ print "%s build dependency %s %s %s couldn't be" % ( egg.name, degg.name, degg.version, degg.platform )
+ print "downloaded automatically. There isn't really a graceful"
+ print "way to handle this when dist-scrambling."
+ failed.append( egg.platform )
+ continue
+ try:
egg.scramble()
except ScrambleFailure:
failed.append( egg.platform )
diff -r cfb0776875c0 -r ac60740712de scripts/scramble.py
--- a/scripts/scramble.py Mon Mar 15 14:05:25 2010 -0400
+++ b/scripts/scramble.py Mon Mar 15 14:35:35 2010 -0400
@@ -14,7 +14,7 @@
lib = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "..", "lib" ) )
sys.path.append( lib )
-from galaxy.eggs.scramble import ScrambleCrate, ScrambleFailure
+from galaxy.eggs.scramble import ScrambleCrate, ScrambleFailure, EggNotFetchable
c = ScrambleCrate()
@@ -31,6 +31,16 @@
except:
print "error: %s not in eggs.ini" % name
sys.exit( 1 )
+ for dependency in egg.dependencies:
+ print "Checking %s dependency: %s" % ( egg.name, dependency )
+ try:
+ c[dependency].require()
+ except EggNotFetchable, e:
+ degg = e.eggs[0]
+ print "%s build dependency %s %s couldn't be downloaded" % ( egg.name, degg.name, degg.version )
+ print "automatically. You can try building it by hand with:"
+ print " python scripts/scramble.py %s" % degg.name
+ sys.exit( 1 )
egg.scramble()
sys.exit( 0 )
except ScrambleFailure, e:
diff -r cfb0776875c0 -r ac60740712de scripts/scramble/lib/scramble_lib.py
--- a/scripts/scramble/lib/scramble_lib.py Mon Mar 15 14:05:25 2010 -0400
+++ b/scripts/scramble/lib/scramble_lib.py Mon Mar 15 14:35:35 2010 -0400
@@ -21,6 +21,15 @@
except:
return None
+def get_deps():
+ try:
+ depf = open( '.galaxy_deps', 'r' )
+ except:
+ return []
+ c = eggs.Crate()
+ for dep in depf:
+ c[dep.strip()].require()
+
def clean( extra_dirs=[] ):
for dir in [ 'build', 'dist' ] + extra_dirs:
try:
@@ -127,29 +136,10 @@
else:
return 'gcc'
-# Monkeypatch pkg_resources for better ABI recognition
-def _get_platform():
- plat = distutils.util._get_platform()
- if sys.version_info[:2] == ( 2, 5 ) and \
- ( ( os.uname()[-1] in ( 'i386', 'ppc' ) and sys.platform == 'darwin' and os.path.abspath( sys.prefix ).startswith( '/System' ) ) or \
- ( sys.platform == 'darwin' and get_config_vars().get('UNIVERSALSDK', '').strip() ) ):
- plat = 'macosx-10.3-fat'
- if sys.platform == "sunos5" and not (plat.endswith('_32') or plat.endswith('_64')):
- if sys.maxint > 2**31:
- plat += '_64'
- else:
- plat += '_32'
- if not (plat.endswith('-ucs2') or plat.endswith('-ucs4')):
- if sys.maxunicode > 2**16:
- plat += '-ucs4'
- else:
- plat += '-ucs2'
- return plat
-try:
- assert distutil.util._get_platform
-except:
- distutils.util._get_platform = distutils.util.get_platform
- distutils.util.get_platform = _get_platform
+# get galaxy eggs lib
+galaxy_lib = os.path.abspath( os.path.join( os.path.dirname( __file__ ), '..', '..', '..', 'lib' ) )
+sys.path.insert( 0, galaxy_lib )
+from galaxy import eggs
# get setuptools
from ez_setup import use_setuptools
diff -r cfb0776875c0 -r ac60740712de scripts/scramble/scripts/generic.py
--- a/scripts/scramble/scripts/generic.py Mon Mar 15 14:05:25 2010 -0400
+++ b/scripts/scramble/scripts/generic.py Mon Mar 15 14:35:35 2010 -0400
@@ -9,6 +9,7 @@
from scramble_lib import *
tag = get_tag() # get the tag
+get_deps() # require any dependent eggs
clean() # clean up any existing stuff (could happen if you run scramble.py by hand)
# reset args for distutils
diff -r cfb0776875c0 -r ac60740712de scripts/test_dist_egg.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/test_dist_egg.py Mon Mar 15 14:35:35 2010 -0400
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+"""
+A crude script for minimal "testing" of dist eggs (require and import). It may
+not work on all zipped eggs. It may be easiest to just customize this script
+for whatever egg you want to test.
+
+usage: test_dist_egg.py <egg_name>
+"""
+import os, sys, logging, subprocess
+
+try:
+ assert sys.argv[1]
+except:
+ print __doc__
+ sys.exit( 1 )
+
+lib = os.path.abspath( os.path.join( os.path.dirname( __file__ ), '..', 'lib' ) )
+sys.path.insert( 0, lib )
+
+if sys.argv[1].endswith( '.egg' ):
+
+ egg = sys.argv[1]
+ egg_name = os.path.basename( egg ).split( '-' )[0]
+ sys.path.insert( 0, egg )
+
+ import pkg_resources
+ pkg_resources.require( egg_name )
+ provider = pkg_resources.get_provider( egg_name )
+ importables = provider.get_metadata('top_level.txt').splitlines()
+
+ for importable in importables:
+ mod = __import__( importable )
+ assert os.path.dirname( mod.__path__[0] ) == os.path.dirname( provider.module_path )
+ print "OK"
+
+ sys.exit( 0 )
+
+else:
+
+ build_dir = os.path.join( os.path.dirname( os.path.abspath( __file__ ) ), 'scramble', 'build' )
+ if os.path.exists( build_dir ):
+ raise Exception( 'Build dir must be removed before testing: %s' % build_dir )
+
+ name = sys.argv[1]
+
+ from galaxy.eggs.dist import DistScrambleCrate
+
+ c = DistScrambleCrate()
+
+ for egg in c[name]:
+ print 'Checking %s %s for %s on %s' % ( name, egg.version, egg.platform, egg.build_host )
+ p = subprocess.Popen( 'ssh %s %s %s %s %s' % ( egg.build_host, egg.python, os.path.abspath( __file__ ), egg.distribution.location, egg.platform ), shell=True )
+ p.wait()
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/cfb0776875c0
changeset: 3532:cfb0776875c0
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Mon Mar 15 14:05:25 2010 -0400
description:
Fix migration script's default value for 'deleted' column in visualization table. Because visualizations are not in use yet, effects are small, and manual fix is easy, it's not necessary to use another migration script to fix this problem. Fix, then, is largely for reference purposes.
diffstat:
lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diffs (15 lines):
diff -r 3c124a19ae94 -r cfb0776875c0 lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py
--- a/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py Mon Mar 15 12:40:30 2010 -0400
+++ b/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py Mon Mar 15 14:05:25 2010 -0400
@@ -54,10 +54,8 @@
log.debug( "Creating visualization_user_share_association table failed: %s" % str( e ) )
# Get default boolean value 'false' so that columns can be initialized.
- if migrate_engine.name == 'mysql':
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
default_false = "0"
- elif migrate_engine.name == 'sqlite':
- default_false = "'false'"
elif migrate_engine.name == 'postgres':
default_false = "false"
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/3c124a19ae94
changeset: 3531:3c124a19ae94
user: rc
date: Mon Mar 15 12:40:30 2010 -0400
description:
lims: automatic update of sample state when the state is changed in th db (using scanner etc)
diffstat:
lib/galaxy/web/controllers/requests_admin.py | 21 ++++++
templates/admin/requests/show_request.mako | 87 ++++++++++++++++++++++++---
templates/requests/sample_datasets.mako | 7 ++
templates/requests/sample_state.mako | 5 +
4 files changed, 109 insertions(+), 11 deletions(-)
diffs (175 lines):
diff -r 6d079d53f9db -r 3c124a19ae94 lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Mon Mar 15 11:31:14 2010 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Mon Mar 15 12:40:30 2010 -0400
@@ -231,6 +231,27 @@
def index( self, trans ):
return trans.fill_template( "/admin/requests/index.mako" )
+ @web.json
+ def sample_state_updates( self, trans, ids=None, states=None ):
+ # Avoid caching
+ trans.response.headers['Pragma'] = 'no-cache'
+ trans.response.headers['Expires'] = '0'
+ # Create new HTML for any that have changed
+ rval = {}
+ if ids is not None and states is not None:
+ ids = map( int, ids.split( "," ) )
+ states = states.split( "," )
+ for id, state in zip( ids, states ):
+ sample = trans.sa_session.query( self.app.model.Sample ).get( id )
+ if sample.current_state().name != state:
+ rval[id] = {
+ "state": sample.current_state().name,
+ "datasets": len(sample.dataset_files),
+ "html_state": unicode( trans.fill_template( "requests/sample_state.mako", sample=sample ), 'utf-8' ),
+ "html_datasets": unicode( trans.fill_template( "requests/sample_datasets.mako", trans=trans, sample=sample ), 'utf-8' )
+ }
+ return rval
+
@web.expose
@web.require_admin
def list( self, trans, **kwd ):
diff -r 6d079d53f9db -r 3c124a19ae94 templates/admin/requests/show_request.mako
--- a/templates/admin/requests/show_request.mako Mon Mar 15 11:31:14 2010 -0400
+++ b/templates/admin/requests/show_request.mako Mon Mar 15 12:40:30 2010 -0400
@@ -1,5 +1,7 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/requests/sample_state.mako" import="render_sample_state" />
+<%namespace file="/requests/sample_datasets.mako" import="render_sample_datasets" />
%if msg:
${render_msg( msg, messagetype )}
@@ -42,6 +44,54 @@
});
</script>
+<script type="text/javascript">
+ // Looks for changes in sample states using an async request. Keeps
+ // calling itself (via setTimeout) until all samples are in a terminal
+ // state.
+ var updater = function ( sample_states ) {
+ // Check if there are any items left to track
+ var empty = true;
+ for ( i in sample_states ) {
+ empty = false;
+ break;
+ }
+ if ( ! empty ) {
+ setTimeout( function() { updater_callback( sample_states ) }, 1000 );
+ }
+ };
+ var updater_callback = function ( sample_states ) {
+ // Build request data
+ var ids = []
+ var states = []
+ $.each( sample_states, function ( id, state ) {
+ ids.push( id );
+ states.push( state );
+ });
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='requests_admin', action='sample_state_updates' )}",
+ dataType: "json",
+ data: { ids: ids.join( "," ), states: states.join( "," ) },
+ success : function ( data ) {
+ $.each( data, function( id, val ) {
+ // Replace HTML
+ var cell1 = $("#sampleState-" + id);
+ cell1.html( val.html_state );
+ var cell2 = $("#sampleDatasets-" + id);
+ cell2.html( val.html_datasets );
+ sample_states[ parseInt(id) ] = val.state;
+ });
+ updater( sample_states );
+ },
+ error: function() {
+ // Just retry, like the old method, should try to be smarter
+ updater( sample_states );
+ }
+ });
+ };
+</script>
+
<style type="text/css">
.msg_head {
padding: 0px 0px;
@@ -162,15 +212,21 @@
%if sample_index in range(len(request.samples)):
<td>${info['name']}</td>
<td>${info['barcode']}</td>
- <td>
- %if sample:
- %if sample.request.unsubmitted():
- Unsubmitted
- %else:
- <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
- %endif
- %endif
- </td>
+ %if sample.request.unsubmitted():
+ <td>Unsubmitted</td>
+ %else:
+ <td id="sampleState-${sample.id}">${render_sample_state( sample )}</td>
+ %endif
+
+## <td>
+## %if sample:
+## %if sample.request.unsubmitted():
+## Unsubmitted
+## %else:
+## <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
+## %endif
+## %endif
+## </td>
%if info['library']:
<td><a href="${h.url_for( controller='library_common', action='browse_library', cntrller='library', id=trans.security.encode_id( info['library'].id ) )}">${info['library'].name}</a></td>
%else:
@@ -182,8 +238,9 @@
<td></td>
%endif
%if request.submitted() or request.complete():
- <td>
- <a href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">${len(sample.dataset_files)}</a>
+ <td id="sampleDatasets-${sample.id}">
+ ${render_sample_datasets( sample )}
+## <a href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">${len(sample.dataset_files)}</a>
</td>
%endif
@@ -358,6 +415,14 @@
<label>There are no samples.</label>
%endif
</div>
+
+ %if request.samples and request.submitted():
+ <script type="text/javascript">
+ // Updater
+ updater({${ ",".join( [ '"%s" : "%s"' % ( s.id, s.current_state().name ) for s in request.samples ] ) }});
+ </script>
+ %endif
+
%if edit_mode == 'False':
<table class="grid">
<tbody>
diff -r 6d079d53f9db -r 3c124a19ae94 templates/requests/sample_datasets.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/requests/sample_datasets.mako Mon Mar 15 12:40:30 2010 -0400
@@ -0,0 +1,7 @@
+<%def name="render_sample_datasets( sample )">
+ <a href="${h.url_for(controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id))}">${sample.transferred_dataset_files()}</a>
+</%def>
+
+
+
+${render_sample_datasets( sample )}
diff -r 6d079d53f9db -r 3c124a19ae94 templates/requests/sample_state.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/requests/sample_state.mako Mon Mar 15 12:40:30 2010 -0400
@@ -0,0 +1,5 @@
+<%def name="render_sample_state( sample )">
+ <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
+</%def>
+
+${render_sample_state( sample )}
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/6d079d53f9db
changeset: 3530:6d079d53f9db
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Mon Mar 15 11:31:14 2010 -0400
description:
Add functionality for inline editing of dataset tags and annotation in history panel (icons are currently opposite save/rerun icons). Various style and template fixes as well.
diffstat:
lib/galaxy/web/base/controller.py | 11 +-
lib/galaxy/web/controllers/dataset.py | 31 ++++-
lib/galaxy/web/controllers/page.py | 2 +-
lib/galaxy/web/controllers/tag.py | 19 ++-
lib/galaxy/web/framework/helpers/grids.py | 4 +-
static/june_2007_style/autocomplete_tagging.css.tmpl | 5 +
static/june_2007_style/base.css.tmpl | 9 +-
static/june_2007_style/blue/autocomplete_tagging.css | 3 +-
static/june_2007_style/blue/base.css | 3 +-
templates/dataset/display.mako | 2 +-
templates/dataset/embed.mako | 6 +-
templates/display_base.mako | 2 +-
templates/embed_base.mako | 20 ++-
templates/grid_base_async.mako | 2 +-
templates/root/history.mako | 110 ++++++++++++++++--
templates/root/history_common.mako | 18 ++-
templates/tagging_common.mako | 6 +-
17 files changed, 203 insertions(+), 50 deletions(-)
diffs (553 lines):
diff -r 96ec861b4b6e -r 6d079d53f9db lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py Sun Mar 14 11:49:44 2010 -0400
+++ b/lib/galaxy/web/base/controller.py Mon Mar 15 11:31:14 2010 -0400
@@ -62,7 +62,7 @@
def get_item_annotation_obj( self, db_session, user, item ):
""" Returns a user's annotation object for an item. """
- # Get annotation association. TODO: we could replace this eval() with a long if/else stmt, but this is more general without sacrificing
+ # Get annotation association.
try:
annotation_assoc_class = eval( "model.%sAnnotationAssociation" % item.__class__.__name__ )
except:
@@ -126,7 +126,7 @@
class UsesHistoryDatasetAssociation:
""" Mixin for controllers that use HistoryDatasetAssociation objects. """
- def get_dataset( self, trans, dataset_id, check_accessible=True ):
+ def get_dataset( self, trans, dataset_id, check_ownership=True, check_accessible=False ):
""" Get an HDA object by id. """
# DEPRECATION: We still support unencoded ids for backward compatibility
try:
@@ -136,6 +136,13 @@
data = trans.sa_session.query( model.HistoryDatasetAssociation ).get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) )
+ if check_ownership:
+ # Verify ownership.
+ user = trans.get_user()
+ if not user:
+ error( "Must be logged in to manage Galaxy items" )
+ if data.history.user != user:
+ error( "%s is not owned by current user" % data.__class__.__name__ )
if check_accessible:
current_user_roles = trans.get_current_user_roles()
if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ):
diff -r 96ec861b4b6e -r 6d079d53f9db lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Sun Mar 14 11:49:44 2010 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Mon Mar 15 11:31:14 2010 -0400
@@ -5,6 +5,7 @@
from galaxy import util, datatypes, jobs, web, model
from cgi import escape, FieldStorage
from galaxy.datatypes.display_applications.util import encode_dataset_user, decode_dataset_user
+from galaxy.util.sanitize_html import sanitize_html
from email.MIMEText import MIMEText
import pkg_resources;
@@ -444,16 +445,14 @@
@web.require_login( "use Galaxy datasets" )
def get_name_and_link_async( self, trans, id=None ):
""" Returns dataset's name and link. """
- dataset = self.get_dataset( trans, id )
+ dataset = self.get_dataset( trans, id, False, True )
return_dict = { "name" : dataset.name, "link" : url_for( action="display_by_username_and_slug", username=dataset.history.user.username, slug=trans.security.encode_id( dataset.id ) ) }
return return_dict
@web.expose
def get_embed_html_async( self, trans, id ):
""" Returns HTML for embedding a dataset in a page. """
-
- # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code.
- dataset = self.get_dataset( trans, id )
+ dataset = self.get_dataset( trans, id, False, True )
if dataset:
return "Embedded Dataset '%s'" % dataset.name
@@ -466,7 +465,7 @@
@web.expose
def display_by_username_and_slug( self, trans, username, slug, preview=True ):
""" Display dataset by username and slug; because datasets do not yet have slugs, the slug is the dataset's id. """
- dataset = self.get_dataset( trans, slug )
+ dataset = self.get_dataset( trans, slug, False, True )
if dataset:
truncated, dataset_data = self.get_data( dataset, preview )
dataset.annotation = self.get_item_annotation_str( trans.sa_session, dataset.history.user, dataset )
@@ -478,7 +477,7 @@
def get_item_content_async( self, trans, id ):
""" Returns item content in HTML format. """
- dataset = self.get_dataset( trans, id )
+ dataset = self.get_dataset( trans, id, False, True )
if dataset is None:
raise web.httpexceptions.HTTPNotFound()
truncated, dataset_data = self.get_data( dataset, preview=True )
@@ -486,6 +485,24 @@
dataset.annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), dataset )
return trans.stream_template_mako( "/dataset/item_content.mako", item=dataset, item_data=dataset_data, truncated=truncated )
+ @web.expose
+ def annotate_async( self, trans, id, new_annotation=None, **kwargs ):
+ dataset = self.get_dataset( trans, id, False, True )
+ if not dataset:
+ web.httpexceptions.HTTPNotFound()
+ if dataset and new_annotation:
+ # Sanitize annotation before adding it.
+ new_annotation = sanitize_html( new_annotation, 'utf-8', 'text/html' )
+ self.add_item_annotation( trans, dataset, new_annotation )
+ trans.sa_session.flush()
+ return new_annotation
+
+ @web.expose
+ def get_annotation_async( self, trans, id ):
+ dataset = self.get_dataset( trans, id, False, True )
+ if not dataset:
+ web.httpexceptions.HTTPNotFound()
+ return self.get_item_annotation_str( trans.sa_session, trans.get_user(), dataset )
@web.expose
def display_at( self, trans, dataset_id, filename=None, **kwd ):
@@ -704,7 +721,7 @@
if user != history.user:
error_msg = error_msg + "You do not have permission to add datasets to %i requested histories. " % ( len( target_histories ) )
for dataset_id in dataset_ids:
- data = self.get_dataset( trans, dataset_id )
+ data = self.get_dataset( trans, dataset_id, False, True )
if data is None:
error_msg = error_msg + "You tried to copy a dataset that does not exist or that you do not have access to. "
invalid_datasets += 1
diff -r 96ec861b4b6e -r 6d079d53f9db lib/galaxy/web/controllers/page.py
--- a/lib/galaxy/web/controllers/page.py Sun Mar 14 11:49:44 2010 -0400
+++ b/lib/galaxy/web/controllers/page.py Mon Mar 15 11:31:14 2010 -0400
@@ -674,7 +674,7 @@
datasets = self.get_history_datasets( trans, history )
return trans.fill_template( "history/embed.mako", item=history, item_data=datasets )
elif item_class == model.HistoryDatasetAssociation:
- dataset = self.get_dataset( trans, item_id )
+ dataset = self.get_dataset( trans, item_id, False, True )
dataset.annotation = self.get_item_annotation_str( trans.sa_session, dataset.history.user, dataset )
if dataset:
data = self.get_data( dataset )
diff -r 96ec861b4b6e -r 6d079d53f9db lib/galaxy/web/controllers/tag.py
--- a/lib/galaxy/web/controllers/tag.py Sun Mar 14 11:49:44 2010 -0400
+++ b/lib/galaxy/web/controllers/tag.py Mon Mar 15 11:31:14 2010 -0400
@@ -11,12 +11,21 @@
def __init__(self, app):
BaseController.__init__(self, app)
-
- # Set up tag handler to recognize the following items: History, HistoryDatasetAssociation, Page, ...
self.tag_handler = TagHandler()
+
+ @web.expose
+ @web.require_login( "edit item tags" )
+ def get_tagging_elt_async( self, trans, item_id, item_class, elt_context="" ):
+ """ Returns HTML for editing an item's tags. """
+ item = self._get_item( trans, item_class, trans.security.decode_id( item_id ) )
+ if not item:
+ return trans.show_error_message( "No item of class %s with id % " % ( item_class, item_id ) )
+ user = trans.get_user()
+ return trans.fill_template( "/tagging_common.mako", tag_type="individual", user=trans.get_user(), tagged_item=item, elt_context=elt_context,
+ in_form=False, input_size="22", tag_click_fn="default_tag_click_fn", use_toggle_link=False )
@web.expose
- @web.require_login( "Add tag to an item." )
+ @web.require_login( "add tag to an item" )
def add_tag_async( self, trans, item_id=None, item_class=None, new_tag=None, context=None ):
""" Add tag to an item. """
@@ -28,10 +37,10 @@
# Log.
params = dict( item_id=item.id, item_class=item_class, tag=new_tag)
- trans.log_action( user, unicode( "tag"), context, params )
+ trans.log_action( user, unicode( "tag" ), context, params )
@web.expose
- @web.require_login( "Remove tag from an item." )
+ @web.require_login( "remove tag from an item" )
def remove_tag_async( self, trans, item_id=None, item_class=None, tag_name=None, context=None ):
""" Remove tag from an item. """
diff -r 96ec861b4b6e -r 6d079d53f9db lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py Sun Mar 14 11:49:44 2010 -0400
+++ b/lib/galaxy/web/framework/helpers/grids.py Mon Mar 15 11:31:14 2010 -0400
@@ -389,7 +389,7 @@
self.grid_name = grid_name
def get_value( self, trans, grid, item ):
return trans.fill_template( "/tagging_common.mako", tag_type="community", trans=trans, user=trans.get_user(), tagged_item=item, elt_context=self.grid_name,
- in_form=True, input_size="20", tag_click_fn="add_tag_to_grid_filter" )
+ in_form=True, input_size="20", tag_click_fn="add_tag_to_grid_filter", use_toggle_link=True )
def filter( self, db_session, user, query, column_filter ):
""" Modify query to filter model_class by tag. Multiple filters are ANDed. """
if column_filter == "All":
@@ -418,7 +418,7 @@
""" Column that supports individual tags. """
def get_value( self, trans, grid, item ):
return trans.fill_template( "/tagging_common.mako", tag_type="individual", trans=trans, user=trans.get_user(), tagged_item=item, elt_context=self.grid_name,
- in_form=True, input_size="20", tag_click_fn="add_tag_to_grid_filter" )
+ in_form=True, input_size="20", tag_click_fn="add_tag_to_grid_filter", use_toggle_link=True )
def get_filter( self, user, column_filter ):
# Parse filter to extract multiple tags.
tag_handler = TagHandler()
diff -r 96ec861b4b6e -r 6d079d53f9db static/june_2007_style/autocomplete_tagging.css.tmpl
--- a/static/june_2007_style/autocomplete_tagging.css.tmpl Sun Mar 14 11:49:44 2010 -0400
+++ b/static/june_2007_style/autocomplete_tagging.css.tmpl Mon Mar 15 11:31:14 2010 -0400
@@ -74,6 +74,11 @@
cursor: pointer;
}
+.individual-tag-area:hover
+{
+ border:dotted #999999 1px;
+}
+
.active-tag-area {
background-color: white;
}
diff -r 96ec861b4b6e -r 6d079d53f9db static/june_2007_style/base.css.tmpl
--- a/static/june_2007_style/base.css.tmpl Sun Mar 14 11:49:44 2010 -0400
+++ b/static/june_2007_style/base.css.tmpl Mon Mar 15 11:31:14 2010 -0400
@@ -835,8 +835,7 @@
cursor:pointer;
}
-.editable-text:hover{
- background-image:url();
- background-repeat:no-repeat;
- background-position:right;
-}
+.editable-text:hover {
+ cursor: text;
+ border: dotted #999999 1px;
+}
\ No newline at end of file
diff -r 96ec861b4b6e -r 6d079d53f9db static/june_2007_style/blue/autocomplete_tagging.css
--- a/static/june_2007_style/blue/autocomplete_tagging.css Sun Mar 14 11:49:44 2010 -0400
+++ b/static/june_2007_style/blue/autocomplete_tagging.css Mon Mar 15 11:31:14 2010 -0400
@@ -7,7 +7,8 @@
.ac_over{background-color:#0A246A;color:white;}
.ac_header{font-style:normal;color:gray;border-bottom:0.1em solid gray;}
.tag-area{width:100%;}
-.individual-tag-area{border:solid 1px #eee;cursor:pointer;}
+.individual-tag-area{cursor:pointer;}
+.individual-tag-area:hover{border:dotted #999999 1px;}
.active-tag-area{background-color:white;}
.toggle-link{font-weight:normal;padding:0.3em;margin-bottom:1em;width:100%;padding:0.2em 0em 0.2em 0em;}
.tag-button{width:auto;color:#444;text-decoration:none;display:inline-block;cursor:pointer;margin:0.2em;border:solid #bbb 1px;padding:0.1em 0.5em 0.1em 0.5em;-moz-border-radius:.5em;-webkit-border-radius:.5em;border-radius:.5em;background:#eee;}
diff -r 96ec861b4b6e -r 6d079d53f9db static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css Sun Mar 14 11:49:44 2010 -0400
+++ b/static/june_2007_style/blue/base.css Mon Mar 15 11:31:14 2010 -0400
@@ -145,4 +145,5 @@
.tipsy-east{background-position:right center;}
.tipsy-west{background-position:left center;}
.editable-text{cursor:pointer;}
-.editable-text:hover{background-image:url();background-repeat:no-repeat;background-position:right;}
+.editable-text:hover{cursor: text;border: dotted #999999 1px;}
+
diff -r 96ec861b4b6e -r 6d079d53f9db templates/dataset/display.mako
--- a/templates/dataset/display.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/dataset/display.mako Mon Mar 15 11:31:14 2010 -0400
@@ -22,7 +22,7 @@
</%def>
<%def name="render_item_links( data )">
- ## Provide links to save data and TODO: import dataset.
+ ## Provide links to save data and import dataset.
<a href="${h.url_for( controller='/dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}" class="icon-button disk tooltip" title="Save dataset"></a>
<a href="${h.url_for( controller='/dataset', action='imp', dataset_id=trans.security.encode_id( data.id ) )}" class="icon-button import tooltip" title="Import dataset"></a>
</%def>
diff -r 96ec861b4b6e -r 6d079d53f9db templates/dataset/embed.mako
--- a/templates/dataset/embed.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/dataset/embed.mako Mon Mar 15 11:31:14 2010 -0400
@@ -3,8 +3,12 @@
from galaxy.web.framework.helpers import iff
%>
-<%def name="render_item_specific_title_links( dataset )">
+<%def name="render_item_links( dataset )">
<a href="${h.url_for( controller='/dataset', action='display', dataset_id=trans.security.encode_id( dataset.id ), to_ext=dataset.ext )}" title="Save dataset" class="icon-button disk tooltip"></a>
+ ## Links for importing and viewing an item.
+ <a href="${h.url_for( controller='/dataset', action='imp', dataset_id=trans.security.encode_id( item.id ) )}" title="Import dataset" class="icon-button import tooltip"></a>
+ <a class="icon-button go-to-full-screen tooltip" href="${h.url_for( controller='/dataset', action='display_by_username_and_slug', username=dataset.history.user.username, slug=trans.security.encode_id( dataset.id ) )}" title="Go to dataset"></a>
+
</%def>
<%def name="render_summary_content( dataset, data )">
diff -r 96ec861b4b6e -r 6d079d53f9db templates/display_base.mako
--- a/templates/display_base.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/display_base.mako Mon Mar 15 11:31:14 2010 -0400
@@ -25,7 +25,7 @@
self.has_left_panel=False
self.has_right_panel=True
self.message_box_visible=False
- self.active_view="user"
+ self.active_view=""
self.overlay_visible=False
%>
</%def>
diff -r 96ec861b4b6e -r 6d079d53f9db templates/embed_base.mako
--- a/templates/embed_base.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/embed_base.mako Mon Mar 15 11:31:14 2010 -0400
@@ -18,8 +18,19 @@
</div>
</div>
-## Render item-specific title links.
-<%def name="render_item_specific_title_links( item )">
+## Render item links.
+<%def name="render_item_links( item )">
+ <%
+ item_display_name = get_class_display_name( item.__class__ ).lower()
+ item_controller = "/%s" % get_controller_name( item )
+ item_user = get_item_user( item )
+ item_slug = get_item_slug( item )
+ display_href = h.url_for( controller=item_controller, action='display_by_username_and_slug', username=item_user.username, slug=item_slug )
+ %>
+
+ ## Links for importing and viewing an item.
+ <a href="${h.url_for( controller=item_controller, action='imp', id=trans.security.encode_id( item.id ) )}" title="Import ${item_display_name}" class="icon-button import tooltip"></a>
+ <a class="icon-button go-to-full-screen tooltip" href="${display_href}" title="Go to ${item_display_name}"></a>
</%def>
<%def name="render_title( item )">
@@ -36,10 +47,7 @@
<a class="toggle-contract icon-button tooltip" href="${display_href}" title="Hide ${item_display_name} content"></a>
</div>
<div style="float: right">
- ${self.render_item_specific_title_links( item )}
- ## Links applicable for all items.
- <a href="${h.url_for( controller=item_controller, action='imp', id=trans.security.encode_id( item.id ) )}" title="Import ${item_display_name}" class="icon-button import tooltip"></a>
- <a class="icon-button go-to-full-screen tooltip" href="${display_href}" title="Go to ${item_display_name}"></a>
+ ${self.render_item_links( item )}
</div>
<h4><a class="toggle-embed tooltip" href="${display_href}" title="Show or hide ${item_display_name} content">Galaxy ${get_class_display_name( item.__class__ )} | ${get_item_name( item )}</a></h4>
%if hasattr( item, "annotation") and item.annotation:
diff -r 96ec861b4b6e -r 6d079d53f9db templates/grid_base_async.mako
--- a/templates/grid_base_async.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/grid_base_async.mako Mon Mar 15 11:31:14 2010 -0400
@@ -13,4 +13,4 @@
*****
${num_pages}
*****
-${render_message( grid )}
\ No newline at end of file
+${render_message( message, message_type )}
\ No newline at end of file
diff -r 96ec861b4b6e -r 6d079d53f9db templates/root/history.mako
--- a/templates/root/history.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/root/history.mako Mon Mar 15 11:31:14 2010 -0400
@@ -42,10 +42,10 @@
$.jStore.remove("history_expand_state");
}).show();
- // Rename management.
+ // History rename functionality.
async_save_text("history-name-container", "history-name", "${h.url_for( controller="/history", action="rename_async", id=trans.security.encode_id(history.id) )}", "new_name", 18);
- // Tag management.
+ // History tagging functionality.
var historyTagArea = $('#history-tag-area');
$('#history-tag').click( function()
{
@@ -57,7 +57,7 @@
return false;
});
- // Annotation management.
+ // History annotation functionality.
var historyAnnotationArea = $('#history-annotation-area');
$('#history-annotate').click( function() {
if ( historyAnnotationArea.is( ":hidden" ) ) {
@@ -104,7 +104,8 @@
})
}
}
-// Add show/hide link and delete link to a history item
+// (a) Add show/hide link and delete link to a history item;
+// (b) handle tagging and annotation using jquery.
function setupHistoryItem( query ) {
query.each( function() {
var id = this.id;
@@ -180,6 +181,99 @@
return false;
});
});
+
+ // Tag handling.
+ $(this).find( "a.icon-button.tags").each( function()
+ {
+ // Use links parameters but custom URL as ajax URL.
+ $(this).click( function() {
+ // Get tag area, tag element.
+ var history_item = $(this).parents(".historyItem");
+ var tag_area = history_item.find(".tag-area");
+ var tag_elt = history_item.find(".tag-elt");
+
+ // Show or hide tag area; if showing tag area and it's empty, fill it.
+ if ( tag_area.is( ":hidden" ) )
+ {
+ if (tag_elt.html() == "" )
+ {
+ // Need to fill tag element.
+ var href_parms = $(this).attr("href").split("?")[1];
+ var ajax_url = "${h.url_for( controller='tag', action='get_tagging_elt_async' )}?" + href_parms;
+ $.ajax({
+ url: ajax_url,
+ error: function() { alert( "Tagging failed" ) },
+ success: function(tag_elt_html) {
+ tag_elt.html(tag_elt_html);
+ tag_elt.find(".tooltip").tipsy( { gravity: 's' } );
+ tag_area.slideDown("fast");
+ }
+ });
+ }
+ else
+ {
+ // Tag element is filled; show.
+ tag_area.slideDown("fast");
+ }
+ }
+ else
+ {
+ // Hide.
+ tag_area.slideUp("fast");
+ }
+ return false;
+ });
+ });
+
+ // Annotation handling.
+ $(this).find( "a.icon-button.annotate").each( function()
+ {
+ // Use links parameters but custom URL as ajax URL.
+ $(this).click( function() {
+ // Get tag area, tag element.
+ var history_item = $(this).parents(".historyItem");
+ var annotation_area = history_item.find(".annotation-area");
+ var annotation_elt = history_item.find(".annotation-elt");
+
+ // Show or hide annotation area; if showing annotation area and it's empty, fill it.
+ if ( annotation_area.is( ":hidden" ) )
+ {
+ if (annotation_elt.html() == "" )
+ {
+ // Need to fill annotation element.
+ var href_parms = $(this).attr("href").split("?")[1];
+ var ajax_url = "${h.url_for( controller='dataset', action='get_annotation_async' )}?" + href_parms;
+ $.ajax({
+ url: ajax_url,
+ error: function() { alert( "Annotations failed" ) },
+ success: function(annotation) {
+ if (annotation == "")
+ annotation = "<i>Describe or add notes to dataset</i>";
+ annotation_elt.html(annotation);
+ annotation_area.find(".tooltip").tipsy( { gravity: 's' } );
+ async_save_text(
+ annotation_elt.attr("id"), annotation_elt.attr("id"),
+ "${h.url_for( controller="/dataset", action="annotate_async")}?" + href_parms,
+ "new_annotation", 18, true, 4);
+ annotation_area.slideDown("fast");
+ }
+ });
+ }
+ else
+ {
+ // Annotation element is filled; show.
+ annotation_area.slideDown("fast");
+ }
+ }
+ else
+ {
+ // Hide.
+ annotation_area.slideUp("fast");
+ }
+ return false;
+ });
+ });
+
});
};
// Looks for changes in dataset state using an async request. Keeps
@@ -279,13 +373,6 @@
padding: 3px;
margin: -4px;
}
-.editable-text:hover {
- cursor: text;
- border: dotted #999999 1px;
-}
-.tag-area {
- border: none;
-}
</style>
<noscript>
@@ -299,7 +386,6 @@
</head>
<body class="historyPage">
-
<div id="top-links" class="historyLinks">
<a title="${_('refresh')}" class="icon-button arrow-circle tooltip" href="${h.url_for('history', show_deleted=show_deleted)}"></a>
diff -r 96ec861b4b6e -r 6d079d53f9db templates/root/history_common.mako
--- a/templates/root/history_common.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/root/history_common.mako Mon Mar 15 11:31:14 2010 -0400
@@ -86,10 +86,26 @@
</div>
<div class="info">${_('Info: ')}${data.display_info()}</div>
<div>
+ <% dataset_id=trans.security.encode_id( data.id ) %>
%if data.has_data:
- <a href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}" title="Save" class="icon-button disk tooltip"></a>
+ <a href="${h.url_for( controller='dataset', action='display', dataset_id=dataset_id, to_ext=data.ext )}" title="Save" class="icon-button disk tooltip"></a>
%if user_owns_dataset:
<a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main" title="Run this job again" class="icon-button arrow-circle tooltip"></a>
+ %if trans.user:
+ <div style="float: right">
+ <a href="${h.url_for( controller='tag', action='retag', item_class=data.__class__.__name__, item_id=dataset_id )}" target="galaxy_main" title="Edit dataset tags" class="icon-button tags tooltip"></a>
+ <a href="${h.url_for( controller='dataset', action='annotate', id=dataset_id )}" target="galaxy_main" title="Edit dataset annotation" class="icon-button annotate tooltip"></a>
+ </div>
+ <div style="clear: both"></div>
+ <div class="tag-area" style="display: none">
+ <strong>Tags:</strong>
+ <div class="tag-elt"></div>
+ </div>
+ <div id="${dataset_id}-annotation-area" class="annotation-area" style="display: none">
+ <strong>Annotation:</strong>
+ <div id="${dataset_id}-annotation-elt" style="margin: 1px 0px 1px 0px" class="annotation-elt tooltip editable-text" title="Edit dataset annotation"></div>
+ </div>
+ %endif
%endif
<div style="clear: both"></div>
%for display_app in data.datatype.get_display_types():
diff -r 96ec861b4b6e -r 6d079d53f9db templates/tagging_common.mako
--- a/templates/tagging_common.mako Sun Mar 14 11:49:44 2010 -0400
+++ b/templates/tagging_common.mako Mon Mar 15 11:31:14 2010 -0400
@@ -13,7 +13,7 @@
## Render a tagging element if there is a tagged_item.
%if tagged_item is not None:
%if tag_type == "individual":
- ${render_individual_tagging_element(user=user, tagged_item=tagged_item, elt_context=elt_context, in_form=in_form, input_size=input_size, tag_click_fn=tag_click_fn)}
+ ${render_individual_tagging_element( user=user, tagged_item=tagged_item, elt_context=elt_context, in_form=in_form, input_size=input_size, tag_click_fn=tag_click_fn, use_toggle_link=use_toggle_link )}
%elif tag_type == "community":
${render_community_tagging_element(tagged_item=tagged_item, elt_context=elt_context, tag_click_fn=tag_click_fn)}
%endif
@@ -123,7 +123,7 @@
//
// Set up autocomplete tagger.
//
-
+
//
// Default function get text to display on the toggle link.
//
@@ -193,7 +193,7 @@
ajax_delete_tag_url: "${h.url_for( controller='/tag', action='remove_tag_async', item_id=tagged_item_id, item_class=tagged_item.__class__.__name__, context=elt_context )}",
delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
- use_toggle_link: ${iff( use_toggle_link, 'true', 'false' )},
+ use_toggle_link: ${iff( use_toggle_link, 'true', 'false' )}
};
$('#${elt_id}').autocomplete_tagging(options);
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/96ec861b4b6e
changeset: 3529:96ec861b4b6e
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Sun Mar 14 11:49:44 2010 -0400
description:
Make the login/register/logout sequence more user friendly. Specific changes: (a) use panels so that Galaxy masthead is always available; (b) provide links to guide users past login; (c) enable 'user' to be an active view; (d) updated functional tests.
diffstat:
lib/galaxy/web/controllers/dataset.py | 4 +-
lib/galaxy/web/controllers/user.py | 28 ++-
lib/galaxy/web/controllers/visualization.py | 2 +-
lib/galaxy/web/controllers/workflow.py | 8 +-
lib/galaxy/web/framework/__init__.py | 26 +-
templates/base_panels.mako | 14 +-
templates/display_base.mako | 12 +-
templates/form.mako | 115 ++++++++++------
templates/history/list_published.mako | 2 +-
templates/message.mako | 3 +-
templates/page/list_published.mako | 2 +-
templates/user/register.mako | 162 ++++++++++++----------
templates/visualization/list_published.mako | 2 +-
templates/workflow/list.mako | 193 +++++++++++++++------------
templates/workflow/list_published.mako | 2 +-
test/base/twilltestcase.py | 11 +-
16 files changed, 329 insertions(+), 257 deletions(-)
diffs (900 lines):
diff -r 48e83411aa91 -r 96ec861b4b6e lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Fri Mar 12 16:11:26 2010 -0500
+++ b/lib/galaxy/web/controllers/dataset.py Sun Mar 14 11:49:44 2010 -0400
@@ -436,8 +436,8 @@
# Do import.
cur_history = trans.get_history( create=True )
status, message = self._copy_datasets( trans, [ dataset_id ], [ cur_history ] )
- message = message + "<br>You can <a href='%s'>start using the dataset</a> or %s." % ( url_for('/'), referer_message )
- return trans.show_message( message, type=status )
+ message = "Dataset imported. <br>You can <a href='%s'>start using the dataset</a> or %s." % ( url_for('/'), referer_message )
+ return trans.show_message( message, type=status, use_panels=True )
@web.expose
@web.json
diff -r 48e83411aa91 -r 96ec861b4b6e lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Fri Mar 12 16:11:26 2010 -0500
+++ b/lib/galaxy/web/controllers/user.py Sun Mar 14 11:49:44 2010 -0400
@@ -115,9 +115,14 @@
you share publicly. Usernames must be at least
four characters in length and contain only lowercase
letters, numbers, and the '-' character.""" ) )
+
@web.expose
- def login( self, trans, email='', password='' ):
+ def login( self, trans, email='', password='', referer='', use_panels='True' ):
email_error = password_error = None
+
+ # Convert use_panels to Boolean.
+ use_panels = use_panels in [ 'True', 'true', 't', 'T' ]
+
# Attempt login
if trans.app.config.require_login:
refresh_frames = [ 'masthead', 'history', 'tools' ]
@@ -136,21 +141,23 @@
else:
trans.handle_user_login( user )
trans.log_event( "User logged in" )
- msg = "Now logged in as " + user.email + "."
+ msg = "You are now logged in as %s.<br>You can <a href='%s'>go back to the page you were visiting</a> or <a href='%s'>go to the Galaxy homepage</a>." % ( user.email, referer, url_for( '/' ) )
if trans.app.config.require_login:
msg += ' <a href="%s">Click here</a> to continue to the front page.' % web.url_for( '/static/welcome.html' )
- return trans.show_ok_message( msg, refresh_frames=refresh_frames )
+ return trans.show_ok_message( msg, refresh_frames=refresh_frames, use_panels=use_panels, active_view="user" )
form = web.FormBuilder( web.url_for(), "Login", submit_text="Login" ) \
.add_text( "email", "Email address", value=email, error=email_error ) \
.add_password( "password", "Password", value='', error=password_error,
- help="<a href='%s'>Forgot password? Reset here</a>" % web.url_for( action='reset_password' ) )
+ help="<a href='%s'>Forgot password? Reset here</a>" % web.url_for( action='reset_password' ) ) \
+ .add_input( "hidden", "referer", "referer", value=trans.request.referer, use_label=False )
if trans.app.config.require_login:
if trans.app.config.allow_user_creation:
- return trans.show_form( form, header = require_login_creation_template % web.url_for( action = 'create' ) )
+ return trans.show_form( form, header = require_login_creation_template % web.url_for( action = 'create' ), use_panels=use_panels, active_view="user" )
else:
- return trans.show_form( form, header = require_login_nocreation_template )
+ return trans.show_form( form, header = require_login_nocreation_template, use_panels=use_panels, active_view="user" )
else:
- return trans.show_form( form )
+ return trans.show_form( form, use_panels=use_panels, active_view="user" )
+
@web.expose
def logout( self, trans ):
if trans.app.config.require_login:
@@ -160,10 +167,11 @@
# Since logging an event requires a session, we'll log prior to ending the session
trans.log_event( "User logged out" )
trans.handle_user_logout()
- msg = "You are no longer logged in."
+ msg = "You have been logged out.<br>You can <a href='%s'>go back to the page you were visiting</a> or <a href='%s'>go to the Galaxy homepage</a>." % ( trans.request.referer, url_for( '/' ) )
if trans.app.config.require_login:
msg += ' <a href="%s">Click here</a> to return to the login page.' % web.url_for( controller='user', action='login' )
- return trans.show_ok_message( msg, refresh_frames=refresh_frames )
+ return trans.show_ok_message( msg, refresh_frames=refresh_frames, use_panels=True, active_view="user" )
+
@web.expose
def create( self, trans, **kwd ):
params = util.Params( kwd )
@@ -217,7 +225,7 @@
trans.log_event( "User created a new account" )
trans.log_event( "User logged in" )
# subscribe user to email list
- return trans.show_ok_message( "Now logged in as " + user.email, refresh_frames=refresh_frames )
+ return trans.show_ok_message( "Now logged in as %s.<br><a href='%s'>Return to the Galaxy start page.</a>" % ( user.email, url_for( '/' ) ), refresh_frames=refresh_frames, use_panels=True )
else:
trans.response.send_redirect( web.url_for( controller='admin',
action='users',
diff -r 48e83411aa91 -r 96ec861b4b6e lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py Fri Mar 12 16:11:26 2010 -0500
+++ b/lib/galaxy/web/controllers/visualization.py Sun Mar 14 11:49:44 2010 -0400
@@ -75,7 +75,7 @@
return trans.fill_template( "visualization/list_published.mako", grid=grid )
@web.expose
- @web.require_login("use Galaxy visualizations")
+ @web.require_login( "use Galaxy visualizations", use_panels=True )
def list( self, trans, *args, **kwargs ):
# Handle operation
if 'operation' in kwargs and 'id' in kwargs:
diff -r 48e83411aa91 -r 96ec861b4b6e lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py Fri Mar 12 16:11:26 2010 -0500
+++ b/lib/galaxy/web/controllers/workflow.py Sun Mar 14 11:49:44 2010 -0400
@@ -85,7 +85,7 @@
@web.expose
def index( self, trans ):
- return trans.fill_template( "workflow/index.mako" )
+ return self.list( trans )
@web.expose
@web.require_login( "use Galaxy workflows" )
@@ -102,7 +102,7 @@
return self.stored_list_grid( trans, **kwargs )
@web.expose
- @web.require_login( "use Galaxy workflows" )
+ @web.require_login( "use Galaxy workflows", use_panels=True )
def list( self, trans ):
"""
Render workflow main page (management of existing workflows)
@@ -276,7 +276,7 @@
item=stored )
@web.expose
- @web.require_login( "use Galaxy workflows" )
+ @web.require_login( "to import a workflow", use_panels=True )
def imp( self, trans, id, **kwargs ):
# Set referer message.
referer = trans.request.referer
@@ -284,7 +284,7 @@
referer_message = "<a href='%s'>return to the previous page</a>" % referer
else:
referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
-
+
# Do import.
session = trans.sa_session
stored = self.get_stored_workflow( trans, id, check_ownership=False )
diff -r 48e83411aa91 -r 96ec861b4b6e lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py Fri Mar 12 16:11:26 2010 -0500
+++ b/lib/galaxy/web/framework/__init__.py Sun Mar 14 11:49:44 2010 -0400
@@ -65,15 +65,15 @@
decorator.exposed = True
return decorator
-def require_login( verb="perform this action" ):
+def require_login( verb="perform this action", use_panels=False ):
def argcatcher( func ):
def decorator( self, trans, *args, **kwargs ):
if trans.get_user():
return func( self, trans, *args, **kwargs )
else:
return trans.show_error_message(
- "You must be <a target='galaxy_main' href='%s'>logged in</a> to %s</div>"
- % ( url_for( controller='user', action='login' ), verb ) )
+ "You must be <a target='_top' href='%s'>logged in</a> to %s</div>."
+ % ( url_for( controller='user', action='login' ), verb ), use_panels=use_panels )
return decorator
return argcatcher
@@ -561,7 +561,7 @@
context.
"""
return self.template_context['message']
- def show_message( self, message, type='info', refresh_frames=[], cont=None, use_panels=False ):
+ def show_message( self, message, type='info', refresh_frames=[], cont=None, use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single message.
@@ -571,28 +571,28 @@
`refresh_frames`: names of frames in the interface that should be
refreshed when the message is displayed
"""
- return self.fill_template( "message.mako", message_type=type, message=message, refresh_frames=refresh_frames, cont=cont, use_panels=use_panels )
- def show_error_message( self, message, refresh_frames=[], use_panels=False ):
+ return self.fill_template( "message.mako", message_type=type, message=message, refresh_frames=refresh_frames, cont=cont, use_panels=use_panels, active_view=active_view )
+ def show_error_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an error message. See `show_message`.
"""
- return self.show_message( message, 'error', refresh_frames, use_panels=use_panels )
- def show_ok_message( self, message, refresh_frames=[], use_panels=False ):
+ return self.show_message( message, 'error', refresh_frames, use_panels=use_panels, active_view=active_view )
+ def show_ok_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an ok message. See `show_message`.
"""
- return self.show_message( message, 'done', refresh_frames, use_panels=use_panels )
- def show_warn_message( self, message, refresh_frames=[], use_panels=False ):
+ return self.show_message( message, 'done', refresh_frames, use_panels=use_panels, active_view=active_view )
+ def show_warn_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an warn message. See `show_message`.
"""
- return self.show_message( message, 'warning', refresh_frames, use_panels=use_panels )
- def show_form( self, form, header=None, template="form.mako" ):
+ return self.show_message( message, 'warning', refresh_frames, use_panels=use_panels, active_view=active_view )
+ def show_form( self, form, header=None, template="form.mako", use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single HTML
form.
"""
- return self.fill_template( template, form=form, header=header )
+ return self.fill_template( template, form=form, header=header, use_panels=use_panels, active_view=active_view )
def fill_template(self, filename, **kwargs):
"""
Fill in a template, putting any keyword arguments on the context.
diff -r 48e83411aa91 -r 96ec861b4b6e templates/base_panels.mako
--- a/templates/base_panels.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/base_panels.mako Sun Mar 14 11:49:44 2010 -0400
@@ -227,7 +227,13 @@
</div>
</td>
- <td class="tab">
+ ## User tab.
+ <%
+ cls = "tab"
+ if self.active_view == 'user':
+ cls += " active"
+ %>
+ <td class="${cls}">
<a>User</a>
<%
if trans.user:
@@ -241,9 +247,9 @@
%>
<div class="submenu">
<ul class="loggedout-only" style="${style1}">
- <li><a target="galaxy_main" href="${h.url_for( controller='/user', action='login' )}">Login</a></li>
+ <li><a href="${h.url_for( controller='/user', action='login' )}">Login</a></li>
%if app.config.allow_user_creation:
- <li><a target="galaxy_main" href="${h.url_for( controller='/user', action='create' )}">Register</a></li>
+ <li><a href="${h.url_for( controller='/user', action='create' )}">Register</a></li>
%endif
</ul>
<ul class="loggedin-only" style="${style2}">
@@ -259,7 +265,7 @@
logout_target = ""
logout_url = h.url_for( controller='/root', action='index', m_c='user', m_a='logout' )
else:
- logout_target = "galaxy_main"
+ logout_target = ""
logout_url = h.url_for( controller='/user', action='logout' )
%>
<li><a target="${logout_target}" href="${logout_url}">Logout</a></li>
diff -r 48e83411aa91 -r 96ec861b4b6e templates/display_base.mako
--- a/templates/display_base.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/display_base.mako Sun Mar 14 11:49:44 2010 -0400
@@ -216,11 +216,13 @@
%endif
</div>
## Individual tags.
- <p>
- <div>
- Yours:
- ${render_individual_tagging_element( user=trans.get_user(), tagged_item=item, elt_context='view.mako', use_toggle_link=False, tag_click_fn='community_tag_click' )}
- </div>
+ %if trans.get_user():
+ <p>
+ <div>
+ Yours:
+ ${render_individual_tagging_element( user=trans.get_user(), tagged_item=item, elt_context='view.mako', use_toggle_link=False, tag_click_fn='community_tag_click' )}
+ </div>
+ %endif
</div>
</div>
</div>
diff -r 48e83411aa91 -r 96ec861b4b6e templates/form.mako
--- a/templates/form.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/form.mako Sun Mar 14 11:49:44 2010 -0400
@@ -1,54 +1,83 @@
+<%!
+ def inherit(context):
+ if context.get('use_panels') is True:
+ print "here"
+ return '/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
<% _=n_ %>
-<%inherit file="/base.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
+
+
<%def name="title()">${form.title}</%def>
<%def name="javascripts()">
-${parent.javascripts()}
-<script type="text/javascript">
-$(function(){
- $("input:text:first").focus();
-})
-</script>
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $(function(){
+ $("input:text:first").focus();
+ })
+ </script>
</%def>
-%if header:
- ${header}
-%endif
+<%def name="center_panel()">
+ ${render_form( )}
+</%def>
-<div class="form">
- <div class="form-title">${form.title}</div>
- <div class="form-body">
- <form name="${form.name}" action="${form.action}" method="post" >
- %for input in form.inputs:
- <%
- cls = "form-row"
- if input.error:
- cls += " form-row-error"
- %>
- <div class="${cls}">
- %if input.use_label:
- <label>
- ${_(input.label)}:
- </label>
- %endif
- <div class="form-row-input">
- <input type="${input.type}" name="${input.name}" value="${input.value}" size="40">
- </div>
- %if input.error:
- <div class="form-row-error-message">${input.error}</div>
- %endif
- %if input.help:
- <div class="toolParamHelp" style="clear: both;">
- ${input.help}
- </div>
- %endif
+<%def name="body()">
+ ${render_form( )}
+</%def>
+
+<%def name="render_form()">
+ %if header:
+ ${header}
+ %endif
- <div style="clear: both"></div>
+ <div class="form" style="margin: 1em">
+ <div class="form-title">${form.title}</div>
+ <div class="form-body">
+ <form name="${form.name}" action="${form.action}" method="post" >
+ %for input in form.inputs:
+ <%
+ cls = "form-row"
+ if input.error:
+ cls += " form-row-error"
+ %>
+ <div class="${cls}">
+ %if input.use_label:
+ <label>
+ ${_(input.label)}:
+ </label>
+ %endif
+ <div class="form-row-input">
+ <input type="${input.type}" name="${input.name}" value="${input.value}" size="40">
+ </div>
+ %if input.error:
+ <div class="form-row-error-message">${input.error}</div>
+ %endif
+ %if input.help:
+ <div class="toolParamHelp" style="clear: both;">
+ ${input.help}
+ </div>
+ %endif
- </div>
- %endfor
- <div class="form-row"><input type="submit" value="${form.submit_text}"></div>
+ <div style="clear: both"></div>
- </form>
+ </div>
+ %endfor
+ <div class="form-row"><input type="submit" value="${form.submit_text}"></div>
+
+ </form>
+ </div>
</div>
-</div>
+</%def>
\ No newline at end of file
diff -r 48e83411aa91 -r 96ec861b4b6e templates/history/list_published.mako
--- a/templates/history/list_published.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/history/list_published.mako Sun Mar 14 11:49:44 2010 -0400
@@ -10,7 +10,7 @@
</%def>
<%def name="title()">
- Galaxy :: Published Histories
+ Galaxy | Published Histories
</%def>
<%def name="stylesheets()">
diff -r 48e83411aa91 -r 96ec861b4b6e templates/message.mako
--- a/templates/message.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/message.mako Sun Mar 14 11:49:44 2010 -0400
@@ -1,6 +1,6 @@
<%!
def inherit(context):
- if context.get('use_panels'):
+ if context.get('use_panels') is True:
return '/base_panels.mako'
else:
return '/base.mako'
@@ -69,7 +69,6 @@
${render_large_message( message, message_type )}
</%def>
-## Render the grid's basic elements. Each of these elements can be subclassed.
<%def name="body()">
${render_large_message( message, message_type )}
</%def>
diff -r 48e83411aa91 -r 96ec861b4b6e templates/page/list_published.mako
--- a/templates/page/list_published.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/page/list_published.mako Sun Mar 14 11:49:44 2010 -0400
@@ -10,7 +10,7 @@
</%def>
<%def name="title()">
- Galaxy :: Published Pages
+ Galaxy | Published Pages
</%def>
<%def name="stylesheets()">
diff -r 48e83411aa91 -r 96ec861b4b6e templates/user/register.mako
--- a/templates/user/register.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/user/register.mako Sun Mar 14 11:49:44 2010 -0400
@@ -1,87 +1,99 @@
-<%inherit file="/base.mako"/>
+<%inherit file="/base_panels.mako"/>
<%namespace file="/message.mako" import="render_msg" />
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view="user"
+ self.message_box_visible=False
+%>
+</%def>
-%if msg:
- ${render_msg( msg, messagetype )}
-%endif
-
-
-
-<script type="text/javascript">
-$( function() {
- $( "select[refresh_on_change='true']").change( function() {
- var refresh = false;
- var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
- if ( refresh_on_change_values ) {
- refresh_on_change_values = refresh_on_change_values.value.split( ',' );
- var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
- for( i= 0; i < refresh_on_change_values.length; i++ ) {
- if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
- refresh = true;
- break;
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
}
}
- }
- else {
- refresh = true;
- }
- if ( refresh ){
- $( "#registration" ).submit();
- }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#registration" ).submit();
+ }
+ });
});
-});
-</script>
+ </script>
-<div class="toolForm">
- <form name="registration" id="registration" action="${h.url_for( controller='user', action='create', admin_view=admin_view )}" method="post" >
- <div class="toolFormTitle">Create account</div>
- <div class="form-row">
- <label>Email</label>
- ${login_info[ 'Email' ].get_html()}
- </div>
- <div class="form-row">
- <label>Password</label>
- ${login_info[ 'Password' ].get_html()}
- </div>
- <div class="form-row">
- <label>Confirm</label>
- ${login_info[ 'Confirm' ].get_html()}
- </div>
- <div class="form-row">
- <label>Public Username</label>
- ${login_info[ 'Public Username' ].get_html()}
- <div class="toolParamHelp" style="clear: both;">
- Optional
+</%def>
+
+<%def name="center_panel()">
+ %if msg:
+ ${render_msg( msg, messagetype )}
+ %endif
+
+ <div class="toolForm" style="margin: 1em">
+ <form name="registration" id="registration" action="${h.url_for( controller='user', action='create', admin_view=admin_view )}" method="post" >
+ <div class="toolFormTitle">Create account</div>
+ <div class="form-row">
+ <label>Email</label>
+ ${login_info[ 'Email' ].get_html()}
</div>
- </div>
- <div class="form-row">
- <label>Subscribe To Mailing List</label>
- ${login_info[ 'Subscribe To Mailing List' ].get_html()}
- </div>
- %if user_info_select:
<div class="form-row">
- <label>User type</label>
- ${user_info_select.get_html()}
+ <label>Password</label>
+ ${login_info[ 'Password' ].get_html()}
</div>
- %endif
- %if user_info_form:
- %for field in widgets:
+ <div class="form-row">
+ <label>Confirm Password</label>
+ ${login_info[ 'Confirm' ].get_html()}
+ </div>
+ <div class="form-row">
+ <label>Public Username</label>
+ ${login_info[ 'Public Username' ].get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ When you share or publish items, this name is shown as the author.
+ </div>
+ </div>
+ <div class="form-row">
+ <label>Subscribe To Mailing List</label>
+ ${login_info[ 'Subscribe To Mailing List' ].get_html()}
+ </div>
+ %if user_info_select:
<div class="form-row">
- <label>${field['label']}</label>
- ${field['widget'].get_html()}
- <div class="toolParamHelp" style="clear: both;">
- ${field['helptext']}
+ <label>User type</label>
+ ${user_info_select.get_html()}
+ </div>
+ %endif
+ %if user_info_form:
+ %for field in widgets:
+ <div class="form-row">
+ <label>${field['label']}</label>
+ ${field['widget'].get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ ${field['helptext']}
+ </div>
+ <div style="clear: both"></div>
</div>
- <div style="clear: both"></div>
- </div>
- %endfor
- %if not user_info_select:
- <input type="hidden" name="user_info_select" value="${user_info_form.id}"/>
- %endif
- %endif
- <div class="form-row">
- <input type="submit" name="create_user_button" value="Submit">
- </div>
- </form>
-</div>
\ No newline at end of file
+ %endfor
+ %if not user_info_select:
+ <input type="hidden" name="user_info_select" value="${user_info_form.id}"/>
+ %endif
+ %endif
+ <div class="form-row">
+ <input type="submit" name="create_user_button" value="Submit">
+ </div>
+ </form>
+ </div>
+</%def>
\ No newline at end of file
diff -r 48e83411aa91 -r 96ec861b4b6e templates/visualization/list_published.mako
--- a/templates/visualization/list_published.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/visualization/list_published.mako Sun Mar 14 11:49:44 2010 -0400
@@ -10,7 +10,7 @@
</%def>
<%def name="title()">
- Galaxy :: Published Visualizations
+ Galaxy | Published Visualizations
</%def>
<%def name="stylesheets()">
diff -r 48e83411aa91 -r 96ec861b4b6e templates/workflow/list.mako
--- a/templates/workflow/list.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/workflow/list.mako Sun Mar 14 11:49:44 2010 -0400
@@ -1,103 +1,118 @@
-<%inherit file="/base.mako"/>
+<%inherit file="/base_panels.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view="workflow"
+ self.message_box_visible=False
+%>
+</%def>
<%def name="title()">Workflow home</%def>
-%if message:
-<%
- try:
- messagetype
- except:
- messagetype = "done"
-%>
-<p />
-<div class="${messagetype}message">
- ${message}
-</div>
-%endif
+<%def name="center_panel()">
+ <div style="overflow: auto; height: 100%;">
+ <div class="page-container" style="padding: 10px;">
+ %if message:
+ <%
+ try:
+ messagetype
+ except:
+ messagetype = "done"
+ %>
+ <p />
+ <div class="${messagetype}message">
+ ${message}
+ </div>
+ %endif
-<h2>Your workflows</h2>
+ <h2>Your workflows</h2>
-<ul class="manage-table-actions">
- <li>
- <a class="action-button" href="${h.url_for( action='create' )}">
- <img src="${h.url_for('/static/images/silk/add.png')}" />
- <span>Create new workflow</span>
- </a>
- </li>
-</ul>
+ <ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( action='create' )}">
+ <img src="${h.url_for('/static/images/silk/add.png')}" />
+ <span>Create new workflow</span>
+ </a>
+ </li>
+ </ul>
-%if workflows:
- <table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" style="width:100%;">
- <tr class="header">
- <th>Name</th>
- <th># of Steps</th>
- ## <th>Last Updated</th>
- <th></th>
- </tr>
- %for i, workflow in enumerate( workflows ):
- <tr>
- <td>
- <div class="menubutton" style="float: left;" id="wf-${i}-popup">
- ${workflow.name | h}
- </div>
- </td>
- <td>${len(workflow.latest_workflow.steps)}</td>
- ## <td>${str(workflow.update_time)[:19]}</td>
- <td>
- <div popupmenu="wf-${i}-popup">
- <a class="action-button" href="${h.url_for( action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">Edit</a>
- <a class="action-button" href="${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(workflow.id) )}" target="_parent">Run</a>
- <a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id(workflow.id) )}">Share or Publish</a>
- <a class="action-button" href="${h.url_for( action='clone', id=trans.security.encode_id(workflow.id) )}">Clone</a>
- <a class="action-button" href="${h.url_for( action='rename', id=trans.security.encode_id(workflow.id) )}">Rename</a>
- <a class="action-button" confirm="Are you sure you want to delete workflow '${workflow.name}'?" href="${h.url_for( action='delete', id=trans.security.encode_id(workflow.id) )}">Delete</a>
- </div>
- </td>
- </tr>
- %endfor
- </table>
-%else:
+ %if workflows:
+ <table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" style="width:100%;">
+ <tr class="header">
+ <th>Name</th>
+ <th># of Steps</th>
+ ## <th>Last Updated</th>
+ <th></th>
+ </tr>
+ %for i, workflow in enumerate( workflows ):
+ <tr>
+ <td>
+ <div class="menubutton" style="float: left;" id="wf-${i}-popup">
+ ${workflow.name | h}
+ </div>
+ </td>
+ <td>${len(workflow.latest_workflow.steps)}</td>
+ ## <td>${str(workflow.update_time)[:19]}</td>
+ <td>
+ <div popupmenu="wf-${i}-popup">
+ <a class="action-button" href="${h.url_for( action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">Edit</a>
+ <a class="action-button" href="${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(workflow.id) )}" target="_parent">Run</a>
+ <a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id(workflow.id) )}">Share or Publish</a>
+ <a class="action-button" href="${h.url_for( action='clone', id=trans.security.encode_id(workflow.id) )}">Clone</a>
+ <a class="action-button" href="${h.url_for( action='rename', id=trans.security.encode_id(workflow.id) )}">Rename</a>
+ <a class="action-button" confirm="Are you sure you want to delete workflow '${workflow.name}'?" href="${h.url_for( action='delete', id=trans.security.encode_id(workflow.id) )}">Delete</a>
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </table>
+ %else:
- You have no workflows.
+ You have no workflows.
-%endif
+ %endif
-<h2>Workflows shared with you by others</h2>
+ <h2>Workflows shared with you by others</h2>
-%if shared_by_others:
- <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr class="header">
- <th>Name</th>
- <th>Owner</th>
- <th># of Steps</th>
- <th></th>
- </tr>
- %for i, association in enumerate( shared_by_others ):
- <% workflow = association.stored_workflow %>
- <tr>
- <td>
- <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a>
- </td>
- <td>${workflow.user.email}</td>
- <td>${len(workflow.latest_workflow.steps)}</td>
- <td>
- <div popupmenu="shared-${i}-popup">
- <a class="action-button" href="${h.url_for( action='display_by_username_and_slug', username=workflow.user.username, slug=workflow.slug)}" target="_top">View</a>
- <a class="action-button" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">Run</a>
- <a class="action-button" href="${h.url_for( action='clone', id=trans.security.encode_id(workflow.id) )}">Clone</a>
- </div>
- </td>
- </tr>
- %endfor
- </table>
-%else:
+ %if shared_by_others:
+ <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
+ <tr class="header">
+ <th>Name</th>
+ <th>Owner</th>
+ <th># of Steps</th>
+ <th></th>
+ </tr>
+ %for i, association in enumerate( shared_by_others ):
+ <% workflow = association.stored_workflow %>
+ <tr>
+ <td>
+ <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a>
+ </td>
+ <td>${workflow.user.email}</td>
+ <td>${len(workflow.latest_workflow.steps)}</td>
+ <td>
+ <div popupmenu="shared-${i}-popup">
+ <a class="action-button" href="${h.url_for( action='display_by_username_and_slug', username=workflow.user.username, slug=workflow.slug)}" target="_top">View</a>
+ <a class="action-button" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">Run</a>
+ <a class="action-button" href="${h.url_for( action='clone', id=trans.security.encode_id(workflow.id) )}">Clone</a>
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </table>
+ %else:
- No workflows have been shared with you.
+ No workflows have been shared with you.
-%endif
+ %endif
-<h2>Other options</h2>
+ <h2>Other options</h2>
-<a class="action-button" href="${h.url_for( action='configure_menu' )}">
- <span>Configure your workflow menu</span>
-</a>
\ No newline at end of file
+ <a class="action-button" href="${h.url_for( action='configure_menu' )}">
+ <span>Configure your workflow menu</span>
+ </a>
+ </div>
+ </div>
+</%def>
\ No newline at end of file
diff -r 48e83411aa91 -r 96ec861b4b6e templates/workflow/list_published.mako
--- a/templates/workflow/list_published.mako Fri Mar 12 16:11:26 2010 -0500
+++ b/templates/workflow/list_published.mako Sun Mar 14 11:49:44 2010 -0400
@@ -10,7 +10,7 @@
</%def>
<%def name="title()">
- Galaxy :: Published Workflows
+ Galaxy | Published Workflows
</%def>
<%def name="stylesheets()">
diff -r 48e83411aa91 -r 96ec861b4b6e test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Fri Mar 12 16:11:26 2010 -0500
+++ b/test/base/twilltestcase.py Sun Mar 14 11:49:44 2010 -0400
@@ -791,7 +791,7 @@
self.home()
# Create user, setting username to email.
self.visit_page( "user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( email, email, password, password ) )
- self.check_page_for_string( "Now logged in as %s" %email )
+ self.check_page_for_string( "now logged in as %s" %email )
self.home()
# Make sure a new private role was created for the user
self.visit_page( "user/set_default_permissions" )
@@ -816,7 +816,7 @@
for index, info_value in enumerate(user_info_values):
tc.fv( "1", "field_%i" % index, info_value )
tc.submit( "create_user_button" )
- self.check_page_for_string( "Now logged in as %s" % email )
+ self.check_page_for_string( "now logged in as %s" % email )
def create_user_with_info_as_admin( self, email, password, username, user_info_forms, user_info_form_id, user_info_values ):
'''
This method registers a new user and also provides use info as an admin
@@ -906,16 +906,17 @@
self.create( email=email, password=password )
except:
self.home()
- self.visit_url( "%s/user/login" % self.url )
+ # HACK: don't use panels because late_javascripts() messes up the twill browser and it can't find form fields (and hence user can't be logged in).
+ self.visit_url( "%s/user/login?use_panels=False" % self.url )
tc.fv( '1', 'email', email )
tc.fv( '1', 'password', password )
tc.submit( 'Login' )
- self.check_page_for_string( "Now logged in as %s" %email )
+ self.check_page_for_string( "now logged in as %s" %email )
self.home()
def logout( self ):
self.home()
self.visit_page( "user/logout" )
- self.check_page_for_string( "You are no longer logged in" )
+ self.check_page_for_string( "You have been logged out" )
self.home()
# Functions associated with browsers, cookies, HTML forms and page visits
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/48e83411aa91
changeset: 3528:48e83411aa91
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Fri Mar 12 16:11:26 2010 -0500
description:
New separate functional test scripts for testing admin features, library features, library security and data security. These use a new test_db_util module for all db interaction ( other functional test scripts can be enhanced to use this ). A lot of code cleanup in the functional tests. In twilltestcase, cleaned up library and security related methods to mirror names in recently merged library code.
diffstat:
lib/galaxy/web/controllers/library_common.py | 7 +-
test/base/test_db_util.py | 123 +
test/base/twilltestcase.py | 342 ++-
test/functional/test_admin_features.py | 422 ++++
test/functional/test_data_security.py | 196 ++
test/functional/test_library_features.py | 606 ++++++
test/functional/test_library_security.py | 603 ++++++
test/functional/test_security_and_libraries.py | 2141 ------------------------
8 files changed, 2167 insertions(+), 2273 deletions(-)
diffs (truncated from 4641 to 3000 lines):
diff -r e39c9a2a0b4c -r 48e83411aa91 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Fri Mar 12 14:27:04 2010 -0500
+++ b/lib/galaxy/web/controllers/library_common.py Fri Mar 12 16:11:26 2010 -0500
@@ -155,7 +155,7 @@
library.root_folder.description = new_description
trans.sa_session.add_all( ( library, library.root_folder ) )
trans.sa_session.flush()
- msg = "Library '%s' has been renamed to '%s'" % ( old_name, new_name )
+ msg = "The information has been updated."
return trans.response.send_redirect( web.url_for( controller='library_common',
action='library_info',
cntrller=cntrller,
@@ -313,7 +313,7 @@
folder.description = new_description
trans.sa_session.add( folder )
trans.sa_session.flush()
- msg = "Folder '%s' has been renamed to '%s'" % ( old_name, new_name )
+ msg = "The information has been updated."
messagetype='done'
else:
msg = "You are not authorized to edit this folder"
@@ -698,7 +698,6 @@
trans.app.security_agent.derive_roles_from_access( trans, trans.app.security.decode_id( library_id ), cntrller, library=True, **vars )
if error:
messagetype = 'error'
-
trans.response.send_redirect( web.url_for( controller='library_common',
action='upload_library_dataset',
cntrller=cntrller,
@@ -1171,7 +1170,7 @@
library_dataset.info = new_info
trans.sa_session.add( library_dataset )
trans.sa_session.flush()
- msg = "Dataset '%s' has been renamed to '%s'" % ( old_name, new_name )
+ msg = "The information has been updated."
messagetype = 'done'
else:
msg = "You are not authorized to change the attributes of this dataset"
diff -r e39c9a2a0b4c -r 48e83411aa91 test/base/test_db_util.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/base/test_db_util.py Fri Mar 12 16:11:26 2010 -0500
@@ -0,0 +1,123 @@
+import galaxy.model
+from galaxy.model.orm import *
+from galaxy.model.mapping import context as sa_session
+from base.twilltestcase import *
+import sys
+
+def flush( obj ):
+ sa_session.add( obj )
+ sa_session.flush()
+def get_all_histories_for_user( user ):
+ return sa_session.query( galaxy.model.History ) \
+ .filter( and_( galaxy.model.History.table.c.user_id==user.id,
+ galaxy.model.History.table.c.deleted==False ) ) \
+ .all()
+def get_dataset_permissions_by_dataset( dataset ):
+ return sa_session.query( galaxy.model.DatasetPermissions ) \
+ .filter( galaxy.model.DatasetPermissions.table.c.dataset_id==dataset.id ) \
+ .all()
+def get_dataset_permissions_by_role( role ):
+ return sa_session.query( galaxy.model.DatasetPermissions ) \
+ .filter( galaxy.model.DatasetPermissions.table.c.role_id == role.id ) \
+ .first()
+def get_default_history_permissions_by_history( history ):
+ return sa_session.query( galaxy.model.DefaultHistoryPermissions ) \
+ .filter( galaxy.model.DefaultHistoryPermissions.table.c.history_id==history.id ) \
+ .all()
+def get_default_history_permissions_by_role( role ):
+ return sa_session.query( galaxy.model.DefaultHistoryPermissions ) \
+ .filter( galaxy.model.DefaultHistoryPermissions.table.c.role_id == role.id ) \
+ .all()
+def get_default_user_permissions_by_role( role ):
+ return sa_session.query( galaxy.model.DefaultUserPermissions ) \
+ .filter( galaxy.model.DefaultUserPermissions.table.c.role_id == role.id ) \
+ .all()
+def get_default_user_permissions_by_user( user ):
+ return sa_session.query( galaxy.model.DefaultUserPermissions ) \
+ .filter( galaxy.model.DefaultUserPermissions.table.c.user_id==user.id ) \
+ .all()
+def get_form( name ):
+ fdc_list = sa_session.query( galaxy.model.FormDefinitionCurrent ) \
+ .filter( galaxy.model.FormDefinitionCurrent.table.c.deleted == False ) \
+ .order_by( galaxy.model.FormDefinitionCurrent.table.c.create_time.desc() )
+ for fdc in fdc_list:
+ sa_session.refresh( fdc )
+ sa_session.refresh( fdc.latest_form )
+ if fdc.latest_form.name == name:
+ return fdc.latest_form
+ return None
+def get_folder( parent_id, name, description ):
+ return sa_session.query( galaxy.model.LibraryFolder ) \
+ .filter( and_( galaxy.model.LibraryFolder.table.c.parent_id==parent_id,
+ galaxy.model.LibraryFolder.table.c.name==name,
+ galaxy.model.LibraryFolder.table.c.description==description ) ) \
+ .first()
+def get_group_by_name( name ):
+ return sa_session.query( galaxy.model.Group ).filter( galaxy.model.Group.table.c.name==name ).first()
+def get_group_role_associations_by_group( group ):
+ return sa_session.query( galaxy.model.GroupRoleAssociation ) \
+ .filter( galaxy.model.GroupRoleAssociation.table.c.group_id == group.id ) \
+ .all()
+def get_group_role_associations_by_role( role ):
+ return sa_session.query( galaxy.model.GroupRoleAssociation ) \
+ .filter( galaxy.model.GroupRoleAssociation.table.c.role_id == role.id ) \
+ .all()
+def get_latest_dataset():
+ return sa_session.query( galaxy.model.Dataset ) \
+ .order_by( desc( galaxy.model.Dataset.table.c.create_time ) ) \
+ .first()
+def get_latest_hda():
+ return sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
+ .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ) \
+ .first()
+def get_latest_history_for_user( user ):
+ return sa_session.query( galaxy.model.History ) \
+ .filter( and_( galaxy.model.History.table.c.deleted==False,
+ galaxy.model.History.table.c.user_id==user.id ) ) \
+ .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
+ .first()
+def get_latest_ldda():
+ return sa_session.query( galaxy.model.LibraryDatasetDatasetAssociation ) \
+ .order_by( desc( galaxy.model.LibraryDatasetDatasetAssociation.table.c.create_time ) ) \
+ .first()
+def get_latest_lddas( limit ):
+ return sa_session.query( galaxy.model.LibraryDatasetDatasetAssociation ) \
+ .order_by( desc( galaxy.model.LibraryDatasetDatasetAssociation.table.c.update_time ) ) \
+ .limit( limit )
+def get_library( name, description, synopsis ):
+ return sa_session.query( galaxy.model.Library ) \
+ .filter( and_( galaxy.model.Library.table.c.name==name,
+ galaxy.model.Library.table.c.description==description,
+ galaxy.model.Library.table.c.synopsis==synopsis,
+ galaxy.model.Library.table.c.deleted==False ) ) \
+ .first()
+def get_private_role( user ):
+ for role in user.all_roles():
+ if role.name == user.email and role.description == 'Private Role for %s' % user.email:
+ return role
+ raise AssertionError( "Private role not found for user '%s'" % user.email )
+def get_role_by_name( name ):
+ return sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
+def get_user( email ):
+ return sa_session.query( galaxy.model.User ) \
+ .filter( galaxy.model.User.table.c.email==email ) \
+ .first()
+def get_user_group_associations_by_group( group ):
+ return sa_session.query( galaxy.model.UserGroupAssociation ) \
+ .filter( galaxy.model.UserGroupAssociation.table.c.group_id == group.id ) \
+ .all()
+def get_user_role_associations_by_role( role ):
+ return sa_session.query( galaxy.model.UserRoleAssociation ) \
+ .filter( galaxy.model.UserRoleAssociation.table.c.role_id == role.id ) \
+ .all()
+def refresh( obj ):
+ sa_session.refresh( obj )
+def set_library_permissions( in_list ):
+ permissions_in = []
+ permissions_out = []
+ for k, v in galaxy.model.Library.permitted_actions.items():
+ if k in in_list:
+ permissions_in.append( k )
+ else:
+ permissions_out.append( k )
+ return permissions_in, permissions_out
diff -r e39c9a2a0b4c -r 48e83411aa91 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Fri Mar 12 14:27:04 2010 -0500
+++ b/test/base/twilltestcase.py Fri Mar 12 16:11:26 2010 -0500
@@ -535,21 +535,55 @@
if check_str:
self.check_page_for_string( check_str )
self.home()
- def edit_hda_attribute_info( self, hda_id, new_name='', new_info='', new_dbkey='', new_startcol='' ):
+ def edit_hda_attribute_info( self, hda_id, new_name='', new_info='', new_dbkey='', new_startcol='',
+ check_str1='', check_str2='', check_str3='', check_str4='',
+ not_displayed1='', not_displayed2='', not_displayed3='' ):
"""Edit history_dataset_association attribute information"""
self.home()
self.visit_url( "%s/root/edit?id=%s" % ( self.url, hda_id ) )
+ submit_required = False
self.check_page_for_string( 'Edit Attributes' )
if new_name:
tc.fv( 'edit_attributes', 'name', new_name )
+ submit_required = True
if new_info:
tc.fv( 'edit_attributes', 'info', new_info )
+ submit_required = True
if new_dbkey:
tc.fv( 'edit_attributes', 'dbkey', new_dbkey )
+ submit_required = True
if new_startcol:
tc.fv( 'edit_attributes', 'startCol', new_startcol )
- tc.submit( 'save' )
- self.check_page_for_string( 'Attributes updated' )
+ submit_required = True
+ if submit_required:
+ tc.submit( 'save' )
+ self.check_page_for_string( 'Attributes updated' )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if check_str2:
+ self.check_page_for_string( check_str2 )
+ if check_str3:
+ self.check_page_for_string( check_str3 )
+ if check_str4:
+ self.check_page_for_string( check_str4 )
+ if not_displayed1:
+ try:
+ self.check_page_for_string( not_displayed1 )
+ raise AssertionError, "String (%s) incorrectly displayed on Edit Attributes page." % not_displayed
+ except:
+ pass
+ if not_displayed2:
+ try:
+ self.check_page_for_string( not_displayed2 )
+ raise AssertionError, "String (%s) incorrectly displayed on Edit Attributes page." % not_displayed
+ except:
+ pass
+ if not_displayed3:
+ try:
+ self.check_page_for_string( not_displayed3 )
+ raise AssertionError, "String (%s) incorrectly displayed on Edit Attributes page." % not_displayed
+ except:
+ pass
self.home()
def auto_detect_metadata( self, hda_id ):
"""Auto-detect history_dataset_association metadata"""
@@ -1164,12 +1198,10 @@
check_str = "Purged 1 users"
self.check_page_for_string( check_str )
self.home()
- def associate_roles_and_groups_with_user( self, user_id, email,
- in_role_ids=[], out_role_ids=[],
- in_group_ids=[], out_group_ids=[],
- check_str='' ):
+ def manage_roles_and_groups_for_user( self, user_id, in_role_ids=[], out_role_ids=[],
+ in_group_ids=[], out_group_ids=[], check_str='' ):
self.home()
- url = "%s/admin/manage_roles_and_groups_for_user?id=%s&user_roles_groups_edit_button=Save" % ( self.url, user_id )
+ url = "%s/admin/manage_roles_and_groups_for_user?id=%s" % ( self.url, user_id )
if in_role_ids:
url += "&in_roles=%s" % ','.join( in_role_ids )
if out_role_ids:
@@ -1178,12 +1210,18 @@
url += "&in_groups=%s" % ','.join( in_group_ids )
if out_group_ids:
url += "&out_groups=%s" % ','.join( out_group_ids )
+ if in_role_ids or out_role_ids or in_group_ids or out_group_ids:
+ url += "&user_roles_groups_edit_button=Save"
self.visit_url( url )
if check_str:
self.check_page_for_string( check_str )
self.home()
# Tests associated with roles
+ def browse_roles( self, check_str1='' ):
+ self.visit_url( '%s/admin/roles' % self.url )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
def create_role( self,
name='Role One',
description="This is Role One",
@@ -1280,6 +1318,10 @@
self.visit_url( "%s/admin/groups" % self.url )
self.check_page_for_string( name )
self.home()
+ def browse_groups( self, check_str1='' ):
+ self.visit_url( '%s/admin/groups' % self.url )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
def rename_group( self, group_id, name='Group One Renamed' ):
"""Rename a group"""
self.home()
@@ -1532,6 +1574,58 @@
self.check_page_for_string( 'Address <b>%s</b> has been added' % address_dict[ 'short_desc' ] )
# Library stuff
+ def add_library_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
+ """Add a new info template to a library item"""
+ self.home()
+ if item_type == 'library':
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s" % \
+ ( self.url, cntrller, item_type, library_id )
+ elif item_type == 'folder':
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s" % \
+ ( self.url, cntrller, item_type, library_id, folder_id )
+ elif item_type == 'ldda':
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s&ldda_id=%s" % \
+ ( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
+ self.visit_url( url )
+ self.check_page_for_string ( "Select a template for the" )
+ tc.fv( '1', 'form_id', form_id )
+ tc.fv( '1', 'inherit', '1' )
+ tc.submit( 'add_template_button' )
+ self.check_page_for_string = 'A template based on the form "%s" has been added to this' % form_name
+ self.home()
+ def browse_libraries_admin( self, deleted=False, check_str1='', check_str2='', not_displayed1='' ):
+ self.visit_url( '%s/library_admin/browse_libraries?sort=name&f-description=All&f-name=All&f-deleted=%s' % ( self.url, str( deleted ) ) )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if check_str2:
+ self.check_page_for_string( check_str2 )
+ if not_displayed1:
+ try:
+ self.check_page_for_string( not_displayed1 )
+ raise AssertionError, "String (%s) incorrectly displayed when browing library." % not_displayed1
+ except:
+ pass
+ def browse_libraries_regular_user( self, check_str1='', check_str2='' ):
+ self.visit_url( '%s/library/browse_libraries' % self.url )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if check_str2:
+ self.check_page_for_string( check_str2 )
+ def browse_library( self, cntrller, id, show_deleted=False,
+ check_str1='', check_str2='', check_str3='', not_displayed='', not_displayed2='' ):
+ self.visit_url( '%s/library_common/browse_library?cntrller=%s&id=%s&show_deleted=%s' % ( self.url, cntrller, id, str( show_deleted ) ) )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if check_str2:
+ self.check_page_for_string( check_str2 )
+ if check_str3:
+ self.check_page_for_string( check_str3 )
+ if not_displayed:
+ try:
+ self.check_page_for_string( not_displayed )
+ raise AssertionError, "String (%s) incorrectly displayed when browing library." % not_displayed
+ except:
+ pass
def create_library( self, name='Library One', description='This is Library One', synopsis='Synopsis for Library One' ):
"""Create a new library"""
self.home()
@@ -1544,6 +1638,28 @@
check_str = "The new library named '%s' has been created" % name
self.check_page_for_string( check_str )
self.home()
+ def library_info( self, cntrller, library_id, library_name, new_name='', new_description='', new_synopsis='',
+ ele_1_field_name='', ele_1_contents='', ele_2_field_name='', ele_2_contents='', check_str1='' ):
+ """Edit information about a library, optionally using an existing template with up to 2 elements"""
+ self.home()
+ self.visit_url( "%s/library_common/library_info?cntrller=%s&id=%s" % ( self.url, cntrller, library_id ) )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if new_name and new_description and new_synopsis:
+ tc.fv( '1', 'name', new_name )
+ tc.fv( '1', 'description', new_description )
+ tc.fv( '1', 'synopsis', new_synopsis )
+ tc.submit( 'library_info_button' )
+ self.check_page_for_string( "The information has been updated." )
+ # If there is a template, then there are 2 forms on this page and the template is the 2nd form
+ if ele_1_field_name and ele_1_contents and ele_2_field_name and ele_2_contents:
+ tc.fv( '2', ele_1_field_name, ele_1_contents )
+ tc.fv( '2', ele_2_field_name, ele_2_contents )
+ tc.submit( 'edit_info_button' )
+ elif ele_1_field_name and ele_1_contents:
+ tc.fv( '2', ele_1_field_name, ele_1_contents )
+ tc.submit( 'edit_info_button' )
+ self.home()
def library_permissions( self, library_id, library_name, role_ids_str, permissions_in, permissions_out, cntrller='library_admin' ):
# role_ids_str must be a comma-separated string of role ids
url = "library_common/library_permissions?id=%s&cntrller=%slibrary_admin&update_roles_button=Save" % ( library_id, cntrller )
@@ -1558,46 +1674,8 @@
check_str = "Permissions updated for library '%s'" % library_name
self.check_page_for_string( check_str )
self.home()
- def rename_library( self, library_id, old_name, name='Library One Renamed', description='This is Library One Re-described',
- synopsis='This is the new synopsis for Library One ', controller='library_admin' ):
- """Rename a library"""
- self.home()
- self.visit_url( "%s/library_common/library_info?id=%s&cntrller=%s" % ( self.url, library_id, controller ) )
- self.check_page_for_string( old_name )
- # Since twill barfs on the form submisson, we ar forced to simulate it
- url = "%s/library_common/library_info?id=%s&cntrller=%s&library_info_button=Save&description=%s&name=%s&synopsis=%s" % \
- ( self.url, library_id, controller, description.replace( ' ', '+' ), name.replace( ' ', '+' ), synopsis.replace( ' ', '+' ) )
- self.home()
- self.visit_url( url )
- check_str = "Library '%s' has been renamed to '%s'" % ( old_name, name )
- self.check_page_for_string( check_str )
- self.home()
- def add_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
- """Add a new info template to a library item"""
- self.home()
- if item_type == 'library':
- url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s" % ( self.url, cntrller, item_type, library_id )
- elif item_type == 'folder':
- url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id )
- elif item_type == 'ldda':
- url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s&ldda_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
- self.visit_url( url )
- self.check_page_for_string ( "Select a template for the" )
- tc.fv( '1', 'form_id', form_id )
- tc.fv( '1', 'inherit', '1' )
- tc.submit( 'add_template_button' )
- self.check_page_for_string = 'A template based on the form "%s" has been added to this' % form_name
- self.home()
- def library_info( self, library_id, library_name, ele_1_field_name, ele_1_contents, ele_2_field_name, ele_2_contents, controller='library_admin' ):
- """Add information to a library using an existing template with 2 elements"""
- self.home()
- self.visit_url( "%s/library_common/library_info?id=%s&cntrller=%s" % ( self.url, library_id, controller ) )
- check_str = 'Other information about library %s' % library_name
- self.check_page_for_string( check_str )
- tc.fv( '2', ele_1_field_name, ele_1_contents )
- tc.fv( '2', ele_2_field_name, ele_2_contents )
- tc.submit( 'create_new_info_button' )
- self.home()
+
+ # Library folder stuff
def add_folder( self, controller, library_id, folder_id, name='Folder One', description='This is Folder One' ):
"""Create a new folder"""
self.home()
@@ -1609,27 +1687,40 @@
check_str = "The new folder named '%s' has been added to the data library." % name
self.check_page_for_string( check_str )
self.home()
- def folder_info( self, controller, folder_id, library_id, name, new_name, description, contents='', field_name='' ):
+ def folder_info( self, cntrller, folder_id, library_id, name='', new_name='', description='',
+ field_name='', contents='', check_str1='', check_str2='', not_displayed='' ):
"""Add information to a library using an existing template with 2 elements"""
self.home()
self.visit_url( "%s/library_common/folder_info?cntrller=%s&id=%s&library_id=%s" % \
- ( self.url, controller, folder_id, library_id) )
+ ( self.url, cntrller, folder_id, library_id ) )
# Twill cannot handle the following call for some reason - it's buggy
# self.check_page_for_string( "Edit folder name and description" )
- tc.fv( '1', "name", new_name )
- tc.fv( '1', "description", description )
- tc.submit( 'rename_folder_button' )
- # Twill cannot handle the following call for some reason - it's buggy
- # check_str = "Folder '%s' has been renamed to '%s'" % ( name, new_name )
- # self.check_page_for_string( check_str )
- if contents and field_name:
+ if name and new_name and description:
+ tc.fv( '1', "name", new_name )
+ tc.fv( '1', "description", description )
+ tc.submit( 'rename_folder_button' )
+ # Twill barfs on this, so keep it commented...
+ #self.check_page_for_string( "The information has been updated." )
+ if field_name and contents:
# We have an information template associated with the folder, so
# there are 2 forms on this page and the template is the 2nd form
tc.fv( '2', field_name, contents )
tc.submit( 'edit_info_button' )
- # Twill cannot handle the following call for some reason - it's buggy
- # self.check_page_for_string( 'The information has been updated.' )
+ # Twill barfs on this, so keep it commented...
+ #self.check_page_for_string( 'The information has been updated.' )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if check_str2:
+ self.check_page_for_string( check_str2 )
+ if not_displayed:
+ try:
+ self.check_page_for_string( not_displayed )
+ raise AssertionError, "String (%s) should not have been displayed on folder info page." % not_displayed
+ except:
+ pass
self.home()
+
+ # Library dataset stuff
def add_library_dataset( self, cntrller, filename, library_id, folder_id, folder_name,
file_type='auto', dbkey='hg18', roles=[], message='', root=False,
template_field_name1='', template_field_contents1='', show_deleted='False',
@@ -1638,7 +1729,7 @@
filename = self.get_filename( filename )
self.home()
self.visit_url( "%s/library_common/upload_library_dataset?cntrller=%s&library_id=%s&folder_id=%s&upload_option=%s&message=%s" % \
- ( self.url, cntrller, library_id, folder_id, upload_option, message ) )
+ ( self.url, cntrller, library_id, folder_id, upload_option, message.replace( ' ', '+' ) ) )
self.check_page_for_string( 'Upload files' )
tc.fv( "1", "library_id", library_id )
tc.fv( "1", "folder_id", folder_id )
@@ -1659,68 +1750,77 @@
check_str = "Added 1 datasets to the folder '%s' (each is selected)." % folder_name
self.library_wait( library_id )
self.home()
- def set_library_dataset_permissions( self, cntrller, library_id, folder_id, ldda_id, ldda_name, role_ids_str, permissions_in, permissions_out ):
+ def ldda_permissions( self, cntrller, library_id, folder_id, id, role_ids_str,
+ permissions_in=[], permissions_out=[], check_str1='' ):
# role_ids_str must be a comma-separated string of role ids
- url = "library_common/ldda_permissions?cntrller=%s&library_id=%s&folder_id=%s&id=%s&update_roles_button=Save" % \
- ( cntrller, library_id, folder_id, ldda_id )
+ url = "%s/library_common/ldda_permissions?cntrller=%s&library_id=%s&folder_id=%s&id=%s" % \
+ ( self.url, cntrller, library_id, folder_id, id )
for po in permissions_out:
key = '%s_out' % po
url ="%s&%s=%s" % ( url, key, role_ids_str )
for pi in permissions_in:
key = '%s_in' % pi
url ="%s&%s=%s" % ( url, key, role_ids_str )
- self.home()
- self.visit_url( "%s/%s" % ( self.url, url ) )
- check_str = "Permissions have been updated on 1 datasets"
+ if permissions_in or permissions_out:
+ url += "&update_roles_button=Save"
+ self.visit_url( url )
+ if check_str1:
+ check_str = check_str1
+ else:
+ check_str = "Permissions have been updated on 1 datasets"
self.check_page_for_string( check_str )
self.home()
- def edit_ldda_template_element_info( self, library_id, folder_id, ldda_id, ldda_name, ele_1_field_name,
- ele_1_contents, ele_2_field_name, ele_2_contents, ele_1_help='', ele_2_help='',
- ele_3_field_name='', ele_3_contents='', ele_3_help='' ):
- """Edit library_dataset_dataset_association template element information"""
- self.home()
- self.visit_url( "%s/library_common/ldda_edit_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
- ( self.url, library_id, folder_id, ldda_id ) )
+ def ldda_edit_info( self, cntrller, library_id, folder_id, ldda_id, ldda_name, new_ldda_name='',
+ ele_1_field_name='', ele_1_contents='', ele_1_help='',
+ ele_2_field_name='', ele_2_contents='', ele_2_help='',
+ ele_3_field_name='', ele_3_contents='', ele_3_help='',
+ check_str1='', check_str2='', check_str3='', not_displayed='' ):
+ """Edit library_dataset_dataset_association information, optionally template element information"""
+ self.visit_url( "%s/library_common/ldda_edit_info?cntrller=%s&library_id=%s&folder_id=%s&id=%s" % \
+ ( self.url, cntrller, library_id, folder_id, ldda_id ) )
check_str = 'Edit attributes of %s' % ldda_name
self.check_page_for_string( check_str )
- ele_1_contents = ele_1_contents.replace( '+', ' ' )
- ele_2_contents = ele_2_contents.replace( '+', ' ' )
- tc.fv( '4', ele_1_field_name, ele_1_contents )
- tc.fv( '4', ele_2_field_name, ele_2_contents.replace( '+', ' ' ) )
+ if new_ldda_name:
+ tc.fv( '1', 'name', new_ldda_name )
+ tc.submit( 'save' )
+ check_str = 'Attributes updated for library dataset %s' % new_ldda_name
+ self.check_page_for_string( check_str )
+ # There are 4 forms on this page and the template is the 4th form
+ if ele_1_field_name and ele_1_contents:
+ ele_1_contents = ele_1_contents.replace( '+', ' ' )
+ tc.fv( '4', ele_1_field_name, ele_1_contents )
+ if ele_2_field_name and ele_2_contents:
+ ele_2_contents = ele_2_contents.replace( '+', ' ' )
+ tc.fv( '4', ele_2_field_name, ele_2_contents.replace( '+', ' ' ) )
if ele_3_field_name and ele_3_contents:
ele_3_contents = ele_3_contents.replace( '+', ' ' )
tc.fv( '4', ele_3_field_name, ele_3_contents )
- tc.submit( 'edit_info_button' )
- self.check_page_for_string( 'This is the latest version of this library dataset' )
- self.check_page_for_string( 'The information has been updated.' )
- self.check_page_for_string( ele_1_contents )
- self.check_page_for_string( ele_2_contents )
- if ele_3_field_name and ele_3_contents:
+ if ele_1_field_name:
+ tc.submit( 'edit_info_button' )
+ self.check_page_for_string( 'This is the latest version of this library dataset' )
+ self.check_page_for_string( 'The information has been updated.' )
+ self.check_page_for_string( ele_1_contents )
+ if ele_2_field_name:
+ self.check_page_for_string( ele_2_contents )
+ if ele_3_field_name:
self.check_page_for_string( ele_3_contents )
if ele_1_help:
check_str = ele_1_help.replace( '+', ' ' )
self.check_page_for_string( check_str )
- self.check_page_for_string( ele_2_contents )
if ele_2_help:
check_str = ele_2_help.replace( '+', ' ' )
self.check_page_for_string( check_str )
if ele_2_help:
check_str = ele_3_help.replace( '+', ' ' )
self.check_page_for_string( check_str )
- self.home()
- def edit_ldda_attribute_info( self, cntrller, library_id, folder_id, ldda_id, ldda_name, new_ldda_name ):
- """Edit library_dataset_dataset_association attribute information"""
- self.home()
- self.visit_url( "%s/library_common/ldda_edit_info?cntrller=%s&library_id=%s&folder_id=%s&id=%s" % \
- ( self.url, cntrller, library_id, folder_id, ldda_id ) )
- check_str = 'Edit attributes of %s' % ldda_name
- self.check_page_for_string( check_str )
- tc.fv( '1', 'name', new_ldda_name )
- tc.submit( 'save' )
- check_str = 'Attributes updated for library dataset %s' % new_ldda_name
- self.check_page_for_string( check_str )
- check_str = 'Edit attributes of %s' % new_ldda_name
- self.check_page_for_string( check_str )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
+ if not_displayed:
+ try:
+ self.check_page_for_string( not_displayed )
+ raise AssertionError, "String (%s) should not have been displayed on ldda Edit Attributes page." % not_displayed
+ except:
+ pass
self.home()
def upload_new_dataset_version( self, cntrller, filename, library_id, folder_id, folder_name, library_dataset_id, ldda_name, file_type='auto',
dbkey='hg18', message='', template_field_name1='', template_field_contents1='' ):
@@ -1755,19 +1855,21 @@
check_str = "Added 1 datasets to the folder '%s' (each is selected)." % folder_name
self.check_page_for_string( check_str )
self.home()
- def add_dir_of_files_from_admin_view( self, library_id, folder_id, file_type='auto', dbkey='hg18', roles_tuple=[],
- message='', check_str_after_submit='', template_field_name1='', template_field_contents1='' ):
+ def upload_directory_of_files( self, cntrller, library_id, folder_id, server_dir, file_type='auto', dbkey='hg18', roles_tuple=[],
+ message='', check_str1='', check_str_after_submit='', template_field_name1='', template_field_contents1='' ):
"""Add a directory of datasets to a folder"""
# roles is a list of tuples: [ ( role_id, role_description ) ]
- self.home()
- self.visit_url( "%s/library_common/upload_library_dataset?cntrller=library_admin&upload_option=upload_directory&library_id=%s&folder_id=%s" % \
- ( self.url, library_id, folder_id ) )
+ url = "%s/library_common/upload_library_dataset?cntrller=%s&library_id=%s&folder_id=%s&upload_option=upload_directory" % \
+ ( self.url, cntrller, library_id, folder_id )
+ self.visit_url( url )
self.check_page_for_string( 'Upload a directory of files' )
+ if check_str1:
+ self.check_page_for_strin( check_str1 )
tc.fv( "1", "folder_id", folder_id )
tc.fv( "1", "file_type", file_type )
tc.fv( "1", "dbkey", dbkey )
- tc.fv( "1", "message", message.replace( '+', ' ' ) )
- tc.fv( "1", "server_dir", "library" )
+ tc.fv( "1", "message", message )
+ tc.fv( "1", "server_dir", server_dir )
for role_tuple in roles_tuple:
tc.fv( "1", "roles", role_tuple[1] ) # role_tuple[1] is the role name
# Add template field contents, if any...
@@ -1778,29 +1880,13 @@
self.check_page_for_string( check_str_after_submit )
self.library_wait( library_id )
self.home()
- def add_dir_of_files_from_libraries_view( self, library_id, folder_id, selected_dir, file_type='auto', dbkey='hg18', roles_tuple=[],
- message='', check_str_after_submit='', template_field_name1='', template_field_contents1='' ):
- """Add a directory of datasets to a folder"""
- # roles is a list of tuples: [ ( role_id, role_description ) ]
- self.home()
- self.visit_url( "%s/library_common/upload_library_dataset?cntrller=library&upload_option=upload_directory&library_id=%s&folder_id=%s" % \
- ( self.url, library_id, folder_id ) )
- self.check_page_for_string( 'Upload a directory of files' )
- tc.fv( "1", "folder_id", folder_id )
- tc.fv( "1", "file_type", file_type )
- tc.fv( "1", "dbkey", dbkey )
- tc.fv( "1", "message", message.replace( '+', ' ' ) )
- tc.fv( "1", "server_dir", selected_dir )
- for role_tuple in roles_tuple:
- tc.fv( "1", "roles", role_tuple[1] ) # role_tuple[1] is the role name
- # Add template field contents, if any...
- if template_field_name1:
- tc.fv( "1", template_field_name1, template_field_contents1 )
- tc.submit( "runtool_btn" )
- if check_str_after_submit:
- self.check_page_for_string( check_str_after_submit )
- self.library_wait( library_id, cntrller='library' )
- self.home()
+ def act_on_multiple_datasets( self, cntrller, library_id, do_action, ldda_ids='', check_str1='' ):
+ # Can't use the ~/library_admin/libraries form as twill barfs on it so we'll simulate the form submission
+ # by going directly to the form action
+ self.visit_url( '%s/library_common/act_on_multiple_datasets?cntrller=%s&library_id=%s&ldda_ids=%s&do_action=%s' \
+ % ( self.url, cntrller, library_id, ldda_ids, do_action ) )
+ if check_str1:
+ self.check_page_for_string( check_str1 )
def download_archive_of_library_files( self, cntrller, library_id, ldda_ids, format ):
self.home()
# Here it would be ideal to have twill set form values and submit the form, but
diff -r e39c9a2a0b4c -r 48e83411aa91 test/functional/test_admin_features.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/functional/test_admin_features.py Fri Mar 12 16:11:26 2010 -0500
@@ -0,0 +1,422 @@
+from base.twilltestcase import *
+from base.test_db_util import *
+
+class TestDataSecurity( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ def test_005_create_new_user_account_as_admin( self ):
+ """Testing creating a new user account as admin"""
+ # Logged in as admin_user
+ email = 'test3(a)bx.psu.edu'
+ password = 'testuser'
+ previously_created = self.create_new_account_as_admin( email=email, password=password )
+ # Get the user object for later tests
+ global regular_user3
+ regular_user3 = get_user( email )
+ assert regular_user3 is not None, 'Problem retrieving user with email "%s" from the database' % email
+ global regular_user3_private_role
+ regular_user3_private_role = get_private_role( regular_user3 )
+ # Make sure DefaultUserPermissions were created
+ if not regular_user3.default_permissions:
+ raise AssertionError( 'No DefaultUserPermissions were created for user %s when the admin created the account' % email )
+ # Make sure a private role was created for the user
+ if not regular_user3.roles:
+ raise AssertionError( 'No UserRoleAssociations were created for user %s when the admin created the account' % email )
+ if not previously_created and len( regular_user3.roles ) != 1:
+ raise AssertionError( '%d UserRoleAssociations were created for user %s when the admin created the account ( should have been 1 )' \
+ % ( len( regular_user3.roles ), regular_user3.email ) )
+ for ura in regular_user3.roles:
+ role = sa_session.query( galaxy.model.Role ).get( ura.role_id )
+ if not previously_created and role.type != 'private':
+ raise AssertionError( 'Role created for user %s when the admin created the account is not private, type is' \
+ % str( role.type ) )
+ if not previously_created:
+ # Make sure a history was not created ( previous test runs may have left deleted histories )
+ histories = get_all_histories_for_user( regular_user3 )
+ if histories:
+ raise AssertionError( 'Histories were incorrectly created for user %s when the admin created the account' % email )
+ # Make sure the user was not associated with any groups
+ if regular_user3.groups:
+ raise AssertionError( 'Groups were incorrectly associated with user %s when the admin created the account' % email )
+ def test_010_reset_password_as_admin( self ):
+ """Testing reseting a user password as admin"""
+ self.reset_password_as_admin( user_id=self.security.encode_id( regular_user3.id ), password='testreset' )
+ def test_015_login_after_password_reset( self ):
+ """Testing logging in after an admin reset a password - tests DefaultHistoryPermissions for accounts created by an admin"""
+ # logged in as admin_user
+ self.logout()
+ self.login( email=regular_user3.email, password='testreset' )
+ # Make sure a History and HistoryDefaultPermissions exist for the user
+ latest_history = get_latest_history_for_user( regular_user3 )
+ if not latest_history.user_id == regular_user3.id:
+ raise AssertionError( 'A history was not created for user %s when he logged in' % email )
+ if not latest_history.default_permissions:
+ raise AssertionError( 'No DefaultHistoryPermissions were created for history id %d when it was created' % latest_history.id )
+ dhps = get_default_history_permissions_by_history( latest_history )
+ if len( dhps ) > 1:
+ raise AssertionError( 'More than 1 DefaultHistoryPermissions were created for history id %d when it was created' % latest_history.id )
+ dhp = dhps[0]
+ if not dhp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
+ raise AssertionError( 'The DefaultHistoryPermission.action for history id %d is "%s", but it should be "manage permissions"' \
+ % ( latest_history.id, dhp.action ) )
+ # Upload a file to create a HistoryDatasetAssociation
+ self.upload_file( '1.bed' )
+ latest_dataset = get_latest_dataset()
+ for dp in latest_dataset.actions:
+ # Should only have 1 DatasetPermissions
+ if dp.action != galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
+ raise AssertionError( 'The DatasetPermissions for dataset id %d is %s ( should have been %s )' \
+ % ( latest_dataset.id,
+ latest_dataset.actions.action,
+ galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
+ self.logout()
+ # Reset the password to the default for later tests
+ self.login( email='test(a)bx.psu.edu' )
+ self.reset_password_as_admin( user_id=self.security.encode_id( regular_user3.id ), password='testuser' )
+ def test_020_mark_user_deleted( self ):
+ """Testing marking a user account as deleted"""
+ # Logged in as admin_user
+ self.mark_user_deleted( user_id=self.security.encode_id( regular_user3.id ), email=regular_user3.email )
+ if not regular_user3.active_histories:
+ raise AssertionError( 'HistoryDatasetAssociations for regular_user3 were incorrectly deleted when the user was marked deleted' )
+ def test_025_undelete_user( self ):
+ """Testing undeleting a user account"""
+ # Logged in as admin_user
+ self.undelete_user( user_id=self.security.encode_id( regular_user3.id ), email=regular_user3.email )
+ def test_030_create_role( self ):
+ """Testing creating new role with 3 members ( and a new group named the same ), then renaming the role"""
+ # Logged in as admin_user
+ name = 'Role One'
+ description = "This is Role Ones description"
+ user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=[],
+ create_group_for_role='yes',
+ private_role=admin_user.email )
+ # Get the role object for later tests
+ global role_one
+ role_one = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
+ assert role_one is not None, 'Problem retrieving role named "Role One" from the database'
+ # Make sure UserRoleAssociations are correct
+ if len( role_one.users ) != len( user_ids ):
+ raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created ( should have been %d )' \
+ % ( len( role_one.users ), role_one.id, len( user_ids ) ) )
+ # Each of the following users should now have 2 role associations, their private role and role_one
+ for user in [ admin_user, regular_user1, regular_user3 ]:
+ refresh( user )
+ if len( user.roles ) != 2:
+ raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 2 )' \
+ % ( len( user.roles ), user.email ) )
+ # Make sure the group was created
+ self.visit_url( '%s/admin/groups' % self.url )
+ self.check_page_for_string( name )
+ global group_zero
+ group_zero = get_group_by_name( name )
+ # Rename the role
+ rename = "Role One's been Renamed"
+ new_description="This is Role One's Re-described"
+ self.rename_role( self.security.encode_id( role_one.id ), name=rename, description=new_description )
+ self.visit_url( '%s/admin/roles' % self.url )
+ self.check_page_for_string( rename )
+ self.check_page_for_string( new_description )
+ # Reset the role back to the original name and description
+ self.rename_role( self.security.encode_id( role_one.id ), name=name, description=description )
+ def test_035_create_group( self ):
+ """Testing creating new group with 3 members and 1 associated role, then renaming it"""
+ # Logged in as admin_user
+ name = "Group One's Name"
+ user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
+ role_ids=[ str( role_one.id ) ]
+ self.create_group( name=name, in_user_ids=user_ids, in_role_ids=role_ids )
+ # Get the group object for later tests
+ global group_one
+ group_one = get_group_by_name( name )
+ assert group_one is not None, 'Problem retrieving group named "Group One" from the database'
+ # Make sure UserGroupAssociations are correct
+ if len( group_one.users ) != len( user_ids ):
+ raise AssertionError( '%d UserGroupAssociations were created for group id %d when it was created ( should have been %d )' \
+ % ( len( group_one.users ), group_one.id, len( user_ids ) ) )
+ # Each user should now have 1 group association, group_one
+ for user in [ admin_user, regular_user1, regular_user3 ]:
+ refresh( user )
+ if len( user.groups ) != 1:
+ raise AssertionError( '%d UserGroupAssociations are associated with user %s ( should be 1 )' % ( len( user.groups ), user.email ) )
+ # Make sure GroupRoleAssociations are correct
+ if len( group_one.roles ) != len( role_ids ):
+ raise AssertionError( '%d GroupRoleAssociations were created for group id %d when it was created ( should have been %d )' \
+ % ( len( group_one.roles ), group_one.id, len( role_ids ) ) )
+ # Rename the group
+ rename = "Group One's been Renamed"
+ self.rename_group( self.security.encode_id( group_one.id ), name=rename, )
+ self.home()
+ self.visit_url( '%s/admin/groups' % self.url )
+ self.check_page_for_string( rename )
+ # Reset the group back to the original name
+ self.rename_group( self.security.encode_id( group_one.id ), name=name )
+ def test_040_add_members_and_role_to_group( self ):
+ """Testing editing user membership and role associations of an existing group"""
+ # Logged in as admin_user
+ name = 'Group Two'
+ self.create_group( name=name, in_user_ids=[], in_role_ids=[] )
+ # Get the group object for later tests
+ global group_two
+ group_two = get_group_by_name( name )
+ assert group_two is not None, 'Problem retrieving group named "Group Two" from the database'
+ # group_two should have no associations
+ if group_two.users:
+ raise AssertionError( '%d UserGroupAssociations were created for group id %d when it was created ( should have been 0 )' \
+ % ( len( group_two.users ), group_two.id ) )
+ if group_two.roles:
+ raise AssertionError( '%d GroupRoleAssociations were created for group id %d when it was created ( should have been 0 )' \
+ % ( len( group_two.roles ), group_two.id ) )
+ user_ids = [ str( regular_user1.id ) ]
+ role_ids = [ str( role_one.id ) ]
+ self.associate_users_and_roles_with_group( self.security.encode_id( group_two.id ),
+ group_two.name,
+ user_ids=user_ids,
+ role_ids=role_ids )
+ def test_045_create_role_with_user_and_group_associations( self ):
+ """Testing creating a role with user and group associations"""
+ # Logged in as admin_user
+ # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
+ # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT
+ # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the
+ # associate_users_and_groups_with_role() method.
+ name = 'Role Two'
+ description = 'This is Role Two'
+ user_ids=[ str( admin_user.id ) ]
+ group_ids=[ str( group_two.id ) ]
+ private_role=admin_user.email
+ # Create the role
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=group_ids,
+ private_role=private_role )
+ # Get the role object for later tests
+ global role_two
+ role_two = get_role_by_name( name )
+ assert role_two is not None, 'Problem retrieving role named "Role Two" from the database'
+ # Make sure UserRoleAssociations are correct
+ if len( role_two.users ) != len( user_ids ):
+ raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created with %d members' \
+ % ( len( role_two.users ), role_two.id, len( user_ids ) ) )
+ # admin_user should now have 3 role associations, private role, role_one, role_two
+ refresh( admin_user )
+ if len( admin_user.roles ) != 3:
+ raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 3 )' % ( len( admin_user.roles ), admin_user.email ) )
+ # Make sure GroupRoleAssociations are correct
+ refresh( role_two )
+ if len( role_two.groups ) != len( group_ids ):
+ raise AssertionError( '%d GroupRoleAssociations were created for role id %d when it was created ( should have been %d )' \
+ % ( len( role_two.groups ), role_two.id, len( group_ids ) ) )
+ # group_two should now be associated with 2 roles: role_one, role_two
+ refresh( group_two )
+ if len( group_two.roles ) != 2:
+ raise AssertionError( '%d GroupRoleAssociations are associated with group id %d ( should be 2 )' % ( len( group_two.roles ), group_two.id ) )
+ def test_050_change_user_role_associations( self ):
+ """Testing changing roles associated with a user"""
+ # Logged in as admin_user
+ # Create a new role with no associations
+ name = 'Role Three'
+ description = 'This is Role Three'
+ user_ids=[]
+ group_ids=[]
+ private_role=admin_user.email
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=group_ids,
+ private_role=private_role )
+ # Get the role object for later tests
+ global role_three
+ role_three = get_role_by_name( name )
+ assert role_three is not None, 'Problem retrieving role named "Role Three" from the database'
+ # Associate the role with a user
+ refresh( admin_user )
+ role_ids = []
+ for ura in admin_user.non_private_roles:
+ role_ids.append( str( ura.role_id ) )
+ role_ids.append( str( role_three.id ) )
+ group_ids = []
+ for uga in admin_user.groups:
+ group_ids.append( str( uga.group_id ) )
+ check_str = "User '%s' has been updated with %d associated roles and %d associated groups" % \
+ ( admin_user.email, len( role_ids ), len( group_ids ) )
+ self.manage_roles_and_groups_for_user( self.security.encode_id( admin_user.id ),
+ in_role_ids=role_ids,
+ in_group_ids=group_ids,
+ check_str=check_str )
+ refresh( admin_user )
+ # admin_user should now be associated with 4 roles: private, role_one, role_two, role_three
+ if len( admin_user.roles ) != 4:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 4 )' % \
+ ( len( admin_user.roles ), admin_user.email ) )
+ def test_055_mark_group_deleted( self ):
+ """Testing marking a group as deleted"""
+ # Logged in as admin_user
+ self.browse_groups( check_str1=group_two.name )
+ self.mark_group_deleted( self.security.encode_id( group_two.id ), group_two.name )
+ refresh( group_two )
+ if not group_two.deleted:
+ raise AssertionError( '%s was not correctly marked as deleted.' % group_two.name )
+ # Deleting a group should not delete any associations
+ if not group_two.members:
+ raise AssertionError( '%s incorrectly lost all members when it was marked as deleted.' % group_two.name )
+ if not group_two.roles:
+ raise AssertionError( '%s incorrectly lost all role associations when it was marked as deleted.' % group_two.name )
+ def test_060_undelete_group( self ):
+ """Testing undeleting a deleted group"""
+ # Logged in as admin_user
+ self.undelete_group( self.security.encode_id( group_two.id ), group_two.name )
+ refresh( group_two )
+ if group_two.deleted:
+ raise AssertionError( '%s was not correctly marked as not deleted.' % group_two.name )
+ def test_065_mark_role_deleted( self ):
+ """Testing marking a role as deleted"""
+ # Logged in as admin_user
+ self.home()
+ self.browse_roles( check_str1=role_two.name )
+ self.mark_role_deleted( self.security.encode_id( role_two.id ), role_two.name )
+ refresh( role_two )
+ if not role_two.deleted:
+ raise AssertionError( '%s was not correctly marked as deleted.' % role_two.name )
+ # Deleting a role should not delete any associations
+ if not role_two.users:
+ raise AssertionError( '%s incorrectly lost all user associations when it was marked as deleted.' % role_two.name )
+ if not role_two.groups:
+ raise AssertionError( '%s incorrectly lost all group associations when it was marked as deleted.' % role_two.name )
+ def test_070_undelete_role( self ):
+ """Testing undeleting a deleted role"""
+ # Logged in as admin_user
+ self.undelete_role( self.security.encode_id( role_two.id ), role_two.name )
+ def test_075_purge_user( self ):
+ """Testing purging a user account"""
+ # Logged in as admin_user
+ self.mark_user_deleted( user_id=self.security.encode_id( regular_user3.id ), email=regular_user3.email )
+ refresh( regular_user3 )
+ self.purge_user( self.security.encode_id( regular_user3.id ), regular_user3.email )
+ refresh( regular_user3 )
+ if not regular_user3.purged:
+ raise AssertionError( 'User %s was not marked as purged.' % regular_user3.email )
+ # Make sure DefaultUserPermissions deleted EXCEPT FOR THE PRIVATE ROLE
+ if len( regular_user3.default_permissions ) != 1:
+ raise AssertionError( 'DefaultUserPermissions for user %s were not deleted.' % regular_user3.email )
+ for dup in regular_user3.default_permissions:
+ role = sa_session.query( galaxy.model.Role ).get( dup.role_id )
+ if role.type != 'private':
+ raise AssertionError( 'DefaultUserPermissions for user %s are not related with the private role.' % regular_user3.email )
+ # Make sure History deleted
+ for history in regular_user3.histories:
+ refresh( history )
+ if not history.deleted:
+ raise AssertionError( 'User %s has active history id %d after their account was marked as purged.' % ( regular_user3.email, hda.id ) )
+ # NOTE: Not all hdas / datasets will be deleted at the time a history is deleted - the cleanup_datasets.py script
+ # is responsible for this.
+ # Make sure UserGroupAssociations deleted
+ if regular_user3.groups:
+ raise AssertionError( 'User %s has active group id %d after their account was marked as purged.' % ( regular_user3.email, uga.id ) )
+ # Make sure UserRoleAssociations deleted EXCEPT FOR THE PRIVATE ROLE
+ if len( regular_user3.roles ) != 1:
+ raise AssertionError( 'UserRoleAssociations for user %s were not deleted.' % regular_user3.email )
+ for ura in regular_user3.roles:
+ role = sa_session.query( galaxy.model.Role ).get( ura.role_id )
+ if role.type != 'private':
+ raise AssertionError( 'UserRoleAssociations for user %s are not related with the private role.' % regular_user3.email )
+ def test_080_manually_unpurge_user( self ):
+ """Testing manually un-purging a user account"""
+ # Logged in as admin_user
+ # Reset the user for later test runs. The user's private Role and DefaultUserPermissions for that role
+ # should have been preserved, so all we need to do is reset purged and deleted.
+ # TODO: If we decide to implement the GUI feature for un-purging a user, replace this with a method call
+ regular_user3.purged = False
+ regular_user3.deleted = False
+ flush( regular_user3 )
+ def test_085_purge_group( self ):
+ """Testing purging a group"""
+ # Logged in as admin_user
+ self.mark_group_deleted( self.security.encode_id( group_two.id ), group_two.name )
+ self.purge_group( self.security.encode_id( group_two.id ), group_two.name )
+ # Make sure there are no UserGroupAssociations
+ if get_user_group_associations_by_group( group_two ):
+ raise AssertionError( "Purging the group did not delete the UserGroupAssociations for group_id '%s'" % group_two.id )
+ # Make sure there are no GroupRoleAssociations
+ if get_group_role_associations_by_group( group_two ):
+ raise AssertionError( "Purging the group did not delete the GroupRoleAssociations for group_id '%s'" % group_two.id )
+ # Undelete the group for later test runs
+ self.undelete_group( self.security.encode_id( group_two.id ), group_two.name )
+ def test_090_purge_role( self ):
+ """Testing purging a role"""
+ # Logged in as admin_user
+ self.mark_role_deleted( self.security.encode_id( role_two.id ), role_two.name )
+ self.purge_role( self.security.encode_id( role_two.id ), role_two.name )
+ # Make sure there are no UserRoleAssociations
+ if get_user_role_associations_by_role( role_two ):
+ raise AssertionError( "Purging the role did not delete the UserRoleAssociations for role_id '%s'" % role_two.id )
+ # Make sure there are no DefaultUserPermissions associated with the Role
+ if get_default_user_permissions_by_role( role_two ):
+ raise AssertionError( "Purging the role did not delete the DefaultUserPermissions for role_id '%s'" % role_two.id )
+ # Make sure there are no DefaultHistoryPermissions associated with the Role
+ if get_default_history_permissions_by_role( role_two ):
+ raise AssertionError( "Purging the role did not delete the DefaultHistoryPermissions for role_id '%s'" % role_two.id )
+ # Make sure there are no GroupRoleAssociations
+ if get_group_role_associations_by_role( role_two ):
+ raise AssertionError( "Purging the role did not delete the GroupRoleAssociations for role_id '%s'" % role_two.id )
+ # Make sure there are no DatasetPermissionss
+ if get_dataset_permissions_by_role( role_two ):
+ raise AssertionError( "Purging the role did not delete the DatasetPermissionss for role_id '%s'" % role_two.id )
+ def test_095_manually_unpurge_role( self ):
+ """Testing manually un-purging a role"""
+ # Logged in as admin_user
+ # Manually unpurge, then undelete the role for later test runs
+ # TODO: If we decide to implement the GUI feature for un-purging a role, replace this with a method call
+ role_two.purged = False
+ flush( role_two )
+ self.undelete_role( self.security.encode_id( role_two.id ), role_two.name )
+ def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as admin_user
+ ##################
+ # Eliminate all non-private roles
+ ##################
+ for role in [ role_one, role_two, role_three ]:
+ self.mark_role_deleted( self.security.encode_id( role.id ), role.name )
+ self.purge_role( self.security.encode_id( role.id ), role.name )
+ # Manually delete the role from the database
+ refresh( role )
+ sa_session.delete( role )
+ sa_session.flush()
+ ##################
+ # Eliminate all groups
+ ##################
+ for group in [ group_zero, group_one, group_two ]:
+ self.mark_group_deleted( self.security.encode_id( group.id ), group.name )
+ self.purge_group( self.security.encode_id( group.id ), group.name )
+ # Manually delete the group from the database
+ refresh( group )
+ sa_session.delete( group )
+ sa_session.flush()
+ ##################
+ # Make sure all users are associated only with their private roles
+ ##################
+ for user in [ admin_user, regular_user1, regular_user2, regular_user3 ]:
+ refresh( user )
+ if len( user.roles) != 1:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) )
diff -r e39c9a2a0b4c -r 48e83411aa91 test/functional/test_data_security.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/functional/test_data_security.py Fri Mar 12 16:11:26 2010 -0500
@@ -0,0 +1,196 @@
+from base.twilltestcase import *
+from base.test_db_util import *
+
+class TestDataSecurity( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ global regular_user1_private_role
+ regular_user1_private_role = get_private_role( regular_user1 )
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ global regular_user2_private_role
+ regular_user2_private_role = get_private_role( regular_user2 )
+ self.logout()
+ self.login( email='test3(a)bx.psu.edu' )
+ global regular_user3
+ regular_user3 = get_user( 'test3(a)bx.psu.edu' )
+ assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
+ global regular_user3_private_role
+ regular_user3_private_role = get_private_role( regular_user3 )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ global admin_user_private_role
+ admin_user_private_role = get_private_role( admin_user )
+ def test_005_default_permissions( self ):
+ """Testing initial settings for DefaultUserPermissions and DefaultHistoryPermissions"""
+ # Logged in as admin_user
+ # Make sure DefaultUserPermissions are correct
+ dups = get_default_user_permissions_by_user( admin_user )
+ if len( dups ) > 1:
+ raise AssertionError( '%d DefaultUserPermissions associated with user %s ( should be 1 )' \
+ % ( len( admin_user.default_permissions ), admin_user.email ) )
+ dup = dups[0]
+ if not dup.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
+ raise AssertionError( 'The DefaultUserPermission.action for user "%s" is "%s", but it should be "%s"' \
+ % ( admin_user.email, dup.action, galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
+ # Make sure DefaultHistoryPermissions are correct
+ latest_history = get_latest_history_for_user( admin_user )
+ dhps = get_default_history_permissions_by_history( latest_history )
+ if len( dhps ) > 1:
+ raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d when it was created ( should have been 1 )' \
+ % ( len( latest_history.default_permissions ), latest_history.id ) )
+ dhp = dhps[0]
+ if not dhp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
+ raise AssertionError( 'The DefaultHistoryPermission.action for history id %d is "%s", but it should be "%s"' \
+ % ( latest_history.id, dhp.action, galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
+ self.manage_roles_and_groups_for_user( self.security.encode_id( admin_user.id ),
+ check_str=admin_user.email )
+ # Try deleting the admin_user's private role
+ check_str = "You cannot eliminate a user's private role association."
+ self.manage_roles_and_groups_for_user( self.security.encode_id( admin_user.id ),
+ out_role_ids=str( admin_user_private_role.id ),
+ check_str=check_str )
+ def test_010_private_role_creation_and_default_history_permissions( self ):
+ """Testing private role creation and changing DefaultHistoryPermissions for new histories"""
+ # Logged in as admin_user
+ self.logout()
+ # Some of the history related tests here are similar to some tests in the
+ # test_history_functions.py script, so we could potentially eliminate 1 or 2 of them.
+ self.login( email='test1(a)bx.psu.edu' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ # Add a dataset to the history
+ self.upload_file( '1.bed' )
+ latest_dataset = get_latest_dataset()
+ # Make sure DatasetPermissions are correct - default is 'manage permissions'
+ dps = get_dataset_permissions_by_dataset( latest_dataset )
+ if len( dps ) > 1:
+ raise AssertionError( '%d DatasetPermissions were created for dataset id %d when it was created ( should have been 1 )' \
+ % ( len( dps ), latest_dataset.id ) )
+ dp = dps[0]
+ if not dp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
+ raise AssertionError( 'The DatasetPermissions.action for dataset id %d is "%s", but it should be "manage permissions"' \
+ % ( latest_dataset.id, dp.action ) )
+ # Change DefaultHistoryPermissions for regular_user1
+ permissions_in = []
+ actions_in = []
+ for key, value in galaxy.model.Dataset.permitted_actions.items():
+ # Setting the 'access' permission with the private role makes this dataset private
+ permissions_in.append( key )
+ actions_in.append( value.action )
+ # Sort actions for later comparison
+ actions_in.sort()
+ self.user_set_default_permissions( permissions_in=permissions_in, role_id=str( regular_user1_private_role.id ) )
+ # Make sure the default permissions are changed for new histories
+ self.new_history()
+ # logged in as regular_user1
+ latest_history = get_latest_history_for_user( regular_user1 )
+ if len( latest_history.default_permissions ) != len( actions_in ):
+ raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d, should have been %d' % \
+ ( len( latest_history.default_permissions ), latest_history.id, len( actions_in ) ) )
+ dhps = []
+ for dhp in latest_history.default_permissions:
+ dhps.append( dhp.action )
+ # Sort permissions for later comparison
+ dhps.sort()
+ for key, value in galaxy.model.Dataset.permitted_actions.items():
+ if value.action not in dhps:
+ raise AssertionError( '%s not in history id %d default_permissions after they were changed' % ( value.action, latest_history.id ) )
+ # Add a dataset to the history
+ self.upload_file( '1.bed' )
+ latest_dataset = get_latest_dataset()
+ # Make sure DatasetPermissions are correct
+ if len( latest_dataset.actions ) != len( latest_history.default_permissions ):
+ raise AssertionError( '%d DatasetPermissions were created for dataset id %d when it was created ( should have been %d )' % \
+ ( len( latest_dataset.actions ), latest_dataset.id, len( latest_history.default_permissions ) ) )
+ dps = []
+ for dp in latest_dataset.actions:
+ dps.append( dp.action )
+ # Sort actions for later comparison
+ dps.sort()
+ # Compare DatasetPermissions with permissions_in - should be the same
+ if dps != actions_in:
+ raise AssertionError( 'DatasetPermissions "%s" for dataset id %d differ from changed default permissions "%s"' \
+ % ( str( dps ), latest_dataset.id, str( actions_in ) ) )
+ # Compare DefaultHistoryPermissions and DatasetPermissions - should be the same
+ if dps != dhps:
+ raise AssertionError( 'DatasetPermissions "%s" for dataset id %d differ from DefaultHistoryPermissions "%s" for history id %d' \
+ % ( str( dps ), latest_dataset.id, str( dhps ), latest_history.id ) )
+ def test_015_change_default_permissions_for_current_history( self ):
+ """Testing changing DefaultHistoryPermissions for the current history"""
+ # logged in a regular_user1
+ self.logout()
+ self.login( email=regular_user2.email )
+ latest_history = get_latest_history_for_user( regular_user2 )
+ self.upload_file( '1.bed' )
+ latest_dataset = get_latest_dataset()
+ permissions_in = [ 'DATASET_MANAGE_PERMISSIONS' ]
+ # Make sure these are in sorted order for later comparison
+ actions_in = [ 'manage permissions' ]
+ permissions_out = [ 'DATASET_ACCESS' ]
+ actions_out = [ 'access' ]
+ # Change DefaultHistoryPermissions for the current history
+ self.history_set_default_permissions( permissions_out=permissions_out, permissions_in=permissions_in, role_id=str( regular_user2_private_role.id ) )
+ if len( latest_history.default_permissions ) != len( actions_in ):
+ raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d, should have been %d' \
+ % ( len( latest_history.default_permissions ), latest_history.id, len( permissions_in ) ) )
+ # Make sure DefaultHistoryPermissions were correctly changed for the current history
+ dhps = []
+ for dhp in latest_history.default_permissions:
+ dhps.append( dhp.action )
+ # Sort permissions for later comparison
+ dhps.sort()
+ # Compare DefaultHistoryPermissions and actions_in - should be the same
+ if dhps != actions_in:
+ raise AssertionError( 'DefaultHistoryPermissions "%s" for history id %d differ from actions "%s" passed for changing' \
+ % ( str( dhps ), latest_history.id, str( actions_in ) ) )
+ # Make sure DatasetPermissionss are correct
+ if len( latest_dataset.actions ) != len( latest_history.default_permissions ):
+ raise AssertionError( '%d DatasetPermissionss were created for dataset id %d when it was created ( should have been %d )' \
+ % ( len( latest_dataset.actions ), latest_dataset.id, len( latest_history.default_permissions ) ) )
+ dps = []
+ for dp in latest_dataset.actions:
+ dps.append( dp.action )
+ # Sort actions for comparison
+ dps.sort()
+ # Compare DatasetPermissionss and DefaultHistoryPermissions - should be the same
+ if dps != dhps:
+ raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s"' \
+ % ( str( dps ), latest_dataset.id, str( dhps ) ) )
+ def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as regular_user2
+ self.logout()
+ self.login( email=admin_user.email )
+ ##################
+ # Make sure all users are associated only with their private roles
+ ##################
+ for user in [ admin_user, regular_user1, regular_user2, regular_user3 ]:
+ refresh( user )
+ if len( user.roles) != 1:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) )
+ #####################
+ # Reset DefaultHistoryPermissions for regular_user1
+ #####################
+ self.logout()
+ self.login( email=regular_user1.email )
+ # Change DefaultHistoryPermissions for regular_user1 back to the default
+ permissions_in = [ 'DATASET_MANAGE_PERMISSIONS' ]
+ permissions_out = [ 'DATASET_ACCESS' ]
+ self.user_set_default_permissions( permissions_in=permissions_in,
+ permissions_out=permissions_out,
+ role_id=str( regular_user1_private_role.id ) )
+ self.logout()
+ self.login( email=admin_user.email )
diff -r e39c9a2a0b4c -r 48e83411aa91 test/functional/test_library_features.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/functional/test_library_features.py Fri Mar 12 16:11:26 2010 -0500
@@ -0,0 +1,606 @@
+from base.twilltestcase import *
+from base.test_db_util import *
+
+class TestLibraryFeatures( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ self.logout()
+ self.login( email='test3(a)bx.psu.edu' )
+ global regular_user3
+ regular_user3 = get_user( 'test3(a)bx.psu.edu' )
+ assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ def test_005_create_library( self ):
+ """Testing creating a new library, then renaming it"""
+ # Logged in as admin_user
+ name = "library features Library1"
+ description = "library features Library1 description"
+ synopsis = "library features Library1 synopsis"
+ self.create_library( name=name, description=description, synopsis=synopsis )
+ self.browse_libraries_admin( check_str1=name, check_str2=description )
+ # Get the library object for later tests
+ global library_one
+ library_one = get_library( name, description, synopsis )
+ assert library_one is not None, 'Problem retrieving library named "%s" from the database' % name
+ # Rename the library
+ new_name = "library features Library1 new name"
+ new_description = "library features Library1 new description"
+ new_synopsis = "library features Library1 new synopsis"
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ new_name=new_name,
+ new_description=new_description,
+ new_synopsis=new_synopsis )
+ self.browse_libraries_admin( check_str1=new_name, check_str2=new_description )
+ # Reset the library back to the original name and description
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ new_name=name,
+ new_description=description,
+ new_synopsis=synopsis )
+ refresh( library_one )
+ def test_010_library_template_features( self ):
+ """Testing adding a template to a library, then filling in the contents"""
+ # Logged in as admin_user
+ form_name = 'Library template Form One'
+ form_desc = 'This is Form One'
+ form_type = galaxy.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
+ # Create form for library template
+ self.create_form( name=form_name, desc=form_desc, formtype=form_type )
+ global form_one
+ form_one = get_form( form_name )
+ assert form_one is not None, 'Problem retrieving form named (%s) from the database' % form_name
+ # Add new template based on the form to the library
+ template_name = 'Library Template 1'
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name )
+ # Make sure the template fields are displayed on the library information page
+ field_dict = form_one.fields[ 0 ]
+ global form_one_field_label
+ form_one_field_label = '%s' % str( field_dict.get( 'label', 'Field 0' ) )
+ global form_one_field_help
+ form_one_field_help = '%s' % str( field_dict.get( 'helptext', 'Field 0 help' ) )
+ global form_one_field_required
+ form_one_field_required = '%s' % str( field_dict.get( 'required', 'optional' ) ).capitalize()
+ # Add information to the library using the template
+ global form_one_field_name
+ form_one_field_name = 'field_0'
+ contents = '%s library contents' % form_one_field_label
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ ele_1_field_name=form_one_field_name,
+ ele_1_contents=contents )
+ def test_015_edit_template_contents_admin_view( self ):
+ """Test editing template contents from the Admin view"""
+ # Logged in as admin_user
+ # Make sure the template contents were from the previous method correctly saved
+ # Twill barfs if this test is run in the previous method.
+ contents = '%s library contents' % form_one_field_label
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ check_str1=contents )
+ contents = '%s library contents' % form_one_field_label
+ contents_edited = contents + ' edited'
+ # Edit the contents and then save them
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ ele_1_field_name=form_one_field_name,
+ ele_1_contents=contents_edited )
+ # Make sure the template contents were correctly saved
+ self.library_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ check_str1=contents_edited )
+ def test_020_add_public_dataset_to_root_folder( self ):
+ """Testing adding a public dataset to the root folder, making sure library template is inherited"""
+ # Logged in as admin_user
+ message = 'Testing adding a public dataset to the root folder'
+ # The template should be inherited to the library dataset upload form.
+ template_contents = "%s contents for root folder 1.bed" % form_one_field_label
+ self.add_library_dataset( 'library_admin',
+ '1.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.root_folder.id ),
+ library_one.root_folder.name,
+ file_type='bed',
+ dbkey='hg18',
+ message=message.replace( ' ', '+' ),
+ root=True,
+ template_field_name1=form_one_field_name,
+ template_field_contents1=template_contents )
+ global ldda_one
+ ldda_one = get_latest_ldda()
+ assert ldda_one is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_one from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1='1.bed',
+ check_str2=message,
+ check_str3=admin_user.email )
+ # Make sure the library template contents were correctly saved
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.root_folder.id ),
+ self.security.encode_id( ldda_one.id ),
+ ldda_one.name,
+ check_str1=template_contents )
+ def test_025_add_new_folder_to_root_folder( self ):
+ """Testing adding a folder to a library root folder"""
+ # logged in as admin_user
+ root_folder = library_one.root_folder
+ name = "Root Folder's Folder One"
+ description = "This is the root folder's Folder One"
+ self.add_folder( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( root_folder.id ),
+ name=name,
+ description=description )
+ global folder_one
+ folder_one = get_folder( root_folder.id, name, description )
+ assert folder_one is not None, 'Problem retrieving library folder named "%s" from the database' % name
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=name,
+ check_str2=description )
+ # Make sure the template was inherited, but the contents were not
+ contents = '%s library contents' % form_one_field_label
+ self.folder_info( 'library_admin',
+ self.security.encode_id( folder_one.id ),
+ self.security.encode_id( library_one.id ),
+ check_str1=form_one_field_name,
+ not_displayed=contents )
+ # Add contents to the inherited template
+ template_contents = "%s contents for Folder One" % form_one_field_label
+ self.folder_info( 'library_admin',
+ self.security.encode_id( folder_one.id ),
+ self.security.encode_id( library_one.id ),
+ field_name=form_one_field_name,
+ contents=template_contents )
+ def test_030_add_subfolder_to_folder( self ):
+ """Testing adding a folder to a library folder"""
+ # logged in as admin_user
+ name = "Folder One's Subfolder"
+ description = "This is the Folder One's subfolder"
+ self.add_folder( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ name=name,
+ description=description )
+ global subfolder_one
+ subfolder_one = get_folder( folder_one.id, name, description )
+ assert subfolder_one is not None, 'Problem retrieving library folder named "Folder Ones Subfolder" from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=name,
+ check_str2=description )
+ # Make sure the template was inherited, but the contents were not
+ contents = '%s library contents' % form_one_field_label
+ self.folder_info( 'library_admin',
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( library_one.id ),
+ check_str1=form_one_field_name,
+ not_displayed=contents )
+ # Add contents to the inherited template
+ template_contents = "%s contents for Folder One" % form_one_field_label
+ self.folder_info( 'library_admin',
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( library_one.id ),
+ field_name=form_one_field_name,
+ contents=template_contents )
+ def test_035_add_2nd_new_folder_to_root_folder( self ):
+ """Testing adding a 2nd folder to a library root folder"""
+ # logged in as admin_user
+ root_folder = library_one.root_folder
+ name = "Folder Two"
+ description = "This is the root folder's Folder Two"
+ self.add_folder( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( root_folder.id ),
+ name=name,
+ description=description )
+ global folder_two
+ folder_two = get_folder( root_folder.id, name, description )
+ assert folder_two is not None, 'Problem retrieving library folder named "%s" from the database' % name
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=name,
+ check_str2=description )
+ def test_040_add_public_dataset_to_root_folders_2nd_subfolder( self ):
+ """Testing adding a public dataset to the root folder's 2nd sub-folder"""
+ # Logged in as admin_user
+ message = "Testing adding a public dataset to the folder named %s" % folder_two.name
+ # The form_one template should be inherited to the library dataset upload form.
+ template_contents = "%s contents for %s 2.bed" % ( form_one_field_label, folder_two.name )
+ self.add_library_dataset( 'library_admin',
+ '2.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_two.id ),
+ folder_two.name,
+ file_type='bed',
+ dbkey='hg18',
+ message=message.replace( ' ', '+' ),
+ root=False,
+ template_field_name1=form_one_field_name,
+ template_field_contents1=template_contents )
+ global ldda_two
+ ldda_two = get_latest_ldda()
+ assert ldda_two is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_two from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1='2.bed',
+ check_str2=message,
+ check_str3=admin_user.email )
+ # Make sure the library template contents were correctly saved
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_two.id ),
+ self.security.encode_id( ldda_two.id ),
+ ldda_two.name,
+ check_str1=template_contents )
+ def test_045_add_2nd_public_dataset_to_root_folders_2nd_subfolder( self ):
+ """Testing adding a 2nd public dataset to the root folder's 2nd sub-folder"""
+ # Logged in as admin_user
+ message = "Testing adding a 2nd public dataset to the folder named %s" % folder_two.name
+ # The form_one template should be inherited to the library dataset upload form.
+ template_contents = "%s contents for %s 3.bed" % ( form_one_field_label, folder_two.name )
+ self.add_library_dataset( 'library_admin',
+ '3.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_two.id ),
+ folder_two.name,
+ file_type='bed',
+ dbkey='hg18',
+ message=message.replace( ' ', '+' ),
+ root=False,
+ template_field_name1=form_one_field_name,
+ template_field_contents1=template_contents )
+ global ldda_three
+ ldda_three = get_latest_ldda()
+ assert ldda_three is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_three from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1='3.bed',
+ check_str2=message,
+ check_str3=admin_user.email )
+ # Make sure the library template contents were correctly saved
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_two.id ),
+ self.security.encode_id( ldda_three.id ),
+ ldda_three.name,
+ check_str1=template_contents )
+ def test_050_copy_dataset_from_history_to_subfolder( self ):
+ """Testing copying a dataset from the current history to a subfolder"""
+ # logged in as admin_user
+ self.new_history()
+ self.upload_file( "4.bed" )
+ latest_hda = get_latest_hda()
+ self.add_history_datasets_to_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ subfolder_one.name,
+ self.security.encode_id( latest_hda.id ),
+ root=False )
+ global ldda_four
+ ldda_four = get_latest_ldda()
+ assert ldda_four is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_four from the database'
+ # Make sure the correct template was inherited but the contents were not inherited
+ contents = "%s contents for Folder One's Subfolder" % form_one_field_label
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four.id ),
+ ldda_four.name,
+ check_str1=form_one_field_name,
+ not_displayed=contents )
+ def test_055_editing_dataset_attribute_info( self ):
+ """Testing editing a library dataset's attribute information"""
+ # logged in as admin_user
+ new_ldda_name = '4.bed ( version 1 )'
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four.id ),
+ ldda_four.name,
+ new_ldda_name=new_ldda_name )
+ refresh( ldda_four )
+ self.browse_library( 'library_admin', self.security.encode_id( library_one.id ), check_str1=new_ldda_name )
+ # Make sure the correct template was inherited but the contents were not inherited
+ contents = "%s contents for Folder One's Subfolder" % form_one_field_label
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four.id ),
+ ldda_four.name,
+ check_str1=form_one_field_name,
+ not_displayed=contents )
+ def test_060_uploading_new_dataset_version( self ):
+ """Testing uploading a new version of a library dataset"""
+ # logged in as admin_user
+ message = 'Testing uploading a new version of a dataset'
+ # The form_one template should be inherited to the library dataset upload form.
+ template_contents = "%s contents for %s new version of 4.bed" % ( form_one_field_label, folder_one.name )
+ self.upload_new_dataset_version( 'library_admin',
+ '4.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ subfolder_one.name,
+ self.security.encode_id( ldda_four.library_dataset.id ),
+ ldda_four.name,
+ file_type='auto',
+ dbkey='hg18',
+ message=message.replace( ' ', '+' ),
+ template_field_name1=form_one_field_name,
+ template_field_contents1=template_contents )
+ global ldda_four_version_two
+ ldda_four_version_two = get_latest_ldda()
+ assert ldda_four_version_two is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_four_version_two from the database'
+ # Make sure the correct template was inherited, but does not include any contents
+ contents = "%s contents for Folder One's Subfolder" % form_one_field_label
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four_version_two.id ),
+ ldda_four_version_two.name,
+ check_str1='This is the latest version of this library dataset',
+ not_displayed=contents )
+ # Fill in the template contents
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four_version_two.id ),
+ ldda_four_version_two.name,
+ ele_1_field_name=form_one_field_name,
+ ele_1_contents=template_contents )
+ # Check the previous version
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( subfolder_one.id ),
+ self.security.encode_id( ldda_four.id ),
+ ldda_four.name,
+ check_str1='This is an expired version of this library dataset' )
+ # Make sure ldda_four is no longer displayed in the library
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ not_displayed=ldda_four.name )
+ def test_065_upload_directory_of_files_from_libraries_view( self ):
+ """Testing uploading a directory of files to a root folder from the Data Libraries view"""
+ # logged in as admin_user
+ # admin_user will not have the option to upload a directory of files from the
+ # Libraries view since a sub-directory named the same as their email is not contained
+ # in the configured user_library_import_dir. However, since members of role_one have
+ # the LIBRARY_ADD permission, we can test this feature as regular_user1 or regular_user3
+ self.logout()
+ self.login( email=regular_user1.email )
+ message = 'Uploaded all files in test-data/users/test1...'
+ # Since regular_user1 does not have any sub-directories contained within her configured
+ # user_library_import_dir, the only option in her server_dir select list will be the
+ # directory named the same as her email
+ check_str_after_submit = "Added 1 datasets to the library '%s' (each is selected)." % library_one.root_folder.name
+ # TODO: gvk( 3/12/10 )this is broken, so commenting until I have time to discover why...
+ """
+ self.upload_directory_of_files( 'library',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.root_folder.id ),
+ server_dir=regular_user1.email,
+ message=message,
+ check_str_after_submit=check_str_after_submit )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=regular_user1.email,
+ check_str2=message )
+ self.logout()
+ self.login( regular_user3.email )
+ message = 'Uploaded all files in test-data/users/test3.../run1'
+ # Since regular_user2 has a subdirectory contained within her configured user_library_import_dir,
+ # she will have a "None" option in her server_dir select list
+ self.upload_directory_of_files( 'library',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.root_folder.id ),
+ server_dir='run1',
+ message=message,
+ check_str1='<option>None</option>',
+ check_str_after_submit=check_str_after_submit )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=regular_user3.email,
+ check_str2=message )
+ """
+ def test_070_download_archive_of_library_files( self ):
+ """Testing downloading an archive of files from the library"""
+ # logged in as regular_user3
+ self.logout()
+ self.login( email=admin_user.email )
+ for format in ( 'tbz', 'tgz', 'zip' ):
+ archive = self.download_archive_of_library_files( cntrller='library',
+ library_id=self.security.encode_id( library_one.id ),
+ ldda_ids=[ self.security.encode_id( ldda_one.id ), self.security.encode_id( ldda_two.id ) ],
+ format=format )
+ self.check_archive_contents( archive, ( ldda_one, ldda_two ) )
+ os.remove( archive )
+ def test_075_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.security.encode_id( ldda_two.library_dataset.id ),
+ ldda_two.name,
+ item_type='library_dataset' )
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ not_displayed=ldda_two.name )
+ def test_080_display_and_hide_deleted_dataset( self ):
+ """Testing displaying and hiding a deleted library dataset"""
+ # Logged in as admin_user
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ show_deleted=True,
+ check_str1=ldda_two.name )
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ not_displayed=ldda_two.name )
+ def test_085_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.security.encode_id( folder_two.id ),
+ folder_two.name,
+ item_type='folder' )
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ not_displayed=folder_two.name )
+ def test_090_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.security.encode_id( folder_two.id ),
+ folder_two.name,
+ item_type='folder' )
+ # 2.bed was deleted before the folder was deleted, so state should have been saved. In order
+ # for 2.bed to be displayed, it would itself have to be marked undeleted.
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=folder_two.name,
+ not_displayed=ldda_two.name )
+ def test_095_mark_library_deleted( self ):
+ """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.security.encode_id( folder_two.id ),
+ folder_two.name,
+ item_type='folder' )
+ self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ item_type='library' )
+ self.browse_libraries_admin( not_displayed1=library_one.name )
+ self.browse_libraries_admin( deleted=True, check_str1=library_one.name )
+ def test_100_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.security.encode_id( library_one.id ),
+ library_one.name,
+ item_type='library' )
+ self.browse_libraries_admin( check_str1=library_one.name )
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=library_one.name,
+ not_displayed=folder_two.name )
+ def test_105_purge_library( self ):
+ """Testing purging a library"""
+ # Logged in as admin_user
+ self.delete_library_item( self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.id ),
+ library_one.name,
+ item_type='library' )
+ self.purge_library( self.security.encode_id( library_one.id ), library_one.name )
+ # Make sure the library was purged
+ refresh( library_one )
+ if not ( library_one.deleted and library_one.purged ):
+ raise AssertionError( 'The library id %s named "%s" has not been marked as deleted and purged.' % ( str( library_one.id ), library_one.name ) )
+ def check_folder( library_folder ):
+ for folder in library_folder.folders:
+ refresh( folder )
+ # Make sure all of the library_folders are purged
+ if not folder.purged:
+ raise AssertionError( 'The library_folder id %s named "%s" has not been marked purged.' % ( str( folder.id ), folder.name ) )
+ check_folder( folder )
+ # Make sure all of the LibraryDatasets and associated objects are deleted
+ refresh( library_folder )
+ for library_dataset in library_folder.datasets:
+ refresh( library_dataset )
+ ldda = library_dataset.library_dataset_dataset_association
+ if ldda:
+ refresh( ldda )
+ if not ldda.deleted:
+ raise AssertionError( 'The library_dataset_dataset_association id %s named "%s" has not been marked as deleted.' % \
+ ( str( ldda.id ), ldda.name ) )
+ # Make sure all of the datasets have been deleted
+ dataset = ldda.dataset
+ refresh( dataset )
+ if not dataset.deleted:
+ raise AssertionError( 'The dataset with id "%s" has not been marked as deleted when it should have been.' % \
+ str( ldda.dataset.id ) )
+ if not library_dataset.deleted:
+ raise AssertionError( 'The library_dataset id %s named "%s" has not been marked as deleted.' % \
+ ( str( library_dataset.id ), library_dataset.name ) )
+ check_folder( library_one.root_folder )
+ def test_110_no_library_template( self ):
+ """Test library features when library has no template"""
+ # Logged in as admin_user
+ name = "library features Library Two"
+ description = "library features This is Library Two"
+ synopsis = "library features Library Two synopsis"
+ # Create a library, adding no template
+ self.create_library( name=name, description=description, synopsis=synopsis )
+ self.browse_libraries_admin( check_str1=name, check_str2=description )
+ global library_two
+ library_two = get_library( name, description, synopsis )
+ assert library_two is not None, 'Problem retrieving library named "%s" from the database' % name
+ # Add a dataset to the library
+ self.add_library_dataset( 'library_admin',
+ '3.bed',
+ self.security.encode_id( library_two.id ),
+ self.security.encode_id( library_two.root_folder.id ),
+ library_two.root_folder.name,
+ file_type='bed',
+ dbkey='hg18',
+ message='',
+ root=True )
+ ldda_three = get_latest_ldda()
+ assert ldda_three is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_three from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_two.id ),
+ check_str1='3.bed',
+ check_str2=admin_user.email )
+ # 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.security.encode_id( library_two.id ),
+ library_two.name,
+ item_type='library' )
+ self.purge_library( self.security.encode_id( library_two.id ), library_two.name )
+ self.home()
+ def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as admin_user
+ ##################
+ # Purge all libraries
+ ##################
+ for library in [ library_one, library_two ]:
+ self.delete_library_item( self.security.encode_id( library.id ),
+ self.security.encode_id( library.id ),
+ library.name,
+ item_type='library' )
+ self.purge_library( self.security.encode_id( library.id ), library.name )
+ ##################
+ # Make sure all users are associated only with their private roles
+ ##################
+ for user in [ admin_user, regular_user1, regular_user2, regular_user3 ]:
+ refresh( user )
+ if len( user.roles) != 1:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) )
+ self.logout()
diff -r e39c9a2a0b4c -r 48e83411aa91 test/functional/test_library_security.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/functional/test_library_security.py Fri Mar 12 16:11:26 2010 -0500
@@ -0,0 +1,603 @@
+from base.twilltestcase import *
+from base.test_db_util import *
+
+class TestLibrarySecurity( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ global regular_user1_private_role
+ regular_user1_private_role = get_private_role( regular_user1 )
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ global regular_user2_private_role
+ regular_user2_private_role = get_private_role( regular_user2 )
+ self.logout()
+ self.login( email='test3(a)bx.psu.edu' )
+ global regular_user3
+ regular_user3 = get_user( 'test3(a)bx.psu.edu' )
+ assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
+ global regular_user3_private_role
+ regular_user3_private_role = get_private_role( regular_user3 )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ global admin_user_private_role
+ admin_user_private_role = get_private_role( admin_user )
+ def test_005_create_required_groups_and_roles( self ):
+ """Testing creating all required groups and roles for this script"""
+ # Logged in as admin_user
+ # Create role_one
+ name = 'library security Role One'
+ description = "library security This is Role One's description"
+ user_ids = [ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=[],
+ create_group_for_role='no',
+ private_role=admin_user.email )
+ # Get the role object for later tests
+ global role_one
+ role_one = get_role_by_name( name )
+ # Create group_one
+ name = 'Group One'
+ self.create_group( name=name, in_user_ids=[ str( regular_user1.id ) ], in_role_ids=[ str( role_one.id ) ] )
+ # Get the group object for later tests
+ global group_one
+ group_one = get_group_by_name( name )
+ assert group_one is not None, 'Problem retrieving group named "Group One" from the database'
+ # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
+ # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT
+ # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the
+ # associate_users_and_groups_with_role() method.
+ #
+ #create role_two
+ name = 'library security Role Two'
+ description = 'library security This is Role Two'
+ user_ids = [ str( admin_user.id ) ]
+ group_ids = [ str( group_one.id ) ]
+ private_role = admin_user.email
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=group_ids,
+ private_role=private_role )
+ # Get the role object for later tests
+ global role_two
+ role_two = get_role_by_name( name )
+ assert role_two is not None, 'Problem retrieving role named "Role Two" from the database'
+ def test_010_create_library( self ):
+ """Testing creating a new library, then renaming it"""
+ # Logged in as admin_user
+ name = "library security Library1"
+ description = "library security Library1 description"
+ synopsis = "library security Library1 synopsis"
+ self.create_library( name=name, description=description, synopsis=synopsis )
+ # Get the library object for later tests
+ global library_one
+ library_one = get_library( name, description, synopsis )
+ assert library_one is not None, 'Problem retrieving library named "%s" from the database' % name
+ # Make sure library_one is public
+ assert 'access library' not in [ a.action for a in library_one.actions ], 'Library %s is not public when first created' % library_one.name
+ # Set permissions on the library, sort for later testing.
+ permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ]
+ permissions_out = []
+ # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for
+ # LIBRARY_ACCESS, LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents.
+ self.library_permissions( self.security.encode_id( library_one.id ),
+ library_one.name,
+ str( role_one.id ),
+ permissions_in,
+ permissions_out )
+ # Make sure the library is accessible by admin_user
+ self.visit_url( '%s/library/browse_libraries' % self.url )
+ self.check_page_for_string( library_one.name )
+ # Make sure the library is not accessible by regular_user2 since regular_user2 does not have Role1.
+ self.logout()
+ self.login( email=regular_user2.email )
+ self.visit_url( '%s/library/browse_libraries' % self.url )
+ try:
+ self.check_page_for_string( library_one.name )
+ raise AssertionError, 'Library %s is accessible by %s when it should be restricted' % ( library_one.name, regular_user2.email )
+ except:
+ pass
+ self.logout()
+ self.login( email=admin_user.email )
+ def test_015_add_new_folder_to_root_folder( self ):
+ """Testing adding a folder to a library root folder"""
+ # logged in as admin_user
+ root_folder = library_one.root_folder
+ name = "Root Folder's Folder One"
+ description = "This is the root folder's Folder One"
+ self.add_folder( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( root_folder.id ),
+ name=name,
+ description=description )
+ global folder_one
+ folder_one = get_folder( root_folder.id, name, description )
+ assert folder_one is not None, 'Problem retrieving library folder named "%s" from the database' % name
+ def test_020_add_dataset_with_private_role_restriction_to_folder( self ):
+ """Testing adding a dataset with a private role restriction to a folder"""
+ # Logged in as admin_user
+ #
+ # Keep in mind that # LIBRARY_ACCESS = "Role One" on the whole library
+ #
+ # Add a dataset restricted by the following:
+ # DATASET_MANAGE_PERMISSIONS = "test(a)bx.psu.edu" via DefaultUserPermissions
+ # DATASET_ACCESS = "regular_user1" private role via this test method
+ # LIBRARY_ADD = "Role One" via inheritance from parent folder
+ # LIBRARY_MODIFY = "Role One" via inheritance from parent folder
+ # LIBRARY_MANAGE = "Role One" via inheritance from parent folder
+ # "Role One" members are: test(a)bx.psu.edu, test1(a)bx.psu.edu, test3(a)bx.psu.edu
+ # This means that only user test1(a)bx.psu.edu can see the dataset from the Libraries view
+ message ='This is a test of the fourth dataset uploaded'
+ self.add_library_dataset( 'library_admin',
+ '1.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ folder_one.name,
+ file_type='bed',
+ dbkey='hg18',
+ roles=[ str( regular_user1_private_role.id ) ],
+ message=message.replace( ' ', '+' ),
+ root=False )
+ global ldda_one
+ ldda_one = get_latest_ldda()
+ assert ldda_one is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_one from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1='1.bed',
+ check_str2=message,
+ check_str3=admin_user.email )
+ def test_025_accessing_dataset_with_private_role_restriction( self ):
+ """Testing accessing a dataset with a private role restriction"""
+ # Logged in as admin_user
+ #
+ # Keep in mind that # LIBRARY_ACCESS = "Role One" on the whole library
+ # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for
+ # LIBRARY_ACCESS, LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents.
+ #
+ # Legitimate roles displayed on the permission form are as follows:
+ # 'Role One' since the LIBRARY_ACCESS permission is associated with Role One. # Role one members are: admin_user, regular_user1, regular_user3.
+ # 'test(a)bx.psu.edu' ( admin_user's private role ) since admin_user has Role One
+ # 'Role Two' since admin_user has Role Two
+ # 'Role Three' since admin_user has Role Three
+ # 'test1(a)bx.psu.edu' ( regular_user1's private role ) since regular_user1 has Role One
+ # 'test3(a)bx.psu.edu' ( regular_user3's private role ) since regular_user3 has Role One
+ #
+ # admin_user should not be able to see 1.bed from the analysis view's access libraries
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ not_displayed=folder_one.name,
+ not_displayed2='1.bed' )
+ self.logout()
+ # regular_user1 should be able to see 1.bed from the analysis view's access librarys
+ # since it was associated with regular_user1's private role
+ self.login( email=regular_user1.email )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=folder_one.name,
+ check_str2='1.bed' )
+ self.logout()
+ # regular_user2 should not be to see the library since they do not have
+ # Role One which is associated with the LIBRARY_ACCESS permission
+ self.login( email=regular_user2.email )
+ self.browse_libraries_regular_user( check_str1="You are not authorized to access any libraries" )
+ self.logout()
+ # regular_user3 should not be able to see 1.bed from the analysis view's access librarys
+ self.login( email=regular_user3.email )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ not_displayed=folder_one.name,
+ not_displayed2='1.bed' )
+ self.logout()
+ self.login( email=admin_user.email )
+ def test_030_change_dataset_access_permission( self ):
+ """Testing changing the access permission on a dataset with a private role restriction"""
+ # Logged in as admin_user
+ # We need admin_user to be able to access 1.bed
+ permissions_in = [ k for k, v in galaxy.model.Dataset.permitted_actions.items() ]
+ for k, v in galaxy.model.Library.permitted_actions.items():
+ if k != 'LIBRARY_ACCESS':
+ permissions_in.append( k )
+ permissions_out = []
+ # Attempt to associate multiple roles with the library dataset, with one of the
+ # roles being private.
+ role_ids_str = '%s,%s' % ( str( role_one.id ), str( admin_user_private_role.id ) )
+ check_str = "At least 1 user must have every role associated with accessing datasets. "
+ check_str += "Since you are associating more than 1 role, no private roles are allowed."
+ self.ldda_permissions( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ self.security.encode_id( ldda_one.id ),
+ role_ids_str,
+ permissions_in,
+ permissions_out,
+ check_str1=check_str )
+ role_ids_str = str( role_one.id )
+ self.ldda_permissions( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ self.security.encode_id( ldda_one.id ),
+ role_ids_str,
+ permissions_in,
+ permissions_out )
+ # admin_user should now be able to see 1.bed from the analysis view's access libraries
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=ldda_one.name )
+ def test_035_add_dataset_with_role_associated_with_group_and_users( self ):
+ """Testing adding a dataset with a role that is associated with a group and users"""
+ # Logged in as admin_user
+ # Add a dataset restricted by role_two, which is currently associated as follows:
+ # groups: group_one
+ # users: test(a)bx.psu.edu, test1(a)bx.psu.edu via group_one
+ #
+ # We first need to make library_one public
+ permissions_in = []
+ for k, v in galaxy.model.Library.permitted_actions.items():
+ if k != 'LIBRARY_ACCESS':
+ permissions_in.append( k )
+ permissions_out = []
+ # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will now be permitted for
+ # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents. The library will be public from
+ # this point on.
+ self.library_permissions( self.security.encode_id( library_one.id ),
+ library_one.name,
+ str( role_one.id ),
+ permissions_in,
+ permissions_out )
+ refresh( library_one )
+ message = 'Testing adding a dataset with a role that is associated with a group and users'
+ self.add_library_dataset( 'library_admin',
+ '2.bed',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ folder_one.name,
+ file_type='bed',
+ dbkey='hg17',
+ roles=[ str( role_two.id ) ],
+ message=message.replace( ' ', '+' ),
+ root=False )
+ global ldda_two
+ ldda_two = get_latest_ldda()
+ assert ldda_two is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_two from the database'
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1='2.bed',
+ check_str2=message,
+ check_str3=admin_user.email )
+ def test_040_accessing_dataset_with_role_associated_with_group_and_users( self ):
+ """Testing accessing a dataset with a role that is associated with a group and users"""
+ # Logged in as admin_user
+ # admin_user should be able to see 2.bed since she is associated with role_two
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1='2.bed',
+ check_str2=admin_user.email )
+ self.logout()
+ # regular_user1 should be able to see 2.bed since she is associated with group_two
+ self.login( email = 'test1(a)bx.psu.edu' )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=folder_one.name,
+ check_str2='2.bed',
+ check_str3=admin_user.email )
+ # Check the permissions on the dataset 2.bed - they are as folows:
+ # DATASET_MANAGE_PERMISSIONS = test(a)bx.psu.edu
+ # DATASET_ACCESS = Role Two
+ # Role Two associations: test(a)bx.psu.edu and Group Two
+ # Group Two members: Role One, Role Two, test1(a)bx.psu.edu
+ # Role One associations: test(a)bx.psu.edu, test1(a)bx.psu.edu, test3(a)bx.psu.edu
+ # LIBRARY_ADD = Role One
+ # Role One aassociations: test(a)bx.psu.edu, test1(a)bx.psu.edu, test3(a)bx.psu.edu
+ # LIBRARY_MODIFY = Role One
+ # Role One aassociations: test(a)bx.psu.edu, test1(a)bx.psu.edu, test3(a)bx.psu.edu
+ # LIBRARY_MANAGE = Role One
+ # Role One aassociations: test(a)bx.psu.edu, test1(a)bx.psu.edu, test3(a)bx.psu.edu
+ self.ldda_edit_info( 'library',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ self.security.encode_id( ldda_two.id ),
+ ldda_two.name,
+ check_str1='2.bed',
+ check_str2='This is the latest version of this library dataset',
+ check_str3='Edit attributes of 2.bed' )
+ self.act_on_multiple_datasets( 'library',
+ self.security.encode_id( library_one.id ),
+ 'import_to_history',
+ ldda_ids=self.security.encode_id( ldda_two.id ),
+ check_str1='1 dataset(s) have been imported into your history' )
+ self.logout()
+ # regular_user2 should not be able to see 2.bed
+ self.login( email = 'test2(a)bx.psu.edu' )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ not_displayed=folder_one.name,
+ not_displayed2='2.bed' )
+
+ self.logout()
+ # regular_user3 should not be able to see folder_one ( even though it does not contain any datasets that she
+ # can access ) since she has Role One, and Role One has all library permissions ( see above ).
+ self.login( email = 'test3(a)bx.psu.edu' )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ check_str1=folder_one.name,
+ not_displayed='2.bed' )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ def test_045_upload_directory_of_files_from_admin_view( self ):
+ """Testing uploading a directory of files to a root folder from the Admin view"""
+ # logged in as admin_user
+ message = 'This is a test for uploading a directory of files'
+ check_str_after_submit="Added 3 datasets to the library '%s' (each is selected)." % library_one.root_folder.name
+ self.upload_directory_of_files( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( library_one.root_folder.id ),
+ server_dir='library',
+ message=message,
+ check_str_after_submit=check_str_after_submit )
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ check_str1=admin_user.email,
+ check_str2=message )
+ def test_050_change_permissions_on_datasets_uploaded_from_library_dir( self ):
+ """Testing changing the permissions on datasets uploaded from a directory from the Admin view"""
+ # logged in as admin_user
+ # It would be nice if twill functioned such that the above test resulted in a
+ # form with the uploaded datasets selected, but it does not ( they're not checked ),
+ # so we'll have to simulate this behavior ( not ideal ) for the 'edit' action. We
+ # first need to get the ldda.id for the 3 new datasets
+ latest_3_lddas = get_latest_lddas( 3 )
+ ldda_ids = ''
+ for ldda in latest_3_lddas:
+ ldda_ids += '%s,' % self.security.encode_id( ldda.id )
+ ldda_ids = ldda_ids.rstrip( ',' )
+ # Set permissions
+ self.ldda_permissions( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ ldda_ids,
+ str( role_one.id ),
+ permissions_in=[ 'DATASET_ACCESS', 'LIBRARY_MANAGE' ],
+ check_str1='Permissions have been updated on 3 datasets' )
+ # Make sure the permissions have been correctly updated for the 3 datasets. Permissions should
+ # be all of the above on any of the 3 datasets that are imported into a history.
+ def check_edit_page( lddas, check_str1='', check_str2='', check_str3='', check_str4='',
+ not_displayed1='', not_displayed2='', not_displayed3='' ):
+ for ldda in lddas:
+ # Import each library dataset into our history
+ self.act_on_multiple_datasets( 'library',
+ self.security.encode_id( library_one.id ),
+ 'import_to_history',
+ ldda_ids=self.security.encode_id( ldda.id ) )
+ # Determine the new HistoryDatasetAssociation id created when the library dataset was imported into our history
+ last_hda_created = get_latest_hda()
+ self.edit_hda_attribute_info( str( last_hda_created.id ),
+ check_str1=check_str1,
+ check_str2=check_str2,
+ check_str3=check_str3,
+ check_str4=check_str4 )
+ # admin_user is associated with role_one, so should have all permissions on imported datasets
+ check_edit_page( latest_3_lddas,
+ check_str1='Manage dataset permissions on',
+ check_str2='Role members can manage the roles associated with permissions on this dataset',
+ check_str3='Role members can import this dataset into their history for analysis' )
+ self.logout()
+ # regular_user1 is associated with role_one, so should have all permissions on imported datasets
+ self.login( email='test1(a)bx.psu.edu' )
+ check_edit_page( latest_3_lddas )
+ self.logout()
+ # Since regular_user2 is not associated with role_one, she should not have
+ # access to any of the 3 datasets, so she will not see folder_one on the libraries page
+ self.login( email='test2(a)bx.psu.edu' )
+ self.browse_library( 'library',
+ self.security.encode_id( library_one.id ),
+ not_displayed=folder_one.name )
+ self.logout()
+ # regular_user3 is associated with role_one, so should have all permissions on imported datasets
+ self.login( email='test3(a)bx.psu.edu' )
+ check_edit_page( latest_3_lddas )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ # Change the permissions and test again
+ self.ldda_permissions( 'library_admin',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( folder_one.id ),
+ ldda_ids,
+ str( role_one.id ),
+ permissions_in=[ 'DATASET_ACCESS' ],
+ check_str1='Permissions have been updated on 3 datasets' )
+ check_edit_page( latest_3_lddas,
+ check_str1='View Permissions',
+ not_displayed1='Manage dataset permissions on',
+ not_displayed2='Role members can manage roles associated with permissions on this library item',
+ not_displayed3='Role members can import this dataset into their history for analysis' )
+ def test_055_library_permissions( self ):
+ """Test library permissions"""
+ # Logged in as admin_user
+ form_name = 'Library template Form One'
+ form_desc = 'This is Form One'
+ form_type = galaxy.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
+ # Create form for library template
+ self.create_form( name=form_name, desc=form_desc, formtype=form_type )
+ global form_one
+ form_one = get_form( form_name )
+ assert form_one is not None, 'Problem retrieving form named (%s) from the database' % form_name
+ # Make sure the template fields are displayed on the library information page
+ field_dict = form_one.fields[ 0 ]
+ global form_one_field_label
+ form_one_field_label = '%s' % str( field_dict.get( 'label', 'Field 0' ) )
+ global form_one_field_help
+ form_one_field_help = '%s' % str( field_dict.get( 'helptext', 'Field 0 help' ) )
+ global form_one_field_required
+ form_one_field_required = '%s' % str( field_dict.get( 'required', 'optional' ) ).capitalize()
+ # Add information to the library using the template
+ global form_one_field_name
+ form_one_field_name = 'field_0'
+ # Create a library, adding no template
+ name = "library security Library Two"
+ description = "library security This is Library Two"
+ synopsis = "library security Library Two synopsis"
+ self.create_library( name=name, description=description, synopsis=synopsis )
+ self.browse_libraries_admin( check_str1=name, check_str2=description )
+ global library_two
+ library_two = get_library( name, description, synopsis )
+ assert library_two is not None, 'Problem retrieving library named "%s" from the database' % name
+ # Set library permissions for regular_user1 and regular_user2. Each of these users will be permitted to
+ # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE for library items.
+ permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ]
+ permissions_out = []
+ role_ids_str = '%s,%s' % ( str( regular_user1_private_role.id ), str( regular_user2_private_role.id ) )
+ self.library_permissions( self.security.encode_id( library_two.id ),
+ library_two.name,
+ role_ids_str,
+ permissions_in,
+ permissions_out )
+ self.logout()
+ # Login as regular_user1 and make sure they can see the library
+ self.login( email=regular_user1.email )
+ self.browse_libraries_regular_user( check_str1=name )
+ self.logout()
+ # Login as regular_user2 and make sure they can see the library
+ self.login( email=regular_user2.email )
+ self.browse_libraries_regular_user( check_str1=name )
+ # Add a dataset to the library
+ message = 'Testing adding 1.bed to Library Two root folder'
+ self.add_library_dataset( 'library',
+ '1.bed',
+ self.security.encode_id( library_two.id ),
+ self.security.encode_id( library_two.root_folder.id ),
+ library_two.root_folder.name,
+ file_type='bed',
+ dbkey='hg18',
+ message=message,
+ root=True )
+ # Add a folder to the library
+ name = "Root Folder's Folder X"
+ description = "This is the root folder's Folder X"
+ self.add_folder( 'library',
+ self.security.encode_id( library_two.id ),
+ self.security.encode_id( library_two.root_folder.id ),
+ name=name,
+ description=description )
+ global folder_x
+ folder_x = get_folder( library_two.root_folder.id, name, description )
+ # Add an information template to the folder
+ template_name = 'Folder Template 1'
+ self.add_library_template( 'library',
+ 'folder',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name,
+ folder_id=self.security.encode_id( folder_x.id ) )
+ # Modify the folder's information
+ contents = '%s folder contents' % form_one_field_label
+ new_name = "Root Folder's Folder Y"
+ new_description = "This is the root folder's Folder Y"
+ self.folder_info( 'library',
+ self.security.encode_id( folder_x.id ),
+ self.security.encode_id( library_two.id ),
+ name,
+ new_name,
+ new_description,
+ contents=contents,
+ field_name=form_one_field_name )
+ # Twill barfs when self.check_page_for_string() is called after dealing with an information template,
+ # the exception is: TypeError: 'str' object is not callable
+ # the work-around it to end this method so any calls are in the next method.
+ def test_060_template_features_and_permissions( self ):
+ """Test library template and more permissions behavior from the Data Libraries view"""
+ # Logged in as regular_user2
+ refresh( folder_x )
+ # Add a dataset to the folder
+ message = 'Testing adding 2.bed to Library Three root folder'
+ self.add_library_dataset( 'library',
+ '2.bed',
+ self.security.encode_id( library_two.id ),
+ self.security.encode_id( folder_x.id ),
+ folder_x.name,
+ file_type='bed',
+ dbkey='hg18',
+ message=message.replace( ' ', '+' ),
+ root=False )
+ global ldda_x
+ ldda_x = get_latest_ldda()
+ assert ldda_x is not None, 'Problem retrieving ldda_x from the database'
+ # Add an information template to the library
+ template_name = 'Library Template 3'
+ self.add_library_template( 'library',
+ 'library',
+ self.security.encode_id( library_two.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name )
+ # Add information to the library using the template
+ contents = '%s library contents' % form_one_field_label
+ self.visit_url( '%s/library_common/library_info?cntrller=library&id=%s' % ( self.url, self.security.encode_id( library_two.id ) ) )
+ # There are 2 forms on this page and the template is the 2nd form
+ tc.fv( '2', form_one_field_name, contents )
+ tc.submit( 'edit_info_button' )
+ # For some reason, the following check:
+ # self.check_page_for_string ( 'The information has been updated.' )
+ # ...throws the following exception - I have not idea why!
+ # TypeError: 'str' object is not callable
+ # The work-around is to not make ANY self.check_page_for_string() calls until the next method
+ def test_065_permissions_as_different_regular_user( self ):
+ """Test library template and more permissions behavior from the Data Libraries view as a different user"""
+ # Logged in as regular_user2
+ self.logout()
+ self.login( email=regular_user1.email )
+ self.browse_library( 'library',
+ self.security.encode_id( library_two.id ),
+ check_str1=ldda_x.name )
+ def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as regular_user1
+ self.logout()
+ self.login( email=admin_user.email )
+ ##################
+ # Purge all libraries
+ ##################
+ for library in [ library_one, library_two ]:
+ self.delete_library_item( self.security.encode_id( library.id ),
+ self.security.encode_id( library.id ),
+ library.name,
+ item_type='library' )
+ self.purge_library( self.security.encode_id( library.id ), library.name )
+ ##################
+ # Eliminate all non-private roles
+ ##################
+ for role in [ role_one, role_two ]:
+ self.mark_role_deleted( self.security.encode_id( role.id ), role.name )
+ self.purge_role( self.security.encode_id( role.id ), role.name )
+ # Manually delete the role from the database
+ refresh( role )
+ sa_session.delete( role )
+ sa_session.flush()
+ ##################
+ # Eliminate all groups
+ ##################
+ for group in [ group_one ]:
+ self.mark_group_deleted( self.security.encode_id( group.id ), group.name )
+ self.purge_group( self.security.encode_id( group.id ), group.name )
+ # Manually delete the group from the database
+ refresh( group )
+ sa_session.delete( group )
+ sa_session.flush()
+ ##################
+ # Make sure all users are associated only with their private roles
+ ##################
+ for user in [ admin_user, regular_user1, regular_user2, regular_user3 ]:
+ refresh( user )
+ if len( user.roles) != 1:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) )
diff -r e39c9a2a0b4c -r 48e83411aa91 test/functional/test_security_and_libraries.py
--- a/test/functional/test_security_and_libraries.py Fri Mar 12 14:27:04 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2141 +0,0 @@
-import galaxy.model
-from galaxy.model.orm import *
-from galaxy.model.mapping import context as sa_session
-from base.twilltestcase import *
-
-not_logged_in_security_msg = 'You must be logged in as an administrator to access this feature.'
-logged_in_security_msg = 'You must be an administrator to access this feature.'
-
-import sys
-class TestSecurityAndLibraries( TwillTestCase ):
- def test_000_admin_features_when_not_logged_in( self ):
- """Testing admin_features when not logged in"""
- self.logout()
- self.visit_url( "%s/admin" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/reload_tool?tool_id=upload1" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/roles" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/create_role" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/create_role" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/manage_users_and_groups_for_role" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/groups" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/create_group" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- self.check_page_for_string( not_logged_in_security_msg )
- self.visit_url( "%s/admin/users" % self.url )
- self.check_page_for_string( not_logged_in_security_msg )
- def test_005_login_as_admin_user( self ):
- """Testing logging in as an admin user test(a)bx.psu.edu - tests initial settings for DefaultUserPermissions and DefaultHistoryPermissions"""
- self.login( email='test(a)bx.psu.edu' ) # test(a)bx.psu.edu is configured as our admin user
- self.visit_page( "admin" )
- self.check_page_for_string( 'Administration' )
- global admin_user
- admin_user = sa_session.query( galaxy.model.User ) \
- .filter( galaxy.model.User.table.c.email=='test(a)bx.psu.edu' ) \
- .first()
- assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
- # Get the admin user's private role for later use
- global admin_user_private_role
- admin_user_private_role = None
- for role in admin_user.all_roles():
- if role.name == admin_user.email and role.description == 'Private Role for %s' % admin_user.email:
- admin_user_private_role = role
- break
- if not admin_user_private_role:
- raise AssertionError( "Private role not found for user '%s'" % admin_user.email )
- # Make sure DefaultUserPermissions are correct
- if len( admin_user.default_permissions ) > 1:
- raise AssertionError( '%d DefaultUserPermissions associated with user %s ( should be 1 )' \
- % ( len( admin_user.default_permissions ), admin_user.email ) )
- dup = sa_session.query( galaxy.model.DefaultUserPermissions ) \
- .filter( galaxy.model.DefaultUserPermissions.table.c.user_id==admin_user.id ) \
- .first()
- if not dup.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
- raise AssertionError( 'The DefaultUserPermission.action for user "%s" is "%s", but it should be "%s"' \
- % ( admin_user.email, dup.action, galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
- # Make sure DefaultHistoryPermissions are correct
- # Logged in as admin_user
- latest_history = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.user_id==admin_user.id ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
- if len( latest_history.default_permissions ) > 1:
- raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d when it was created ( should have been 1 )' \
- % ( len( latest_history.default_permissions ), latest_history.id ) )
- dhp = sa_session.query( galaxy.model.DefaultHistoryPermissions ) \
- .filter( galaxy.model.DefaultHistoryPermissions.table.c.history_id==latest_history.id ) \
- .first()
- if not dhp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
- raise AssertionError( 'The DefaultHistoryPermission.action for history id %d is "%s", but it should be "%s"' \
- % ( latest_history.id, dhp.action, galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
- self.home()
- self.visit_url( "%s/admin/manage_roles_and_groups_for_user?id=%s" % ( self.url, self.security.encode_id( admin_user.id ) ) )
- self.check_page_for_string( admin_user.email )
- # Try deleting the admin_user's private role
- check_str = "You cannot eliminate a user's private role association."
- self.associate_roles_and_groups_with_user( self.security.encode_id( admin_user.id ), admin_user.email,
- out_role_ids=str( admin_user_private_role.id ),
- check_str=check_str )
- self.logout()
- def test_010_login_as_regular_user1( self ):
- """Testing logging in as regular user test1(a)bx.psu.edu - tests private role creation and changing DefaultHistoryPermissions for new histories"""
- # Some of the history related tests here are similar to some tests in the
- # test_history_functions.py script, so we could potentially eliminate 1 or 2 of them.
- self.login( email='test1(a)bx.psu.edu' ) # test1(a)bx.psu.edu is not an admin user
- global regular_user1
- regular_user1 = sa_session.query( galaxy.model.User ) \
- .filter( galaxy.model.User.table.c.email=='test1(a)bx.psu.edu' ) \
- .first()
- assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
- self.visit_page( "admin" )
- self.check_page_for_string( logged_in_security_msg )
- # Make sure a private role exists for regular_user1
- private_role = None
- for role in regular_user1.all_roles():
- if role.name == regular_user1.email and role.description == 'Private Role for %s' % regular_user1.email:
- private_role = role
- break
- if not private_role:
- raise AssertionError( "Private role not found for user '%s'" % regular_user1.email )
- global regular_user1_private_role
- regular_user1_private_role = private_role
- # Add a dataset to the history
- self.upload_file( '1.bed' )
- latest_dataset = sa_session.query( galaxy.model.Dataset ) \
- .order_by( desc( galaxy.model.Dataset.table.c.create_time ) ) \
- .first()
- # Make sure DatasetPermissions is correct - default is 'manage permissions'
- if len( latest_dataset.actions ) > 1:
- actions = [ a.action for a in latest_dataset.actions ]
- raise AssertionError( '%d DatasetPermissions (%s) were created for dataset id %d when it was created ( should have been 1 )' \
- % ( len( latest_dataset.actions ), str( actions ), latest_dataset.id ) )
- dp = sa_session.query( galaxy.model.DatasetPermissions ) \
- .filter( galaxy.model.DatasetPermissions.table.c.dataset_id==latest_dataset.id ) \
- .first()
- if not dp.action:
- raise AssertionError( 'The Dataset id %d has no associated DatasetPermissions when is should have "manage permissions".' \
- % latest_dataset.id )
- elif not dp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
- raise AssertionError( 'The DatasetPermissions.action for dataset id %d is "%s", but it should be "manage permissions"' \
- % ( latest_dataset.id, dp.action ) )
- # Change DefaultHistoryPermissions for regular_user1
- permissions_in = []
- actions_in = []
- for key, value in galaxy.model.Dataset.permitted_actions.items():
- # NOTE: setting the 'access' permission with the private role makes this dataset private
- permissions_in.append( key )
- actions_in.append( value.action )
- # Sort actions for later comparison
- actions_in.sort()
- role_id = str( private_role.id )
- self.user_set_default_permissions( permissions_in=permissions_in, role_id=role_id )
- # Make sure the default permissions are changed for new histories
- self.new_history()
- # logged in as regular_user1
- latest_history = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
- if len( latest_history.default_permissions ) != len( galaxy.model.Dataset.permitted_actions.items() ):
- raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d, should have been %d' % \
- ( len( latest_history.default_permissions ), latest_history.id, len( galaxy.model.Dataset.permitted_actions.items() ) ) )
- dhps = []
- for dhp in latest_history.default_permissions:
- dhps.append( dhp.action )
- # Sort permissions for later comparison
- dhps.sort()
- for key, value in galaxy.model.Dataset.permitted_actions.items():
- if value.action not in dhps:
- raise AssertionError( '%s not in history id %d default_permissions after they were changed' % ( value.action, latest_history.id ) )
- # Add a dataset to the history
- self.upload_file( '1.bed' )
- latest_dataset = sa_session.query( galaxy.model.Dataset ).order_by( desc( galaxy.model.Dataset.table.c.create_time ) ).first()
- # Make sure DatasetPermissionss are correct
- if len( latest_dataset.actions ) != len( latest_history.default_permissions ):
- raise AssertionError( '%d DatasetPermissionss were created for dataset id %d when it was created ( should have been %d )' % \
- ( len( latest_dataset.actions ), latest_dataset.id, len( latest_history.default_permissions ) ) )
- dps = []
- for dp in latest_dataset.actions:
- dps.append( dp.action )
- # Sort actions for later comparison
- dps.sort()
- # Compare DatasetPermissions with permissions_in - should be the same
- if dps != actions_in:
- raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from changed default permissions "%s"' \
- % ( str( dps ), latest_dataset.id, str( actions_in ) ) )
- # Compare DefaultHistoryPermissions and DatasetPermissionss - should be the same
- if dps != dhps:
- raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s" for history id %d' \
- % ( str( dps ), latest_dataset.id, str( dhps ), latest_history.id ) )
- self.logout()
-
- def test_015_login_as_regular_user2( self ):
- """Testing logging in as regular user test2(a)bx.psu.edu - tests changing DefaultHistoryPermissions for the current history"""
- email = 'test2(a)bx.psu.edu'
- self.login( email=email ) # This will not be an admin user
- global regular_user2
- regular_user2 = sa_session.query( galaxy.model.User ) \
- .filter( galaxy.model.User.table.c.email==email ) \
- .first()
- assert regular_user2 is not None, 'Problem retrieving user with email "" from the database' % email
- # Logged in as regular_user2
- latest_history = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
- self.upload_file( '1.bed' )
- latest_dataset = sa_session.query( galaxy.model.Dataset ).order_by( desc( galaxy.model.Dataset.table.c.create_time ) ).first()
- permissions_in = [ 'DATASET_MANAGE_PERMISSIONS' ]
- # Make sure these are in sorted order for later comparison
- actions_in = [ 'manage permissions' ]
- permissions_out = [ 'DATASET_ACCESS' ]
- actions_out = [ 'access' ]
- global regular_user2_private_role
- regular_user2_private_role = None
- for role in regular_user2.all_roles():
- if role.name == regular_user2.email and role.description == 'Private Role for %s' % regular_user2.email:
- regular_user2_private_role = role
- break
- if not regular_user2_private_role:
- raise AssertionError( "Private role not found for user '%s'" % regular_user2.email )
- role_id = str( regular_user2_private_role.id )
- # Change DefaultHistoryPermissions for the current history
- self.history_set_default_permissions( permissions_out=permissions_out, permissions_in=permissions_in, role_id=role_id )
- if len( latest_history.default_permissions ) != len( actions_in ):
- raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d, should have been %d' \
- % ( len( latest_history.default_permissions ), latest_history.id, len( permissions_in ) ) )
- # Make sure DefaultHistoryPermissions were correctly changed for the current history
- dhps = []
- for dhp in latest_history.default_permissions:
- dhps.append( dhp.action )
- # Sort permissions for later comparison
- dhps.sort()
- # Compare DefaultHistoryPermissions and actions_in - should be the same
- if dhps != actions_in:
- raise AssertionError( 'DefaultHistoryPermissions "%s" for history id %d differ from actions "%s" passed for changing' \
- % ( str( dhps ), latest_history.id, str( actions_in ) ) )
- # Make sure DatasetPermissionss are correct
- if len( latest_dataset.actions ) != len( latest_history.default_permissions ):
- raise AssertionError( '%d DatasetPermissionss were created for dataset id %d when it was created ( should have been %d )' \
- % ( len( latest_dataset.actions ), latest_dataset.id, len( latest_history.default_permissions ) ) )
- dps = []
- for dp in latest_dataset.actions:
- dps.append( dp.action )
- # Sort actions for comparison
- dps.sort()
- # Compare DatasetPermissionss and DefaultHistoryPermissions - should be the same
- if dps != dhps:
- raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s"' \
- % ( str( dps ), latest_dataset.id, str( dhps ) ) )
- self.logout()
- def test_020_create_new_user_account_as_admin( self ):
- """Testing creating a new user account as admin"""
- self.login( email=admin_user.email )
- email = 'test3(a)bx.psu.edu'
- password = 'testuser'
- previously_created = self.create_new_account_as_admin( email=email, password=password )
- # Get the user object for later tests
- global regular_user3
- regular_user3 = sa_session.query( galaxy.model.User ).filter( galaxy.model.User.table.c.email==email ).first()
- assert regular_user3 is not None, 'Problem retrieving user with email "%s" from the database' % email
- global regular_user3_private_role
- regular_user3_private_role = None
- for role in regular_user3.all_roles():
- if role.name == regular_user3.email and role.description == 'Private Role for %s' % regular_user3.email:
- regular_user3_private_role = role
- break
- if not regular_user3_private_role:
- raise AssertionError( "Private role not found for user '%s'" % regular_user3.email )
- # Make sure DefaultUserPermissions were created
- if not regular_user3.default_permissions:
- raise AssertionError( 'No DefaultUserPermissions were created for user %s when the admin created the account' % email )
- # Make sure a private role was created for the user
- if not regular_user3.roles:
- raise AssertionError( 'No UserRoleAssociations were created for user %s when the admin created the account' % email )
- if not previously_created and len( regular_user3.roles ) != 1:
- raise AssertionError( '%d UserRoleAssociations were created for user %s when the admin created the account ( should have been 1 )' \
- % ( len( regular_user3.roles ), regular_user3.email ) )
- for ura in regular_user3.roles:
- role = sa_session.query( galaxy.model.Role ).get( ura.role_id )
- if not previously_created and role.type != 'private':
- raise AssertionError( 'Role created for user %s when the admin created the account is not private, type is' \
- % str( role.type ) )
- if not previously_created:
- # Make sure a history was not created ( previous test runs may have left deleted histories )
- histories = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.user_id==regular_user3.id,
- galaxy.model.History.table.c.deleted==False ) ) \
- .all()
- if histories:
- raise AssertionError( 'Histories were incorrectly created for user %s when the admin created the account' % email )
- # Make sure the user was not associated with any groups
- if regular_user3.groups:
- raise AssertionError( 'Groups were incorrectly associated with user %s when the admin created the account' % email )
- def test_025_reset_password_as_admin( self ):
- """Testing reseting a user password as admin"""
- email = 'test3(a)bx.psu.edu'
- self.reset_password_as_admin( user_id=self.security.encode_id( regular_user3.id ), password='testreset' )
- self.logout()
- def test_030_login_after_password_reset( self ):
- """Testing logging in after an admin reset a password - tests DefaultHistoryPermissions for accounts created by an admin"""
- self.login( email='test3(a)bx.psu.edu', password='testreset' )
- # Make sure a History and HistoryDefaultPermissions exist for the user
- # Logged in as regular_user3
- latest_history = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.user_id==regular_user3.id ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
- if not latest_history.user_id == regular_user3.id:
- raise AssertionError( 'A history was not created for user %s when he logged in' % email )
- if not latest_history.default_permissions:
- raise AssertionError( 'No DefaultHistoryPermissions were created for history id %d when it was created' % latest_history.id )
- if len( latest_history.default_permissions ) > 1:
- raise AssertionError( 'More than 1 DefaultHistoryPermissions were created for history id %d when it was created' % latest_history.id )
- dhp = sa_session.query( galaxy.model.DefaultHistoryPermissions ) \
- .filter( galaxy.model.DefaultHistoryPermissions.table.c.history_id==latest_history.id ) \
- .first()
- if not dhp.action == galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
- raise AssertionError( 'The DefaultHistoryPermission.action for history id %d is "%s", but it should be "manage permissions"' \
- % ( latest_history.id, dhp.action ) )
- # Upload a file to create a HistoryDatasetAssociation
- self.upload_file( '1.bed' )
- latest_dataset = sa_session.query( galaxy.model.Dataset ).order_by( desc( galaxy.model.Dataset.table.c.create_time ) ).first()
- for dp in latest_dataset.actions:
- # Should only have 1 DatasetPermissions
- if dp.action != galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action:
- raise AssertionError( 'The DatasetPermissions for dataset id %d is %s ( should have been %s )' \
- % ( latest_dataset.id,
- latest_dataset.actions.action,
- galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
- self.logout()
- # Reset the password to the default for later tests
- self.login( email='test(a)bx.psu.edu' )
- self.reset_password_as_admin( user_id=self.security.encode_id( regular_user3.id ), password='testuser' )
- def test_035_mark_user_deleted( self ):
- """Testing marking a user account as deleted"""
- # Logged in as admin_user
- self.mark_user_deleted( user_id=self.security.encode_id( regular_user3.id ), email=regular_user3.email )
- # Deleting a user should not delete any associations
- sa_session.refresh( regular_user3 )
- if not regular_user3.active_histories:
- raise AssertionError( 'HistoryDatasetAssociations for regular_user3 were incorrectly deleted when the user was marked deleted' )
- def test_040_undelete_user( self ):
- """Testing undeleting a user account"""
- # Logged in as admin_user
- self.undelete_user( user_id=self.security.encode_id( regular_user3.id ), email=regular_user3.email )
- def test_045_create_role( self ):
- """Testing creating new role with 3 members ( and a new group named the same ), then renaming the role"""
- # Logged in as admin_user
- name = 'Role One'
- description = "This is Role Ones description"
- user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
- self.create_role( name=name,
- description=description,
- in_user_ids=user_ids,
- in_group_ids=[],
- create_group_for_role='yes',
- private_role=admin_user.email )
- # Get the role object for later tests
- global role_one
- role_one = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
- assert role_one is not None, 'Problem retrieving role named "Role One" from the database'
- # Make sure UserRoleAssociations are correct
- if len( role_one.users ) != len( user_ids ):
- raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created ( should have been %d )' \
- % ( len( role_one.users ), role_one.id, len( user_ids ) ) )
- # Each of the following users should now have 2 role associations, their private role and role_one
- for user in [ admin_user, regular_user1, regular_user3 ]:
- sa_session.refresh( user )
- if len( user.roles ) != 2:
- raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 2 )' \
- % ( len( user.roles ), user.email ) )
- # Make sure the group was created
- self.home()
- self.visit_page( 'admin/groups' )
- self.check_page_for_string( name )
- global group_zero
- group_zero = sa_session.query( galaxy.model.Group ).filter( galaxy.model.Group.table.c.name==name ).first()
- # Rename the role
- rename = "Role One's been Renamed"
- new_description="This is Role One's Re-described"
- self.rename_role( self.security.encode_id( role_one.id ), name=rename, description=new_description )
- self.home()
- self.visit_page( 'admin/roles' )
- self.check_page_for_string( rename )
- self.check_page_for_string( new_description )
- # Reset the role back to the original name and description
- self.rename_role( self.security.encode_id( role_one.id ), name=name, description=description )
- def test_050_create_group( self ):
- """Testing creating new group with 3 members and 1 associated role, then renaming it"""
- # Logged in as admin_user
- name = "Group One's Name"
- user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
- role_ids=[ str( role_one.id ) ]
- self.create_group( name=name, in_user_ids=user_ids, in_role_ids=role_ids )
- # Get the group object for later tests
- global group_one
- group_one = sa_session.query( galaxy.model.Group ).filter( galaxy.model.Group.table.c.name==name ).first()
- assert group_one is not None, 'Problem retrieving group named "Group One" from the database'
- # Make sure UserGroupAssociations are correct
- if len( group_one.users ) != len( user_ids ):
- raise AssertionError( '%d UserGroupAssociations were created for group id %d when it was created ( should have been %d )' \
- % ( len( group_one.users ), group_one.id, len( user_ids ) ) )
- # Each user should now have 1 group association, group_one
- for user in [ admin_user, regular_user1, regular_user3 ]:
- sa_session.refresh( user )
- if len( user.groups ) != 1:
- raise AssertionError( '%d UserGroupAssociations are associated with user %s ( should be 1 )' % ( len( user.groups ), user.email ) )
- # Make sure GroupRoleAssociations are correct
- if len( group_one.roles ) != len( role_ids ):
- raise AssertionError( '%d GroupRoleAssociations were created for group id %d when it was created ( should have been %d )' \
- % ( len( group_one.roles ), group_one.id, len( role_ids ) ) )
- # Rename the group
- rename = "Group One's been Renamed"
- self.rename_group( self.security.encode_id( group_one.id ), name=rename, )
- self.home()
- self.visit_page( 'admin/groups' )
- self.check_page_for_string( rename )
- # Reset the group back to the original name
- self.rename_group( self.security.encode_id( group_one.id ), name=name )
- def test_055_add_members_and_role_to_group( self ):
- """Testing editing user membership and role associations of an existing group"""
- # Logged in as admin_user
- name = 'Group Two'
- self.create_group( name=name, in_user_ids=[], in_role_ids=[] )
- # Get the group object for later tests
- global group_two
- group_two = sa_session.query( galaxy.model.Group ).filter( galaxy.model.Group.table.c.name==name ).first()
- assert group_two is not None, 'Problem retrieving group named "Group Two" from the database'
- # group_two should have no associations
- if group_two.users:
- raise AssertionError( '%d UserGroupAssociations were created for group id %d when it was created ( should have been 0 )' \
- % ( len( group_two.users ), group_two.id ) )
- if group_two.roles:
- raise AssertionError( '%d GroupRoleAssociations were created for group id %d when it was created ( should have been 0 )' \
- % ( len( group_two.roles ), group_two.id ) )
- user_ids = [ str( regular_user1.id ) ]
- role_ids = [ str( role_one.id ) ]
- self.associate_users_and_roles_with_group( self.security.encode_id( group_two.id ),
- group_two.name,
- user_ids=user_ids,
- role_ids=role_ids )
- def test_060_create_role_with_user_and_group_associations( self ):
- """Testing creating a role with user and group associations"""
- # Logged in as admin_user
- # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
- # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT
- # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the
- # associate_users_and_groups_with_role() method.
- name = 'Role Two'
- description = 'This is Role Two'
- user_ids=[ str( admin_user.id ) ]
- group_ids=[ str( group_two.id ) ]
- private_role=admin_user.email
- # Create the role
- self.create_role( name=name,
- description=description,
- in_user_ids=user_ids,
- in_group_ids=group_ids,
- private_role=private_role )
- # Get the role object for later tests
- global role_two
- role_two = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
- assert role_two is not None, 'Problem retrieving role named "Role Two" from the database'
- # Make sure UserRoleAssociations are correct
- if len( role_two.users ) != len( user_ids ):
- raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created with %d members' \
- % ( len( role_two.users ), role_two.id, len( user_ids ) ) )
- # admin_user should now have 3 role associations, private role, role_one, role_two
- sa_session.refresh( admin_user )
- if len( admin_user.roles ) != 3:
- raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 3 )' % ( len( admin_user.roles ), admin_user.email ) )
- # Make sure GroupRoleAssociations are correct
- sa_session.refresh( role_two )
- if len( role_two.groups ) != len( group_ids ):
- raise AssertionError( '%d GroupRoleAssociations were created for role id %d when it was created ( should have been %d )' \
- % ( len( role_two.groups ), role_two.id, len( group_ids ) ) )
- # group_two should now be associated with 2 roles: role_one, role_two
- sa_session.refresh( group_two )
- if len( group_two.roles ) != 2:
- raise AssertionError( '%d GroupRoleAssociations are associated with group id %d ( should be 2 )' % ( len( group_two.roles ), group_two.id ) )
- def test_065_change_user_role_associations( self ):
- """Testing changing roles associated with a user"""
- # Logged in as admin_user
- # Create a new role with no associations
- name = 'Role Three'
- description = 'This is Role Three'
- user_ids=[]
- group_ids=[]
- private_role=admin_user.email
- self.create_role( name=name,
- description=description,
- in_user_ids=user_ids,
- in_group_ids=group_ids,
- private_role=private_role )
- # Get the role object for later tests
- global role_three
- role_three = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
- assert role_three is not None, 'Problem retrieving role named "Role Three" from the database'
- # Associate the role with a user
- sa_session.refresh( admin_user )
- role_ids = []
- for ura in admin_user.non_private_roles:
- role_ids.append( str( ura.role_id ) )
- role_ids.append( str( role_three.id ) )
- group_ids = []
- for uga in admin_user.groups:
- group_ids.append( str( uga.group_id ) )
- check_str = "User '%s' has been updated with %d associated roles and %d associated groups" % ( admin_user.email, len( role_ids ), len( group_ids ) )
- self.associate_roles_and_groups_with_user( self.security.encode_id( admin_user.id ),
- str( admin_user.email ),
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/e39c9a2a0b4c
changeset: 3527:e39c9a2a0b4c
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Mar 12 14:27:04 2010 -0500
description:
UI Improvements:
-Make it possible to show messages in frames.
-Improve import interactions by showing messages in frames and providing useful links.
-Add action icons to display framework.
diffstat:
lib/galaxy/web/controllers/dataset.py | 16 +++++++++---
lib/galaxy/web/controllers/history.py | 35 ++++++++++++++++++---------
lib/galaxy/web/controllers/workflow.py | 22 +++++++++++++----
lib/galaxy/web/framework/__init__.py | 16 ++++++------
templates/dataset/display.mako | 10 ++++---
templates/display_base.mako | 7 +++--
templates/display_common.mako | 10 ++++++++
templates/grid_base.mako | 13 +--------
templates/grid_base_async.mako | 3 +-
templates/history/display.mako | 11 +--------
templates/message.mako | 36 +++++++++++++++++++++++++++-
templates/page/select_items_grid_async.mako | 3 +-
templates/workflow/display.mako | 6 +----
13 files changed, 122 insertions(+), 66 deletions(-)
diffs (411 lines):
diff -r f8c305ba23cb -r e39c9a2a0b4c lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Fri Mar 12 12:43:31 2010 -0500
+++ b/lib/galaxy/web/controllers/dataset.py Fri Mar 12 14:27:04 2010 -0500
@@ -418,17 +418,25 @@
return self.stored_list_grid( trans, status=status, message=message, **kwargs )
@web.expose
- def imp( self, trans, id=None, **kwd ):
+ def imp( self, trans, dataset_id=None, **kwd ):
""" Import another user's dataset via a shared URL; dataset is added to user's current history. """
msg = ""
+ # Set referer message.
+ referer = trans.request.referer
+ if referer is not "":
+ referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ else:
+ referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
+
# Error checking.
- if not id:
- return trans.show_error_message( "You must specify an ID for a dataset to import." )
+ if not dataset_id:
+ return trans.show_error_message( "You must specify a dataset to import. You can %s." % referer_message, use_panels=True )
# Do import.
cur_history = trans.get_history( create=True )
- status, message = self._copy_datasets( trans, [ id ], [ cur_history ] )
+ status, message = self._copy_datasets( trans, [ dataset_id ], [ cur_history ] )
+ message = message + "<br>You can <a href='%s'>start using the dataset</a> or %s." % ( url_for('/'), referer_message )
return trans.show_message( message, type=status )
@web.expose
diff -r f8c305ba23cb -r e39c9a2a0b4c lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Fri Mar 12 12:43:31 2010 -0500
+++ b/lib/galaxy/web/controllers/history.py Fri Mar 12 14:27:04 2010 -0500
@@ -505,16 +505,27 @@
msg = ""
user = trans.get_user()
user_history = trans.get_history()
+ # Set referer message
+ if 'referer' in kwd:
+ referer = kwd['referer']
+ else:
+ referer = trans.request.referer
+ if referer is not "":
+ referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ else:
+ referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
+
+ # Do import.
if not id:
- return trans.show_error_message( "You must specify a history you want to import." )
+ return trans.show_error_message( "You must specify a history you want to import.<br>You can %s." % referer_message, use_panels=True )
import_history = self.get_history( trans, id, check_ownership=False )
if not import_history:
- return trans.show_error_message( "The specified history does not exist.")
+ return trans.show_error_message( "The specified history does not exist.<br>You can %s." % referer_message, use_panels=True )
if not import_history.importable:
- error( "The owner of this history has disabled imports via this link." )
+ return trans.show_error_message( "The owner of this history has disabled imports via this link.<br>You can %s." % referer_message, use_panels=True )
if user:
if import_history.user_id == user.id:
- return trans.show_error_message( "You cannot import your own history." )
+ return trans.show_error_message( "You cannot import your own history.<br>You can %s." % referer_message, use_panels=True )
new_history = import_history.copy( target_user=user )
new_history.name = "imported: " + new_history.name
new_history.user_id = user.id
@@ -530,9 +541,9 @@
trans.sa_session.flush()
if not user_history.datasets:
trans.set_history( new_history )
- return trans.show_ok_message( """
- History "%s" has been imported. Click <a href="%s">here</a>
- to begin.""" % ( new_history.name, web.url_for( '/' ) ) )
+ return trans.show_ok_message(
+ message="""History "%s" has been imported. <br>You can <a href="%s">start using this history</a> or %s."""
+ % ( new_history.name, web.url_for( '/' ), referer_message ), use_panels=True )
elif not user_history or not user_history.datasets or confirm:
new_history = import_history.copy()
new_history.name = "imported: " + new_history.name
@@ -548,13 +559,13 @@
trans.sa_session.add( new_history )
trans.sa_session.flush()
trans.set_history( new_history )
- return trans.show_ok_message( """
- History "%s" has been imported. Click <a href="%s">here</a>
- to begin.""" % ( new_history.name, web.url_for( '/' ) ) )
+ return trans.show_ok_message(
+ message="""History "%s" has been imported. <br>You can <a href="%s">start using this history</a> or %s."""
+ % ( new_history.name, web.url_for( '/' ), referer_message ), use_panels=True )
return trans.show_warn_message( """
Warning! If you import this history, you will lose your current
- history. Click <a href="%s">here</a> to confirm.
- """ % web.url_for( id=id, confirm=True ) )
+ history. <br>You can <a href="%s">continue and import this history</a> or %s.
+ """ % ( web.url_for( id=id, confirm=True, referer=trans.request.referer ), referer_message ), use_panels=True )
@web.expose
def view( self, trans, id=None ):
diff -r f8c305ba23cb -r e39c9a2a0b4c lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py Fri Mar 12 12:43:31 2010 -0500
+++ b/lib/galaxy/web/controllers/workflow.py Fri Mar 12 14:27:04 2010 -0500
@@ -278,18 +278,28 @@
@web.expose
@web.require_login( "use Galaxy workflows" )
def imp( self, trans, id, **kwargs ):
+ # Set referer message.
+ referer = trans.request.referer
+ if referer is not "":
+ referer_message = "<a href='%s'>return to the previous page</a>" % referer
+ else:
+ referer_message = "<a href='%s'>go to Galaxy's start page</a>" % url_for( '/' )
+
+ # Do import.
session = trans.sa_session
stored = self.get_stored_workflow( trans, id, check_ownership=False )
if stored.importable == False:
- error( "The owner of this workflow has disabled imports via this link" )
+ return trans.show_error_message( "The owner of this workflow has disabled imports via this link.<br>You can %s" % referer_message, use_panels=True )
elif stored.user == trans.user:
- error( "You are already the owner of this workflow, can't import" )
+ return trans.show_error_message( "You can't import this workflow because you own it.<br>You can %s" % referer_message, use_panels=True )
elif stored.deleted:
- error( "This workflow has been deleted, can't import" )
+ return trans.show_error_message( "You can't import this workflow because it has been deleted.<br>You can %s" % referer_message, use_panels=True )
elif session.query( model.StoredWorkflowUserShareAssociation ) \
.filter_by( user=trans.user, stored_workflow=stored ).count() > 0:
- error( "This workflow is already shared with you" )
+ # TODO: this is only reasonable as long as import creates a sharing relation.
+ return trans.show_error_message( "You can't import this workflow because it is already shared with you.<br>You can %s" % referer_message, use_panels=True )
else:
+ # TODO: Shouldn't an import provide a copy of a workflow?
share = model.StoredWorkflowUserShareAssociation()
share.stored_workflow = stored
share.user = trans.user
@@ -297,7 +307,9 @@
session.add( share )
session.flush()
# Redirect to load galaxy frames.
- return trans.response.send_redirect( url_for( controller='workflow' ) )
+ return trans.show_ok_message(
+ message="""Workflow "%s" has been imported. <br>You can <a href="%s">start using this workflow</a> or %s."""
+ % ( stored.name, web.url_for( controller='workflow' ), referer_message ), use_panels=True )
@web.expose
@web.require_login( "use Galaxy workflows" )
diff -r f8c305ba23cb -r e39c9a2a0b4c lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py Fri Mar 12 12:43:31 2010 -0500
+++ b/lib/galaxy/web/framework/__init__.py Fri Mar 12 14:27:04 2010 -0500
@@ -561,7 +561,7 @@
context.
"""
return self.template_context['message']
- def show_message( self, message, type='info', refresh_frames=[], cont=None ):
+ def show_message( self, message, type='info', refresh_frames=[], cont=None, use_panels=False ):
"""
Convenience method for displaying a simple page with a single message.
@@ -571,22 +571,22 @@
`refresh_frames`: names of frames in the interface that should be
refreshed when the message is displayed
"""
- return self.fill_template( "message.mako", message_type=type, message=message, refresh_frames=refresh_frames, cont=cont )
- def show_error_message( self, message, refresh_frames=[] ):
+ return self.fill_template( "message.mako", message_type=type, message=message, refresh_frames=refresh_frames, cont=cont, use_panels=use_panels )
+ def show_error_message( self, message, refresh_frames=[], use_panels=False ):
"""
Convenience method for displaying an error message. See `show_message`.
"""
- return self.show_message( message, 'error', refresh_frames )
- def show_ok_message( self, message, refresh_frames=[] ):
+ return self.show_message( message, 'error', refresh_frames, use_panels=use_panels )
+ def show_ok_message( self, message, refresh_frames=[], use_panels=False ):
"""
Convenience method for displaying an ok message. See `show_message`.
"""
- return self.show_message( message, 'done', refresh_frames )
- def show_warn_message( self, message, refresh_frames=[] ):
+ return self.show_message( message, 'done', refresh_frames, use_panels=use_panels )
+ def show_warn_message( self, message, refresh_frames=[], use_panels=False ):
"""
Convenience method for displaying an warn message. See `show_message`.
"""
- return self.show_message( message, 'warning', refresh_frames )
+ return self.show_message( message, 'warning', refresh_frames, use_panels=use_panels )
def show_form( self, form, header=None, template="form.mako" ):
"""
Convenience method for displaying a simple page with a single HTML
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/dataset/display.mako
--- a/templates/dataset/display.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/dataset/display.mako Fri Mar 12 14:27:04 2010 -0500
@@ -23,7 +23,8 @@
<%def name="render_item_links( data )">
## Provide links to save data and TODO: import dataset.
- <a href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}">save</a>
+ <a href="${h.url_for( controller='/dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}" class="icon-button disk tooltip" title="Save dataset"></a>
+ <a href="${h.url_for( controller='/dataset', action='imp', dataset_id=trans.security.encode_id( data.id ) )}" class="icon-button import tooltip" title="Import dataset"></a>
</%def>
<%def name="render_item( data, data_to_render )">
@@ -49,11 +50,12 @@
<div class="unified-panel-body">
<div style="overflow: auto; height: 100%;">
<div class="page-body">
- <div style="padding: 0px 0px 5px 0px">
+ <div style="float: right">
${self.render_item_links( item )}
</div>
-
- ${self.render_item_header( item )}
+ <div>
+ ${self.render_item_header( item )}
+ </div>
${self.render_item( item, item_data )}
</div>
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/display_base.mako
--- a/templates/display_base.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/display_base.mako Fri Mar 12 14:27:04 2010 -0500
@@ -156,11 +156,12 @@
<div class="unified-panel-body">
<div style="overflow: auto; height: 100%;">
<div class="page-body">
- <div style="padding: 0px 0px 5px 0px">
+ <div style="float: right">
${self.render_item_links( item )}
</div>
-
- ${self.render_item_header( item )}
+ <div>
+ ${self.render_item_header( item )}
+ </div>
${self.render_item( item, item_data )}
</div>
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/display_common.mako
--- a/templates/display_common.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/display_common.mako Fri Mar 12 14:27:04 2010 -0500
@@ -128,3 +128,13 @@
%endif
</%def>
+## Render message.
+<%def name="render_message( message, message_type )">
+ %if message:
+ <p>
+ <div class="${message_type}message transient-message">${util.restore_text( message )}</div>
+ <div style="clear: both"></div>
+ </p>
+ %endif
+</%def>
+
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/grid_base.mako
--- a/templates/grid_base.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/grid_base.mako Fri Mar 12 14:27:04 2010 -0500
@@ -9,6 +9,7 @@
return '/base.mako'
%>
<%inherit file="${inherit(context)}"/>
+<%namespace file="/display_common.mako" import="render_message" />
<%def name="init()">
<%
@@ -663,23 +664,13 @@
<tr>
<td width="75%">${self.render_grid_header( grid )}</td>
<td></td>
- <td width="25%" id="grid-message" valign="top">${self.render_grid_message( grid )}</td>
+ <td width="25%" id="grid-message" valign="top">${render_message( message, message_type )}</td>
</tr>
</table>
${self.render_grid_table( grid )}
</%def>
-## Render grid message.
-<%def name="render_grid_message( grid )">
- %if message:
- <p>
- <div class="${message_type}message transient-message">${util.restore_text( message )}</div>
- <div style="clear: both"></div>
- </p>
- %endif
-</%def>
-
## Render grid header.
<%def name="render_grid_header( grid, render_title=True)">
<div class="grid-header">
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/grid_base_async.mako
--- a/templates/grid_base_async.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/grid_base_async.mako Fri Mar 12 14:27:04 2010 -0500
@@ -1,4 +1,5 @@
<%namespace file="./grid_base.mako" import="*" />
+<%namespace file="/display_common.mako" import="render_message" />
<%
# Set flag to indicate whether grid has operations that operate on multiple items.
@@ -12,4 +13,4 @@
*****
${num_pages}
*****
-${render_grid_message( grid )}
\ No newline at end of file
+${render_message( grid )}
\ No newline at end of file
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/history/display.mako
--- a/templates/history/display.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/history/display.mako Fri Mar 12 14:27:04 2010 -0500
@@ -236,16 +236,7 @@
</%def>
<%def name="render_item_links( history )">
- %if history.user != trans.get_user():
- <a href="${h.url_for( controller='/history', action='imp', id=trans.security.encode_id(history.id) )}">import and start using history</a>
- %else:
- ## TODO: add tooltip to indicate why this link is disabled.
- import and start using history
- %endif
- ##<a href="${self.get_history_link( history )}">${_('refresh')}</a>
- %if show_deleted:
- | <a href="${h.url_for('history', show_deleted=False)}">${_('hide deleted')}</a>
- %endif
+ <a href="${h.url_for( controller='/history', action='imp', id=trans.security.encode_id(history.id) )}" class="icon-button import tooltip" title="Import history"></a>
</%def>
<%def name="render_item( history, datasets )">
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/message.mako
--- a/templates/message.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/message.mako Fri Mar 12 14:27:04 2010 -0500
@@ -1,5 +1,21 @@
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
<% _=n_ %>
-<%inherit file="/base.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
<%def name="javascripts()">
${parent.javascripts()}
@@ -45,7 +61,23 @@
</script>
</%def>
-<div class="${message_type}messagelarge">${_(message)}</div>
+##
+## Override methods from base.mako and base_panels.mako
+##
+
+<%def name="center_panel()">
+ ${render_large_message( message, message_type )}
+</%def>
+
+## Render the grid's basic elements. Each of these elements can be subclassed.
+<%def name="body()">
+ ${render_large_message( message, message_type )}
+</%def>
+
+## Render large message.
+<%def name="render_large_message( message, message_type )">
+ <div class="${message_type}messagelarge" style="margin: 1em">${_(message)}</div>
+</%def>
## Render a message
<%def name="render_msg( msg, messagetype='done' )">
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/page/select_items_grid_async.mako
--- a/templates/page/select_items_grid_async.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/page/select_items_grid_async.mako Fri Mar 12 14:27:04 2010 -0500
@@ -1,8 +1,9 @@
<%namespace file="../grid_base.mako" import="*" />
+<%namespace file="/display_common.mako" import="render_message" />
## Always show item checkboxes so that users can select histories.
${render_grid_table_body_contents( grid, show_item_checkboxes=True )}
*****
${num_pages}
*****
-${render_grid_message( grid )}
\ No newline at end of file
+${render_message( message, message_type )}
\ No newline at end of file
diff -r f8c305ba23cb -r e39c9a2a0b4c templates/workflow/display.mako
--- a/templates/workflow/display.mako Fri Mar 12 12:43:31 2010 -0500
+++ b/templates/workflow/display.mako Fri Mar 12 14:27:04 2010 -0500
@@ -77,11 +77,7 @@
<%def name="render_item_links( workflow )">
- %if workflow.user != trans.get_user():
- <a href="${h.url_for( controller='/workflow', action='imp', id=trans.security.encode_id(workflow.id) )}">import and start using workflow</a>
- %else:
- import and start using workflow
- %endif
+ <a href="${h.url_for( controller='/workflow', action='imp', id=trans.security.encode_id(workflow.id) )}" class="icon-button import tooltip" title="Import workflow"></a>
</%def>
<%def name="render_item( workflow, steps )">
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/f8c305ba23cb
changeset: 3526:f8c305ba23cb
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Mar 12 12:43:31 2010 -0500
description:
When preparing Display Applications make manual click refresh link a non-javascript action.
diffstat:
templates/dataset/display_application/display.mako | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (11 lines):
diff -r 90fa86a7b4e3 -r f8c305ba23cb templates/dataset/display_application/display.mako
--- a/templates/dataset/display_application/display.mako Fri Mar 12 12:17:36 2010 -0500
+++ b/templates/dataset/display_application/display.mako Fri Mar 12 12:43:31 2010 -0500
@@ -7,6 +7,6 @@
%if refresh:
<%def name="metas()"><meta http-equiv="refresh" content="10" /></%def>
<p>
-This page will <a href="javascript:location.reload(true);">refresh</a> after 10 seconds.
+This page will <a href="${trans.request.url}">refresh</a> after 10 seconds.
</p>
%endif
1
0