osso 0.0.3.7 → 0.0.3.12

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/pipeline.yml +5 -3
  3. data/Gemfile.lock +5 -1
  4. data/bin/annotate +1 -0
  5. data/db/schema.rb +11 -54
  6. data/lib/osso/db/migrate/20200714223226_add_identity_provider_service_enum.rb +1 -1
  7. data/lib/osso/db/migrate/20200722230116_add_identity_provider_status_enum_and_use_on_identity_providers.rb +15 -0
  8. data/lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb +35 -0
  9. data/lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb +9 -0
  10. data/lib/osso/graphql/mutation.rb +7 -1
  11. data/lib/osso/graphql/mutations.rb +7 -1
  12. data/lib/osso/graphql/mutations/add_redirect_uris_to_oauth_client.rb +39 -0
  13. data/lib/osso/graphql/mutations/configure_identity_provider.rb +1 -1
  14. data/lib/osso/graphql/mutations/create_oauth_client.rb +30 -0
  15. data/lib/osso/graphql/mutations/delete_enterprise_account.rb +34 -0
  16. data/lib/osso/graphql/mutations/delete_oauth_client.rb +30 -0
  17. data/lib/osso/graphql/mutations/delete_redirect_uri.rb +38 -0
  18. data/lib/osso/graphql/mutations/mark_redirect_uri_primary.rb +34 -0
  19. data/lib/osso/graphql/mutations/regenerate_oauth_credentials.rb +31 -0
  20. data/lib/osso/graphql/query.rb +15 -2
  21. data/lib/osso/graphql/resolvers/enterprise_accounts.rb +12 -4
  22. data/lib/osso/graphql/resolvers/oauth_clients.rb +1 -1
  23. data/lib/osso/graphql/types.rb +3 -0
  24. data/lib/osso/graphql/types/base_connection.rb +15 -0
  25. data/lib/osso/graphql/types/base_object.rb +4 -0
  26. data/lib/osso/graphql/types/identity_provider.rb +1 -5
  27. data/lib/osso/graphql/types/identity_provider_status.rb +14 -0
  28. data/lib/osso/graphql/types/oauth_client.rb +14 -1
  29. data/lib/osso/graphql/types/redirect_uri.rb +23 -0
  30. data/lib/osso/helpers/auth.rb +13 -12
  31. data/lib/osso/models/access_token.rb +18 -0
  32. data/lib/osso/models/authorization_code.rb +20 -0
  33. data/lib/osso/models/enterprise_account.rb +20 -0
  34. data/lib/osso/models/identity_provider.rb +29 -0
  35. data/lib/osso/models/models.rb +2 -0
  36. data/lib/osso/models/oauth_client.rb +20 -10
  37. data/lib/osso/models/redirect_uri.rb +17 -0
  38. data/lib/osso/models/user.rb +22 -0
  39. data/lib/osso/routes/admin.rb +6 -0
  40. data/lib/osso/routes/auth.rb +1 -1
  41. data/lib/osso/version.rb +1 -1
  42. data/osso-rb.gemspec +1 -0
  43. data/spec/factories/identity_providers.rb +22 -0
  44. data/spec/graphql/mutations/configure_identity_provider_spec.rb +3 -3
  45. data/spec/graphql/mutations/create_oauth_client_spec.rb +55 -0
  46. data/spec/graphql/mutations/delete_enterprise_account_spec.rb +63 -0
  47. data/spec/graphql/mutations/delete_oauth_client_spec.rb +51 -0
  48. data/spec/graphql/query/enterprise_account_spec.rb +1 -1
  49. data/spec/graphql/query/enterprise_accounts_spec.rb +32 -18
  50. data/spec/graphql/query/identity_provider_spec.rb +2 -2
  51. data/spec/graphql/query/{oauth_clients_account_spec.rb → oauth_clients_spec.rb} +2 -0
  52. data/spec/routes/auth_spec.rb +25 -0
  53. metadata +35 -8
  54. data/lib/osso/db/migrate/20200328143303_create_oauth_tables.rb +0 -57
  55. data/lib/osso/graphql/mutations/set_identity_provider.rb +0 -27
  56. data/lib/osso/models/saml_provider.rb +0 -49
  57. data/lib/osso/models/saml_providers/azure_saml_provider.rb +0 -22
  58. data/lib/osso/models/saml_providers/okta_saml_provider.rb +0 -23
