diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index b555e2f298..6e78310e41 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -17,6 +17,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released ### Changed - Some mesh-related actions were disabled in proofreading-mode when using meshfiles that were created for a mapping rather than an oversegmentation. [#8091](https://github.com/scalableminds/webknossos/pull/8091) +- Admins can now see and cancel all jobs. The owner of the job is shown in the job list. [#8112](https://github.com/scalableminds/webknossos/pull/8112) ### Fixed - Fixed a bug during dataset upload in case the configured `datastore.baseFolder` is an absolute path. [#8098](https://github.com/scalableminds/webknossos/pull/8098) [#8103](https://github.com/scalableminds/webknossos/pull/8103) diff --git a/app/models/job/Job.scala b/app/models/job/Job.scala index 9e39f96ec8..4fe3fe6ac3 100644 --- a/app/models/job/Job.scala +++ b/app/models/job/Job.scala @@ -141,7 +141,9 @@ class JobDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContext) """ private def listAccessQ(requestingUserId: ObjectId) = - q"""_owner = $requestingUserId""" + q"""_owner = $requestingUserId OR + ((SELECT u._organization FROM webknossos.users_ u WHERE u._id = _owner) IN (SELECT _organization FROM webknossos.users_ WHERE _id = $requestingUserId AND isAdmin)) + """ override def findAll(implicit ctx: DBAccessContext): Fox[List[Job]] = for { diff --git a/app/models/job/JobService.scala b/app/models/job/JobService.scala index 28c6e371da..0b595516a9 100644 --- a/app/models/job/JobService.scala +++ b/app/models/job/JobService.scala @@ -163,9 +163,11 @@ class JobService @Inject()(wkConf: WkConf, owner <- userDAO.findOne(job._owner) ?~> "user.notFound" organization <- organizationDAO.findOne(owner._organization) ?~> "organization.notFound" resultLink = job.resultLink(organization._id) + ownerJson <- userService.compactWrites(owner) } yield { Json.obj( "id" -> job._id.id, + "owner" -> ownerJson, "command" -> job.command, "commandArgs" -> (job.commandArgs - "webknossos_token" - "user_auth_token"), "state" -> job.state, diff --git a/frontend/javascripts/admin/api/jobs.ts b/frontend/javascripts/admin/api/jobs.ts index 30fdc89dfe..df704428b5 100644 --- a/frontend/javascripts/admin/api/jobs.ts +++ b/frontend/javascripts/admin/api/jobs.ts @@ -16,6 +16,7 @@ import { assertResponseLimit } from "./api_utils"; function transformBackendJobToAPIJob(job: any): APIJob { return { id: job.id, + owner: job.owner, type: job.command, datasetName: job.commandArgs.dataset_name, organizationId: job.commandArgs.organization_name, diff --git a/frontend/javascripts/admin/job/job_list_view.tsx b/frontend/javascripts/admin/job/job_list_view.tsx index 910c613a0f..17c32a2a56 100644 --- a/frontend/javascripts/admin/job/job_list_view.tsx +++ b/frontend/javascripts/admin/job/job_list_view.tsx @@ -15,7 +15,7 @@ import { InfoCircleOutlined, } from "@ant-design/icons"; import type * as React from "react"; -import { type APIJob, APIJobType } from "types/api_flow_types"; +import { type APIJob, APIJobType, type APIUserBase } from "types/api_flow_types"; import { getJobs, cancelJob } from "admin/admin_rest_api"; import Persistence from "libs/persistence"; import * as Utils from "libs/utils"; @@ -375,7 +375,7 @@ function JobListView() {
- WEBKNOSSOS will notfiy you via email when a job has finished or reload this page to track + WEBKNOSSOS will notify you via email when a job has finished or reload this page to track progress.
((job) => job.createdAt)} defaultSortOrder="descend" /> + ((job) => job.owner.lastName)} + render={(owner: APIUserBase) => ( + <> +
{owner.email ? `${owner.lastName}, ${owner.firstName}` : "-"}
+
{owner.email ? `(${owner.email})` : "-"}
+ + )} + />