osso 0.0.3.18 → 0.0.3.19

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: 6b1068b7192ca709b9ba61cccaae62a9d98b350c756f88890f48b7fe2f7e4780
4
- data.tar.gz: c9b499428182dc6c920624fdbcd36c2e0d3b5a14e83259d95b506c3bbbf2efad
3
+ metadata.gz: 995be763d7567651350cc953d6d800a8bbd86e3de1eda57f7ab673869ffbb6dc
4
+ data.tar.gz: 01aa99f9fc68465df111624a22175ce2d5d110e94e2389d128a1c94cb0466494
5
5
  SHA512:
6
- metadata.gz: 49a87999664fb1d809ced917bbd85c37e69c995c1e287683d0b84b3bbc97b9c24a19b31ffc0225a21c88fec9caa059b2b3bddd0d7b2e37480d7e2f92d0651cb9
7
- data.tar.gz: 7a94be7b14bdb164d4f18fab52c9f7453f79e2547cfff606aa7ae854b281ac03017e176ea1b697130bc4a0a5191c31519f94aab974ebcd56a69ddc228e67eee9
6
+ metadata.gz: e4f45a4c188da6bf0adce208bec4b32ad76850136bed6af4ca221f0f5ccf94c6547b19a8486b92b1e05c57f0224389b25b7f8efd5f0c3a9c260a4a745cb2687c
7
+ data.tar.gz: 7df17b8bd2726c59a828d4ceb6f04e2246eeb9ac651f12a6f7956f0c65a9b45e5dcc4c2266d55eec3816f64ae635f9fbf70a37cb57eb0f4efc94c1b49803499c
@@ -6,6 +6,15 @@ steps:
6
6
  - bundle exec rake db:create
7
7
  - RACK_ENV=test bundle exec rake db:migrate
8
8
  - bundle exec rspec