@@ -18,3 +18,20 @@ module Osso
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ # == Schema Information
23
+ #
24
+ # Table name: redirect_uris
25
+ #
26
+ # id :uuid not null, primary key
27
+ # uri :string not null
28
+ # primary :boolean default(FALSE), not null
29
+ # oauth_client_id :uuid
30
+ # created_at :datetime not null
31
+ # updated_at :datetime not null
32
+ #
33
+ # Indexes
34
+ #
35
+ # index_redirect_uris_on_oauth_client_id (oauth_client_id)
36
+ # index_redirect_uris_on_uri_and_primary (uri,primary) UNIQUE
37
+ #
@@ -22,3 +22,25 @@ module Osso
22
22
  end
23
23
  end
24
24
  end
25
+
26
+ # == Schema Information
27
+ #
28
+ # Table name: users
29
+ #
30
+ # id :uuid not null, primary key
31
+ # email :string not null
32
+ # idp_id :string not null
33
+ # identity_provider_id :uuid
34
+ # enterprise_account_id :uuid
35
+ # created_at :datetime not null
36
+ # updated_at :datetime not null
37
+ #
38
+ # Indexes
39
+ #
40
+ # index_users_on_email_and_idp_id (email,idp_id) UNIQUE
41
+ # index_users_on_enterprise_account_id (enterprise_account_id)
42
+ #
43
+ # Foreign Keys
44
+ #
45
+ # fk_rails_... (identity_provider_id => identity_providers.id)
46
+ #
@@ -36,6 +36,12 @@ module Osso
36
36
 
37
37
  erb :admin
38
38
  end
39
+
40
+ get '/config/:id' do
41
+ admin_protected!
42
+
43
+ erb :admin
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -23,7 +23,7 @@ module Osso
23
23
  self,
24
24
  provider_name: 'saml',
25
25
  identity_provider_id_regex: UUID_REGEXP,
26
- path_prefix: '/saml',
26
+ path_prefix: '/auth/saml',
27
27
  callback_suffix: 'callback',
28
28
  ) do |identity_provider_id, _env|
29
29
  provider = Models::IdentityProvider.find(identity_provider_id)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.7'
4
+ VERSION = '0.0.3.12'
5
5
  end
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_runtime_dependency 'sinatra-activerecord'
29
29
  spec.add_runtime_dependency 'sinatra-contrib'
30
30
 
31
+ spec.add_development_dependency 'annotate', '~> 3.1'
31
32
  spec.add_development_dependency 'bundler', '~> 2.1'
32
33
  spec.add_development_dependency 'pry'
33
34
 
@@ -47,3 +47,25 @@ FactoryBot.define do
47
47
  end
48
48
  end
49
49
  end
