osso 0.0.3.2 → 0.0.3.7

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/pipeline.yml +4 -1
  3. data/.rubocop.yml +1 -2
  4. data/Gemfile.lock +3 -1
  5. data/bin/console +4 -3
  6. data/config/database.yml +2 -2
  7. data/db/schema.rb +133 -1
  8. data/lib/osso.rb +2 -0
  9. data/lib/osso/db/migrate/20200328143305_create_identity_providers.rb +12 -0
  10. data/lib/osso/db/migrate/20200411184535_add_provider_id_to_users.rb +2 -2
  11. data/lib/osso/db/migrate/20200411192645_create_enterprise_accounts.rb +1 -1
  12. data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_accounts_and_identity_providers.rb +6 -0
  13. data/lib/osso/db/migrate/20200714223226_add_identity_provider_service_enum.rb +17 -0
  14. data/lib/osso/db/migrate/20200715154211_rename_idp_fields_on_identity_provider_to_sso.rb +6 -0
  15. data/lib/osso/db/migrate/20200715205801_add_name_to_enterprise_account.rb +5 -0
  16. data/lib/osso/graphql/mutation.rb +10 -5
  17. data/lib/osso/graphql/mutations.rb +5 -2
  18. data/lib/osso/graphql/mutations/base_mutation.rb +35 -14
  19. data/lib/osso/graphql/mutations/configure_identity_provider.rb +31 -21
  20. data/lib/osso/graphql/mutations/create_enterprise_account.rb +25 -0
  21. data/lib/osso/graphql/mutations/create_identity_provider.rb +22 -16
  22. data/lib/osso/graphql/mutations/set_identity_provider.rb +27 -0
  23. data/lib/osso/graphql/query.rb +19 -22
  24. data/lib/osso/graphql/resolvers.rb +5 -1
  25. data/lib/osso/graphql/resolvers/enterprise_account.rb +16 -12
  26. data/lib/osso/graphql/resolvers/enterprise_accounts.rb +10 -6
  27. data/lib/osso/graphql/resolvers/oauth_clients.rb +9 -5
  28. data/lib/osso/graphql/schema.rb +27 -19
  29. data/lib/osso/graphql/types.rb +4 -1
  30. data/lib/osso/graphql/types/base_enum.rb +6 -2
  31. data/lib/osso/graphql/types/base_input_object.rb +10 -0
  32. data/lib/osso/graphql/types/base_object.rb +6 -2
  33. data/lib/osso/graphql/types/enterprise_account.rb +22 -18
  34. data/lib/osso/graphql/types/identity_provider.rb +26 -25
  35. data/lib/osso/graphql/types/identity_provider_service.rb +8 -4
  36. data/lib/osso/graphql/types/oauth_client.rb +13 -9
  37. data/lib/osso/graphql/types/user.rb +10 -5
  38. data/lib/osso/helpers/auth.rb +5 -3
  39. data/lib/osso/lib/app_config.rb +1 -1
  40. data/lib/osso/lib/route_map.rb +28 -0
  41. data/lib/osso/models/enterprise_account.rb +4 -4
  42. data/lib/osso/models/identity_provider.rb +48 -0
  43. data/lib/osso/models/models.rb +1 -1
  44. data/lib/osso/models/oauth_client.rb +2 -2
  45. data/lib/osso/models/saml_provider.rb +13 -16
  46. data/lib/osso/models/saml_providers/azure_saml_provider.rb +2 -2
  47. data/lib/osso/models/saml_providers/okta_saml_provider.rb +1 -1
  48. data/lib/osso/models/user.rb +3 -3
  49. data/lib/osso/routes/admin.rb +18 -15
  50. data/lib/osso/routes/auth.rb +30 -27
  51. data/lib/osso/routes/oauth.rb +50 -45
  52. data/lib/osso/version.rb +1 -1
  53. data/osso-rb.gemspec +3 -3
  54. data/spec/factories/enterprise_account.rb +5 -4
  55. data/spec/factories/identity_providers.rb +49 -0
  56. data/spec/factories/user.rb +1 -1
  57. data/spec/graphql/mutations/configure_identity_provider_spec.rb +75 -0
  58. data/spec/graphql/mutations/create_enterprise_account_spec.rb +68 -0
  59. data/spec/graphql/mutations/create_identity_provider_spec.rb +104 -0
  60. data/spec/graphql/query/enterprise_account_spec.rb +68 -0
  61. data/spec/graphql/query/enterprise_accounts_spec.rb +44 -0
  62. data/spec/graphql/query/identity_provider_spec.rb +65 -0
  63. data/spec/graphql/query/oauth_clients_account_spec.rb +48 -0
  64. data/spec/models/azure_saml_provider_spec.rb +14 -14
  65. data/spec/models/identity_provider_spec.rb +17 -0
  66. data/spec/models/okta_saml_provider_spec.rb +15 -15
  67. data/spec/routes/admin_spec.rb +2 -0
  68. data/spec/routes/auth_spec.rb +9 -9
  69. data/spec/routes/oauth_spec.rb +1 -1
  70. data/spec/spec_helper.rb +4 -5
  71. data/spec/support/spec_app.rb +9 -0
  72. data/spec/support/views/admin.erb +5 -0
  73. metadata +37 -12
  74. data/lib/osso/db/migrate/20200411144528_create_saml_providers.rb +0 -13
  75. data/lib/osso/db/migrate/20200413153029_add_oauth_client_reference_to_saml_providers.rb +0 -5
  76. data/lib/osso/db/migrate/20200501203026_drop_null_constraints_from_saml_provider.rb +0 -7
  77. data/lib/osso/db/migrate/20200501204047_drop_acs_url.rb +0 -5
  78. data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_account.rb +0 -5
  79. data/lib/osso/db/migrate/20200601131227_drop_null_constraint_from_saml_providers_provider.rb +0 -7
  80. data/lib/osso/db/schema.rb +0 -132
  81. data/lib/osso/graphql/mutations/set_saml_provider.rb +0 -23
  82. data/spec/factories/saml_providers.rb +0 -46
  83. data/spec/models/saml_provider_spec.rb +0 -31
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'EnterpriseAccount' do
7
+ let(:domain) { Faker::Internet.domain_name }
8
+ let(:variables) { { domain: domain } }
9
+ let(:query) do
10
+ <<~GRAPHQL
11
+ query EnterpriseAccount($domain: String!) {
12
+ enterpriseAccount(domain: $domain) {
13
+ domain
14
+ id
15
+ identityProviders {
16
+ id
17
+ service
18
+ domain
19
+ acsUrl
20
+ ssoCert
21
+ ssoUrl
22
+ configured
23
+ }
24
+ name
25
+ status
26
+ }
27
+ }
28
+ GRAPHQL
29
+ end
30
+
31
+ before do
32
+ create(:enterprise_account)
33
+ create(:enterprise_account, domain: domain)
34
+ end
35
+
36
+ subject do
37
+ described_class.execute(
38
+ query,
39
+ variables: variables,
40
+ context: { scope: current_scope },
41
+ )
42
+ end
43
+
44
+ describe 'for an admin user' do
45
+ let(:current_scope) { :admin }
46
+ it 'returns Enterprise Account for domain' do
47
+ expect(subject['errors']).to be_nil
48
+ expect(subject.dig('data', 'enterpriseAccount', 'domain')).to eq(domain)
49
+ end
50
+ end
51
+
52
+ describe 'for an email scoped user' do
53
+ let(:current_scope) { domain }
54
+ it 'returns Enterprise Account for domain' do
55
+ expect(subject['errors']).to be_nil
56
+ expect(subject.dig('data', 'enterpriseAccount', 'domain')).to eq(domain)
57
+ end
58
+ end
59
+
60
+ describe 'for the wrong email scoped user' do
61
+ let(:current_scope) { 'bar.com' }
62
+ it 'returns Enterprise Account for domain' do
63
+ expect(subject['errors']).to be_nil
64
+ expect(subject.dig('data', 'enterpriseAccount')).to be_nil
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'EnterpriseAccounts' do
7
+ describe 'for an admin user' do
8
+ let(:current_scope) { :admin }
9
+
10
+ it 'returns Enterprise Accounts' do
11
+ create_list(:enterprise_account, 2)
12
+
13
+ query = <<~GRAPHQL
14
+ query EnterpriseAccounts {
15
+ enterpriseAccounts {
16
+ domain
17
+ id
18
+ identityProviders {
19
+ id
20
+ service
21
+ domain
22
+ acsUrl
23
+ ssoCert
24
+ ssoUrl
25
+ configured
26
+ }
27
+ name
28
+ status
29
+ }
30
+ }
31
+ GRAPHQL
32
+
33
+ response = described_class.execute(
34
+ query,
35
+ variables: nil,
36
+ context: { scope: current_scope },
37
+ )
38
+
39
+ expect(response['errors']).to be_nil
40
+ expect(response.dig('data', 'enterpriseAccounts').count).to eq(2)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'Identity Provider' do
7
+ let(:id) { Faker::Internet.uuid }
8
+ let(:domain) { Faker::Internet.domain_name }
9
+ let(:variables) { { id: id } }
10
+ let(:query) do
11
+ <<~GRAPHQL
12
+ query IdentityProvider($id: ID!) {
13
+ identityProvider(id: $id) {
14
+ id
15
+ service
16
+ domain
17
+ acsUrl
18
+ ssoCert
19
+ ssoUrl
20
+ configured
21
+ }
22
+ }
23
+ GRAPHQL
24
+ end
25
+
26
+ before do
27
+ create(:identity_provider)
28
+ create(:identity_provider, id: id, domain: domain)
29
+ end
30
+
31
+ subject do
32
+ described_class.execute(
33
+ query,
34
+ variables: variables,
35
+ context: { scope: current_scope },
36
+ )
37
+ end
38
+
39
+ describe 'for an admin user' do
40
+ let(:current_scope) { :admin }
41
+ it 'returns Identity Provider for id' do
42
+ expect(subject['errors']).to be_nil
43
+ expect(subject.dig('data', 'identityProvider', 'id')).to eq(id)
44
+ end
45
+ end
46
+
47
+ describe 'for an email scoped user' do
48
+ let(:current_scope) { domain }
49
+
50
+ it 'returns Enterprise Account for domain' do
51
+ expect(subject['errors']).to be_nil
52
+ expect(subject.dig('data', 'identityProvider', 'domain')).to eq(domain)
53
+ end
54
+ end
55
+
56
+ describe 'for the wrong email scoped user' do
57
+ let(:current_scope) { 'bar.com' }
58
+
59
+ it 'returns Enterprise Account for domain' do
60
+ expect(subject['errors']).to_not be_empty
61
+ expect(subject.dig('data', 'enterpriseAccount')).to be_nil
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'OAuthClients' do
7
+ let(:query) do
8
+ <<~GRAPHQL
9
+ query OAuthClients {
10
+ oauthClients {
11
+ name
12
+ id
13
+ }
14
+ }
15
+ GRAPHQL
16
+ end
17
+
18
+ before do
19
+ create_list(:oauth_client, 2)
20
+ end
21
+
22
+ subject do
23
+ described_class.execute(
24
+ query,
25
+ variables: nil,
26
+ context: { scope: current_scope },
27
+ )
28
+ end
29
+
30
+ describe 'for an admin user' do
31
+ let(:current_scope) { :admin }
32
+
33
+ it 'returns Oauth Clients' do
34
+ expect(subject['errors']).to be_nil
35
+ expect(subject.dig('data', 'oauthClients').count).to eq(2)
36
+ end
37
+ end
38
+
39
+ describe 'for an email scoped user' do
40
+ let(:current_scope) { 'foo.com' }
41
+
42
+ it 'returns Oauth Clients' do
43
+ expect(subject['errors']).to be_nil
44
+ expect(subject.dig('data', 'oauthClients')).to be_nil
45
+ end
46
+ end
47
+ end
48
+ end
@@ -2,18 +2,18 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Osso::Models::AzureSamlProvider do
6
- subject { create(:azure_saml_provider) }
5
+ # describe Osso::Models::AzureSamlProvider do
6
+ # subject { create(:azure_identity_provider) }
7
7
 
