Skip to content

Commit 8c8a53f

Browse files
committed
Merge branch 'master' into bug-fix-cycle-14
2 parents 4fdb9b3 + d79dee8 commit 8c8a53f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1268
-34
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ GEM
325325
rb-fsevent (0.9.8)
326326
rb-inotify (0.10.1)
327327
ffi (~> 1.0)
328-
rbtrace (0.4.12)
328+
rbtrace (0.4.14)
329329
ffi (>= 1.0.6)
330330
msgpack (>= 0.4.3)
331331
optimist (>= 3.0.0)

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
class Travis::Api::App
44
class SettingsEndpoint < Endpoint
5+
include ActiveSupport::Callbacks
6+
7+
define_callbacks :after_save
8+
9+
set_callback :after_save, :after, :save_audit
510
set(:prefix) { "/settings/" << name[/[^:]+$/].underscore }
611

712
class << self
@@ -38,6 +43,7 @@ def define_routes!
3843
# Rails style methods for easy overriding
3944
def index
4045
respond_with(collection, type: name, version: :v2)
46+
4147
end
4248

4349
def show
@@ -48,9 +54,12 @@ def update
4854
disallow_migrating!(repo)
4955

5056
record.update(JSON.parse(request.body.read)[singular_name])
51-
5257
if record.valid?
58+
@changes = { :"env_vars" => { created: "name: #{record.name}, is_public: #{record.public}, branch: #{record.branch || 'all'} " } } if is_env_var?
59+
5360
repo_settings.save
61+
run_callbacks :after_save if is_env_var?
62+
5463
respond_with(record, type: singular_name, version: :v2)
5564
else
5665
status 422
@@ -62,9 +71,12 @@ def create
6271
disallow_migrating!(repo)
6372

6473
record = collection.create(JSON.parse(request.body.read)[singular_name])
65-
6674
if record.valid?
75+
@changes = { :"env_vars" => { created: "name: #{record.name}, is_public: #{record.public}, branch: #{record.branch || 'all'}" } } if is_env_var?
76+
6777
repo_settings.save
78+
run_callbacks :after_save if is_env_var?
79+
6880
respond_with(record, type: singular_name, version: :v2)
6981
else
7082
status 422
@@ -76,7 +88,11 @@ def destroy
7688
disallow_migrating!(repo)
7789

7890
record = collection.destroy(params[:id]) || record_not_found
91+
@changes = { :"env_vars" => { destroyed: "name: #{record.name}, is_public: #{record.public}, branch: #{record.branch || 'all'} " } } if is_env_var?
92+
7993
repo_settings.save
94+
run_callbacks :after_save if is_env_var?
95+
8096
respond_with(record, type: singular_name, version: :v2)
8197
end
8298

@@ -89,7 +105,7 @@ def collection
89105
end
90106

91107
def repo
92-
Repository.find(params[:repository_id])
108+
@repo = Repository.find(params[:repository_id])
93109
end
94110

95111
# This method can't be called "settings" because it clashes with
@@ -107,5 +123,21 @@ def record
107123
def record_not_found
108124
halt(404, { error: "Could not find a requested setting" })
109125
end
126+
127+
def changes
128+
@changes
129+
end
130+
131+
def is_env_var?
132+
singular_name == 'env_var'
133+
end
134+
135+
private
136+
137+
def save_audit
138+
change_source = access_token.app_id == 2 ? 'admin-v2' : 'travis-api'
139+
Travis::API::V3::Models::Audit.create!(owner: current_user, change_source: change_source, source: @repo, source_changes: { settings: self.changes })
140+
@changes = {}
141+
end
110142
end
111143
end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module Travis::API::V3
2+
class Models::CustomKey < Model
3+
belongs_to :owner, polymorphic: true
4+
5+
serialize :private_key, Travis::Model::EncryptedColumn.new
6+
7+
validates_each :private_key do |record, attr, private_key|
8+
record.errors.add(attr, :missing_attr, message: 'missing_attr') if private_key.blank?
9+
record.errors.add(attr, :invalid_pem, message: 'invalid_pem') unless record.valid_pem?
10+
end
11+
12+
def save_key!(owner_type, owner_id, name, description, private_key, added_by)
13+
self.owner_type = owner_type
14+
self.owner_id = owner_id
15+
self.private_key = private_key
16+
self.name = name
17+
self.description = description
18+
self.added_by = added_by
19+
20+
if self.valid?
21+
self.fingerprint = calculate_fingerprint(private_key)
22+
self.public_key = OpenSSL::PKey::RSA.new(private_key).public_key.to_s
23+
24+
self.save!
25+
end
26+
27+
self
28+
end
29+
30+
def valid_pem?
31+
private_key && OpenSSL::PKey::RSA.new(private_key)
32+
true
33+
rescue OpenSSL::PKey::RSAError
34+
false
35+
end
36+
37+
private
38+
39+
def calculate_fingerprint(source)
40+
rsa_key = OpenSSL::PKey::RSA.new(source)
41+
public_ssh_rsa = "\x00\x00\x00\x07ssh-rsa" + rsa_key.e.to_s(0) + rsa_key.n.to_s(0)
42+
OpenSSL::Digest::MD5.new(public_ssh_rsa).hexdigest.scan(/../).join(':')
43+
end
44+
end
45+
end