50
+
51
+ # == Schema Information
52
+ #
53
+ # Table name: identity_providers
54
+ #
55
+ # id :uuid not null, primary key
56
+ # service :string
57
+ # domain :string not null
58
+ # sso_url :string
59
+ # sso_cert :text
60
+ # enterprise_account_id :uuid
61
+ # oauth_client_id :uuid
62
+ # status :enum default("PENDING")
63
+ # created_at :datetime
64
+ # updated_at :datetime
65
+ #
66
+ # Indexes
67
+ #
68
+ # index_identity_providers_on_domain (domain)
69
+ # index_identity_providers_on_enterprise_account_id (enterprise_account_id)
70
+ # index_identity_providers_on_oauth_client_id (oauth_client_id)
71
+ #
@@ -23,7 +23,7 @@ describe Osso::GraphQL::Schema do
23
23
  identityProvider {
24
24
  id
25
25
  domain
26
- configured
26
+ status
27
27
  enterpriseAccountId
28
28
  service
29
29
  acsUrl
@@ -46,8 +46,8 @@ describe Osso::GraphQL::Schema do
46
46
  describe 'for an admin user' do
47
47
  let(:current_scope) { :admin }
48
48
  it 'configures an identity provider' do
49
- expect(subject.dig('data', 'configureIdentityProvider', 'identityProvider', 'configured')).
50
- to be true
49
+ expect(subject.dig('data', 'configureIdentityProvider', 'identityProvider', 'status')).
50
+ to eq('Configured')
51
51
  end
52
52
  end
53
53
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'CreateOauthClient' do
7
+ let(:variables) do
8
+ {
9
+ input: {
10
+ name: Faker::Company.name,
11
+ },
12
+ }
13
+ end
14
+
15
+ let(:mutation) do
16
+ <<~GRAPHQL
17
+ mutation CreateOauthClient($input: CreateOauthClientInput!) {
18
+ createOauthClient(input: $input) {
19
+ oauthClient {
20
+ id
21
+ name
22
+ clientId
23
+ clientSecret
24
+ }
25
+ }
26
+ }
27
+ GRAPHQL
28
+ end
29
+
30
+ subject do
31
+ described_class.execute(
32
+ mutation,
33
+ variables: variables,
34
+ context: { scope: current_scope },
35
+ )
36
+ end
37
+
38
+ describe 'for an admin user' do
39
+ let(:current_scope) { :admin }
40
+ it 'creates an OauthClient' do
41
+ expect { subject }.to change { Osso::Models::OauthClient.count }.by(1)
42
+ expect(subject.dig('data', 'createOauthClient', 'oauthClient', 'clientId')).
43
+ to_not be_nil
44
+ end
45
+ end
46
+
47
+ describe 'for an email scoped user' do
48
+ let(:current_scope) { 'foo.com' }
49
+
50
+ it 'does not create an OauthClient Account' do
51
+ expect { subject }.to_not(change { Osso::Models::OauthClient.count })
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'DeleteEnterpriseAccount' do
7
+ let(:domain) { Faker::Internet.domain_name }
8
+ let!(:enterprise_account) { create(:enterprise_account, domain: domain) }
9
+ let(:variables) do
10
+ {
11
+ input: {
12
+ id: enterprise_account.id,
13
+ },
14
+ }
15
+ end
16
+
17
+ let(:mutation) do
18
+ <<~GRAPHQL
19
+ mutation DeleteEnterpriseAccount($input: DeleteEnterpriseAccountInput!) {
20
+ deleteEnterpriseAccount(input: $input) {
21
+ enterpriseAccount {
22
+ id
23
+ }
24
+ }
25
+ }
26
+ GRAPHQL
27
+ end
28
+
29
+ subject do
30
+ described_class.execute(
31
+ mutation,
32
+ variables: variables,
33
+ context: { scope: current_scope },
34
+ )
35
+ end
36
+
37
+ describe 'for an admin user' do
38
+ let(:current_scope) { :admin }
39
+ it 'deletes an Enterprise Account' do
40
+ expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(-1)
41
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount')).
42
+ to be_nil
43
+ end
44
+ end
45
+
46
+ describe 'for an email scoped user' do
47
+ let(:current_scope) { domain }
48
+
49
+ it 'deletes the Enterprise Account' do
50
+ expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(-1)
51
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount')).
52
+ to be_nil
53
+ end
54
+ end
55
+ describe 'for the wrong email scoped user' do
56
+ let(:current_scope) { 'foo.com' }
57
+
58
+ it 'does not delete the Enterprise Account' do
59
+ expect { subject }.to_not(change { Osso::Models::EnterpriseAccount.count })
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'DeleteOauthClient' do
7
+ let!(:oauth_client) { create(:oauth_client) }
8
+ let(:variables) do
9
+ {
10
+ input: {
11
+ id: oauth_client.id,
12
+ },
13
+ }
14
+ end
15
+
16
+ let(:mutation) do
17
+ <<~GRAPHQL
18
+ mutation DeleteOauthClient($input: DeleteOauthClientInput!) {
19
+ deleteOauthClient(input: $input) {
20
+ oauthClient {
21
+ id
22
+ }
23
+ }
24
+ }
25
+ GRAPHQL
26
+ end
27
+
28
+ subject do
29
+ described_class.execute(
30
+ mutation,
31
+ variables: variables,
32
+ context: { scope: current_scope },
33
+ )
34
+ end
35
+
36
+ describe 'for an admin user' do
37
+ let(:current_scope) { :admin }
38
+ it 'deletes the OauthClient' do
39
+ expect { subject }.to change { Osso::Models::OauthClient.count }.by(-1)
40
+ end
41
+ end
42
+
43
+ describe 'for an email scoped user' do
44
+ let(:current_scope) { 'foo.com' }
45
+
46
+ it 'does not create an OauthClient Account' do
47
+ expect { subject }.to_not(change { Osso::Models::OauthClient.count })
48
+ end
49
+ end
50
+ end
51
+ end
@@ -19,7 +19,7 @@ describe Osso::GraphQL::Schema do
19
19
  acsUrl
20
20
  ssoCert
21
21
  ssoUrl
22
- configured
22
+ status
23
23
  }
24
24
  name
25
25
  status
