authify-api 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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