osso 0.0.3.9 → 0.0.3.15

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: 3f0c8535a6ba6dd39ada0f3ba0aa0617ff96bd880ef6985149c0ecbeca57bc1a
4
- data.tar.gz: da6bec63d5e071b1c0520e42cd67c3971851445bfad8ec597f1b9d1aef0759d8
3
+ metadata.gz: a63fecde3c20b225ac8f4f52dfa33cbbbcc768337b43b38d3e482e7a6d38806a
4
+ data.tar.gz: 0ef7c41aef96e4b8299481a5cd9ca7f43c1b59b2ef846b813f9e8aa41957530e
5
5
  SHA512:
6
- metadata.gz: 3e3938abd7b541d6e272cb1b1420e9f4dc75738edd763cc1c35e82db4b315852c125f268ad8ed36528373252c23bdea79b7ac865711abb1c52159cae709c47c5
7
- data.tar.gz: fa63314128c1833ddd1136ea1cdacee8e8f4cbfb92a6eaffc0c8ae8dfc0ccb93b62effcac55e0cf916033a32cd1941e5ea915959f032ed6a983133711f4610e0
6
+ metadata.gz: cca50c6661352e1f076b747d90038796ba9f76590c9baa18e05128d2bc891a7f7de1090541f464814f28eacb713e0ed8f65fac34ac78a636674000df64092e1f
7
+ data.tar.gz: a290b9403984ef9d454529008b62be363a1409cf5ff398a7db7e74f7a99e84f4fadb5c54fb7f939243496a863a4a155c841bf92101e1357dae4cbc2ae51a4f96
@@ -5,4 +5,11 @@ steps:
5
5
  - bundle exec rake db:drop
6
6
  - bundle exec rake db:create
7
7
  - RACK_ENV=test bundle exec rake db:migrate
8
- - bundle exec rspec
8
+ - bundle exec rspec
9
+
10
+ - block: ":rubygems: Publish :red_button:"
11
+ branches: "main"
12
+
13
+ - name: "Push :rubygems:"
14
+ commands: "./bin/publish"
15
+ branches: "main"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.3.9)
4
+ osso (0.0.3.15)
5
5
  activesupport (>= 6.0.3.2)
6
6
  graphql
7
7
  jwt
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+ # Scriptacular - gemify.sh
3
+ # Create a Ruby gem and push it to rubygems.org
4
+ # Copyright 2013 Christopher Simpkins
5
+ # MIT License
6
+
7
+ GEM_NAME="osso-rb"
8
+ GEMSPEC_SUFFIX=".gemspec"
9
+
10
+ # run the gem build and parse for the gem release filename
11
+ GEM_BUILD_NAME=$(gem build "$GEM_NAME$GEMSPEC_SUFFIX" | awk '/File/ {print $2}' -)
12
+
13
+ if [ -z "$GEM_BUILD_NAME" ]; then
14
+ echo "The gem build failed." >&2
15
+ exit 1
16
+ fi
17
+
18
+ gem push $GEM_BUILD_NAME
@@ -12,6 +12,8 @@ module Osso
12
12
  field :create_oauth_client, mutation: Mutations::CreateOauthClient
13
13
  field :delete_enterprise_account, mutation: Mutations::DeleteEnterpriseAccount
14
14
  field :delete_oauth_client, mutation: Mutations::DeleteOauthClient
15
+ field :set_redirect_uris, mutation: Mutations::SetRedirectUris
16
+ field :regenerate_oauth_credentials, mutation: Mutations::RegenerateOauthCredentials
15
17
  end
16
18
  end
17
19
  end
@@ -12,3 +12,5 @@ require_relative 'mutations/create_enterprise_account'
12
12
  require_relative 'mutations/create_oauth_client'
13
13
  require_relative 'mutations/delete_enterprise_account'
14
14
  require_relative 'mutations/delete_oauth_client'