@@ -7,37 +7,51 @@ describe Osso::GraphQL::Schema do
7
7
  describe 'for an admin user' do
8
8
  let(:current_scope) { :admin }
9
9
 
10
- it 'returns Enterprise Accounts' do
11
- create_list(:enterprise_account, 2)
10
+ it 'returns paginated Enterprise Accounts' do
11
+ %w[A B C].map do |name|
12
+ create(:enterprise_account, name: name)
13
+ end
12
14
 
13
15
  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
16
+ query EnterpriseAccounts($first: Int, $sortColumn: String, $sortOrder: String) {
17
+ enterpriseAccounts(first: $first, sortColumn: $sortColumn, sortOrder: $sortOrder) {
18
+ pageInfo {
19
+ hasNextPage
20
+ endCursor
21
+ }
22
+ totalCount
23
+ edges {
24
+ node {
25
+ domain
26
+ id
27
+ identityProviders {
28
+ id
29
+ service
30
+ domain
31
+ acsUrl
32
+ ssoCert
33
+ ssoUrl
34
+ status
35
+ }
36
+ name
37
+ status
38
+ }
26
39
  }
27
- name
28
- status
29
40
  }
30
41
  }
31
42
  GRAPHQL
32
43
 
33
44
  response = described_class.execute(
34
45
  query,
35
- variables: nil,
46
+ variables: { first: 2, sortOrder: 'descending', sortColumn: 'name' },
36
47
  context: { scope: current_scope },
37
48
  )
38
49
 
39
50
  expect(response['errors']).to be_nil
40
- expect(response.dig('data', 'enterpriseAccounts').count).to eq(2)
51
+ expect(response.dig('data', 'enterpriseAccounts', 'edges').count).to eq(2)
52
+ expect(response.dig('data', 'enterpriseAccounts', 'edges', 0, 'node', 'name')).to eq('C')
53
+ expect(response.dig('data', 'enterpriseAccounts', 'totalCount')).to eq(3)
54
+ expect(response.dig('data', 'enterpriseAccounts', 'pageInfo', 'hasNextPage')).to eq(true)
41
55
  end
42
56
  end
43
57
  end
@@ -17,7 +17,7 @@ describe Osso::GraphQL::Schema do
17
17
  acsUrl
18
18
  ssoCert
19
19
  ssoUrl
20
- configured
20
+ status
21
21
  }
22
22
  }
23
23
  GRAPHQL
@@ -55,7 +55,7 @@ describe Osso::GraphQL::Schema do
55
55
 
56
56
  describe 'for the wrong email scoped user' do
57
57
  let(:current_scope) { 'bar.com' }
58
-
58
+
59
59
  it 'returns Enterprise Account for domain' do
60
60
  expect(subject['errors']).to_not be_empty
61
61
  expect(subject.dig('data', 'enterpriseAccount')).to be_nil
@@ -10,6 +10,8 @@ describe Osso::GraphQL::Schema do
10
10
  oauthClients {
11
11
  name
12
12
  id
13
+ clientSecret
14
+ clientId
13
15
  }
14
16
  }
15
17
  GRAPHQL
@@ -3,6 +3,31 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Osso::Auth do
6
+ describe 'get /auth/saml/:uuid' do
7
+ describe 'for an Okta SAML provider' do
8
+ let(:enterprise) { create(:enterprise_with_okta) }
9
+ let(:okta_provider) { enterprise.identity_providers.first }
10
+ it 'uses omniauth saml' do
11
+ get("/auth/saml/#{okta_provider.id}")
12
+
13
+ expect(last_response).to be_redirect
14
+ follow_redirect!
15
+ expect(last_request.url).to match("auth/saml/#{okta_provider.id}")
16
+ end
17
+ end
18
+
19
+ describe 'for an Azure SAML provider' do
20
+ let(:enterprise) { create(:enterprise_with_okta) }
21
+ let(:azure_provider) { enterprise.identity_providers.first }
22
+ it 'uses omniauth saml' do
23
+ get("/auth/saml/#{azure_provider.id}")
24
+
25
+ expect(last_response).to be_redirect
26
+ follow_redirect!
27
+ expect(last_request.url).to match("auth/saml/#{azure_provider.id}")
28
+ end
29
+ end
30
+ end
6
31
  describe 'post /auth/saml/:uuid/callback' do
7
32
  describe 'for an Okta SAML provider' do
8
33
  let(:enterprise) { create(:enterprise_with_okta) }