osso 0.0.3.8 → 0.0.3.9

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 (40) 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 +9 -43
  6. data/lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb +35 -0
  7. data/lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb +9 -0
  8. data/lib/osso/graphql/mutation.rb +3 -1
  9. data/lib/osso/graphql/mutations.rb +3 -1
  10. data/lib/osso/graphql/mutations/configure_identity_provider.rb +1 -1
  11. data/lib/osso/graphql/mutations/create_oauth_client.rb +30 -0
  12. data/lib/osso/graphql/mutations/delete_enterprise_account.rb +34 -0
  13. data/lib/osso/graphql/mutations/delete_oauth_client.rb +30 -0
  14. data/lib/osso/graphql/resolvers/oauth_clients.rb +1 -1
  15. data/lib/osso/graphql/types/base_object.rb +2 -0
  16. data/lib/osso/graphql/types/oauth_client.rb +13 -1
  17. data/lib/osso/helpers/auth.rb +11 -12
  18. data/lib/osso/models/access_token.rb +18 -0
  19. data/lib/osso/models/authorization_code.rb +20 -0
  20. data/lib/osso/models/enterprise_account.rb +20 -0
  21. data/lib/osso/models/identity_provider.rb +22 -1
  22. data/lib/osso/models/models.rb +2 -0
  23. data/lib/osso/models/oauth_client.rb +17 -1
  24. data/lib/osso/models/redirect_uri.rb +17 -0
  25. data/lib/osso/models/user.rb +22 -0
  26. data/lib/osso/version.rb +1 -1
  27. data/osso-rb.gemspec +1 -0
  28. data/spec/factories/identity_providers.rb +22 -0
  29. data/spec/graphql/mutations/configure_identity_provider_spec.rb +1 -1
  30. data/spec/graphql/mutations/create_oauth_client_spec.rb +55 -0
  31. data/spec/graphql/mutations/delete_enterprise_account_spec.rb +63 -0
  32. data/spec/graphql/mutations/delete_oauth_client_spec.rb +51 -0
  33. data/spec/graphql/query/identity_provider_spec.rb +1 -1
  34. data/spec/graphql/query/{oauth_clients_account_spec.rb → oauth_clients_spec.rb} +2 -0
  35. metadata +27 -8
  36. data/lib/osso/db/migrate/20200328143303_create_oauth_tables.rb +0 -57
  37. data/lib/osso/graphql/mutations/set_identity_provider.rb +0 -27
  38. data/lib/osso/models/saml_provider.rb +0 -49
  39. data/lib/osso/models/saml_providers/azure_saml_provider.rb +0 -22
  40. data/lib/osso/models/saml_providers/okta_saml_provider.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73de8a2c5af9b7d62c94a5ed34c094455dc9b49b7345eb252308f7048e1164c0
4
- data.tar.gz: c37913b5f3a857245d588ad03155ece0c5aca99c22c4c56069f50d442cb74db5
3
+ metadata.gz: 3f0c8535a6ba6dd39ada0f3ba0aa0617ff96bd880ef6985149c0ecbeca57bc1a
4
+ data.tar.gz: da6bec63d5e071b1c0520e42cd67c3971851445bfad8ec597f1b9d1aef0759d8
5
5
  SHA512:
6
- metadata.gz: 3047a07787aa764d105e77580846d60a943d4bd859baed5c861aebd8face6fb461342f3cccc01cc58e33d66310ba0d852185605fea09eb54d21c126aa149230c
7
- data.tar.gz: f61b3e5aa31946a69512762601d08ecc021be26a56df0b182fc826d53e7be0836ea019c90ad09fc6b927dc3b37ee8efbc01e6145c0c4af4ff97198b9cd89828c
6
+ metadata.gz: 3e3938abd7b541d6e272cb1b1420e9f4dc75738edd763cc1c35e82db4b315852c125f268ad8ed36528373252c23bdea79b7ac865711abb1c52159cae709c47c5
7
+ data.tar.gz: fa63314128c1833ddd1136ea1cdacee8e8f4cbfb92a6eaffc0c8ae8dfc0ccb93b62effcac55e0cf916033a32cd1941e5ea915959f032ed6a983133711f4610e0
@@ -1,6 +1,8 @@
1
1
  steps:
