osso 0.0.3.1 → 0.0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) 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 +29 -14
  19. data/lib/osso/graphql/mutations/configure_identity_provider.rb +19 -18
  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 +23 -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 +19 -19
  34. data/lib/osso/graphql/types/identity_provider.rb +19 -27
  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 +53 -49
  39. data/lib/osso/helpers/helpers.rb +3 -1
  40. data/lib/osso/lib/app_config.rb +1 -1
  41. data/lib/osso/lib/route_map.rb +28 -0
  42. data/lib/osso/models/enterprise_account.rb +4 -4
  43. data/lib/osso/models/identity_provider.rb +48 -0
  44. data/lib/osso/models/models.rb +1 -1
  45. data/lib/osso/models/oauth_client.rb +2 -2
  46. data/lib/osso/models/saml_provider.rb +13 -16
  47. data/lib/osso/models/saml_providers/azure_saml_provider.rb +2 -2
  48. data/lib/osso/models/saml_providers/okta_saml_provider.rb +1 -1
  49. data/lib/osso/models/user.rb +3 -3
  50. data/lib/osso/routes/admin.rb +18 -15
  51. data/lib/osso/routes/auth.rb +30 -27
  52. data/lib/osso/routes/oauth.rb +50 -45
  53. data/lib/osso/version.rb +1 -1
  54. data/osso-rb.gemspec +3 -3
  55. data/spec/factories/enterprise_account.rb +5 -4
  56. data/spec/factories/identity_providers.rb +49 -0
  57. data/spec/factories/user.rb +1 -1
  58. data/spec/graphql/mutations/configure_identity_provider_spec.rb +65 -0
  59. data/spec/graphql/mutations/create_enterprise_account_spec.rb +68 -0
  60. data/spec/graphql/mutations/create_identity_provider_spec.rb +104 -0
  61. data/spec/graphql/query/enterprise_account_spec.rb +68 -0
  62. data/spec/graphql/query/enterprise_accounts_spec.rb +44 -0
  63. data/spec/graphql/query/identity_provider_spec.rb +62 -0
  64. data/spec/graphql/query/oauth_clients_account_spec.rb +48 -0
  65. data/spec/models/azure_saml_provider_spec.rb +14 -14
  66. data/spec/models/identity_provider_spec.rb +17 -0
  67. data/spec/models/okta_saml_provider_spec.rb +15 -15
  68. data/spec/routes/admin_spec.rb +2 -0
  69. data/spec/routes/auth_spec.rb +9 -9
  70. data/spec/routes/oauth_spec.rb +1 -1
  71. data/spec/spec_helper.rb +4 -5
  72. data/spec/support/spec_app.rb +9 -0
  73. data/spec/support/views/{public/index.erb → admin.erb} +0 -0
  74. metadata +37 -13
  75. data/lib/osso/db/migrate/20200411144528_create_saml_providers.rb +0 -13
  76. data/lib/osso/db/migrate/20200413153029_add_oauth_client_reference_to_saml_providers.rb +0 -5
  77. data/lib/osso/db/migrate/20200501203026_drop_null_constraints_from_saml_provider.rb +0 -7
  78. data/lib/osso/db/migrate/20200501204047_drop_acs_url.rb +0 -5
  79. data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_account.rb +0 -5
  80. data/lib/osso/db/migrate/20200601131227_drop_null_constraint_from_saml_providers_provider.rb +0 -7
  81. data/lib/osso/db/schema.rb +0 -132
  82. data/lib/osso/graphql/mutations/set_saml_provider.rb +0 -23
  83. data/spec/factories/saml_providers.rb +0 -46
  84. data/spec/models/saml_provider_spec.rb +0 -31
@@ -8,6 +8,7 @@ require 'omniauth-saml'
8
8
  module Osso
9
9
  class Auth < Sinatra::Base
10
10
  include AppConfig
11
+ register Sinatra::Namespace
11
12
 
12
13
  UUID_REGEXP =
13
14
  /[0-9a-f]{8}-[0-9a-f]{3,4}-[0-9a-f]{4}-[0-9a-f]{3,4}-[0-9a-f]{12}/.
@@ -24,41 +25,43 @@ module Osso
24
25
  identity_provider_id_regex: UUID_REGEXP,
25
26
  path_prefix: '/saml',
26
27
  callback_suffix: 'callback',