lib/travis/api/v3/models/env_vars.rb

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@
22

33
module Travis::API::V3
44
class Models::EnvVars < Travis::Settings::Collection
5-
include Models::JsonSync
5+
include Models::JsonSync, ActiveSupport::Callbacks
6+
extend ActiveSupport::Concern
67
model Models::EnvVar
8+
define_callbacks :after_save
79

10+
set_callback :after_save, :after, :save_audit
11+
12+
attr_accessor :user, :change_source
813
# See Models::JsonSync
914
def to_h
1015
{ 'env_vars' => map(&:to_h).map(&:stringify_keys) }
1116
end
1217

1318
def create(attributes)
14-
super(attributes).tap { sync! }
19+
@changes = { :"env_vars" => { created: "#{attributes.except("value")}" } }
20+
env_var = super(attributes).tap { sync! }
21+
run_callbacks :after_save
22+
env_var
1523
end
1624

1725
def add(env_var)
@@ -20,11 +28,28 @@ def add(env_var)
2028
end
2129

2230
def destroy(id)
23-
super(id).tap { sync! }
31+
env_var = find(id)
32+
@changes = { :"env_vars" => { deleted: "#{env_var.attributes.delete("value")}" } }
33+
deleted_env_var = super(id).tap { sync! }
34+
run_callbacks :after_save
35+
deleted_env_var
2436
end
2537

2638
def repository
2739
@repository ||= Models::Repository.find(additional_attributes[:repository_id])
2840
end
41+
42+
def changes
43+
@changes
44+
end
45+
46+
private
47+
48+
def save_audit
49+
if self.change_source
50+
Travis::API::V3::Models::Audit.create!(owner: self.user, change_source: self.change_source, source: self.repository, source_changes: { settings: self.changes })
51+
@changes = {}
52+
end
53+
end
2954
end
3055
end

lib/travis/api/v3/models/organization.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ def build_priorities_enabled?
2929
Travis::Features.owner_active?(:build_priorities_org, self)
3030
end
3131

32+
def custom_keys
33+
return @custom_keys if defined? @custom_keys
34+
@custom_keys = Models::CustomKey.where(owner_type: 'Organization', owner_id: id)
35+
end
36+
3237
alias members users
3338
end
3439
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
module Travis::API::V3
3+
class Models::ScanResult
4+
attr_reader :id, :log_id, :job_id, :owner_id, :owner_type, :created_at, :formatted_content, :issues_found, :archived, :purged_at,
5+
:job_number, :build_id, :build_number, :job_finished_at, :commit_sha, :commit_compare_url, :commit_branch, :repository_id
6+
7+
def initialize(attributes = {})
8+
@id = attributes.fetch('id')
9+
@log_id = attributes.fetch('log_id')
10+
@job_id = attributes.fetch('job_id')
11+
@owner_id = attributes.fetch('owner_id')
12+
@owner_type = attributes.fetch('owner_type')
13+
@created_at = attributes.fetch('created_at')
14+
@formatted_content = attributes.fetch('formatted_content')
15+
@issues_found = attributes.fetch('issues_found')
16+
@archived = attributes.fetch('archived')
17+
@purged_at = attributes.fetch('purged_at')
18+
@job_number = attributes.fetch('job_number')
19+
@build_id = attributes.fetch('build_id')
20+
@build_number = attributes.fetch('build_number')
21+
@job_finished_at = attributes.fetch('job_finished_at')
22+
@commit_sha = attributes.fetch('commit_sha')
23+
@commit_compare_url = attributes.fetch('commit_compare_url')
24+
@commit_branch = attributes.fetch('commit_branch')
25+
@repository_id = attributes.fetch('repository_id')
26+
end
27+
end
28+
end
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
3+
module Travis::API::V3
4+
class Models::ScannerCollection
5+
def initialize(collection, total_count)
6+
@collection = collection
7+
@total_count = total_count
8+
end
9+
10+
def count(*)
11+
@total_count
12+
end
13+
14+
def limit(*)
15+
self
16+
end
17+
18+
def offset(*)
19+
self
20+
end
21+
22+
def map
23+
return @collection.map unless block_given?
24+
25+
@collection.map { |x| yield x }
26+
end
27+
28+
def to_sql
29+
"scanner_query:#{Time.now.to_i}"
30+
end
31+
end
32+
end

