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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5497bdb2727e103fa3727595ca62bbaf065b9135dd9bfbc8674f21506929dd0
4
- data.tar.gz: ad09cdae9730b0f5c7983eb478c660ef8cc1c13d1d2c1cb13cd9a143b67f4029
3
+ metadata.gz: 3c73a32dcfadaf698e4d904a110a4ab140a235699d6d71b1f064127624dc4832
4
+ data.tar.gz: f99c45c100d53fc494bdfef2f886dbb1385951caebfbf5754d6a496f019f1fe3
5
5
  SHA512:
6
- metadata.gz: 719fcf3175dced8eaea5e238551d7d143edc185e9131c44ae9bf5358509de252da07491c27c16f485644c782f73c8f351379744c60f20bc803b074f024ecdbb8
7
- data.tar.gz: ad157de69fbd575e5a9197594901b811a0cb1e74f25eb49146c011fbec9d32ebd6874e8712f2ef8edff4799d9e46cd04e2040c5cbe7c48b3a04e7f428917ab5a
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(email, password)
10
- @email = email
11
- @password = password
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) if api_user
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
- user = User.find_by_email(email)
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,7 @@
1
+ class UsedToken < ApplicationRecord
2
+ belongs_to :user, inverse_of: :used_tokens
3
+
4
+ rails_admin do
5
+ visible false
6
+ end
7
+ end
@@ -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).
@@ -1,14 +1,19 @@
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
+ UsedToken.create(token: result, user_id: payload[:user_id])
7
+ result
13
8
  end
14
- end
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.13
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-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,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