authify-api 0.3.1 → 0.3.2

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
  SHA1:
3
- metadata.gz: 7722ad1f79781ba027cff0bfc6f174d194fb24de
4
- data.tar.gz: bf8817c6c7b784ee76cfe3e4665540fc3e3b59eb
3
+ metadata.gz: 034407bd9058f89a81db15e6d658f16f5d5a5365
4
+ data.tar.gz: af8a965cc5f481ba754ccd2c5fe79168e35daf68
5
5
  SHA512:
6
- metadata.gz: 7aec0faa2c66766a5f3b2570a52198598ee9ab42605581f964841531637954ab69ee255e2fe85747227b7a9c8fc9fbe15bc6c12b8ad91579670098089142ea83
7
- data.tar.gz: faddeefb5815e21c5c7d991f123ab1f71cb802792183fdf2af43f135d82b1e7b1f25e0143703d000fbe5fdc21d7e898eb3bd36279fcfb4adc4c2e56e8c4fd248
6
+ metadata.gz: 3fb4dd7817c46abf6dc0a2342b48281a9f1862123e990f7c9f4af11baa6d408533fad7376eca7740f3fff865c6052ef63efc88f5b4059abdeb0b8c04f25a8375
7
+ data.tar.gz: ffafbf61deae31c0ae88c4d8d1333fca27464fd557b5876ddab461304f5fe50a84b31a645da7b948ba55925f9e43a0ce213a0957c77e08542b7e785455f81eb1
data/README.md CHANGED
@@ -83,7 +83,7 @@ File.write(File.expand_path('/path/to/keys/private.pem'), secret_key.to_pem)
83
83
  public_key = secret_key
84
84
  public_key.private_key = nil
85
85
  # write out the public key to a file...
