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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5497bdb2727e103fa3727595ca62bbaf065b9135dd9bfbc8674f21506929dd0
4
- data.tar.gz: ad09cdae9730b0f5c7983eb478c660ef8cc1c13d1d2c1cb13cd9a143b67f4029
3
+ metadata.gz: d38e64a791f7147bdc145e1767814ac885fcf75ff5031cf30743b96d8717fb32
4
+ data.tar.gz: 213dc7345b1061bca3a93826ac9c52b63e97bee20891aca0569f0e14ce11f565
5
5
  SHA512:
6
- metadata.gz: 719fcf3175dced8eaea5e238551d7d143edc185e9131c44ae9bf5358509de252da07491c27c16f485644c782f73c8f351379744c60f20bc803b074f024ecdbb8
7
- data.tar.gz: ad157de69fbd575e5a9197594901b811a0cb1e74f25eb49146c011fbec9d32ebd6874e8712f2ef8edff4799d9e46cd04e2040c5cbe7c48b3a04e7f428917ab5a
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(email, password)
10
- @email = email
11
- @password = password
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
- JsonWebToken.encode(user_id: api_user.id) if api_user
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
- user = User.find_by_email(email)
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
@@ -0,0 +1,3 @@
1
+ class UsedToken < ApplicationRecord
2
+ belongs_to :user, inverse_of: :used_tokens
3
+ end
data/config/routes.rb CHANGED
@@ -12,6 +12,7 @@ Rails.application.routes.draw do
12
12
  get :translations
13
13
  get :schema
14
14
  get :dsl
15
+ get :heartbeat
15
16
  end
16
17
 
17
18
  post "authenticate" => "authentication#authenticate"
@@ -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
@@ -0,0 +1,7 @@
1
+ class RenameValidToIsValidInUsedToken < ActiveRecord::Migration[6.0]
2
+ def change
3
+ change_table :used_tokens do |t|
4
+ t.rename :valid, :is_valid
5
+ end
6
+ end
7
+ 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).
@@ -1,14 +1,20 @@
1
1
  class JsonWebToken
2
- class << self
3
- def encode(payload, expiry = 15.minutes.from_now.to_i)
4
- ::JWT.encode(payload.merge(exp: expiry), ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"])
5
- end
6
-
7
- def decode(token)
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
+ # 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
- end
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.13
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-04-12 00:00:00.000000000 Z
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