2
2
  - name: ":rspec:"
3
3
  commands:
4
- - "bundle install"
5
- - "bundle exec rake db:test:prepare"
6
- - "bundle exec rspec"
4
+ - bundle install
5
+ - bundle exec rake db:drop
6
+ - bundle exec rake db:create
7
+ - RACK_ENV=test bundle exec rake db:migrate
8
+ - bundle exec rspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.3.8)
4
+ osso (0.0.3.9)
5
5
  activesupport (>= 6.0.3.2)
6
6
  graphql
7
7
  jwt
@@ -32,6 +32,9 @@ GEM
32
32
  addressable (2.7.0)
33
33
  public_suffix (>= 2.0.2, < 5.0)
34
34
  aes_key_wrap (1.0.1)
35
+ annotate (3.1.1)
36
+ activerecord (>= 3.2, < 7.0)
37
+ rake (>= 10.4, < 14.0)
35
38
  ast (2.4.1)
36
39
  attr_required (1.0.1)
37
40
  backports (3.18.1)
@@ -160,6 +163,7 @@ PLATFORMS
160
163
  ruby
161
164
 
162
165
  DEPENDENCIES
166
+ annotate (~> 3.1)
163
167
  bundler (~> 2.1)
164
168
  database_cleaner-active_record
165
169
  factory_bot
@@ -0,0 +1 @@
1
+ annotate --require osso.rb --models --model-dir ./lib/osso/models/ --position bottom -k -i
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2020_07_22_230116) do
13
+ ActiveRecord::Schema.define(version: 2020_07_23_162228) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "pgcrypto"
@@ -47,6 +47,8 @@ ActiveRecord::Schema.define(version: 2020_07_22_230116) do
47
47
  t.string "external_id"
48
48
  t.uuid "oauth_client_id"
49
49
  t.string "name", null: false
50
+ t.datetime "created_at", null: false
51
+ t.datetime "updated_at", null: false
50
52
  t.index ["domain"], name: "index_enterprise_accounts_on_domain", unique: true
51
53
  t.index ["oauth_client_id"], name: "index_enterprise_accounts_on_oauth_client_id"
52
54
  end
@@ -54,48 +56,12 @@ ActiveRecord::Schema.define(version: 2020_07_22_230116) do
54
56
  # Could not dump table "identity_providers" because of following StandardError
55
57
  # Unknown type 'identity_provider_status' for column 'status'
56
58
 
57
- create_table "oauth_access_grants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
58
- t.uuid "resource_owner_id", null: false
59
- t.uuid "application_id", null: false
60
- t.string "token", null: false
61
- t.integer "expires_in", null: false
62
- t.text "redirect_uri", null: false
63
- t.datetime "created_at", null: false
64
- t.datetime "revoked_at"
65
- t.string "scopes", default: "", null: false
66
- t.index ["application_id"], name: "index_oauth_access_grants_on_application_id"
67
- t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
68
- end
69
-
70
- create_table "oauth_access_tokens", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
71
- t.uuid "resource_owner_id"
72
- t.uuid "application_id"
73
- t.string "token", null: false
74
- t.string "refresh_token"
75
- t.integer "expires_in"
76
- t.datetime "revoked_at"
77
- t.datetime "created_at", null: false
78
- t.string "scopes"
79
- t.string "previous_refresh_token", default: "", null: false
80
- t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id"
81
- t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
82
- t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
83
- end
84
-
85
- create_table "oauth_applications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
86
- t.string "name", null: false
87
- t.string "secret", null: false
88
- t.text "redirect_uri", null: false
89
- t.string "scopes", default: "", null: false
90
- t.boolean "confidential", default: true, null: false
91
- t.datetime "created_at", precision: 6, null: false
92
- t.datetime "updated_at", precision: 6, null: false
93
- end
94
-
95
59
  create_table "oauth_clients", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
96
60
  t.string "name", null: false
