Merge pull request #292 from travis-ci/rlh_cleanup3

use the new method
This commit is contained in:
Renée Hendricksen 2016-07-14 19:54:25 -04:00 committed by GitHub
commit b31301ac1f
27 changed files with 79 additions and 174 deletions

View File

@ -1,109 +0,0 @@
require 'securerandom'
require 'base64'
module Travis::API::V3
module Extensions
class EncryptedColumn
attr_reader :disable, :options
alias disabled? disable
def initialize(options = {})
@options = options || {}
@disable = self.options[:disable]
@key = self.options[:key]
end
def enabled?
!disabled?
end
def load(data)
return nil unless data
data = data.to_s
decrypt?(data) ? decrypt(data) : data
end
def dump(data)
encrypt?(data) ? encrypt(data.to_s) : data
end
def key
@key || config.key
end
def iv
SecureRandom.hex(8)
end
def prefix
'--ENCR--'
end
def decrypt?(data)
data.present? && (!use_prefix? || prefix_used?(data))
end
def encrypt?(data)
data.present? && enabled?
end
def prefix_used?(data)
data[0..7] == prefix
end
def decrypt(data)
data = data[8..-1] if prefix_used?(data)
data = decode data
iv = data[-16..-1]
data = data[0..-17]
aes = create_aes :decrypt, key.to_s, iv
result = aes.update(data) + aes.final
end
def encrypt(data)
iv = self.iv
aes = create_aes :encrypt, key.to_s, iv
encrypted = aes.update(data) + aes.final
encrypted = "#{encrypted}#{iv}"
encrypted = encode encrypted
encrypted = "#{prefix}#{encrypted}" if use_prefix?
encrypted
end
def use_prefix?
options.has_key?(:use_prefix) ? options[:use_prefix] : Travis::Features.feature_inactive?(:db_encryption_prefix)
end
def create_aes(mode = :encrypt, key, iv)
aes = OpenSSL::Cipher::AES.new(256, :CBC)
aes.send(mode)
aes.key = key
aes.iv = iv
aes
end
def config
Travis.config.encryption
end
def decode(str)
Base64.strict_decode64 str
end
def encode(str)
Base64.strict_encode64 str
end
end
end
end

View File

@ -2,7 +2,7 @@ module Travis::API::V3
class Models::EnvVar < Travis::Settings::Model
attribute :id, Integer
attribute :name, String
attribute :value, String
attribute :value, Travis::Settings::EncryptedValue
attribute :public, Boolean
attribute :repository_id, Integer
@ -11,7 +11,7 @@ module Travis::API::V3
end
validates_each :id, :name do |record, attr, value|
others = record.repository.env_vars.select { |ev| ev.id != record.id }
others = record.repository.env_vars.select { |ev| ev.id != record.id }
record.errors.add(:base, :duplicate_resource) if others.find { |ev| ev.send(attr) == record.send(attr) }
end
end

View File

@ -2,7 +2,7 @@ module Travis::API::V3
class Models::SSLKey < Model
belongs_to :repository
serialize :private_key, Travis::API::V3::Extensions::EncryptedColumn.new
serialize :private_key, Travis::Settings::EncryptedColumn.new
def encoded_public_key
key = build_key.public_key

View File

@ -2,7 +2,7 @@ module Travis::API::V3
class Models::Token < Model
belongs_to :user
validate :token, presence: true
serialize :token, Extensions::EncryptedColumn.new(disable: true)
serialize :token, Travis::Settings::EncryptedColumn.new(disable: true)
before_validation :generate_token, on: :create
protected

View File

@ -9,7 +9,7 @@ module Travis::API::V3
has_many :stars
has_one :subscription, as: :owner
serialize :github_oauth_token, Extensions::EncryptedColumn.new(disable: true)
serialize :github_oauth_token, Travis::Settings::EncryptedColumn.new(disable: true)
def token
tokens.first_or_create.token

View File

