osso 0.0.7 → 0.1.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/pipeline.yml +1 -0
  3. data/.rubocop.yml +4 -16
  4. data/Gemfile +2 -2
  5. data/Gemfile.lock +62 -58
  6. data/Rakefile +1 -0
  7. data/bin/console +3 -0
  8. data/lib/osso.rb +1 -0
  9. data/lib/osso/graphql/mutations/configure_identity_provider.rb +4 -1
  10. data/lib/osso/graphql/mutations/create_enterprise_account.rb +4 -1
  11. data/lib/osso/graphql/mutations/create_identity_provider.rb +8 -3
  12. data/lib/osso/graphql/mutations/create_oauth_client.rb +4 -1
  13. data/lib/osso/graphql/mutations/delete_enterprise_account.rb +4 -1
  14. data/lib/osso/graphql/mutations/delete_identity_provider.rb +4 -1
  15. data/lib/osso/graphql/mutations/delete_oauth_client.rb +4 -1
  16. data/lib/osso/graphql/mutations/invite_admin_user.rb +6 -0
  17. data/lib/osso/graphql/mutations/regenerate_oauth_credentials.rb +10 -1
  18. data/lib/osso/graphql/mutations/set_redirect_uris.rb +2 -0
  19. data/lib/osso/graphql/mutations/update_app_config.rb +4 -1
  20. data/lib/osso/graphql/query.rb +26 -31
  21. data/lib/osso/graphql/schema.rb +0 -1
  22. data/lib/osso/lib/analytics.rb +55 -0
  23. data/lib/osso/lib/route_map.rb +2 -0
  24. data/lib/osso/models/account.rb +1 -1
  25. data/lib/osso/models/identity_provider.rb +3 -2
  26. data/lib/osso/routes/admin.rb +47 -5
  27. data/lib/osso/routes/auth.rb +2 -0
  28. data/lib/osso/routes/oauth.rb +10 -4
  29. data/lib/osso/version.rb +1 -1
  30. data/lib/tasks/bootstrap.rake +6 -4
  31. data/osso-rb.gemspec +5 -3
  32. data/spec/graphql/mutations/create_identity_provider_spec.rb +1 -1
  33. data/spec/models/identity_provider_spec.rb +1 -0
  34. data/spec/routes/admin_spec.rb +54 -9
  35. data/spec/routes/auth_spec.rb +5 -3
  36. data/spec/routes/oauth_spec.rb +20 -12
  37. data/spec/spec_helper.rb +2 -0
  38. data/spec/support/views/hosted_login.erb +1 -0
  39. data/spec/support/views/saml_login_form.erb +1 -0
  40. metadata +39 -15
  41. data/spec/routes/app_spec.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3557c5b1128c7a026fa1ddb14cb570b6d247231f3dc7ef22c4ef60af427ec3a2
4
- data.tar.gz: fa59daf216455edc141fc1c1dd20b965cb90122dfa7e0e30ad3d3fc46a348951
3
+ metadata.gz: 8304c085cb599d56e9da71e5b30d8eec9096bf51f026f5f1bd2ac328b71600d7
4
+ data.tar.gz: e1d36cd4b70b19d7952c1d0e6f196c8bb608ca9b9431bdf376cacd632797d5d9
5
5
  SHA512:
6
- metadata.gz: 4089820668fa27aa45e7dbb92bf58713202657ec71e6bb2ca24d79b19176e9e444f9c114119489c08417909b7b6403c7e3a1342bf4caa3174d0d5dca77d822f3
7
- data.tar.gz: 41f3deba4a448aa35c03cf5630b1eeb9784fa200b5bdd020a2c5e29d4b8f8df95da1af0d6dea942d71cdfff2c691948412053a834fd249f8e4b66116e4d025f5
6
+ metadata.gz: 1f24f85bff86b6728a42cac1a421e8a93a2c1b3d529a668bf6935698b0d509733626677d4922febc45b6fcb88690e6a67f86c49ce69e9ed37d6e026da72a3543
7
+ data.tar.gz: 52a7d82d04e5073502c06e83b6a42bf31036a083e210f0683ce9d115ad88dbd97cf09e246a85b2d31a7cd419a8ca6b5460113a22d44e39130134cacf3cfff458
@@ -12,6 +12,7 @@ steps:
12
12
  - coverage/*
13
13
 
14
14
  - name: ":codeclimate:"
15
+ soft_fail: true
15
16
  plugins:
16
17
  - jobready/codeclimate-test-reporter#v2.0:
17
18
  artifact: "coverage/.resultset.json"
@@ -1,25 +1,10 @@
1
1
  AllCops:
2
+ NewCops: enable
2
3
  TargetRubyVersion: 2.6.0
3
4
  Exclude:
4
5
  - db/**/*
5
6
  - lib/osso/db/**/*
6
7
 
7
- # New rules must be explicitly opted into / out of
8
- Lint/RaiseException:
9
- Enabled: true
10
- Lint/StructNewOverride:
11
- Enabled: true
12
- Style/HashEachMethods:
13
- Enabled: true
14
- Style/HashTransformKeys:
15
- Enabled: true
16
- Style/HashTransformValues:
17
- Enabled: true
18
- Layout/SpaceAroundMethodCallOperator:
19
- Enabled: true
20
- Style/ExponentialNotation:
21
- Enabled: true
22
-
23
8
  Style/TrailingCommaInArguments:
24
9
  Description: "Checks for trailing comma in argument lists."
25
10
  StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas"
@@ -50,6 +35,9 @@ Style/TrailingCommaInHashLiteral:
50
35
  - no_comma
51
36
  Enabled: true
52
37
 
38
+ Layout/FirstHashElementIndentation:
39
+ EnforcedStyle: consistent
40
+
53
41
  Layout/MultilineMethodCallIndentation:
54
42
  EnforcedStyle: indented
55
43
 
data/Gemfile CHANGED
@@ -12,8 +12,8 @@ group :test do
12
12
  gem 'rack-test'
13
13
  gem 'rspec', '~> 3.10'
14
14
  gem 'rubocop'
15
- gem 'simplecov', '= 0.17', require: false
16
- gem 'webmock', '~> 3.10'
15
+ gem 'simplecov', '0.21.2', require: false
16
+ gem 'webmock', '~> 3.11'
17
17
  end