97
61
  t.string "secret", null: false
98
62
  t.string "identifier", null: false
63
+ t.datetime "created_at", null: false
64
+ t.datetime "updated_at", null: false
99
65
  t.index ["identifier"], name: "index_oauth_clients_on_identifier", unique: true
100
66
  end
101
67
 
@@ -103,6 +69,8 @@ ActiveRecord::Schema.define(version: 2020_07_22_230116) do
103
69
  t.string "uri", null: false
104
70
  t.boolean "primary", default: false, null: false
105
71
  t.uuid "oauth_client_id"
72
+ t.datetime "created_at", null: false
73
+ t.datetime "updated_at", null: false
106
74
  t.index ["oauth_client_id"], name: "index_redirect_uris_on_oauth_client_id"
107
75
  t.index ["uri", "primary"], name: "index_redirect_uris_on_uri_and_primary", unique: true
108
76
  end
@@ -112,13 +80,11 @@ ActiveRecord::Schema.define(version: 2020_07_22_230116) do
112
80
  t.string "idp_id", null: false
113
81
  t.uuid "identity_provider_id"
114
82
  t.uuid "enterprise_account_id"
83
+ t.datetime "created_at", null: false
84
+ t.datetime "updated_at", null: false
115
85
  t.index ["email", "idp_id"], name: "index_users_on_email_and_idp_id", unique: true
116
86
  t.index ["enterprise_account_id"], name: "index_users_on_enterprise_account_id"
117
87
  end
118
88
 
119
- add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id"
120
- add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id"
121
- add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id"
122
- add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id"
123
89
  add_foreign_key "users", "identity_providers"
124
90
  end
@@ -0,0 +1,35 @@
1
+ class AddMissingTimestamps < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :enterprise_accounts, :created_at, :timestamp
4
+ add_column :enterprise_accounts, :updated_at, :timestamp
5
+ update "UPDATE enterprise_accounts SET created_at = NOW(), updated_at = NOW()"
6
+ change_column_null :enterprise_accounts, :created_at, false
7
+ change_column_null :enterprise_accounts, :updated_at, false
8
+
9
+
10
+ add_column :identity_providers, :created_at, :timestamp
11
+ add_column :identity_providers, :updated_at, :timestamp
12
+ update "UPDATE enterprise_accounts SET created_at = NOW(), updated_at = NOW()"
13
+ change_column_null :enterprise_accounts, :created_at, false
14
+ change_column_null :enterprise_accounts, :updated_at, false
15
+
16
+ add_column :oauth_clients, :created_at, :timestamp
17
+ add_column :oauth_clients, :updated_at, :timestamp
18
+ update "UPDATE oauth_clients SET created_at = NOW(), updated_at = NOW()"
19
+ change_column_null :oauth_clients, :created_at, false
20
+ change_column_null :oauth_clients, :updated_at, false
21
+
22
+ add_column :redirect_uris, :created_at, :timestamp
23
+ add_column :redirect_uris, :updated_at, :timestamp
24
+ update "UPDATE redirect_uris SET created_at = NOW(), updated_at = NOW()"
25
+ change_column_null :redirect_uris, :created_at, false
26
+ change_column_null :redirect_uris, :updated_at, false
27
+
28
+ add_column :users, :created_at, :timestamp
29
+ add_column :users, :updated_at, :timestamp
30
+ update "UPDATE users SET created_at = NOW(), updated_at = NOW()"
31
+ change_column_null :users, :created_at, false
32
+ change_column_null :users, :updated_at, false
33
+
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ class DropUnneededTables < ActiveRecord::Migration[6.0]
2
+ def change
3
+ drop_table(:oauth_grants, if_exists: true)
4
+ drop_table(:oauth_access_tokens, if_exists: true)
5
+ drop_table(:oauth_applications, if_exists: true)
6
+
7
+
8
+ end
9
+ end
@@ -9,7 +9,9 @@ module Osso
9
9
  field :configure_identity_provider, mutation: Mutations::ConfigureIdentityProvider, null: true
10
10
  field :create_identity_provider, mutation: Mutations::CreateIdentityProvider