15
+ require_relative 'mutations/regenerate_oauth_credentials'
16
+ require_relative 'mutations/set_redirect_uris'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class RegenerateOauthCredentials < BaseMutation
7
+ null false
8
+
9
+ argument :id, ID, required: true
10
+
11
+ field :oauth_client, Types::OauthClient, null: false
12
+ field :errors, [String], null: false
13
+
14
+ def resolve(id:)
15
+ oauth_client = Osso::Models::OauthClient.find(id)
16
+ oauth_client.generate_secrets
17
+
18
+ return response_data(oauth_client: oauth_client) if oauth_client.save
19
+
20
+ response_error(errors: oauth_client.errors.full_messages)
21
+ end
22
+
23
+ def ready?(*)
24
+ return true if context[:scope] == :admin
25
+
26
+ raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Mutations
6
+ class SetRedirectUris < BaseMutation
7
+ null false
8
+
9
+ argument :id, ID, required: true
10
+ argument :redirect_uris, [Types::RedirectUrisInput], required: true
11
+
12
+ field :oauth_client, Types::OauthClient, null: true
13
+ field :errors, [String], null: false
14
+
15
+ def resolve(id:, redirect_uris:)
16
+ oauth_client = Osso::Models::OauthClient.find(id)
17
+
18
+ update_existing(oauth_client, redirect_uris)
19
+ create_new(oauth_client, redirect_uris)
20
+
21
+ response_data(oauth_client: oauth_client.reload)
22
+ rescue StandardError => e
23
+ response_error(errors: e)
24
+ end
25
+
26
+ def ready?(*)
27
+ return true if context[:scope] == :admin
28
+
29
+ raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
30
+ end
31
+
32
+ def update_existing(oauth_client, redirect_uris)
33
+ oauth_client.redirect_uris.each do |redirect|
34
+ updating_index = redirect_uris.index{ |incoming| incoming[:id] == redirect.id }
35
+
36
+ if updating_index
37
+ updating = redirect_uris.delete_at(updating_index)
38
+ redirect.update(updating.to_h)
39
+ next
40
+ end
41
+
42
+ redirect.destroy
43
+ end
44
+ end
45
+
46
+ def create_new(oauth_client, redirect_uris)
47
+ redirect_uris.map do |uri|
48
+ oauth_client.redirect_uris.create(uri.to_h.without(:id))
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -4,13 +4,17 @@ module Osso
4
4
  module GraphQL
5
5
  module Types
6
6
  class QueryType < ::GraphQL::Schema::Object
7
- field :enterprise_accounts, null: true, resolver: Resolvers::EnterpriseAccounts
8
- field :oauth_clients, null: true, resolver: Resolvers::OAuthClients
7
+ field :enterprise_accounts, null: true, resolver: Resolvers::EnterpriseAccounts do
8
+ argument :sort_column, String, required: false
9
+ argument :sort_order, String, required: false
10
+ end
9
11
 
10
12
  field :enterprise_account, null: true, resolver: Resolvers::EnterpriseAccount do
11
13
  argument :domain, String, required: true
12
14
  end
13
15
 
16
+ field :oauth_clients, null: true, resolver: Resolvers::OAuthClients
17
+
14
18
  field(
15
19
  :identity_provider,
16
20
  Types::IdentityProvider,
@@ -19,6 +23,15 @@ module Osso
19
23
  ) do
20
24
  argument :id, ID, required: true
21
25
  end
26
+
27
+ field(
28
+ :oauth_client,
29
+ Types::OauthClient,
30
+ null: true,
31
+ resolve: ->(_obj, args, _context) { Osso::Models::OauthClient.find(args[:id]) },
32
+ ) do
33
+ argument :id, ID, required: true
34
+ end
22
35
  end
23
36
  end
24
37
  end
@@ -4,12 +4,20 @@ module Osso
4
4
  module GraphQL
5
5
  module Resolvers
6
6
  class EnterpriseAccounts < ::GraphQL::Schema::Resolver
7
- type [Types::EnterpriseAccount], null: true
7
+ type Types::EnterpriseAccount.connection_type, null: true
8
8
 
9
- def resolve
10
- return Osso::Models::EnterpriseAccount.all if context[:scope] == :admin
9
+ def resolve(sort_column: nil, sort_order: nil)
10
+ return Array(Osso::Models::EnterpriseAccount.find_by(domain: context[:scope])) if context[:scope] != :admin
11
11
 
12
- Array(Osso::Models::EnterpriseAccount.find_by(domain: context[:scope]))
12
+ accounts = Osso::Models::EnterpriseAccount
13
+
14
+ accounts = accounts.order(sort_column => sort_order_sym(sort_order)) if sort_column && sort_order
15
+
16
+ accounts.all
17
+ end
18
+
19
+ def sort_order_sym(order_string)
20
+ order_string == 'ascend' ? :asc : :desc
13
21
  end
