api_guard 0.2.2 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b7ce3ac5306ae3a652084d29da83f37ec9b41c5
4
- data.tar.gz: 7fb6b919ed4044e459a3840e442505326bfda971
3
+ metadata.gz: 5e4c4d5d2ef0490d9c1cfbb9bf408d09c5152fc3
4
+ data.tar.gz: 21f401a251b77bf72dfffccf92965f3ecd501f81
5
5
  SHA512:
6
- metadata.gz: e02605d2b473c9931a1c494203562ae9e87ef90d5b3adfa4e043aba6b96e3da7aa3fc306189139a4d546b7b88eb4ecbdb876783dab28b9e6879b37dcca2f1c97
7
- data.tar.gz: 293b709e2ae69d3b07912c319d5fd37c8ae3156797cf09b19aa55ab8bc317e90822747a3b3d0a856c368d0e16d8a89cdb7b6ca208d047e9dc5142db81db385d8
6
+ metadata.gz: 19a27ce1e5ae8f87482e891895de91ce3e08fae8912392ef09f24b4e3763b3e9a1db2315578acb784b6097548fb2ec02e3a9ab8d1776f71c5b0eafaf466e42fa
7
+ data.tar.gz: c76a2d4620091808a89f903abbf65672b25cddcd8c7974c6e8fdccdb195da88d96258bab30f3f0221954bb371705c619828f3167878dd45b0bfc06cf25d55f30
data/README.md CHANGED
@@ -35,6 +35,7 @@ for cryptographic signing.
35
35
  * [Overriding defaults](#overriding-defaults)
36
36
  * [Controllers](#controllers)
37
37
  * [Routes](#routes)
38
+ * [Customizing / translating response messages using I18n](#customizing--translating-response-messages-using-i18n)
38
39
  * [Testing](#testing)
39
40
  * [Contributing](#contributing)
40
41
  * [License](#license)
@@ -353,19 +354,19 @@ configurations.
353
354
  ApiGuard.setup do |config|
354
355
  # Validity of the JWT access token
355
356
  # Default: 1 day
356
- config.token_validity = 1.day
357
+ # config.token_validity = 1.day
357
358
 
358
359
  # Secret key for signing (encoding & decoding) the JWT access token
359
360
  # Default: 'secret_key_base' from Rails secrets
360
- config.token_signing_secret = Rails.application.secrets.secret_key_base
361
+ # config.token_signing_secret = 'my_signing_secret'
361
362
 
362
363
  # Invalidate old tokens on changing the password
363
364
  # Default: false
364
- config.invalidate_old_tokens_on_password_change = false
365
+ # config.invalidate_old_tokens_on_password_change = false
365
366
 
366
367
  # Blacklist JWT access token after refreshing
367
368
  # Default: false
368
- config.blacklist_token_after_refreshing = false
369
+ # config.blacklist_token_after_refreshing = false
369
370
  end
370
371
  ```
371
372
 
@@ -555,6 +556,22 @@ end
555
556
  Above configuration will replace default registration routes `users/sign_up` & `users/delete` with `account/create` &
556
557
  `account/delete`
557
558
 
559
+ ### Customizing / translating response messages using I18n
560
+
561
+ API Guard uses [I18n](https://guides.rubyonrails.org/i18n.html) for success and error messages. You can create your own
562
+ locale file and customize the messages for any language.
563
+
564
+ ```yaml
565
+ en:
566
+ api_guard:
567
+ authentication:
568
+ signed_in: 'Signed in successfully'
569
+ signed_out: 'Signed out successfully'
570
+ ```
571
+
572
+ You can find the complete list of available keys in this file:
573
+ https://github.com/Gokul595/api_guard/blob/master/config/locales/en.yml
574
+
558
575
  ## Testing
559
576
 
560
577
  API Guard comes with helper for creating JWT access token and refresh token for the resource which you can use it for
@@ -8,22 +8,22 @@ module ApiGuard
8
8
  def create
9
9
  if resource.authenticate(params[:password])
10
10
  create_token_and_set_header(resource, resource_name)
11
- render_success(message: 'Signed in successfully')
11
+ render_success(message: I18n.t('api_guard.authentication.signed_in'))
12
12
  else
13
- render_error(422, message: 'Invalid login credentials')
13
+ render_error(422, message: I18n.t('api_guard.authentication.invalid_login_credentials'))
14
14
  end
15
15
  end
16
16
 
17
17
  def destroy
18
18
  blacklist_token
19
- render_success(message: 'Signed out successfully')
19
+ render_success(message: I18n.t('api_guard.authentication.signed_out'))
20
20
  end
21
21
 
22
22
  private
23
23
 
24
24
  def find_resource
25
25
  self.resource = resource_class.find_by(email: params[:email].downcase.strip) if params[:email].present?
26
- render_error(422, message: 'Invalid login credentials') unless resource
26
+ render_error(422, message: I18n.t('api_guard.authentication.invalid_login_credentials')) unless resource
27
27
  end
28
28
  end
29
29
  end
@@ -12,7 +12,7 @@ module ApiGuard
12
12
  destroy_all_refresh_tokens(current_resource)
13
13
 
14
14
  create_token_and_set_header(current_resource, resource_name)
15
- render_success(message: 'Password changed successfully')
15
+ render_success(message: I18n.t('api_guard.password.changed'))
16
16
  else
17
17
  render_error(422, object: current_resource)
18
18
  end
@@ -8,7 +8,7 @@ module ApiGuard
8
8
  init_resource(sign_up_params)
9
9
  if resource.save
10
10
  create_token_and_set_header(resource, resource_name)
11
- render_success(message: 'Signed up successfully')
11
+ render_success(message: I18n.t('api_guard.registration.signed_up'))
12
12
  else
13
13
  render_error(422, object: resource)
14
14
  end
@@ -16,7 +16,7 @@ module ApiGuard
16
16
 
17
17
  def destroy
18
18
  current_resource.destroy
19
- render_success(message: "Account deleted successfully")
19
+ render_success(message: I18n.t('api_guard.registration.account_deleted'))
20
20
  end
21
21
 
22
22
  private
@@ -11,7 +11,7 @@ module ApiGuard
11
11
  @refresh_token.destroy
12
12
  blacklist_token if ApiGuard.blacklist_token_after_refreshing
13
13
 
14
- render_success(message: 'Token refreshed successfully')
14
+ render_success(message: I18n.t('api_guard.access_token.refreshed'))
15
15
  end
16
16
 
17
17
  private
@@ -21,9 +21,9 @@ module ApiGuard
21
21
 
22
22
  if refresh_token_from_header
23
23
  @refresh_token = find_refresh_token_of(current_resource, refresh_token_from_header)
24
- return render_error(401, message: 'Invalid refresh token') unless @refresh_token
24
+ return render_error(401, message: I18n.t('api_guard.refresh_token.invalid')) unless @refresh_token
25
25
  else
26
- render_error(401, message: 'Refresh token is missing in the request')
26
+ render_error(401, message: I18n.t('api_guard.refresh_token.missing'))
27
27
  end
28
28
  end
29
29
  end
@@ -0,0 +1,22 @@
1
+ en:
2
+ api_guard:
3
+ authentication:
4
+ signed_in: 'Signed in successfully'
5
+ signed_out: 'Signed out successfully'
6
+ invalid_login_credentials: 'Invalid login credentials'
7
+ password:
8
+ changed: 'Password changed successfully'
9
+ registration:
10
+ signed_up: 'Signed up successfully'
11
+ account_deleted: 'Account deleted successfully'
12
+ access_token:
13
+ refreshed: 'Token refreshed successfully'
14
+ missing: 'Access token is missing in the request'
15
+ invalid: 'Invalid access token'
16
+ expired: 'Access token expired'
17
+ refresh_token:
18
+ invalid: 'Invalid refresh token'
19
+ missing: 'Refresh token is missing in the request'
20
+ response:
21
+ success: 'success'
22
+ error: 'error'
@@ -19,17 +19,17 @@ module ApiGuard
19
19
  @resource_name = resource_name
20
20
 
21
21
  @token = request.headers['Authorization']&.split('Bearer ')&.last
22
- return render_error(401, message: 'Access token is missing in the request') unless @token
22
+ return render_error(401, message: I18n.t('api_guard.access_token.missing')) unless @token
23
23
 
24
24
  authenticate_token
25
25
 
26
26
  # Render error response only if no resource found and no previous render happened
27
- render_error(401, message: 'Invalid access token') if !current_resource && !performed?
27
+ render_error(401, message: I18n.t('api_guard.access_token.invalid')) if !current_resource && !performed?
28
28
  rescue JWT::DecodeError => e
29
29
  if e.message == 'Signature has expired'
30
- render_error(401, message: 'Access token expired')
30
+ render_error(401, message: I18n.t('api_guard.access_token.expired'))
31
31
  else
32
- render_error(401, message: 'Invalid access token')
32
+ render_error(401, message: I18n.t('api_guard.access_token.invalid'))
33
33
  end
34
34
  end
35
35
 
@@ -64,11 +64,12 @@ module ApiGuard
64
64
 
65
65
  return if current_resource && valid_issued_at? && !blacklisted?
66
66
 
67
- render_error(401, message: 'Invalid access token')
67
+ render_error(401, message: I18n.t('api_guard.access_token.invalid'))
68
68
  end
69
69
 
70
70
  def current_resource
71
71
  return unless respond_to?("current_#{@resource_name}")
72
+
72
73
  public_send("current_#{@resource_name}")
73
74
  end
74
75
  end
@@ -18,12 +18,14 @@ module ApiGuard
18
18
  # Returns whether the JWT token is blacklisted or not
19
19
  def blacklisted?
20
20
  return false unless token_blacklisting_enabled?(current_resource)
21
+
21
22
  blacklisted_tokens_for(current_resource).exists?(token: @token)
22
23
  end
23
24
 
24
25
  # Blacklist the current JWT token from future access
25
26
  def blacklist_token
26
27
  return unless token_blacklisting_enabled?(current_resource)
28
+
27
29
  blacklisted_tokens_for(current_resource).create(token: @token, expire_at: Time.at(@decoded_token[:exp]).utc)
28
30
  end
29
31
  end
@@ -59,6 +59,7 @@ module ApiGuard
59
59
  # to restrict access to old access(JWT) tokens
60
60
  def invalidate_old_jwt_tokens(resource)
61
61
  return unless ApiGuard.invalidate_old_tokens_on_password_change
62
+
62
63
  resource.token_issued_at = Time.at(token_issued_at).utc
63
64
  end
64
65
  end
@@ -30,11 +30,13 @@ module ApiGuard
30
30
  # Create a new refresh_token for the current resource
31
31
  def new_refresh_token(resource)
32
32
  return unless refresh_token_enabled?(resource)
33
+
33
34
  refresh_tokens_for(resource).create(token: uniq_refresh_token(resource)).token
34
35
  end
35
36
 
36
37
  def destroy_all_refresh_tokens(resource)
37
38
  return unless refresh_token_enabled?(resource)
39
+
38
40
  refresh_tokens_for(resource).destroy_all
39
41
  end
40
42
  end
@@ -2,14 +2,14 @@ module ApiGuard
2
2
  module ResponseFormatters
3
3
  module Renderer
4
4
  def render_success(data: nil, message: nil)
5
- resp_data = { status: 'success' }
5
+ resp_data = { status: I18n.t('api_guard.response.success') }
6
6
  resp_data[:message] = message if message
7
7
 
8
8
  render json: resp_data, status: 200
9
9
  end
10
10
 
11
11
  def render_error(status, options = {})
12
- data = { status: 'error' }
12
+ data = { status: I18n.t('api_guard.response.error') }
13
13
  data[:error] = options[:object] ? options[:object].errors.full_messages[0] : options[:message]
14
14
 
15
15
  render json: data, status: status
@@ -1,3 +1,3 @@
1
1
  module ApiGuard
2
- VERSION = '0.2.2'
2
+ VERSION = '0.3.0'.freeze
3
3
  end
@@ -1,22 +1,22 @@
1
1
  module ApiGuard
2
2
  class ControllersGenerator < Rails::Generators::Base
3
- CONTROLLERS = %i[registration authentication tokens passwords]
3
+ CONTROLLERS = %i[registration authentication tokens passwords].freeze
4
4
 
5
5
  desc 'Generates API Guard controllers in app/controllers/'
6
6
  source_root File.expand_path('../templates', __FILE__)
7
7
 
8
- argument :scope, required: true,
9
- desc: "The scope to create controllers in, e.g. users, admins"
8
+ argument :scope, required: true, desc: 'The scope to create controllers in, e.g. users, admins'
10
9
 
11
10
  class_option :controllers, aliases: "-c", type: :array,
12
- desc: "Specify the controllers to generate (#{CONTROLLERS.join(', ')})"
11
+ desc: "Specify the controllers to generate (#{CONTROLLERS.join(', ')})"
13
12
 
14
13
  def create_controllers
15
14
  @controller_scope = scope.camelize
16
15
  controllers = options[:controllers] || CONTROLLERS
17
16
 
18
17
  controllers.each do |controller_name|
19
- template "#{controller_name}_controller.rb", "app/controllers/#{scope}/#{controller_name}_controller.rb"
18
+ template "#{controller_name}_controller.rb",
19
+ "app/controllers/#{scope}/#{controller_name}_controller.rb"
20
20
  end
21
21
  end
22
22
  end
@@ -6,22 +6,22 @@ module <%= @controller_scope %>
6
6
  # def create
7
7
  # if resource.authenticate(params[:password])
8
8
  # create_token_and_set_header(resource, resource_name)
9
- # render_success(data: resource)
9
+ # render_success(message: I18n.t('api_guard.authentication.signed_in'))
10
10
  # else
11
- # render_error(422, message: 'Invalid login credentials')
11
+ # render_error(422, message: I18n.t('api_guard.authentication.invalid_login_credentials'))
12
12
  # end
13
13
  # end
14
14
 
15
15
  # def destroy
16
16
  # blacklist_token
17
- # render_success(message: 'Signed out successfully')
17
+ # render_success(message: I18n.t('api_guard.authentication.signed_out'))
18
18
  # end
19
19
 
20
20
  # private
21
21
 
22
22
  # def find_resource
23
23
  # self.resource = resource_class.find_by(email: params[:email].downcase.strip) if params[:email].present?
24
- # render_error(422, message: 'Invalid login credentials') unless resource
24
+ # render_error(422, message: I18n.t('api_guard.authentication.invalid_login_credentials')) unless resource
25
25
  # end
26
26
  end
27
27
  end
@@ -6,11 +6,11 @@ module <%= @controller_scope %>
6
6
  # invalidate_old_jwt_tokens(current_resource)
7
7
  #
8
8
  # if current_resource.update_attributes(password_params)
9
- # blacklist_token
9
+ # blacklist_token unless ApiGuard.invalidate_old_tokens_on_password_change
10
10
  # destroy_all_refresh_tokens(current_resource)
11
11
  #
12
12
  # create_token_and_set_header(current_resource, resource_name)
13
- # render_success(data: current_resource)
13
+ # render_success(message: I18n.t('api_guard.password.changed'))
14
14
  # else
15
15
  # render_error(422, object: current_resource)
16
16
  # end
@@ -19,7 +19,7 @@ module <%= @controller_scope %>
19
19
  # private
20
20
 
21
21
  # def password_params
22
- # params.require(resource_name.to_sym).permit(:password, :password_confirmation)
22
+ # params.permit(:password, :password_confirmation)
23
23
  # end
24
24
  end
25
25
  end
@@ -6,7 +6,7 @@ module <%= @controller_scope %>
6
6
  # init_resource(sign_up_params)
7
7
  # if resource.save
8
8
  # create_token_and_set_header(resource, resource_name)
9
- # render_success(data: resource, message: "#{resource_name.capitalize} created successfully")
9
+ # render_success(message: I18n.t('api_guard.registration.signed_up'))
10
10
  # else
11
11
  # render_error(422, object: resource)
12
12
  # end
@@ -14,13 +14,13 @@ module <%= @controller_scope %>
14
14
 
15
15
  # def destroy
16
16
  # current_resource.destroy
17
- # render_success(message: "#{resource_name.capitalize} destroyed successfully")
17
+ # render_success(message: I18n.t('api_guard.registration.account_deleted'))
18
18
  # end
19
19
 
20
20
  # private
21
21
 
22
22
  # def sign_up_params
23
- # params.require(resource_name.to_sym).permit(:email, :password, :password_confirmation)
23
+ # params.permit(:email, :password, :password_confirmation)
24
24
  # end
25
25
  end
26
26
  end
@@ -4,9 +4,12 @@ module <%= @controller_scope %>
4
4
  # before_action :find_refresh_token, only: [:create]
5
5
 
6
6
  # def create
7
- # @refresh_token.destroy
8
7
  # create_token_and_set_header(current_resource, resource_name)
9
- # render_success(data: current_resource)
8
+ #
9
+ # @refresh_token.destroy
10
+ # blacklist_token if ApiGuard.blacklist_token_after_refreshing
11
+ #
12
+ # render_success(message: I18n.t('api_guard.access_token.refreshed'))
10
13
  # end
11
14
 
12
15
  # private
@@ -16,9 +19,9 @@ module <%= @controller_scope %>
16
19
  #
17
20
  # if refresh_token_from_header
18
21
  # @refresh_token = find_refresh_token_of(current_resource, refresh_token_from_header)
19
- # return render_error(401, message: 'Invalid refresh token') unless @refresh_token
22
+ # return render_error(401, message: I18n.t('api_guard.refresh_token.invalid')) unless @refresh_token
20
23
  # else
21
- # render_error(401, message: 'Refresh token is missing in the request')
24
+ # render_error(401, message: I18n.t('api_guard.refresh_token.missing'))
22
25
  # end
23
26
  # end
24
27
  end
@@ -1,17 +1,17 @@
1
1
  ApiGuard.setup do |config|
2
2
  # Validity of the JWT access token
3
3
  # Default: 1 day
4
- config.token_validity = 1.day
4
+ # config.token_validity = 1.day
5
5
 
6
6
  # Secret key for signing (encoding & decoding) the JWT access token
7
7
  # Default: 'secret_key_base' from Rails secrets
8
- config.token_signing_secret = Rails.application.secrets.secret_key_base
8
+ # config.token_signing_secret = 'my_signing_secret'
9
9
 
10
10
  # Invalidate old tokens on changing the password
11
11
  # Default: false
12
- config.invalidate_old_tokens_on_password_change = false
12
+ # config.invalidate_old_tokens_on_password_change = false
13
13
 
14
14
  # Blacklist JWT access token after refreshing
15
15
  # Default: false
16
- config.blacklist_token_after_refreshing = false
16
+ # config.blacklist_token_after_refreshing = false
17
17
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gokul Murali
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-08 00:00:00.000000000 Z
11
+ date: 2019-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -167,6 +167,7 @@ files:
167
167
  - app/controllers/api_guard/tokens_controller.rb
168
168
  - app/models/api_guard/application_record.rb
169
169
  - app/views/layouts/api_guard/application.html.erb
170
+ - config/locales/en.yml
170
171
  - config/routes.rb
171
172
  - lib/api_guard.rb
172
173
  - lib/api_guard/app_secret_key.rb