86
- File.write(File.expand_path('/path/to/keys/public.pem'), private_key.to_pem)
86
+ File.write(File.expand_path('/path/to/keys/public.pem'), public_key.to_pem)
87
87
  ```
88
88
 
89
89
  Using the OpenSSL CLI tool:
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  # spec.add_runtime_dependency 'sinja', '~> 1.2', '>= 1.2.4'
38
38
  spec.add_runtime_dependency 'puma', '~> 3.7'
39
39
  spec.add_runtime_dependency 'resque', '~> 1.26'
40
+ spec.add_runtime_dependency 'hitimes', '~> 1.2'
40
41
 
41
42
  spec.add_development_dependency 'bundler', '~> 1.12'
42
43
  spec.add_development_dependency 'rake', '~> 10.0'
data/config.ru CHANGED
@@ -7,4 +7,5 @@ use Rack::ShowExceptions
7
7
  run Rack::URLMap.new \
8
8
  '/' => Authify::API::Services::API.new,
9
9
  '/jwt' => Authify::API::Services::JWTProvider.new,
10
- '/registration' => Authify::API::Services::Registration.new
10
+ '/registration' => Authify::API::Services::Registration.new,
11
+ '/monitoring' => Authify::API::Services::Monitoring.new
@@ -12,6 +12,7 @@ require 'tilt/erb'
12
12
  require 'connection_pool'
13
13
  require 'moneta'
14
14
  require 'resque'
15
+ require 'hitimes'
15
16
 
16
17
  # Internal Requirements
17
18
  module Authify
@@ -53,6 +54,9 @@ require 'authify/api/models/user'
53
54
  require 'authify/api/helpers/jwt_encryption'
54
55
  require 'authify/api/helpers/api_user'
55
56
  require 'authify/api/service'
57
+ require 'authify/api/metrics'
58
+ require 'authify/api/middleware/metrics'
56
59
  require 'authify/api/services/api'
57
60
  require 'authify/api/services/jwt_provider'
58
61
  require 'authify/api/services/registration'
62
+ require 'authify/api/services/monitoring'
@@ -0,0 +1,55 @@
1
+ module Authify
2
+ module API
3
+ # A place to store metrics data
4
+ class Metrics
5
+ include Singleton
6
+
7
+ def update(key, value)
8
+ write_lock do
9
+ storage[key] = value
10
+ end
11
+ end
12
+
13
+ def increment(key, change = 1)
14
+ write_lock do
15
+ storage.key?(key) ? storage[key] += change : storage[key] = change
16
+ end
17
+ end
18
+
19
+ def decrement(key, change = 1)
20
+ increment(key, -1 * change)
21
+ end
22
+
23
+ def [](key)
24
+ storage[key]
25
+ end
26
+
27
+ def time(key)
28
+ timer = storage.key?(key) ? storage[key] : Hitimes::TimedMetric.new(key)
29
+ result = timer.measure do
30
+ yield
31
+ end
32
+ update(key, timer)
33
+ result
34
+ end
35
+
36
+ def each(&block)
37
+ storage.each(&block)
38
+ end
39
+
40
+ private
41
+
42
+ def write_lock
43
+ @wlock ||= Mutex.new
44
+ @wlock.synchronize do
45
+ yield
46
+ end
47
+ end
48
+
49
+ def storage
50
+ # While not perfectly thread-safe, this works well enough for Metrics
51
+ @storage ||= Concurrent::Map.new
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Authify
2
+ module API
3
+ module Middleware
4
+ # A middleware for analytics of rack requests
5
+ class Metrics
6
+ def initialize(app)
7
+ @app = app
8
+ @metrics = Authify::API::Metrics.instance
9
+ @key = 'rack.action.response'
10
+ end
11
+
12
+ def call(env)
13
+ status, header, body = @metrics.time(construct_metric_key('time', env)) do
14
+ @app.call env
15
+ end
16
+
17
+ @metrics.increment construct_metric_key('count', env)
18
+
19
+ [status, header, body]
20
+ end
21
+
22
+ private
23
+
24
+ def construct_metric_key(type, env)
25
+ path = Rack::Request.new(env)
26
+ .path.gsub(%r{/([0-9]+)(/?)}, '/:id\2')
27
+ .gsub(%r{/}, '.')
28
+ .chomp('.')
29
+ "#{@key}.#{type}.#{env['REQUEST_METHOD'].downcase}#{path}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -3,7 +3,9 @@ module Authify
3
3
  module Services
4
4
  # The main API Sinatra App
5
5
  class API < Service
6
- use Middleware::JWTAuth
6
+ use Authify::API::Middleware::Metrics
7
+ use Authify::Middleware::JWTAuth
8
+
7
9
  register Sinatra::JSONAPI
8
10
 
9
11
  helpers Helpers::APIUser
@@ -3,6 +3,8 @@ module Authify
3
3
  module Services
4
4
  # A Sinatra App specifically for managing JWT tokens
5
5
  class JWTProvider < Service
6
+ use Authify::API::Middleware::Metrics
7
+
6
8
  helpers Helpers::APIUser
7
9
 
8
10
  configure do
@@ -16,6 +18,21 @@ module Authify
16
18
  OPTIONS
17
19
  GET
18
20
  POST
21
+ ],
22
+ 'Access-Control-Allow-Headers' => %w[
23
+ Origin
24
+ Accept
25
+ Accept-Encoding
26
+ Accept-Language
27
+ Access-Control-Request-Headers
28
+ Access-Control-Request-Method
29
+ Connection
30
+ Content-Type
31
+ Host
32
+ Referer
33
+ User-Agent
34
+ X-Requested-With
35
+ X-Forwarded-For
19
36
  ]
20
37
 
21
38
  begin
@@ -51,12 +68,17 @@ module Authify
51
68
 
52
69
  if found_user
53
70
  update_current_user found_user
71
+ Metrics.instance.increment('jwt.tokens.provided')
54
72
  { jwt: jwt_token(custom_data: custom_data) }.to_json
55
73
  else
56
74
  halt 401
57
75
  end
58
76
  end
59
77
 
78
+ options '/token' do
79
+ halt 200
80
+ end
81
+
60
82
  # Provide information about the JWTs generated by the server
61
83
  get '/meta' do
62
84
  {
@@ -66,12 +88,20 @@ module Authify
66
88
  }.to_json
67
89
  end
68
90
 
91
+ options '/meta' do
92
+ halt 200
93
+ end
94
+
69
95
  # Provide access to the public ECDSA key
70
96
  get '/key' do
71
97
  {
72
98
  data: public_key.export
73
99
  }.to_json
74
100
  end
101
+
102
+ options '/key' do
103
+ halt 200
104
+ end
75
105
  end
76
106
  end
77
107
  end
@@ -0,0 +1,60 @@
1
+ module Authify
2
+ module API
3
+ module Services
4
+ # The monitoring application
5
+ class Monitoring < Service
6
+ configure do
7
+ set :protection, except: :http_origin
8
+ end
9
+
10
+ before '*' do
11
+ content_type 'application/json'
12
+ headers 'Access-Control-Allow-Origin' => '*',
13
+ 'Access-Control-Allow-Methods' => %w[
14
+ OPTIONS
15
+ GET
16
+ POST
17
+ ],
18
+ 'Access-Control-Allow-Headers' => %w[
19
+ Origin
20
+ Accept
21
+ Accept-Encoding
22
+ Accept-Language
23
+ Access-Control-Request-Headers
24
+ Access-Control-Request-Method
25
+ Connection
26
+ Content-Type
27
+ Host
28
+ Referer
29
+ User-Agent
30
+ X-Requested-With
31
+ X-Forwarded-For
32
+ ]
33
+
34
+ begin
35
+ unless request.get? || request.options?
36
+ request.body.rewind
37
+ @parsed_body = JSON.parse(request.body.read, symbolize_names: true)
38
+ end
39
+ rescue => e
40
+ halt(400, { error: "Request must be valid JSON: #{e.message}" }.to_json)
41
+ end
42
+ end
43
+
44
+ # Provide information about the JWTs generated by the server
45
+ get '/info' do
46
+ metrics = Metrics.instance
47
+ output = {}
48
+ metrics.each do |key, value|
49
+ output[key] = value
50
+ end
51
+ output.to_json
52
+ end
53
+
54
+ options '/info' do
55
+ halt 200
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,6 +3,7 @@ module Authify
3
3
  module Services
4
4
  # A Sinatra App specifically for registering with the system
5
5
  class Registration < Service
6
+ use Authify::API::Middleware::Metrics
6
7
  helpers Helpers::APIUser
7
8
 
8
9
  configure do
@@ -16,6 +17,21 @@ module Authify
16
17
  OPTIONS
17
18
  GET
18
19
  POST
20
+ ],
21
+ 'Access-Control-Allow-Headers' => %w[
22
+ Origin
23
+ Accept
24
+ Accept-Encoding
25
+ Accept-Language
26
+ Access-Control-Request-Headers
27
+ Access-Control-Request-Method
28
+ Connection
29
+ Content-Type
30
+ Host
31
+ Referer
32
+ User-Agent
33
+ X-Requested-With
34
+ X-Forwarded-For
19
35
  ]
20
36
 
21
37
  begin
@@ -63,6 +79,10 @@ module Authify
63
79
  response.to_json
64
80
  end
65
81
 
82
+ options '/signup' do
83
+ halt 200
84
+ end
85
+
66
86
  post '/forgot_password' do
67
87
  email = @parsed_body[:email]
68
88
  token = @parsed_body[:token]
@@ -74,6 +94,7 @@ module Authify
74
94
  found_user.verified = true
75
95
  found_user.password = @parsed_body[:password]
76
96
  found_user.save
97
+ Metrics.instance.increment('registration.password.resets')
77
98
  {
78
99
  id: found_user.id,
79
100
  email: found_user.email,
@@ -88,6 +109,10 @@ module Authify
88
109
  end
89
110
  end
90
111
 
112
+ options '/forgot_password' do
113
+ halt 200
114
+ end
115
+
91
116
  post '/verify' do
92
117
  email = @parsed_body[:email]
93
118
  password = @parsed_body[:password]
@@ -112,6 +137,10 @@ module Authify
112
137
  jwt: jwt_token(user: found_user)
113
138
  }.to_json
114
139
  end
140
+
141
+ options '/verify' do
142
+ halt 200
143
+ end
115
144
  end
116
145
  end
117
146
  end
@@ -3,7 +3,7 @@ module Authify
3
3
  VERSION = [
4
4
  0, # Major
5
5
  3, # Minor
6
- 1 # Patch
6
+ 2 # Patch
7
7
  ].join('.')
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authify-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Gnagy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-11 00:00:00.000000000 Z
11
+ date: 2017-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: authify-core
@@ -204,6 +204,20 @@ dependencies:
204
204
  - - "~>"
205
205
  - !ruby/object:Gem::Version
206
206
  version: '1.26'
207
+ - !ruby/object:Gem::Dependency
208
+ name: hitimes
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - "~>"
212
+ - !ruby/object:Gem::Version
213
+ version: '1.2'
214
+ type: :runtime
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - "~>"
219
+ - !ruby/object:Gem::Version
220
+ version: '1.2'
207
221
  - !ruby/object:Gem::Dependency
208
222
  name: bundler
209
223
  requirement: !ruby/object:Gem::Requirement
@@ -355,6 +369,8 @@ files:
355
369
  - lib/authify/api/helpers/api_user.rb
356
370
  - lib/authify/api/helpers/jwt_encryption.rb
357
371
  - lib/authify/api/jsonapi_utils.rb
372
+ - lib/authify/api/metrics.rb
373
+ - lib/authify/api/middleware/metrics.rb
358
374
  - lib/authify/api/models/apikey.rb
359
375
  - lib/authify/api/models/group.rb
360
376
  - lib/authify/api/models/identity.rb
@@ -370,6 +386,7 @@ files:
370
386
  - lib/authify/api/service.rb
371
387
  - lib/authify/api/services/api.rb
372
388
  - lib/authify/api/services/jwt_provider.rb
389
+ - lib/authify/api/services/monitoring.rb
373
390
  - lib/authify/api/services/registration.rb
374
391
  - lib/authify/api/version.rb
375
392
  homepage: https://github.com/knuedge/authify-api