14
22
  end
15
23
  end
@@ -5,6 +5,7 @@ module Osso
5
5
  end
6
6
  end
7
7
 
8
+ require_relative 'types/base_connection'
8
9
  require_relative 'types/base_object'
9
10
  require_relative 'types/base_enum'
10
11
  require_relative 'types/base_input_object'
@@ -12,5 +13,7 @@ require_relative 'types/identity_provider_service'
12
13
  require_relative 'types/identity_provider_status'
13
14
  require_relative 'types/identity_provider'
14
15
  require_relative 'types/enterprise_account'
16
+ require_relative 'types/redirect_uri'
17
+ require_relative 'types/redirect_uri_input'
15
18
  require_relative 'types/oauth_client'
16
19
  require_relative 'types/user'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module GraphQL
5
+ module Types
6
+ class BaseConnection < ::GraphQL::Types::Relay::BaseConnection
7
+ field :total_count, Integer, null: false
8
+
9
+ def total_count
10
+ object.items&.count
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -6,6 +6,8 @@ module Osso
6
6
  module GraphQL
7
7
  module Types
8
8
  class BaseObject < ::GraphQL::Schema::Object
9
+ connection_type_class GraphQL::Types::BaseConnection
10
+
9
11
  field :created_at, ::GraphQL::Types::ISO8601DateTime, null: false
10
12
  field :updated_at, ::GraphQL::Types::ISO8601DateTime, null: false
11
13
  end
@@ -14,6 +14,7 @@ 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
+ field :redirect_uris, [Types::RedirectUri], null: true
17
18
 
18
19
  def client_id
19
20
  object.identifier
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Osso
6
+ module GraphQL
7
+ module Types
8
+ class RedirectUri < Types::BaseObject
9
+ description 'An allowed redirect URI for an OauthClient'
10
+ implements ::GraphQL::Types::Relay::Node
11
+
12
+ global_id_field :gid
13
+ field :id, ID, null: false
14
+ field :uri, String, null: false
15
+ field :primary, Boolean, null: false
16
+
17
+ def self.authorized?(object, context)
18
+ super && context[:scope] == :admin
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Osso
6
+ module GraphQL
7
+ module Types
8
+ class RedirectUrisInput < Types::BaseInputObject
9
+ description 'Attributes for creating or updating a collection of redirect URIs for an Oauth Client'
10
+ argument :id, ID, 'Database ID', required: false
11
+ argument :uri, String, 'URI value', required: true
12
+ argument :primary, Boolean, 'Whether the URI is the primary uri used in IDP initiated login', required: true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -14,6 +14,8 @@ module Osso
14
14
  redirect ENV['JWT_URL']
15
15
  end
16
16
 
17
+ # use client id in payload to restrict customer
18
+ # users from accessing dev?
17
19
  def enterprise_authorized?(_domain)
18
20
  payload, _args = decode(token)
19
21
 
@@ -19,20 +19,14 @@ module Osso
19
19
  end
20
20
 
21
21
  def saml_options
22
- attributes.slice(
23
- 'domain',
24
- 'idp_cert',
25
- 'idp_sso_target_url',
26
- ).symbolize_keys
22
+ {
23
+ domain: domain,
24
+ idp_sso_target_url: sso_url,
25
+ idp_cert: sso_cert,
26
+ issuer: domain,
27
+ }
27
28
  end
28
29
 
29
- # def saml_options
30
- # raise(
31
- # NoMethodError,
32
- # '#saml_options must be defined on each provider specific subclass',
33
- # )
34
- # end
35
-
36
30
  def assertion_consumer_service_url
