diff --git a/client/src/components/Grid/GridHistory.vue b/client/src/components/Grid/GridHistory.vue index fe61e4ab0103..a54e2437d3be 100644 --- a/client/src/components/Grid/GridHistory.vue +++ b/client/src/components/Grid/GridHistory.vue @@ -11,13 +11,14 @@ import { useUserStore } from "@/stores/userStore"; import Heading from "@/components/Common/Heading.vue"; import LoginRequired from "@/components/Common/LoginRequired.vue"; import GridList from "@/components/Grid/GridList.vue"; +import HistoryArchive from "@/components/History/Archiving/HistoryArchive.vue"; const userStore = useUserStore(); library.add(faPlus); interface Props { - activeList?: "my" | "shared" | "published"; + activeList?: "archived" | "my" | "shared" | "published"; username?: string; } @@ -64,9 +65,17 @@ const props = withDefaults(defineProps(), { Public Histories + + Archived Histories + - + + diff --git a/client/src/components/History/Archiving/HistoryArchive.vue b/client/src/components/History/Archiving/HistoryArchive.vue index 927fb77e91f9..69bda0d3c45c 100644 --- a/client/src/components/History/Archiving/HistoryArchive.vue +++ b/client/src/components/History/Archiving/HistoryArchive.vue @@ -135,12 +135,11 @@ async function onImportCopy(history: ArchivedHistorySummary) { diff --git a/client/src/entry/analysis/menu.js b/client/src/entry/analysis/menu.js index b870446bbd3f..495b0ae231a2 100644 --- a/client/src/entry/analysis/menu.js +++ b/client/src/entry/analysis/menu.js @@ -243,10 +243,6 @@ export function fetchMenu(options = {}) { url: "/interactivetool_entry_points/list", }); } - userTab.menu.push({ - title: _l("Archived Histories"), - url: "/histories/archived", - }); if (Galaxy.config.enable_notification_system) { userTab.menu.push({ title: _l("Notifications"), diff --git a/client/src/entry/analysis/router.js b/client/src/entry/analysis/router.js index 87202bbd41c4..5bf39d07f2fa 100644 --- a/client/src/entry/analysis/router.js +++ b/client/src/entry/analysis/router.js @@ -63,7 +63,6 @@ import { patchRouterPush } from "./router-push"; import AboutGalaxy from "@/components/AboutGalaxy.vue"; import GridVisualization from "@/components/Grid/GridVisualization.vue"; -import HistoryArchive from "@/components/History/Archiving/HistoryArchive.vue"; import HistoryArchiveWizard from "@/components/History/Archiving/HistoryArchiveWizard.vue"; import HistoryDatasetPermissions from "@/components/History/HistoryDatasetPermissions.vue"; import NotificationsList from "@/components/Notifications/NotificationsList.vue"; @@ -288,7 +287,10 @@ export function getRouter(Galaxy) { }, { path: "histories/archived", - component: HistoryArchive, + component: GridHistory, + props: { + activeList: "archived", + }, }, { path: "histories/list", diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index 8c51b9f14db8..f9952c882a21 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -665,11 +665,11 @@ def _ensure_valid_session(self, session_cookie: str, create: bool = True) -> Non galaxy_session = self.__create_new_session(prev_galaxy_session, user_for_new_session) galaxy_session_requires_flush = True self.galaxy_session = galaxy_session - if self.webapp.name == "galaxy": - self.get_or_create_default_history() self.__update_session_cookie(name=session_cookie) else: self.galaxy_session = galaxy_session + if self.webapp.name == "galaxy": + self.get_or_create_default_history() # Do we need to flush the session? if galaxy_session_requires_flush: self.sa_session.add(galaxy_session) @@ -814,10 +814,10 @@ def _associate_user_history(self, user, prev_galaxy_session=None): and not users_last_session.current_history.deleted ): history = users_last_session.current_history - elif not history: - history = self.get_history(create=True, most_recent=True) if history not in self.galaxy_session.histories: self.galaxy_session.add_history(history) + if not history: + history = self.new_history() if history.user is None: history.user = user self.galaxy_session.current_history = history @@ -927,29 +927,30 @@ def get_or_create_default_history(self): Gets or creates a default history and associates it with the current session. """ - - # There must be a user to fetch a default history. - if not self.galaxy_session.user: - return self.new_history() - - # Look for default history that (a) has default name + is not deleted and - # (b) has no datasets. If suitable history found, use it; otherwise, create - # new history. - stmt = select(self.app.model.History).filter_by( - user=self.galaxy_session.user, name=self.app.model.History.default_name, deleted=False - ) - unnamed_histories = self.sa_session.scalars(stmt) - default_history = None - for history in unnamed_histories: - if history.empty: - # Found suitable default history. - default_history = history - break - - # Set or create history. - if default_history: - history = default_history - self.set_history(history) + history = self.galaxy_session.current_history + if history and not history.deleted: + return history + + user = self.galaxy_session.user + if user: + # Look for default history that (a) has default name + is not deleted and + # (b) has no datasets. If suitable history found, use it; otherwise, create + # new history. + stmt = select(self.app.model.History).filter_by( + user=user, name=self.app.model.History.default_name, deleted=False + ) + unnamed_histories = self.sa_session.scalars(stmt) + default_history = None + for history in unnamed_histories: + if history.empty: + # Found suitable default history. + default_history = history + break + + # Set or create history. + if default_history: + history = default_history + self.set_history(history) else: history = self.new_history() diff --git a/lib/galaxy_test/api/test_authenticate.py b/lib/galaxy_test/api/test_authenticate.py index 41f437d49134..7cd375516a32 100644 --- a/lib/galaxy_test/api/test_authenticate.py +++ b/lib/galaxy_test/api/test_authenticate.py @@ -53,3 +53,25 @@ def test_tool_runner_session_cookie_handling(self): current_history_json_response.raise_for_status() current_history = current_history_json_response.json() assert current_history["contents_active"]["active"] == 1 + + def test_anon_history_creation(self): + # First request: + # We don't create any histories, just return a session cookie + response = get(self.url) + cookie = {"galaxysession": response.cookies["galaxysession"]} + # Check that we don't have any histories (API doesn't auto-create new histories) + histories_response = get( + urljoin( + self.url, + "api/histories", + ) + ) + assert not histories_response.json() + # Second request, we know client follows conventions by including cookies, + # default history is created. + get(self.url, cookies=cookie) + second_histories_response = get( + urljoin(self.url, "history/current_history_json"), + cookies=cookie, + ) + assert second_histories_response.json()