18
18
 
19
19
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.7)
4
+ osso (0.1.1)
5
5
  activesupport (>= 6.0.3.2)
6
6
  bcrypt (~> 3.1.13)
7
7
  graphql
@@ -9,31 +9,33 @@ PATH
9
9
  mail (~> 2.7.1)
10
10
  omniauth-multi-provider
11
11
  omniauth-saml
12
+ posthog-ruby
12
13
  rack (>= 2.1.4)
13
14
  rack-contrib
14
15
  rack-oauth2
16
+ rack-protection (~> 2.1.0)
15
17
  rake
16
- rodauth (~> 2.6.0)
17
- sequel (>= 5.37, < 5.40)
18
+ rodauth (~> 2.9)
19
+ sequel (~> 5.40)
18
20
  sequel-activerecord_connection (>= 0.3, < 2.0)
19
21
  sinatra
20
- sinatra-activerecord
22
+ sinatra-activerecord (>= 2.0.22)
21
23
  sinatra-contrib
22
24
 
23
25
  GEM
24
26
  remote: https://rubygems.org/
25
27
  specs:
26
- activemodel (6.0.3.4)
27
- activesupport (= 6.0.3.4)
28
- activerecord (6.0.3.4)
29
- activemodel (= 6.0.3.4)
30
- activesupport (= 6.0.3.4)
31
- activesupport (6.0.3.4)
28
+ activemodel (6.1.1)
29
+ activesupport (= 6.1.1)
30
+ activerecord (6.1.1)
31
+ activemodel (= 6.1.1)
32
+ activesupport (= 6.1.1)
33
+ activesupport (6.1.1)
32
34
  concurrent-ruby (~> 1.0, >= 1.0.2)
33
- i18n (>= 0.7, < 2)
34
- minitest (~> 5.1)
35
- tzinfo (~> 1.1)
36
- zeitwerk (~> 2.2, >= 2.2.2)
35
+ i18n (>= 1.6, < 2)
36
+ minitest (>= 5.1)
37
+ tzinfo (~> 2.0)
38
+ zeitwerk (~> 2.3)
37
39
  addressable (2.7.0)
38
40
  public_suffix (>= 2.0.2, < 5.0)
39
41
  aes_key_wrap (1.1.0)
@@ -42,30 +44,30 @@ GEM
42
44
  annotate (3.1.1)
43
45
  activerecord (>= 3.2, < 7.0)
44
46
  rake (>= 10.4, < 14.0)
45
- ast (2.4.1)
47
+ ast (2.4.2)
46
48
  attr_required (1.0.1)
47
49
  bcrypt (3.1.16)
48
50
  bindata (2.4.8)
49
51
  coderay (1.1.3)
50
- concurrent-ruby (1.1.7)
51
- crack (0.4.4)
52
+ concurrent-ruby (1.1.8)
53
+ crack (0.4.5)
54
+ rexml
52
55
  database_cleaner (1.8.5)
53
56
  database_cleaner-active_record (1.8.0)
54
57
  activerecord
55
58
  database_cleaner (~> 1.8.0)
56
59
  diff-lcs (1.4.4)
57
- docile (1.3.2)
60
+ docile (1.3.5)
58
61
  factory_bot (6.1.0)
59
62
  activesupport (>= 5.0.0)
60
63
  faker (2.15.1)
61
64
  i18n (>= 1.6, < 2)
62
- graphql (1.11.6)
65
+ graphql (1.12.3)
63
66
  hashdiff (1.0.1)
64
67
  hashie (4.1.0)
65
68
  httpclient (2.8.3)
66
- i18n (1.8.5)
69
+ i18n (1.8.7)
67
70
  concurrent-ruby (~> 1.0)
68
- json (2.3.1)
69
71
  json-jwt (1.13.0)
70
72
  activesupport (>= 4.2)
71
73
  aes_key_wrap
@@ -75,29 +77,31 @@ GEM
75
77
  mini_mime (>= 0.1.1)
76
78
  method_source (1.0.0)
77
79
  mini_mime (1.0.2)
78
- mini_portile2 (2.4.0)
79
- minitest (5.14.2)
80
+ minitest (5.14.3)
80
81
  multi_json (1.15.0)
81
82
  mustermann (1.1.1)
82
83
  ruby2_keywords (~> 0.0.1)
83
- nokogiri (1.10.10)
84
- mini_portile2 (~> 2.4.0)
85
- omniauth (1.9.1)
84
+ nokogiri (1.11.1-x86_64-darwin)
85
+ racc (~> 1.4)
86
+ omniauth (2.0.1)
86
87
  hashie (>= 3.4.6)
87
88
  rack (>= 1.6.2, < 3)
89
+ rack-protection
88
90
  omniauth-multi-provider (0.2.1)
89
91
  omniauth
90
- omniauth-saml (1.10.3)
91
- omniauth (~> 1.3, >= 1.3.2)
92
+ omniauth-saml (2.0.0)
93
+ omniauth (~> 2.0)
92
94
  ruby-saml (~> 1.9)
93
95
  parallel (1.20.1)
94
- parser (2.7.2.0)
96
+ parser (3.0.0.0)
95
97
  ast (~> 2.4.1)
96
98
  pg (1.2.3)
99
+ posthog-ruby (1.1.0)
97
100
  pry (0.13.1)
98
101
  coderay (~> 1.1)
99
102
  method_source (~> 1.0)
100
103
  public_suffix (4.0.6)
104
+ racc (1.5.2)
101
105
  rack (2.2.3)
102
106
  rack-contrib (2.3.0)
103
107
  rack (~> 2.0)
@@ -112,58 +116,59 @@ GEM
112
116
  rack-test (1.1.0)
113
117
  rack (>= 1.0, < 3)
114
118
  rainbow (3.0.0)
115
- rake (13.0.1)
116
- regexp_parser (2.0.0)
119
+ rake (13.0.3)
120
+ regexp_parser (2.0.3)
117
121
  rexml (3.2.4)
118
- roda (3.38.0)
122
+ roda (3.40.0)
119
123
  rack