37
31
  [
38
32
  ENV.fetch('BASE_URL'),
@@ -9,11 +9,11 @@ module Osso
9
9
  has_many :identity_providers
10
10
  has_many :redirect_uris
11
11
 
12
- before_validation :setup, on: :create
12
+ before_validation :generate_secrets, on: :create
13
13
  validates :name, :secret, presence: true
14
14
  validates :identifier, presence: true, uniqueness: true
15
15
 
16
- def default_redirect_uri
16
+ def primary_redirect_uri
17
17
  redirect_uris.find(&:primary)
18
18
  end
19
19
 
@@ -21,9 +21,7 @@ module Osso
21
21
  redirect_uris.map(&:uri)
22
22
  end
23
23
 
24
- private
25
-
26
- def setup
24
+ def generate_secrets
27
25
  self.identifier = SecureRandom.hex(16)
28
26
  self.secret = SecureRandom.hex(32)
29
27
  end
@@ -36,6 +36,12 @@ module Osso
36
36
 
37
37
  erb :admin
38
38
  end
39
+
40
+ get '/config/:id' do
41
+ admin_protected!
42
+
43
+ erb :admin
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -23,7 +23,7 @@ module Osso
23
23
  self,
24
24
  provider_name: 'saml',
25
25
  identity_provider_id_regex: UUID_REGEXP,
26
- path_prefix: '/saml',
26
+ path_prefix: '/auth/saml',
27
27
  callback_suffix: 'callback',
28
28
  ) do |identity_provider_id, _env|
29
29
  provider = Models::IdentityProvider.find(identity_provider_id)
@@ -40,7 +40,7 @@ module Osso
40
40
  post '/saml/:id/callback' do
41
41
  provider = Models::IdentityProvider.find(params[:id])
42
42
  oauth_client = provider.oauth_client
43
- redirect_uri = env['redirect_uri'] || oauth_client.default_redirect_uri.uri
43
+ redirect_uri = env['redirect_uri'] || oauth_client.primary_redirect_uri.uri
44
44
 
45
45
  attributes = env['omniauth.auth']&.
46
46
  extra&.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.9'
4
+ VERSION = '0.0.3.15'
5
5
  end
@@ -7,37 +7,51 @@ describe Osso::GraphQL::Schema do
7
7
  describe 'for an admin user' do
8
8
  let(:current_scope) { :admin }
9
9
 
10
- it 'returns Enterprise Accounts' do
11
- create_list(:enterprise_account, 2)
10
+ it 'returns paginated Enterprise Accounts' do
11
+ %w[A B C].map do |name|
12
+ create(:enterprise_account, name: name)
13
+ end
12
14
 
13
15
  query = <<~GRAPHQL
