From 5f97c06fab82edd78db44ec0811125686f9f1bf0 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Thu, 16 Jan 2025 00:26:01 +0400 Subject: [PATCH 01/10] TBT-137 Be able to use environment variables across different repos --- lib/travis/api/v3/models/account_env_var.rb | 19 ++++++ lib/travis/api/v3/models/user.rb | 6 ++ lib/travis/api/v3/queries/account_env_var.rb | 63 +++++++++++++++++++ lib/travis/api/v3/renderer/account_env_var.rb | 7 +++ lib/travis/api/v3/renderer/user.rb | 2 +- lib/travis/api/v3/routes.rb | 10 +++ lib/travis/api/v3/services.rb | 2 + .../api/v3/services/account_env_var/delete.rb | 10 +++ .../v3/services/account_env_vars/create.rb | 12 ++++ lib/travis/model/user.rb | 1 + 10 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 lib/travis/api/v3/models/account_env_var.rb create mode 100644 lib/travis/api/v3/queries/account_env_var.rb create mode 100644 lib/travis/api/v3/renderer/account_env_var.rb create mode 100644 lib/travis/api/v3/services/account_env_var/delete.rb create mode 100644 lib/travis/api/v3/services/account_env_vars/create.rb diff --git a/lib/travis/api/v3/models/account_env_var.rb b/lib/travis/api/v3/models/account_env_var.rb new file mode 100644 index 000000000..289bf82f0 --- /dev/null +++ b/lib/travis/api/v3/models/account_env_var.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + class Models::AccountEnvVar < Model + belongs_to :owner, polymorphic: true + + def save_account_env_var!(owner_type, owner_id, name, value, public) + self.owner_type = owner_type + self.owner_id = owner_id + self.name = name + self.value = value + self.public = public + + if self.valid? + self.save! + end + + self + end + end +end diff --git a/lib/travis/api/v3/models/user.rb b/lib/travis/api/v3/models/user.rb index 54df28c54..4cb3130cb 100644 --- a/lib/travis/api/v3/models/user.rb +++ b/lib/travis/api/v3/models/user.rb @@ -100,5 +100,11 @@ def custom_keys return @custom_keys if defined? @custom_keys @custom_keys = Models::CustomKey.where(owner_type: 'User', owner_id: id) end + + def account_env_vars + return @account_env_vars if defined? @account_env_vars + @account_env_vars = Models::AccountEnvVar.where(owner_type: 'User', owner_id: id) + end + end end diff --git a/lib/travis/api/v3/queries/account_env_var.rb b/lib/travis/api/v3/queries/account_env_var.rb new file mode 100644 index 000000000..bcf8a64e6 --- /dev/null +++ b/lib/travis/api/v3/queries/account_env_var.rb @@ -0,0 +1,63 @@ +module Travis::API::V3 + class Queries::AccountEnvVar < Query + def create(params, current_user) + # 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? + + if params['owner_type'] == 'User' + org_ids = User.find(params['owner_id']).organizations.map(&:id) + + 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? + elsif params['owner_type'] == 'Organization' + user_ids = Membership.where(organization_id: params['owner_id']).map(&:user_id) + + 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? + end + + key = Travis::API::V3::Models::AccountEnvVar.new.save_account_env_var!( + params['owner_type'], + params['owner_id'], + params['name'], + params['value'], + params['public'] + ) + handle_errors(key) unless key.valid? + + Travis::API::V3::Models::Audit.create!( + owner: current_user, + change_source: 'travis-api', + source: key, + source_changes: { + action: 'create', + fingerprint: key.id + } + ) + + key + end + + def delete(params, current_user) + key = Travis::API::V3::Models::AccountEnvVar.find(params['id']) + Travis::API::V3::Models::Audit.create!( + owner: current_user, + change_source: 'travis-api', + source: key, + source_changes: { + action: 'delete', + name: key.name, + owner_type: key.owner_type, + owner_id: key.owner_id + } + ) + + key.destroy + end + + private + + def handle_errors(key) + private_key = key.errors[:private_key] + raise UnprocessableEntity, 'This key is not a private key.' if private_key.include?('invalid_pem') + raise WrongParams if private_key.include?('missing_attr') + end + end +end diff --git a/lib/travis/api/v3/renderer/account_env_var.rb b/lib/travis/api/v3/renderer/account_env_var.rb new file mode 100644 index 000000000..31bbb872c --- /dev/null +++ b/lib/travis/api/v3/renderer/account_env_var.rb @@ -0,0 +1,7 @@ +module Travis::API::V3 + class Renderer::AccountEnvVar < ModelRenderer + representation :standard, :id, :owner_id, :owner_type, :name, :value, :public, :created_at, :updated_at + representation :minimal, *representations[:standard] + + end +end diff --git a/lib/travis/api/v3/renderer/user.rb b/lib/travis/api/v3/renderer/user.rb index 9ebcc6504..97955297d 100644 --- a/lib/travis/api/v3/renderer/user.rb +++ b/lib/travis/api/v3/renderer/user.rb @@ -2,7 +2,7 @@ module Travis::API::V3 class Renderer::User < Renderer::Owner - representation(:standard, :email, :is_syncing, :synced_at, :recently_signed_up, :secure_user_hash, :ro_mode, :confirmed_at, :custom_keys) + representation(:standard, :email, :is_syncing, :synced_at, :recently_signed_up, :secure_user_hash, :ro_mode, :confirmed_at, :custom_keys, :account_env_vars) representation(:additional, :emails, :collaborator) def email diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 8b4c8e711..033686d64 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -350,6 +350,16 @@ module Routes delete :delete end + hidden_resource :account_env_vars do + route '/account_env_var' + post :create + end + + hidden_resource :account_env_var do + route '/account_env_var/{id}' + delete :delete + end + hidden_resource :storage do route '/storage/{id}' get :find diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb index 8a727a23a..4cd79417d 100644 --- a/lib/travis/api/v3/services.rb +++ b/lib/travis/api/v3/services.rb @@ -66,6 +66,8 @@ module Services User = Module.new { extend Services } UserSetting = Module.new { extend Services } UserSettings = Module.new { extend Services } + AccountEnvVar = Module.new { extend Services } + AccountEnvVars = Module.new { extend Services } def result_type @result_type ||= name[/[^:]+$/].underscore.to_sym diff --git a/lib/travis/api/v3/services/account_env_var/delete.rb b/lib/travis/api/v3/services/account_env_var/delete.rb new file mode 100644 index 000000000..4621eeb2b --- /dev/null +++ b/lib/travis/api/v3/services/account_env_var/delete.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::AccountEnvVar::Delete < Service + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + + query(:account_env_var).delete(params, access_control.user) + deleted + end + end +end diff --git a/lib/travis/api/v3/services/account_env_vars/create.rb b/lib/travis/api/v3/services/account_env_vars/create.rb new file mode 100644 index 000000000..5eec4450c --- /dev/null +++ b/lib/travis/api/v3/services/account_env_vars/create.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::AccountEnvVars::Create < Service + params :owner_id, :owner_type, :name, :value, :public + result_type :account_env_var + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + + result query(:account_env_var).create(params, access_control.user) + end + end +end diff --git a/lib/travis/model/user.rb b/lib/travis/model/user.rb index 990f6c3d9..1365c089d 100644 --- a/lib/travis/model/user.rb +++ b/lib/travis/model/user.rb @@ -15,6 +15,7 @@ class User < Travis::Model has_many :emails, dependent: :destroy has_one :owner_group, as: :owner has_many :custom_keys, as: :owner + has_many :account_env_vars, as: :owner has_many :broadcasts, as: :recipient before_create :set_as_recent From 86a392ee0327612b6f9cd705d1b19e23d0c1f97f Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Fri, 17 Jan 2025 04:07:44 +0400 Subject: [PATCH 02/10] TBT-137 Add encryption for env value --- lib/travis/api/v3/models/account_env_var.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/travis/api/v3/models/account_env_var.rb b/lib/travis/api/v3/models/account_env_var.rb index 289bf82f0..468c2947b 100644 --- a/lib/travis/api/v3/models/account_env_var.rb +++ b/lib/travis/api/v3/models/account_env_var.rb @@ -2,6 +2,8 @@ module Travis::API::V3 class Models::AccountEnvVar < Model belongs_to :owner, polymorphic: true + serialize :value, Travis::Model::EncryptedColumn.new + def save_account_env_var!(owner_type, owner_id, name, value, public) self.owner_type = owner_type self.owner_id = owner_id From 9c944a2271c33a58c9cbc807984d63039f4a9c56 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Fri, 17 Jan 2025 12:08:58 +0400 Subject: [PATCH 03/10] TBT-137 Apply changes for organization type --- lib/travis/api/v3/models/organization.rb | 5 +++++ lib/travis/api/v3/renderer/owner.rb | 2 +- lib/travis/api/v3/renderer/user.rb | 2 +- lib/travis/model/organization.rb | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/v3/models/organization.rb b/lib/travis/api/v3/models/organization.rb index ff0c3e1fb..ce49ff61d 100644 --- a/lib/travis/api/v3/models/organization.rb +++ b/lib/travis/api/v3/models/organization.rb @@ -47,6 +47,11 @@ def custom_keys @custom_keys = Models::CustomKey.where(owner_type: 'Organization', owner_id: id) end + def account_env_vars + return @account_env_vars if defined? @account_env_vars + @account_env_vars = Models::AccountEnvVar.where(owner_type: 'Organization', owner_id: id) + end + alias members users end end diff --git a/lib/travis/api/v3/renderer/owner.rb b/lib/travis/api/v3/renderer/owner.rb index ee5aae9a8..e5fb29aa4 100644 --- a/lib/travis/api/v3/renderer/owner.rb +++ b/lib/travis/api/v3/renderer/owner.rb @@ -6,7 +6,7 @@ class Renderer::Owner < ModelRenderer representation(:minimal, :id, :login, :name, :vcs_type, :ro_mode) representation(:standard, :id, :login, :name, :github_id, :vcs_id, :vcs_type, :avatar_url, :education, - :allow_migration, :allowance, :ro_mode, :custom_keys, :trial_allowed) + :allow_migration, :allowance, :ro_mode, :custom_keys, :trial_allowed, :account_env_vars) representation(:additional, :repositories, :installation, :trial_allowed) def initialize(model, **options) diff --git a/lib/travis/api/v3/renderer/user.rb b/lib/travis/api/v3/renderer/user.rb index 97955297d..9ebcc6504 100644 --- a/lib/travis/api/v3/renderer/user.rb +++ b/lib/travis/api/v3/renderer/user.rb @@ -2,7 +2,7 @@ module Travis::API::V3 class Renderer::User < Renderer::Owner - representation(:standard, :email, :is_syncing, :synced_at, :recently_signed_up, :secure_user_hash, :ro_mode, :confirmed_at, :custom_keys, :account_env_vars) + representation(:standard, :email, :is_syncing, :synced_at, :recently_signed_up, :secure_user_hash, :ro_mode, :confirmed_at, :custom_keys) representation(:additional, :emails, :collaborator) def email diff --git a/lib/travis/model/organization.rb b/lib/travis/model/organization.rb index 421beb4cb..e8fdb4dda 100644 --- a/lib/travis/model/organization.rb +++ b/lib/travis/model/organization.rb @@ -8,6 +8,7 @@ class Organization < Travis::Model has_many :repositories, :as => :owner has_one :owner_group, as: :owner has_many :custom_keys, as: :owner + has_many :account_env_vars, as: :owner has_many :broadcasts, as: :recipient after_initialize do From fe38656a17125286cf4ed0572557becb6f7cdcbd Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Fri, 24 Jan 2025 12:42:31 +0400 Subject: [PATCH 04/10] TBT-137 Add permission checks --- lib/travis/api/v3/models/organization.rb | 6 ++---- lib/travis/api/v3/models/user.rb | 6 ++---- .../api/v3/permissions/account_env_var.rb | 19 +++++++++++++++++++ .../api/v3/services/account_env_var/delete.rb | 1 + .../v3/services/account_env_vars/create.rb | 1 + 5 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 lib/travis/api/v3/permissions/account_env_var.rb diff --git a/lib/travis/api/v3/models/organization.rb b/lib/travis/api/v3/models/organization.rb index ce49ff61d..78b5e843c 100644 --- a/lib/travis/api/v3/models/organization.rb +++ b/lib/travis/api/v3/models/organization.rb @@ -43,13 +43,11 @@ def ensure_preferences end def custom_keys - return @custom_keys if defined? @custom_keys - @custom_keys = Models::CustomKey.where(owner_type: 'Organization', owner_id: id) + @custom_keys != Models::CustomKey.where(owner_type: 'Organization', owner_id: id) end def account_env_vars - return @account_env_vars if defined? @account_env_vars - @account_env_vars = Models::AccountEnvVar.where(owner_type: 'Organization', owner_id: id) + @account_env_vars != Models::AccountEnvVar.where(owner_type: 'Organization', owner_id: id) end alias members users diff --git a/lib/travis/api/v3/models/user.rb b/lib/travis/api/v3/models/user.rb index 4cb3130cb..8ed62f7d9 100644 --- a/lib/travis/api/v3/models/user.rb +++ b/lib/travis/api/v3/models/user.rb @@ -97,13 +97,11 @@ def ensure_preferences end def custom_keys - return @custom_keys if defined? @custom_keys - @custom_keys = Models::CustomKey.where(owner_type: 'User', owner_id: id) + @custom_keys != Models::CustomKey.where(owner_type: 'User', owner_id: id) end def account_env_vars - return @account_env_vars if defined? @account_env_vars - @account_env_vars = Models::AccountEnvVar.where(owner_type: 'User', owner_id: id) + @account_env_vars != Models::AccountEnvVar.where(owner_type: 'User', owner_id: id) end end diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb new file mode 100644 index 000000000..e25926706 --- /dev/null +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + class Permissions::AccountEnvVar < Permissions::Generic + def write? + return organization_permissions.admin? if object.owner_type == 'Organization' + authorizer.for_account(object.owner_id, 'account_settings_create') + end + + def delete? + return organization_permissions.admin? if object.owner_type == 'Organization' + authorizer.for_account(object.owner_id, 'account_settings_delete') + end + + private + + def organization_permissions + @organization_permissions ||= Permissions::Organization.new(access_control, {id: object.owner_id}) + end + end +end diff --git a/lib/travis/api/v3/services/account_env_var/delete.rb b/lib/travis/api/v3/services/account_env_var/delete.rb index 4621eeb2b..4445e02d8 100644 --- a/lib/travis/api/v3/services/account_env_var/delete.rb +++ b/lib/travis/api/v3/services/account_env_var/delete.rb @@ -2,6 +2,7 @@ module Travis::API::V3 class Services::AccountEnvVar::Delete < Service def run! raise LoginRequired unless access_control.full_access_or_logged_in? + access_control.permissions(account_env_var).delete! query(:account_env_var).delete(params, access_control.user) deleted diff --git a/lib/travis/api/v3/services/account_env_vars/create.rb b/lib/travis/api/v3/services/account_env_vars/create.rb index 5eec4450c..bed3b5369 100644 --- a/lib/travis/api/v3/services/account_env_vars/create.rb +++ b/lib/travis/api/v3/services/account_env_vars/create.rb @@ -5,6 +5,7 @@ class Services::AccountEnvVars::Create < Service def run! raise LoginRequired unless access_control.full_access_or_logged_in? + access_control.permissions(account_env_var).write? result query(:account_env_var).create(params, access_control.user) end From 3bd4c7c26d2f2276f734e90cc71e0cace2fb3853 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Sun, 2 Feb 2025 01:23:54 +0400 Subject: [PATCH 05/10] TBT-137 Add specs --- lib/travis/api/v3/models/organization.rb | 4 +- lib/travis/api/v3/models/user.rb | 4 +- .../api/v3/permissions/account_env_var.rb | 8 ++-- lib/travis/api/v3/queries/account_env_var.rb | 45 +++++++------------ lib/travis/api/v3/routes.rb | 2 +- .../create.rb | 11 ++++- .../api/v3/services/account_env_var/delete.rb | 16 +++++-- .../services/account_env_var/create_spec.rb | 39 ++++++++++++++++ .../services/account_env_var/delete_spec.rb | 14 ++++++ 9 files changed, 100 insertions(+), 43 deletions(-) rename lib/travis/api/v3/services/{account_env_vars => account_env_var}/create.rb (53%) create mode 100644 spec/v3/services/account_env_var/create_spec.rb create mode 100644 spec/v3/services/account_env_var/delete_spec.rb diff --git a/lib/travis/api/v3/models/organization.rb b/lib/travis/api/v3/models/organization.rb index 78b5e843c..8be188a0d 100644 --- a/lib/travis/api/v3/models/organization.rb +++ b/lib/travis/api/v3/models/organization.rb @@ -43,11 +43,11 @@ def ensure_preferences end def custom_keys - @custom_keys != Models::CustomKey.where(owner_type: 'Organization', owner_id: id) + @custom_keys ||= Models::CustomKey.where(owner_type: 'Organization', owner_id: id) end def account_env_vars - @account_env_vars != Models::AccountEnvVar.where(owner_type: 'Organization', owner_id: id) + @account_env_vars ||= Models::AccountEnvVar.where(owner_type: 'Organization', owner_id: id) end alias members users diff --git a/lib/travis/api/v3/models/user.rb b/lib/travis/api/v3/models/user.rb index 8ed62f7d9..1dd2d9043 100644 --- a/lib/travis/api/v3/models/user.rb +++ b/lib/travis/api/v3/models/user.rb @@ -97,11 +97,11 @@ def ensure_preferences end def custom_keys - @custom_keys != Models::CustomKey.where(owner_type: 'User', owner_id: id) + @custom_keys ||= Models::CustomKey.where(owner_type: 'User', owner_id: id) end def account_env_vars - @account_env_vars != Models::AccountEnvVar.where(owner_type: 'User', owner_id: id) + @account_env_vars ||= Models::AccountEnvVar.where(owner_type: 'User', owner_id: id) end end diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index e25926706..85bb73f41 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -1,13 +1,13 @@ +require 'travis/api/v3/permissions/generic' + module Travis::API::V3 class Permissions::AccountEnvVar < Permissions::Generic def write? - return organization_permissions.admin? if object.owner_type == 'Organization' - authorizer.for_account(object.owner_id, 'account_settings_create') + authorizer.for_account(object.owner_id, 'account_settings_create') if object.owner_type == 'Organization' end def delete? - return organization_permissions.admin? if object.owner_type == 'Organization' - authorizer.for_account(object.owner_id, 'account_settings_delete') + authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' end private diff --git a/lib/travis/api/v3/queries/account_env_var.rb b/lib/travis/api/v3/queries/account_env_var.rb index bcf8a64e6..7c809868c 100644 --- a/lib/travis/api/v3/queries/account_env_var.rb +++ b/lib/travis/api/v3/queries/account_env_var.rb @@ -1,63 +1,48 @@ module Travis::API::V3 class Queries::AccountEnvVar < Query - def create(params, current_user) - # 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? - - if params['owner_type'] == 'User' - org_ids = User.find(params['owner_id']).organizations.map(&:id) - 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? - elsif params['owner_type'] == 'Organization' - user_ids = Membership.where(organization_id: params['owner_id']).map(&:user_id) + def find(params) + Models::AccountEnvVar.where(owner_type: params['owner_type'], owner_id: params['owner_id']) + end - 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? - end + def create(params, current_user) + raise UnprocessableEntity, "'#{params['name']}' environment variable already exists." unless Models::AccountEnvVar.where(name: params['name'], owner_id: params['owner_id'], owner_type: params['owner_type']).count.zero? - key = Travis::API::V3::Models::AccountEnvVar.new.save_account_env_var!( + env_var = Travis::API::V3::Models::AccountEnvVar.new.save_account_env_var!( params['owner_type'], params['owner_id'], params['name'], params['value'], params['public'] ) - handle_errors(key) unless key.valid? Travis::API::V3::Models::Audit.create!( owner: current_user, change_source: 'travis-api', - source: key, + source: env_var, source_changes: { action: 'create', - fingerprint: key.id + fingerprint: env_var.id } ) - - key + env_var end def delete(params, current_user) - key = Travis::API::V3::Models::AccountEnvVar.find(params['id']) + env_var = Travis::API::V3::Models::AccountEnvVar.find(params['id']) Travis::API::V3::Models::Audit.create!( owner: current_user, change_source: 'travis-api', - source: key, + source: env_var, source_changes: { action: 'delete', - name: key.name, - owner_type: key.owner_type, - owner_id: key.owner_id + name: env_var.name, + owner_type: env_var.owner_type, + owner_id: env_var.owner_id } ) - key.destroy - end - - private - - def handle_errors(key) - private_key = key.errors[:private_key] - raise UnprocessableEntity, 'This key is not a private key.' if private_key.include?('invalid_pem') - raise WrongParams if private_key.include?('missing_attr') + env_var.destroy end end end diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 033686d64..4407004bc 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -350,7 +350,7 @@ module Routes delete :delete end - hidden_resource :account_env_vars do + hidden_resource :account_env_var do route '/account_env_var' post :create end diff --git a/lib/travis/api/v3/services/account_env_vars/create.rb b/lib/travis/api/v3/services/account_env_var/create.rb similarity index 53% rename from lib/travis/api/v3/services/account_env_vars/create.rb rename to lib/travis/api/v3/services/account_env_var/create.rb index bed3b5369..c8bc9110d 100644 --- a/lib/travis/api/v3/services/account_env_vars/create.rb +++ b/lib/travis/api/v3/services/account_env_var/create.rb @@ -1,10 +1,19 @@ module Travis::API::V3 - class Services::AccountEnvVars::Create < Service + class Services::AccountEnvVar::Create < Service params :owner_id, :owner_type, :name, :value, :public result_type :account_env_var def run! raise LoginRequired unless access_control.full_access_or_logged_in? + + account_env_var = Travis::API::V3::Models::AccountEnvVar.new( + owner_type: params['owner_type'], + owner_id: params['owner_id'], + name: params['name'], + value: params['value'], + public: params['public'] + ) + access_control.permissions(account_env_var).write? result query(:account_env_var).create(params, access_control.user) diff --git a/lib/travis/api/v3/services/account_env_var/delete.rb b/lib/travis/api/v3/services/account_env_var/delete.rb index 4445e02d8..5829dabf9 100644 --- a/lib/travis/api/v3/services/account_env_var/delete.rb +++ b/lib/travis/api/v3/services/account_env_var/delete.rb @@ -1,11 +1,21 @@ module Travis::API::V3 class Services::AccountEnvVar::Delete < Service + params :id + def run! raise LoginRequired unless access_control.full_access_or_logged_in? - access_control.permissions(account_env_var).delete! - query(:account_env_var).delete(params, access_control.user) - deleted + account_env_var = Travis::API::V3::Models::AccountEnvVar.find_by( + id: params['id'] + ) + + if account_env_var + access_control.permissions(account_env_var).delete! + query(:account_env_var).delete(params, access_control.user) + deleted + else + raise NotFound, "No matching environment variable found." + end end end end diff --git a/spec/v3/services/account_env_var/create_spec.rb b/spec/v3/services/account_env_var/create_spec.rb new file mode 100644 index 000000000..a67032370 --- /dev/null +++ b/spec/v3/services/account_env_var/create_spec.rb @@ -0,0 +1,39 @@ +describe Travis::API::V3::Services::CustomKeys::Create, set_app: true do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}", "Content-Type" => "application/json" }} + let(:options) do + { + 'owner_id' => user.id, + 'owner_type' => 'User', + 'name' => 'TEST_VAR', + 'value' => 'VAL', + 'public' => true + } + end + let(:parsed_body) { JSON.load(body) } + + describe "try creating a account env var without login" do + before { post('/v3/account_env_var', options) } + example { expect(parsed_body).to eql_json({ + "@type" => "error", + "error_type" => "login_required", + "error_message" => "login required" + })} + end + + describe "creating account env var" do + before { post('/v3/account_env_var', options, headers) } + example { expect(parsed_body.except("id", "@permissions")).to eql_json({ + "@type" => "account_env_var", + "@representation" => "standard", + 'owner_id' => user.id, + 'owner_type' => 'User', + "name" => "TEST_VAR", + "value" => "VAL", + "public" => true, + "created_at" => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), + "updated_at" => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ') + })} + end +end diff --git a/spec/v3/services/account_env_var/delete_spec.rb b/spec/v3/services/account_env_var/delete_spec.rb new file mode 100644 index 000000000..ba7af2505 --- /dev/null +++ b/spec/v3/services/account_env_var/delete_spec.rb @@ -0,0 +1,14 @@ +describe Travis::API::V3::Services::AccountEnvVar::Delete, set_app: true do + let(:user) { FactoryBot.create(:user) } + let(:account_env_var) { Travis::API::V3::Models::AccountEnvVar.new.save_account_env_var!('User', user.id, 'TEST_VAR', 'VAL', true) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:parsed_body) { JSON.load(body) } + + describe "deleting account env var by id" do + before { delete("/v3/account_env_var/#{account_env_var.id}", {}, headers) } + example { expect(last_response.status).to eq 204 } + example { expect(Travis::API::V3::Models::AccountEnvVar.where(id: account_env_var.id)).to be_empty } + example { expect(parsed_body).to be_nil } + end +end From 88545d9f4af0796fcdc02282c8c399544f97fe95 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Sun, 2 Feb 2025 02:27:22 +0400 Subject: [PATCH 06/10] TBT-137 Add logs for debugging --- lib/travis/api/v3/authorizer.rb | 1 + lib/travis/api/v3/permissions/account_env_var.rb | 6 +++++- lib/travis/api/v3/services/account_env_var/delete.rb | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/authorizer.rb b/lib/travis/api/v3/authorizer.rb index 98ac417f8..fd387e4ee 100644 --- a/lib/travis/api/v3/authorizer.rb +++ b/lib/travis/api/v3/authorizer.rb @@ -175,6 +175,7 @@ def get_permission(resource_type, resource_id, permission) data = redis.smembers(key) data.include?(permission) else + Travis.logger.info "checking permissions: resource_type: #{resource_type} resource_id: #{resource_id} permission: #{permission}" response = connection.get("/permissions/#{resource_type == 'repository' ? 'repo' : 'org'}/#{resource_id}") unless response.status == 200 && response.body&.include?('permissions') Travis.logger.warn("Authorizer permission response error: #{response.status} for user: #{@user_id}, resource: #{resource_type}: #{resource_id}") diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index 85bb73f41..0e8b35d7b 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -3,11 +3,15 @@ module Travis::API::V3 class Permissions::AccountEnvVar < Permissions::Generic def write? + Travis.logger.info "checking rights" authorizer.for_account(object.owner_id, 'account_settings_create') if object.owner_type == 'Organization' end def delete? - authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' + Travis.logger.info "checking rights" + Travis.logger.info "the object: #{object.owner_id}" + return authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' + Travis.logger.info "user rights" end private diff --git a/lib/travis/api/v3/services/account_env_var/delete.rb b/lib/travis/api/v3/services/account_env_var/delete.rb index 5829dabf9..b1c08f33c 100644 --- a/lib/travis/api/v3/services/account_env_var/delete.rb +++ b/lib/travis/api/v3/services/account_env_var/delete.rb @@ -10,6 +10,7 @@ def run! ) if account_env_var + Travis.logger.info "starting deletion" access_control.permissions(account_env_var).delete! query(:account_env_var).delete(params, access_control.user) deleted From 4592dc9f34d57800c00521c0357a967cd6f63724 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Sun, 2 Feb 2025 02:52:00 +0400 Subject: [PATCH 07/10] TBT-137 Remove logs for debugging --- lib/travis/api/v3/authorizer.rb | 1 - lib/travis/api/v3/permissions/account_env_var.rb | 6 +----- lib/travis/api/v3/services/account_env_var/delete.rb | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/travis/api/v3/authorizer.rb b/lib/travis/api/v3/authorizer.rb index fd387e4ee..98ac417f8 100644 --- a/lib/travis/api/v3/authorizer.rb +++ b/lib/travis/api/v3/authorizer.rb @@ -175,7 +175,6 @@ def get_permission(resource_type, resource_id, permission) data = redis.smembers(key) data.include?(permission) else - Travis.logger.info "checking permissions: resource_type: #{resource_type} resource_id: #{resource_id} permission: #{permission}" response = connection.get("/permissions/#{resource_type == 'repository' ? 'repo' : 'org'}/#{resource_id}") unless response.status == 200 && response.body&.include?('permissions') Travis.logger.warn("Authorizer permission response error: #{response.status} for user: #{@user_id}, resource: #{resource_type}: #{resource_id}") diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index 0e8b35d7b..85bb73f41 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -3,15 +3,11 @@ module Travis::API::V3 class Permissions::AccountEnvVar < Permissions::Generic def write? - Travis.logger.info "checking rights" authorizer.for_account(object.owner_id, 'account_settings_create') if object.owner_type == 'Organization' end def delete? - Travis.logger.info "checking rights" - Travis.logger.info "the object: #{object.owner_id}" - return authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' - Travis.logger.info "user rights" + authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' end private diff --git a/lib/travis/api/v3/services/account_env_var/delete.rb b/lib/travis/api/v3/services/account_env_var/delete.rb index b1c08f33c..5829dabf9 100644 --- a/lib/travis/api/v3/services/account_env_var/delete.rb +++ b/lib/travis/api/v3/services/account_env_var/delete.rb @@ -10,7 +10,6 @@ def run! ) if account_env_var - Travis.logger.info "starting deletion" access_control.permissions(account_env_var).delete! query(:account_env_var).delete(params, access_control.user) deleted From ad70dd68f8f1641dfef2862dde3fcf23a9f9197d Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Mon, 3 Feb 2025 05:25:56 +0400 Subject: [PATCH 08/10] TBT-137 Add return keyword --- lib/travis/api/v3/permissions/account_env_var.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index 85bb73f41..d99924fc8 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -7,7 +7,7 @@ def write? end def delete? - authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' + return authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' end private From 51201151ad333343aef2a0d32537831545268f5f Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Mon, 3 Feb 2025 05:42:06 +0400 Subject: [PATCH 09/10] TBT-137 Add logs --- lib/travis/api/v3/permissions/account_env_var.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index d99924fc8..59999dff2 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -7,7 +7,10 @@ def write? end def delete? + Travis.logger.info "checking rights" + Travis.logger.info "the object: #{object.owner_id}" return authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' + Travis.logger.info "user rights" end private From 78d4d1e9522dc0a0fad144b9b4f5b0e9cb78c133 Mon Sep 17 00:00:00 2001 From: tonoyansergey-devt Date: Mon, 3 Feb 2025 21:52:57 +0400 Subject: [PATCH 10/10] TBT-137 Fix permissions --- lib/travis/api/v3/permissions/account_env_var.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/travis/api/v3/permissions/account_env_var.rb b/lib/travis/api/v3/permissions/account_env_var.rb index 59999dff2..6aca292f2 100644 --- a/lib/travis/api/v3/permissions/account_env_var.rb +++ b/lib/travis/api/v3/permissions/account_env_var.rb @@ -3,14 +3,15 @@ module Travis::API::V3 class Permissions::AccountEnvVar < Permissions::Generic def write? - authorizer.for_account(object.owner_id, 'account_settings_create') if object.owner_type == 'Organization' + object.owner_type == 'Organization' ? + authorizer.for_account(object.owner_id, 'account_settings_create') : + true end def delete? - Travis.logger.info "checking rights" - Travis.logger.info "the object: #{object.owner_id}" - return authorizer.for_account(object.owner_id, 'account_settings_delete') if object.owner_type == 'Organization' - Travis.logger.info "user rights" + object.owner_type == 'Organization' ? + authorizer.for_account(object.owner_id, 'account_settings_delete') : + true end private