120
- rodauth (2.6.0)
124
+ rodauth (2.9.0)
121
125
  roda (>= 2.6.0)
122
126
  sequel (>= 4)
123
127
  rspec (3.10.0)
124
128
  rspec-core (~> 3.10.0)
125
129
  rspec-expectations (~> 3.10.0)
126
130
  rspec-mocks (~> 3.10.0)
127
- rspec-core (3.10.0)
131
+ rspec-core (3.10.1)
128
132
  rspec-support (~> 3.10.0)
129
- rspec-expectations (3.10.0)
133
+ rspec-expectations (3.10.1)
130
134
  diff-lcs (>= 1.2.0, < 2.0)
131
135
  rspec-support (~> 3.10.0)
132
- rspec-mocks (3.10.0)
136
+ rspec-mocks (3.10.1)
133
137
  diff-lcs (>= 1.2.0, < 2.0)
134
138
  rspec-support (~> 3.10.0)
135
- rspec-support (3.10.0)
136
- rubocop (1.5.2)
139
+ rspec-support (3.10.1)
140
+ rubocop (1.8.1)
137
141
  parallel (~> 1.10)
138
- parser (>= 2.7.1.5)
142
+ parser (>= 3.0.0.0)
139
143
  rainbow (>= 2.2.2, < 4.0)
140
144
  regexp_parser (>= 1.8, < 3.0)
141
145
  rexml
142
146
  rubocop-ast (>= 1.2.0, < 2.0)
143
147
  ruby-progressbar (~> 1.7)
144
- unicode-display_width (>= 1.4.0, < 2.0)
145
- rubocop-ast (1.3.0)
148
+ unicode-display_width (>= 1.4.0, < 3.0)
149
+ rubocop-ast (1.4.1)
146
150
  parser (>= 2.7.1.5)
147
- ruby-progressbar (1.10.1)
151
+ ruby-progressbar (1.11.0)
148
152
  ruby-saml (1.11.0)
149
153
  nokogiri (>= 1.5.10)
150
- ruby2_keywords (0.0.2)
151
- sequel (5.39.0)
152
- sequel-activerecord_connection (1.2.0)
154
+ ruby2_keywords (0.0.4)
155
+ sequel (5.40.0)
156
+ sequel-activerecord_connection (1.2.2)
153
157
  activerecord (>= 4.2, < 7)
154
158
  after_commit_everywhere (~> 0.1.5)
155
159
  sequel (~> 5.16)
156
- simplecov (0.17.0)
160
+ simplecov (0.21.2)
157
161
  docile (~> 1.1)
158
- json (>= 1.8, < 3)
159
- simplecov-html (~> 0.10.0)
160
- simplecov-html (0.10.2)
162
+ simplecov-html (~> 0.11)
163
+ simplecov_json_formatter (~> 0.1)
164
+ simplecov-html (0.12.3)
165
+ simplecov_json_formatter (0.1.2)
161
166
  sinatra (2.1.0)
162
167
  mustermann (~> 1.0)
163
168
  rack (~> 2.2)
164
169
  rack-protection (= 2.1.0)
165
170
  tilt (~> 2.0)
166
- sinatra-activerecord (2.0.21)
171
+ sinatra-activerecord (2.0.22)
167
172
  activerecord (>= 4.1)
168
173
  sinatra (>= 1.0)
169
174
  sinatra-contrib (2.1.0)
@@ -172,16 +177,15 @@ GEM
172
177
  rack-protection (= 2.1.0)
173
178
  sinatra (= 2.1.0)
174
179
  tilt (~> 2.0)
175
- thread_safe (0.3.6)
176
180
  tilt (2.0.10)
177
- tzinfo (1.2.8)
178
- thread_safe (~> 0.1)
179
- unicode-display_width (1.7.0)
180
- webmock (3.10.0)
181
+ tzinfo (2.0.4)
182
+ concurrent-ruby (~> 1.0)
183
+ unicode-display_width (2.0.0)
184
+ webmock (3.11.1)
181
185
  addressable (>= 2.3.6)
182
186
  crack (>= 0.3.2)
183
187
  hashdiff (>= 0.4.0, < 2.0.0)
184
- zeitwerk (2.4.1)
188
+ zeitwerk (2.4.2)
185
189
 
186
190
  PLATFORMS
187
191
  ruby
@@ -198,8 +202,8 @@ DEPENDENCIES
198
202
  rack-test
199
203
  rspec (~> 3.10)
200
204
  rubocop
201
- simplecov (= 0.17)
202
- webmock (~> 3.10)
205
+ simplecov (= 0.21.2)
206
+ webmock (~> 3.11)
203
207
 
204
208
  BUNDLED WITH
205
209
  2.1.4
data/Rakefile CHANGED
@@ -5,6 +5,7 @@
5
5
  # schema and migrations
6
6
 
7
7
  ENV['SESSION_SECRET'] ||= 'rake-secret'
8
+ ENV['BASE_URL'] ||= 'https://example.com'
8
9
 
9
10
  require 'bundler/gem_tasks'
10
11
  require 'sinatra/activerecord/rake'
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ ENV['SESSION_SECRET'] ||= 'irb-secret'
5
+ ENV['BASE_URL'] ||= 'https://example.com'
6
+
4
7
  require 'bundler/setup'
5
8
  require 'osso'
6
9
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Osso
4
4
  require_relative 'osso/error/error'
5
+ require_relative 'osso/lib/analytics'
5
6
  require_relative 'osso/lib/app_config'
6
7
  require_relative 'osso/lib/oauth2_token'
7
8
  require_relative 'osso/lib/route_map'
@@ -15,7 +15,10 @@ module Osso
15
15
  def resolve(**args)
16
16
  provider = identity_provider(**args)
17
17
 
18
- return response_data(identity_provider: provider) if provider.update(args)
18
+ if provider.update(args)
19
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: args)
20
+ return response_data(identity_provider: provider)
21
+ end
19
22
 
20
23
  response_error(provider.errors)
21
24
  end
@@ -15,7 +15,10 @@ module Osso
15
15
  def resolve(**args)
16
16
  enterprise_account = Osso::Models::EnterpriseAccount.new(args)
17
17
 
