diff --git a/app/resources/seed_resource.rb b/app/resources/seed_resource.rb index 71af7d129..1323f9b7c 100644 --- a/app/resources/seed_resource.rb +++ b/app/resources/seed_resource.rb @@ -13,6 +13,13 @@ class SeedResource < ApplicationResource attribute :gmo, :string attribute :heirloom, :string + # What reading the photos of the packet found, written by the OCR script, which an admin runs. Not shown: it is + # not on any page yet. Writing it is not a member editing their own seed, so it is not theirs to do. + attribute :packet_text, :string, readable: false + before_save do |record| + context.authorize!(:manage, record) if written?(record) && record.packet_text_changed? + end + attribute :crop_id, :integer, readable: false belongs_to :crop diff --git a/spec/requests/api/v1/packet_text_request_spec.rb b/spec/requests/api/v1/packet_text_request_spec.rb new file mode 100644 index 000000000..0cf019544 --- /dev/null +++ b/spec/requests/api/v1/packet_text_request_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'rails_helper' + +# The text read from a seed packet's photos is saved by the OCR script, with an admin's token. +RSpec.describe 'Writing the text from a seed packet' do + include_context 'with an API member' + + let(:owner) { create(:member) } + let(:seed) { create(:seed, owner:) } + let(:text) { "Approx 15 seeds per packet\nSow by: December 2026" } + + def write(attributes, headers: auth_headers) + patch "/api/v1/seeds/#{seed.id}", params: { data: { type: 'seeds', id: seed.id.to_s, attributes: } }.to_json, headers: + end + + context 'with an admin, whose seed it is not' do + let(:member) { create(:admin_member) } + + before { write({ 'packet-text' => text }) } + + it('is saved') { expect(response).to have_http_status(:ok) } + it('is on the seed') { expect(seed.reload.packet_text).to eq text } + it('is not shown in the response') { expect(json['data']['attributes']).not_to have_key('packet-text') } + end + + context 'with the member whose seed it is' do + let(:member) { owner } + + before { write({ 'packet-text' => text }) } + + it('is forbidden') { expect(response).to have_http_status(:forbidden) } + it('is not saved') { expect(seed.reload.packet_text).to be_nil } + end + + context 'with another member' do + before { write({ 'packet-text' => text }) } + + it('is forbidden') { expect(response).to have_http_status(:forbidden) } + it('is not saved') { expect(seed.reload.packet_text).to be_nil } + end + + context 'with no token' do + before { write({ 'packet-text' => text }, headers: write_headers) } + + it('is unauthorised') { expect(response).to have_http_status(:unauthorized) } + end + + context 'when the member whose seed it is changes something else' do + let(:member) { owner } + + before { write({ 'quantity' => 40 }) } + + it('is saved') { expect(response).to have_http_status(:ok) } + it('is on the seed') { expect(seed.reload.quantity).to eq 40 } + end +end