Skip to content

get/read ownership transfer - #1017

Draft
DNR500 wants to merge 5 commits into
1766-create-ownership-transferfrom
create-and-get-ownership-transfer
Draft

DNR500 wants to merge 5 commits into
1766-create-ownership-transferfrom
create-and-get-ownership-transfer

Conversation

@DNR500

@DNR500 DNR500 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary WIP

Backend for #1767 / #1770.

Built on top of #1019 (nominated_user_id / requested_by_user_id / status schema for ownership_transfers), which lays the data model but doesn't add any endpoint yet. This PR should be rebased onto main once #1019 merges — as the base branch #1019 develops it will mainly be concerned with the endpoint to start a transfer, so this PR is scoped to the get/read endpoint that provides the status of a transfer.

Adds the endpoint editor-standalone needs to show ownership transfer status to both the owner and the nominee.

What's changed?

  • GET /api/schools/:school_id/ownership_transfer — returns who the current user is relative to the pending transfer; anyone not involved gets a 404, same as if no transfer existed
  • Closes a race condition Create ownership transfer #1019 flagged as not yet covered: a partial unique index on ownership_transfers.school_id (scoped to status = 'pending') plus a matching model validation, so two concurrent requests can't both succeed
  • Small fix to a pre-existing bug in Create ownership transfer #1019's own mailer spec (unrelated to the above — the bare factory's random nominated_user_id never had a role anywhere, so create(:ownership_transfer) always failed validation)

Examples

Checking transfer status

GET /api/schools/9d9c1e3e-1e4b-4b0a-9a2e-6a2b7e6f1a10/ownership_transfer
Authorization: Bearer <token>

As the owner who requested it, while it's pending:

// 200 OK
{
  "status": "pending",
  "you_are": "owner",
  "nominee_name": "Priya Shah"
}

As the nominee, while it's pending:

// 200 OK
{
  "status": "pending",
  "you_are": "nominee"
}

The transfer stays visible to the requester and nominee after it's resolved — status reflects whatever actually happened, rather than the response disappearing once it's no longer pending:

// 200 OK — the requester, after the nominee accepted
{
  "status": "completed",
  "you_are": "owner",
  "nominee_name": "Priya Shah"
}
// 200 OK — the nominee, after declining it themselves
{
  "status": "rejected",
  "you_are": "nominee"
}

As anyone else at the school (a different teacher, a different owner who wasn't involved, or if no transfer has ever existed for the school) — deliberately indistinguishable, so the response doesn't leak whether one exists or what happened to it:

404 Not Found

(empty body)

Other responses: 401 (no token), 403 (caller has no role at that school at all).

@cla-bot cla-bot Bot added the cla-signed label Sep 14, 2026
@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown

Test coverage

93.59% line coverage reported by SimpleCov.
Run: https://github.com/RaspberryPiFoundation/editor-api/actions/runs/34990734477

response
rescue StandardError => e
Sentry.capture_exception(e)
response[:error] = "Error creating ownership transfer: #{e}"
@DNR500 DNR500 changed the title Create and get ownership transfer get/read ownership transfer Sep 15, 2026
@DNR500
DNR500 force-pushed the create-and-get-ownership-transfer branch from 3acb88c to 44c8217 Compare September 15, 2026 15:46
@DNR500
DNR500 changed the base branch from main to 1766-create-ownership-transfer September 15, 2026 15:48
@DNR500
DNR500 force-pushed the create-and-get-ownership-transfer branch from 44c8217 to 69a8eed Compare September 15, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants