osso 0.0.3.18 → 0.0.3.19

Sign up to get free protection for your applications and to get access to all the features.
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