n_base_rails 0.1.1

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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +5 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +49 -0
  8. data/Rakefile +4 -0
  9. data/bin/console +15 -0
  10. data/bin/setup +8 -0
  11. data/lib/.env +4 -0
  12. data/lib/.rspec +1 -0
  13. data/lib/.rubocop.yml +288 -0
  14. data/lib/.rubocop_disabled.yml +31 -0
  15. data/lib/.rubocop_enabled.yml +0 -0
  16. data/lib/Capfile +46 -0
  17. data/lib/Gemfile +51 -0
  18. data/lib/config/database.yml +24 -0
  19. data/lib/config/deploy/development.rb +85 -0
  20. data/lib/config/deploy/production.rb +63 -0
  21. data/lib/config/deploy/staging.rb +56 -0
  22. data/lib/config/deploy.rb +7 -0
  23. data/lib/config/initializers/devise.rb +315 -0
  24. data/lib/config/locales/devise.en.yml +65 -0
  25. data/lib/config/locales/en.yml +33 -0
  26. data/lib/config/locales/errors.en.yml +57 -0
  27. data/lib/config/routes.rb +26 -0
  28. data/lib/config/settings.yml +22 -0
  29. data/lib/controllers/api/admin/base_controller.rb +5 -0
  30. data/lib/controllers/api/admin/sessions_controller.rb +39 -0
  31. data/lib/controllers/api/admin/users_controller.rb +9 -0
  32. data/lib/controllers/api/v1/base_controller.rb +5 -0
  33. data/lib/controllers/api/v1/sessions_controller.rb +39 -0
  34. data/lib/controllers/api/v1/users_controller.rb +7 -0
  35. data/lib/controllers/application_controller.rb +30 -0
  36. data/lib/controllers/concerns/.DS_Store +0 -0
  37. data/lib/controllers/concerns/.keep +0 -0
  38. data/lib/controllers/concerns/base_concern.rb +9 -0
  39. data/lib/controllers/concerns/json_renderer.rb +76 -0
  40. data/lib/controllers/concerns/pagination.rb +32 -0
  41. data/lib/controllers/concerns/rescue_exception.rb +73 -0
  42. data/lib/db/migrate/20220721091426_devise_create_users.rb +46 -0
  43. data/lib/db/migrate/20230113072522_create_devices.rb +13 -0
  44. data/lib/db/migrate/20230227135020_create_posts.rb +15 -0
  45. data/lib/db/migrate/20230303165318_devise_create_admins.rb +46 -0
  46. data/lib/db/schema.rb +62 -0
  47. data/lib/db/seeds.rb +7 -0
  48. data/lib/generators/n_base_rails/install_generator.rb +42 -0
  49. data/lib/lib/.DS_Store +0 -0
  50. data/lib/lib/active_record_validation/error.rb +33 -0
  51. data/lib/lib/api/error.rb +63 -0
  52. data/lib/lib/json_web_token.rb +13 -0
  53. data/lib/log/.keep +0 -0
  54. data/lib/log/capistrano.log +28367 -0
  55. data/lib/log/development.log +30201 -0
  56. data/lib/log/test.log +11768 -0
  57. data/lib/models/admin.rb +10 -0
  58. data/lib/models/application_record.rb +5 -0
  59. data/lib/models/concerns/.keep +0 -0
  60. data/lib/models/device.rb +11 -0
  61. data/lib/models/post.rb +5 -0
  62. data/lib/models/user.rb +9 -0
  63. data/lib/n_base_rails/version.rb +5 -0
  64. data/lib/n_base_rails.rb +9 -0
  65. data/lib/public/404.html +67 -0
  66. data/lib/public/422.html +67 -0
  67. data/lib/public/500.html +66 -0
  68. data/lib/public/apple-touch-icon-precomposed.png +0 -0
  69. data/lib/public/apple-touch-icon.png +0 -0
  70. data/lib/public/docs/api/admin/definitions/users.yaml +15 -0
  71. data/lib/public/docs/api/admin/paths/index.yaml +29 -0
  72. data/lib/public/docs/api/admin/paths/sessions.yaml +121 -0
  73. data/lib/public/docs/api/admin/paths/users.yaml +39 -0
  74. data/lib/public/docs/api/shared/meta_infos.yaml +41 -0
  75. data/lib/public/docs/api/shared/unauthorized_response.yaml +31 -0
  76. data/lib/public/docs/api/v1/definitions/users.yaml +13 -0
  77. data/lib/public/docs/api/v1/paths/example.yaml +431 -0
  78. data/lib/public/docs/api/v1/paths/index.yaml +28 -0
  79. data/lib/public/docs/api/v1/paths/sessions.yaml +121 -0
  80. data/lib/public/docs/api/v1/paths/users.yaml +24 -0
  81. data/lib/public/favicon.ico +0 -0
  82. data/lib/public/robots.txt +1 -0
  83. data/lib/public/swagger/admin/admin-swagger-initializer.js +24 -0
  84. data/lib/public/swagger/admin/admin.html +19 -0
  85. data/lib/public/swagger/favicon-16x16.png +0 -0
  86. data/lib/public/swagger/favicon-32x32.png +0 -0
  87. data/lib/public/swagger/index.css +16 -0
  88. data/lib/public/swagger/oauth2-redirect.html +79 -0
  89. data/lib/public/swagger/swagger-ui-bundle.js +3 -0
  90. data/lib/public/swagger/swagger-ui-bundle.js.map +1 -0
  91. data/lib/public/swagger/swagger-ui-es-bundle-core.js +2 -0
  92. data/lib/public/swagger/swagger-ui-es-bundle-core.js.map +1 -0
  93. data/lib/public/swagger/swagger-ui-es-bundle.js +3 -0
  94. data/lib/public/swagger/swagger-ui-es-bundle.js.map +1 -0
  95. data/lib/public/swagger/swagger-ui-standalone-preset.js +3 -0
  96. data/lib/public/swagger/swagger-ui-standalone-preset.js.map +1 -0
  97. data/lib/public/swagger/swagger-ui.css +4 -0
  98. data/lib/public/swagger/swagger-ui.css.map +1 -0
  99. data/lib/public/swagger/swagger-ui.js +2 -0
  100. data/lib/public/swagger/swagger-ui.js.map +1 -0
  101. data/lib/public/swagger/v1/app.html +19 -0
  102. data/lib/public/swagger/v1/swagger-initializer.js +25 -0
  103. data/lib/serializers/.DS_Store +0 -0
  104. data/lib/serializers/action_not_allowed_serializer.rb +18 -0
  105. data/lib/serializers/api/.DS_Store +0 -0
  106. data/lib/serializers/api/admin/base_serializer.rb +14 -0
  107. data/lib/serializers/api/admin/hash_serializer.rb +22 -0
  108. data/lib/serializers/api/admin/user_serializer.rb +9 -0
  109. data/lib/serializers/api/v1/base_serializer.rb +14 -0
  110. data/lib/serializers/api/v1/hash_serializer.rb +22 -0
  111. data/lib/serializers/api/v1/user_serializer.rb +9 -0
  112. data/lib/serializers/record_not_found_serializer.rb +28 -0
  113. data/lib/serializers/validation_error_serializer.rb +45 -0
  114. data/lib/services/api/admin/generate_access_token_service.rb +34 -0
  115. data/lib/services/api/admin/generate_refresh_token_service.rb +24 -0
  116. data/lib/services/api/authorize_request_service.rb +35 -0
  117. data/lib/services/api/v1/generate_access_token_service.rb +34 -0
  118. data/lib/services/api/v1/generate_refresh_token_service.rb +24 -0
  119. data/lib/spec/controllers/api/admin/sessions_controller_spec.rb +125 -0
  120. data/lib/spec/controllers/api/admin/users_controller_spec.rb +35 -0
  121. data/lib/spec/controllers/api/v1/sessions_controller_spec.rb +125 -0
  122. data/lib/spec/controllers/api/v1/users_controller_spec.rb +23 -0
  123. data/lib/spec/factories/admins.rb +8 -0
  124. data/lib/spec/factories/devices.rb +7 -0
  125. data/lib/spec/factories/posts.rb +6 -0
  126. data/lib/spec/factories/users.rb +8 -0
  127. data/lib/spec/helpers/request_helpers.rb +7 -0
  128. data/lib/spec/models/admin_spec.rb +9 -0
  129. data/lib/spec/models/device_spec.rb +13 -0
  130. data/lib/spec/models/post_spec.rb +6 -0
  131. data/lib/spec/models/user_spec.rb +9 -0
  132. data/lib/spec/rails_helper.rb +66 -0
  133. data/lib/spec/serializers/api/admin/user_serializer.rb +20 -0
  134. data/lib/spec/serializers/api/v1/user_serializer.rb +20 -0
  135. data/lib/spec/spec_helper.rb +94 -0
  136. data/lib/spec/supports/shared_context.rb +19 -0
  137. data/lib/spec/supports/shared_example/admin_authentication.rb +47 -0
  138. data/lib/spec/supports/shared_example/user_authentication.rb +47 -0
  139. metadata +181 -0