8
- describe '#saml_options' do
9
- it 'returns the required args' do
10
- expect(subject.saml_options).
11
- to match(
12
- domain: subject.domain,
13
- idp_cert: subject.idp_cert,
14
- idp_sso_target_url: subject.idp_sso_target_url,
15
- issuer: "id:#{subject.id}",
16
- )
17
- end
18
- end
19
- end
8
+ # describe '#saml_options' do
9
+ # it 'returns the required args' do
10
+ # expect(subject.saml_options).
11
+ # to match(
12
+ # domain: subject.domain,
13
+ # idp_cert: subject.idp_cert,
14
+ # idp_sso_target_url: subject.idp_sso_target_url,
15
+ # issuer: "id:#{subject.id}",
16
+ # )
17
+ # end
18
+ # end
19
+ # end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::Models::IdentityProvider do
6
+ subject { create(:okta_identity_provider) }
7
+
8
+ describe '#assertion_consumer_service_url' do
9
+ it 'returns the expected URI' do
10
+ ENV['BASE_URL'] = 'https://example.com'
11
+
12
+ expect(subject.assertion_consumer_service_url).to eq(
13
+ "https://example.com/auth/saml/#{subject.id}/callback",
14
+ )
15
+ end
16
+ end
17
+ end
@@ -2,19 +2,19 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Osso::Models::OktaSamlProvider do
6
- subject { create(:okta_saml_provider) }
5
+ # describe Osso::Models::OktaSamlProvider do
6
+ # subject { create(:okta_identity_provider) }
7
7
 