11
11
  field :create_enterprise_account, mutation: Mutations::CreateEnterpriseAccount
12
- field :set_identity_provider, mutation: Mutations::SetSamlProvider
12
+ field :create_oauth_client, mutation: Mutations::CreateOauthClient
13
+ field :delete_enterprise_account, mutation: Mutations::DeleteEnterpriseAccount
14
+ field :delete_oauth_client, mutation: Mutations::DeleteOauthClient
13
15
  end
14
16
  end
15
17
  end
@@ -9,4 +9,6 @@ require_relative 'mutations/base_mutation'
9
9
  require_relative 'mutations/configure_identity_provider'
10
10
  require_relative 'mutations/create_identity_provider'
11
11
  require_relative 'mutations/create_enterprise_account'
12
- require_relative 'mutations/set_identity_provider'
12
+ require_relative 'mutations/create_oauth_client'
13
+ require_relative 'mutations/delete_enterprise_account'
14
+ require_relative 'mutations/delete_oauth_client'
@@ -21,7 +21,7 @@ module Osso
21
21
  response_error(errors: provder.errors.messages)
22
22
  end
23
23
 
24
- def ready?(id:, **args)
24
+ def ready?(id:, **_args)
25
25
  return true if context[:scope] == :admin
26
26
 
27
27
  domain = Osso::Models::IdentityProvider.find(id)&.domain
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class CreateOauthClient < BaseMutation
7
+ null false
8
+
9
+ argument :name, String, required: true
10
+
11
+ field :oauth_client, Types::OauthClient, null: false
12
+ field :errors, [String], null: false
13
+
14
+ def resolve(**args)
15
+ oauth_client = Osso::Models::OauthClient.new(args)
16
+
17
+ return response_data(oauth_client: oauth_client) if oauth_client.save
18
+
19
+ response_error(errors: oauth_client.errors.full_messages)
20
+ end
21
+
22
+ def ready?(*)
23
+ return true if context[:scope] == :admin
24
+
25
+ raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class DeleteEnterpriseAccount < BaseMutation
7
+ null false
8
+
9
+ argument :id, ID, required: true
10
+
11
+ field :enterprise_account, Types::EnterpriseAccount, null: true
12
+ field :errors, [String], null: false
13
+
14
+ def resolve(id:)
15
+ enterprise_account = Osso::Models::EnterpriseAccount.find(id)
16
+
17
+ return response_data(enterprise_account: nil) if enterprise_account.destroy
18
+
19
+ response_error(errors: enterprise_account.errors.full_messages)
20
+ end
21
+
22
+ def ready?(id:)
23
+ return true if context[:scope] == :admin
24
+
25
+ domain = account_domain(id)
26
+
27
+ return true if domain == context[:scope]
28
+
29
+ raise ::GraphQL::ExecutionError, "This user lacks the scope to mutate records belonging to #{domain}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class DeleteOauthClient < BaseMutation
7
+ null false
8
+
9
+ argument :id, ID, required: true
10
+
11
+ field :oauth_client, Types::OauthClient, null: true
12
+ field :errors, [String], null: false
13
+
14
+ def resolve(id:)
15
+ oauth_client = Osso::Models::OauthClient.find(id)
16
+
17
+ return response_data(oauth_client: nil) if oauth_client.destroy
18
+
19
+ response_error(errors: oauth_client.errors.full_messages)
20
+ end
21
+
22
+ def ready?(*)
23
+ return true if context[:scope] == :admin
24
+
25
+ raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,7 +4,7 @@ module Osso
4
4
  module GraphQL
5
5
  module Resolvers
6
6
  class OAuthClients < ::GraphQL::Schema::Resolver
7
- type [Types::OAuthClient], null: true
7
+ type [Types::OauthClient], null: true
8
8
 
9
9
  def resolve
10
10
  return Osso::Models::OauthClient.all if context[:scope] == :admin
@@ -6,6 +6,8 @@ module Osso
6
6
  module GraphQL
7
7
  module Types
8
8
  class BaseObject < ::GraphQL::Schema::Object
