From 952cfd15754e38c8e237f6e5e943cbd02faa5c76 Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Mon, 10 Oct 2022 14:43:17 +0300 Subject: [PATCH 1/8] Fix log token working with new log settings --- lib/travis/api/v3/access_control/log_token.rb | 3 ++- lib/travis/api/v3/log_token.rb | 14 +++++++++----- lib/travis/api/v3/renderer/log.rb | 2 +- lib/travis/api/v3/services/log/find.rb | 9 +++++++-- spec/v3/services/job/find_spec.rb | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/travis/api/v3/access_control/log_token.rb b/lib/travis/api/v3/access_control/log_token.rb index 91effec0ce..3da47dfc42 100644 --- a/lib/travis/api/v3/access_control/log_token.rb +++ b/lib/travis/api/v3/access_control/log_token.rb @@ -5,7 +5,7 @@ module Travis::API::V3 class AccessControl::LogToken < AccessControl::Generic auth_type('log.token') - attr_accessor :token + attr_accessor :token, :repo_can_write def self.for_request(type, token, env) new(token) @@ -13,6 +13,7 @@ def self.for_request(type, token, env) def initialize(token) self.token = token + self.repo_can_write = Travis::API::V3::LogToken.find(token).repo_can_write end def temp_access? diff --git a/lib/travis/api/v3/log_token.rb b/lib/travis/api/v3/log_token.rb index cfea1a20af..1c0ba88505 100644 --- a/lib/travis/api/v3/log_token.rb +++ b/lib/travis/api/v3/log_token.rb @@ -1,14 +1,17 @@ module Travis::API::V3 class LogToken - attr_accessor :job_id + attr_accessor :job_id, :repo_can_write def self.find(token) - new(redis.get("l:#{token}").to_i) + values = redis.smembers("l:#{token}") + new(values[0].to_i, !!values[1]) end - def self.create(job) + def self.create(job, user_id) + repo_can_write = !!job.repository.users.where(id: user_id, permissions: { push: true }).first + token = SecureRandom.urlsafe_base64(16) - redis.set("l:#{token}", job.id) + redis.sadd("l:#{token}", [job.id, repo_can_write]) redis.expire("l:#{token}", 1.day) token end @@ -17,8 +20,9 @@ def self.redis Travis.redis end - def initialize(job_id) + def initialize(job_id, repo_can_write) self.job_id = job_id + self.repo_can_write = repo_can_write end def matches?(job) diff --git a/lib/travis/api/v3/renderer/log.rb b/lib/travis/api/v3/renderer/log.rb index 603ad59896..99f94d8e7c 100644 --- a/lib/travis/api/v3/renderer/log.rb +++ b/lib/travis/api/v3/renderer/log.rb @@ -26,7 +26,7 @@ def render(representation) raw_log_href = "/v3#{raw_log_href}" end if enterprise? || model.repository_private? - token = LogToken.create(model.job) + token = LogToken.create(model.job, access_control&.user&.id) raw_log_href += "?log.token=#{token}" end result['@raw_log_href'] = raw_log_href diff --git a/lib/travis/api/v3/services/log/find.rb b/lib/travis/api/v3/services/log/find.rb index 040f59ee40..691bd3c60e 100644 --- a/lib/travis/api/v3/services/log/find.rb +++ b/lib/travis/api/v3/services/log/find.rb @@ -4,9 +4,14 @@ class Services::Log::Find < Service def run! job = Models::Job.find(params['job.id']) - repo_can_write = access_control.user ? !!job.repository.users.where(id: access_control.user.id, permissions: { push: true }).first : false - log = query.find(job) + repo_can_write = false + if access_control.is_a?(Travis::API::V3::AccessControl::LogToken) + repo_can_write = access_control.repo_can_write + elsif access_control.user + repo_can_write = !!job.repository.users.where(id: access_control.user.id, permissions: { push: true }).first + end + raise(NotFound, :log) unless access_control.visible? log raise LogExpired if job.repository.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - job.repository.user_settings.job_log_access_older_than_days.days raise LogAccessDenied if job.repository.user_settings.job_log_access_based_limit && !repo_can_write diff --git a/spec/v3/services/job/find_spec.rb b/spec/v3/services/job/find_spec.rb index edcbe18cb5..b2bcf3a437 100644 --- a/spec/v3/services/job/find_spec.rb +++ b/spec/v3/services/job/find_spec.rb @@ -141,7 +141,7 @@ end describe "fetching job on private repository, private API, with a log.token" do - let(:log_token) { Travis::API::V3::LogToken.create(job).to_s } + let(:log_token) { Travis::API::V3::LogToken.create(job, owner.id).to_s } before { repo.update_attribute(:private, true) } before { get("/v3/job/#{job.id}?log.token=#{log_token}", {}, {}) } after { repo.update_attribute(:private, false) } From 53622d63f1f44c3bcd949ffb2c6f94aa8be4e862 Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Mon, 10 Oct 2022 17:15:34 +0300 Subject: [PATCH 2/8] Fix --- lib/travis/api/v3/log_token.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/travis/api/v3/log_token.rb b/lib/travis/api/v3/log_token.rb index 1c0ba88505..a657ce60e4 100644 --- a/lib/travis/api/v3/log_token.rb +++ b/lib/travis/api/v3/log_token.rb @@ -3,15 +3,16 @@ class LogToken attr_accessor :job_id, :repo_can_write def self.find(token) - values = redis.smembers("l:#{token}") - new(values[0].to_i, !!values[1]) + key = "l:#{token}" + new(redis.hget(key, :job_id).to_i, !!redis.hget(key, :repo_can_write)) end def self.create(job, user_id) repo_can_write = !!job.repository.users.where(id: user_id, permissions: { push: true }).first token = SecureRandom.urlsafe_base64(16) - redis.sadd("l:#{token}", [job.id, repo_can_write]) + redis.hset("l:#{token}", :job_id, job_id) + redis.hset("l:#{token}", :repo_can_write, repo_can_write) redis.expire("l:#{token}", 1.day) token end From 9aa99de7f444d8515ea9011799c939b032a167ea Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Mon, 10 Oct 2022 17:29:51 +0300 Subject: [PATCH 3/8] Fix --- lib/travis/api/v3/log_token.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/v3/log_token.rb b/lib/travis/api/v3/log_token.rb index a657ce60e4..7ed7201696 100644 --- a/lib/travis/api/v3/log_token.rb +++ b/lib/travis/api/v3/log_token.rb @@ -11,7 +11,7 @@ def self.create(job, user_id) repo_can_write = !!job.repository.users.where(id: user_id, permissions: { push: true }).first token = SecureRandom.urlsafe_base64(16) - redis.hset("l:#{token}", :job_id, job_id) + redis.hset("l:#{token}", :job_id, job.id) redis.hset("l:#{token}", :repo_can_write, repo_can_write) redis.expire("l:#{token}", 1.day) token From 85f4d925e0b473fbb136fa7493b8315d5e7a228b Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Tue, 11 Oct 2022 10:36:13 +0300 Subject: [PATCH 4/8] Fix condition --- lib/travis/api/app/endpoint/logs.rb | 2 +- lib/travis/api/v3/services/log/find.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/app/endpoint/logs.rb b/lib/travis/api/app/endpoint/logs.rb index 6160df95f5..83407e0578 100644 --- a/lib/travis/api/app/endpoint/logs.rb +++ b/lib/travis/api/app/endpoint/logs.rb @@ -14,7 +14,7 @@ class Logs < Endpoint repo = Travis::API::V3::Models::Repository.find(job.repository.id) repo_can_write = current_user ? !!repo.users.where(id: current_user.id, permissions: { push: true }).first : false - raise LogExpired if repo.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - repo.user_settings.job_log_access_older_than_days.days + raise LogExpired if !repo.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - repo.user_settings.job_log_access_older_than_days.days raise LogAccessDenied if repo.user_settings.job_log_access_based_limit && !repo_can_write if !resource || ((job.try(:private?) || !allow_public?) && !has_permission?(job)) diff --git a/lib/travis/api/v3/services/log/find.rb b/lib/travis/api/v3/services/log/find.rb index 691bd3c60e..0878bf8a26 100644 --- a/lib/travis/api/v3/services/log/find.rb +++ b/lib/travis/api/v3/services/log/find.rb @@ -13,7 +13,7 @@ def run! end raise(NotFound, :log) unless access_control.visible? log - raise LogExpired if job.repository.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - job.repository.user_settings.job_log_access_older_than_days.days + raise LogExpired if !job.repository.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - job.repository.user_settings.job_log_access_older_than_days.days raise LogAccessDenied if job.repository.user_settings.job_log_access_based_limit && !repo_can_write result log From 120099003a9cf9c34bb8a6d1c826d8afe6fd4b98 Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Tue, 11 Oct 2022 10:56:45 +0300 Subject: [PATCH 5/8] Fix spec --- lib/travis/api/app/endpoint/logs.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/app/endpoint/logs.rb b/lib/travis/api/app/endpoint/logs.rb index 83407e0578..f00c45ec77 100644 --- a/lib/travis/api/app/endpoint/logs.rb +++ b/lib/travis/api/app/endpoint/logs.rb @@ -14,8 +14,13 @@ class Logs < Endpoint repo = Travis::API::V3::Models::Repository.find(job.repository.id) repo_can_write = current_user ? !!repo.users.where(id: current_user.id, permissions: { push: true }).first : false - raise LogExpired if !repo.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - repo.user_settings.job_log_access_older_than_days.days - raise LogAccessDenied if repo.user_settings.job_log_access_based_limit && !repo_can_write + if !repo.user_settings.job_log_time_based_limit && job.started_at && job.started_at < Time.now - repo.user_settings.job_log_access_older_than_days.days + halt 403, { error: { message: "We're sorry, but this data is not available anymore. Please check the repository settings in Travis CI." } } + end + + if repo.user_settings.job_log_access_based_limit && !repo_can_write + halt 403, { error: { message: "We're sorry, but this data is not available. Please check the repository settings in Travis CI." } } + end if !resource || ((job.try(:private?) || !allow_public?) && !has_permission?(job)) halt 404 From c5b26790a59828c26dfcd1064eed7cbfe880d1a1 Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Tue, 11 Oct 2022 11:14:35 +0300 Subject: [PATCH 6/8] Fix spec --- spec/auth/v1/logs_spec.rb | 7 ++++++- spec/auth/v2.1/logs_spec.rb | 3 +++ spec/auth/v2/logs_spec.rb | 3 +++ spec/integration/visibility_spec.rb | 5 +++++ spec/v3/services/log/find_spec.rb | 3 +++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/spec/auth/v1/logs_spec.rb b/spec/auth/v1/logs_spec.rb index 3a9efddf9d..1e2ea54378 100644 --- a/spec/auth/v1/logs_spec.rb +++ b/spec/auth/v1/logs_spec.rb @@ -6,7 +6,12 @@ let(:log) { double(id: 1) } let(:log_url) { "#{Travis.config[:logs_api][:url]}/logs/1?by=id&source=api" } - before { stub_request(:get, log_url).to_return(status: 200, body: %({"job_id": #{job.id}, "content": "content"})) } + before do + stub_request(:get, log_url).to_return(status: 200, body: %({"job_id": #{job.id}, "content": "content"})) + repository = Travis::API::V3::Models::Repository.find(repo.id) + repository.user_settings.update(:job_log_time_based_limit, true) + repository.save! + end describe 'in public mode, with a private repo', mode: :public, repo: :private do describe 'GET /logs/%{log.id}' do diff --git a/spec/auth/v2.1/logs_spec.rb b/spec/auth/v2.1/logs_spec.rb index a65a797bea..588676c093 100644 --- a/spec/auth/v2.1/logs_spec.rb +++ b/spec/auth/v2.1/logs_spec.rb @@ -32,6 +32,9 @@ allow(remote).to receive(:find_by_job_id).and_return(Travis::RemoteLog.new(log_from_api)) allow(remote).to receive(:find_by_id).and_return(Travis::RemoteLog.new(log_from_api)) allow(remote).to receive(:fetch_archived_log_content).and_return(archived_content) + repository = Travis::API::V3::Models::Repository.find(repo.id) + repository.user_settings.update(:job_log_time_based_limit, true) + repository.save! end describe 'in public mode, with a private repo', mode: :public, repo: :private do diff --git a/spec/auth/v2/logs_spec.rb b/spec/auth/v2/logs_spec.rb index 2ba65afc75..cae31da587 100644 --- a/spec/auth/v2/logs_spec.rb +++ b/spec/auth/v2/logs_spec.rb @@ -32,6 +32,9 @@ allow(remote).to receive(:find_by_job_id).and_return(Travis::RemoteLog.new(log_from_api)) allow(remote).to receive(:find_by_id).and_return(Travis::RemoteLog.new(log_from_api)) allow(remote).to receive(:fetch_archived_log_content).and_return(archived_content) + repository = Travis::API::V3::Models::Repository.find(repo.id) + repository.user_settings.update(:job_log_time_based_limit, true) + repository.save! end describe 'in public mode, with a private repo', mode: :public, repo: :private do diff --git a/spec/integration/visibility_spec.rb b/spec/integration/visibility_spec.rb index ae6afb023a..d57fa5ecc2 100644 --- a/spec/integration/visibility_spec.rb +++ b/spec/integration/visibility_spec.rb @@ -16,6 +16,11 @@ before { requests[0].update_attributes(private: false) } before { builds[0].update_attributes(private: false) } before { jobs[0].update_attributes(private: false) } + before do + repository = Travis::API::V3::Models::Repository.find(repo.id) + repository.user_settings.update(:job_log_time_based_limit, true) + repository.save! + end before :each do Fog.mock! storage = Fog::Storage.new({ diff --git a/spec/v3/services/log/find_spec.rb b/spec/v3/services/log/find_spec.rb index cf19db14ad..397063cc46 100644 --- a/spec/v3/services/log/find_spec.rb +++ b/spec/v3/services/log/find_spec.rb @@ -82,6 +82,9 @@ remote = double('remote') allow(Travis::RemoteLog::Remote).to receive(:new).and_return(remote) allow(remote).to receive(:find_by_job_id).and_return(Travis::RemoteLog.new(log_from_api)) + repository = Travis::API::V3::Models::Repository.find(repo.id) + repository.user_settings.update(:job_log_time_based_limit, true) + repository.save! end after do Fog.unmock! From 4ba87109d5628632659b4458eefe5af72922910a Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Tue, 11 Oct 2022 11:26:02 +0300 Subject: [PATCH 7/8] Fix spec --- spec/v3/services/log/find_spec.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/spec/v3/services/log/find_spec.rb b/spec/v3/services/log/find_spec.rb index 397063cc46..f3fe17a2c7 100644 --- a/spec/v3/services/log/find_spec.rb +++ b/spec/v3/services/log/find_spec.rb @@ -82,9 +82,6 @@ remote = double('remote') allow(Travis::RemoteLog::Remote).to receive(:new).and_return(remote) allow(remote).to receive(:find_by_job_id).and_return(Travis::RemoteLog.new(log_from_api)) - repository = Travis::API::V3::Models::Repository.find(repo.id) - repository.user_settings.update(:job_log_time_based_limit, true) - repository.save! end after do Fog.unmock! @@ -227,7 +224,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, true) + user_settings.update(:job_log_time_based_limit, false) user_settings.update(:job_log_access_based_limit, false) end @@ -258,7 +255,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, true) + user_settings.update(:job_log_time_based_limit, false) user_settings.update(:job_log_access_based_limit, true) end @@ -316,7 +313,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, false) + user_settings.update(:job_log_time_based_limit, true) user_settings.update(:job_log_access_based_limit, true) end @@ -370,7 +367,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, false) + user_settings.update(:job_log_time_based_limit, true) user_settings.update(:job_log_access_based_limit, false) end @@ -402,7 +399,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, true) + user_settings.update(:job_log_time_based_limit, false) user_settings.update(:job_log_access_based_limit, false) end @@ -438,7 +435,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, true) + user_settings.update(:job_log_time_based_limit, false) user_settings.update(:job_log_access_based_limit, true) end @@ -497,7 +494,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, false) + user_settings.update(:job_log_time_based_limit, true) user_settings.update(:job_log_access_based_limit, true) end @@ -552,7 +549,7 @@ user_settings = Travis::API::V3::Models::Repository.find(repo.id).user_settings user_settings.user = user user_settings.change_source = 'travis-api' - user_settings.update(:job_log_time_based_limit, false) + user_settings.update(:job_log_time_based_limit, true) user_settings.update(:job_log_access_based_limit, false) end From e9bbb063f95a47f5d11c4e3a08ae7d2d33ff2871 Mon Sep 17 00:00:00 2001 From: AndriiMysko Date: Fri, 14 Oct 2022 11:20:31 +0300 Subject: [PATCH 8/8] Create log token for public repos with log access enabled --- lib/travis/api/v3/models/log.rb | 4 ++++ lib/travis/api/v3/renderer/log.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/models/log.rb b/lib/travis/api/v3/models/log.rb index 5f40f89c4d..2989d63124 100644 --- a/lib/travis/api/v3/models/log.rb +++ b/lib/travis/api/v3/models/log.rb @@ -27,6 +27,10 @@ def repository_private? job.repository.private? end + def repository + @repository ||= Travis::API::V3::Models::Repository.find(job.repository.id) + end + private def archived_log_part diff --git a/lib/travis/api/v3/renderer/log.rb b/lib/travis/api/v3/renderer/log.rb index 99f94d8e7c..459f3e7f1e 100644 --- a/lib/travis/api/v3/renderer/log.rb +++ b/lib/travis/api/v3/renderer/log.rb @@ -25,7 +25,7 @@ def render(representation) if raw_log_href !~ /^\/v3/ raw_log_href = "/v3#{raw_log_href}" end - if enterprise? || model.repository_private? + if enterprise? || model.repository_private? || model.repository.user_settings.job_log_access_based_limit token = LogToken.create(model.job, access_control&.user&.id) raw_log_href += "?log.token=#{token}" end