From b36573540f270457c44240341f65a874e9a43840 Mon Sep 17 00:00:00 2001 From: Andrew <72628255+PivovarAndrew@users.noreply.github.com> Date: Sun, 6 Feb 2022 19:05:10 +0300 Subject: [PATCH 1/6] Change profile policy specs. --- spec/policies/profile_policy_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/policies/profile_policy_spec.rb b/spec/policies/profile_policy_spec.rb index ff0cacc6..84771132 100644 --- a/spec/policies/profile_policy_spec.rb +++ b/spec/policies/profile_policy_spec.rb @@ -22,8 +22,8 @@ end end - permissions :update?, :edit?, :destroy? do - it "is not allowed to update and delete the instance that doesn't belong to him" do + permissions :update?, :edit?, :destroy?, :add_tag?, :remove_tag? do + it "is not allowed to update and delete the instance and that tags that doesn't belong to him" do expect(policy).not_to permit(user, record) end end @@ -33,7 +33,7 @@ let(:user) { create :user } let(:record) { user.profile } - permissions :update?, :edit? do + permissions :update?, :edit?, :add_tag?, :remove_tag? do it 'is allowed to update the instance' do expect(policy).to permit(user, record) end From e1772eb573caf4e760aa1cf175052b0b806d69af Mon Sep 17 00:00:00 2001 From: Andrew <72628255+PivovarAndrew@users.noreply.github.com> Date: Sun, 6 Feb 2022 19:05:25 +0300 Subject: [PATCH 2/6] Add tag actions to profile policy. --- app/policies/profile_policy.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/policies/profile_policy.rb b/app/policies/profile_policy.rb index 24ebbaa2..3a59597e 100644 --- a/app/policies/profile_policy.rb +++ b/app/policies/profile_policy.rb @@ -14,6 +14,14 @@ def update? owns_record? end + def add_tag? + update? + end + + def remove_tag? + update? + end + # Profile policy scope class Scope < Scope def resolve From 087a7522d0e8a667f7a4635ff3fe54bc60cb7e00 Mon Sep 17 00:00:00 2001 From: Andrew <72628255+PivovarAndrew@users.noreply.github.com> Date: Sun, 6 Feb 2022 19:13:19 +0300 Subject: [PATCH 3/6] Create specs for user interests API endpoint request handlers. --- spec/requests/profiles_spec.rb | 77 ++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/spec/requests/profiles_spec.rb b/spec/requests/profiles_spec.rb index 74f9adfc..14bf0f65 100644 --- a/spec/requests/profiles_spec.rb +++ b/spec/requests/profiles_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' +# rubocop:disable Metrics/BlockLength RSpec.describe 'Profiles', type: :request do let(:current_user) { FactoryBot.create(:user) } let(:auth_headers) { current_user.create_new_auth_token } @@ -182,4 +183,80 @@ end end end + + describe 'POST /api/v1/profiles/:id/add_tag' do + describe 'add tag to profile' do + let(:current_user_profile) { FactoryBot.create(:profile, user_id: current_user.id) } + let(:tag) { FactoryBot.create(:tag) } + + before { post "/api/v1/profiles/#{current_user_profile.id}/add_tag", params: { name: tag.name }, headers: auth_headers } + + context 'when user is authenticated' do + it 'creates profile tag' do + expect(response).to have_http_status(:created) + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + context 'with profile that is not current user\'s profile' do + let(:not_current_user_profile) { FactoryBot.create(:profile) } + let(:tag) { FactoryBot.create(:tag) } + + before { post "/api/v1/profiles/#{not_current_user_profile.id}/add_tag", params: { name: tag.name }, headers: auth_headers } + + it 'can\'t create profile tag' do + expect(response).to have_http_status(:forbidden) + end + end + end + + context 'when user is not authenticated' do + before { post "/api/v1/profiles/#{current_user_profile.id}/add_tag", params: { name: tag.name } } + + it 'have http status 401' do + expect(response).to have_http_status(:unauthorized) + end + end + end + end + + describe 'DELETE /api/v1/profiles/:profile_id/remove_tag/:name' do + describe 'delete tag from profile' do + let(:current_user_profile) { create :profile, user: current_user } + let(:tag) { FactoryBot.create(:tag) } + + before { delete "/api/v1/profiles/#{current_user_profile.id}/remove_tag/#{tag.name}", headers: auth_headers } + + context 'when user is authenticated' do + it 'returns no content' do + expect(response).to have_http_status(:no_content) + end + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + context 'with profile that is not current user\'s profile' do + let(:not_current_user_profile) { FactoryBot.create(:profile) } + + before { delete "/api/v1/profiles/#{not_current_user_profile.id}/remove_tag/#{tag.name}", headers: auth_headers } + + it 'can\'t delete profile tag' do + expect(response).to have_http_status(:forbidden) + end + end + end + + context 'when user is not authenticated' do + before { delete "/api/v1/profiles/#{current_user_profile.id}/remove_tag/#{tag.name}" } + + it 'have http status 401' do + expect(response).to have_http_status(:unauthorized) + end + end + end + end end +# rubocop:enable Metrics/BlockLength From 9b41e706929c55c05c2348defea983770902d95f Mon Sep 17 00:00:00 2001 From: Andrew <72628255+PivovarAndrew@users.noreply.github.com> Date: Mon, 7 Feb 2022 00:47:12 +0300 Subject: [PATCH 4/6] Create request handlers with routes for user interests API endpoint. --- app/controllers/api/v1/profiles_controller.rb | 37 +++++++++++++++++-- app/serializers/profile_serializer.rb | 2 +- config/routes.rb | 4 ++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/profiles_controller.rb b/app/controllers/api/v1/profiles_controller.rb index b92e186d..8997c83d 100644 --- a/app/controllers/api/v1/profiles_controller.rb +++ b/app/controllers/api/v1/profiles_controller.rb @@ -4,13 +4,15 @@ module API module V1 # Controller class that is responsible for handling profile requests. class ProfilesController < ApplicationController - before_action :set_profile, only: %i[show update] before_action :authorize_profile! + before_action :set_profile, except: %i[index create] + before_action :set_tag, only: %i[remove_tag] after_action :verify_authorized # GET /profiles or /profiles.json def index - render json: Profile.all, status: :ok + profiles = Profile.all + render json: profiles, status: :ok end # GET /profiles/:id or /profiles/:id.json @@ -37,16 +39,45 @@ def update end end - private + # POST /profiles/:id/add_tag or /profiles/:id/add_tag.json + def add_tag + tag = Tag.find_or_create_by(params[:tag]) + if tag_params.blank? + render json: { error: 'There was no tag data passed in so your profile could not be saved.' }, + status: :unprocessable_entity + else + if @profile.tags << tag + render json: @profile, status: :created + else + render json: @profile.errors, status: :unprocessable_entity + end + end + end def set_profile @profile = Profile.find_by(user_id: params[:user_id]) end + # DELETE /profiles/:profile_id/remove_tag/:id or /profiles/:profile_id/remove_tag/:id.json + def remove_tag + @profile.tags.destroy(@tag) + head 204 + end + + private + + def set_tag + @tag = Tag.find_by(name: params[:name]) + end + def profile_params params.permit(:surname, :name, :patronymic, :birthday, :phone, :about, :user_id) end + def tag_params + params.permit(:name) + end + def authorize_profile! authorize(@profile || Profile) end diff --git a/app/serializers/profile_serializer.rb b/app/serializers/profile_serializer.rb index ef06605b..d2a228ce 100644 --- a/app/serializers/profile_serializer.rb +++ b/app/serializers/profile_serializer.rb @@ -29,5 +29,5 @@ # Сlass responsible for serializing profile data class ProfileSerializer < ActiveModel::Serializer attributes :id, :surname, :name, :patronymic, - :birthday, :phone, :about + :birthday, :phone, :about, :tags end diff --git a/config/routes.rb b/config/routes.rb index 9eba3ef3..7444e4e1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,6 +24,10 @@ resources :conversations do post 'add_user/:user_id', to: 'conversations#add_user' delete 'delete_user/:user_id', to: 'conversations#delete_user' + get :profile, to: 'profiles#show' + put :profile, to: 'profiles#update' + post '/add_tag', to: 'profiles#add_tag' + delete '/remove_tag/:name', to: 'profiles#remove_tag' end get '/search_profile', to: 'search#search_profile' get '/search_conversation', to: 'search#search_conversation' From 568e62f17ac55b2eba57b6173f2d4c5abaed0766 Mon Sep 17 00:00:00 2001 From: Andrew <72628255+PivovarAndrew@users.noreply.github.com> Date: Wed, 9 Feb 2022 05:57:20 +0300 Subject: [PATCH 5/6] Change tags factory bot. --- spec/factories/tags.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/tags.rb b/spec/factories/tags.rb index e12dfb73..a6cebcaf 100644 --- a/spec/factories/tags.rb +++ b/spec/factories/tags.rb @@ -15,6 +15,6 @@ # FactoryBot.define do factory :tag do - name { Faker::Hobby.unique.activity } + name { Faker::Hobby.unique.activity.downcase.gsub(' ','_') } end end From 4ef8e10655f84da1875686e4be5ef6a930cbffd6 Mon Sep 17 00:00:00 2001 From: skripchenkoveta Date: Mon, 21 Feb 2022 01:45:07 +0300 Subject: [PATCH 6/6] SN-41/resolve conflicts --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index 7444e4e1..176f8eab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,6 +19,7 @@ post :subscribe, to: 'user_subscriptions#subscribe' post :unsubscribe, to: 'user_subscriptions#unsubscribe' end + resources :likes, only: %i[create destroy index] resources :messages, except: %i[index, show] resources :conversations do