9
+ field :created_at, ::GraphQL::Types::ISO8601DateTime, null: false
10
+ field :updated_at, ::GraphQL::Types::ISO8601DateTime, null: false
9
11
  end
10
12
  end
11
13
  end
@@ -5,7 +5,7 @@ require 'graphql'
5
5
  module Osso
6
6
  module GraphQL
7
7
  module Types
8
- class OAuthClient < Types::BaseObject
8
+ class OauthClient < Types::BaseObject
9
9
  description 'An OAuth client used to consume Osso SAML users'
10
10
  implements ::GraphQL::Types::Relay::Node
11
11
 
@@ -14,6 +14,18 @@ module Osso
14
14
  field :name, String, null: false
15
15
  field :client_id, String, null: false
16
16
  field :client_secret, String, null: false
17
+
18
+ def client_id
19
+ object.identifier
20
+ end
21
+
22
+ def client_secret
23
+ object.secret
24
+ end
25
+
26
+ def self.authorized?(object, context)
27
+ super && context[:scope] == :admin
28
+ end
17
29
  end
18
30
  end
19
31
  end
@@ -15,12 +15,7 @@ module Osso
15
15
  end
16
16
 
17
17
  def enterprise_authorized?(_domain)
18
- payload, _args = JWT.decode(
19
- token,
20
- ENV['JWT_HMAC_SECRET'],
21
- true,
22
- { algorithm: 'HS256' },
23
- )
18
+ payload, _args = decode(token)
24
19
 
25
20
  @current_scope = payload['scope']
26
21
 
@@ -36,12 +31,7 @@ module Osso
36
31
  end
37
32
 
38
33
  def admin_authorized?
39
- payload, _args = JWT.decode(
40
- token,
41
- ENV['JWT_HMAC_SECRET'],
42
- true,
43
- { algorithm: 'HS256' },
44
- )
34
+ payload, _args = decode(token)
45
35
 
46
36
  if payload['scope'] == 'admin'
47
37
  @current_scope = :admin
@@ -66,6 +56,15 @@ module Osso
66
56
 
67
57
  redirect request.path
68
58
  end
59
+
60
+ def decode(token)
61
+ JWT.decode(
62
+ token,
63
+ ENV['JWT_HMAC_SECRET'],
64
+ true,
65
+ { algorithm: 'HS256' },
66
+ )
67
+ end
69
68
  end
70
69
  end
71
70
  end
@@ -27,3 +27,21 @@ module Osso
27
27
  end
28
28
  end
29
29
  end
30
+
31
+ # == Schema Information
32
+ #
33
+ # Table name: access_tokens
34
+ #
35
+ # id :uuid not null, primary key
36
+ # token :string
37
+ # expires_at :datetime
38
+ # created_at :datetime not null
39
+ # updated_at :datetime not null
40
+ # user_id :uuid
41
+ # oauth_client_id :uuid
42
+ #
43
+ # Indexes
44
+ #
45
+ # index_access_tokens_on_oauth_client_id (oauth_client_id)
46
+ # index_access_tokens_on_user_id (user_id)
47
+ #
@@ -12,3 +12,23 @@ module Osso
12
12
  end
13
13
  end
14
14
  end
15
+
16
+ # == Schema Information
17
+ #
18
+ # Table name: authorization_codes
19
+ #
20
+ # id :uuid not null, primary key
21
+ # token :string
22
+ # redirect_uri :string
23
+ # expires_at :datetime
24
+ # created_at :datetime not null
25
+ # updated_at :datetime not null
26
+ # user_id :uuid
27
+ # oauth_client_id :uuid
28
+ #
29
+ # Indexes
30
+ #
31
+ # index_authorization_codes_on_oauth_client_id (oauth_client_id)
32
+ # index_authorization_codes_on_token (token) UNIQUE
33
+ # index_authorization_codes_on_user_id (user_id)
34
+ #
@@ -26,3 +26,23 @@ module Osso
26
26
  end
27
27
  end
28
28
  end