8
- describe '#saml_options' do
9
- it 'returns the required args' do
10
- expect(subject.saml_options).
11
- to match(
12
- domain: subject.domain,
13
- idp_cert: subject.idp_cert,
14
- idp_sso_target_url: subject.idp_sso_target_url,
15
- issuer: subject.id,
16
- name_identifier_format: described_class::NAME_FORMAT,
17
- )
18
- end
19
- end
20
- end
8
+ # describe '#saml_options' do
9
+ # it 'returns the required args' do
10
+ # expect(subject.saml_options).
11
+ # to match(
12
+ # domain: subject.domain,
13
+ # idp_cert: subject.idp_cert,
14
+ # idp_sso_target_url: subject.idp_sso_target_url,
15
+ # issuer: subject.id,
16
+ # name_identifier_format: described_class::NAME_FORMAT,
17
+ # )
18
+ # end
19
+ # end
20
+ # end
@@ -25,7 +25,9 @@ describe Osso::Admin do
25
25
  get('/admin', token: SecureRandom.hex(32))
26
26
 
27
27
  expect(last_response).to be_redirect
28
+
28
29
  follow_redirect!
30
+
29
31
  expect(last_request.url).to eq(jwt_url)
30
32
  end
31
33
 
@@ -6,7 +6,7 @@ describe Osso::Auth do
6
6
  describe 'post /auth/saml/:uuid/callback' do