lib/travis/api/v3/models/user.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,10 @@ def installation
8282
def github?
8383
vcs_type == 'GithubUser'
8484
end
85+
86+
def custom_keys
87+
return @custom_keys if defined? @custom_keys
88+
@custom_keys = Models::CustomKey.where(owner_type: 'User', owner_id: id)
89+
end
8590
end
8691
end

lib/travis/api/v3/permissions/repository.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def create_request?
4242
write?
4343
end
4444

45+
def check_scan_results?
46+
write?
47+
end
48+
4549
def admin?
4650
access_control.adminable? object
4751
end
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module Travis::API::V3
2+
class Queries::CustomKey < Query
3+
def create(params, current_user)
4+
raise UnprocessableEntity, 'Key with this identifier already exists.' unless Travis::API::V3::Models::CustomKey.where(name: params['name'], owner_id: params['owner_id'], owner_type: params['owner_type']).count.zero?
5+
6+
if params['owner_type'] == 'User'
7+
org_ids = User.find(params['owner_id']).organizations.map(&:id)
8+
9+
raise UnprocessableEntity, 'Key with this identifier already exists in one of your organizations.' unless Travis::API::V3::Models::CustomKey.where(name: params['name'], owner_id: org_ids, owner_type: 'Organization').count.zero?
10+
elsif params['owner_type'] == 'Organization'
11+
user_ids = Membership.where(organization_id: params['owner_id']).map(&:user_id)
12+
13+
raise UnprocessableEntity, 'Key with this identifier already exists for your user.' unless Travis::API::V3::Models::CustomKey.where(name: params['name'], owner_id: user_ids, owner_type: 'User').count.zero?
14+
end
15+
16+
key = Travis::API::V3::Models::CustomKey.new.save_key!(
17+
params['owner_type'],
18+
params['owner_id'],
19+
params['name'],
20+
params['description'],
21+
params['private_key'],
22+
params['added_by']
23+
)
24+
handle_errors(key) unless key.valid?
25+
26+
Travis::API::V3::Models::Audit.create!(
27+
owner: current_user,
28+
change_source: 'travis-api',
29+
source: key,
30+
source_changes: {
31+
action: 'create',
32+
fingerprint: key.fingerprint
33+
}
34+
)
35+
36+
key
37+
end
38+
39+
def delete(params, current_user)
40+
key = Travis::API::V3::Models::CustomKey.find(params['id'])
41+
Travis::API::V3::Models::Audit.create!(
42+
owner: current_user,
43+
change_source: 'travis-api',
44+
source: key,
45+
source_changes: {
46+
action: 'delete',
47+
name: key.name,
48+
owner_type: key.owner_type,
49+
owner_id: key.owner_id,
50+
fingerprint: key.fingerprint
51+
}
52+
)
53+
54+
key.destroy
55+
end
56+
57+
private
58+
59+
def handle_errors(key)
60+
private_key = key.errors[:private_key]
61+
raise UnprocessableEntity, 'This key is not a private key.' if private_key.include?('invalid_pem')
62+
raise WrongParams if private_key.include?('missing_attr')
63+
end
64+
end
65+
end

0 commit comments

Comments
 (0)