27
- ) do |saml_provider_id, _env|
28
- provider = Models::SamlProvider.find(saml_provider_id)
28
+ ) do |identity_provider_id, _env|
29
+ provider = Models::IdentityProvider.find(identity_provider_id)
29
30
  provider.saml_options
30
31
  end
31
32
  end
32
33
 
33
- # Enterprise users are sent here after authenticating against
34
- # their Identity Provider. We find or create a user record,
35
- # and then create an authorization code for that user. The user
36
- # is redirected back to your application with this code
37
- # as a URL query param, which you then exhange for an access token
38
- post '/saml/:id/callback' do
39
- provider = Models::SamlProvider.find(params[:id])
40
- oauth_client = provider.oauth_client
41
- redirect_uri = env['redirect_uri'] || oauth_client.default_redirect_uri.uri
34
+ namespace '/auth' do
35
+ # Enterprise users are sent here after authenticating against
36
+ # their Identity Provider. We find or create a user record,
37
+ # and then create an authorization code for that user. The user
38
+ # is redirected back to your application with this code
39
+ # as a URL query param, which you then exhange for an access token
40
+ post '/saml/:id/callback' do
41
+ provider = Models::IdentityProvider.find(params[:id])
42
+ oauth_client = provider.oauth_client
43
+ redirect_uri = env['redirect_uri'] || oauth_client.default_redirect_uri.uri
42
44
 
43
- attributes = env['omniauth.auth']&.
44
- extra&.
45
- response_object&.
46
- attributes
45
+ attributes = env['omniauth.auth']&.
46
+ extra&.
47
+ response_object&.
48
+ attributes
47
49
 
48
- user = Models::User.where(
49
- email: attributes[:email],
50
- idp_id: attributes[:id],
51
- ).first_or_create! do |new_user|
52
- new_user.enterprise_account_id = provider.enterprise_account_id
53
- new_user.saml_provider_id = provider.id
54
- end
50
+ user = Models::User.where(
51
+ email: attributes[:email],
52
+ idp_id: attributes[:id],
53
+ ).first_or_create! do |new_user|
54
+ new_user.enterprise_account_id = provider.enterprise_account_id
55
+ new_user.identity_provider_id = provider.id
56
+ end
55
57
 
56
- authorization_code = user.authorization_codes.create!(
57
- oauth_client: oauth_client,
58
- redirect_uri: redirect_uri,
59
- )
58
+ authorization_code = user.authorization_codes.create!(
59
+ oauth_client: oauth_client,
60
+ redirect_uri: redirect_uri,
61
+ )
60
62
 
61
- redirect(redirect_uri + "?code=#{CGI.escape(authorization_code.token)}&state=#{session[:oauth_state]}")
63
+ redirect(redirect_uri + "?code=#{CGI.escape(authorization_code.token)}&state=#{session[:oauth_state]}")
64
+ end
62
65
  end
63
66
  end
64
67
  end
@@ -5,54 +5,59 @@ require 'rack/oauth2'
5
5
  module Osso
6
6
  class Oauth < Sinatra::Base
7
7
  include AppConfig
8
- # Send your users here in order to being an authentication
9
- # flow. This flow follows the authorization grant oauth
10
- # spec with one exception - you must also pass the domain
11
- # of the user who wants to sign in.
12
- get '/authorize' do
13
- @enterprise = Models::EnterpriseAccount.
14
- includes(:saml_providers).
15
- find_by!(domain: params[:domain])
16
-
17
- Rack::OAuth2::Server::Authorize.new do |req, _res|
18
- client = Models::OauthClient.find_by!(identifier: req.client_id)
19
- req.verify_redirect_uri!(client.redirect_uri_values)
20
- end.call(env)
21
-
22
- if @enterprise.single_provider?
23
- session[:oauth_state] = params[:state]
24
- redirect "/auth/saml/#{@enterprise.provider.id}"
8
+ register Sinatra::Namespace
9
+ # rubocop:disable Metrics/BlockLength
10
+ namespace '/oauth' do
11
+ # Send your users here in order to being an authentication
12
+ # flow. This flow follows the authorization grant oauth
13
+ # spec with one exception - you must also pass the domain
14
+ # of the user who wants to sign in.
15
+ get '/authorize' do
16
+ @enterprise = Models::EnterpriseAccount.
17
+ includes(:identity_providers).
18
+ find_by!(domain: params[:domain])
19
+
20
+ Rack::OAuth2::Server::Authorize.new do |req, _res|
21
+ client = Models::OauthClient.find_by!(identifier: req.client_id)
22
+ req.verify_redirect_uri!(client.redirect_uri_values)
23
+ end.call(env)
24
+
25
+ if @enterprise.single_provider?
26
+ session[:oauth_state] = params[:state]
27
+ redirect "/auth/saml/#{@enterprise.provider.id}"
28
+ end
29
+
30
+ # TODO: multiple provider support
31
+ # erb :multiple_providers
32
+
33
+ rescue Rack::OAuth2::Server::Authorize::BadRequest => e
34
+ @error = e
35
+ return erb :error
25
36
  end