18
- return response_data(enterprise_account: enterprise_account) if enterprise_account.save
18
+ if enterprise_account.save
19
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: args)
20
+ return response_data(enterprise_account: enterprise_account)
21
+ end
19
22
 
20
23
  response_error(enterprise_account.errors)
21
24
  end
@@ -13,7 +13,7 @@ module Osso
13
13
  field :identity_provider, Types::IdentityProvider, null: false
14
14
  field :errors, [String], null: false
15
15
 
16
- def resolve(service: nil, enterprise_account_id:, oauth_client_id:)
16
+ def resolve(enterprise_account_id:, oauth_client_id:, service: nil)
17
17
  customer = enterprise_account(enterprise_account_id: enterprise_account_id)
18
18
 
19
19
  identity_provider = customer.identity_providers.build(
@@ -22,12 +22,17 @@ module Osso
22
22
  oauth_client_id: oauth_client_id,
23
23
  )
24
24
 
25
- return response_data(identity_provider: identity_provider) if identity_provider.save
25
+ if identity_provider.save
26
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: {
27
+ service: service, enterprise_account_id: enterprise_account_id, oauth_client_id: oauth_client_id
28
+ })
29
+ return response_data(identity_provider: identity_provider)
30
+ end
26
31
 
27
32
  response_error(identity_provider.errors)
28
33
  end
29
34
 
30
- def domain(enterprise_account_id:, **args)
35
+ def domain(enterprise_account_id:, **_args)
31
36
  enterprise_account(enterprise_account_id: enterprise_account_id)&.domain
32
37
  end
33
38
 
@@ -14,7 +14,10 @@ module Osso
14
14
  def resolve(**args)
15
15
  oauth_client = Osso::Models::OauthClient.new(args)
16
16
 
17
- return response_data(oauth_client: oauth_client) if oauth_client.save
17
+ if oauth_client.save
18
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: args)
19
+ return response_data(oauth_client: oauth_client)
20
+ end
18
21
 
19
22
  response_error(oauth_client.errors)
20
23
  end
@@ -18,7 +18,10 @@ module Osso
18
18
  def resolve(**args)
19
19
  customer = enterprise_account(**args)
20
20
 
21
- return response_data(enterprise_account: nil) if customer.destroy
21
+ if customer.destroy
22
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: args)
23
+ return response_data(enterprise_account: nil)
24
+ end
22
25
 
23
26
  response_error(customer.errors)
24
27
  end
@@ -14,7 +14,10 @@ module Osso
14
14
  def resolve(id:)
15
15
  identity_provider = Osso::Models::IdentityProvider.find(id)
16
16
 
17
- return response_data(identity_provider: nil) if identity_provider.destroy
17
+ if identity_provider.destroy
18
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: { id: id })
19
+ return response_data(identity_provider: nil)
20
+ end
18
21
 
19
22
  response_error(identity_provider.errors)
20
23
  end
@@ -14,7 +14,10 @@ module Osso
14
14
  def resolve(id:)
15
15
  oauth_client = Osso::Models::OauthClient.find(id)
16
16
 
17
- return response_data(oauth_client: nil) if oauth_client.destroy
17
+ if oauth_client.destroy
18
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: { id: id })
19
+ return response_data(oauth_client: nil)
20
+ end
18
21
 
19
22
  response_error(oauth_client.errors)
20
23
  end
@@ -23,6 +23,12 @@ module Osso
23
23
  if admin_user.save
24
24
  verify_user(email)
25
25
 
26
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: {
27
+ invited_email: email,
28
+ invited_role: role,
29
+ invited_oauth_client_id: oauth_client_id,
30
+ })
31
+
26
32
  return response_data(admin_user: admin_user)
27
33
  end
28
34
 
@@ -15,7 +15,16 @@ module Osso
15
15
  oauth_client = Osso::Models::OauthClient.find(id)
16
16
  oauth_client.regenerate_secrets!
17
17
 
18
- return response_data(oauth_client: oauth_client) if oauth_client.save
18
+ if oauth_client.save
19
+ Osso::Analytics.capture(
20
+ email: context[:email],
21
+ event: self.class.name.demodulize,
22
+ properties: {
23
+ oauth_client_id: id
24
+ }
25
+ )
26
+ return response_data(oauth_client: oauth_client)
27
+ end
19
28
 
20
29
  response_error(oauth_client.errors)
21
30
  end
@@ -18,6 +18,8 @@ module Osso
18
18
  update_existing(oauth_client, redirect_uris)
19
19
  create_new(oauth_client, redirect_uris)
20
20
 
21
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: redirect_uris)
22
+
21
23
  response_data(oauth_client: oauth_client.reload)
22
24
  rescue StandardError => e
23
25
  response_error(e)
@@ -15,7 +15,10 @@ module Osso
15
15
 
16
16
  def resolve(**args)
17
17
  app_config = Osso::Models::AppConfig.find
18
- return response_data(app_config: app_config) if app_config.update(**args)
18
+ if app_config.update(**args)
19
+ Osso::Analytics.capture(email: context[:email], event: self.class.name.demodulize, properties: args)
20
+ return response_data(app_config: app_config)
21
+ end
19
22
 
20
23
  response_error(app_config.errors)
21
24
  end
@@ -16,44 +16,39 @@ module Osso
16
16
 
17
17
  field :oauth_clients, null: true, resolver: Resolvers::OAuthClients
18
18
 
19
- field(
20
- :identity_provider,
21
- Types::IdentityProvider,
22
- null: true,
23
- resolve: ->(_obj, args, _context) { Osso::Models::IdentityProvider.find(args[:id]) },
24
- ) do
19
+ field :admin_users, [Types::AdminUser], null: false
20
+
21
+ field :app_config, Types::AppConfig, null: false
22
+
23
+ field :current_user, Types::AdminUser, null: false
24
+
25
+ field :identity_provider, Types::IdentityProvider, null: true do
25
26
  argument :id, ID, required: true
26
27
  end
27
28
 