9
+ artifact_paths:
10
+ - coverage/*
11
+
12
+ - name: ":codeclimate:"
13
+ plugins:
14
+ - jobready/codeclimate-test-reporter#v2.0:
15
+ artifact: "coverage/.resultset.json"
16
+ input_type: simplecov
17
+ prefix: '/var/lib/buildkite-agent/builds/enterprise-oss-bk-1/enterpriseoss/osso-rb/'
9
18
 
10
19
  - block: ":rubygems: Publish :red_button:"
11
20
  branches: "main"
data/Gemfile CHANGED
@@ -12,6 +12,7 @@ group :test do
12
12
  gem 'rack-test'
13
13
  gem 'rspec', '~> 3.2'
14
14
  gem 'rubocop'
15
+ gem 'simplecov', '= 0.17', require: false
15
16
  gem 'webmock', '~> 3.0'
16
17
  end
17
18
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.3.18)
4
+ osso (0.0.3.19)
5
5
  activesupport (>= 6.0.3.2)
6
6
  graphql
7
7
  jwt
@@ -48,6 +48,7 @@ GEM
48
48
  activerecord
49
49
  database_cleaner (~> 1.8.0)
50
50
  diff-lcs (1.4.4)
51
+ docile (1.3.2)
51
52
  factory_bot (6.0.2)
52
53
  activesupport (>= 5.0.0)
53
54
  faker (2.13.0)
@@ -58,6 +59,7 @@ GEM
58
59
  httpclient (2.8.3)
59
60
  i18n (1.8.3)
60
61
  concurrent-ruby (~> 1.0)
62
+ json (2.3.1)
61
63
  json-jwt (1.13.0)
62
64
  activesupport (>= 4.2)
63
65
  aes_key_wrap
@@ -133,6 +135,11 @@ GEM
133
135
  nokogiri (>= 1.5.10)
134
136
  ruby2_keywords (0.0.2)
135
137
  safe_yaml (1.0.5)
138
+ simplecov (0.17.0)
139
+ docile (~> 1.1)
140
+ json (>= 1.8, < 3)
141
+ simplecov-html (~> 0.10.0)
142
+ simplecov-html (0.10.2)
136
143
  sinatra (2.0.8.1)
137
144
  mustermann (~> 1.0)
138
145
  rack (~> 2.0)
@@ -174,6 +181,7 @@ DEPENDENCIES
174
181
  rack-test
175
182
  rspec (~> 3.2)
176
183
  rubocop
184
+ simplecov (= 0.17)
177
185
  webmock (~> 3.0)
178
186
 
179
187
  BUNDLED WITH
data/README.md CHANGED
@@ -1,2 +1,3 @@
1
- [![Maintainability](https://api.codeclimate.com/v1/badges/2b04828dc45bcb5abcb1/maintainability)](https://codeclimate.com/github/enterprise-oss/osso-rb/maintainability)
2
- [![Build status](https://badge.buildkite.com/0e01845bdd51be4131b9cbd496d9caa39cd48f171fc2d9a9ca.svg)](https://buildkite.com/enterpriseoss/osso-rb)
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/0d80be043d2747e91ef3/maintainability)](https://codeclimate.com/repos/5f4676cc3f757b01b6011403/maintainability)
2
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/0d80be043d2747e91ef3/test_coverage)](https://codeclimate.com/repos/5f4676cc3f757b01b6011403/test_coverage)
3
+ [![Build status](https://badge.buildkite.com/0e01845bdd51be4131b9cbd496d9caa39cd48f171fc2d9a9ca.svg)](https://buildkite.com/enterpriseoss/osso-rb)
@@ -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_23_162228) do
13
+ ActiveRecord::Schema.define(version: 2020_08_26_201852) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "pgcrypto"
@@ -27,6 +27,14 @@ ActiveRecord::Schema.define(version: 2020_07_23_162228) do
27
27
  t.index ["user_id"], name: "index_access_tokens_on_user_id"
28
28
  end
29
29
 
30
+ create_table "app_configs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
31
+ t.string "contact_email"
32
+ t.string "logo_url"
33
+ t.string "name"
34
+ t.datetime "created_at", precision: 6, null: false
35
+ t.datetime "updated_at", precision: 6, null: false
36
+ end
37
+
30
38
  create_table "authorization_codes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
31
39
  t.string "token"
32
40
  t.string "redirect_uri"
@@ -0,0 +1,11 @@
1
+ class CreateAppConfig < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :app_configs, id: :uuid do |t|
4
+ t.string :contact_email
5
+ t.string :logo_url
6
+ t.string :name
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -14,6 +14,7 @@ module Osso
14
14
  field :delete_oauth_client, mutation: Mutations::DeleteOauthClient
15
15
  field :set_redirect_uris, mutation: Mutations::SetRedirectUris
16
16
  field :regenerate_oauth_credentials, mutation: Mutations::RegenerateOauthCredentials
17
+ field :update_app_config, mutation: Mutations::UpdateAppConfig
17
18
 
18
19
  def self.authorized?(_object, _context)
19
20
  # mutations are prevented from executing with ready? so
@@ -14,3 +14,5 @@ require_relative 'mutations/delete_enterprise_account'
14
14
  require_relative 'mutations/delete_oauth_client'
15
15
  require_relative 'mutations/regenerate_oauth_credentials'
16
16
  require_relative 'mutations/set_redirect_uris'
17
+ require_relative 'mutations/update_app_config'
18
+
@@ -8,19 +8,24 @@ module Osso
8
8
 
9
9
  argument :domain, String, required: true
10
10
  argument :name, String, required: true
11
- argument :oauth_client_id, ID, required: false
11
+ argument :oauth_client_id, String, required: false
12
12
 
13
13
  field :enterprise_account, Types::EnterpriseAccount, null: false
14
14
  field :errors, [String], null: false
15
15
 
16
16
  def resolve(**args)
17
17
  enterprise_account = Osso::Models::EnterpriseAccount.new(args)
18
- enterprise_account.oauth_client_id ||= context[:oauth_client_id]
18
+ enterprise_account.oauth_client_id ||= find_client_db_id(context[:oauth_client_id])
19
19
 
20
20
  return response_data(enterprise_account: enterprise_account) if enterprise_account.save
21
21
 
22
22
  response_error(errors: enterprise_account.errors.full_messages)
23
23
  end
24
+
25
+ def find_client_db_id(oauth_client_identifier)
26
+ Osso::Models::OauthClient.find_by(identifier: oauth_client_identifier).
27
+ id
28
+ end
24
29
  end
25
30
  end
26
31
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class UpdateAppConfig < BaseMutation
7
+ null false
8
+
9
+ argument :name, String, required: false
10
+ argument :logo_url, String, required: false
11
+ argument :contact_email, String, required: false
12
+
13
+
14
+ field :app_config, Types::AppConfig, null: true
15
+ field :errors, [String], null: false
16
+
17
+ def resolve(**args)
18
+ app_config = Osso::Models::AppConfig.find
19
+ return response_data(app_config: app_config) if app_config.update(**args)
20
+
21
+ response_error(errors: e)
22
+ end
23
+
24
+ def ready?(*)
25
+ admin_ready?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -24,6 +24,13 @@ module Osso
24
24
  argument :id, ID, required: true
25
25
  end
26
26
 
27
+ field(
28
+ :app_config,
29
+ Types::AppConfig,
30
+ null: false,
31
+ resolve: ->(_obj, _args, _context) { Osso::Models::AppConfig.find },
32
+ )
33
+
27
34
  field(
28
35
  :oauth_client,
29
36
  Types::OauthClient,
@@ -10,6 +10,7 @@ require_relative 'types/base_object'
10
10
  require_relative 'types/base_enum'
11
11
  require_relative 'types/base_input_object'
12
12
  require_relative 'types/admin_user'
13
+ require_relative 'types/app_config'
13
14
  require_relative 'types/identity_provider_service'
14
15
  require_relative 'types/identity_provider_status'
15
16
  require_relative 'types/identity_provider'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Osso
6
+ module GraphQL
7
+ module Types
8
+ class AppConfig < Types::BaseObject
9
+ description 'Configuration values for your application'
10
+
11
+ field :id, ID, null: false
12
+ field :name, String, null: true
13
+ field :logo_url, String, null: true
14
+ field :contact_email, String, null: true
15
+
16
+ def self.authorized?(_object, context)
17
+ admin_authorized?(context)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -25,6 +25,21 @@ module Osso
25
25
  redirect ENV['JWT_URL']
26
26
  end
27
27
 
28
+ def internal_protected!
29
+ return if admin_authorized?
30
+ return if internal_authorized?
31
+
32
+ redirect ENV['JWT_URL']
33
+ end
34
+
35
+ def admin_protected!
36
+ return true if admin_authorized?
37
+
38
+ redirect ENV['JWT_URL']
39
+ end
40
+
41
+ private
42
+
28
43
  def enterprise_authorized?(domain)
29
44
  decode(token)
30
45
 
@@ -34,13 +49,6 @@ module Osso
34
49
  false
35
50
  end
36
51
 
37
- def internal_protected!
38
- return if admin_authorized?
39
- return if internal_authorized?
40
-
41
- redirect ENV['JWT_URL']
42
- end
43
-
44
52
  def internal_authorized?
45
53
  decode(token)
46
54
 
@@ -49,12 +57,6 @@ module Osso
49
57
  false
50
58
  end
51
59
 
52
- def admin_protected!
53
- return if admin_authorized?
54
-
55
- redirect ENV['JWT_URL']
56
- end
57
-
58
60
  def admin_authorized?
59
61
  decode(token)
60
62
 
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ class AppConfig < ::ActiveRecord::Base
6
+ validate :limit_to_one, on: :create
7
+
8
+ def self.find
9
+ first
10
+ end
11
+
12
+ private
13
+
14
+ def limit_to_one
15
+ return if Osso::Models::AppConfig.count.zero?
16
+
17
+ errors[:base] << 'AppConfig already exists'
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # == Schema Information
24
+ #
25
+ # Table name: app_configs
26
+ #
27
+ # id :uuid not null, primary key
28
+ # contact_email :string
29
+ # logo_url :string
30
+ # name :string
31
+ # created_at :datetime not null
32
+ # updated_at :datetime not null
33
+ #
@@ -10,6 +10,7 @@ module Osso
10
10
  end
11
11
 
12
12
  require_relative 'access_token'
13
+ require_relative 'app_config'
13
14
  require_relative 'authorization_code'
14
15
  require_relative 'enterprise_account'
15
16
  require_relative 'oauth_client'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.18'
4
+ VERSION = '0.0.3.19'
5
5
  end
@@ -12,5 +12,7 @@ namespace :osso do
12
12
  name: environement,
13
13
  )
14
14
  end
15
+
16
+ Osso::Models::AppConfig.create!
15
17
  end
16
18
  end
@@ -5,6 +5,7 @@ require 'spec_helper'
5
5
  describe Osso::GraphQL::Schema do
6
6
  describe 'CreateIdentityProvider' do
7
7
  let(:domain) { Faker::Internet.domain_name }
8
+ let!(:oauth_client) { create(:oauth_client) }
8
9
  let(:variables) do
9
10
  {
10
11
  input: {
@@ -41,11 +42,45 @@ describe Osso::GraphQL::Schema do
41
42
  let(:current_context) do
42
43
  { scope: 'admin' }
43
44
  end
45
+ let(:variables) do
46
+ {
47
+ input: {
48
+ name: Faker::Company.name,
49
+ domain: domain,
50
+ oauthClientId: oauth_client.id,
51
+ },
52
+ }
53
+ end
54
+
55
+ it 'creates an Enterprise Account' do
56
+ expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(1)
57
+ expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
58
+ to eq(domain)
59
+ end
60
+
61
+ it 'attaches the Enterprise Account to the correct OAuth Client' do
62
+ expect { subject }.to change { oauth_client.enterprise_accounts.count }.by(1)
63
+ end
64
+ end
65
+
66
+ describe 'for an internal scoped user' do
67
+ let(:current_context) do
68
+ {
69
+ scope: 'internal',
70
+ email: 'user@saasco.com',
71
+ oauth_client_id: oauth_client.identifier,
72
+ }
73
+ end
74
+
44
75
  it 'creates an Enterprise Account' do
45
76
  expect { subject }.to change { Osso::Models::EnterpriseAccount.count }.by(1)
46
77
  expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
47
78
  to eq(domain)
48
79
  end
80
+
81
+ it 'attaches the Enterprise Account to the correct OAuth Client' do
82
+ expect { subject }.to change { oauth_client.enterprise_accounts.count }.by(1)
83
+ end
49
84
  end
50
85
 
51
86
  describe 'for an email scoped user' do
@@ -53,6 +88,7 @@ describe Osso::GraphQL::Schema do
53
88
  {
54
89
  scope: 'end-user',
55
90
  email: "user@#{domain}",
91
+ oauth_client_id: oauth_client.identifier,
56
92
  }
57
93
  end
58
94
 
@@ -61,6 +97,10 @@ describe Osso::GraphQL::Schema do
61
97
  expect(subject.dig('data', 'createEnterpriseAccount', 'enterpriseAccount', 'domain')).
62
98
  to eq(domain)
63
99
  end
100
+
101
+ it 'attaches the Enterprise Account to the correct OAuth Client' do
102
+ expect { subject }.to change { oauth_client.enterprise_accounts.count }.by(1)
103
+ end
64
104
  end
65
105
  describe 'for the wrong email scoped user' do
66
106
  let(:current_context) do
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Osso::Helpers::Auth do
6
+ before do
7
+ ENV['JWT_HMAC_SECRET'] = 'super-secret'
8
+ end
9
+
10
+ subject(:app) do
11
+ Class.new { include Osso::Helpers::Auth }
12
+ end
13
+
14
+ describe 'with the token as a header' do
15
+ before do
16
+ allow_any_instance_of(subject).to receive(:request) do
17
+ double('Request', env: { 'admin_token' => token }, post?: false)
18
+ end
19
+
20
+ allow_any_instance_of(subject).to receive(:redirect) do
21
+ false
22
+ end
23
+ end
24
+
25
+ describe 'with an admin token' do
26
+ let(:token) { encode({ scope: 'admin' }) }
27
+
28
+ it 'allows #token_protected! methods' do
29
+ expect(subject.new.token_protected!).to_not be(false)
30
+ end
31
+
32
+ it 'allows #enterprise_protected! methods' do
33
+ expect(subject.new.enterprise_protected!).to_not be(false)
34
+ end
35
+
36
+ it 'allows #internal_protected! methods' do
37
+ expect(subject.new.internal_protected!).to_not be(false)
38
+ end
39
+
40
+ it 'allows #admin_protected! methods' do
41
+ expect(subject.new.admin_protected!).to_not be(false)
42
+ end
43
+ end
44
+
45
+ describe 'with an internal token' do
46
+ let(:token) { encode({ scope: 'internal' }) }
47
+
48
+ it 'allows #token_protected! methods' do
49
+ expect(subject.new.token_protected!).to_not be(false)
50
+ end
51
+
52
+ it 'allows #enterprise_protected! methods' do
53
+ expect(subject.new.enterprise_protected!).to_not be(false)
54
+ end
55
+
56
+ it 'allows #internal_protected! methods' do
57
+ expect(subject.new.internal_protected!).to_not be(false)
58
+ end
59
+
60
+ it 'allows #admin_protected! methods' do
61
+ expect(subject.new.admin_protected!).to be(false)
62
+ end
63
+ end
64
+
65
+ describe 'with an end-user token' do
66
+ let(:token) { encode({ scope: 'end-user', email: 'user@example.com' }) }
67
+
68
+ it 'allows #token_protected! methods' do
69
+ expect(subject.new.token_protected!).to_not be(false)
70
+ end
71
+
72
+ it 'allows #enterprise_protected! methods for the scoped domain' do
73
+ expect(subject.new.enterprise_protected!('example.com')).to_not be(false)
74
+ end
75
+
76
+ it 'halts #enterprise_protected! methods for the wrong scoped domain' do
77
+ expect(subject.new.enterprise_protected!('foo.com')).to be(false)
78
+ end
79
+
80
+ it 'halts #internal_protected! methods' do
81
+ expect(subject.new.internal_protected!).to be(false)
82
+ end
83
+
84
+ it 'halts #admin_protected! methods' do
85
+ expect(subject.new.admin_protected!).to be(false)
86
+ end
87
+ end
88
+ end
89
+
90
+ def encode(payload)
91
+ JWT.encode(
92
+ payload,
93
+ ENV['JWT_HMAC_SECRET'],
94
+ 'HS256',
95
+ )
96
+ end
97
+ end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
3
6
  require 'database_cleaner/active_record'
4
7
  require 'factory_bot'
5
8
  require 'faker'
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.18
4
+ version: 0.0.3.19
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-08-19 00:00:00.000000000 Z
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -270,6 +270,7 @@ files:
270
270
  - lib/osso/db/migrate/20200722230116_add_identity_provider_status_enum_and_use_on_identity_providers.rb
271
271
  - lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb
272
272
  - lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb
273
+ - lib/osso/db/migrate/20200826201852_create_app_config.rb
273
274
  - lib/osso/graphql/.DS_Store
274
275
  - lib/osso/graphql/mutation.rb
275
276
  - lib/osso/graphql/mutations.rb
@@ -282,6 +283,7 @@ files:
282
283
  - lib/osso/graphql/mutations/delete_oauth_client.rb
283
284
  - lib/osso/graphql/mutations/regenerate_oauth_credentials.rb
284
285
  - lib/osso/graphql/mutations/set_redirect_uris.rb
286
+ - lib/osso/graphql/mutations/update_app_config.rb
285
287
  - lib/osso/graphql/query.rb
286
288
  - lib/osso/graphql/resolvers.rb
287
289
  - lib/osso/graphql/resolvers/base_resolver.rb
@@ -291,6 +293,7 @@ files:
291
293
  - lib/osso/graphql/schema.rb
292
294
  - lib/osso/graphql/types.rb
293
295
  - lib/osso/graphql/types/admin_user.rb
296
+ - lib/osso/graphql/types/app_config.rb
294
297
  - lib/osso/graphql/types/base_connection.rb
295
298
  - lib/osso/graphql/types/base_enum.rb
296
299
  - lib/osso/graphql/types/base_input_object.rb
@@ -308,6 +311,7 @@ files:
308
311
  - lib/osso/lib/oauth2_token.rb
309
312
  - lib/osso/lib/route_map.rb
310
313
  - lib/osso/models/access_token.rb
314
+ - lib/osso/models/app_config.rb
311
315
  - lib/osso/models/authorization_code.rb
312
316
  - lib/osso/models/enterprise_account.rb
313
317
  - lib/osso/models/identity_provider.rb
@@ -341,6 +345,7 @@ files:
341
345
  - spec/graphql/query/enterprise_accounts_spec.rb
342
346
  - spec/graphql/query/identity_provider_spec.rb
343
347
  - spec/graphql/query/oauth_clients_spec.rb
348
+ - spec/helpers/auth_spec.rb
344
349
  - spec/models/azure_saml_provider_spec.rb
345
350
  - spec/models/identity_provider_spec.rb
346
351
  - spec/models/okta_saml_provider_spec.rb