26
37
 
27
- # TODO: multiple provider support
28
- # erb :multiple_providers
29
-
30
- rescue Rack::OAuth2::Server::Authorize::BadRequest => e
31
- @error = e
32
- return erb :error
33
- end
34
-
35
- # Exchange an authorization code token for an access token.
36
- # In addition to the token, you must include all paramaters
37
- # required by Oauth spec: redirect_uri, client ID, and client secret
38
- post '/token' do
39
- Rack::OAuth2::Server::Token.new do |req, res|
40
- code = Models::AuthorizationCode.
41
- find_by_token!(params[:code])
42
- client = Models::OauthClient.find_by!(identifier: req.client_id)
43
- req.invalid_client! if client.secret != req.client_secret
44
- req.invalid_grant! if code.redirect_uri != req.redirect_uri
45
- res.access_token = code.access_token.to_bearer_token
46
- end.call(env)
47
- end
38
+ # Exchange an authorization code token for an access token.
39
+ # In addition to the token, you must include all paramaters
40
+ # required by Oauth spec: redirect_uri, client ID, and client secret
41
+ post '/token' do
42
+ Rack::OAuth2::Server::Token.new do |req, res|
43
+ code = Models::AuthorizationCode.
44
+ find_by_token!(params[:code])
45
+ client = Models::OauthClient.find_by!(identifier: req.client_id)
46
+ req.invalid_client! if client.secret != req.client_secret
47
+ req.invalid_grant! if code.redirect_uri != req.redirect_uri
48
+ res.access_token = code.access_token.to_bearer_token
49
+ end.call(env)
50
+ end
48
51
 
49
- # Use the access token to request a user profile
50
- get '/me' do
51
- json Models::AccessToken.
52
- includes(:user).
53
- valid.
54
- find_by_token!(params[:access_token]).
55
- user
52
+ # Use the access token to request a user profile
53
+ get '/me' do
54
+ json Models::AccessToken.
55
+ includes(:user).
56
+ valid.
57
+ find_by_token!(params[:access_token]).
58
+ user
59
+ end
56
60
  end
57
61
  end
58
62
  end
63
+ # rubocop:enable Metrics/BlockLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.1'
4
+ VERSION = '0.0.3.6'
5
5
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'lib/osso/version'
4
4
 
5
+ # rubocop:disable Metrics/BlockLength
5
6
  Gem::Specification.new do |spec|
6
7
  spec.name = 'osso'
7
8
  spec.version = Osso::VERSION
@@ -15,6 +16,7 @@ Gem::Specification.new do |spec|
15
16
  spec.license = 'MIT'
16
17
 
17
18
  spec.add_runtime_dependency 'activesupport', '>= 6.0.3.2'
19
+ spec.add_runtime_dependency 'graphql'
18
20
  spec.add_runtime_dependency 'jwt'
19
21
  spec.add_runtime_dependency 'omniauth-multi-provider'
20
22
  spec.add_runtime_dependency 'omniauth-saml'
@@ -29,12 +31,10 @@ Gem::Specification.new do |spec|
29
31
  spec.add_development_dependency 'bundler', '~> 2.1'
30
32
  spec.add_development_dependency 'pry'
31
33
 
32
- # Specify which files should be added to the gem when it is released.
33
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
34
34
  spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
35
35
  spec.files = `git ls-files`.split("\n")
36
36
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
37
37
  spec.bindir = 'bin'
38
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
39
38
  spec.require_paths = ['lib']
40
39
  end
40
+ # rubocop:enable Metrics/BlockLength
@@ -3,6 +3,7 @@
3
3
  FactoryBot.define do
4
4
  factory :enterprise_account, class: Osso::Models::EnterpriseAccount do
5
5
  id { SecureRandom.uuid }
6
+ name { Faker::Company.name }
6
7
  domain { Faker::Internet.domain_name }
7
8
  oauth_client
8
9
  end
