osso 0.0.7 → 0.1.1

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