diff --git a/app/controllers/api/v1/experiment_user_assignments_controller.rb b/app/controllers/api/v1/experiment_user_assignments_controller.rb index 8f6f233f0..82a36e0f9 100644 --- a/app/controllers/api/v1/experiment_user_assignments_controller.rb +++ b/app/controllers/api/v1/experiment_user_assignments_controller.rb @@ -11,6 +11,7 @@ module Api def index user_assignments = @experiment.user_assignments + .includes(:user_role) .page(params.dig(:page, :number)) .per(params.dig(:page, :size)) @@ -28,17 +29,18 @@ module Api def create raise PermissionError.new(Experiment, :manage) unless can_manage_experiment?(@experiment) - user_role = UserRole.find_by_name user_assignment_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_assignment_params[:role]) experiment_member = ExperimentMember.new(current_user, @experiment, @project) experiment_member.create( user_role_id: user_role.id, user_id: user_assignment_params[:user_id] ) - render jsonapi: experiment_member.user_project, serializer: ExperimentUserAssignmentSerializer, status: :created + + render jsonapi: experiment_member.user_assignment.reload, serializer: ExperimentUserAssignmentSerializer, status: :created end def update - user_role = UserRole.find_by_name user_assignment_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_assignment_params[:role]) user = @user_assignment.user experiment_member = ExperimentMember.new( current_user, @@ -51,7 +53,7 @@ module Api return render body: nil, status: :no_content if @user_assignment.user_role == user_role experiment_member.update(user_role_id: user_role.id, user_id: user.id) - render jsonapi: experiment_member.user_project, serializer: ExperimentUserAssignmentSerializer, status: :ok + render jsonapi: experiment_member.user_assignment.reload, serializer: ExperimentUserAssignmentSerializer, status: :ok end def destroy @@ -68,6 +70,8 @@ module Api private + include Api::V1::UserRoleSanitizer + def load_user_assignment @user_assignment = @experiment.user_assignments.find(params.require(:id)) end diff --git a/app/controllers/api/v1/task_user_assignments_controller.rb b/app/controllers/api/v1/task_user_assignments_controller.rb index 8038b7d6f..8055a852f 100644 --- a/app/controllers/api/v1/task_user_assignments_controller.rb +++ b/app/controllers/api/v1/task_user_assignments_controller.rb @@ -12,6 +12,7 @@ module Api def index user_assignments = @task.user_assignments + .includes(:user_role) .page(params.dig(:page, :number)) .per(params.dig(:page, :size)) @@ -29,17 +30,17 @@ module Api def create raise PermissionError.new(MyModule, :read) unless can_manage_module?(@task) - user_role = UserRole.find_by_name user_assignment_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_assignment_params[:role]) my_module_member = MyModuleMember.new(current_user, @task, @experiment, @project) my_module_member.create( user_role_id: user_role.id, user_id: user_assignment_params[:user_id] ) - render jsonapi: my_module_member.user_project, serializer: TaskUserAssignmentSerializer, status: :created + render jsonapi: my_module_member.user_assignment.reload, serializer: TaskUserAssignmentSerializer, status: :created end def update - user_role = UserRole.find_by_name user_assignment_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_assignment_params[:role]) user = @user_assignment.user my_module_member = MyModuleMember.new( current_user, @@ -53,7 +54,7 @@ module Api return render body: nil, status: :no_content if @user_assignment.user_role == user_role my_module_member.update(user_role_id: user_role.id, user_id: user.id) - render jsonapi: my_module_member.user_project, serializer: TaskUserAssignmentSerializer, status: :ok + render jsonapi: my_module_member.user_assignment.reload, serializer: TaskUserAssignmentSerializer, status: :ok end def destroy @@ -71,6 +72,8 @@ module Api private + include Api::V1::UserRoleSanitizer + def load_user_assignment @user_assignment = @task.user_assignments.find(params.require(:id)) end diff --git a/app/controllers/api/v1/user_projects_controller.rb b/app/controllers/api/v1/user_projects_controller.rb index c7c2fc7c6..1d572b7d8 100644 --- a/app/controllers/api/v1/user_projects_controller.rb +++ b/app/controllers/api/v1/user_projects_controller.rb @@ -9,7 +9,7 @@ module Api before_action :load_user_project_for_managing, only: %i(update destroy) def index - user_projects = @project.user_projects + user_projects = @project.user_projects.includes(:user, project: [user_assignments: :user_role]) .page(params.dig(:page, :number)) .per(params.dig(:page, :size)) @@ -28,7 +28,7 @@ module Api raise PermissionError.new(Project, :manage) unless can_manage_project?(@project) # internally we reuse the same logic as for user project assignment - user_role = UserRole.find_by_name user_project_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_project_params[:role]) user = @team.users.find(user_project_params[:user_id]) project_member = ProjectMember.new(user, @project, current_user) @@ -36,11 +36,11 @@ module Api project_member.user_role_id = user_role.id project_member.create - render jsonapi: project_member.user_project, serializer: UserProjectSerializer, status: :created + render jsonapi: project_member.user_project.reload, serializer: UserProjectSerializer, status: :created end def update - user_role = UserRole.find_by_name user_project_params[:role] + user_role = UserRole.find_by_name incoming_role_name(user_project_params[:role]) project_member = ProjectMember.new(@user_project.user, @project, current_user) if project_member.user_assignment&.user_role == user_role @@ -49,7 +49,7 @@ module Api project_member.user_role_id = user_role.id project_member.update - render jsonapi: @user_project, serializer: UserProjectSerializer, status: :ok + render jsonapi: @user_project.reload, serializer: UserProjectSerializer, status: :ok end def destroy @@ -60,6 +60,8 @@ module Api private + include Api::V1::UserRoleSanitizer + def load_user_project @user_project = @project.user_projects.find(params.require(:id)) end diff --git a/app/controllers/concerns/api/v1/user_role_sanitizer.rb b/app/controllers/concerns/api/v1/user_role_sanitizer.rb new file mode 100644 index 000000000..3274f6e6a --- /dev/null +++ b/app/controllers/concerns/api/v1/user_role_sanitizer.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Api + module V1 + module UserRoleSanitizer + extend ActiveSupport::Concern + + def incoming_role_name(role) + case role + when 'owner' + I18n.t('user_roles.predefined.owner') + when 'normal_user' + I18n.t('user_roles.predefined.normal_user') + when 'technician' + I18n.t('user_roles.predefined.technician') + when 'viewer' + I18n.t('user_roles.predefined.viewer') + else + raise IncludeNotSupportedError + end + end + end + end +end diff --git a/app/helpers/user_roles_helper.rb b/app/helpers/user_roles_helper.rb index 30cacea7a..50f6a025d 100644 --- a/app/helpers/user_roles_helper.rb +++ b/app/helpers/user_roles_helper.rb @@ -6,4 +6,17 @@ module UserRolesHelper @user_roles_collection ||= UserRole.all.pluck(:name, :id) end end + + def legacy_user_role_parser(name) + case name + when I18n.t('user_roles.predefined.owner') + 'owner' + when I18n.t('user_roles.predefined.normal_user') + 'normal_user' + when I18n.t('user_roles.predefined.technician') + 'technician' + when I18n.t('user_roles.predefined.viewer') + 'viewer' + end + end end diff --git a/app/serializers/api/v1/experiment_user_assignment_serializer.rb b/app/serializers/api/v1/experiment_user_assignment_serializer.rb index 4c2d88625..ec274f98d 100644 --- a/app/serializers/api/v1/experiment_user_assignment_serializer.rb +++ b/app/serializers/api/v1/experiment_user_assignment_serializer.rb @@ -3,11 +3,17 @@ module Api module V1 class ExperimentUserAssignmentSerializer < ActiveModel::Serializer + include UserRolesHelper + type :experiment_user_assignments attributes :id, :role belongs_to :user, serializer: UserSerializer - belongs_to :experiment, serializer: ExperimentSerializer + + def role + # TODO: sync about the role solution + legacy_user_role_parser(object.user_role.name) + end end end end diff --git a/app/serializers/api/v1/task_user_assigment_serializer.rb b/app/serializers/api/v1/task_user_assignment_serializer.rb similarity index 61% rename from app/serializers/api/v1/task_user_assigment_serializer.rb rename to app/serializers/api/v1/task_user_assignment_serializer.rb index 37f9ae66c..12737bbad 100644 --- a/app/serializers/api/v1/task_user_assigment_serializer.rb +++ b/app/serializers/api/v1/task_user_assignment_serializer.rb @@ -3,11 +3,17 @@ module Api module V1 class TaskUserAssignmentSerializer < ActiveModel::Serializer + include UserRolesHelper + type :task_user_assignments attributes :id, :role belongs_to :user, serializer: UserSerializer - belongs_to :task, serializer: TaskSerializer + + def role + # TODO: sync about the role solution + legacy_user_role_parser(object.user_role.name) + end end end end diff --git a/app/serializers/api/v1/user_project_serializer.rb b/app/serializers/api/v1/user_project_serializer.rb index e2e138232..9679e9924 100644 --- a/app/serializers/api/v1/user_project_serializer.rb +++ b/app/serializers/api/v1/user_project_serializer.rb @@ -3,10 +3,22 @@ module Api module V1 class UserProjectSerializer < ActiveModel::Serializer + include UserRolesHelper + type :user_projects attributes :id, :role belongs_to :user, serializer: UserSerializer + + def role + # TODO: sync about the role solution + user_role = object.project + .user_assignments + .select { |ua| ua.user_id == object.user.id } + .first&.user_role + return unless user_role + legacy_user_role_parser(user_role.name) + end end end end diff --git a/config/routes.rb b/config/routes.rb index 5a70116d0..2d43cdff5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -697,11 +697,15 @@ Rails.application.routes.draw do get 'activities', to: 'projects#activities' resources :reports, only: %i(index show), path: 'reports', as: :reports resources :experiments, only: %i(index show create update) do - resources :experiment_user_assignments, only: %i(index show create update) + resources :user_assignments, + only: %i(index show create update), + controller: :experiment_user_assignments resources :task_groups, only: %i(index show) resources :connections, only: %i(index show) resources :tasks, only: %i(index show create update) do - resources :tasks_user_assignments, only: %i(index show create update) + resources :user_assignments, + only: %i(index show create update), + controller: :task_user_assignments resources :task_inventory_items, only: %i(index show), path: 'items', as: :items diff --git a/spec/requests/api/v1/experiment_user_assignments_controller_spec.rb b/spec/requests/api/v1/experiment_user_assignments_controller_spec.rb new file mode 100644 index 000000000..f8fa5934d --- /dev/null +++ b/spec/requests/api/v1/experiment_user_assignments_controller_spec.rb @@ -0,0 +1,330 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe "Api::V1::ExperimentUserAssignmentsController", type: :request do + before :all do + @user = create(:user) + @another_user = create(:user) + @team = create(:team, created_by: @user) + @normal_user_role = create :normal_user_role + @owner_role = create :owner_role + create(:user_team, user: @user, team: @team, role: :normal_user) + create(:user_team, user: @another_user, team: @team, role: :normal_user) + @own_project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @team) + @own_experiment = create :experiment, + name: Faker::Name.unique.name, + project: @own_project, + created_by: @user + @invalid_project = create :project, + name: Faker::Name.unique.name, + created_by: @another_user, + team: @team, + visibility: :hidden + @invalid_experiment = create :experiment, + name: Faker::Name.unique.name, + project: @invalid_project, + created_by: @another_user + create :user_project, user: @user, project: @own_project + create :user_assignment, assignable: @own_project, user: @user, user_role: @owner_role, assigned_by: @user + create :user_assignment, assignable: @own_experiment, user: @user, user_role: @owner_role, assigned_by: @user + create :technician_role + + @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } + end + + describe 'GET experiment_user_assignments, #index' do + it 'Response with correct user assignments' do + hash_body = nil + get api_v1_team_project_experiment_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@own_experiment.user_assignments, each_serializer: Api::V1::ExperimentUserAssignmentSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not an owner of the experiment' do + hash_body = nil + get api_v1_team_project_experiment_user_assignments_path( + team_id: @team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id), + headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing experiment' do + hash_body = nil + get api_v1_team_project_experiment_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'GET user_assignment, #show' do + it 'When valid request, user can read user assignment' do + hash_body = nil + get api_v1_team_project_experiment_user_assignment_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + id: @own_experiment.user_assignments.first.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@own_experiment.user_assignments.first, serializer: Api::V1::ExperimentUserAssignmentSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not member of the project' do + hash_body = nil + get api_v1_team_project_experiment_user_assignment_path( + team_id: @team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing project' do + hash_body = nil + get api_v1_team_project_experiment_user_assignment_path( + team_id: @team.id, + project_id: -1, + experiment_id: -1, + id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'POST user_assignment, #create' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + create :user_assignment, + assignable: @own_project, + user: @another_user, + user_role: @owner_role, + assigned_by: @user + end + + let(:action) do + post(api_v1_team_project_experiment_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id), + params: request_body.to_json, headers: @valid_headers) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: { + user_id: @another_user.id, + role: 'normal_user' + } + } + } + end + + it 'creates new user_assignment' do + expect { action }.to change { UserAssignment.count }.by(1) + end + + it 'returns status 201' do + action + + expect(response).to have_http_status 201 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'experiment_user_assignments', + attributes: hash_including(role: 'normal_user'), + relationships: hash_including(user: hash_including(data: hash_including(id: @another_user.id.to_s))) + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: {} + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + + context 'when user is not an owner of the project' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: { + user_id: @another_user.id, + role: 'normal_user' + } + } + } + end + + it 'renders 403' do + post( + api_v1_team_project_experiment_user_assignments_path( + team_id: @invalid_project.team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + + expect(response).to have_http_status(403) + end + end + end + + describe 'PATCH user_assignment, #update' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + @user_assignment = create :user_assignment, + assignable: @own_experiment, + user: @another_user, + user_role: @normal_user_role, + assigned_by: @user + end + + let(:action) do + patch( + api_v1_team_project_experiment_user_assignment_path( + team_id: @own_project.team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + id: @user_assignment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: { + role: :technician + } + } + } + end + + it 'returns status 200' do + action + + expect(response).to have_http_status 200 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'experiment_user_assignments', + attributes: hash_including(role: 'technician') + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + + context 'when user is not an owner of the project' do + let(:request_body) do + { + data: { + type: 'experiment_user_assignments', + attributes: { + role: :technician + } + } + } + end + + it 'renders 403' do + invalid_user_assignment = create :user_assignment, + assignable: @invalid_experiment, + user: @another_user, + user_role: @normal_user_role, + assigned_by: @another_user + + patch( + api_v1_team_project_experiment_user_assignment_path( + team_id: @invalid_project.team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + id: invalid_user_assignment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + + expect(response).to have_http_status(403) + end + end + end +end diff --git a/spec/requests/api/v1/task_user_assignments_controller_spec.rb b/spec/requests/api/v1/task_user_assignments_controller_spec.rb new file mode 100644 index 000000000..d24affc31 --- /dev/null +++ b/spec/requests/api/v1/task_user_assignments_controller_spec.rb @@ -0,0 +1,343 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe "Api::V1::TaskUserAssignmentsController", type: :request do + before :all do + @user = create(:user) + @another_user = create(:user) + @team = create(:team, created_by: @user) + @normal_user_role = create :normal_user_role + @owner_role = create :owner_role + create(:user_team, user: @user, team: @team, role: :normal_user) + create(:user_team, user: @another_user, team: @team, role: :normal_user) + @own_project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @team) + @own_experiment = create :experiment, + name: Faker::Name.unique.name, + project: @own_project, + created_by: @user + @own_task = create :my_module, name: Faker::Name.unique.name, experiment: @own_experiment + @invalid_project = create :project, + name: Faker::Name.unique.name, + created_by: @another_user, + team: @team, + visibility: :hidden + @invalid_experiment = create :experiment, + name: Faker::Name.unique.name, + project: @invalid_project, + created_by: @another_user + @invalid_task = create :my_module, name: Faker::Name.unique.name, experiment: @invalid_experiment + create :user_project, user: @user, project: @own_project + create :user_assignment, assignable: @own_project, user: @user, user_role: @owner_role, assigned_by: @user + create :user_assignment, assignable: @own_experiment, user: @user, user_role: @owner_role, assigned_by: @user + create :user_assignment, assignable: @own_task, user: @user, user_role: @owner_role, assigned_by: @user + create :technician_role + + @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } + end + + describe 'GET task_user_assignments, #index' do + it 'Response with correct user assignments' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + task_id: @own_task.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@own_task.user_assignments, each_serializer: Api::V1::TaskUserAssignmentSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not an owner of the task' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignments_path( + team_id: @team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + task_id: @invalid_task.id + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing task' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + task_id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'GET user_assignment, #show' do + it 'When valid request, user can read user assignment' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignment_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + task_id: @own_task.id, + id: @own_task.user_assignments.first.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@own_task.user_assignments.first, serializer: Api::V1::TaskUserAssignmentSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not member of the project' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignment_path( + team_id: @team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + task_id: @invalid_task.id, + id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing project' do + hash_body = nil + get api_v1_team_project_experiment_task_user_assignment_path( + team_id: @team.id, + project_id: -1, + experiment_id: -1, + task_id: -1, + id: -1 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'POST user_assignment, #create' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + create :user_assignment, + assignable: @own_project, + user: @another_user, + user_role: @owner_role, + assigned_by: @user + end + + let(:action) do + post(api_v1_team_project_experiment_task_user_assignments_path( + team_id: @team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + task_id: @own_task.id), + params: request_body.to_json, headers: @valid_headers) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: { + user_id: @another_user.id, + role: 'normal_user' + } + } + } + end + + it 'creates new user_assignment' do + expect { action }.to change { UserAssignment.count }.by(1) + end + + it 'returns status 201' do + action + + expect(response).to have_http_status 201 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'task_user_assignments', + attributes: hash_including(role: 'normal_user'), + relationships: hash_including(user: hash_including(data: hash_including(id: @another_user.id.to_s))) + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: {} + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + + context 'when user is not an owner of the project' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: { + user_id: @another_user.id, + role: 'normal_user' + } + } + } + end + + it 'renders 403' do + post( + api_v1_team_project_experiment_task_user_assignments_path( + team_id: @invalid_project.team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + task_id: @invalid_task.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + + expect(response).to have_http_status(403) + end + end + end + + describe 'PATCH user_assignment, #update' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + @user_assignment = create :user_assignment, + assignable: @own_task, + user: @another_user, + user_role: @normal_user_role, + assigned_by: @user + end + + let(:action) do + patch( + api_v1_team_project_experiment_task_user_assignment_path( + team_id: @own_project.team.id, + project_id: @own_project.id, + experiment_id: @own_experiment.id, + task_id: @own_task.id, + id: @user_assignment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: { + role: :technician + } + } + } + end + + it 'returns status 200' do + action + + expect(response).to have_http_status 200 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'task_user_assignments', + attributes: hash_including(role: 'technician') + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + + context 'when user is not an owner of the project' do + let(:request_body) do + { + data: { + type: 'task_user_assignments', + attributes: { + role: :technician + } + } + } + end + + it 'renders 403' do + invalid_user_assignment = create :user_assignment, + assignable: @invalid_task, + user: @another_user, + user_role: @normal_user_role, + assigned_by: @another_user + + patch( + api_v1_team_project_experiment_task_user_assignment_path( + team_id: @invalid_project.team.id, + project_id: @invalid_project.id, + experiment_id: @invalid_experiment.id, + task_id: @invalid_task.id, + id: invalid_user_assignment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + + expect(response).to have_http_status(403) + end + end + end +end diff --git a/spec/requests/api/v1/user_projects_controller_spec.rb b/spec/requests/api/v1/user_projects_controller_spec.rb index 48448facb..5e560b947 100644 --- a/spec/requests/api/v1/user_projects_controller_spec.rb +++ b/spec/requests/api/v1/user_projects_controller_spec.rb @@ -13,6 +13,8 @@ RSpec.describe "Api::V1::UserProjectsController", type: :request do @invalid_project = create(:project, name: Faker::Name.unique.name, created_by: @another_user, team: @team, visibility: :hidden) create(:user_project, role: :owner, user: @user, project: @own_project) + create :user_assignment, assignable: @own_project, user: @user, user_role: create(:owner_role), assigned_by: @user + @normal_user_role = create :normal_user_role @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } end @@ -177,7 +179,13 @@ RSpec.describe "Api::V1::UserProjectsController", type: :request do describe 'PATCH user_project, #update' do before :all do @valid_headers['Content-Type'] = 'application/json' - @user_project = create(:user_project, role: :normal_user, user: @another_user, project: @own_project) + @user_project = create(:user_project, user: @another_user, project: @own_project) + create :user_assignment, + assignable: @own_project, + user: @another_user, + user_role: @normal_user_role, + assigned_by: @user + create :technician_role end let(:action) do