@ -10,7 +10,7 @@ module Travis::API::V3
extend self
def clear(**args)
args.select { |key, value| !value.nil? }
args.compact
end
def href(type, string_args = nil, script_name: nil, **args)
@ -49,6 +49,7 @@ module Travis::API::V3
when Model then render_model(value, **options)
when ActiveRecord::Relation then render_value(value.to_a, **options)
when ActiveRecord::Associations::CollectionProxy then render_value(value.to_a, **options)
when Travis::Settings::EncryptedValue then value.decrypt
else raise ArgumentError, 'cannot render %p (%p)' % [value.class, value]
end
end

View File

@ -110,6 +110,7 @@ module Travis::API::V3
end
fields.each do |field|
next if field == :value && !@model.public?
value = Renderer.render_value(send(field),
access_control: access_control,
script_name: script_name,

View File

@ -68,7 +68,7 @@ module Travis::API::V3
def check_login_and_find(*args)
raise LoginRequired unless access_control.full_access_or_logged_in?
find(*args)
find(*args) or raise NotFound
end
def not_found(actually_not_found = false, type = nil)

View File

@ -2,8 +2,7 @@ module Travis::API::V3
class Services::Build::Cancel < Service
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless build = find(:build)
build = check_login_and_find(:build)
access_control.permissions(build).cancel!
query.cancel(access_control.user)

View File

@ -2,8 +2,7 @@ module Travis::API::V3
class Services::Build::Restart < Service
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless build = find(:build)
build = check_login_and_find(:build)
access_control.permissions(build).restart!
query.restart(access_control.user)

View File

@ -4,8 +4,7 @@ module Travis::API::V3
params :interval, :disable_by_build
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
raise NotFound unless branch = find(:branch, repository)
raise Error.new('Crons can only be set up for branches existing on GitHub!', status: 422) unless branch.exists_on_github
raise Error.new('Invalid value for interval. Interval must be "daily", "weekly" or "monthly"!', status: 422) unless ["daily", "weekly", "monthly"].include?(params["interval"])

View File

@ -3,8 +3,7 @@ module Travis::API::V3
#params :id
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
cron = find
cron = check_login_and_find
access_control.permissions(cron).delete!
cron.destroy
end

View File

@ -2,8 +2,7 @@ module Travis::API::V3
class Services::Job::Cancel < Service
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless job = find(:job)
job = check_login_and_find(:job)
access_control.permissions(job).cancel!
query.cancel(access_control.user)

View File

@ -5,8 +5,7 @@ module Travis::API::V3
attr_reader :job
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless @job = find(:job)
@job = check_login_and_find(:job)
raise WrongCredentials unless Travis.config.debug_tools_enabled or Travis::Features.active?(:debug_tools, job.repository)
access_control.permissions(job).debug!

View File

@ -2,8 +2,7 @@ module Travis::API::V3
class Services::Job::Restart < Service
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless job = find(:job)
job = check_login_and_find(:job)
access_control.permissions(job).restart!
query.restart(access_control.user)

View File

@ -1,8 +1,7 @@
module Travis::API::V3
class Services::Repository::Disable < Service
def run!(activate = false)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
check_access(repository)
admin = access_control.admin_for(repository)

View File

@ -1,8 +1,7 @@
module Travis::API::V3
class Services::Repository::Star < Service
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
check_access(repository)
current_user = access_control.user
query.star(current_user)

View File

@ -1,8 +1,7 @@
module Travis::API::V3
class Services::Repository::Unstar < Service
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
check_access(repository)
current_user = access_control.user
query.unstar(current_user)

View File

@ -8,8 +8,7 @@ module Travis::API::V3
params "request", "user", :config, :message, :branch, :token
def run
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
access_control.permissions(repository).create_request!
user = find(:user) if access_control.full_access? and params_for? 'user'.freeze

View File

@ -1,8 +1,7 @@
module Travis::API::V3
class Services::Settings::Find < Service
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repo = find(:repository)
repo = check_login_and_find(:repository)
find(:settings, repo)
end
end

View File

@ -3,8 +3,7 @@ module Travis::API::V3
params :builds_only_with_travis_yml, :build_pushes, :build_pull_requests, :maximum_number_of_builds, prefix: :settings
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
repository = check_login_and_find(:repository)
query.update(repository)
end
end

View File

@ -2,8 +2,7 @@ module Travis::API::V3
class Services::User::Sync < Service
def run!
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless user = find(:user)
user = check_login_and_find(:user)
access_control.permissions(user).sync!
query.sync(user)

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Delete, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: 'bar', public: true, repository_id: repo.id } }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
@ -28,6 +28,6 @@ describe Travis::API::V3::Services::EnvVar::Delete, set_app: true do
end
example { expect(last_response.status).to eq 200 }
example { pending 'should we return an empty body here?' }
example { expect(JSON.parse(last_response.body)["id"]).to eq(env_var[:id]) }
end
end

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Find, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: 'bar', public: true, repository_id: repo.id } }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
@ -36,7 +36,7 @@ describe Travis::API::V3::Services::EnvVar::Find, set_app: true do
'id' => env_var[:id],
'name' => env_var[:name],
'public' => env_var[:public],
'value' => env_var[:value]
'value' => env_var[:value].decrypt
)
end
end

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Update, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: 'bar', public: true, repository_id: repo.id } }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
let(:json_headers) { { 'CONTENT_TYPE' => 'application/json' } }
@ -42,7 +42,7 @@ describe Travis::API::V3::Services::EnvVar::Update, set_app: true do
'@representation' => 'standard',
'id' => env_var[:id],
'name' => params['env_var.name'],
'value' => env_var[:value],
'value' => env_var[:value].decrypt,
'public' => env_var[:public]
)
end

