diff --git a/app/controllers/api/v1/projects_controller.rb b/app/controllers/api/v1/projects_controller.rb index c527e7761..8bc2ce54a 100644 --- a/app/controllers/api/v1/projects_controller.rb +++ b/app/controllers/api/v1/projects_controller.rb @@ -8,6 +8,7 @@ module Api load_project(:id) end before_action :load_project, only: :activities + before_action :load_project_for_managing, only: %i(update) def index projects = @team.projects @@ -22,6 +23,31 @@ module Api render jsonapi: @project, serializer: ProjectSerializer end + def create + raise PermissionError.new(Project, :create) unless can_create_projects?(@team) + + project = @team.projects.create!(project_params.merge!(created_by: current_user)) + + render jsonapi: project, serializer: ProjectSerializer, status: :created + end + + def update + @project.assign_attributes(project_params) + + return render body: nil, status: :no_content unless @project.changed? + + if @project.archived_changed? + if @project.archived? + @project.archived_by = current_user + else + @project.restored_by = current_user + end + end + @project.last_modified_by = current_user + @project.save! + render jsonapi: @project, serializer: ProjectSerializer, status: :ok + end + def activities activities = @project.activities .page(params.dig(:page, :number)) @@ -29,6 +55,19 @@ module Api render jsonapi: activities, each_serializer: ActivitySerializer end + + private + + def project_params + raise TypeError unless params.require(:data).require(:type) == 'projects' + + params.require(:data).require(:attributes).permit(:name, :visibility, :archived) + end + + def load_project_for_managing + @project = @team.projects.find(params.require(:id)) + raise PermissionError.new(Project, :manage) unless can_manage_project?(@project) + end end end end diff --git a/config/routes.rb b/config/routes.rb index 8e603000e..c74d99192 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -696,7 +696,7 @@ Rails.application.routes.draw do as: :cells end end - resources :projects, only: %i(index show) do + resources :projects, only: %i(index show create update) do resources :user_projects, only: %i(index show), path: 'users', as: :users resources :project_comments, only: %i(index show), diff --git a/spec/requests/api/v1/projects_controller_spec.rb b/spec/requests/api/v1/projects_controller_spec.rb index 4da003fe1..72a7d067e 100644 --- a/spec/requests/api/v1/projects_controller_spec.rb +++ b/spec/requests/api/v1/projects_controller_spec.rb @@ -9,10 +9,12 @@ RSpec.describe "Api::V1::ProjectsController", type: :request do create(:user_team, user: @user, team: @teams.first, role: 2) # valid_projects - create(:project, name: Faker::Name.unique.name, - created_by: @user, team: @teams.first) - create(:project, name: Faker::Name.unique.name, - created_by: @user, team: @teams.first) + create(:user_project, :owner, + user: @user, + project: create(:project, name: Faker::Name.unique.name, created_by: @user, team: @teams.first)) + create(:user_project, :owner, + user: @user, + project: create(:project, name: Faker::Name.unique.name, created_by: @user, team: @teams.first)) # unaccessable_projects create(:project, name: Faker::Name.unique.name, @@ -100,4 +102,139 @@ RSpec.describe "Api::V1::ProjectsController", type: :request do expect(hash_body['errors'][0]).to include('status': 404) end end + + describe 'POST project, #create' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + end + + let(:action) do + post(api_v1_team_projects_path(team_id: @teams.first.id), params: request_body.to_json, headers: @valid_headers) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'projects', + attributes: { + name: 'Project name', + visibility: 'hidden' + } + } + } + end + + it 'creates new project' do + expect { action }.to change { Project.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: 'projects', + attributes: hash_including(name: 'Project name', visibility: 'hidden') + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'projects', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + end + + describe 'PATCH project, #update' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + @project = @user.teams.first.projects.first + end + + let(:action) do + patch( + api_v1_team_project_path( + team_id: @project.team.id, + id: @project.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'projects', + attributes: { + name: 'New project name', + visibility: 'hidden', + archived: true + } + } + } + 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: 'projects', + attributes: hash_including(name: 'New project name', visibility: 'hidden', archived: true) + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'projects', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + end end