model_driven_api 2.3.13 → 2.3.19
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 +26 -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 +3 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20210519145438_create_used_tokens.rb +12 -0
- data/db/migrate/20210528111450_rename_valid_to_is_valid_in_used_token.rb +7 -0
- data/lib/concerns/model_driven_api_user.rb +1 -1
- data/lib/json_web_token.rb +18 -12
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d38e64a791f7147bdc145e1767814ac885fcf75ff5031cf30743b96d8717fb32
|
4
|
+
data.tar.gz: 213dc7345b1061bca3a93826ac9c52b63e97bee20891aca0569f0e14ce11f565
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d435ae0c87967fcdfb1517cf1f353588635efb1df3a657b555f9d622bd7aff36c684c8c8cfaf764926edaf93109ddabc813867dbb62000a7b92d220c1d1a93e
|
7
|
+
data.tar.gz: 609644b3be46a961b594e95fc601bc48393095a6bf090679094d5227427856ced680c83d0fb44d489589d3e2433d145473bc080a90a8574040c77cfbb59ab47f
|
@@ -6,26 +6,43 @@ class AuthenticateUser
|
|
6
6
|
end
|
7
7
|
prepend SimpleCommand
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
|
11
|
-
|
9
|
+
def initialize(*args)
|
10
|
+
first_arg = args.first
|
11
|
+
if !first_arg[:email].blank? && !first_arg[:password].blank?
|
12
|
+
@email = first_arg[:email]
|
13
|
+
@password = first_arg[:password]
|
14
|
+
elsif !first_arg[:access_token].blank?
|
15
|
+
@access_token = first_arg[:access_token]
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
def call
|
15
|
-
|
20
|
+
current_u = api_user
|
21
|
+
if !current_u.blank? && result = JsonWebToken.encode(user_id: current_u.id)
|
22
|
+
# The token is created and the api_user exists => Invalidating all the previous tokens
|
23
|
+
# Since this is a new login and I don't care from where it comes, new logins always
|
24
|
+
# Invalidate older tokens
|
25
|
+
UsedToken.where(user_id: api_user.id).update(is_valid: false) if ENV["ALLOW_MULTISESSIONS"] == "false"
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
nil
|
16
29
|
end
|
17
30
|
|
18
31
|
private
|
19
32
|
|
20
|
-
attr_accessor :email, :password
|
33
|
+
attr_accessor :email, :password, :access_token
|
21
34
|
|
22
35
|
def api_user
|
23
|
-
|
36
|
+
if !email.blank? && !password.blank?
|
37
|
+
user = User.find_by(email: email)
|
38
|
+
# Verify the password.
|
39
|
+
raise AccessDenied if user.blank? && user.authenticate(password).blank?
|
40
|
+
elsif !access_token.blank?
|
41
|
+
user = User.find_by(access_token: access_token)
|
42
|
+
end
|
43
|
+
|
24
44
|
raise AccessDenied unless user.present?
|
25
45
|
|
26
|
-
# Verify the password. You can create a blank method for now.
|
27
|
-
raise AccessDenied if user.authenticate(password).blank?
|
28
|
-
|
29
46
|
return user
|
30
47
|
end
|
31
48
|
|
@@ -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 by returning a new token
|
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
|
data/config/routes.rb
CHANGED
@@ -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,20 @@
|
|
1
1
|
class JsonWebToken
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
+
# In a public environment management, without login, it has no interest, so I don't pollute the DB
|
7
|
+
UsedToken.find_or_create_by(token: result, user_id: payload[:user_id]) if ENV["ALLOW_MULTISESSIONS"] == "false"
|
8
|
+
result
|
13
9
|
end
|
14
|
-
|
10
|
+
|
11
|
+
def decode(token)
|
12
|
+
# Check if the passed token is present and valid into the UsedToken
|
13
|
+
raise "Token is invalidated by new login" unless UsedToken.exists?(token: token, is_valid: true) if ENV["ALLOW_MULTISESSIONS"] == "false"
|
14
|
+
body = ::JWT.decode(token, ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"])[0]
|
15
|
+
::HashWithIndifferentAccess.new body
|
16
|
+
rescue
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
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.19
|
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,15 @@ 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
|
150
|
+
- db/migrate/20210528111450_rename_valid_to_is_valid_in_used_token.rb
|
148
151
|
- lib/concerns/api_exception_management.rb
|
149
152
|
- lib/concerns/model_driven_api_role.rb
|
150
153
|
- lib/concerns/model_driven_api_user.rb
|
@@ -173,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
176
|
- !ruby/object:Gem::Version
|
174
177
|
version: '0'
|
175
178
|
requirements: []
|
176
|
-
rubygems_version: 3.0.3
|
179
|
+
rubygems_version: 3.0.3.1
|
177
180
|
signing_key:
|
178
181
|
specification_version: 4
|
179
182
|
summary: Convention based RoR engine which uses DB schema introspection to create
|