authify-api 0.0.6 → 0.1.0

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.
@@ -7,7 +7,10 @@ module Authify
7
7
 
8
8
  attribute :email
9
9
  attribute :full_name
10
- has_many :api_keys
10
+ attribute :admin
11
+ attribute :created_at
12
+
13
+ has_many :apikeys
11
14
  has_many :groups
12
15
  has_many :organizations
13
16
  has_many :identities
@@ -6,47 +6,42 @@ module Authify
6
6
  use Middleware::JWTAuth
7
7
  register Sinatra::JSONAPI
8
8
 
9
- configure do
10
- set :protection, except: :http_origin
11
- end
12
-
13
- # rubocop:disable Metrics/BlockLength
14
- before '*' do
15
- headers 'Access-Control-Allow-Origin' => '*',
16
- 'Access-Control-Allow-Methods' => %w(
17
- OPTIONS
18
- DELETE
19
- GET
20
- PATCH
21
- POST
22
- PUT
23
- )
9
+ helpers Helpers::APIUser
24
10
 
25
- unless env[:authenticated]
26
- processed_headers = request.env.dup.each_with_object({}) do |(k, v), acc|
27
- acc[Regexp.last_match(1).downcase] = v if k =~ /^http_(.*)/i
11
+ helpers do
12
+ def determine_roles
13
+ on_behalf_of = processed_headers['x_authify_on_behalf_of']
14
+ if !env[:authenticated] && remote_app
15
+ env[:authenticated] = true
16
+ update_current_user on_behalf_of if on_behalf_of
28
17
  end
29
- if processed_headers.key?('x_authify_access')
30
- access = processed_headers['x_authify_access']
31
- secret = processed_headers['x_authify_secret']
32
- remote_app = Models::TrustedDelegate.from_access_key(access, secret)
33
- env[:authenticated] = true if remote_app
34
18
 
35
- if remote_app && processed_headers.key?('x_authify_on_behalf_of')
36
- @current_user = Models::User.find_by_email(
37
- processed_headers['x_authify_on_behalf_of']
38
- )
39
- end
40
- end
19
+ @roles ||= []
20
+ @roles << :trusted if remote_app && !on_behalf_of
21
+ @roles << :user if env[:authenticated]
22
+ @roles << :admin if current_user && current_user.admin?
41
23
  end
42
- unless env[:authenticated]
43
- halt 401, env[:authentication_errors].map(&:message).join(', ')
24
+
25
+ def role
26
+ (@roles || []).uniq
44
27
  end
45
28
  end
46
29
 
47
- helpers Helpers::APIUser
30
+ before '*' do
31
+ # headers 'Access-Control-Allow-Origin' => '*',
32
+ # 'Access-Control-Allow-Methods' => %w(
33
+ # OPTIONS
34
+ # DELETE
35
+ # GET
36
+ # PATCH
37
+ # POST
38
+ # PUT
39
+ # )
40
+ determine_roles
41
+ end
48
42
 
49
- resource :api_keys, &Controllers::APIKey
43
+ resource :apikeys, &Controllers::APIKey
44
+ resource :identities, &Controllers::Identity
50
45
  resource :groups, &Controllers::Group
51
46
  resource :organizations, &Controllers::Organization
52
47
  resource :users, &Controllers::User
@@ -21,7 +21,7 @@ module Authify
21
21
  begin
22
22
  unless request.get? || request.options?
23
23
  request.body.rewind
24
- @parsed_body = JSON.parse(request.body.read)
24
+ @parsed_body = JSON.parse(request.body.read, symbolize_names: true)
25
25
  end
26
26
  rescue => e
27
27
  halt(400, { error: "Request must be valid JSON: #{e.message}" }.to_json)
@@ -30,14 +30,26 @@ module Authify
30
30
 
31
31
  post '/token' do
32
32
  # For CLI / Typical API clients
33
- access = @parsed_body['access_key']
34
- secret = @parsed_body['secret_key']
33
+ access = @parsed_body[:access_key] || @parsed_body[:'access-key']
34
+ secret = @parsed_body[:secret_key] || @parsed_body[:'secret-key']
35
35
  # For Web UIs
36
- email = @parsed_body['email']
37
- password = @parsed_body['password']
36
+ email = @parsed_body[:email]
37
+ password = @parsed_body[:password]
38
+ # For Trusted Delegates signing users in via omniauth
39
+ del_data = @parsed_body[:delegate]
40
+ omni_provider = @parsed_body[:provider]
41
+ omni_uid = @parsed_body[:uid]
42
+ trusted_delegate = if del_data
43
+ Models::TrustedDelegate.from_access_key(
44
+ del_data[:access],
45
+ del_data[:secret]
46
+ )
47
+ end
38
48
 
