model_driven_api 2.3.10 → 2.3.16
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/app/commands/authenticate_user.rb +25 -9
- data/app/controllers/api/v2/application_controller.rb +3 -5
- 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: 6f42b6fcf4138560f8e183c7f02e10854836f7e04247bbe8bb96cdf3b3299324
|
4
|
+
data.tar.gz: 1ea8b0e0819840b9f443c06d77f5b175c510085ea435aed509968bf87f2cf2ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcb26da2904c349a2749d30ec86011b2712847c0fbfd7577bbc02bcb549e1d2bc05425c5beb609c62784dae0ae3f25a2272a240707ec9647d5e8f3a97c59034a
|
7
|
+
data.tar.gz: e4f5477ef79bfe582465ba72a25b984b248d9a2f0b28bf35ad16e4dca4ad104eaa96bd1487df95b0ad7476593544a0fef8c010418b99d6bffc7f8b2012972baa
|
@@ -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
|
|
@@ -113,7 +113,8 @@ class Api::V2::ApplicationController < ActionController::API
|
|
113
113
|
resource = "custom_action_#{params[:do]}"
|
114
114
|
raise NoMethodError unless @model.respond_to?(resource)
|
115
115
|
# return true, MultiJson.dump(params[:id].blank? ? @model.send(resource, params) : @model.send(resource, params[:id].to_i, params))
|
116
|
-
|
116
|
+
puts json_attrs
|
117
|
+
return true, @model.send(resource, params).to_json(json_attrs)
|
117
118
|
end
|
118
119
|
# if it's here there is no custom action in the request querystring
|
119
120
|
return false
|
@@ -127,15 +128,12 @@ class Api::V2::ApplicationController < ActionController::API
|
|
127
128
|
end
|
128
129
|
|
129
130
|
def authenticate_request
|
130
|
-
# puts request.headers.inspect
|
131
131
|
@current_user = nil
|
132
|
-
# puts "Are there wbehooks headers to check for? #{Settings.ns(:security).allowed_authorization_headers}"
|
133
132
|
Settings.ns(:security).allowed_authorization_headers.split(",").each do |header|
|
134
133
|
# puts "Found header #{header}: #{request.headers[header.underscore.dasherize]}"
|
135
134
|
check_authorization("Authorize#{header}".constantize.call(request.headers, request.raw_post)) if request.headers[header.underscore.dasherize]
|
136
135
|
end
|
137
136
|
|
138
|
-
# This is the default one, if the header doesn't have a valid form for one of the other Auth methods, then use this Auth Class
|
139
137
|
check_authorization AuthorizeApiRequest.call(request.headers) unless @current_user
|
140
138
|
return unauthenticated!(OpenStruct.new({message: @auth_errors})) unless @current_user
|
141
139
|
|
@@ -160,7 +158,7 @@ class Api::V2::ApplicationController < ActionController::API
|
|
160
158
|
# has precedence over if you have setup the json_attrs in the model concern
|
161
159
|
from_params = params[:a].deep_symbolize_keys unless params[:a].blank?
|
162
160
|
from_params = params[:json_attrs].deep_symbolize_keys unless params[:json_attrs].blank?
|
163
|
-
from_params.presence || @
|
161
|
+
from_params.presence || @json_attrs.presence || @model.json_attrs.presence || {} rescue {}
|
164
162
|
end
|
165
163
|
|
166
164
|
def extract_model
|
@@ -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,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))[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.16
|
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
|