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.