29
+
30
+ # == Schema Information
31
+ #
32
+ # Table name: enterprise_accounts
33
+ #
34
+ # id :uuid not null, primary key
35
+ # domain :string not null
36
+ # external_uuid :uuid
37
+ # external_int_id :integer
38
+ # external_id :string
39
+ # oauth_client_id :uuid
40
+ # name :string not null
41
+ # created_at :datetime not null
42
+ # updated_at :datetime not null
43
+ #
44
+ # Indexes
45
+ #
46
+ # index_enterprise_accounts_on_domain (domain) UNIQUE
47
+ # index_enterprise_accounts_on_oauth_client_id (oauth_client_id)
48
+ #
@@ -10,7 +10,6 @@ module Osso
10
10
  has_many :users
11
11
  before_save :set_status
12
12
 
13
-
14
13
  def name
15
14
  service.titlecase
16
15
  # raise(
@@ -54,3 +53,25 @@ module Osso
54
53
  end
55
54
  end
56
55
  end
56
+
57
+ # == Schema Information
58
+ #
59
+ # Table name: identity_providers
60
+ #
61
+ # id :uuid not null, primary key
62
+ # service :string
63
+ # domain :string not null
64
+ # sso_url :string
65
+ # sso_cert :text
66
+ # enterprise_account_id :uuid
67
+ # oauth_client_id :uuid
68
+ # status :enum default("PENDING")
69
+ # created_at :datetime
70
+ # updated_at :datetime
71
+ #
72
+ # Indexes
73
+ #
74
+ # index_identity_providers_on_domain (domain)
75
+ # index_identity_providers_on_enterprise_account_id (enterprise_account_id)
76
+ # index_identity_providers_on_oauth_client_id (oauth_client_id)
77
+ #
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # -*- SkipSchemaAnnotations
4
+
3
5
  require 'sinatra/activerecord'
4
6
 
5
7
  module Osso
@@ -25,8 +25,24 @@ module Osso
25
25
 
26
26
  def setup
27
27
  self.identifier = SecureRandom.hex(16)
28
- self.secret = SecureRandom.hex(64)
28
+ self.secret = SecureRandom.hex(32)
29
29
  end
30
30
  end
31
31
  end
32
32
  end
33
+
34
+ # == Schema Information
35
+ #
36
+ # Table name: oauth_clients
37
+ #
38
+ # id :uuid not null, primary key
39
+ # name :string not null
40
+ # secret :string not null
41
+ # identifier :string not null
42
+ # created_at :datetime not null
43
+ # updated_at :datetime not null
44
+ #
45
+ # Indexes
46
+ #
47
+ # index_oauth_clients_on_identifier (identifier) UNIQUE
48
+ #
@@ -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
+ #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.8'
4
+ VERSION = '0.0.3.9'
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
+ #
@@ -47,7 +47,7 @@ describe Osso::GraphQL::Schema do
47
47
  let(:current_scope) { :admin }
48
48
  it 'configures an identity provider' do
49
49
  expect(subject.dig('data', 'configureIdentityProvider', 'identityProvider', 'status')).
50
- to eq('configured')
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
@@ -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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.8
4
+ version: 0.0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Bauch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-23 00:00:00.000000000 Z
11
+ date: 2020-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: annotate
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '3.1'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '3.1'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: bundler
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -210,6 +224,7 @@ description: This gem includes the main functionality for Osso apps,
210
224
  email:
211
225
  - sbauch@gmail.com
212
226
  executables:
227
+ - annotate
213
228
  - console
214
229
  - setup
215
230
  extensions: []
@@ -229,6 +244,7 @@ files:
229
244
  - LICENSE
230
245
  - README.md
231
246
  - Rakefile
247
+ - bin/annotate
232
248
  - bin/console
233
249
  - bin/setup
234
250
  - config/database.yml
@@ -238,7 +254,6 @@ files:
238
254
  - lib/osso/Rakefile
239
255
  - lib/osso/db/migrate/20190909230109_enable_uuid.rb
240
256
  - lib/osso/db/migrate/20200328135750_create_users.rb