39
49
  found_user = if access
40
50
  Models::User.from_api_key(access, secret)
51
+ elsif trusted_delegate
52
+ Models::User.from_identity(omni_provider, omni_uid)
41
53
  elsif email
42
54
  Models::User.from_email(email, password)
43
55
  end
@@ -50,10 +62,20 @@ module Authify
50
62
  end
51
63
  end
52
64
 
65
+ # Provide information about the JWTs generated by the server
66
+ get '/meta' do
67
+ {
68
+ algorithm: CONFIG[:jwt][:algorithm],
69
+ issuer: CONFIG[:jwt][:issuer],
70
+ expiration: CONFIG[:jwt][:expiration]
71
+ }.to_json
72
+ end
73
+
74
+ # Provide access to the public ECDSA key
53
75
  get '/key' do
54
- content_type 'application/x-pem-file'
55
- headers['Content-Disposition'] = 'attachment;filename=public_key.pem'
56
- public_key.export
76
+ {
77
+ data: public_key.export
78
+ }.to_json
57
79
  end
58
80
  end
59
81
  end
@@ -0,0 +1,63 @@
1
+ module Authify
2
+ module API
3
+ module Services
4
+ # A Sinatra App specifically for registering with the system
5
+ class Registration < Service
6
+ helpers Helpers::APIUser
7
+
8
+ configure do
9
+ set :protection, except: :http_origin
10
+ end
11
+
12
+ before '*' do
13
+ content_type 'application/json'
14
+ headers 'Access-Control-Allow-Origin' => '*',
15
+ 'Access-Control-Allow-Methods' => %w(
16
+ OPTIONS
17
+ GET
18
+ POST
19
+ )
20
+
21
+ begin
22
+ unless request.get? || request.options?
23
+ request.body.rewind
24
+ @parsed_body = JSON.parse(request.body.read, symbolize_names: true)
25
+ end
26
+ rescue => e
27
+ halt(400, { error: "Request must be valid JSON: #{e.message}" }.to_json)
28
+ end
29
+ end
30
+
31
+ post '/signup' do
32
+ email = @parsed_body[:email]
33
+ via = @parsed_body[:via]
34
+ password = @parsed_body[:password]
35
+ name = @parsed_body[:name]
36
+ del_data = @parsed_body[:delegate]
37
+ trusted_delegate = if del_data
38
+ Models::TrustedDelegate.from_access_key(
39
+ del_data[:access],
40
+ del_data[:secret]
41
+ )
42
+ end
43
+
44
+ halt(422, 'Duplicate User') if Models::User.exists?(email: email)
45
+ halt(403, 'Password Required') unless password || trusted_delegate
46
+
47
+ new_user = Models::User.new(email: email)
48
+ new_user.full_name = name if name
49
+ new_user.password = password if password
50
+ if via && via[:provider]
51
+ new_user.identities.build(
52
+ provider: via[:provider],
53
+ uid: via[:uid] ? via[:uid] : email
54
+ )
55
+ end
56
+ new_user.save
57
+ update_current_user new_user
58
+ { id: new_user.id, email: new_user.email, jwt: jwt_token(new_user) }.to_json
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -2,8 +2,8 @@ module Authify
2
2
  module API