@@ -10,7 +11,7 @@ FactoryBot.define do
10
11
  factory :enterprise_with_okta, parent: :enterprise_account do
11
12
  after :create do |enterprise|
12
13
  create(
13
- :okta_saml_provider,
14
+ :okta_identity_provider,
14
15
  domain: enterprise.domain,
15
16
  enterprise_account_id: enterprise.id,
16
17
  )
@@ -20,7 +21,7 @@ FactoryBot.define do
20
21
  factory :enterprise_with_azure, parent: :enterprise_account do
21
22
  after :create do |enterprise|
22
23
  create(
23
- :azure_saml_provider,
24
+ :azure_identity_provider,
24
25
  domain: enterprise.domain,
25
26
  enterprise_account_id: enterprise.id,
26
27
  )
@@ -30,13 +31,13 @@ FactoryBot.define do
30
31
  factory :enterprise_with_multiple_providers, parent: :enterprise_account do
31
32
  after :create do |enterprise|
32
33
  create(
33
- :okta_saml_provider,
34
+ :okta_identity_provider,
34
35
  domain: enterprise.domain,
35
36
  enterprise_account_id: enterprise.id,
36
37
  )
37
38
 
38
39
  create(
39
- :azure_saml_provider,
40
+ :azure_identity_provider,
40
41
  domain: enterprise.domain,
41
42
  enterprise_account_id: enterprise.id,
42
43
  )
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :identity_provider, class: Osso::Models::IdentityProvider do
5
+ id { SecureRandom.uuid }
6
+ domain { Faker::Internet.domain_name }
7
+ oauth_client
8
+
9
+ factory :okta_identity_provider, parent: :identity_provider do
10
+ service { 'OKTA' }
11
+ sso_url do
12
+ 'https://dev-162024.okta.com/app/vcardmedev162024_rubydemo2_1/exk51326b3U1941Hf4x6/sso/saml'
13
+ end
14
+ end
15
+
16
+ factory :azure_identity_provider, parent: :identity_provider do
17
+ service { 'AZURE' }
18
+ sso_url do
19
+ 'https://login.microsoftonline.com/0af6c610-c40c-4683-9ea4-f25e509b8172/saml2'
20
+ end
21
+ end
22
+
23
+ factory :configured_identity_provider, parent: :identity_provider do
24
+ sso_cert do
25
+ <<~CERT
26
+ -----BEGIN CERTIFICATE-----
27
+ MIIDpDCCAoygAwIBAgIGAXEiD4LlMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEG
28
+ A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
29
+ MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi0xNjIwMjQxHDAaBgkqhkiG9w0BCQEW
30
+ DWluZm9Ab2t0YS5jb20wHhcNMjAwMzI4MTY1MTU0WhcNMzAwMzI4MTY1MjU0WjCBkjELMAkGA1UE
31
+ BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV
32
+ BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtMTYyMDI0MRwwGgYJ
33
+ KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
34
+ wsnP4UTfv3bxR5Jh0at51Dqjj+fKxFznzFW3XA5NbF2SlRLjeYcvj3+47TC0eP6xOsLWfnvdnx4v
35
+ dd9Ufn7jDCo5pL3JykMVEh2I0szF3RLC+a532ArcwgU9Px48+rWVwPkASS7l4NHAM4+gOBHJMQt2
36
+ AMohPT0kU41P8BEPzfwhNyiEXR66JNZIJUE8fM3Vpgnxm/VSwYzJf0NfOyfxv8JczF0zkDbpE7Tk
37
+ 3Ww/PFFLoMxWzanWGJQ+blnhv6UV6H4fcfAbcwAplOdIVHjS2ghYBvYNGahuFxjia0+6csyZGrt8
38
+ H4XmR5Dr+jXY5K1b1VOA0k19/FCnHHN/smn25wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBgD9NE
39
+ 4OCuR1+vucV8S1T6XXIL2hB7bXBAZEVHZ1aErRzktgXAMgVwG267vIkD5VOXBiTy9yNU5LK6G3k2
40
+ zewU190sL1dMfyPnoVZyn94nvwe9A+on0tmZdmk00xirKk3FJdacnZNE9Dl/afIrcNf6xAm0WsU9
41
+ kbMiRwwvjO4TAiygDQzbrRC8ZfmT3hpBa3aTUzAccrvEQcgarLk4r7UjXP7a2mCN3UIIh+snN2Ms
42
+ vXHL0r6fM3xbniz+5lleWtPFw73yySBc8znkWZ4Tn8Lh0r6o5nCRYbr2REUB7ZIfiIyBbZxIp4kv
43
+ a+habbnQDFiNVzEd8OPXHh4EqLxOPDRW
44
+ -----END CERTIFICATE-----
45
+ CERT
46
+ end
47
+ end
48
+ end
49
+ end
@@ -5,7 +5,7 @@ FactoryBot.define do
5
5
  id { SecureRandom.uuid }