14
- query EnterpriseAccounts {
15
- enterpriseAccounts {
16
- domain
17
- id
18
- identityProviders {
19
- id
20
- service
21
- domain
22
- acsUrl
23
- ssoCert
24
- ssoUrl
25
- status
16
+ query EnterpriseAccounts($first: Int, $sortColumn: String, $sortOrder: String) {
17
+ enterpriseAccounts(first: $first, sortColumn: $sortColumn, sortOrder: $sortOrder) {
18
+ pageInfo {
19
+ hasNextPage
20
+ endCursor
21
+ }
22
+ totalCount
23
+ edges {
24
+ node {
25
+ domain
26
+ id
27
+ identityProviders {
28
+ id
29
+ service
30
+ domain
31
+ acsUrl
32
+ ssoCert
33
+ ssoUrl
34
+ status
35
+ }
36
+ name
37
+ status
38
+ }
26
39
  }
27
- name
28
- status
29
40
  }
30
41
  }
31
42
  GRAPHQL
32
43
 
33
44
  response = described_class.execute(
34
45
  query,
35
- variables: nil,
46
+ variables: { first: 2, sortOrder: 'descending', sortColumn: 'name' },
36
47
  context: { scope: current_scope },
37
48
  )
38
49
 
39
50
  expect(response['errors']).to be_nil
40
- expect(response.dig('data', 'enterpriseAccounts').count).to eq(2)
51
+ expect(response.dig('data', 'enterpriseAccounts', 'edges').count).to eq(2)
52
+ expect(response.dig('data', 'enterpriseAccounts', 'edges', 0, 'node', 'name')).to eq('C')
53
+ expect(response.dig('data', 'enterpriseAccounts', 'totalCount')).to eq(3)
54
+ expect(response.dig('data', 'enterpriseAccounts', 'pageInfo', 'hasNextPage')).to eq(true)
41
55
  end
42
56
  end
43
57
  end
@@ -14,4 +14,16 @@ describe Osso::Models::IdentityProvider do
14
14
  )
15
15
  end
16
16
  end
17
+
18
+ describe '#saml_options' do
19
+ it 'returns the required args' do
20
+ expect(subject.saml_options).
21
+ to match(
22
+ domain: subject.domain,
23
+ idp_cert: subject.sso_cert,
24
+ idp_sso_target_url: subject.sso_url,
25
+ issuer: subject.domain,
26
+ )
27
+ end
28
+ end
17
29
  end
@@ -3,6 +3,31 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Osso::Auth do
6
+ describe 'get /auth/saml/:uuid' do
7
+ describe 'for an Okta SAML provider' do
8
+ let(:enterprise) { create(:enterprise_with_okta) }
9
+ let(:okta_provider) { enterprise.identity_providers.first }
10
+ it 'uses omniauth saml' do
11
+ get("/auth/saml/#{okta_provider.id}")
12
+
13
+ expect(last_response).to be_redirect
14
+ follow_redirect!
15
+ expect(last_request.url).to match("auth/saml/#{okta_provider.id}")
16
+ end
17
+ end
18
+
19
+ describe 'for an Azure SAML provider' do
20
+ let(:enterprise) { create(:enterprise_with_okta) }
21
+ let(:azure_provider) { enterprise.identity_providers.first }
22
+ it 'uses omniauth saml' do
23
+ get("/auth/saml/#{azure_provider.id}")
24
+
25
+ expect(last_response).to be_redirect
26
+ follow_redirect!
27
+ expect(last_request.url).to match("auth/saml/#{azure_provider.id}")
28
+ end
29
+ end
30
+ end
6
31
  describe 'post /auth/saml/:uuid/callback' do
7
32
  describe 'for an Okta SAML provider' do
8
33
  let(:enterprise) { create(:enterprise_with_okta) }
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.9
4
+ version: 0.0.3.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Bauch
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-24 00:00:00.000000000 Z
11
+ date: 2020-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -226,6 +226,7 @@ email:
226
226
  executables:
227
227
  - annotate
228
228
  - console
229
+ - publish
229
230
  - setup
230
231
  extensions: []
231
232
  extra_rdoc_files: []
@@ -246,6 +247,7 @@ files:
246
247
  - Rakefile
247
248
  - bin/annotate
248
249
  - bin/console
250
+ - bin/publish
249
251
  - bin/setup
250
252
  - config/database.yml
251
253
  - db/schema.rb
@@ -278,6 +280,8 @@ files:
278
280
  - lib/osso/graphql/mutations/create_oauth_client.rb
279
281
  - lib/osso/graphql/mutations/delete_enterprise_account.rb
280
282
  - lib/osso/graphql/mutations/delete_oauth_client.rb
283
+ - lib/osso/graphql/mutations/regenerate_oauth_credentials.rb
284
+ - lib/osso/graphql/mutations/set_redirect_uris.rb
281
285
  - lib/osso/graphql/query.rb
282
286
  - lib/osso/graphql/resolvers.rb
283
287
  - lib/osso/graphql/resolvers/enterprise_account.rb
@@ -285,6 +289,7 @@ files:
285
289
  - lib/osso/graphql/resolvers/oauth_clients.rb
286
290
  - lib/osso/graphql/schema.rb
287
291
  - lib/osso/graphql/types.rb
292
+ - lib/osso/graphql/types/base_connection.rb
288
293
  - lib/osso/graphql/types/base_enum.rb
289
294
  - lib/osso/graphql/types/base_input_object.rb
290
295
  - lib/osso/graphql/types/base_object.rb
@@ -293,6 +298,8 @@ files:
293
298
  - lib/osso/graphql/types/identity_provider_service.rb
294
299
  - lib/osso/graphql/types/identity_provider_status.rb
295
300
  - lib/osso/graphql/types/oauth_client.rb
301
+ - lib/osso/graphql/types/redirect_uri.rb
302
+ - lib/osso/graphql/types/redirect_uri_input.rb
296
303
  - lib/osso/graphql/types/user.rb
297
304
  - lib/osso/helpers/auth.rb
298
305
  - lib/osso/helpers/helpers.rb
@@ -347,7 +354,7 @@ homepage: https://github.com/enterprise-oss/osso-rb
347
354
  licenses:
348
355
  - MIT
349
356
  metadata: {}
350
- post_install_message:
357
+ post_install_message:
351
358
  rdoc_options: []
352
359
  require_paths:
353
360
  - lib
@@ -363,7 +370,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
363
370
  version: '0'
364
371
  requirements: []
365
372
  rubygems_version: 3.0.3
366
- signing_key:
373
+ signing_key:
367
374
  specification_version: 4
368
375
  summary: Main functionality for Osso
369
376
  test_files: []