mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'release_20.09' into dev
This commit is contained in:
@@ -21,7 +21,6 @@
|
||||
</button>
|
||||
<div v-if="metadata.can_add_library_item">
|
||||
<div
|
||||
v-if="multiple_add_dataset_options"
|
||||
title="Add datasets to current folder"
|
||||
class="dropdown add-library-items add-library-items-datasets mr-1"
|
||||
>
|
||||
@@ -201,7 +200,6 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
is_admin: false,
|
||||
multiple_add_dataset_options: false,
|
||||
user_library_import_dir: false,
|
||||
library_import_dir: false,
|
||||
allow_library_path_paste: false,
|
||||
@@ -227,13 +225,6 @@ export default {
|
||||
this.user_library_import_dir = Galaxy.config.user_library_import_dir;
|
||||
this.library_import_dir = Galaxy.config.library_import_dir;
|
||||
this.allow_library_path_paste = Galaxy.config.allow_library_path_paste;
|
||||
if (
|
||||
this.user_library_import_dir !== null ||
|
||||
this.allow_library_path_paste !== false ||
|
||||
this.library_import_dir !== null
|
||||
) {
|
||||
this.multiple_add_dataset_options = true;
|
||||
}
|
||||
|
||||
this.fetchExtAndGenomes();
|
||||
},
|
||||
|
||||
@@ -259,7 +259,7 @@ export default {
|
||||
return $(this.$refs.uploadTable);
|
||||
},
|
||||
extensionDetails(extension) {
|
||||
return findExtension(this.effectiveExtensions, extension);
|
||||
return findExtension(this.app.effectiveExtensions, extension);
|
||||
},
|
||||
initExtensionInfo() {
|
||||
$(this.$refs.footerExtensionInfo)
|
||||
|
||||
@@ -1940,10 +1940,13 @@ class JobWrapper(HasResourceParameters):
|
||||
return self.output_paths
|
||||
|
||||
def get_output_path(self, dataset):
|
||||
if getattr(dataset, "fake_dataset_association", False):
|
||||
return dataset.file_name
|
||||
assert dataset.id is not None, "{} needs to be flushed to find output path".format(dataset)
|
||||
if self.output_paths is None:
|
||||
self.compute_outputs()
|
||||
for (hda, dataset_path) in self.output_hdas_and_paths.values():
|
||||
if hda == dataset:
|
||||
if hda.id == dataset.id:
|
||||
return dataset_path
|
||||
raise KeyError(f"Couldn't find job output for [{dataset}] in [{self.output_hdas_and_paths.values()}]")
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ from galaxy.managers import (
|
||||
deletable
|
||||
)
|
||||
from galaxy.security.validate_user_input import (
|
||||
VALID_EMAIL_RE,
|
||||
validate_email,
|
||||
validate_password,
|
||||
validate_publicname
|
||||
@@ -278,6 +279,22 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
raise exceptions.AuthenticationFailed(msg, **kwargs)
|
||||
return user
|
||||
|
||||
def get_user_by_identity(self, identity):
|
||||
"""Get user by username or email."""
|
||||
user = None
|
||||
if VALID_EMAIL_RE.match(identity):
|
||||
# VALID_PUBLICNAME and VALID_EMAIL do not overlap, so 'identity' here is an email address
|
||||
user = self.session().query(self.model_class).filter(
|
||||
self.model_class.table.c.email == identity).first()
|
||||
if not user:
|
||||
# Try a case-insensitive match on the email
|
||||
user = self.session().query(self.model_class).filter(
|
||||
func.lower(self.model_class.table.c.email) == identity.lower()).first()
|
||||
else:
|
||||
user = self.session().query(self.model_class).filter(
|
||||
self.model_class.table.c.username == identity).first()
|
||||
return user
|
||||
|
||||
# ---- current
|
||||
def current_user(self, trans):
|
||||
# define here for single point of change and make more readable
|
||||
|
||||
@@ -15,9 +15,9 @@ from .mulled_build import (
|
||||
add_build_arguments,
|
||||
add_single_image_arguments,
|
||||
args_to_mull_targets_kwds,
|
||||
build_target,
|
||||
mull_targets,
|
||||
)
|
||||
from .util import build_target
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
|
||||
@@ -83,7 +83,7 @@ def mulled_tags_for(namespace, image, tag_prefix=None, resolution_cache=None):
|
||||
# Following check is pretty expensive against biocontainers... don't even bother doing it
|
||||
# if can't cache the response.
|
||||
if not _namespace_has_repo_name(namespace, image, resolution_cache):
|
||||
log.debug("skipping mulled_tags_for [%s] no repository" % image)
|
||||
log.info("skipping mulled_tags_for [%s] no repository" % image)
|
||||
return []
|
||||
|
||||
cache_key = "galaxy.tool_util.deps.container_resolvers.mulled.util:tag_cache"
|
||||
@@ -158,7 +158,8 @@ def build_target(package_name, version=None, build=None, tag=None):
|
||||
assert build is None
|
||||
version, build = split_tag(tag)
|
||||
|
||||
return Target(package_name, version, build, package_name)
|
||||
# conda package and quay image names are lowercase
|
||||
return Target(package_name.lower(), version, build, package_name)
|
||||
|
||||
|
||||
def conda_build_target_str(target):
|
||||
|
||||
@@ -15,7 +15,10 @@ from base64 import b64decode
|
||||
from urllib.parse import unquote
|
||||
|
||||
from galaxy import exceptions
|
||||
from galaxy.managers import api_keys
|
||||
from galaxy.managers import (
|
||||
api_keys,
|
||||
users,
|
||||
)
|
||||
from galaxy.util import (
|
||||
smart_str,
|
||||
unicodify
|
||||
@@ -30,6 +33,7 @@ class AuthenticationController(BaseAPIController):
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self.user_manager = users.UserManager(app)
|
||||
self.api_keys_manager = api_keys.ApiKeyManager(app)
|
||||
|
||||
@expose_api_anonymous_and_sessionless
|
||||
@@ -58,18 +62,12 @@ class AuthenticationController(BaseAPIController):
|
||||
|
||||
:raises: ObjectNotFound, HTTPBadRequest
|
||||
"""
|
||||
email, password = self._decode_baseauth(trans.environ.get('HTTP_AUTHORIZATION'))
|
||||
|
||||
user = trans.sa_session.query(trans.app.model.User).filter(trans.app.model.User.table.c.email == email).all()
|
||||
|
||||
if len(user) == 0:
|
||||
identity, password = self._decode_baseauth(trans.environ.get('HTTP_AUTHORIZATION'))
|
||||
# check if this is an email address or username
|
||||
user = self.user_manager.get_user_by_identity(identity)
|
||||
if not user:
|
||||
raise exceptions.ObjectNotFound('The user does not exist.')
|
||||
elif len(user) > 1:
|
||||
# DB is inconsistent and we have more users with the same email.
|
||||
raise exceptions.InconsistentDatabase('An error occurred, please contact your administrator.')
|
||||
else:
|
||||
user = user[0]
|
||||
is_valid_user = self.app.auth_manager.check_password(user, password)
|
||||
is_valid_user = self.app.auth_manager.check_password(user, password)
|
||||
if is_valid_user:
|
||||
key = self.api_keys_manager.get_or_create_api_key(user)
|
||||
return dict(api_key=key)
|
||||
|
||||
@@ -7,10 +7,6 @@ from datetime import datetime, timedelta
|
||||
from urllib.parse import unquote
|
||||
|
||||
from markupsafe import escape
|
||||
from sqlalchemy import (
|
||||
func,
|
||||
or_
|
||||
)
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from galaxy import (
|
||||
@@ -134,15 +130,7 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesApiKeysMixin):
|
||||
status = None
|
||||
if not login or not password:
|
||||
return self.message_exception(trans, "Please specify a username and password.")
|
||||
user = trans.sa_session.query(trans.app.model.User).filter(or_(
|
||||
trans.app.model.User.table.c.email == login,
|
||||
trans.app.model.User.table.c.username == login
|
||||
)).first()
|
||||
if not user:
|
||||
# Try a case-insensitive match on the email
|
||||
user = trans.sa_session.query(trans.app.model.User).filter(
|
||||
func.lower(trans.app.model.User.table.c.email) == login.lower()
|
||||
).first()
|
||||
user = self.user_manager.get_user_by_identity(login)
|
||||
log.debug("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file)
|
||||
if user is None:
|
||||
message, user = self.__autoregistration(trans, login, password)
|
||||
|
||||
@@ -23,6 +23,8 @@ changed_password = '654321'
|
||||
user2_data = dict(email='user2@user2.user2', username='user2', password=default_password)
|
||||
user3_data = dict(email='user3@user3.user3', username='user3', password=default_password)
|
||||
user4_data = dict(email='user4@user4.user4', username='user4', password=default_password)
|
||||
uppercase_email_user = dict(email='USER5@USER5.USER5', username='USER5', password=default_password)
|
||||
lowercase_email_user = dict(email='user5@user5.user5', username='user5', password=default_password)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -192,6 +194,31 @@ class UserManagerTestCase(BaseTestCase):
|
||||
self.assertFalse(check_password("", user.password))
|
||||
self.assertFalse(check_password(None, user.password))
|
||||
|
||||
def test_get_user_by_identity(self):
|
||||
# return None if username/email not found
|
||||
assert self.user_manager.get_user_by_identity('xyz') is None
|
||||
uppercase_user = self.user_manager.create(**uppercase_email_user)
|
||||
assert uppercase_user.email == uppercase_email_user['email']
|
||||
assert uppercase_user.username == uppercase_email_user['username']
|
||||
assert self.user_manager.get_user_by_identity(uppercase_user.email) == uppercase_user
|
||||
assert self.user_manager.get_user_by_identity(uppercase_user.username) == uppercase_user
|
||||
# Create another user with the same email just differently capitalized.
|
||||
# This is not normally allowed now, since registration goes through user_manager.register(),
|
||||
# which checks for that, but was possible in earlier releases of Galaxy
|
||||
lowercase_user = self.user_manager.create(**lowercase_email_user)
|
||||
assert lowercase_user.email == lowercase_email_user['email']
|
||||
assert lowercase_user.username == lowercase_email_user['username']
|
||||
assert self.user_manager.get_user_by_identity(lowercase_user.email) == lowercase_user
|
||||
assert self.user_manager.get_user_by_identity(lowercase_user.username) == lowercase_user
|
||||
# assert uppercase user can still be retrieved
|
||||
assert self.user_manager.get_user_by_identity(uppercase_user.email) == uppercase_user
|
||||
assert self.user_manager.get_user_by_identity(uppercase_user.username) == uppercase_user
|
||||
# username matches need to be exact
|
||||
assert self.user_manager.get_user_by_identity(uppercase_user.username.capitalize()) is None
|
||||
# email matches can ignore capitalization
|
||||
ignore_email_capitalization_user = self.user_manager.create(email='user123@nopassword.com', username='someusername123')
|
||||
assert self.user_manager.get_user_by_identity(ignore_email_capitalization_user.email.capitalize()) == ignore_email_capitalization_user
|
||||
|
||||
|
||||
# =============================================================================
|
||||
class UserSerializerTestCase(BaseTestCase):
|
||||
|
||||
Reference in New Issue
Block a user