7
7
  describe 'for an Okta SAML provider' do
8
8
  let(:enterprise) { create(:enterprise_with_okta) }
9
- let(:okta_provider) { enterprise.saml_providers.first }
9
+ let(:okta_provider) { enterprise.identity_providers.first }
10
10
 
11
11
  describe "on the user's first authentication" do
12
12
  it 'creates a user' do
@@ -18,7 +18,7 @@ describe Osso::Auth do
18
18
  nil,
19
19
  {
20
20
  'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
21
- 'saml_provider' => okta_provider,
21
+ 'identity_provider' => okta_provider,
22
22
  },
23
23
  )
24
24
  end.to change { Osso::Models::User.count }.by(1)
@@ -33,7 +33,7 @@ describe Osso::Auth do
33
33
  nil,
34
34
  {
35
35
  'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
36
- 'saml_provider' => okta_provider,
36
+ 'identity_provider' => okta_provider,
37
37
  },
38
38
  )
39
39
  end.to change { Osso::Models::AuthorizationCode.count }.by(1)
@@ -42,8 +42,8 @@ describe Osso::Auth do
42
42
 
43
43
  describe 'on subsequent authentications' do
44
44
  let!(:enterprise) { create(:enterprise_with_okta) }
45
- let!(:okta_provider) { enterprise.saml_providers.first }
46
- let(:user) { create(:user, saml_provider_id: okta_provider.id) }
45
+ let!(:okta_provider) { enterprise.identity_providers.first }
46
+ let(:user) { create(:user, identity_provider_id: okta_provider.id) }
47
47
 
