aptible-auth 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a41b77f6708abdde557d4763215fd5f6e18460716a25c94c29fdd15564588dc3
4
- data.tar.gz: a74283bb27a4a0ac4b952b2c0dd7065f0e7b35640d6354af73ab01910101f4de
3
+ metadata.gz: 7fa3270646948b32ac4d6f467b2441757c28af525f0c2c1bf465c0a7ceda6cf4
4
+ data.tar.gz: d4869199daef0e8763be2bda7c4dd60bc59a35bb90664cade8ec81141df8551c
5
5
  SHA512:
6
- metadata.gz: 9597770fc7f1a203eb2efbb0326a58e495912cc3fde1835737cb6d9850395ab1a0d341ccea701db3502137aef32cfdd6199ada643908048148690224f55d0614
7
- data.tar.gz: 05e43ea50940aa25ba554db3b0eb78469d52c27e96ad9af0db46b6efb9803dc39e0fe916dbd3c0c608babc606dff23f4cd7804c436d87cedc6cdd8997a4aa2ae
6
+ metadata.gz: 53f90bf3f134007f0003edadb8a1bc254811c6e3ca76d473dde1a0447b03dc4e75176e6550c455d7bce55567a0bfc81789a2f22237faf3a6d85b931bba879370
7
+ data.tar.gz: 7b673c460863f56d6b9319314ccc291fade0fd3d678bb64f2de5716de86e6585541988f2078616774e661c8435d096df689d90e85aa8370ef214e3df34d61767
@@ -0,0 +1,26 @@
1
+ on:
2
+ release:
3
+ types: [published]
4
+
5
+ jobs:
6
+ push:
7
+ name: Push gem to RubyGems.org
8
+ runs-on: ubuntu-latest
9
+
10
+ permissions:
11
+ id-token: write
12
+ contents: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
16
+ with:
17
+ persist-credentials: false
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@211ffaaa5f8dda97e9e8bca4e70d0fbaf2f8c41c
20
+ with:
21
+ bundler-cache: false
22
+ ruby-version: "3.3"
23
+
24
+ - run: bundle install
25
+
26
+ - uses: rubygems/release-gem@1c162a739e8b4cb21a676e97b087e8268d8fc40b
data/Makefile CHANGED
@@ -2,12 +2,18 @@
2
2
  export COMPOSE_IGNORE_ORPHANS ?= true
3
3
  export RUBY_VERSION ?= 2.3.1
4
4
  RUBY_VERSION_MAJOR = $(word 1,$(subst ., ,$(RUBY_VERSION)))
5
+ RUBY_VERSION_MINOR = $(word 2,$(subst ., ,$(RUBY_VERSION)))
5
6
  export BUNDLER_VERSION ?=
6
7
  ifeq ($(BUNDLER_VERSION),)
7
8
  ifeq ($(RUBY_VERSION_MAJOR),2)
9
+ # Use old bundler for Ruby 2.3-2.6; Ruby 2.7 needs bundler 2.x to avoid resolver bugs
10
+ ifeq ($(RUBY_VERSION_MINOR),7)
11
+ export BUNDLER_VERSION = 2.4.22
12
+ else
8
13
  export BUNDLER_VERSION = 1.17.3
9
14
  endif
10
15
  endif
16
+ endif
11
17
  PROJECT_NAME = $(shell ls *.gemspec | sed 's/\.gemspec//')
12
18
  export COMPOSE_PROJECT_NAME ?= $(PROJECT_NAME)-$(subst .,_,$(RUBY_VERSION))
13
19
 
data/aptible-auth.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'oauth2', '2.0.9'
27
27
 
28
28
  spec.add_development_dependency 'aptible-tasks', '>= 0.6.0'
29
+ spec.add_development_dependency 'httplog'
29
30
  spec.add_development_dependency 'pry'
30
31
  spec.add_development_dependency 'rake'
31
32
  spec.add_development_dependency 'rspec', '~> 3.0'
@@ -40,6 +40,11 @@ module Aptible
40
40
  cause: e)
41
41
  end
42
42
 
43
+ def self.current_token(token:)
44
+ url = "#{Aptible::Auth.configuration.root_url}/current_token"
45
+ find_by_url(url, token: token)
46
+ end
47
+
43
48
  def authenticate_user(email, password, options = {})
44
49
  options[:scope] ||= 'manage'
45
50
  oauth_token = oauth.password.get_token(email, password, options)
@@ -24,6 +24,21 @@ module Aptible
24
24
  # TODO: Implement query params for /operations
25
25
  []
26
26
  end
27
+
28
+ # Returns roles with their organizations pre-loaded to avoid N+1 API calls
29
+ # when iterating through roles and accessing role.organization.
30
+ # Makes 2 backend requests: one for orgs, one for roles.
31
+ def roles_with_organizations
32
+ orgs_by_href = Organization.all(token: token, headers: headers)
33
+ .index_by(&:href)
34
+
35
+ roles.tap do |all_roles|
36
+ all_roles.each do |role|
37
+ org = orgs_by_href[role.links[:organization].href]
38
+ role.instance_variable_set(:@organization, org)
39
+ end
40
+ end
41
+ end
27
42
  end
28
43
  end
29
44
  end
@@ -1,5 +1,5 @@
1
1
  module Aptible
2
2
  module Auth
3
- VERSION = '1.4.0'.freeze
3
+ VERSION = '1.5.0'.freeze
4
4
  end
5
5
  end
@@ -229,4 +229,33 @@ describe Aptible::Auth::Token do
229
229
  expect(subject.send(:oauth)).to be(c)