28
- field(
29
- :app_config,
30
- Types::AppConfig,
31
- null: false,
32
- resolve: ->(_obj, _args, _context) { Osso::Models::AppConfig.find },
33
- )
34
-
35
- field(
36
- :oauth_client,
37
- Types::OauthClient,
38
- null: true,
39
- resolve: ->(_obj, args, _context) { Osso::Models::OauthClient.find(args[:id]) },
40
- ) do
29
+ field :oauth_client, Types::OauthClient, null: true do
41
30
  argument :id, ID, required: true
42
31
  end
43
32
 
44
- field(
45
- :admin_users,
46
- [Types::AdminUser],
47
- null: false,
48
- resolve: ->(_obj, _args, _context) { Osso::Models::Account.all },
49
- )
33
+ def admin_users
34
+ Osso::Models::Account.all
35
+ end
36
+
37
+ def app_config
38
+ Osso::Models::AppConfig.find
39
+ end
40
+
41
+ def current_user
42
+ context.to_h
43
+ end
50
44
 
51
- field(
52
- :current_user,
53
- Types::AdminUser,
54
- null: false,
55
- resolve: ->(_obj, _args, context) { context.to_h },
56
- )
45
+ def identity_provider(id:)
46
+ Osso::Models::IdentityProvider.find(id)
47
+ end
48
+
49
+ def oauth_client(id:)
50
+ Osso::Models::OauthClient.find(id)
51
+ end
57
52
  end
58
53
  end
59
54
  end
