model_driven_api 2.3.13 → 2.3.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/commands/authenticate_user.rb +25 -9
- data/app/controllers/api/v2/authentication_controller.rb +1 -1
- data/app/controllers/api/v2/info_controller.rb +7 -0
- data/app/models/used_token.rb +7 -0
- data/db/migrate/20210519145438_create_used_tokens.rb +12 -0
- data/lib/concerns/model_driven_api_user.rb +1 -1
- data/lib/json_web_token.rb +17 -12
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c73a32dcfadaf698e4d904a110a4ab140a235699d6d71b1f064127624dc4832
|
4
|
+
data.tar.gz: f99c45c100d53fc494bdfef2f886dbb1385951caebfbf5754d6a496f019f1fe3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1642e0c66e19c6ea3c8a383d3000329d5bba051803c026c40767e05ebadce23bff75e0983fc4a720a3681b28566d41d3d3e0d2f61f2a23f602b89ada4b078681
|
7
|
+
data.tar.gz: 0b31e00c37e1a7511c35b6add9c91428791f8e0c13976f83044d5e52dcb43ef0a70071a04828fdd472e5d783239f7eaeb63669a61b6d3258026e83b47057a050
|
@@ -6,26 +6,42 @@ class AuthenticateUser
|
|
6
6
|
end
|
7
7
|
prepend SimpleCommand
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
|
11
|
-
|
9
|
+
def initialize(*args)
|
10
|
+
if !args.email.blank? && !args.password.blank?
|
11
|
+
@email = args.email
|
12
|
+
@password = args.password
|
13
|
+
elsif !args.access_token.blank?
|
14
|
+
@access_token = args.access_token
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def call
|
15
|
-
JsonWebToken.encode(user_id: api_user.id)
|
19
|
+
if !api_user.blank? && result = JsonWebToken.encode(user_id: api_user.id)
|
20
|
+
# The token is created and the api_user exists => Invalidating all the previous tokens
|
21
|
+
# Since this is a new login and I don't care from where it comes, new logins always
|
22
|
+
# Invalidate older tokens
|
23
|
+
UsedToken.where(user_id: api_user.id).update(valid: false)
|
24
|
+
return result
|
25
|
+
end
|
26
|
+
nil
|
16
27
|
end
|
17
28
|
|
18
29
|
private
|
19
30
|
|
20
|
-
attr_accessor :email, :password
|
31
|
+
attr_accessor :email, :password, :access_token
|
21
32
|
|
22
33
|
def api_user
|
23
|
-
|
34
|
+
if !email.blank? && !password.blank?
|
35
|
+
user = User.find_by(email: email)
|
36
|
+
|
37
|
+
# Verify the password. You can create a blank method for now.
|
38
|
+
raise AccessDenied if user.blank? && user.authenticate(password).blank?
|
39
|
+
elsif !access_token.blank?
|
40
|
+
user = User.find_by(access_token: access_token)
|
41
|
+
end
|
42
|
+
|
24
43
|
raise AccessDenied unless user.present?
|
25
44
|
|
26
|
-
# Verify the password. You can create a blank method for now.
|
27
|
-
raise AccessDenied if user.authenticate(password).blank?
|
28
|
-
|
29
45
|
return user
|
30
46
|
end
|
31
47
|
|
@@ -2,7 +2,7 @@ class Api::V2::AuthenticationController < ActionController::API
|
|
2
2
|
include ::ApiExceptionManagement
|
3
3
|
|
4
4
|
def authenticate
|
5
|
-
command = AuthenticateUser.call(params[:auth][:email], params[:auth][:password])
|
5
|
+
command = !params[:atoken].blank? && User.column_names.include?("access_token") ? AuthenticateUser.call(access_token: params[:atoken]) : AuthenticateUser.call(email: params[:auth][:email], password: params[:auth][:password])
|
6
6
|
|
7
7
|
if command.success?
|
8
8
|
response.headers['Token'] = command.result
|
@@ -15,6 +15,13 @@ class Api::V2::InfoController < Api::V2::ApplicationController
|
|
15
15
|
render json: ::Role.all.to_json, status: 200
|
16
16
|
end
|
17
17
|
|
18
|
+
|
19
|
+
# api :GET, '/api/v2/info/heartbeat'
|
20
|
+
# Just keeps the session alive
|
21
|
+
def heartbeat
|
22
|
+
head :ok
|
23
|
+
end
|
24
|
+
|
18
25
|
# GET '/api/v2/info/translations'
|
19
26
|
def translations
|
20
27
|
render json: I18n.t(".", locale: (params[:locale].presence || :it)).to_json, status: 200
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateUsedTokens < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
create_table :used_tokens do |t|
|
4
|
+
t.string :token
|
5
|
+
t.references :user, null: false, foreign_key: true
|
6
|
+
t.boolean :valid, default: true
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
add_index :used_tokens, :token, unique: true
|
11
|
+
end
|
12
|
+
end
|
@@ -2,7 +2,7 @@ module ModelDrivenApiUser
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
included do
|
5
|
-
|
5
|
+
has_many :used_tokens, inverse_of: :user, dependent: :destroy
|
6
6
|
## DSL (AKA what to show in the returned JSON)
|
7
7
|
# Use @@json_attrs to drive json rendering for
|
8
8
|
# API model responses (index, show and update ones).
|
data/lib/json_web_token.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
class JsonWebToken
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
body = ::JWT.decode(token, ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"])[0]
|
9
|
-
::HashWithIndifferentAccess.new body
|
10
|
-
rescue
|
11
|
-
nil
|
12
|
-
end
|
2
|
+
class << self
|
3
|
+
def encode(payload, expiry = 15.minutes.from_now.to_i)
|
4
|
+
result = ::JWT.encode(payload.merge(exp: expiry), ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"])
|
5
|
+
# Store the created token into the DB for later checks if is invalid
|
6
|
+
UsedToken.create(token: result, user_id: payload[:user_id])
|
7
|
+
result
|
13
8
|
end
|
14
|
-
|
9
|
+
|
10
|
+
def decode(token)
|
11
|
+
# Check if the passed token is present and valid into the UsedToken
|
12
|
+
raise "Token is invalidated by new login" unless UsedToken.exists?(token: token, valid: true)
|
13
|
+
body = ::JWT.decode(token, ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"])[0]
|
14
|
+
::HashWithIndifferentAccess.new body
|
15
|
+
rescue
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: model_driven_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriele Tassoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thecore_backend_commons
|
@@ -139,12 +139,14 @@ files:
|
|
139
139
|
- app/controllers/api/v2/authentication_controller.rb
|
140
140
|
- app/controllers/api/v2/info_controller.rb
|
141
141
|
- app/controllers/api/v2/users_controller.rb
|
142
|
+
- app/models/used_token.rb
|
142
143
|
- config/initializers/after_initialize_for_model_driven_api.rb
|
143
144
|
- config/initializers/cors_api_thecore.rb
|
144
145
|
- config/initializers/knock.rb
|
145
146
|
- config/initializers/time_with_zone.rb
|
146
147
|
- config/initializers/wrap_parameters.rb
|
147
148
|
- config/routes.rb
|
149
|
+
- db/migrate/20210519145438_create_used_tokens.rb
|
148
150
|
- lib/concerns/api_exception_management.rb
|
149
151
|
- lib/concerns/model_driven_api_role.rb
|
150
152
|
- lib/concerns/model_driven_api_user.rb
|
@@ -173,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
175
|
- !ruby/object:Gem::Version
|
174
176
|
version: '0'
|
175
177
|
requirements: []
|
176
|
-
rubygems_version: 3.0.3
|
178
|
+
rubygems_version: 3.0.3.1
|
177
179
|
signing_key:
|
178
180
|
specification_version: 4
|
179
181
|
summary: Convention based RoR engine which uses DB schema introspection to create
|