48
48
  before do
49
49
  mock_saml_omniauth(email: user.email, id: user.idp_id)
@@ -56,7 +56,7 @@ describe Osso::Auth do
56
56
  nil,
57
57
  {
58
58
  'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
59
- 'saml_provider' => okta_provider,
59
+ 'identity_provider' => okta_provider,
60
60
  },
61
61
  )
62
62
  end.to_not(change { Osso::Models::User.count })
@@ -78,7 +78,7 @@ describe Osso::Auth do
78
78
  nil,
79
79
  {
80
80
  'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
81
- 'saml_provider' => azure_provider,
81
+ 'identity_provider' => azure_provider,
82
82
  },
83
83
  )
84
84
  end.to change { Osso::Models::User.count }.by(1)
@@ -88,7 +88,7 @@ describe Osso::Auth do
88
88
  describe 'on subsequent authentications' do
89
89
  let!(:enterprise) { create(:enterprise_with_azure) }
90
90
  let!(:azure_provider) { enterprise.provider }
91
- let(:user) { create(:user, saml_provider_id: azure_provider.id) }
91
+ let(:user) { create(:user, identity_provider_id: azure_provider.id) }
92
92
 
93
93
  before do
94
94
  mock_saml_omniauth(email: user.email, id: user.idp_id)
@@ -101,7 +101,7 @@ describe Osso::Auth do
101
101
  nil,
102
102
  {
103
103
  'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
104
- 'saml_provider' => azure_provider,
104
+ 'identity_provider' => azure_provider,
105
105
  },
106
106
  )
107
107
  end.to_not(change { Osso::Models::User.count })
@@ -35,7 +35,7 @@ describe Osso::Oauth do
35
35
  redirect_uri: client.redirect_uri_values.sample,
36
36
  )
37
37
 
38
- provider_id = enterprise.saml_providers.first.id
38
+ provider_id = enterprise.identity_providers.first.id
39
39
 
40
40
  expect(last_response).to be_redirect
41
41
  follow_redirect!
@@ -11,18 +11,17 @@ require 'webmock/rspec'
11
11
 
12
12
  ENV['RACK_ENV'] = 'test'
13
13
  ENV['SESSION_SECRET'] = 'supersecret'
14
+ ENV['BASE_URL'] = 'https://example.com'
14
15
 
15
16
  require File.expand_path '../lib/osso.rb', __dir__
16
17
 
18
+ require File.expand_path 'support/spec_app', __dir__
19
+
17
20
  module RSpecMixin
18
21
  include Rack::Test::Methods
19
22
 
20
23
  def app
21
- Rack::URLMap.new(
22
- '/admin' => Osso::Admin,
23
- '/auth' => Osso::Auth,
24
- '/oauth' => Osso::Oauth,
25
- )
24
+ SpecApp
26
25
  end
27
26
 
28
27
  def mock_saml_omniauth(email: 'user@enterprise.com', id: SecureRandom.uuid)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SpecApp < Sinatra::Base
4
+ include Osso::RouteMap
5
+
6
+ get '/health' do
7
+ 'ok'
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ <%#
2
+ NB: this file exists so that the admin routes have something to render in spec.
3
+ In real-world usage, those routes render an index.html file that includes the
4
+ React app.
5
+ %>