230
230
  end
231
231
  end
232
+
233
+ describe '.current_token' do
234
+ let(:token_response) { double 'token_response' }
235
+ let(:access_token) { 'my_access_token' }
236
+ let(:root_url) { 'https://auth.example.com' }
237
+
238
+ before do
239
+ Aptible::Auth.configuration.root_url = root_url
240
+ end
241
+
242
+ it 'should fetch from /current_token endpoint with the provided token' do
243
+ expect(described_class).to receive(:find_by_url)
244
+ .with("#{root_url}/current_token", token: access_token)
245
+ .and_return(token_response)
246
+
247
+ expect(described_class.current_token(token: access_token)).to eq(token_response)
248
+ end
249
+
250
+ it 'should use configured root_url' do
251
+ custom_url = 'https://custom-auth.aptible.com'
252
+ Aptible::Auth.configuration.root_url = custom_url
253
+
254
+ expect(described_class).to receive(:find_by_url)
255
+ .with("#{custom_url}/current_token", token: access_token)
256
+ .and_return(token_response)
257
+
258
+ described_class.current_token(token: access_token)
259
+ end
260
+ end
232
261
  end
@@ -30,4 +30,95 @@ describe Aptible::Auth::User do
30
30
  expect(subject.organizations.count).to eq 1
31
31
  end
32
32
  end
33
+
34
+ describe '#roles_with_organizations' do
35
+ let(:token) { 'some-token' }
36
+ let(:headers) { { 'Authorization' => 'Bearer some-token' } }
37
+
38
+ let(:org1) do
39
+ double('Aptible::Auth::Organization', href: '/organizations/1', id: 1)
40
+ end
41
+ let(:org2) do
42
+ double('Aptible::Auth::Organization', href: '/organizations/2', id: 2)
43
+ end
44
+
45
+ let(:org1_link) do
46
+ double('Aptible::Auth::Organization::Link', href: '/organizations/1')
47
+ end
48
+ let(:org2_link) do
49
+ double('Aptible::Auth::Organization::Link', href: '/organizations/2')
50
+ end
51
+
52
+ let(:role1_links) { double('Role1::Links') }
53
+ let(:role2_links) { double('Role2::Links') }
54
+ let(:role3_links) { double('Role3::Links') }
55
+
56
+ let(:role1) { Aptible::Auth::Role.new }
57
+ let(:role2) { Aptible::Auth::Role.new }
58
+ let(:role3) { Aptible::Auth::Role.new }
59
+
60
+ before do
61
+ subject.stub(:token) { token }
62
+ subject.stub(:headers) { headers }
63
+
64
+ role1_links.stub(:[]).with(:organization) { org1_link }
65
+ role2_links.stub(:[]).with(:organization) { org2_link }
66
+ role3_links.stub(:[]).with(:organization) { org1_link }
67
+
68
+ role1.stub(:links) { role1_links }
69
+ role2.stub(:links) { role2_links }
70
+ role3.stub(:links) { role3_links }
71
+ end
72
+
73
+ it 'returns the roles' do
74
+ allow(Aptible::Auth::Organization).to receive(:all).and_return([org1])
75
+ subject.stub(:roles) { [role1] }
76
+
77
+ expect(subject.roles_with_organizations).to eq [role1]
78
+ end
79
+
80
+ it 'pre-populates @organization on each role' do
81
+ allow(Aptible::Auth::Organization).to receive(:all)
82
+ .with(token: token, headers: headers)
83
+ .and_return([org1, org2])
84
+ subject.stub(:roles) { [role1, role2] }
85
+
86
+ subject.roles_with_organizations
87
+
88
+ expect(role1.instance_variable_get(:@organization)).to eq org1
89
+ expect(role2.instance_variable_get(:@organization)).to eq org2
90
+ end
91
+
92
+ it 'maps multiple roles to the same organization' do
93
+ allow(Aptible::Auth::Organization).to receive(:all)
94
+ .with(token: token, headers: headers)
95
+ .and_return([org1, org2])
96
+ subject.stub(:roles) { [role1, role2, role3] }
97
+
98
+ subject.roles_with_organizations
99
+
100
+ expect(role1.instance_variable_get(:@organization)).to eq org1
101
+ expect(role2.instance_variable_get(:@organization)).to eq org2
102
+ expect(role3.instance_variable_get(:@organization)).to eq org1
103
+ end
104
+
105
+ it 'returns empty array when user has no roles' do
106
+ allow(Aptible::Auth::Organization).to receive(:all)
107
+ .with(token: token, headers: headers)
108
+ .and_return([])
109
+ subject.stub(:roles) { [] }
110
+
111
+ expect(subject.roles_with_organizations).to eq []
112
+ end
113
+
114
+ it 'makes exactly one call to Organization.all' do
115
+ expect(Aptible::Auth::Organization).to receive(:all)
116
+ .with(token: token, headers: headers)
117
+ .once
118
+ .and_return([org1])
119
+ subject.stub(:roles) { [role1] }
120
+
121
+ subject.roles_with_organizations
122
+ end
123
+ end
33
124
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aptible-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-17 00:00:00.000000000 Z
11
+ date: 2025-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aptible-resource
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.6.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: httplog
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: pry
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -159,6 +173,7 @@ extra_rdoc_files: []
159
173
  files:
160
174
  - ".github/CODEOWNERS"
161
175
  - ".github/workflows/ci.yml"
176
+ - ".github/workflows/release.yml"
162
177
  - ".gitignore"
163
178
  - ".rspec"
164
179
  - Dockerfile