From e57da54eda3f5963d5739a2769190eda5cbffbe5 Mon Sep 17 00:00:00 2001 From: martintomas Date: Tue, 31 Dec 2024 13:50:27 +0100 Subject: [PATCH] feat: Private api endpoints for funder --- .../api/v1/members/base_controller.rb | 9 ++ .../api/v1/members/funders_controller.rb | 77 +++++++++ .../controllers/api/v1/members_controller.rb | 8 +- backend/app/models/ability.rb | 3 +- backend/app/models/funder.rb | 1 + backend/config/routes/api.rb | 7 +- ... => get-member-include-relationships.json} | 16 +- ...t.json => get-member-sparse-fieldset.json} | 2 +- .../{get-member-me.json => get-member.json} | 10 +- .../get-funder-include-relationships.json | 41 +++++ .../members/get-funder-sparse-fieldset.json | 12 ++ .../snapshots/api/v1/members/get-funder.json | 80 ++++++++++ .../update-funder-include-relationships.json | 41 +++++ .../update-funder-sparse-fieldset.json | 12 ++ .../api/v1/members/update-funder.json | 80 ++++++++++ .../requests/api/v1/members/funders_spec.rb | 149 ++++++++++++++++++ backend/spec/requests/api/v1/members_spec.rb | 90 ++++++----- 17 files changed, 571 insertions(+), 67 deletions(-) create mode 100644 backend/app/controllers/api/v1/members/base_controller.rb create mode 100644 backend/app/controllers/api/v1/members/funders_controller.rb rename backend/spec/fixtures/snapshots/api/v1/{get-member-me-include-relationships.json => get-member-include-relationships.json} (74%) rename backend/spec/fixtures/snapshots/api/v1/{get-member-me-sparse-fieldset.json => get-member-sparse-fieldset.json} (76%) rename backend/spec/fixtures/snapshots/api/v1/{get-member-me.json => get-member.json} (51%) create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/get-funder-include-relationships.json create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/get-funder-sparse-fieldset.json create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/get-funder.json create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/update-funder-include-relationships.json create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/update-funder-sparse-fieldset.json create mode 100644 backend/spec/fixtures/snapshots/api/v1/members/update-funder.json create mode 100644 backend/spec/requests/api/v1/members/funders_spec.rb diff --git a/backend/app/controllers/api/v1/members/base_controller.rb b/backend/app/controllers/api/v1/members/base_controller.rb new file mode 100644 index 0000000..07373fd --- /dev/null +++ b/backend/app/controllers/api/v1/members/base_controller.rb @@ -0,0 +1,9 @@ +module API + module V1 + module Members + class BaseController < API::V1::BaseController + before_action :authenticate! + end + end + end +end diff --git a/backend/app/controllers/api/v1/members/funders_controller.rb b/backend/app/controllers/api/v1/members/funders_controller.rb new file mode 100644 index 0000000..bfe7dca --- /dev/null +++ b/backend/app/controllers/api/v1/members/funders_controller.rb @@ -0,0 +1,77 @@ +module API + module V1 + module Members + class FundersController < BaseController + skip_before_action :require_json!, only: %i[update] + + load_and_authorize_resource + + def show + render json: FunderSerializer.new( + current_member.funder, + include: included_relationships, + fields: sparse_fieldset, + params: {current_member: current_member, current_ability: current_ability} + ).serializable_hash + end + + def update + if current_member.funder.update(funder_params) + render json: FunderSerializer.new( + current_member.funder, + include: included_relationships, + fields: sparse_fieldset, + params: {current_member: current_member, current_ability: current_ability} + ).serializable_hash + else + raise API::UnprocessableEntityError, current_member.funder.errors.full_messages.to_sentence + end + end + + private + + def funder_params + p = params.fetch(:funder_params, {}).permit( + :name, + :description, + :logo, + :primary_office_address, + :primary_office_city, + :primary_office_state_id, + :primary_office_country_id, + :primary_contact_first_name, + :primary_contact_last_name, + :primary_contact_email, + :show_primary_email, + :primary_contact_phone, + :primary_contact_location, + :primary_contact_role, + :secondary_email_which_can_be_shared, + :website, + :date_joined_fora, + :funder_type, + :funder_type_other, + :capital_acceptances_other, + :leadership_demographics_other, + :number_staff_employees, + :application_status, + :funder_legal_status, + :funder_legal_status_other, + :new_to_regenerative_ag, + :networks, + :capital_types_other, + :spend_down_strategy, + :areas_other, + :demographics_other, + capital_acceptances: [], + leadership_demographics: [], + capital_types: [], + areas: [], + demographics: [] + ) + p.merge published: true + end + end + end + end +end diff --git a/backend/app/controllers/api/v1/members_controller.rb b/backend/app/controllers/api/v1/members_controller.rb index 7956317..ecfdc88 100644 --- a/backend/app/controllers/api/v1/members_controller.rb +++ b/backend/app/controllers/api/v1/members_controller.rb @@ -3,7 +3,7 @@ module V1 class MembersController < BaseController load_and_authorize_resource except: :sign_in - def me + def show render json: API::V1::MemberSerializer.new( current_member, include: included_relationships, @@ -13,15 +13,15 @@ def me end def update - if @member.update(member_params) + if current_member.update(member_params) render json: API::V1::MemberSerializer.new( - @member, + current_member, include: included_relationships, fields: sparse_fieldset, params: {current_member: current_member, current_ability: current_ability} ).serializable_hash else - raise API::UnprocessableEntityError, @member.errors.full_messages.to_sentence + raise API::UnprocessableEntityError, current_member.errors.full_messages.to_sentence end end diff --git a/backend/app/models/ability.rb b/backend/app/models/ability.rb index 3192654..d6e6fd1 100644 --- a/backend/app/models/ability.rb +++ b/backend/app/models/ability.rb @@ -28,7 +28,8 @@ def admin_rights end def member_rights - can %i[me update], Member, id: @member.id + can %i[show update], Member, id: @member.id + can %i[show update], Funder, id: @member.funder_id end def default_rights diff --git a/backend/app/models/funder.rb b/backend/app/models/funder.rb index d9069e9..7c0bbe6 100644 --- a/backend/app/models/funder.rb +++ b/backend/app/models/funder.rb @@ -4,6 +4,7 @@ class Funder < ApplicationRecord belongs_to :primary_office_state, class_name: "Subgeographic", optional: true belongs_to :primary_office_country, class_name: "Subgeographic", optional: true + has_one :member, dependent: :restrict_with_exception has_many :investments, dependent: :destroy has_many :projects, -> { distinct }, through: :investments has_many :funder_subgeographics, dependent: :destroy diff --git a/backend/config/routes/api.rb b/backend/config/routes/api.rb index d3ba30f..46c889b 100644 --- a/backend/config/routes/api.rb +++ b/backend/config/routes/api.rb @@ -32,12 +32,15 @@ get :download end end - resources :members, only: %i[update] do + resource :member, only: %i[show update] do collection do - get :me post :sign_in end end resource :reset_password, only: [:create, :update] + + namespace :members do + resource :funder, only: %i[show update] + end end end diff --git a/backend/spec/fixtures/snapshots/api/v1/get-member-me-include-relationships.json b/backend/spec/fixtures/snapshots/api/v1/get-member-include-relationships.json similarity index 74% rename from backend/spec/fixtures/snapshots/api/v1/get-member-me-include-relationships.json rename to backend/spec/fixtures/snapshots/api/v1/get-member-include-relationships.json index 822c3fb..2051295 100644 --- a/backend/spec/fixtures/snapshots/api/v1/get-member-me-include-relationships.json +++ b/backend/spec/fixtures/snapshots/api/v1/get-member-include-relationships.json @@ -1,6 +1,6 @@ { "data": { - "id": "284482a5-7e3b-4c85-a339-306b5b635297", + "id": "f5f720f9-2896-4583-b63a-d61bb98e5e96", "type": "member", "attributes": { "first_name": "Dawna" @@ -8,7 +8,7 @@ "relationships": { "funder": { "data": { - "id": "42bafc40-e1d1-4547-b5f0-fc084c314e3b", + "id": "8ff19280-2af6-4a2c-be00-ba5fbea69263", "type": "funder" } } @@ -16,7 +16,7 @@ }, "included": [ { - "id": "42bafc40-e1d1-4547-b5f0-fc084c314e3b", + "id": "8ff19280-2af6-4a2c-be00-ba5fbea69263", "type": "funder", "attributes": { "name": "Otha Kemmer", @@ -58,21 +58,21 @@ "demographics_other": "Enim repellat pariatur est.", "contact_email": "dawna.block@example.org", "logo": { - "small": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt4TVRrMFl6TmlaQzB6Wmpjd0xUUTRPREV0WWpJM1pDMWtNV00yTW1JME1qTmpaak1HT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--e07e810222ab916c357c81f15aaadfd91d37f4a3/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERJd01IZ3lNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--8673702c2d856505736727890dcac6a632977811/picture.jpg", - "medium": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt4TVRrMFl6TmlaQzB6Wmpjd0xUUTRPREV0WWpJM1pDMWtNV00yTW1JME1qTmpaak1HT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--e07e810222ab916c357c81f15aaadfd91d37f4a3/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERnd01IZzRNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e82a96c0eabd93d914de4ef37febd98c36e0e275/picture.jpg", - "original": "http://localhost:4000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt4TVRrMFl6TmlaQzB6Wmpjd0xUUTRPREV0WWpJM1pDMWtNV00yTW1JME1qTmpaak1HT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--e07e810222ab916c357c81f15aaadfd91d37f4a3/picture.jpg" + "small": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWxrWTJNMVpUZzFOaTFtTm1NNExUUTROMlV0T1RrNU5TMWtaVEl4WkdKaE0ySTJPV0VHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--6ebae4c6f2260e3a7353702f52289ee02cc113ad/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERJd01IZ3lNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--8673702c2d856505736727890dcac6a632977811/picture.jpg", + "medium": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWxrWTJNMVpUZzFOaTFtTm1NNExUUTROMlV0T1RrNU5TMWtaVEl4WkdKaE0ySTJPV0VHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--6ebae4c6f2260e3a7353702f52289ee02cc113ad/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERnd01IZzRNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e82a96c0eabd93d914de4ef37febd98c36e0e275/picture.jpg", + "original": "http://localhost:4000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWxrWTJNMVpUZzFOaTFtTm1NNExUUTROMlV0T1RrNU5TMWtaVEl4WkdKaE0ySTJPV0VHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--6ebae4c6f2260e3a7353702f52289ee02cc113ad/picture.jpg" } }, "relationships": { "primary_office_state": { "data": { - "id": "5e0a16f2-669d-4edd-802b-727294069bee", + "id": "8382f3a9-e384-4716-8675-a428592c41f8", "type": "subgeographic" } }, "primary_office_country": { "data": { - "id": "c9d602e6-c5c8-4488-b834-5acc1d5300f3", + "id": "7c156964-9f67-4333-8160-3b9728840bd5", "type": "subgeographic" } }, diff --git a/backend/spec/fixtures/snapshots/api/v1/get-member-me-sparse-fieldset.json b/backend/spec/fixtures/snapshots/api/v1/get-member-sparse-fieldset.json similarity index 76% rename from backend/spec/fixtures/snapshots/api/v1/get-member-me-sparse-fieldset.json rename to backend/spec/fixtures/snapshots/api/v1/get-member-sparse-fieldset.json index e6238d4..161e5d1 100644 --- a/backend/spec/fixtures/snapshots/api/v1/get-member-me-sparse-fieldset.json +++ b/backend/spec/fixtures/snapshots/api/v1/get-member-sparse-fieldset.json @@ -1,6 +1,6 @@ { "data": { - "id": "2f2605b9-f43c-4c91-b09a-090aef968712", + "id": "c0843a5d-8672-4a7f-9692-f92dbc9fc5c6", "type": "member", "attributes": { "first_name": "Dawna", diff --git a/backend/spec/fixtures/snapshots/api/v1/get-member-me.json b/backend/spec/fixtures/snapshots/api/v1/get-member.json similarity index 51% rename from backend/spec/fixtures/snapshots/api/v1/get-member-me.json rename to backend/spec/fixtures/snapshots/api/v1/get-member.json index 4d73cd2..2d9da13 100644 --- a/backend/spec/fixtures/snapshots/api/v1/get-member-me.json +++ b/backend/spec/fixtures/snapshots/api/v1/get-member.json @@ -1,19 +1,19 @@ { "data": { - "id": "242e574b-ea06-4a1d-b925-b77147214bd9", + "id": "40e66665-d429-44db-b1b7-e59bedd968fd", "type": "member", "attributes": { - "id": "242e574b-ea06-4a1d-b925-b77147214bd9", + "id": "40e66665-d429-44db-b1b7-e59bedd968fd", "email": "admin1@example.com", "first_name": "Dawna", "last_name": "Block", - "created_at": "2024-12-31T11:21:25.233Z", - "updated_at": "2024-12-31T11:21:25.233Z" + "created_at": "2024-12-31T12:30:07.642Z", + "updated_at": "2024-12-31T12:30:07.642Z" }, "relationships": { "funder": { "data": { - "id": "44a070ab-5bf7-476a-b552-e8868bb23c7a", + "id": "48b5de22-d450-4e58-985c-aba167f82920", "type": "funder" } } diff --git a/backend/spec/fixtures/snapshots/api/v1/members/get-funder-include-relationships.json b/backend/spec/fixtures/snapshots/api/v1/members/get-funder-include-relationships.json new file mode 100644 index 0000000..1fbfad2 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/get-funder-include-relationships.json @@ -0,0 +1,41 @@ +{ + "data": { + "id": "fa9efb5e-e30a-4e41-b877-9d8d6884e088", + "type": "funder", + "attributes": { + "name": "Otha Kemmer" + }, + "relationships": { + "primary_office_country": { + "data": { + "id": "6f0bcd78-a484-451b-87a1-531cd7aed386", + "type": "subgeographic" + } + } + } + }, + "included": [ + { + "id": "6f0bcd78-a484-451b-87a1-531cd7aed386", + "type": "subgeographic", + "attributes": { + "name": "Papua New Guinea", + "code": "NPL", + "geographic": "countries", + "abbreviation": "C-NPL", + "created_at": "2024-12-31T11:53:23.489Z", + "updated_at": "2024-12-31T11:53:23.489Z" + }, + "relationships": { + "parent": { + "data": null + }, + "subgeographics": { + "data": [ + + ] + } + } + } + ] +} \ No newline at end of file diff --git a/backend/spec/fixtures/snapshots/api/v1/members/get-funder-sparse-fieldset.json b/backend/spec/fixtures/snapshots/api/v1/members/get-funder-sparse-fieldset.json new file mode 100644 index 0000000..5129b14 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/get-funder-sparse-fieldset.json @@ -0,0 +1,12 @@ +{ + "data": { + "id": "01448ed1-3dae-43d4-a6ed-625f69ab7f78", + "type": "funder", + "attributes": { + "name": "Otha Kemmer", + "description": "Enim repellat pariatur. Earum modi eos. Libero tempora exercitationem. Qui dolorem quo." + }, + "relationships": { + } + } +} \ No newline at end of file diff --git a/backend/spec/fixtures/snapshots/api/v1/members/get-funder.json b/backend/spec/fixtures/snapshots/api/v1/members/get-funder.json new file mode 100644 index 0000000..d404c36 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/get-funder.json @@ -0,0 +1,80 @@ +{ + "data": { + "id": "a76e97ea-5a98-4d8f-adb5-d62b47d8a2a8", + "type": "funder", + "attributes": { + "name": "Otha Kemmer", + "description": "Enim repellat pariatur. Earum modi eos. Libero tempora exercitationem. Qui dolorem quo.", + "primary_office_city": "South Moises", + "website": "http://kutch-spencer.com/moises", + "date_joined_fora": "2021-11-27T00:00:00.000Z", + "funder_type": "funder_collaborative_or_network", + "funder_type_other": "Enim repellat pariatur est.", + "capital_acceptances": [ + "other", + "investments_accepted" + ], + "capital_acceptances_other": "Enim repellat pariatur est.", + "leadership_demographics": [ + "hispanic_or_latinx", + "other" + ], + "leadership_demographics_other": "Enim repellat pariatur est.", + "application_status": "invitation_only", + "funder_legal_status": "other", + "funder_legal_status_other": "Enim repellat pariatur est.", + "networks": "Enim repellat pariatur. Earum modi eos. Libero tempora exercitationem. Qui dolorem quo.", + "capital_types": [ + "re_grants", + "pris" + ], + "capital_types_other": "Enim repellat pariatur est.", + "spend_down_strategy": true, + "areas": [ + "land_asset_financing", + "capacity_building" + ], + "areas_other": "Enim repellat pariatur est.", + "demographics": [ + "hispanic_or_latinx", + "other" + ], + "demographics_other": "Enim repellat pariatur est.", + "contact_email": "dawna.block@example.org", + "logo": { + "small": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt6WlRjd09EQmlaQzB3TW1SbExUUmhPRFV0WVRSaVlpMHlOV05tTlRZM09UTXpZaklHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--0a6421a4d48a2cb819c50eaabc7173b3b13eb6ed/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERJd01IZ3lNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--8673702c2d856505736727890dcac6a632977811/picture.jpg", + "medium": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt6WlRjd09EQmlaQzB3TW1SbExUUmhPRFV0WVRSaVlpMHlOV05tTlRZM09UTXpZaklHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--0a6421a4d48a2cb819c50eaabc7173b3b13eb6ed/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERnd01IZzRNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e82a96c0eabd93d914de4ef37febd98c36e0e275/picture.jpg", + "original": "http://localhost:4000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWt6WlRjd09EQmlaQzB3TW1SbExUUmhPRFV0WVRSaVlpMHlOV05tTlRZM09UTXpZaklHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--0a6421a4d48a2cb819c50eaabc7173b3b13eb6ed/picture.jpg" + } + }, + "relationships": { + "primary_office_state": { + "data": { + "id": "82ecb6e8-d4e1-4b38-b0a3-93218f43de66", + "type": "subgeographic" + } + }, + "primary_office_country": { + "data": { + "id": "76a7f382-aab9-429b-a553-168b8f2aa83b", + "type": "subgeographic" + } + }, + "subgeographics": { + "data": [ + + ] + }, + "subgeographic_ancestors": { + "data": [ + + ] + }, + "projects": { + "data": [ + + ] + } + } + } +} \ No newline at end of file diff --git a/backend/spec/fixtures/snapshots/api/v1/members/update-funder-include-relationships.json b/backend/spec/fixtures/snapshots/api/v1/members/update-funder-include-relationships.json new file mode 100644 index 0000000..c460a69 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/update-funder-include-relationships.json @@ -0,0 +1,41 @@ +{ + "data": { + "id": "319063d3-87f1-4d57-8ab9-b9b8a6e97c69", + "type": "funder", + "attributes": { + "name": "New name" + }, + "relationships": { + "primary_office_country": { + "data": { + "id": "50a4b9ef-1171-48b2-bdcc-02f45d225244", + "type": "subgeographic" + } + } + } + }, + "included": [ + { + "id": "50a4b9ef-1171-48b2-bdcc-02f45d225244", + "type": "subgeographic", + "attributes": { + "name": "Libyan Arab Jamahiriya", + "code": "KOR", + "geographic": "countries", + "abbreviation": "C-KOR", + "created_at": "2024-12-31T12:49:44.043Z", + "updated_at": "2024-12-31T12:49:44.043Z" + }, + "relationships": { + "parent": { + "data": null + }, + "subgeographics": { + "data": [ + + ] + } + } + } + ] +} \ No newline at end of file diff --git a/backend/spec/fixtures/snapshots/api/v1/members/update-funder-sparse-fieldset.json b/backend/spec/fixtures/snapshots/api/v1/members/update-funder-sparse-fieldset.json new file mode 100644 index 0000000..49672a8 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/update-funder-sparse-fieldset.json @@ -0,0 +1,12 @@ +{ + "data": { + "id": "9ea84931-7a44-48b9-979b-a041ae198cb7", + "type": "funder", + "attributes": { + "name": "New name", + "description": "Placeat commodi libero. Quo recusandae repellat. Sunt commodi tempore. Voluptatem et corrupti." + }, + "relationships": { + } + } +} \ No newline at end of file diff --git a/backend/spec/fixtures/snapshots/api/v1/members/update-funder.json b/backend/spec/fixtures/snapshots/api/v1/members/update-funder.json new file mode 100644 index 0000000..4f37381 --- /dev/null +++ b/backend/spec/fixtures/snapshots/api/v1/members/update-funder.json @@ -0,0 +1,80 @@ +{ + "data": { + "id": "ab26be52-28ee-4575-b7f8-34656daaf9fc", + "type": "funder", + "attributes": { + "name": "New name", + "description": "Placeat commodi libero. Quo recusandae repellat. Sunt commodi tempore. Voluptatem et corrupti.", + "primary_office_city": "Lake Genarostad", + "website": "http://bartoletti.com/jeremiah_cronin", + "date_joined_fora": "2022-04-07T00:00:00.000Z", + "funder_type": "loan_fund", + "funder_type_other": "Placeat commodi libero et.", + "capital_acceptances": [ + "advises_and_manages_capital", + "does_not_provide_funding" + ], + "capital_acceptances_other": "Placeat commodi libero et.", + "leadership_demographics": [ + "no_specific_focus", + "other" + ], + "leadership_demographics_other": "Placeat commodi libero et.", + "application_status": "does_not_provide_funding", + "funder_legal_status": "for_profit", + "funder_legal_status_other": "Placeat commodi libero et.", + "networks": "Placeat commodi libero. Quo recusandae repellat. Sunt commodi tempore. Voluptatem et corrupti.", + "capital_types": [ + "other", + "guarantees" + ], + "capital_types_other": "Placeat commodi libero et.", + "spend_down_strategy": true, + "areas": [ + "fermentation", + "soil_measurement_and_technology" + ], + "areas_other": "Placeat commodi libero et.", + "demographics": [ + "no_specific_focus", + "other" + ], + "demographics_other": "Placeat commodi libero et.", + "contact_email": "desmond_herzog@example.org", + "logo": { + "small": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWs1T1dObU1HUXhaaTB3WVdNeUxUUXlaall0T1RNeE9TMHhNVGd6TnpFM09XVTNZMllHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--03642d845c2a2a7f9f9277cf9338df244630989b/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERJd01IZ3lNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--8673702c2d856505736727890dcac6a632977811/picture.jpg", + "medium": "http://localhost:4000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWs1T1dObU1HUXhaaTB3WVdNeUxUUXlaall0T1RNeE9TMHhNVGd6TnpFM09XVTNZMllHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--03642d845c2a2a7f9f9277cf9338df244630989b/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2QzNKbGMybDZaVWtpRERnd01IZzRNREFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e82a96c0eabd93d914de4ef37febd98c36e0e275/picture.jpg", + "original": "http://localhost:4000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWs1T1dObU1HUXhaaTB3WVdNeUxUUXlaall0T1RNeE9TMHhNVGd6TnpFM09XVTNZMllHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--03642d845c2a2a7f9f9277cf9338df244630989b/picture.jpg" + } + }, + "relationships": { + "primary_office_state": { + "data": { + "id": "e1d67509-f581-4c3f-8b22-855be9477280", + "type": "subgeographic" + } + }, + "primary_office_country": { + "data": { + "id": "4a9c8aec-564e-4367-b41d-886ec23179f2", + "type": "subgeographic" + } + }, + "subgeographics": { + "data": [ + + ] + }, + "subgeographic_ancestors": { + "data": [ + + ] + }, + "projects": { + "data": [ + + ] + } + } + } +} \ No newline at end of file diff --git a/backend/spec/requests/api/v1/members/funders_spec.rb b/backend/spec/requests/api/v1/members/funders_spec.rb new file mode 100644 index 0000000..4e7175b --- /dev/null +++ b/backend/spec/requests/api/v1/members/funders_spec.rb @@ -0,0 +1,149 @@ +require "swagger_helper" + +RSpec.describe "API V1 Member Funder", type: :request do + path "/api/v1/members/funder" do + get "Returns funder of current member" do + tags "Funders" + consumes "application/json" + produces "application/json" + security [Bearer: {}] + + include_context "with authorization" + + parameter name: "fields[funder]", in: :query, type: :string, description: "Get only required fields. Use comma to separate multiple fields", required: false + parameter name: :includes, in: :query, type: :string, description: "Include relationships. Use comma to separate multiple fields", required: false + + let!(:member) { create :member } + + response "200", :success do + schema type: :object, properties: {data: {"$ref" => "#/components/schemas/funder"}} + + let(:Authorization) { "Bearer #{JWTAuth.encode(member)}" } + + run_test! + + it "matches snapshot", generate_swagger_example: true do + expect(response.body).to match_snapshot("api/v1/members/get-funder") + end + + context "with sparse fieldset" do + let("fields[funder]") { "name,description,nonexisting" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/members/get-funder-sparse-fieldset") + end + end + + context "with relationships" do + let("fields[funder]") { "name,primary_office_country,nonexisting" } + let(:includes) { "primary_office_country" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/members/get-funder-include-relationships") + end + end + end + end + + put "Updates funder of current member" do + tags "Funders" + consumes "multipart/form-data" + produces "application/json" + security [Bearer: {}] + + include_context "with authorization" + + parameter name: :funder_params, in: :formData, schema: { + type: :object, + properties: { + name: {type: :string}, + description: {type: :string}, + logo: {type: :binary}, + primary_office_address: {type: :string}, + primary_office_city: {type: :string}, + primary_office_state_id: {type: :integer}, + primary_office_country_id: {type: :integer}, + primary_contact_first_name: {type: :string}, + primary_contact_last_name: {type: :string}, + primary_contact_email: {type: :string}, + show_primary_email: {type: :boolean}, + primary_contact_phone: {type: :string}, + primary_contact_location: {type: :string}, + primary_contact_role: {type: :string}, + secondary_email_which_can_be_shared: {type: :string}, + website: {type: :string}, + date_joined_fora: {type: :string}, + funder_type: {type: :string}, + funder_type_other: {type: :string}, + capital_acceptances_other: {type: :string}, + leadership_demographics_other: {type: :string}, + number_staff_employees: {type: :integer}, + application_status: {type: :string}, + funder_legal_status: {type: :string}, + funder_legal_status_other: {type: :string}, + new_to_regenerative_ag: {type: :boolean}, + networks: {type: :string}, + capital_types_other: {type: :string}, + spend_down_strategy: {type: :string}, + areas_other: {type: :string}, + demographics_other: {type: :string}, + capital_acceptances: {type: :array, items: {type: :string}}, + leadership_demographics: {type: :array, items: {type: :string}}, + capital_types: {type: :array, items: {type: :string}}, + areas: {type: :array, items: {type: :string}}, + demographics: {type: :array, items: {type: :string}} + } + } + parameter name: "fields[funder]", in: :formData, type: :string, description: "Get only required fields. Use comma to separate multiple fields", required: false + parameter name: :includes, in: :formData, type: :string, description: "Include relationships. Use comma to separate multiple fields", required: false + + let(:funder_params) {} + let(:member) { create :member } + + response "200", :success do + schema type: :object, properties: {data: {"$ref" => "#/components/schemas/funder"}} + + let(:Authorization) { "Bearer #{JWTAuth.encode(member)}" } + let(:funder) { create :funder } + let(:funder_params) { + funder.attributes.except("id").merge( + name: "New name", + logo: fixture_file_upload("spec/fixtures/files/picture.jpg") + ) + } + + run_test! + + it "matches snapshot", generate_swagger_example: true do + expect(response.body).to match_snapshot("api/v1/members/update-funder") + end + + context "with sparse fieldset" do + let("fields[funder]") { "name,description,nonexisting" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/members/update-funder-sparse-fieldset") + end + end + + context "with relationships" do + let("fields[funder]") { "name,primary_office_country,nonexisting" } + let(:includes) { "primary_office_country" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/members/update-funder-include-relationships") + end + end + end + + response "422", "Invalid attributes" do + schema "$ref" => "#/components/schemas/errors" + + let(:Authorization) { "Bearer #{JWTAuth.encode(member)}" } + let(:funder_params) { {name: ""} } + + run_test! + end + end + end +end diff --git a/backend/spec/requests/api/v1/members_spec.rb b/backend/spec/requests/api/v1/members_spec.rb index b21f8be..7af48ad 100644 --- a/backend/spec/requests/api/v1/members_spec.rb +++ b/backend/spec/requests/api/v1/members_spec.rb @@ -3,8 +3,49 @@ require "swagger_helper" RSpec.describe "API V1 Members", type: :request do - path "/api/v1/members/{id}" do - put "Updates a member" do + path "/api/v1/member" do + get "Returns current member" do + tags "Member" + consumes "application/json" + produces "application/json" + security [Bearer: {}] + parameter name: "fields[member]", in: :query, type: :string, description: "Get only required fields. Use comma to separate multiple fields", required: false + parameter name: :includes, in: :query, type: :string, description: "Include relationships. Use comma to separate multiple fields", required: false + + include_context "with authorization" + + response "200", :success do + schema type: :object, properties: {data: {"$ref" => "#/components/schemas/member"}} + + let(:member) { create :member } + let(:Authorization) { "Bearer #{JWTAuth.encode(member)}" } + + run_test! + + it "matches snapshot", generate_swagger_example: true do + expect(response.body).to match_snapshot("api/v1/get-member") + end + + context "with sparse fieldset" do + let("fields[member]") { "first_name,email,nonexisting" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/get-member-sparse-fieldset") + end + end + + context "with relationships" do + let("fields[member]") { "first_name,funder,nonexisting" } + let(:includes) { "funder" } + + it "matches snapshot" do + expect(response.body).to match_snapshot("api/v1/get-member-include-relationships") + end + end + end + end + + put "Updates a current member" do tags "Member" consumes "application/json" produces "application/json" @@ -79,50 +120,7 @@ end end - path "/api/v1/members/me" do - get "Returns current member" do - tags "Member" - consumes "application/json" - produces "application/json" - security [Bearer: {}] - parameter name: "fields[member]", in: :query, type: :string, description: "Get only required fields. Use comma to separate multiple fields", required: false - parameter name: :includes, in: :query, type: :string, description: "Include relationships. Use comma to separate multiple fields", required: false - - include_context "with authorization" - - response "200", :success do - schema type: :object, properties: {data: {"$ref" => "#/components/schemas/member"}} - - let(:member) { create :member } - let(:Authorization) { "Bearer #{JWTAuth.encode(member)}" } - - run_test! - - it "matches snapshot", generate_swagger_example: true do - expect(response.body).to match_snapshot("api/v1/get-member-me") - end - - context "with sparse fieldset" do - let("fields[member]") { "first_name,email,nonexisting" } - - it "matches snapshot" do - expect(response.body).to match_snapshot("api/v1/get-member-me-sparse-fieldset") - end - end - - context "with relationships" do - let("fields[member]") { "first_name,funder,nonexisting" } - let(:includes) { "funder" } - - it "matches snapshot" do - expect(response.body).to match_snapshot("api/v1/get-member-me-include-relationships") - end - end - end - end - end - - path "/api/v1/members/sign_in" do + path "/api/v1/member/sign_in" do post "Returns member access token" do tags "Member" consumes "application/json"