241
- - lib/osso/db/migrate/20200328143303_create_oauth_tables.rb
242
257
  - lib/osso/db/migrate/20200328143305_create_identity_providers.rb
243
258
  - lib/osso/db/migrate/20200411184535_add_provider_id_to_users.rb
244
259
  - lib/osso/db/migrate/20200411192645_create_enterprise_accounts.rb
@@ -251,6 +266,8 @@ files:
251
266
  - lib/osso/db/migrate/20200715154211_rename_idp_fields_on_identity_provider_to_sso.rb
252
267
  - lib/osso/db/migrate/20200715205801_add_name_to_enterprise_account.rb
253
268
  - lib/osso/db/migrate/20200722230116_add_identity_provider_status_enum_and_use_on_identity_providers.rb
269
+ - lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb
270
+ - lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb
254
271
  - lib/osso/graphql/.DS_Store
255
272
  - lib/osso/graphql/mutation.rb
256
273
  - lib/osso/graphql/mutations.rb
@@ -258,7 +275,9 @@ files:
258
275
  - lib/osso/graphql/mutations/configure_identity_provider.rb
259
276
  - lib/osso/graphql/mutations/create_enterprise_account.rb
260
277
  - lib/osso/graphql/mutations/create_identity_provider.rb
261
- - lib/osso/graphql/mutations/set_identity_provider.rb
278
+ - lib/osso/graphql/mutations/create_oauth_client.rb
279
+ - lib/osso/graphql/mutations/delete_enterprise_account.rb
280
+ - lib/osso/graphql/mutations/delete_oauth_client.rb
262
281
  - lib/osso/graphql/query.rb
263
282
  - lib/osso/graphql/resolvers.rb
264
283
  - lib/osso/graphql/resolvers/enterprise_account.rb
@@ -287,9 +306,6 @@ files:
287
306
  - lib/osso/models/models.rb
288
307
  - lib/osso/models/oauth_client.rb
289
308
  - lib/osso/models/redirect_uri.rb
290
- - lib/osso/models/saml_provider.rb
291
- - lib/osso/models/saml_providers/azure_saml_provider.rb
292
- - lib/osso/models/saml_providers/okta_saml_provider.rb
293
309
  - lib/osso/models/user.rb
294
310
  - lib/osso/rake.rb
295
311
  - lib/osso/routes/admin.rb
@@ -310,10 +326,13 @@ files:
310
326
  - spec/graphql/mutations/configure_identity_provider_spec.rb
311
327
  - spec/graphql/mutations/create_enterprise_account_spec.rb
312
328
  - spec/graphql/mutations/create_identity_provider_spec.rb
329
+ - spec/graphql/mutations/create_oauth_client_spec.rb
330
+ - spec/graphql/mutations/delete_enterprise_account_spec.rb
331
+ - spec/graphql/mutations/delete_oauth_client_spec.rb
313
332
  - spec/graphql/query/enterprise_account_spec.rb
314
333
  - spec/graphql/query/enterprise_accounts_spec.rb
315
334
  - spec/graphql/query/identity_provider_spec.rb
316
- - spec/graphql/query/oauth_clients_account_spec.rb
335
+ - spec/graphql/query/oauth_clients_spec.rb
317
336
  - spec/models/azure_saml_provider_spec.rb
318
337
  - spec/models/identity_provider_spec.rb
