devise-api 0.1.1 → 0.1.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +45 -1
- data/app/controllers/devise/api/tokens_controller.rb +34 -3
- data/app/services/devise/api/tokens_service/create.rb +1 -1
- data/app/services/devise/api/tokens_service/refresh.rb +1 -1
- data/config/locales/en.yml +1 -0
- data/lib/devise/api/configuration.rb +4 -0
- data/lib/devise/api/controllers/helpers.rb +7 -10
- data/lib/devise/api/generators/install_generator.rb +0 -16
- data/lib/devise/api/generators/templates/migration.rb.erb +15 -2
- data/lib/devise/api/responses/error_response.rb +2 -0
- data/lib/devise/api/token.rb +2 -2
- data/lib/devise/api/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d47e2be72c7d15e0c0de4535943a208d8d37e7d2b801de167ccf5f5c8e3d08e
|
4
|
+
data.tar.gz: 87d42ee2c7784370789032608d0caa634f5a703c7c4cbb15139c82d34ca26664
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b6045dbf6c5906a5ef70de320d39df12f79b1c7599ce91851c98e61be2449959b0f7e263ad3a795d21070d56b9a84944d4799e1a5156fee8ae90039f8c9642e
|
7
|
+
data.tar.gz: b92e03c4fdb2d18eb3d3cf1ca690782e9f9149362b27b4535ccae3c739dbae3e14550b9e5d4535da6a3aa7658ee25936b59e49c937a3093b90b88d9477ca0f13
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -69,6 +69,8 @@ Your user model is now ready to use `devise-api` gem. It will draw routes for to
|
|
69
69
|
| sign_in_user_tokens | POST | /users/tokens/sign_in | devise/api/tokens#sign_in |
|
70
70
|
| info_user_tokens | GET | /users/tokens/info | devise/api/tokens#info |
|
71
71
|
|
72
|
+
### You can look up the [example requests](#example-api-requests).
|
73
|
+
|
72
74
|
## Configuration
|
73
75
|
|
74
76
|
`devise-api` is a full configurable gem. You can configure it to your needs. Here is a basic usage example:
|
@@ -89,6 +91,8 @@ Devise.setup do |config|
|
|
89
91
|
api.refresh_token.generator = ->(_resource_owner) { Devise.friendly_token(60) }
|
90
92
|
api.refresh_token.expires_in_infinite = ->(_resource_owner) { false }
|
91
93
|
|
94
|
+
# Sign up
|
95
|
+
api.sign_up.enabled = true
|
92
96
|
|
93
97
|
# Authorization
|
94
98
|
api.authorization.key = 'Authorization'
|
@@ -226,9 +230,49 @@ class Api::V1::TokensController < YourBaseController
|
|
226
230
|
end
|
227
231
|
```
|
228
232
|
|
233
|
+
## Example API requests
|
234
|
+
|
235
|
+
### Sign in
|
236
|
+
```curl
|
237
|
+
curl --location --request POST 'http://127.0.0.1:3000/users/tokens/sign_in' \
|
238
|
+
--header 'Content-Type: application/json' \
|
239
|
+
--data-raw '{
|
240
|
+
"email": "test@development.com",
|
241
|
+
"password": "123456"
|
242
|
+
}'
|
243
|
+
```
|
244
|
+
|
245
|
+
### Sign up
|
246
|
+
```curl
|
247
|
+
curl --location --request POST 'http://127.0.0.1:3000/users/tokens/sign_up' \
|
248
|
+
--header 'Content-Type: application/json' \
|
249
|
+
--data-raw '{
|
250
|
+
"email": "test@development.com",
|
251
|
+
"password": "123456"
|
252
|
+
}'
|
253
|
+
```
|
254
|
+
|
255
|
+
### Refresh token
|
256
|
+
```curl
|
257
|
+
curl --location --request POST 'http://127.0.0.1:3000/users/tokens/refresh' \
|
258
|
+
--header 'Authorization: Bearer <refresh_token>'
|
259
|
+
```
|
260
|
+
|
261
|
+
### Revoke
|
262
|
+
```curl
|
263
|
+
curl --location --request POST 'http://127.0.0.1:3000/users/tokens/revoke' \
|
264
|
+
--header 'Authorization: Bearer <access_token>'
|
265
|
+
```
|
266
|
+
|
267
|
+
### Info
|
268
|
+
```curl
|
269
|
+
curl --location --request GET 'http://127.0.0.1:3000/users/tokens/info' \
|
270
|
+
--header 'Authorization: Bearer <access_token>'
|
271
|
+
```
|
272
|
+
|
229
273
|
## Development
|
230
274
|
|
231
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake
|
275
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
232
276
|
|
233
277
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
234
278
|
|
@@ -1,15 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
3
4
|
module Devise
|
4
5
|
module Api
|
5
6
|
class TokensController < Devise.api.config.base_controller.constantize
|
6
7
|
skip_before_action :verify_authenticity_token, raise: false
|
7
|
-
before_action :authenticate_devise_api_token!, only: %i[info
|
8
|
+
before_action :authenticate_devise_api_token!, only: %i[info]
|
8
9
|
|
9
10
|
respond_to :json
|
10
11
|
|
11
12
|
# rubocop:disable Metrics/AbcSize
|
12
13
|
def sign_up
|
14
|
+
unless Devise.api.config.sign_up.enabled
|
15
|
+
error_response = Devise::Api::Responses::ErrorResponse.new(request, error: :sign_up_disabled,
|
16
|
+
resource_class: resource_class)
|
17
|
+
|
18
|
+
return render json: error_response.body, status: error_response.status
|
19
|
+
end
|
20
|
+
|
13
21
|
Devise.api.config.before_sign_up.call(sign_up_params, request, resource_class)
|
14
22
|
|
15
23
|
service = Devise::Api::ResourceOwnerService::SignUp.new(params: sign_up_params,
|
@@ -103,9 +111,23 @@ module Devise
|
|
103
111
|
return render json: error_response.body, status: error_response.status
|
104
112
|
end
|
105
113
|
|
106
|
-
|
114
|
+
if current_devise_api_refresh_token.blank?
|
115
|
+
error_response = Devise::Api::Responses::ErrorResponse.new(request, error: :invalid_token,
|
116
|
+
resource_class: resource_class)
|
117
|
+
|
118
|
+
return render json: error_response.body, status: error_response.status
|
119
|
+
end
|
120
|
+
|
121
|
+
if current_devise_api_refresh_token.revoked?
|
122
|
+
error_response = Devise::Api::Responses::ErrorResponse.new(request, error: :revoked_token,
|
123
|
+
resource_class: resource_class)
|
124
|
+
|
125
|
+
render json: error_response.body, status: error_response.status
|
126
|
+
end
|
127
|
+
|
128
|
+
Devise.api.config.before_refresh.call(current_devise_api_refresh_token, request)
|
107
129
|
|
108
|
-
service = Devise::Api::TokensService::Refresh.new(devise_api_token:
|
130
|
+
service = Devise::Api::TokensService::Refresh.new(devise_api_token: current_devise_api_refresh_token).call
|
109
131
|
|
110
132
|
if service.success?
|
111
133
|
token_response = Devise::Api::Responses::TokenResponse.new(request, token: service.success,
|
@@ -141,6 +163,15 @@ module Devise
|
|
141
163
|
|
142
164
|
resource_owner.update_tracked_fields!(request)
|
143
165
|
end
|
166
|
+
|
167
|
+
def current_devise_api_refresh_token
|
168
|
+
return @current_devise_api_refresh_token if @current_devise_api_refresh_token
|
169
|
+
|
170
|
+
token = find_devise_api_token
|
171
|
+
devise_api_token_model = Devise.api.config.base_token_model.constantize
|
172
|
+
@current_devise_api_refresh_token = devise_api_token_model.find_by(refresh_token: token)
|
173
|
+
end
|
144
174
|
end
|
145
175
|
end
|
146
176
|
end
|
177
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -8,7 +8,7 @@ module Devise
|
|
8
8
|
option :previous_refresh_token, type: Types::String | Types::Nil, default: proc { nil }
|
9
9
|
|
10
10
|
def call
|
11
|
-
return Failure(:invalid_resource_owner) unless resource_owner.respond_to?(:access_tokens)
|
11
|
+
return Failure(error: :invalid_resource_owner) unless resource_owner.respond_to?(:access_tokens)
|
12
12
|
|
13
13
|
devise_api_token = yield create_devise_api_token
|
14
14
|
|
@@ -8,7 +8,7 @@ module Devise
|
|
8
8
|
option :resource_owner, default: proc { devise_api_token.resource_owner }
|
9
9
|
|
10
10
|
def call
|
11
|
-
return Failure(:expired_refresh_token) if devise_api_token.refresh_token_expired?
|
11
|
+
return Failure(error: :expired_refresh_token) if devise_api_token.refresh_token_expired?
|
12
12
|
|
13
13
|
devise_api_token = yield create_devise_api_token
|
14
14
|
Success(devise_api_token)
|
data/config/locales/en.yml
CHANGED
@@ -8,6 +8,7 @@ en:
|
|
8
8
|
expired_refresh_token: "Refresh token has expired"
|
9
9
|
revoked_token: "Token has been revoked"
|
10
10
|
refresh_token_disabled: "Refresh token is disabled for this application"
|
11
|
+
sign_up_disabled: "Sign up is disabled for this application"
|
11
12
|
invalid_refresh_token: "Refresh token is invalid"
|
12
13
|
invalid_email: "Email is invalid"
|
13
14
|
invalid_resource_owner: "Resource owner is invalid"
|
@@ -20,6 +20,10 @@ module Devise
|
|
20
20
|
setting :expires_in_infinite, default: proc { |_resource_owner| false }, reader: true
|
21
21
|
end
|
22
22
|
|
23
|
+
setting :sign_up, reader: true do
|
24
|
+
setting :enabled, default: true, reader: true
|
25
|
+
end
|
26
|
+
|
23
27
|
setting :authorization, reader: true do
|
24
28
|
setting :key, default: 'Authorization', reader: true
|
25
29
|
setting :scheme, default: 'Bearer', reader: true
|
@@ -38,18 +38,11 @@ module Devise
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def current_devise_api_token
|
41
|
-
|
41
|
+
return @current_devise_api_token if @current_devise_api_token
|
42
42
|
|
43
|
+
token = find_devise_api_token
|
43
44
|
devise_api_token_model = Devise.api.config.base_token_model.constantize
|
44
|
-
|
45
|
-
if Devise.api.config.refresh_token.enabled
|
46
|
-
return devise_api_token_model
|
47
|
-
.where(access_token: token)
|
48
|
-
.or(devise_api_token_model.where(refresh_token: token))
|
49
|
-
&.first
|
50
|
-
end
|
51
|
-
|
52
|
-
devise_api_token_model.find_by(access_token: token)
|
45
|
+
@current_devise_api_token = devise_api_token_model.find_by(access_token: token)
|
53
46
|
end
|
54
47
|
|
55
48
|
def current_devise_api_user
|
@@ -58,6 +51,10 @@ module Devise
|
|
58
51
|
|
59
52
|
private
|
60
53
|
|
54
|
+
def resource_class
|
55
|
+
current_devise_api_user&.class
|
56
|
+
end
|
57
|
+
|
61
58
|
def extract_devise_api_token_from_params
|
62
59
|
params[Devise.api.config.authorization.params_key]
|
63
60
|
end
|
@@ -40,22 +40,6 @@ module Devise
|
|
40
40
|
def migration_version
|
41
41
|
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
42
42
|
end
|
43
|
-
|
44
|
-
def primary_key_type
|
45
|
-
fallback = :integer
|
46
|
-
|
47
|
-
begin
|
48
|
-
ActiveRecord::Base.connection.supports_pgcrypto_uuid? ? :uuid : fallback
|
49
|
-
rescue StandardError
|
50
|
-
fallback
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def table_defaults_for_primary_key_type
|
55
|
-
return ', type: :uuid' if primary_key_type == :uuid
|
56
|
-
|
57
|
-
''
|
58
|
-
end
|
59
43
|
end
|
60
44
|
end
|
61
45
|
end
|
@@ -2,8 +2,11 @@
|
|
2
2
|
|
3
3
|
class CreateDeviseApiTables < ActiveRecord::Migration<%= migration_version %>
|
4
4
|
def change
|
5
|
-
|
6
|
-
|
5
|
+
# Use Active Record's configured type for primary and foreign keys
|
6
|
+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
7
|
+
|
8
|
+
create_table :devise_api_tokens, id: primary_key_type do |t|
|
9
|
+
t.belongs_to :resource_owner, null: false, polymorphic: true, index: true, type: foreign_key_type
|
7
10
|
t.string :access_token, null: false, index: true
|
8
11
|
t.string :refresh_token, null: true, index: true
|
9
12
|
t.integer :expires_in, null: false
|
@@ -13,4 +16,14 @@ class CreateDeviseApiTables < ActiveRecord::Migration<%= migration_version %>
|
|
13
16
|
t.timestamps
|
14
17
|
end
|
15
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def primary_and_foreign_key_types
|
23
|
+
config = Rails.configuration.generators
|
24
|
+
setting = config.options[config.orm][:primary_key_type]
|
25
|
+
primary_key_type = setting || :primary_key
|
26
|
+
foreign_key_type = setting || :bigint
|
27
|
+
[primary_key_type, foreign_key_type]
|
28
|
+
end
|
16
29
|
end
|
@@ -12,6 +12,7 @@ module Devise
|
|
12
12
|
expired_refresh_token
|
13
13
|
revoked_token
|
14
14
|
refresh_token_disabled
|
15
|
+
sign_up_disabled
|
15
16
|
invalid_refresh_token
|
16
17
|
invalid_email
|
17
18
|
invalid_resource_owner
|
@@ -112,6 +113,7 @@ module Devise
|
|
112
113
|
invalid_email_error? ||
|
113
114
|
invalid_refresh_token_error? ||
|
114
115
|
refresh_token_disabled_error? ||
|
116
|
+
sign_up_disabled_error? ||
|
115
117
|
invalid_resource_owner_error?
|
116
118
|
end
|
117
119
|
end
|
data/lib/devise/api/token.rb
CHANGED
@@ -41,7 +41,7 @@ module Devise
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def inactive?
|
44
|
-
revoked?
|
44
|
+
revoked? || expired?
|
45
45
|
end
|
46
46
|
|
47
47
|
def expired?
|
@@ -51,7 +51,7 @@ module Devise
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def refresh_token_expired?
|
54
|
-
return false
|
54
|
+
return false if Devise.api.config.refresh_token.expires_in_infinite.call(resource_owner)
|
55
55
|
|
56
56
|
Time.now.utc > refresh_token_expires_at
|
57
57
|
end
|
data/lib/devise/api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nejdetkadir
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: devise
|
@@ -166,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: '0'
|
168
168
|
requirements: []
|
169
|
-
rubygems_version: 3.
|
169
|
+
rubygems_version: 3.4.12
|
170
170
|
signing_key:
|
171
171
|
specification_version: 4
|
172
172
|
summary: The devise-api gem is a convenient way to add authentication to your Ruby
|