3
3
  VERSION = [
4
4
  0, # Major
5
- 0, # Minor
6
- 6 # Patch
5
+ 1, # Minor
6
+ 0 # 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.0.6
4
+ version: 0.1.0
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-02-07 00:00:00.000000000 Z
11
+ date: 2017-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: authify-core
@@ -56,16 +56,42 @@ dependencies:
56
56
  name: sinatra
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.4'
61
+ version: 2.0.0.beta2
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '3'
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
- - - "~>"
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 2.0.0.beta2
72
+ - - "<"
67
73
  - !ruby/object:Gem::Version
68
- version: '1.4'
74
+ version: '3'
75
+ - !ruby/object:Gem::Dependency
76
+ name: sinatra-contrib
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 2.0.0.beta2
82
+ - - "<"
83
+ - !ruby/object:Gem::Version
84
+ version: '3'
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 2.0.0.beta2
92
+ - - "<"
93
+ - !ruby/object:Gem::Version
94
+ version: '3'
69
95
  - !ruby/object:Gem::Dependency
70
96
  name: sinatra-activerecord
71
97
  requirement: !ruby/object:Gem::Requirement
@@ -123,33 +149,33 @@ dependencies:
123
149
  - !ruby/object:Gem::Version
124
150
  version: '1.3'
125
151
  - !ruby/object:Gem::Dependency
126
- name: jsonapi-serializers
152
+ name: json
127
153
  requirement: !ruby/object:Gem::Requirement
128
154
  requirements:
129
155
  - - "~>"
130
156
  - !ruby/object:Gem::Version
131
- version: '0.16'
157
+ version: '2.0'
132
158
  type: :runtime
133
159
  prerelease: false
134
160
  version_requirements: !ruby/object:Gem::Requirement
135
161
  requirements:
136
162
  - - "~>"
137
163
  - !ruby/object:Gem::Version
138
- version: '0.16'
164
+ version: '2.0'
139
165
  - !ruby/object:Gem::Dependency
140
- name: sinja
166
+ name: jsonapi-serializers
141
167
  requirement: !ruby/object:Gem::Requirement
142
168
  requirements:
143
169
  - - "~>"
144
170
  - !ruby/object:Gem::Version
145
- version: '1.2'
171
+ version: '0.16'
146
172
  type: :runtime
147
173
  prerelease: false
148
174
  version_requirements: !ruby/object:Gem::Requirement
149
175
  requirements:
150
176
  - - "~>"
151
177
  - !ruby/object:Gem::Version
152
- version: '1.2'
178
+ version: '0.16'
153
179
  - !ruby/object:Gem::Dependency
154
180
  name: puma
155
181
  requirement: !ruby/object:Gem::Requirement
@@ -287,29 +313,34 @@ files:
287
313
  - db/migrate/20170203231922_create_organizations_and_organization_memberships.rb
288
314
  - db/migrate/20170203231929_create_groups.rb
289
315
  - db/migrate/20170204001405_create_trusted_delegates.rb
316
+ - db/migrate/20170208021933_add_admin_to_user.rb
317
+ - db/migrate/20170208022427_set_default_for_user_admin.rb
290
318
  - db/schema.rb
291
319
  - lib/authify/api.rb
292
- - lib/authify/api/controllers/api_key.rb
320
+ - lib/authify/api/controllers/apikey.rb
293
321
  - lib/authify/api/controllers/group.rb
322
+ - lib/authify/api/controllers/identity.rb
294
323
  - lib/authify/api/controllers/organization.rb
295
324
  - lib/authify/api/controllers/user.rb
296
325
  - lib/authify/api/helpers/api_user.rb
297
326
  - lib/authify/api/helpers/jwt_encryption.rb
298
327
  - lib/authify/api/jsonapi_utils.rb
299
- - lib/authify/api/models/api_key.rb
328
+ - lib/authify/api/models/apikey.rb
300
329
  - lib/authify/api/models/group.rb
301
330
  - lib/authify/api/models/identity.rb
302
331
  - lib/authify/api/models/organization.rb
303
332
  - lib/authify/api/models/organization_membership.rb
304
333
  - lib/authify/api/models/trusted_delegate.rb
305
334
  - lib/authify/api/models/user.rb
306
- - lib/authify/api/serializers/api_key_serializer.rb
335
+ - lib/authify/api/serializers/apikey_serializer.rb
307
336
  - lib/authify/api/serializers/group_serializer.rb
337
+ - lib/authify/api/serializers/identity_serializer.rb
308
338
  - lib/authify/api/serializers/organization_serializer.rb
309
339
  - lib/authify/api/serializers/user_serializer.rb
310
340
  - lib/authify/api/service.rb
311
341
  - lib/authify/api/services/api.rb
312
342
  - lib/authify/api/services/jwt_provider.rb
343
+ - lib/authify/api/services/registration.rb
313
344
  - lib/authify/api/version.rb
314
345
  homepage: https://github.com/knuedge/authify-api
315
346
  licenses:
@@ -1,36 +0,0 @@
1
- module Authify
2
- module API
3
- module Controllers
4
- APIKey = proc do
5
- helpers do
6
- def find(id)
7
- Models::APIKey.find(id.to_i)
8
- end
9
- end
10
-
11
- index do
12
- Models::APIKey.all
13
- end
14
-
15
- show do
16
- last_modified resource.updated_at
17
- next resource
18
- end
19
-
20
- destroy do
21
- resource.destroy
22
- end
23
-
24
- show_many do |ids|
25
- Models::APIKey.find(ids)
26
- end
27
-
28
- has_one :user do
29
- pluck do
30
- resource.user
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end