Skip to content

Commit d456c3f

Browse files
Merge pull request #1268 from travis-ci/bug-fix-cycle-14
Bug fix cycle 14
2 parents d79dee8 + 8c8a53f commit d456c3f

File tree

8 files changed

+77
-12
lines changed

8 files changed

+77
-12
lines changed

lib/travis/api/app/access_token.rb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
class Travis::Api::App
55
class AccessToken
66
DEFAULT_SCOPES = [:public, :private]
7-
attr_reader :token, :scopes, :user_id, :app_id, :expires_in, :extra
7+
attr_reader :token, :travis_token, :scopes, :user_id, :app_id, :expires_in, :extra
88

99
def self.create(options = {})
1010
new(options).tap(&:save)
1111
end
1212

1313
def self.for_travis_token(travis_token, options = {})
1414
travis_token = Token.find_by_token(travis_token) unless travis_token.respond_to? :user
15-
new(scope: :travis_token, app_id: 1, user: travis_token.user).tap(&:save) if travis_token
15+
new(scope: :travis_token, app_id: 1, user: travis_token.user, travis_token: travis_token).tap(&:save) if travis_token
1616
end
1717

1818
def self.find_by_token(token)
@@ -32,12 +32,13 @@ def initialize(options = {})
3232
raise ArgumentError, 'expires_in must be of integer type'
3333
end
3434

35-
@app_id = Integer(options[:app_id])
36-
@scopes = Array(options[:scopes] || options[:scope] || DEFAULT_SCOPES).map(&:to_sym)
37-
@user = options[:user]
38-
@user_id = Integer(options[:user_id] || @user.id)
39-
@token = options[:token] || reuse_token || SecureRandom.urlsafe_base64(16)
40-
@extra = options[:extra]
35+
@app_id = Integer(options[:app_id])
36+
@scopes = Array(options[:scopes] || options[:scope] || DEFAULT_SCOPES).map(&:to_sym)
37+
@user = options[:user]
38+
@user_id = Integer(options[:user_id] || @user.id)
39+
@token = options[:token] || reuse_token || SecureRandom.urlsafe_base64(16)
40+
@travis_token = options[:travis_token]
41+
@extra = options[:extra]
4142
end
4243

4344
def save

lib/travis/api/app/endpoint/authorization.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ def update_first_login(user)
153153

154154
def serialize_user(user)
155155
rendered = Travis::Api::Serialize.data(user, version: :v2)
156-
rendered['user'].merge('token' => user.tokens.first.try(:token).to_s)
156+
token = user.tokens.asset.first.try(:token).to_s
157+
rendered['user'].merge(
158+
'token' => token,
159+
'rss_token' => user.tokens.rss.first.try(:token) || token,
160+
)
157161
end
158162

159163
def oauth_endpoint

lib/travis/api/app/endpoint/repos.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class RepoStatus < Endpoint
2222
end
2323

2424
get '/:owner_name/:name/builds', scope: [:public, :travis_token] do
25+
halt 401 if scope == :travis_token && access_token.travis_token && !access_token.travis_token.rss? && access_token.user.tokens.rss.exists?
26+
2527
respond_with service(:find_builds, params), responder: :atom, responders: :atom
2628
end
2729

lib/travis/model/token.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
# one) that they need use on their service hooks. This gives us some security
88
# that people cannot throw random repositories at Travis CI.
99
class Token < Travis::Model
10+
enum purpose: [ :asset, :rss ]
11+
1012
belongs_to :user
1113

1214
validates :token, :presence => true

lib/travis/model/user.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class User < Travis::Model
1616
has_many :custom_keys, as: :owner
1717

1818
before_create :set_as_recent
19-
after_create :create_a_token
19+
after_create :create_the_tokens
2020
before_save :track_previous_changes
2121

2222
serialize :github_scopes
@@ -164,8 +164,9 @@ def inspect
164164
github_oauth_token ? super.gsub(github_oauth_token, '[REDACTED]') : super
165165
end
166166

167-
def create_a_token
168-
self.tokens.create!
167+
def create_the_tokens
168+
self.tokens.asset.create! unless self.tokens.asset.exists?
169+
self.tokens.rss.create!
169170
end
170171

171172
def github?

spec/lib/model/user_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,13 @@ def user(payload)
182182
end
183183
end
184184
end
185+
186+
describe 'tokens' do
187+
let(:user) { FactoryBot.create(:user) }
188+
189+
it 'creates two tokens on creation' do
190+
expect(user.tokens.asset.count).to eq(1)
191+
expect(user.tokens.rss.count).to eq(1)
192+
end
193+
end
185194
end

spec/unit/access_token_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,15 @@
4444
token = described_class.find_by_token(token.token)
4545
expect(token.extra).to eq({ 'required_params' => { 'job_id' => '1' } })
4646
end
47+
48+
it 'allows to save travis token' do
49+
attrs = {
50+
app_id: 1,
51+
user_id: 3,
52+
travis_token: Token.new
53+
}
54+
55+
token = described_class.new(attrs).tap(&:save)
56+
expect(token.travis_token).to eq(attrs[:travis_token])
57+
end
4758
end

spec/unit/endpoint/repos_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,39 @@
4848
end
4949
end
5050
end
51+
52+
describe 'builds endpoint' do
53+
let(:user) { FactoryBot.create(:user) }
54+
let(:repo) { FactoryBot.create(:repository, private: false, owner_name: 'user', name: 'repo') }
55+
56+
before { user.permissions.create(repository_id: repo.id, push: false) }
57+
58+
context 'when user is authorizing with token' do
59+
context 'and token is not a RSS one' do
60+
let(:token) { user.tokens.asset.first }
61+
62+
context 'and user has a RSS token' do
63+
it 'responds with 401' do
64+
expect(get("/repo_status/#{repo.owner_name}/#{repo.name}/builds.atom?token=#{token.token}", {}, {}).status).to eq(401)
65+
end
66+
end
67+
68+
context 'and user does not have a RSS token' do
69+
before { user.tokens.rss.delete_all }
70+
71+
it 'responds with 200' do
72+
expect(get("/repo_status/#{repo.owner_name}/#{repo.name}/builds.atom?token=#{token.token}", {}, {}).status).to eq(200)
73+
end
74+
end
75+
end
76+
77+
context 'and token is a RSS one' do
78+
let(:token) { user.tokens.rss.first }
79+
80+
it 'responds with 200' do
81+
expect(get("/repo_status/#{repo.owner_name}/#{repo.name}/builds.atom?token=#{token.token}", {}, {}).status).to eq(200)
82+
end
83+
end
84+
end
85+
end
5186
end

0 commit comments

Comments
 (0)