diff --git a/.gitignore b/.gitignore index ec389e2..d3c1559 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,6 @@ .byebug_history /.yardoc/ +/coverage/ /doc/ diff --git a/app/controllers/v1/spin_candidates_controller.rb b/app/controllers/v1/spin_candidates_controller.rb index 959ef05..754a4fd 100644 --- a/app/controllers/v1/spin_candidates_controller.rb +++ b/app/controllers/v1/spin_candidates_controller.rb @@ -35,19 +35,13 @@ def index ### # Show (id: identification of the spin) - # Provides a view of the spin - # TODO: When authenticated, provide extended info - # users//spins/ Get a specific spin of user + # Provides a view of the Spin Candidate + # + # @params id: integer id of the spin candidate def show - if params[:user_id] - @user = User.find_by_github_login(params[:user_id]) - return_response status: :not_found unless @user - @spin = SpinCandidate.find_by(user_id: @user.id, visible: true, id: params[:id]) || Spin.find_by(user_id: @user.id, visible: true, name: params[:id]) - else - @spin = SpinCandidate.find_by(id: params[:id], visible: true) || Spin.find_by(name: params[:id], visible: true) - end + @spin = SpinCandidate.find_by(user_id: current_user.id, id: params[:id]) unless @spin - render_error_exchange(:spin_not_found, :not_found) + render_error_exchange(:spin_candidate_not_found, :not_found) return end return_response @spin, :ok, {} diff --git a/app/jobs/refresh_spin_candidates_job.rb b/app/jobs/refresh_spin_candidates_job.rb index 41e6d57..5078d6d 100644 --- a/app/jobs/refresh_spin_candidates_job.rb +++ b/app/jobs/refresh_spin_candidates_job.rb @@ -39,7 +39,7 @@ def perform(user:, token:) full_name: repo.full_name, user: user, validation_log: "Pending validation") - if (spin_candidate.is_candidate? client: client) + if (spin_candidate.is_candidate? user: user) spin_candidate.save else spin_candidate.destroy unless spin_candidate.new_record? diff --git a/app/models/providers/github_manager.rb b/app/models/providers/github_manager.rb index ee9411c..739c70f 100644 --- a/app/models/providers/github_manager.rb +++ b/app/models/providers/github_manager.rb @@ -3,9 +3,9 @@ class GithubManager < BaseManager attr_reader :server_type, :github_access def initialize(provider) - Rails.logger.info 'Generating new connection to Source Control' + Rails.logger.info 'Generating new connection to GitHub' - github_url = provider[:enterprise] ? URI::HTTPS.build(host: provider[:server],path: "api/#{provider[:version]}") : URI::HTTPS.build(host: provider[:server]) + # github_url = provider[:enterprise] ? URI::HTTPS.build(host: provider[:server],path: "api/#{provider[:version]}") : URI::HTTPS.build(host: provider[:server]) github_url = URI::HTTPS.build(host: provider[:server]) opts = { @@ -17,7 +17,6 @@ def initialize(provider) } @github_access ||= Octokit::Client.new opts - @server_type = 'GitHub' end @@ -104,11 +103,10 @@ def candidate_spin?(full_name) raise Octokit::NotFound if @github_access.nil? begin # GitHub returns false when there is no content, or the content otherwise - not (@github_access.contents(full_name, path: '/.manageiq-spin', accept: 'application/vnd.github.raw') == false) - rescue Octokit::NotFound + not (@github_access.contents(full_name, path: '/.manageiq-spin') == false) + rescue Octokit::NotFound, Octokit::InvalidRepository return false end end - end end \ No newline at end of file diff --git a/app/models/spin_candidate.rb b/app/models/spin_candidate.rb index 7ba2eac..f51b7a3 100644 --- a/app/models/spin_candidate.rb +++ b/app/models/spin_candidate.rb @@ -1,15 +1,9 @@ class SpinCandidate < ApplicationRecord belongs_to :user + validates :full_name, :validation_log, presence: true - def is_candidate?(client:) - begin - raise Octokit::NotFound if client.github_access.nil? - if client.github_access.contents(full_name, path: '/.manageiq-spin') - true - end - rescue Octokit::NotFound - false - end + def is_candidate? user: + client = Providers::BaseManager.new(user.authentication_tokens.first.provider).get_connector + client.candidate_spin? full_name end - end diff --git a/app/serializers/v1/application_serializer.rb b/app/serializers/v1/application_serializer.rb index c97cc18..f2517a1 100644 --- a/app/serializers/v1/application_serializer.rb +++ b/app/serializers/v1/application_serializer.rb @@ -13,11 +13,11 @@ def attributes(*args) end def load_serialization_config_for(type = 'attributes') - @seed_data[@object.class.name.downcase.pluralize][type] + @seed_data[@object.class.name.tableize][type] end def serialization_columns - @serialization_columns ||= @seed_data[@object.class.name.downcase.pluralize]['columns'] + @serialization_columns ||= @seed_data[@object.class.name.tableize]['columns'] end def param_admin? diff --git a/app/serializers/v1/spin_candidate_serializer.rb b/app/serializers/v1/spin_candidate_serializer.rb new file mode 100644 index 0000000..21c2b9b --- /dev/null +++ b/app/serializers/v1/spin_candidate_serializer.rb @@ -0,0 +1,4 @@ +module V1 +class SpinCandidateSerializer < ApplicationSerializer + end +end diff --git a/app/serializers/v1/spin_serializer.rb b/app/serializers/v1/spin_serializer.rb index 509ce1e..d922ae8 100644 --- a/app/serializers/v1/spin_serializer.rb +++ b/app/serializers/v1/spin_serializer.rb @@ -1,4 +1,4 @@ module V1 - class SpinSerializer < ApplicationSerializer +class SpinSerializer < ApplicationSerializer end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 8e1ab81..d7745d9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -79,3 +79,10 @@ en: user_not_found: title: This user is not in the database detail: Maybe the id of user is wrong + spin_candidate_not_found: + title: Spin Candidate not found in the database + detail: Check that the id of the spin exists + spin_candidate_not_owner: + title: You don't have access to the Spin Candidate + detail: The user is wrong or the Spin Candidate does not exist + diff --git a/product/json_returns.yml b/product/json_returns.yml index 2b6df2b..23ebb5a 100644 --- a/product/json_returns.yml +++ b/product/json_returns.yml @@ -10,9 +10,17 @@ users: github_company: "company" spins: attributes: ["id","user_login", "name", "description", "watchers_count" ,"stargazers_count"] - expand: ["readme","license_name","license_html_url","license_key","default_branch","user_id", "clone_url", "forks_count", "open_issues_count", "metadata","releases"] - staff: ["created_at","updated_at"] + expand: ["readme", "license_name", "license_html_url", "license_key", "default_branch", "user_id", "clone_url", "forks_count", "open_issues_count", "metadata", "releases"] + staff: ["created_at", "updated_at"] admin: ["visible", "published"] columns: id: "id" +spin_candidates: + attributes: ["id", "full_name", "validation_log"] + expand: [] + staff: ["created_at", "updated_at"] + admin: [] + columns: + id: "id" + diff --git a/spec/factories/spin_candidates.rb b/spec/factories/spin_candidates.rb index 33d074f..134060e 100644 --- a/spec/factories/spin_candidates.rb +++ b/spec/factories/spin_candidates.rb @@ -1,5 +1,11 @@ FactoryBot.define do factory :spin_candidate do - + user + full_name { "#{user.github_login}/#{Faker::App.name.parameterize}" } + validation_log 'Pending validation' + + trait :validation_log_full do + validation_log { Faker::Lorem.sentence } + end end end diff --git a/spec/models/spin_candidate_spec.rb b/spec/models/spin_candidate_spec.rb index 45a63e7..16d3b57 100644 --- a/spec/models/spin_candidate_spec.rb +++ b/spec/models/spin_candidate_spec.rb @@ -1,18 +1,60 @@ require 'rails_helper' RSpec.describe SpinCandidate, type: :model do - context "when not authenticated " do - pending "index" - pending "show" - pending "refresh" + let(:spin_candidate) { FactoryBot.build(:spin_candidate) } + let!(:user) { FactoryBot.create(:user) } + let(:non_valid_repo) { 'ManageIQ-Exchange/manageiq-exchange' } + let(:nonexisting_repo) { 'ManageIQ-Exchange/i_do-not_exist' } + let(:valid_repo) { 'ManageIQ-Exchange/manageiq-exchange-spin-template' } + it 'has a valid factory' do + spin_candidate.valid? + expect(spin_candidate).to be_valid end - context "when authenticated" do - pending "index" - pending "show when valid id" - pending "show when invalid id" - pending "refresh when same repos" - pending "refresh when deleted repos" - pending "refresh when new repos" - pending "refresh when updated repos" + + it 'is not valid without a user' do + spin_candidate.user = nil + spin_candidate.valid? + expect(spin_candidate.errors.details[:user]).to include(error: :blank) + end + + it 'is not valid without a full name' do + spin_candidate.full_name = nil + spin_candidate.valid? + expect(spin_candidate.errors.details[:full_name]).to include(error: :blank) + end + + it 'is not valid without a validation_log' do + spin_candidate.validation_log = nil + spin_candidate.valid? + expect(spin_candidate.errors.details[:validation_log]).to include(error: :blank) + end + + it 'verifies a non-valid repo' do + spin_candidate.full_name = non_valid_repo + @user = user + api_basic_authorize + VCR.use_cassette('providers/github/spin_candidates/get-non-valid-repo') do + expect(spin_candidate.is_candidate?(user: user)).to be_falsy + end + + end + + it 'verifies a non-existing repo' do + spin_candidate.full_name = nonexisting_repo + @user = user + api_basic_authorize + VCR.use_cassette('providers/github/spin_candidates/get-non-existing-repo') do + expect(spin_candidate.is_candidate?(user: user)).to be_falsy + end + + end + + it 'verifies a valid repo' do + spin_candidate.full_name = valid_repo + @user = user + api_basic_authorize + VCR.use_cassette('providers/github/spin_candidates/get-valid-repo') do + expect(spin_candidate.is_candidate?(user: user)).to be_truthy + end end end diff --git a/spec/requests/v1/spin_candidate_spec.rb b/spec/requests/v1/spin_candidate_spec.rb new file mode 100644 index 0000000..27455a5 --- /dev/null +++ b/spec/requests/v1/spin_candidate_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +RSpec.describe 'V1::SpinCandidates', type: :request do + let!(:prefix) { 'v1' } + + context 'when not authenticated' do + it '#index returns 401' do + get "/#{prefix}/spin_candidates" + expect(response).to have_http_status(401) + end + + it '#show returns 401' do + get "/#{prefix}/spin_candidates/1" + expect(response).to have_http_status(401) + end + + it '#publish returns 401' do + post "/#{prefix}/spin_candidates/1/publish" + expect(response).to have_http_status(401) + end + + it '#refresh returns 401' do + post "/#{prefix}/spin_candidates/refresh" + expect(response).to have_http_status(401) + end + end + context 'when authenticated' do + let!(:user) { FactoryBot.create(:user) } + let!(:spin_candidate) { FactoryBot.create(:spin_candidate, user: user) } + let!(:spin_candidate1) { FactoryBot.create(:spin_candidate, user: user) } + + it '#index' do + @user = user + api_basic_authorize + get "/#{prefix}/spin_candidates" + expect(response).to have_http_status(:ok) + data = JSON.parse(response.body)["data"] + expect(data).to include ({"id" => spin_candidate.id, "full_name" => spin_candidate.full_name, "validation_log" => spin_candidate.validation_log}) + expect(data).to include ({"id" => spin_candidate1.id, "full_name" => spin_candidate1.full_name, "validation_log" => spin_candidate1.validation_log}) + end + + + it "show when valid id" do + @user = user + api_basic_authorize + get "/#{prefix}/spin_candidates/#{spin_candidate.id}" + expect(response).to have_http_status(:ok) + data = JSON.parse(response.body)["data"] + expect(data).to include ({"id" => spin_candidate.id, "full_name" => spin_candidate.full_name, "validation_log" => spin_candidate.validation_log}) + end + + it 'show when invalid id' do + @user = user + api_basic_authorize + get "/#{prefix}/spin_candidates/error" + expect(response).to have_http_status(:not_found) + end + pending "refresh when same repos" + pending "refresh when deleted repos" + pending "refresh when new repos" + pending "refresh when updated repos" + end +end diff --git a/spec/vcr_cassettes/providers/github/spins_candidates/get-index.yml b/spec/vcr_cassettes/providers/github/spins_candidates/get-index.yml new file mode 100644 index 0000000..3e8b22f --- /dev/null +++ b/spec/vcr_cassettes/providers/github/spins_candidates/get-index.yml @@ -0,0 +1,65 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.github.com/repos/mohamed-konopelski/cardguard/contents/.manageiq-spin?client_id=CLIENT-ID&client_secret=CLIENT-SECRET + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Octokit Ruby Gem 4.8.0 + Accept: + - application/vnd.github.v3+json + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 404 + message: Not Found + headers: + Server: + - GitHub.com + Date: + - Tue, 06 Feb 2018 10:54:50 GMT + Content-Type: + - application/json; charset=utf-8 + Transfer-Encoding: + - chunked + Status: + - 404 Not Found + X-Ratelimit-Limit: + - '5000' + X-Ratelimit-Remaining: + - '4996' + X-Ratelimit-Reset: + - '1517915401' + X-Github-Media-Type: + - github.v3; format=json + Access-Control-Expose-Headers: + - ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval + Access-Control-Allow-Origin: + - "*" + Content-Security-Policy: + - default-src 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-Xss-Protection: + - 1; mode=block + X-Runtime-Rack: + - '0.018148' + X-Github-Request-Id: + - DB47:2E705:4CD0E7:82AE7A:5A79897A + body: + encoding: ASCII-8BIT + string: '{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}' + http_version: + recorded_at: Tue, 06 Feb 2018 10:54:50 GMT +recorded_with: VCR 4.0.0