View File

@ -13,7 +13,7 @@ describe Travis::API::V3::Services::EnvVars::Create, set_app: true do
describe 'authenticated, repo missing' do
before { post("/v3/repo/99999999/env_vars", {}, auth_headers) }
include_examples 'missing repo'
include_examples 'missing repo'
end
describe 'authenticated, existing repo, env var already exists' do
@ -26,7 +26,7 @@ describe Travis::API::V3::Services::EnvVars::Create, set_app: true do
end
before do
repo.update_attributes(settings: JSON.generate(env_vars: [{ id: 'abc', name: 'FOO', value: 'bar', public: false }]))
repo.update_attributes(settings: JSON.generate(env_vars: [{ id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: false }]))
post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers))
end
@ -41,27 +41,53 @@ describe Travis::API::V3::Services::EnvVars::Create, set_app: true do
end
describe 'authenticated, existing repo, env var is new' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => false
}
describe 'private' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => false
}
end
before { post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers)) }
example { expect(last_response.status).to eq 201 }
example do
response = JSON.load(body)
expect(response).to include(
'@type' => 'env_var',
'@representation' => 'standard',
'name' => 'FOO',
'public' => false
)
expect(response).to include('@href', 'id')
end
end
before { post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers)) }
describe 'public' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => true
}
end
example { expect(last_response.status).to eq 201 }
example do
response = JSON.load(body)
expect(response).to include(
'@type' => 'env_var',
'@representation' => 'standard',
'name' => 'FOO',
'value' => 'bar',
'public' => false
)
expect(response).to include('@href', 'id')
before { post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers)) }
example { expect(last_response.status).to eq 201 }
example do
response = JSON.load(body)
expect(response).to include(
'@type' => 'env_var',
'@representation' => 'standard',
'name' => 'FOO',
'value' => 'bar',
'public' => true
)
expect(response).to include('@href', 'id')
end
end
end
end

View File

@ -3,9 +3,9 @@ require 'spec_helper'
describe Travis::API::V3::Services::EnvVars::ForRepository, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: 'bar', public: true, repository_id: repo.id } }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
before { get("/v3/repo/#{repo.id}/env_vars") }
include_examples 'not authenticated'
@ -13,7 +13,7 @@ describe Travis::API::V3::Services::EnvVars::ForRepository, set_app: true do
describe 'authenticated, missing repo' do
before { get("/v3/repo/999999999/env_vars", {}, auth_headers) }
include_examples 'missing repo'
include_examples 'missing repo'
end
describe 'authenticated, existing repo, no env vars' do
@ -49,7 +49,7 @@ describe Travis::API::V3::Services::EnvVars::ForRepository, set_app: true do
'@representation' => 'standard',
'id' => env_var[:id],
'name' => env_var[:name],
'value' => env_var[:value],
'value' => env_var[:value].decrypt,
'public' => env_var[:public]
}
]