@@ -0,0 +1,19 @@
1
+ <!-- HTML for static distribution bundle build -->
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Swagger UI</title>
7
+ <link rel="stylesheet" type="text/css" href="../swagger-ui.css" />
8
+ <link rel="stylesheet" type="text/css" href="../index.css" />
9
+ <link rel="icon" type="image/png" href="../favicon-32x32.png" sizes="32x32" />
10
+ <link rel="icon" type="image/png" href="../favicon-16x16.png" sizes="16x16" />
11
+ </head>
12
+
13
+ <body>
14
+ <div id="swagger-ui"></div>
15
+ <script src="../swagger-ui-bundle.js" charset="UTF-8"> </script>
16
+ <script src="../swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
17
+ <script src="./swagger-initializer.js" charset="UTF-8"> </script>
18
+ </body>
19
+ </html>
@@ -0,0 +1,25 @@
1
+ window.onload = function() {
2
+ //<editor-fold desc="Changeable Configuration Block">
3
+
4
+ // the following lines will be replaced by docker/configurator, when it runs in a docker-container
5
+ window.ui = SwaggerUIBundle({
6
+ url: "/docs/api/v1/paths/index.yaml",
7
+ dom_id: '#swagger-ui',
8
+ deepLinking: true,
9
+ presets: [
10
+ SwaggerUIBundle.presets.apis,
11
+ SwaggerUIStandalonePreset
12
+ ],
13
+ plugins: [
14
+ SwaggerUIBundle.plugins.DownloadUrl
15
+ ],
16
+ layout: "StandaloneLayout",
17
+ requestInterceptor: (req) => {
18
+
19
+ req.headers["Authorization"] = "Bearer " + req.headers["Authorization"]
20
+ return req
21
+ }
22
+ });
23
+
24
+ //</editor-fold>
25
+ };
Binary file
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActionNotAllowedSerializer
4
+ def initialize(error)
5
+ @error = error
6
+ end
7
+
8
+ def serialize
9
+ {
10
+ success: false,
11
+ errors: [I18n.t(:not_allowed, scope: %i[errors action])]
12
+ }
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :error
18
+ end
Binary file
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::BaseSerializer < ActiveModel::Serializer
4
+ def initialize(object, options = {})
5
+ @type = options[:type]
6
+ super(object, options)
7
+ end
8
+
9
+ def attributes(*args)
10
+ field_custom = "Api::Admin::#{object.class}Serializer".constantize::FIELD_CUSTOM
11
+
12
+ super.slice(*field_custom[@type] || super.keys)
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::HashSerializer
4
+ attr_reader :object, :root
5
+
6
+ def initialize(object, args = {})
7
+ @object = object
8
+ @root = args[:root]
9
+ end
10
+
11
+ def to_hash
12
+ root ? {root_key => object.to_h} : object.to_h
13
+ end
14
+
15
+ private
16
+
17
+ def root_key
18
+ return :data if root == true
19
+
20
+ root.to_sym if root.is_a?(String) || root.is_a?(Symbol)
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::UserSerializer < Api::Admin::BaseSerializer
4
+ attributes :id, :email, :created_at
5
+
6
+ FIELD_CUSTOM = {
7
+ user_list: %i[id email]
8
+ }.freeze
9
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::BaseSerializer < ActiveModel::Serializer
4
+ def initialize(object, options = {})
5
+ @type = options[:type]
6
+ super(object, options)
7
+ end
8
+
9
+ def attributes(*args)
10
+ field_custom = "Api::V1::#{object.class}Serializer".constantize::FIELD_CUSTOM
11
+
12
+ super.slice(*field_custom[@type] || super.keys)
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::HashSerializer
4
+ attr_reader :object, :root
5
+
6
+ def initialize(object, args = {})
7
+ @object = object
8
+ @root = args[:root]
9
+ end
10
+
11
+ def to_hash
12
+ root ? {root_key => object.to_h} : object.to_h
13
+ end
14
+
15
+ private
16
+
17
+ def root_key
18
+ return :data if root == true
19
+
20
+ root.to_sym if root.is_a?(String) || root.is_a?(Symbol)
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::UserSerializer < Api::V1::BaseSerializer
4
+ attributes :id, :email, :created_at
5
+
6
+ FIELD_CUSTOM = {
7
+ user_details: %i[id email]
8
+ }.freeze
9
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RecordNotFoundSerializer
4
+ def initialize(error)
5
+ @error = error
6
+ @resource = error.model.underscore
7
+ end
8
+
9
+ def serialize
10
+ {
11
+ success: false,
12
+ errors: [
13
+ {
14
+ resource: resource,
15
+ field: nil
16
+ }.merge(details)
17
+ ]
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :error, :resource
24
+
25
+ def details
26
+ I18n.t :not_found, scope: %i[errors active_record]
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ValidationErrorSerializer
4
+ def initialize(record, field, details, message)
5
+ @record = record
6
+ @field = field
7
+ @details = details
8
+ @message = message
9
+ end
10
+
11
+ def serialize
12
+ {
13
+ resource: resource,
14
+ field: field,
15
+ code: code,
16
+ message: message
17
+ }
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :record, :message
23
+
24
+ def resource
25
+ I18n.t underscored_resource_name,
26
+ scope: %i[errors resources],
27
+ default: underscored_resource_name
28
+ end
29
+
30
+ def field
31
+ I18n.t @field,
32
+ scope: [:errors, :fields, underscored_resource_name],
33
+ default: @field.to_s
34
+ end
35
+
36
+ def code
37
+ I18n.t @details[:error],
38
+ scope: %i[errors code],
39
+ default: @details[:error].to_s
40
+ end
41
+
42
+ def underscored_resource_name
43
+ record.class.to_s.gsub("::", "").underscore
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::GenerateAccessTokenService
4
+ def initialize(args)
5
+ @resource = args[:resource]
6
+ @refresh_token = args[:refresh_token]
7
+ @device_id = args[:device_id]
8
+ end
9
+
10
+ def execute
11
+ {
12
+ access_token: JsonWebToken.encode(payload),
13
+ refresh_token: refresh_token,
14
+ "#{resource.class.name.downcase}": {
15
+ id: resource.id,
16
+ email: resource.email
17
+ }
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :resource, :refresh_token, :device_id
24
+
25
+ def payload
26
+ {
27
+ id: resource.id,
28
+ email: resource.email,
29
+ resource_type: resource.class.name,
30
+ device_id: device_id,
31
+ exp: (Time.current + Settings.admin.authenticate.access_token.exp.hours).to_i
32
+ }
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::GenerateRefreshTokenService
4
+ def initialize(device)
5
+ @device = device
6
+ end
7
+
8
+ def execute
9
+ device.refresh_token = Device.digest_token
10
+ device.save!
11
+ JsonWebToken.encode(payload)
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :device
17
+
18
+ def payload
19
+ {
20
+ refresh_token: device.refresh_token,
21
+ exp: (Time.current + Settings.admin.authenticate.refresh_token.exp.days).to_i
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::AuthorizeRequestService
4
+ def initialize(args)
5
+ @authorization_header = args[:authorization_header]
6
+ @resource_class = args[:resource_type].to_s.classify
7
+ end
8
+
9
+ def perform
10
+ authorize_request!
11
+ verify_author_resource
12
+ author_resource
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :authorization_header, :resource_class, :decoded_access_token, :author_resource
18
+
19
+ def authorize_request!
20
+ access_token = authorization_header.split.last
21
+ @decoded_access_token = JsonWebToken.decode(access_token)
22
+ raise JWT::DecodeError unless decoded_access_token[:resource_type] == resource_class
23
+ end
24
+
25
+ def verify_author_resource
26
+ @author_resource = Class.const_get(resource_class).find_by id: decoded_access_token[:id]
27
+ raise JWT::DecodeError unless author_resource
28
+
29
+ raise JWT::DecodeError unless valid_device?
30
+ end
31
+
32
+ def valid_device?
33
+ author_resource.devices.find_by(id: decoded_access_token[:device_id])
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::GenerateAccessTokenService
4
+ def initialize(args)
5
+ @resource = args[:resource]
6
+ @refresh_token = args[:refresh_token]
7
+ @device_id = args[:device_id]
8
+ end
9
+
10
+ def execute
11
+ {
12
+ access_token: JsonWebToken.encode(payload),
13
+ refresh_token: refresh_token,
14
+ "#{resource.class.name.downcase}": {
15
+ id: resource.id,
16
+ email: resource.email
17
+ }
18
+ }
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :resource, :refresh_token, :device_id
24
+
25
+ def payload
26
+ {
27
+ id: resource.id,
28
+ email: resource.email,
29
+ resource_type: resource.class.name,
30
+ device_id: device_id,
31
+ exp: (Time.current + Settings.user.authenticate.access_token.exp.hours).to_i
32
+ }
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::GenerateRefreshTokenService
4
+ def initialize(device)
5
+ @device = device
6
+ end
7
+
8
+ def execute
9
+ device.refresh_token = Device.digest_token
10
+ device.save!
11
+ JsonWebToken.encode(payload)
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :device
17
+
18
+ def payload
19
+ {
20
+ refresh_token: device.refresh_token,
21
+ exp: (Time.current + Settings.user.authenticate.refresh_token.exp.days).to_i
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe Api::Admin::SessionsController, type: :request do
6
+ describe "POST #create" do
7
+ let!(:admin) {create :admin, email: "emailtest@gmail.com", password: "Aa@123456"}
8
+ let(:params) do
9
+ {
10
+ admin: {
11
+ email: "emailtest@gmail.com",
12
+ password: "Aa@123456"
13
+ }
14
+ }
15
+ end
16
+
17
+ before do
18
+ post api_admin_sign_in_path, params: params
19
+ end
20
+
21
+ context "when login success" do
22
+ it "should return status 200" do
23
+ expect(response.status).to eq 200
24
+ expect(json_response["success"]).to eq true
25
+ expect(json_response["data"]["access_token"].present?).to eq true
26
+ expect(json_response["data"]["refresh_token"].present?).to eq true
27
+ expect(json_response["data"]["admin"]["id"]).to eq admin.id
28
+ expect(json_response["data"]["admin"]["email"]).to eq "emailtest@gmail.com"
29
+ expect(admin.reload.devices.present?).to eq true
30
+ end
31
+ end
32
+
33
+ context "when invalid email or password" do
34
+ let(:params) do
35
+ {
36
+ admin: {
37
+ email: "emailtest@gmail.com",
38
+ password: "Aa@123456bb"
39
+ }
40
+ }
41
+ end
42
+
43
+ it "should return status 400" do
44
+ expect(response.status).to eq 400
45
+ expect(json_response["success"]).to eq false
46
+ expect(json_response["errors"][0]["code"]).to eq 1203
47
+ expect(json_response["errors"][0]["message"]).to eq "Invalid email or password"
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "POST #refresh" do
53
+ let(:admin) {create :admin}
54
+ let!(:device) {create :device, resourceable: admin}
55
+
56
+ let(:params) do
57
+ {
58
+ refresh_token: Api::V1::GenerateRefreshTokenService.new(device).execute
59
+ }
60
+ end
61
+
62
+ before do
63
+ post api_admin_refresh_path, params: params
64
+ end
65
+
66
+ context "when refresh token success" do
67
+ it "should return status 200" do
68
+ expect(response.status).to eq 200
69
+ expect(json_response["success"]).to eq true
70
+ expect(json_response["data"]["access_token"].present?).to eq true
71
+ expect(json_response["data"]["refresh_token"].present?).to eq true
72
+ expect(json_response["data"]["admin"]["id"]).to eq admin.id
73
+ expect(json_response["data"]["admin"]["email"]).to eq admin.email
74
+ end
75
+ end
76
+
77
+ context "when refresh token not correct" do
78
+ let(:params) do
79
+ {
80
+ refresh_token: JsonWebToken.encode({refresh_token: "not_correct"})
81
+ }
82
+ end
83
+
84
+ it "should return status 401" do
85
+ expect(response.status).to eq 401
86
+ expect(json_response["success"]).to eq false
87
+ expect(json_response["errors"][0]["code"]).to eq 1204
88
+ expect(json_response["errors"][0]["message"]).to eq "Invalid Token"
89
+ end
90
+ end
91
+
92
+ context "when refresh token expired" do
93
+ let(:params) do
94
+ {
95
+ refresh_token: JsonWebToken.encode({exp: (Time.current - 1.hour).to_i})
96
+ }
97
+ end
98
+
99
+ it "should return status 401" do
100
+ expect(response.status).to eq 401
101
+ expect(json_response["success"]).to eq false
102
+ expect(json_response["errors"][0]["code"]).to eq 1205
103
+ expect(json_response["errors"][0]["message"]).to eq "Token Expired"
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "POST #destroy" do
109
+ include_context "admin_logged_in"
110
+
111
+ before do
112
+ delete api_admin_logout_path, headers: headers
113
+ end
114
+
115
+ context "when logged out success" do
116
+ it "should return status 200" do
117
+ expect(response.status).to eq 200
118
+ expect(json_response["success"]).to eq true
119
+ expect(admin.devices.blank?).to eq true
120
+ end
121
+ end
122
+
123
+ include_examples :admin_authentication
124
+ end
125
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe Api::Admin::UsersController, type: :request do
6
+ describe "GET #index" do
7
+ include_context "admin_logged_in"
8
+ let!(:user_1) {create :user}
9
+ let!(:user_2) {create :user}
10
+ let!(:user_3) {create :user}
11
+
12
+ let(:params) do
13
+ {
14
+ page: 1,
15
+ items: 2
16
+ }
17
+ end
18
+
19
+ before do
20
+ get api_admin_users_path, headers: headers, params: params
21
+ end
22
+
23
+ context "when logged out success" do
24
+ it "should return status 200" do
25
+ expect(response.status).to eq 200
26
+ expect(json_response["success"]).to eq true
27
+ expect(json_response["data"]["users"].size).to eq 2
28
+ expect(json_response["data"]["users"][0]["id"]).to eq user_1.id
29
+ expect(json_response["data"]["users"][1]["id"]).to eq user_2.id
30
+ end
31
+ end
32
+
33
+ include_examples :admin_authentication
34
+ end
35
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe Api::V1::SessionsController, type: :request do
6
+ describe "POST #create" do
7
+ let!(:user) {create :user, email: "emailtest@gmail.com", password: "Aa@123456"}
8
+ let(:params) do
9
+ {
10
+ user: {
11
+ email: "emailtest@gmail.com",
12
+ password: "Aa@123456"
13
+ }
14
+ }
15
+ end
16
+
17
+ before do
18
+ post api_v1_sign_in_path, params: params
19
+ end
20
+
21
+ context "when login success" do
22
+ it "should return status 200" do
23
+ expect(response.status).to eq 200
24
+ expect(json_response["success"]).to eq true
25
+ expect(json_response["data"]["access_token"].present?).to eq true
26
+ expect(json_response["data"]["refresh_token"].present?).to eq true
27
+ expect(json_response["data"]["user"]["id"]).to eq user.id
28
+ expect(json_response["data"]["user"]["email"]).to eq "emailtest@gmail.com"
29
+ expect(user.reload.devices.present?).to eq true
30
+ end
31
+ end
32
+
33
+ context "when invalid email or password" do
34
+ let(:params) do
35
+ {
36
+ user: {
37
+ email: "emailtest@gmail.com",
38
+ password: "Aa@123456bb"
39
+ }
40
+ }
41
+ end
42
+
43
+ it "should return status 400" do
44
+ expect(response.status).to eq 400
45
+ expect(json_response["success"]).to eq false
46
+ expect(json_response["errors"][0]["code"]).to eq 1203
47
+ expect(json_response["errors"][0]["message"]).to eq "Invalid email or password"
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "POST #refresh" do
53
+ let(:user) {create :user}
54
+ let!(:device) {create :device, resourceable: user}
55
+
56
+ let(:params) do
57
+ {
58
+ refresh_token: Api::V1::GenerateRefreshTokenService.new(device).execute
59
+ }
60
+ end
61
+
62
+ before do
63
+ post api_v1_refresh_path, params: params
64
+ end
65
+
66
+ context "when refresh token success" do
67
+ it "should return status 200" do
68
+ expect(response.status).to eq 200
69
+ expect(json_response["success"]).to eq true
70
+ expect(json_response["data"]["access_token"].present?).to eq true
71
+ expect(json_response["data"]["refresh_token"].present?).to eq true
72
+ expect(json_response["data"]["user"]["id"]).to eq user.id
73
+ expect(json_response["data"]["user"]["email"]).to eq user.email
74
+ end
75
+ end
76
+
77
+ context "when refresh token not correct" do
78
+ let(:params) do
79
+ {
80
+ refresh_token: JsonWebToken.encode({refresh_token: "not_correct"})
81
+ }
82
+ end
83
+
84
+ it "should return status 401" do
85
+ expect(response.status).to eq 401
86
+ expect(json_response["success"]).to eq false
87
+ expect(json_response["errors"][0]["code"]).to eq 1204
88
+ expect(json_response["errors"][0]["message"]).to eq "Invalid Token"
89
+ end
90
+ end
91
+
92
+ context "when refresh token expired" do
93
+ let(:params) do
94
+ {
95
+ refresh_token: JsonWebToken.encode({exp: (Time.current - 1.hour).to_i})
96
+ }
97
+ end
98
+
99
+ it "should return status 401" do
100
+ expect(response.status).to eq 401
101
+ expect(json_response["success"]).to eq false
102
+ expect(json_response["errors"][0]["code"]).to eq 1205
103
+ expect(json_response["errors"][0]["message"]).to eq "Token Expired"
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "POST #destroy" do
109
+ include_context "user_logged_in"
110
+
111
+ before do
112
+ delete api_v1_logout_path, headers: headers
113
+ end
114
+
115
+ context "when logged out success" do
116
+ it "should return status 200" do
117
+ expect(response.status).to eq 200
118
+ expect(json_response["success"]).to eq true
119
+ expect(user.devices.blank?).to eq true
120
+ end
121
+ end
122
+
123
+ include_examples :user_authentication
124
+ end
125
+ end