6
6
  email { Faker::Internet.email }
7
7
  idp_id { SecureRandom.hex(32) }
8
- saml_provider { create(:okta_saml_provider) }
8
+ identity_provider { create(:okta_identity_provider) }
9
9
  enterprise_account
10
10
  after(:create) do |user|
11
11
  create(
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'ConfigureIdentityProvider' do
7
+ let(:enterprise_account) { create(:enterprise_account) }
8
+ let(:identity_provider) { create(:identity_provider, enterprise_account: enterprise_account) }
9
+ let(:variables) do
10
+ {
11
+ input: {
12
+ id: identity_provider.id,
13
+ service: 'OKTA',
14
+ ssoUrl: 'https://example.com',
15
+ ssoCert: 'BEGIN_CERTIFICATE',
16
+ },
17
+ }
18
+ end
19
+ let(:mutation) do
20
+ <<~GRAPHQL
21
+ mutation ConfigureIdentityProvider($input: ConfigureIdentityProviderInput!) {
22
+ configureIdentityProvider(input: $input) {
23
+ identityProvider {
24
+ id
25
+ domain
26
+ configured
27
+ enterpriseAccountId
28
+ service
29
+ acsUrl
30
+ ssoCert
31
+ ssoUrl
32
+ }
33
+ }
34
+ }
35
+ GRAPHQL
36
+ end
37
+
38
+ subject do
39
+ described_class.execute(
40
+ mutation,
41
+ variables: variables,
42
+ context: { scope: current_scope },
43
+ )
44
+ end
45
+
46
+ describe 'for an admin user' do
47
+ let(:current_scope) { :admin }
48
+ it 'configures an identity provider' do
49
+ expect(subject.dig('data', 'configureIdentityProvider', 'identityProvider', 'configured')).
50
+ to be true
51
+ end
52
+ end
53
+
54
+ describe 'for an email scoped user' do
55
+ let(:domain) { Faker::Internet.domain_name }
56
+ let(:current_scope) { domain }
57
+ let(:enterprise_account) { create(:enterprise_account, domain: domain) }
58
+
59
+ it 'creates an identity provider' do
60
+ expect(subject.dig('data', 'configureIdentityProvider', 'identityProvider', 'domain')).
61
+ to eq(domain)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::GraphQL::Schema do
6
+ describe 'CreateIdentityProvider' do
7
+ let(:domain) { Faker::Internet.domain_name }
8
+ let(:variables) do
9
+ {
10
+ input: {
11
+ name: Faker::Company.name,
12
+ domain: domain,
13
+ },
14
+ }
15
+ end
16
+
17
+ let(:mutation) do
18
+ <<~GRAPHQL
19
+ mutation CreateEnterpriseAccount($input: CreateEnterpriseAccountInput!) {
20
+ createEnterpriseAccount(input: $input) {
21
+ enterpriseAccount {
22
+ id
23
+ domain
24
+ name
25
+ status
26
+ }
27
+ }
28
+ }
29
+ GRAPHQL
30
+ end
31
+
32
+ subject do
33
+ described_class.execute(
34
+ mutation,
35
+ variables: variables,
36
+ context: { scope: current_scope },
37
+ )
38
+ end
39
+
40
+ describe 'for an admin user' do
41
+ let(:current_scope) { :admin }
42
+ it 'creates an Enterprise Account' do
43
+ expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(1)
44
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
45
+ to eq(domain)
46
+ end
47
+ end
48
+
49
+ describe 'for an email scoped user' do
50
+ let(:current_scope) { domain }
51
+
52
+ it 'creates an Enterprise Account' do
53
+ expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(1)
54
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
55
+ to eq(domain)
56
+ end
57
+ end
58
+ describe 'for the wrong email scoped user' do
59
+ let(:current_scope) { 'foo.com' }
60
+
61
+ it 'does not create an Enterprise Account' do
62
+ expect { subject }.to_not(change { Osso::Models::EnterpriseAccount.count })
63
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
64
+ to be_nil
65
+ end
66
+ end
67
+ end
68
+ end