mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge pull request #11342 from mvdbeek/resolve_session_problems
Resolve session problems, enabled pages and tags fastAPI routes
This commit is contained in:
@@ -6,6 +6,8 @@ alabaster==0.7.12; python_version >= "3.5"
|
||||
amqp==5.0.3; python_version >= "3.6"
|
||||
appdirs==1.4.4; python_version >= "3.6"
|
||||
argcomplete==1.12.2; python_version >= "3.6" and python_version < "4"
|
||||
async-exit-stack==1.0.1; python_version >= "3.6" and python_version < "3.7"
|
||||
async-generator==1.10; python_version >= "3.6" and python_version < "3.7"
|
||||
atomicwrites==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "win32" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") or sys_platform == "win32" and python_version >= "3.6" and python_full_version >= "3.4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
|
||||
attmap==0.12.11
|
||||
attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
|
||||
@@ -5,6 +5,8 @@ aiofiles==0.6.0
|
||||
amqp==5.0.3; python_version >= "3.6"
|
||||
appdirs==1.4.4; python_version >= "3.6"
|
||||
argcomplete==1.12.2; python_version >= "3.6" and python_version < "4"
|
||||
async-exit-stack==1.0.1; python_version >= "3.6" and python_version < "3.7"
|
||||
async-generator==1.10; python_version >= "3.6" and python_version < "3.7"
|
||||
attmap==0.12.11
|
||||
attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
babel==2.9.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0")
|
||||
|
||||
@@ -87,6 +87,11 @@ class MalformedId(MessageException):
|
||||
err_code = error_codes_by_name['MALFORMED_ID']
|
||||
|
||||
|
||||
class UserInvalidRunAsException(MessageException):
|
||||
status_code = 400
|
||||
err_code = error_codes_by_name['USER_INVALID_RUN_AS']
|
||||
|
||||
|
||||
class MalformedContents(MessageException):
|
||||
status_code = 400
|
||||
err_code = error_codes_by_name['MALFORMED_CONTENTS']
|
||||
@@ -157,6 +162,11 @@ class InsufficientPermissionsException(MessageException):
|
||||
err_code = error_codes_by_name['INSUFFICIENT_PERMISSIONS']
|
||||
|
||||
|
||||
class UserCannotRunAsException(MessageException):
|
||||
status_code = 403
|
||||
err_code = error_codes_by_name['USER_CANNOT_RUN_AS']
|
||||
|
||||
|
||||
class AdminRequiredException(MessageException):
|
||||
status_code = 403
|
||||
err_code = error_codes_by_name['ADMIN_REQUIRED']
|
||||
|
||||
@@ -34,7 +34,7 @@ class JobPortsView:
|
||||
raise ItemAccessibilityException("Invalid job_key supplied.")
|
||||
|
||||
# Verify job is active. Don't update the contents of complete jobs.
|
||||
sa_session = self._app.model.context.current
|
||||
sa_session = self._app.model.session
|
||||
job = sa_session.query(model.Job).get(job_id)
|
||||
if not job.running:
|
||||
error_message = "Attempting to read or modify the files of a job that has already completed."
|
||||
|
||||
@@ -883,7 +883,7 @@ class PulsarJobRunner(AsynchronousJobRunner):
|
||||
remote_job_id = full_status["job_id"]
|
||||
if len(remote_job_id) == 32:
|
||||
# It is a UUID - assign_ids = uuid in destination params...
|
||||
sa_session = self.app.model.context.current
|
||||
sa_session = self.app.model.session
|
||||
galaxy_job_id = sa_session.query(model.Job).filter(model.Job.job_runner_external_id == remote_job_id).one().id
|
||||
else:
|
||||
galaxy_job_id = remote_job_id
|
||||
|
||||
@@ -42,7 +42,12 @@ from typing import List, Optional
|
||||
from sqlalchemy.orm.scoping import scoped_session
|
||||
|
||||
from galaxy.exceptions import UserActivationRequiredException
|
||||
from galaxy.model import Dataset, History, HistoryDatasetAssociation, Role
|
||||
from galaxy.model import (
|
||||
Dataset,
|
||||
History,
|
||||
HistoryDatasetAssociation,
|
||||
Role,
|
||||
)
|
||||
from galaxy.model.base import ModelMapping
|
||||
from galaxy.security.idencoding import IdEncodingHelper
|
||||
from galaxy.structured_app import StructuredApp
|
||||
@@ -126,7 +131,7 @@ class ProvidesAppContext:
|
||||
|
||||
:rtype: sqlalchemy.orm.scoping.scoped_session
|
||||
"""
|
||||
return self.app.model.context.current
|
||||
return self.app.model.session
|
||||
|
||||
def expunge_all(self):
|
||||
"""Expunge all the objects in Galaxy's SQLAlchemy sessions."""
|
||||
@@ -201,13 +206,7 @@ class ProvidesUserContext(ProvidesAppContext):
|
||||
|
||||
@property
|
||||
def user_can_do_run_as(self) -> bool:
|
||||
run_as_users = [user for user in self.app.config.get("api_allow_run_as", "").split(",") if user]
|
||||
if not run_as_users:
|
||||
return False
|
||||
user_in_run_as_users = self.user and self.user.email in run_as_users
|
||||
# Can do if explicitly in list or master_api_key supplied.
|
||||
can_do_run_as = user_in_run_as_users or self.user.bootstrap_admin_user
|
||||
return can_do_run_as
|
||||
return self.app.user_manager.user_can_do_run_as(self.user)
|
||||
|
||||
@property
|
||||
def user_is_active(self) -> bool:
|
||||
|
||||
@@ -84,7 +84,7 @@ class JobManager:
|
||||
def stop(self, job, message=None):
|
||||
if not job.finished:
|
||||
job.mark_deleted(self.app.config.track_jobs_in_database)
|
||||
self.app.model.context.current.flush()
|
||||
self.app.model.session.flush()
|
||||
self.app.job_manager.stop(job, message=message)
|
||||
return True
|
||||
else:
|
||||
|
||||
@@ -11,6 +11,7 @@ from pydantic import (
|
||||
|
||||
from galaxy.managers.context import ProvidesUserContext
|
||||
from galaxy.model import ItemTagAssociation
|
||||
from galaxy.model.tags import GalaxyTagHandlerSession
|
||||
from galaxy.schema.fields import EncodedDatabaseIdField
|
||||
|
||||
taggable_item_names = {item: item for item in ItemTagAssociation.associated_item_names}
|
||||
@@ -45,7 +46,7 @@ class TagsManager:
|
||||
|
||||
def update(self, trans: ProvidesUserContext, payload: ItemTagsPayload) -> None:
|
||||
"""Apply a new set of tags to an item; previous tags are deleted."""
|
||||
tag_handler = trans.app.tag_handler
|
||||
tag_handler = GalaxyTagHandlerSession(trans.sa_session)
|
||||
new_tags: Optional[str] = None
|
||||
if payload.item_tags and len(payload.item_tags) > 0:
|
||||
new_tags = ",".join(payload.item_tags)
|
||||
@@ -59,7 +60,7 @@ class TagsManager:
|
||||
"""
|
||||
Get an item based on type and id.
|
||||
"""
|
||||
tag_handler = trans.app.tag_handler
|
||||
tag_handler = GalaxyTagHandlerSession(trans.sa_session)
|
||||
id = trans.security.decode_id(payload.item_id)
|
||||
item_class = tag_handler.item_tag_assoc_info[payload.item_class].item_class
|
||||
item = trans.sa_session.query(item_class).filter(item_class.id == id).first()
|
||||
|
||||
@@ -225,6 +225,9 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
if self.by_email(email) is not None:
|
||||
raise exceptions.Conflict('Email must be unique', email=email)
|
||||
|
||||
def by_id(self, user_id):
|
||||
return self.app.model.session.query(self.model_class).get(user_id)
|
||||
|
||||
# ---- filters
|
||||
def by_email(self, email, filters=None, **kwargs):
|
||||
"""
|
||||
@@ -352,6 +355,15 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
# TODO: seems like this should return the model
|
||||
return api_keys.ApiKeyManager(self.app).create_api_key(user)
|
||||
|
||||
def user_can_do_run_as(self, user) -> bool:
|
||||
run_as_users = [u for u in self.app.config.get("api_allow_run_as", "").split(",") if u]
|
||||
if not run_as_users:
|
||||
return False
|
||||
user_in_run_as_users = user and user.email in run_as_users
|
||||
# Can do if explicitly in list or master_api_key supplied.
|
||||
can_do_run_as = user_in_run_as_users or user.bootstrap_admin_user
|
||||
return can_do_run_as
|
||||
|
||||
# TODO: possibly move to ApiKeyManager
|
||||
def valid_api_key(self, user):
|
||||
"""
|
||||
|
||||
@@ -21,14 +21,15 @@ class ModelMapping(Bunch):
|
||||
|
||||
def __init__(self, model_modules, engine):
|
||||
self.engine = engine
|
||||
Session = sessionmaker(autoflush=False, autocommit=True)
|
||||
versioned_session(Session)
|
||||
context = scoped_session(Session)
|
||||
SessionLocal = sessionmaker(autoflush=False, autocommit=True)
|
||||
versioned_session(SessionLocal)
|
||||
context = scoped_session(SessionLocal)
|
||||
# For backward compatibility with "context.current"
|
||||
# deprecated?
|
||||
context.current = context
|
||||
self.context = context
|
||||
self.session = context
|
||||
self._SessionLocal = SessionLocal
|
||||
self._session = context
|
||||
self.local_session = None
|
||||
|
||||
model_classes = {}
|
||||
for module in model_modules:
|
||||
@@ -41,6 +42,27 @@ class ModelMapping(Bunch):
|
||||
context.remove()
|
||||
context.configure(bind=engine)
|
||||
|
||||
def set_local_session(self):
|
||||
self.session = self._SessionLocal()
|
||||
|
||||
def dispose_local_session(self):
|
||||
self.session = None
|
||||
|
||||
@property
|
||||
def session(self):
|
||||
return self.local_session or self._session
|
||||
|
||||
@session.setter
|
||||
def session(self, session):
|
||||
# For backward compatibility with "context.current"
|
||||
if session:
|
||||
session.current = session
|
||||
self.local_session = session
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
return self.session
|
||||
|
||||
@property
|
||||
def Session(self):
|
||||
"""
|
||||
|
||||
@@ -78,7 +78,7 @@ class ModelImportStore(metaclass=abc.ABCMeta):
|
||||
self.object_store = object_store
|
||||
self.app = app
|
||||
if app is not None:
|
||||
self.sa_session = app.model.context.current
|
||||
self.sa_session = app.model.session
|
||||
self.sessionless = False
|
||||
else:
|
||||
self.sa_session = SessionlessContext()
|
||||
@@ -1137,7 +1137,7 @@ class DirectoryModelExportStore(ModelExportStore):
|
||||
with open(history_attrs_filename, 'w') as history_attrs_out:
|
||||
dump(history_attrs, history_attrs_out)
|
||||
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
|
||||
# Write collections' attributes (including datasets list) to file.
|
||||
query = (sa_session.query(model.HistoryDatasetCollectionAssociation)
|
||||
|
||||
@@ -110,8 +110,8 @@ class InstalledRepositoryManager:
|
||||
data_manager_relative_install_dir,
|
||||
repository,
|
||||
repository_tools_tups)
|
||||
self.install_model.context.current.add(repository)
|
||||
self.install_model.context.current.flush()
|
||||
self.install_model.session.add(repository)
|
||||
self.install_model.session.flush()
|
||||
if repository.includes_datatypes:
|
||||
if tool_path:
|
||||
repository_install_dir = os.path.abspath(os.path.join(tool_path, relative_install_dir))
|
||||
@@ -663,13 +663,13 @@ class InstalledRepositoryManager:
|
||||
repository.error_message = None
|
||||
else:
|
||||
repository.status = self.app.install_model.ToolShedRepository.installation_status.DEACTIVATED
|
||||
self.app.install_model.context.current.add(repository)
|
||||
self.app.install_model.context.current.flush()
|
||||
self.app.install_model.session.add(repository)
|
||||
self.app.install_model.session.flush()
|
||||
return errors
|
||||
|
||||
def purge_repository(self, repository):
|
||||
"""Purge a repository with status New (a white ghost) from the database."""
|
||||
sa_session = self.app.model.context.current
|
||||
sa_session = self.app.model.session
|
||||
status = 'ok'
|
||||
message = ''
|
||||
purged_tool_versions = 0
|
||||
|
||||
@@ -66,7 +66,7 @@ class MigrateToolsApplication(galaxy.config.ConfiguresGalaxyMixin):
|
||||
|
||||
@property
|
||||
def sa_session(self):
|
||||
return self.model.context.current
|
||||
return self.model.session
|
||||
|
||||
def shutdown(self):
|
||||
self.object_store.shutdown()
|
||||
|
||||
@@ -100,7 +100,7 @@ class MetadataGenerator:
|
||||
self.updating_installed_repository = updating_installed_repository
|
||||
self.persist = persist
|
||||
self.invalid_file_tups = []
|
||||
self.sa_session = app.model.context.current
|
||||
self.sa_session = app.model.session
|
||||
self.NOT_TOOL_CONFIGS = [suc.DATATYPES_CONFIG_FILENAME,
|
||||
REPOSITORY_DEPENDENCY_DEFINITION_FILENAME,
|
||||
TOOL_DEPENDENCY_DEFINITION_FILENAME,
|
||||
|
||||
@@ -308,7 +308,7 @@ def get_repository_by_id(app, id):
|
||||
if is_tool_shed_client(app):
|
||||
return app.install_model.context.query(app.install_model.ToolShedRepository).get(app.security.decode_id(id))
|
||||
else:
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Repository).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
@@ -495,7 +495,7 @@ def get_repository_query(app):
|
||||
|
||||
def get_role_by_id(app, role_id):
|
||||
"""Get a Role from the database by id."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Role).get(app.security.decode_id(role_id))
|
||||
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ def get_tool_panel_config_tool_path_install_dir(app, repository):
|
||||
|
||||
def get_user(app, id):
|
||||
"""Get a user from the database by id."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.User).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
|
||||
@@ -670,36 +670,36 @@ class GalaxyInteractorApi:
|
||||
|
||||
return fetcher
|
||||
|
||||
def api_key_header(self, key, admin, anon):
|
||||
header = {}
|
||||
def api_key_header(self, key, admin, anon, headers):
|
||||
header = headers or {}
|
||||
if not anon:
|
||||
if not key:
|
||||
key = self.api_key if not admin else self.master_api_key
|
||||
header['x-api-key'] = key
|
||||
return header
|
||||
|
||||
def _post(self, path, data=None, files=None, key=None, admin=False, anon=False, json=False):
|
||||
def _post(self, path, data=None, files=None, key=None, headers=None, admin=False, anon=False, json=False):
|
||||
# If json=True, use post payload using request's json parameter instead of the data
|
||||
# parameter (i.e. assume the contents is a jsonified blob instead of form parameters
|
||||
# with individual parameters jsonified if needed).
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon)
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon, headers=headers)
|
||||
url = f"{self.api_url}/{path}"
|
||||
return galaxy_requests_post(url, data=data, files=files, as_json=json, headers=headers)
|
||||
|
||||
def _delete(self, path, data=None, key=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon)
|
||||
def _delete(self, path, data=None, key=None, headers=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon, headers=headers)
|
||||
return requests.delete(f"{self.api_url}/{path}", params=data, headers=headers)
|
||||
|
||||
def _patch(self, path, data=None, key=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon)
|
||||
def _patch(self, path, data=None, key=None, headers=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon, headers=headers)
|
||||
return requests.patch(f"{self.api_url}/{path}", data=data, headers=headers)
|
||||
|
||||
def _put(self, path, data=None, key=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon)
|
||||
def _put(self, path, data=None, key=None, headers=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon, headers=headers)
|
||||
return requests.put(f"{self.api_url}/{path}", data=data, headers=headers)
|
||||
|
||||
def _get(self, path, data=None, key=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon)
|
||||
def _get(self, path, data=None, key=None, headers=None, admin=False, anon=False):
|
||||
headers = self.api_key_header(key=key, admin=admin, anon=anon, headers=headers)
|
||||
if path.startswith("/api"):
|
||||
path = path[len("/api"):]
|
||||
url = f"{self.api_url}/{path}"
|
||||
|
||||
@@ -293,7 +293,7 @@ class ToolShedRepositoryCache:
|
||||
|
||||
def rebuild(self):
|
||||
try:
|
||||
session = self.app.install_model.context.current.session_factory()
|
||||
session = self.app.install_model._SessionLocal()
|
||||
self.repositories = session.query(self.app.install_model.ToolShedRepository).options(
|
||||
defer(self.app.install_model.ToolShedRepository.metadata),
|
||||
joinedload('tool_dependencies').subqueryload('tool_shed_repository').options(
|
||||
|
||||
@@ -271,7 +271,7 @@ def get_tool_shed_repository_url(app, tool_shed, owner, name):
|
||||
|
||||
def get_user_by_username(app, username):
|
||||
"""Get a user from the database by username."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
try:
|
||||
user = sa_session.query(app.model.User) \
|
||||
.filter(app.model.User.table.c.username == username) \
|
||||
|
||||
@@ -221,6 +221,9 @@ def __extract_payload_from_request(trans, func, kwargs):
|
||||
# should ideally be in reverse, with the if clause being a check for application/json and the else clause assuming a standard encoding
|
||||
# such as multipart/form-data. Leaving it as is for backward compatibility, just in case.
|
||||
payload = loads(unicodify(trans.request.body))
|
||||
run_as = trans.request.headers.get('run-as')
|
||||
if run_as:
|
||||
payload['run_as'] = run_as
|
||||
return payload
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ This module *does not* contain API routes. It exclusively contains dependencies
|
||||
"""
|
||||
from typing import (
|
||||
cast,
|
||||
Generator,
|
||||
Optional,
|
||||
)
|
||||
|
||||
@@ -19,17 +20,32 @@ from galaxy import (
|
||||
model,
|
||||
)
|
||||
from galaxy.app import UniverseApplication
|
||||
from galaxy.exceptions import AdminRequiredException
|
||||
from galaxy.exceptions import (
|
||||
AdminRequiredException,
|
||||
UserCannotRunAsException,
|
||||
UserInvalidRunAsException,
|
||||
)
|
||||
from galaxy.managers.jobs import JobManager
|
||||
from galaxy.managers.session import GalaxySessionManager
|
||||
from galaxy.managers.users import UserManager
|
||||
from galaxy.model import User
|
||||
from galaxy.schema.fields import EncodedDatabaseIdField
|
||||
from galaxy.security.idencoding import IdEncodingHelper
|
||||
from galaxy.web.framework.decorators import require_admin_message
|
||||
from galaxy.work.context import SessionRequestContext
|
||||
|
||||
|
||||
def get_app() -> UniverseApplication:
|
||||
return cast(UniverseApplication, galaxy_app.app)
|
||||
def get_app() -> Generator[UniverseApplication, None, None]:
|
||||
app = cast(UniverseApplication, galaxy_app.app)
|
||||
try:
|
||||
app.model.set_local_session()
|
||||
yield app
|
||||
finally:
|
||||
app.model.dispose_local_session()
|
||||
|
||||
|
||||
def get_id_encoding_helper(app: UniverseApplication = Depends(get_app)) -> IdEncodingHelper:
|
||||
return app.security
|
||||
|
||||
|
||||
def get_job_manager(app: UniverseApplication = Depends(get_app)) -> JobManager:
|
||||
@@ -51,21 +67,36 @@ def get_session_manager(app: UniverseApplication = Depends(get_app)) -> GalaxySe
|
||||
|
||||
|
||||
def get_session(session_manager: GalaxySessionManager = Depends(get_session_manager),
|
||||
app: UniverseApplication = Depends(get_app),
|
||||
security: IdEncodingHelper = Depends(get_id_encoding_helper),
|
||||
galaxysession: Optional[str] = Cookie(None)) -> Optional[model.GalaxySession]:
|
||||
if galaxysession:
|
||||
session_key = app.security.decode_guid(galaxysession)
|
||||
session_key = security.decode_guid(galaxysession)
|
||||
if session_key:
|
||||
return session_manager.get_session_from_session_key(session_key)
|
||||
# TODO: What should we do if there is no session? Since this is the API, maybe nothing is the right choice?
|
||||
return None
|
||||
|
||||
|
||||
def get_api_user(user_manager: UserManager = Depends(get_user_manager), key: Optional[str] = Query(None), x_api_key: Optional[str] = Header(None)) -> Optional[User]:
|
||||
def get_api_user(
|
||||
security: IdEncodingHelper = Depends(get_id_encoding_helper),
|
||||
user_manager: UserManager = Depends(get_user_manager),
|
||||
key: Optional[str] = Query(None),
|
||||
x_api_key: Optional[str] = Header(None),
|
||||
run_as: Optional[EncodedDatabaseIdField] = Header(None, title='Run as User', description='Admins and ')) -> Optional[User]:
|
||||
api_key = key or x_api_key
|
||||
if not api_key:
|
||||
return None
|
||||
return user_manager.by_api_key(api_key=api_key)
|
||||
user = user_manager.by_api_key(api_key=api_key)
|
||||
if run_as:
|
||||
if user_manager.user_can_do_run_as(user):
|
||||
try:
|
||||
decoded_run_as_id = security.decode_id(run_as)
|
||||
except Exception:
|
||||
raise UserInvalidRunAsException
|
||||
return user_manager.by_id(decoded_run_as_id)
|
||||
else:
|
||||
raise UserCannotRunAsException
|
||||
return user
|
||||
|
||||
|
||||
def get_user(galaxy_session: Optional[model.GalaxySession] = Depends(get_session), api_user: Optional[User] = Depends(get_api_user)) -> Optional[User]:
|
||||
|
||||
@@ -33,8 +33,7 @@ from . import get_app, get_trans
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# TODO: This FastAPI router is disabled. Please rename it to `router` when the database session issues are fixed.
|
||||
_router = APIRouter(tags=['pages'])
|
||||
router = APIRouter(tags=['pages'])
|
||||
|
||||
DeletedQueryParam: bool = Query(
|
||||
default=False,
|
||||
@@ -53,11 +52,11 @@ def get_pages_manager(app=Depends(get_app)) -> PagesManager:
|
||||
return PagesManager(app)
|
||||
|
||||
|
||||
@cbv(_router)
|
||||
@cbv(router)
|
||||
class FastAPIPages:
|
||||
manager: PagesManager = Depends(get_pages_manager)
|
||||
|
||||
@_router.get(
|
||||
@router.get(
|
||||
'/api/pages',
|
||||
summary="Lists all Pages viewable by the user.",
|
||||
response_description="A list with summary page information.",
|
||||
@@ -70,7 +69,7 @@ class FastAPIPages:
|
||||
"""Get a list with summary information of all Pages available to the user."""
|
||||
return self.manager.index(trans, deleted)
|
||||
|
||||
@_router.post(
|
||||
@router.post(
|
||||
'/api/pages',
|
||||
summary="Create a page and return summary information.",
|
||||
response_description="The page summary information.",
|
||||
@@ -83,7 +82,7 @@ class FastAPIPages:
|
||||
"""Get a list with details of all Pages available to the user."""
|
||||
return self.manager.create(trans, payload)
|
||||
|
||||
@_router.delete(
|
||||
@router.delete(
|
||||
'/api/pages/{id}',
|
||||
summary="Marks the specific Page as deleted.",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
@@ -96,7 +95,7 @@ class FastAPIPages:
|
||||
"""Marks the Page with the given ID as deleted."""
|
||||
self.manager.delete(trans, id)
|
||||
|
||||
@_router.get(
|
||||
@router.get(
|
||||
'/api/pages/{id}',
|
||||
summary="Return a page summary and the content of the last revision.",
|
||||
response_description="The page summary information.",
|
||||
@@ -109,7 +108,7 @@ class FastAPIPages:
|
||||
"""Return summary information about a specific Page and the content of the last revision."""
|
||||
return self.manager.show(trans, id)
|
||||
|
||||
@_router.get(
|
||||
@router.get(
|
||||
'/api/pages/{id}.pdf',
|
||||
summary="Return a PDF document of the last revision of the Page.",
|
||||
response_class=StreamingResponse,
|
||||
@@ -191,6 +190,7 @@ class PagesController(BaseAPIController):
|
||||
:returns: Dictionary with 'success' or 'error' element to indicate the result of the request
|
||||
"""
|
||||
self.manager.delete(trans, id)
|
||||
trans.response.status = 204
|
||||
|
||||
@expose_api_anonymous_and_sessionless
|
||||
def show(self, trans, id, **kwd):
|
||||
|
||||
@@ -25,19 +25,18 @@ from . import (
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# TODO: This FastAPI router is disabled. Please rename it to `router` when the database session issues are fixed.
|
||||
_router = APIRouter(tags=['tags'])
|
||||
router = APIRouter(tags=['tags'])
|
||||
|
||||
|
||||
def get_tags_manager() -> TagsManager:
|
||||
return TagsManager() # TODO: remove/refactor after merging #11180
|
||||
|
||||
|
||||
@cbv(_router)
|
||||
@cbv(router)
|
||||
class FastAPITags:
|
||||
manager: TagsManager = Depends(get_tags_manager)
|
||||
|
||||
@_router.put(
|
||||
@router.put(
|
||||
'/api/tags',
|
||||
summary="Apply a new set of tags to an item.",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
|
||||
@@ -546,7 +546,7 @@ class AdminToolshed(AdminGalaxy):
|
||||
clause_list = []
|
||||
for tsr_id in tsr_ids:
|
||||
clause_list.append(trans.install_model.ToolShedRepository.table.c.id == tsr_id)
|
||||
query = trans.install_model.context.current.query(trans.install_model.ToolShedRepository).filter(or_(*clause_list))
|
||||
query = trans.install_model.session.query(trans.install_model.ToolShedRepository).filter(or_(*clause_list))
|
||||
return trans.fill_template('admin/tool_shed_repository/monitor_repository_installation.mako',
|
||||
tool_shed_repositories=tool_shed_repositories,
|
||||
query=query,
|
||||
@@ -978,7 +978,7 @@ class AdminToolshed(AdminGalaxy):
|
||||
clause_list = []
|
||||
for tsr_id in tsr_ids:
|
||||
clause_list.append(trans.install_model.ToolShedRepository.table.c.id == tsr_id)
|
||||
query = trans.install_model.context.current.query(trans.install_model.ToolShedRepository) \
|
||||
query = trans.install_model.session.query(trans.install_model.ToolShedRepository) \
|
||||
.filter(or_(*clause_list))
|
||||
return trans.fill_template('admin/tool_shed_repository/monitor_repository_installation.mako',
|
||||
encoded_kwd=encoded_kwd,
|
||||
|
||||
@@ -16,8 +16,7 @@ class BasePageApiTestCase(ApiTestCase):
|
||||
def _create_valid_page_as(self, other_email, slug):
|
||||
run_as_user = self._setup_user(other_email)
|
||||
page_request = self._test_page_payload(slug=slug)
|
||||
page_request["run_as"] = run_as_user["id"]
|
||||
page_response = self._post("pages", page_request, admin=True, json=True)
|
||||
page_response = self._post("pages", page_request, headers={'run-as': run_as_user["id"]}, admin=True, json=True)
|
||||
self._assert_status_code_is(page_response, 200)
|
||||
return page_response.json()
|
||||
|
||||
@@ -138,7 +137,7 @@ steps:
|
||||
def test_delete(self):
|
||||
response_json = self._create_valid_page_with_slug("testdelete")
|
||||
delete_response = delete(self._api_url("pages/%s" % response_json['id'], use_key=True))
|
||||
self._assert_status_code_is(delete_response, 200)
|
||||
self._assert_status_code_is(delete_response, 204)
|
||||
|
||||
def test_400_on_delete_invalid_page_id(self):
|
||||
delete_response = delete(self._api_url("pages/%s" % self._random_key(), use_key=True))
|
||||
|
||||
@@ -212,19 +212,19 @@ def _raise_skip_if(check, *args):
|
||||
class BasePopulator(metaclass=ABCMeta):
|
||||
|
||||
@abstractmethod
|
||||
def _post(self, route, data=None, files=None, admin=False, json: bool = False) -> Response:
|
||||
def _post(self, route, data=None, files=None, headers=None, admin=False, json: bool = False) -> Response:
|
||||
"""POST data to target Galaxy instance on specified route."""
|
||||
|
||||
@abstractmethod
|
||||
def _put(self, route, data=None, admin=False) -> Response:
|
||||
def _put(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
"""PUT data to target Galaxy instance on specified route."""
|
||||
|
||||
@abstractmethod
|
||||
def _get(self, route, data=None, admin=False) -> Response:
|
||||
def _get(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
"""GET data from target Galaxy instance on specified route."""
|
||||
|
||||
@abstractmethod
|
||||
def _delete(self, route, data=None, admin=False) -> Response:
|
||||
def _delete(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
"""DELETE against target Galaxy instance on specified route."""
|
||||
|
||||
|
||||
@@ -784,23 +784,23 @@ class GalaxyInteractorHttpMixin:
|
||||
def _api_key(self):
|
||||
return self.galaxy_interactor.api_key
|
||||
|
||||
def _post(self, route, data=None, files=None, admin=False, json: bool = False) -> Response:
|
||||
return self.galaxy_interactor.post(route, data, files=files, admin=admin, json=json)
|
||||
def _post(self, route, data=None, files=None, headers=None, admin=False, json: bool = False) -> Response:
|
||||
return self.galaxy_interactor.post(route, data, files=files, admin=admin, headers=headers, json=json)
|
||||
|
||||
def _put(self, route, data=None, admin=False):
|
||||
return self.galaxy_interactor.put(route, data, admin=admin)
|
||||
def _put(self, route, data=None, headers=None, admin=False):
|
||||
return self.galaxy_interactor.put(route, data, headers=headers, admin=admin)
|
||||
|
||||
def _get(self, route, data=None, admin=False):
|
||||
def _get(self, route, data=None, headers=None, admin=False):
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
return self.galaxy_interactor.get(route, data=data, admin=admin)
|
||||
return self.galaxy_interactor.get(route, data=data, headers=headers, admin=admin)
|
||||
|
||||
def _delete(self, route, data=None, admin=False):
|
||||
def _delete(self, route, data=None, headers=None, admin=False):
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
return self.galaxy_interactor.delete(route, data=data, admin=admin)
|
||||
return self.galaxy_interactor.delete(route, data=data, headers=headers, admin=admin)
|
||||
|
||||
|
||||
class DatasetPopulator(GalaxyInteractorHttpMixin, BaseDatasetPopulator):
|
||||
@@ -1732,26 +1732,26 @@ class GiHttpMixin:
|
||||
data = {}
|
||||
return self._gi.make_get_request(self._url(route), data=data)
|
||||
|
||||
def _post(self, route, data=None, files=None, admin=False, json: bool = False) -> Response:
|
||||
def _post(self, route, data=None, files=None, headers=None, admin=False, json: bool = False) -> Response:
|
||||
if data is None:
|
||||
data = {}
|
||||
data = data.copy()
|
||||
data['key'] = self._gi.key
|
||||
return requests.post(self._url(route), data=data)
|
||||
return requests.post(self._url(route), data=data, headers=headers)
|
||||
|
||||
def _put(self, route, data=None, admin=False):
|
||||
def _put(self, route, data=None, headers=None, admin=False):
|
||||
if data is None:
|
||||
data = {}
|
||||
data = data.copy()
|
||||
data['key'] = self._gi.key
|
||||
return requests.put(self._url(route), data=data)
|
||||
return requests.put(self._url(route), data=data, headers=headers)
|
||||
|
||||
def _delete(self, route, data=None):
|
||||
def _delete(self, route, data=None, headers=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
data = data.copy()
|
||||
data['key'] = self._gi.key
|
||||
return requests.delete(self._url(route), data=data)
|
||||
return requests.delete(self._url(route), data=data, headers=headers)
|
||||
|
||||
def _url(self, route):
|
||||
if route.startswith("/api/"):
|
||||
|
||||
@@ -541,7 +541,7 @@ class SeleniumSessionGetPostMixin:
|
||||
def _mixin_admin_api_key(self) -> str:
|
||||
return getattr(self, "admin_api_key", get_admin_api_key())
|
||||
|
||||
def _get(self, route, data=None, admin=False) -> Response:
|
||||
def _get(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
data = data or {}
|
||||
full_url = self.selenium_context.build_url("api/" + route, for_selenium=False)
|
||||
cookies = None
|
||||
@@ -549,10 +549,10 @@ class SeleniumSessionGetPostMixin:
|
||||
full_url = f"{full_url}?key={self._mixin_admin_api_key}"
|
||||
else:
|
||||
cookies = self.selenium_context.selenium_to_requests_cookies()
|
||||
response = requests.get(full_url, params=data, cookies=cookies)
|
||||
response = requests.get(full_url, params=data, cookies=cookies, headers=headers)
|
||||
return response
|
||||
|
||||
def _post(self, route, data=None, files=None, admin=False, json: bool = False) -> Response:
|
||||
def _post(self, route, data=None, files=None, headers=None, admin=False, json: bool = False) -> Response:
|
||||
full_url = self.selenium_context.build_url("api/" + route, for_selenium=False)
|
||||
if data is None:
|
||||
data = {}
|
||||
@@ -567,10 +567,10 @@ class SeleniumSessionGetPostMixin:
|
||||
full_url = f"{full_url}?key={self._mixin_admin_api_key}"
|
||||
else:
|
||||
cookies = self.selenium_context.selenium_to_requests_cookies()
|
||||
response = requests.post(full_url, data=data, cookies=cookies, files=files)
|
||||
response = requests.post(full_url, data=data, cookies=cookies, files=files, headers=headers)
|
||||
return response
|
||||
|
||||
def _delete(self, route, data=None, admin=False) -> Response:
|
||||
def _delete(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
data = data or {}
|
||||
full_url = self.selenium_context.build_url("api/" + route, for_selenium=False)
|
||||
cookies = None
|
||||
@@ -578,10 +578,10 @@ class SeleniumSessionGetPostMixin:
|
||||
full_url = f"{full_url}?key={self._mixin_admin_api_key}"
|
||||
else:
|
||||
cookies = self.selenium_context.selenium_to_requests_cookies()
|
||||
response = requests.delete(full_url, data=data, cookies=cookies)
|
||||
response = requests.delete(full_url, data=data, cookies=cookies, headers=headers)
|
||||
return response
|
||||
|
||||
def _put(self, route, data=None, admin=False) -> Response:
|
||||
def _put(self, route, data=None, headers=None, admin=False) -> Response:
|
||||
data = data or {}
|
||||
full_url = self.selenium_context.build_url("api/" + route, for_selenium=False)
|
||||
cookies = None
|
||||
@@ -589,7 +589,7 @@ class SeleniumSessionGetPostMixin:
|
||||
full_url = f"{full_url}?key={self._mixin_admin_api_key}"
|
||||
else:
|
||||
cookies = self.selenium_context.selenium_to_requests_cookies()
|
||||
response = requests.put(full_url, data=data, cookies=cookies)
|
||||
response = requests.put(full_url, data=data, cookies=cookies, headers=headers)
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ class Registry:
|
||||
|
||||
@property
|
||||
def sa_session(self):
|
||||
return self.app.model.context.current
|
||||
return self.app.model.session
|
||||
|
||||
def unload_certified_level_one_repository_and_suite_tuple(self, repository):
|
||||
# The received repository has been determined to be level one certified.
|
||||
|
||||
@@ -67,7 +67,7 @@ def check_file_contents_for_email_alerts(app):
|
||||
See if any admin users have chosen to receive email alerts when a repository is updated.
|
||||
If so, the file contents of the update must be checked for inappropriate content.
|
||||
"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
admin_users = app.config.get("admin_users", "").split(",")
|
||||
for repository in sa_session.query(app.model.Repository) \
|
||||
.filter(app.model.Repository.table.c.email_alerts != null()):
|
||||
|
||||
@@ -19,7 +19,7 @@ def get_all_dependencies(app, metadata_entry, processed_dependency_links=None):
|
||||
encoder = app.security.encode_id
|
||||
value_mapper = {'repository_id': encoder, 'id': encoder, 'user_id': encoder}
|
||||
metadata = metadata_entry.to_dict(value_mapper=value_mapper, view='element')
|
||||
db = app.model.context.current
|
||||
db = app.model.session
|
||||
returned_dependencies = []
|
||||
required_metadata = get_dependencies_for_metadata_revision(app, metadata)
|
||||
if required_metadata is None:
|
||||
@@ -102,7 +102,7 @@ def get_latest_downloadable_changeset_revision(app, repository):
|
||||
|
||||
def get_latest_repository_metadata(app, decoded_repository_id, downloadable=False):
|
||||
"""Get last metadata defined for a specified repository from the database."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
repository = sa_session.query(app.model.Repository).get(decoded_repository_id)
|
||||
if downloadable:
|
||||
changeset_revision = get_latest_downloadable_changeset_revision(app, repository)
|
||||
@@ -117,7 +117,7 @@ def get_metadata_revisions(app, repository, sort_revisions=True, reverse=False,
|
||||
"""
|
||||
Return a list of changesets for the provided repository.
|
||||
"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
if downloadable:
|
||||
metadata_revisions = repository.downloadable_revisions
|
||||
else:
|
||||
@@ -225,7 +225,7 @@ def get_repository_metadata_by_changeset_revision(app, id, changeset_revision):
|
||||
# Make sure there are no duplicate records, and return the single unique record for the changeset_revision.
|
||||
# Duplicate records were somehow created in the past. The cause of this issue has been resolved, but we'll
|
||||
# leave this method as is for a while longer to ensure all duplicate records are removed.
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
all_metadata_records = sa_session.query(app.model.RepositoryMetadata) \
|
||||
.filter(and_(app.model.RepositoryMetadata.table.c.repository_id == app.security.decode_id(id),
|
||||
app.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision)) \
|
||||
@@ -243,7 +243,7 @@ def get_repository_metadata_by_changeset_revision(app, id, changeset_revision):
|
||||
|
||||
def get_repository_metadata_by_id(app, id):
|
||||
"""Get repository metadata from the database"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryMetadata).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ def create_repository_admin_role(app, repository):
|
||||
Create a new role with name-spaced name based on the repository name and its owner's public user
|
||||
name. This will ensure that the tole name is unique.
|
||||
"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
name = get_repository_admin_role_name(str(repository.name), str(repository.user.username))
|
||||
description = 'A user or group member with this role can administer this repository.'
|
||||
role = app.model.Role(name=name, description=description, type=app.model.Role.types.SYSTEM)
|
||||
@@ -148,7 +148,7 @@ def create_repository_admin_role(app, repository):
|
||||
def create_repository(app, name, type, description, long_description, user_id, category_ids=None, remote_repository_url=None, homepage_url=None):
|
||||
"""Create a new ToolShed repository"""
|
||||
category_ids = category_ids or []
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
# Add the repository record to the database.
|
||||
repository = app.model.Repository(name=name,
|
||||
type=type,
|
||||
@@ -263,7 +263,7 @@ def get_repo_info_dict(app, user, repository_id, changeset_revision):
|
||||
|
||||
|
||||
def get_repositories_by_category(app, category_id, installable=False, sort_order='asc', sort_key='name', page=None, per_page=25):
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
query = sa_session.query(app.model.Repository) \
|
||||
.join(app.model.RepositoryCategoryAssociation, app.model.Repository.id == app.model.RepositoryCategoryAssociation.repository_id) \
|
||||
.join(app.model.User, app.model.User.id == app.model.Repository.user_id) \
|
||||
@@ -349,7 +349,7 @@ def get_tool_shed_repository_status_label(app, tool_shed_repository=None, name=N
|
||||
|
||||
|
||||
def handle_role_associations(app, role, repository, **kwd):
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
message = escape(kwd.get('message', ''))
|
||||
status = kwd.get('status', 'done')
|
||||
repository_owner = repository.user
|
||||
@@ -415,7 +415,7 @@ def update_repository(app, trans, id, **kwds):
|
||||
"""Update an existing ToolShed repository"""
|
||||
message = None
|
||||
flush_needed = False
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
repository = sa_session.query(app.model.Repository).get(app.security.decode_id(id))
|
||||
if repository is None:
|
||||
return None, "Unknown repository ID"
|
||||
|
||||
@@ -32,19 +32,19 @@ def changeset_revision_reviewed_by_user(user, repository, changeset_revision):
|
||||
|
||||
def get_component(app, id):
|
||||
"""Get a component from the database."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Component).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
def get_component_review(app, id):
|
||||
"""Get a component_review from the database"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.ComponentReview).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
def get_component_by_name(app, name):
|
||||
"""Get a component from the database via a name."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Component) \
|
||||
.filter(app.model.Component.table.c.name == name) \
|
||||
.first()
|
||||
@@ -52,7 +52,7 @@ def get_component_by_name(app, name):
|
||||
|
||||
def get_component_review_by_repository_review_id_component_id(app, repository_review_id, component_id):
|
||||
"""Get a component_review from the database via repository_review_id and component_id."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.ComponentReview) \
|
||||
.filter(and_(app.model.ComponentReview.table.c.repository_review_id == app.security.decode_id(repository_review_id),
|
||||
app.model.ComponentReview.table.c.component_id == app.security.decode_id(component_id))) \
|
||||
@@ -60,7 +60,7 @@ def get_component_review_by_repository_review_id_component_id(app, repository_re
|
||||
|
||||
|
||||
def get_components(app):
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Component) \
|
||||
.order_by(app.model.Component.name) \
|
||||
.all()
|
||||
@@ -90,7 +90,7 @@ def get_previous_repository_reviews(app, repository, changeset_revision):
|
||||
|
||||
def get_review(app, id):
|
||||
"""Get a repository_review from the database via id."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryReview).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ def get_review_by_repository_id_changeset_revision_user_id(app, repository_id, c
|
||||
Get a repository_review from the database via repository id, changeset_revision
|
||||
and user_id.
|
||||
"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryReview) \
|
||||
.filter(and_(app.model.RepositoryReview.repository_id == app.security.decode_id(repository_id),
|
||||
app.model.RepositoryReview.changeset_revision == changeset_revision,
|
||||
@@ -109,7 +109,7 @@ def get_review_by_repository_id_changeset_revision_user_id(app, repository_id, c
|
||||
|
||||
def get_reviews_by_repository_id_changeset_revision(app, repository_id, changeset_revision):
|
||||
"""Get all repository_reviews from the database via repository id and changeset_revision."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryReview) \
|
||||
.filter(and_(app.model.RepositoryReview.repository_id == app.security.decode_id(repository_id),
|
||||
app.model.RepositoryReview.changeset_revision == changeset_revision)) \
|
||||
|
||||
@@ -91,7 +91,7 @@ def search_names_versions(tool_dict, exact_matches_checked, match_tuples, reposi
|
||||
|
||||
def search_repository_metadata(app, exact_matches_checked, tool_ids='', tool_names='', tool_versions='',
|
||||
workflow_names='', all_workflows=False):
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
match_tuples = []
|
||||
ok = True
|
||||
if tool_ids or tool_names or tool_versions:
|
||||
|
||||
@@ -38,7 +38,7 @@ def build_index(whoosh_index_dir, file_path, hgweb_config_dir, dburi, **kwargs):
|
||||
Returns a tuple with number of repos and tools that were indexed.
|
||||
"""
|
||||
model = ts_mapping.init(file_path, dburi, engine_options={}, create_tables=False)
|
||||
sa_session = model.context.current
|
||||
sa_session = model.session
|
||||
repo_index, tool_index = _get_or_create_index(whoosh_index_dir)
|
||||
|
||||
repo_index_writer = AsyncWriter(repo_index)
|
||||
|
||||
@@ -97,7 +97,7 @@ This message was sent from the Galaxy Tool Shed instance hosted on the server
|
||||
|
||||
|
||||
def count_repositories_in_category(app, category_id):
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryCategoryAssociation) \
|
||||
.filter(app.model.RepositoryCategoryAssociation.table.c.category_id == app.security.decode_id(category_id)) \
|
||||
.count()
|
||||
@@ -105,7 +105,7 @@ def count_repositories_in_category(app, category_id):
|
||||
|
||||
def get_categories(app):
|
||||
"""Get all categories from the database."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Category) \
|
||||
.filter(app.model.Category.table.c.deleted == false()) \
|
||||
.order_by(app.model.Category.table.c.name) \
|
||||
@@ -114,13 +114,13 @@ def get_categories(app):
|
||||
|
||||
def get_category(app, id):
|
||||
"""Get a category from the database."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.Category).get(app.security.decode_id(id))
|
||||
|
||||
|
||||
def get_category_by_name(app, name):
|
||||
"""Get a category from the database via name."""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
try:
|
||||
return sa_session.query(app.model.Category).filter_by(name=name).one()
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
@@ -180,7 +180,7 @@ def get_requirements_from_repository(repository):
|
||||
|
||||
def get_repository_categories(app, id):
|
||||
"""Get categories of a repository on the tool shed side from the database via id"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
return sa_session.query(app.model.RepositoryCategoryAssociation) \
|
||||
.filter(app.model.RepositoryCategoryAssociation.table.c.repository_id == app.security.decode_id(id))
|
||||
|
||||
@@ -326,7 +326,7 @@ def handle_email_alerts(app, host, repository, content_alert_str='', new_repo_al
|
||||
that was included in the change set.
|
||||
|
||||
"""
|
||||
sa_session = app.model.context.current
|
||||
sa_session = app.model.session
|
||||
repo = repository.hg_repo
|
||||
sharable_link = repository_util.generate_sharable_link_for_repository_in_tool_shed(repository, changeset_revision=None)
|
||||
smtp_server = app.config.smtp_server
|
||||
|
||||
@@ -15,6 +15,8 @@ url = "https://wheels.galaxyproject.org/simple"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
aiofiles = "*"
|
||||
async-generator = {version = "*", python = "~3.6"}
|
||||
async-exit-stack = {version = "*", python = "~3.6"}
|
||||
Babel = "*"
|
||||
bdbag = "*"
|
||||
Beaker = "1.11.0"
|
||||
|
||||
@@ -26,7 +26,7 @@ class PageJsonEncodingIntegrationTestCase(integration_util.IntegrationTestCase):
|
||||
title="MY PAGE",
|
||||
content='''<p>Page!<div class="embedded-item" id="History-%s"></div></p>''' % self.history_id,
|
||||
)
|
||||
page_response = self._post("pages", request)
|
||||
page_response = self._post("pages", request, json=True)
|
||||
api_asserts.assert_status_code_is_ok(page_response)
|
||||
sa_session = self._app.model.context
|
||||
page_revision = sa_session.query(model.PageRevision).filter_by(content_format="html").all()[0]
|
||||
@@ -50,7 +50,7 @@ history_dataset_display(history_dataset_id=%s)
|
||||
```''' % dataset["id"],
|
||||
content_format="markdown",
|
||||
)
|
||||
page_response = self._post("pages", request)
|
||||
page_response = self._post("pages", request, json=True)
|
||||
api_asserts.assert_status_code_is_ok(page_response)
|
||||
sa_session = self._app.model.context
|
||||
page_revision = sa_session.query(model.PageRevision).filter_by(content_format="markdown").all()[0]
|
||||
|
||||
@@ -31,7 +31,7 @@ class BaseWrapperTestCase(UsesApp):
|
||||
job.user = User()
|
||||
job.object_store_id = "foo"
|
||||
self.model_objects = {Job: {345: job}}
|
||||
self.app.model.context = MockContext(self.model_objects)
|
||||
self.app.model._session = MockContext(self.model_objects)
|
||||
|
||||
self.app.toolbox = MockToolbox(MockTool(self))
|
||||
self.working_directory = os.path.join(self.test_directory, "working")
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
-->
|
||||
<command><![CDATA[
|
||||
#try
|
||||
#set $authz_record=$__app__.authnz_manager.try_get_authz_config($__app__.obj.model.context.current, int($__user_id__), $__app__.security.decode_id($authz_id.__str__()))
|
||||
#set $credentials_file = $__app__.authnz_manager.get_cloud_access_credentials_in_file($__app__.config.new_file_path, $authz_record, $__app__.obj.model.context.current, int($__user_id__))
|
||||
#set $authz_record=$__app__.authnz_manager.try_get_authz_config($__app__.obj.model.session, int($__user_id__), $__app__.security.decode_id($authz_id.__str__()))
|
||||
#set $credentials_file = $__app__.authnz_manager.get_cloud_access_credentials_in_file($__app__.config.new_file_path, $authz_record, $__app__.obj.model.session, int($__user_id__))
|
||||
#except Exception as e:
|
||||
echo '$e' >&2
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user