@@ -14,7 +14,6 @@ GraphQL::Relay::BaseConnection.register_connection_implementation(
14
14
  module Osso
15
15
  module GraphQL
16
16
  class Schema < ::GraphQL::Schema
17
- use ::GraphQL::Pagination::Connections
18
17
  query Types::QueryType
19
18
  mutation Types::MutationType
20
19
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'posthog-ruby'
4
+
5
+ module Osso
6
+ # Osso::Analytics provides an interface to track product analytics for any provider.
7
+ # Osso recommends PostHog as an open source solution for your product analytics needs.
8
+ # If you want to use another product analytics provider, you can patch the Osso::Analytics
9
+ # class yourself in your parent application. Be sure to implement the public
10
+ # .identify and .capture class methods with the required method signatures and require
11
+ # your class after requiring Osso.
12
+ class Analytics
13
+ class << self
14
+ def identify(email:, properties: {})
15
+ return unless configured?
16
+
17
+ client.identify({
18
+ distinct_id: email,
19
+ properties: properties.merge(instance_properties),
20
+ })
21
+ end
22
+
23
+ def capture(email:, event:, properties: {})
24
+ return unless configured?
25
+
26
+ client.capture(
27
+ distinct_id: email,
28
+ event: event,
29
+ properties: properties.merge(instance_properties),
30
+ )
31
+ end
32
+
33
+ private
34
+
35
+ def configured?
36
+ ENV['POSTHOG_API_KEY'].present?
37
+ end
38
+
39
+ def client
40
+ @client ||= PostHog::Client.new({
41
+ api_key: ENV['POSTHOG_API_KEY'],
42
+ api_host: ENV['POSTHOG_HOST'],
43
+ on_error: proc { |_status, msg| print msg },
44
+ })
45
+ end
46
+
47
+ def instance_properties
48
+ {
49
+ instance_url: ENV['BASE_URL'],
50
+ osso_plan: ENV['OSSO_PLAN'],
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rack/protection'
4
+
3
5
  module Osso
4
6
  module RouteMap
5
7
  def self.included(klass)
@@ -3,7 +3,7 @@
3
3
  module Osso
4
4
  module Models
5
5
  class Account < ::ActiveRecord::Base
6
- enum status_id: { 1 => :Unverified, 2 => :Verified, 3 => :Closed }
6
+ enum status_id: { Unverified: 1, Verified: 2, Closed: 3 }
7
7
 
8
8
  def context
9
9
  {
@@ -18,7 +18,7 @@ module Osso
18
18
 
19
19
  ENTITY_ID_URI_REQUIRED = [
20
20
  'PING',
21
- ]
21
+ ].freeze
22
22
 
23
23
  def name
24
24
  service.titlecase
@@ -30,6 +30,7 @@ module Osso
30
30
  idp_sso_target_url: sso_url,
31
31
  idp_cert: sso_cert,
32
32
  issuer: sso_issuer,
33
+ name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
33
34
  }
34
35
  end
35
36
 
@@ -55,7 +56,7 @@ module Osso
55
56
 
56
57
  def set_sso_issuer
57
58
  parts = [domain, oauth_client_id]
58
-
59
+
59
60
  parts.unshift('https:/') if ENTITY_ID_URI_REQUIRED.any?(service)
60
61
 
61
62
  self.sso_issuer = parts.join('/')
@@ -10,16 +10,46 @@ module Osso
10
10
  DB = Sequel.postgres(extensions: :activerecord_connection)
11
11
  use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
12
12
 
13
+ plugin :json
14
+ plugin :json_parser
13
15
  plugin :middleware
14
16
  plugin :render, engine: 'erb', views: ENV['RODAUTH_VIEWS'] || DEFAULT_VIEWS_DIR
15
17
  plugin :route_csrf
16
18
 
17
19
  plugin :rodauth do
18
- enable :login, :verify_account
20
+ enable :login, :verify_account, :jwt
21
+
22
+ base_uri = URI.parse(ENV.fetch('BASE_URL'))
23
+ base_url base_uri
24
+ domain base_uri.host
25
+
26
+ jwt_secret ENV.fetch('SESSION_SECRET')
27
+ only_json? false
28
+
29
+ email_from { "Osso <no-reply@#{domain}>" }
19
30
  verify_account_set_password? true
20
- already_logged_in { redirect login_redirect }
21
31
  use_database_authentication_functions? false
22
32
 
33
+ after_login do
34
+ Osso::Analytics.identify(email: account[:email], properties: account)
35
+ end
36
+
37
+ verify_account_view do
38
+ render :admin
39
+ end
40
+
41
+ login_view do
42
+ render :admin
43
+ end
44
+
45
+ verify_account_email_subject do
46
+ DB[:accounts].one? ? 'Your Osso instance is ready' : 'You\'ve been invited to start using Osso'
47
+ end
48
+
49
+ verify_account_email_body do
50
+ DB[:accounts].one? ? render('verify-first-account-email') : render('verify-account-email')
51
+ end
52
+
23
53
  before_create_account_route do
24
54
  request.halt unless DB[:accounts].empty?
25
55
  end
@@ -31,16 +61,28 @@ module Osso
31
61
  r.rodauth
32
62
 
33
63
  def current_account
34
- Osso::Models::Account.find(rodauth.session['account_id']).
35
- context.
64
+ Osso::Models::Account.find(
65
+ rodauth.
66
+ session.
67
+ to_hash.
68
+ stringify_keys['account_id'],
69
+ ).context.
36
70
  merge({ rodauth: rodauth })
37
71
  end
38
72
 
39
73
  r.on 'admin' do
40
- rodauth.require_authentication
41
74
  erb :admin, layout: false
42
75
  end
43
76
 
77
+ r.post 'idp' do
78
+ onboarded = Osso::Models::IdentityProvider.
79
+ not_pending.
80
+ where(domain: r.params['domain']).
81
+ exists?
82
+
83
+ { onboarded: onboarded }.to_json
84
+ end
85
+
44
86
  r.post 'graphql' do
45
87
  rodauth.require_authentication
46
88
 
@@ -14,6 +14,8 @@ module Osso
14
14
  /[0-9a-f]{8}-[0-9a-f]{3,4}-[0-9a-f]{4}-[0-9a-f]{3,4}-[0-9a-f]{12}/.
15
15
  freeze
16
16
 
17
+ use Rack::Protection, allow_if: ->(env) { Rack::Request.new(env)&.path&.end_with?('callback') }
18
+
17
19
  use OmniAuth::Builder do
18
20
  OmniAuth::MultiProvider.register(
19
21
  self,
@@ -16,13 +16,14 @@ module Osso
16
16
  # Once they complete IdP login, they will be returned to the
17
17
  # redirect_uri with an authorization code parameter.
18
18
  get '/authorize' do
19
- identity_providers = find_providers
20
-
21
19
  validate_oauth_request(env)
22
20
 
23
- redirect "/auth/saml/#{identity_providers.first.id}" if identity_providers.one?
21
+ return erb :hosted_login if render_hosted_login?
22
+
23
+ @providers = find_providers
24
+
25
+ return erb :saml_login_form if @providers.one?
24
26
 
25
- @providers = identity_providers.not_pending
26
27
  return erb :multiple_providers if @providers.count > 1
27
28
 
28
29
  raise Osso::Error::MissingConfiguredIdentityProvider.new(domain: params[:domain])
@@ -61,6 +62,10 @@ module Osso
61
62
 
62
63
  private
63
64
 
65
+ def render_hosted_login?
66
+ [params[:email], params[:domain]].all?(&:nil?)
67
+ end
68
+
64
69
  def find_providers
65
70
  if params[:email]
66
71
  user = Osso::Models::User.
@@ -71,6 +76,7 @@ module Osso
71
76
 
72
77
  Osso::Models::IdentityProvider.
73
78
  joins(:oauth_client).
79
+ not_pending.
74
80
  where(
75
81
  domain: domain_from_params,
76
82
  oauth_clients: { identifier: params[:client_id] },
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.7'
4
+ VERSION = '0.1.1'
5
5
  end
@@ -8,9 +8,11 @@ namespace :osso do
8
8
  desc 'Bootstrap Osso data for a deployment'
9
9
  task :bootstrap do
10
10
  %w[Production Staging Development].each do |environment|
11
+ next if Osso::Models::OauthClient.find_by_name(environment)
12
+
11
13
  Osso::Models::OauthClient.create!(
12
14
  name: environment,
13
- ) unless Osso::Models::OauthClient.find_by_name(environment)
15
+ )
14
16
  end
15
17
 
16
18
  Osso::Models::AppConfig.create
@@ -18,7 +20,7 @@ namespace :osso do
18
20
  admin_email = ENV['ADMIN_EMAIL']
19
21
 
20
22
  if admin_email
21
- admin = Osso::Models::Account.create(
23
+ Osso::Models::Account.create(
22
24
  email: admin_email,
23
25
  status_id: 1,
24
26
  role: 'admin',
@@ -29,10 +31,10 @@ namespace :osso do
29
31
  rodauth = Osso::Admin.rodauth.new(Osso::Admin.new({
30
32
  'HTTP_HOST' => base_uri.host,
31
33
  'SERVER_NAME' => base_uri.to_s,
32
- 'rack.url_scheme' => base_uri.scheme
34
+ 'rack.url_scheme' => base_uri.scheme,
33
35
  }))
34
36
 
35
- account = rodauth.account_from_login(admin_email)
37
+ rodauth.account_from_login(admin_email)
36
38
  rodauth.setup_account_verification
37
39
  end
38
40
  end
@@ -22,15 +22,17 @@ Gem::Specification.new do |spec|
22
22
  spec.add_runtime_dependency 'mail', '~> 2.7.1'
23
23
  spec.add_runtime_dependency 'omniauth-multi-provider'
24
24
  spec.add_runtime_dependency 'omniauth-saml'
25
+ spec.add_runtime_dependency 'posthog-ruby'
25
26
  spec.add_runtime_dependency 'rack', '>= 2.1.4'
26
27
  spec.add_runtime_dependency 'rack-contrib'
27
28
  spec.add_runtime_dependency 'rack-oauth2'
29
+ spec.add_runtime_dependency 'rack-protection', '~> 2.1.0'
28
30
  spec.add_runtime_dependency 'rake'
29
- spec.add_runtime_dependency 'rodauth', '~> 2.6.0'
30
- spec.add_runtime_dependency 'sequel', '>= 5.37', '< 5.40'
31
+ spec.add_runtime_dependency 'rodauth', '~> 2.9'
32
+ spec.add_runtime_dependency 'sequel', '~> 5.40'
31
33
  spec.add_runtime_dependency 'sequel-activerecord_connection', '>= 0.3', '< 2.0'
32
34
  spec.add_runtime_dependency 'sinatra'
33
- spec.add_runtime_dependency 'sinatra-activerecord'
35
+ spec.add_runtime_dependency 'sinatra-activerecord', '>= 2.0.22'
34
36
  spec.add_runtime_dependency 'sinatra-contrib'
35
37
 
36
38
  spec.add_development_dependency 'annotate', '~> 3.1'
@@ -91,7 +91,7 @@ describe Osso::GraphQL::Schema do
91
91
  },
92
92
  }
93
93
  end
94
-
94
+
95
95
  it 'creates an identity provider' do
96
96
  expect { subject }.to change { enterprise_account.identity_providers.count }.by(1)
97
97
  expect(subject.dig('data', 'createIdentityProvider', 'identityProvider', 'domain')).
@@ -66,6 +66,7 @@ describe Osso::Models::IdentityProvider do
66
66
  idp_cert: subject.sso_cert,
67
67
  idp_sso_target_url: subject.sso_url,
68
68
  issuer: subject.sso_issuer,
69
+ name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
69
70
  )
70
71
  end
71
72
  end
@@ -4,23 +4,68 @@ require 'spec_helper'
4
4
 
5
5
  describe Osso::Admin do
6
6
  describe 'get /admin' do
7
- it 'redirects to /login without a session' do
7
+ it 'renders the admin layout' do
8
8
  get('/admin')
9
9
 
10
- expect(last_response).to be_redirect
11
- follow_redirect!
12
- expect(last_request.url).to match('/login')
10
+ expect(last_response).to be_ok
13
11
  end
12
+ end
14
13
 
15
- xit 'renders the admin page for a valid session token' do
16
- password = SecureRandom.urlsafe_base64(16)
17
- account = create(:verified_account, password: password)
14
+ describe 'post /graphql' do
15
+ let(:account) { create(:account) }
18
16
 
19
- post('/login', { email: account.email, password: password })
17
+ it 'runs a GraphQL query with a valid jwt' do
18
+ allow_any_instance_of(described_class.rodauth).to receive(:logged_in?).and_return(true)
19
+ allow(Osso::Models::Account).to receive(:find).and_return(account)
20
+ allow(Osso::GraphQL::Schema).to receive(:execute).and_return({ graphql: true })
20
21
 
21
- get('/admin')
22
+ header 'Content-Type', 'application/json'
23
+ post('/graphql')
24
+
25
+ expect(last_response).to be_ok
26
+ expect(last_json_response).to eq({ graphql: true })
27
+ end
28
+
29
+ it 'returns a 400 for an invalid jwt' do
30
+ header 'Content-Type', 'application/json'
31
+ header 'Authorization', 'Bearer bad-token'
32
+ post('/graphql')
33
+
34
+ expect(last_response.status).to eq 400
35
+ end
36
+
37
+ it 'returns a 401 without a jwt' do
38
+ header 'Content-Type', 'application/json'
39
+ post('/graphql')
40
+
41
+ expect(last_response.status).to eq 401
42
+ end
43
+ end
44
+
45
+ describe 'post /idp' do
46
+ let(:domain) { Faker::Internet.domain_name }
47
+
48
+ before do
49
+ create(:configured_identity_provider, domain: domain)
50
+ end
51
+
52
+ it 'returns true when an available IDP is found' do
53
+ header 'Content-Type', 'application/json'
54
+ header 'Accept', 'application/json'
55
+ post('/idp', { domain: domain }.to_json)
56
+
57
+ expect(last_response).to be_ok
58
+ expect(last_json_response).to eq({ onboarded: true })
59
+ end
60
+
61
+ it 'returns false when an available IDP is not found' do
62
+ header 'Content-Type', 'application/json'
63
+ header 'Accept', 'application/json'
64
+
65
+ post('/idp', { domain: domain.reverse}.to_json)
22
66
 
23
67
  expect(last_response).to be_ok
68
+ expect(last_json_response).to eq({ onboarded: false })
24
69
  end
25
70
  end
26
71
  end
@@ -6,12 +6,13 @@ describe Osso::Auth do
6
6
  before do
7
7
  described_class.set(:views, spec_views)
8
8
  end
9
- describe 'get /auth/saml/:uuid' do
9
+
10
+ describe 'post /auth/saml/:uuid' do
10
11
  describe 'for an Okta SAML provider' do
11
12
  let(:enterprise) { create(:enterprise_with_okta) }
12
13
  let(:okta_provider) { enterprise.identity_providers.first }
13
14
  it 'uses omniauth saml' do
14
- get("/auth/saml/#{okta_provider.id}")
15
+ post("/auth/saml/#{okta_provider.id}")
15
16
 
16
17
  expect(last_response).to be_redirect
17
18
  follow_redirect!
@@ -23,7 +24,7 @@ describe Osso::Auth do
23
24
  let(:enterprise) { create(:enterprise_with_okta) }
24
25
  let(:azure_provider) { enterprise.identity_providers.first }
25
26
  it 'uses omniauth saml' do
26
- get("/auth/saml/#{azure_provider.id}")
27
+ post("/auth/saml/#{azure_provider.id}")
27
28
 
28
29
  expect(last_response).to be_redirect
29
30
  follow_redirect!
@@ -31,6 +32,7 @@ describe Osso::Auth do
31
32
  end
32
33
  end
33
34
  end
35
+
34
36
  describe 'post /auth/saml/:uuid/callback' do
35
37
  describe 'for an Okta SAML provider' do
36
38
  let(:enterprise) { create(:enterprise_with_okta) }
@@ -27,8 +27,22 @@ describe Osso::Oauth do
27
27
  end
28
28
  end
29
29
 
30
+ describe 'for a request without email or domain' do
31
+ it 'renders the hosted login page' do
32
+ get(
33
+ '/oauth/authorize',
34
+ client_id: client.identifier,
35
+ response_type: 'code',
36
+ redirect_uri: client.redirect_uri_values.sample,
37
+ )
38
+
39
+ expect(last_response).to be_ok
40
+ expect(last_response.body).to eq('HOSTED LOGIN')
41
+ end
42
+ end
43
+
30
44
  describe 'for an enterprise domain with one SAML provider' do
31
- it 'redirects to /auth/saml/:provider_id' do
45
+ it 'renders the saml login form' do
32
46
  enterprise = create(:enterprise_with_okta, oauth_client: client)
33
47
 
34
48
  get(
@@ -41,9 +55,7 @@ describe Osso::Oauth do
41
55
 
42
56
  provider_id = enterprise.identity_providers.first.id
43
57
 
44
- expect(last_response).to be_redirect
45
- follow_redirect!
46
- expect(last_request.url).to match("auth/saml/#{provider_id}")
58
+ expect(last_response.body).to match(provider_id)
47
59
  end
48
60
  end
49
61
 
@@ -65,7 +77,7 @@ describe Osso::Oauth do
65
77
  end
66
78
 
67
79
  describe "for an existing user's email address" do
68
- it 'redirects to /auth/saml/:provider_id' do
80
+ it 'renders the saml login form' do
69
81
  enterprise = create(:enterprise_with_okta, oauth_client: client)
70
82
  provider_id = enterprise.identity_providers.first.id
71
83
  user = create(:user, email: "user@#{enterprise.domain}", identity_provider_id: provider_id)
@@ -78,14 +90,12 @@ describe Osso::Oauth do
78
90
  redirect_uri: client.redirect_uri_values.sample,
79
91
  )
80
92
 
81
- expect(last_response).to be_redirect
82
- follow_redirect!
83
- expect(last_request.url).to match("auth/saml/#{provider_id}")
93
+ expect(last_response.body).to match(provider_id)
84
94
  end
85
95
  end
86
96
 
87
97
  describe "for a new user's email address belonging to an enterprise with one SAML provider" do
88
- it 'redirects to /auth/saml/:provider_id' do
98
+ it 'renders the saml login form' do
89
99
  enterprise = create(:enterprise_with_okta, oauth_client: client)
90
100
 
91
101
  get(
@@ -98,9 +108,7 @@ describe Osso::Oauth do
98
108
 
99
109
  provider_id = enterprise.identity_providers.first.id
100
110
 
101
- expect(last_response).to be_redirect
102
- follow_redirect!
103
- expect(last_request.url).to match("auth/saml/#{provider_id}")
111
+ expect(last_response.body).to match(provider_id)
104
112
  end
105
113
  end
106
114
 
@@ -80,5 +80,7 @@ RSpec.configure do |config|
80
80
 
81
81
  OmniAuth.config.test_mode = true
82
82
  OmniAuth.config.logger = Logger.new('/dev/null')
83
+ OmniAuth.config.request_validation_phase = proc {}
84
+
83
85
  WebMock.disable_net_connect!(allow_localhost: true)
84
86
  end
@@ -0,0 +1 @@
1
+ HOSTED LOGIN
@@ -0,0 +1 @@
1
+ <%= @providers.first.id %>
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.7
4
+ version: 0.1.1
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-12-08 00:00:00.000000000 Z
11
+ date: 2021-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: posthog-ruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rack
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,20 @@ dependencies:
150
164
  - - ">="
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rack-protection
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 2.1.0
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 2.1.0
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: rake
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -170,32 +198,26 @@ dependencies:
170
198
  requirements:
171
199
  - - "~>"
172
200
  - !ruby/object:Gem::Version
173
- version: 2.6.0
201
+ version: '2.9'
174
202
  type: :runtime
175
203
  prerelease: false
176
204
  version_requirements: !ruby/object:Gem::Requirement
177
205
  requirements:
178
206
  - - "~>"
179
207
  - !ruby/object:Gem::Version
180
- version: 2.6.0
208
+ version: '2.9'
181
209
  - !ruby/object:Gem::Dependency
182
210
  name: sequel
183
211
  requirement: !ruby/object:Gem::Requirement
184
212
  requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '5.37'
188
- - - "<"
213
+ - - "~>"
189
214
  - !ruby/object:Gem::Version
190
215
  version: '5.40'
191
216
  type: :runtime
192
217
  prerelease: false
193
218
  version_requirements: !ruby/object:Gem::Requirement
194
219
  requirements:
195
- - - ">="
196
- - !ruby/object:Gem::Version
197
- version: '5.37'
198
- - - "<"
220
+ - - "~>"
199
221
  - !ruby/object:Gem::Version
200
222
  version: '5.40'
201
223
  - !ruby/object:Gem::Dependency
@@ -238,14 +260,14 @@ dependencies:
238
260
  requirements:
239
261
  - - ">="
240
262
  - !ruby/object:Gem::Version
241
- version: '0'
263
+ version: 2.0.22
242
264
  type: :runtime
243
265
  prerelease: false
244
266
  version_requirements: !ruby/object:Gem::Requirement
245
267
  requirements:
246
268
  - - ">="
247
269
  - !ruby/object:Gem::Version
248
- version: '0'
270
+ version: 2.0.22
249
271
  - !ruby/object:Gem::Dependency
250
272
  name: sinatra-contrib
251
273
  requirement: !ruby/object:Gem::Requirement
@@ -407,6 +429,7 @@ files:
407
429
  - lib/osso/graphql/types/oauth_client.rb
408
430
  - lib/osso/graphql/types/redirect_uri.rb
409
431
  - lib/osso/graphql/types/redirect_uri_input.rb
432
+ - lib/osso/lib/analytics.rb
410
433
  - lib/osso/lib/app_config.rb
411
434
  - lib/osso/lib/oauth2_token.rb
412
435
  - lib/osso/lib/route_map.rb
@@ -455,7 +478,6 @@ files:
455
478
  - spec/models/enterprise_account_spec.rb
456
479
  - spec/models/identity_provider_spec.rb
457
480
  - spec/routes/admin_spec.rb
458
- - spec/routes/app_spec.rb
459
481
  - spec/routes/auth_spec.rb
460
482
  - spec/routes/oauth_spec.rb
461
483
  - spec/spec_helper.rb
@@ -463,8 +485,10 @@ files:
463
485
  - spec/support/spec_app.rb
464
486
  - spec/support/views/admin.erb
465
487
  - spec/support/views/error.erb
488
+ - spec/support/views/hosted_login.erb
466
489
  - spec/support/views/layout.erb
467
490
  - spec/support/views/multiple_providers.erb
491
+ - spec/support/views/saml_login_form.erb
468
492
  homepage: https://github.com/enterprise-oss/osso-rb
469
493
  licenses:
470
494
  - MIT
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe 'App' do
6
- end