319
338
  - spec/models/okta_saml_provider_spec.rb
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateOauthTables < ActiveRecord::Migration[6.0]
4
- def change
5
- create_table :oauth_applications, id: :uuid do |t|
6
- t.string :name, null: false
7
- t.string :secret, null: false
8
- t.text :redirect_uri, null: false
9
- t.string :scopes, null: false, default: ''
10
- t.boolean :confidential, null: false, default: true
11
- t.timestamps null: false
12
- end
13
-
14
- create_table :oauth_access_grants, id: :uuid do |t|
15
- t.uuid :resource_owner_id, null: false
16
- t.references :application, type: :uuid, null: false
17
- t.string :token, null: false
18
- t.integer :expires_in, null: false
19
- t.text :redirect_uri, null: false
20
- t.datetime :created_at, null: false
21
- t.datetime :revoked_at
22
- t.string :scopes, null: false, default: ''
23
- end
24
-
25
- add_index :oauth_access_grants, :token, unique: true
26
- add_foreign_key(
27
- :oauth_access_grants,
28
- :oauth_applications,
29
- column: :application_id
30
- )
31
-
32
- create_table :oauth_access_tokens, id: :uuid do |t|
33
- t.uuid :resource_owner_id
34
- t.references :application, type: :uuid
35
- t.string :token, null: false
36
-
37
- t.string :refresh_token
38
- t.integer :expires_in
39
- t.datetime :revoked_at
40
- t.datetime :created_at, null: false
41
- t.string :scopes
42
-
43
- t.string :previous_refresh_token, null: false, default: ''
44
- end
45
-
46
- add_index :oauth_access_tokens, :token, unique: true
47
- add_index :oauth_access_tokens, :refresh_token, unique: true
48
- add_foreign_key(
49
- :oauth_access_tokens,
50
- :oauth_applications,
51
- column: :application_id
52
- )
53
-
54
- add_foreign_key :oauth_access_grants, :users, column: :resource_owner_id
55
- add_foreign_key :oauth_access_tokens, :users, column: :resource_owner_id
56
- end
57
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module GraphQL
5
- module Mutations
6
- class SetSamlProvider < BaseMutation
7
- null false
8
-
9
- argument :provider, Types::IdentityProviderService, required: true
10
- argument :id, ID, required: true
11
-
12
- field :identity_provider, Types::IdentityProvider, null: false
13
- field :errors, [String], null: false
14
-
15
- def resolve(provider:, id:)
16
- identity_provider = Osso::Models::IdentityProvider.find(id)
17
- identity_provider.service = provider
18
- identity_provider.save!
19
- {
20
- identity_provider: identity_provider,
21
- errors: [],
22
- }
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Models
5
- # Base class for SAML Providers
6
- class IdentityProvider < ActiveRecord::Base
7
- NAME_FORMAT = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
8
- belongs_to :enterprise_account
9
- belongs_to :oauth_client
10
- has_many :users
11
-
12
- before_create :create_enterprise_account
13
-
14
- # def name
15
- # raise(
16
- # NoMethodError,
17
- # '#name must be defined on each provider specific subclass',
18
- # )
19
- # end
20
-
21
- # def saml_options
22
- # raise(
23
- # NoMethodError,
24
- # '#saml_options must be defined on each provider specific subclass',
25
- # )
26
- # end
27
-
28
- def assertion_consumer_service_url
29
- [
30
- ENV.fetch('BASE_URL'),
31
- 'auth',
32
- 'saml',
33
- id,
34
- 'callback',
35
- ].join('/')
36
- end
37
-
38
- alias acs_url assertion_consumer_service_url
39
-
40
- def create_enterprise_account
41
- return if enterprise_account_id
42
-
43
- self.enterprise_account = Models::EnterpriseAccount.create(
44
- domain: domain,
45
- )
46
- end
47
- end
48
- end
49
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Models
5
- # Subclass for Azure / ADFS IDP instances
6
- class AzureSamlProvider < Models::IdentityProvider
7
- def name
8
- 'Azure'
9
- end
10
-
11
- def saml_options
12
- attributes.slice(
13
- 'domain',
14
- 'idp_cert',
15
- 'idp_sso_target_url',
16
- ).merge(
17
- issuer: "id:#{id}",
18
- ).symbolize_keys
19
- end
20
- end
21
- end
22
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Models
5
- # Subclass for Okta IDP instances
6
- class OktaSamlProvider < Models::IdentityProvider
7
- def name
8
- 'Okta'
9
- end
10
-
11
- def saml_options
12
- attributes.slice(
13
- 'domain',
14
- 'idp_cert',
15
- 'idp_sso_target_url',
16
- ).merge(
17
- issuer: id,
18
- name_identifier_format: NAME_FORMAT,
19
- ).symbolize_keys
20
- end
21
- end
22
- end
23
- end