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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +49 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/.env +4 -0
- data/lib/.rspec +1 -0
- data/lib/.rubocop.yml +288 -0
- data/lib/.rubocop_disabled.yml +31 -0
- data/lib/.rubocop_enabled.yml +0 -0
- data/lib/Capfile +46 -0
- data/lib/Gemfile +51 -0
- data/lib/config/database.yml +24 -0
- data/lib/config/deploy/development.rb +85 -0
- data/lib/config/deploy/production.rb +63 -0
- data/lib/config/deploy/staging.rb +56 -0
- data/lib/config/deploy.rb +7 -0
- data/lib/config/initializers/devise.rb +315 -0
- data/lib/config/locales/devise.en.yml +65 -0
- data/lib/config/locales/en.yml +33 -0
- data/lib/config/locales/errors.en.yml +57 -0
- data/lib/config/routes.rb +26 -0
- data/lib/config/settings.yml +22 -0
- data/lib/controllers/api/admin/base_controller.rb +5 -0
- data/lib/controllers/api/admin/sessions_controller.rb +39 -0
- data/lib/controllers/api/admin/users_controller.rb +9 -0
- data/lib/controllers/api/v1/base_controller.rb +5 -0
- data/lib/controllers/api/v1/sessions_controller.rb +39 -0
- data/lib/controllers/api/v1/users_controller.rb +7 -0
- data/lib/controllers/application_controller.rb +30 -0
- data/lib/controllers/concerns/.DS_Store +0 -0
- data/lib/controllers/concerns/.keep +0 -0
- data/lib/controllers/concerns/base_concern.rb +9 -0
- data/lib/controllers/concerns/json_renderer.rb +76 -0
- data/lib/controllers/concerns/pagination.rb +32 -0
- data/lib/controllers/concerns/rescue_exception.rb +73 -0
- data/lib/db/migrate/20220721091426_devise_create_users.rb +46 -0
- data/lib/db/migrate/20230113072522_create_devices.rb +13 -0
- data/lib/db/migrate/20230227135020_create_posts.rb +15 -0
- data/lib/db/migrate/20230303165318_devise_create_admins.rb +46 -0
- data/lib/db/schema.rb +62 -0
- data/lib/db/seeds.rb +7 -0
- data/lib/generators/n_base_rails/install_generator.rb +42 -0
- data/lib/lib/.DS_Store +0 -0
- data/lib/lib/active_record_validation/error.rb +33 -0
- data/lib/lib/api/error.rb +63 -0
- data/lib/lib/json_web_token.rb +13 -0
- data/lib/log/.keep +0 -0
- data/lib/log/capistrano.log +28367 -0
- data/lib/log/development.log +30201 -0
- data/lib/log/test.log +11768 -0
- data/lib/models/admin.rb +10 -0
- data/lib/models/application_record.rb +5 -0
- data/lib/models/concerns/.keep +0 -0
- data/lib/models/device.rb +11 -0
- data/lib/models/post.rb +5 -0
- data/lib/models/user.rb +9 -0
- data/lib/n_base_rails/version.rb +5 -0
- data/lib/n_base_rails.rb +9 -0
- data/lib/public/404.html +67 -0
- data/lib/public/422.html +67 -0
- data/lib/public/500.html +66 -0
- data/lib/public/apple-touch-icon-precomposed.png +0 -0
- data/lib/public/apple-touch-icon.png +0 -0
- data/lib/public/docs/api/admin/definitions/users.yaml +15 -0
- data/lib/public/docs/api/admin/paths/index.yaml +29 -0
- data/lib/public/docs/api/admin/paths/sessions.yaml +121 -0
- data/lib/public/docs/api/admin/paths/users.yaml +39 -0
- data/lib/public/docs/api/shared/meta_infos.yaml +41 -0
- data/lib/public/docs/api/shared/unauthorized_response.yaml +31 -0
- data/lib/public/docs/api/v1/definitions/users.yaml +13 -0
- data/lib/public/docs/api/v1/paths/example.yaml +431 -0
- data/lib/public/docs/api/v1/paths/index.yaml +28 -0
- data/lib/public/docs/api/v1/paths/sessions.yaml +121 -0
- data/lib/public/docs/api/v1/paths/users.yaml +24 -0
- data/lib/public/favicon.ico +0 -0
- data/lib/public/robots.txt +1 -0
- data/lib/public/swagger/admin/admin-swagger-initializer.js +24 -0
- data/lib/public/swagger/admin/admin.html +19 -0
- data/lib/public/swagger/favicon-16x16.png +0 -0
- data/lib/public/swagger/favicon-32x32.png +0 -0
- data/lib/public/swagger/index.css +16 -0
- data/lib/public/swagger/oauth2-redirect.html +79 -0
- data/lib/public/swagger/swagger-ui-bundle.js +3 -0
- data/lib/public/swagger/swagger-ui-bundle.js.map +1 -0
- data/lib/public/swagger/swagger-ui-es-bundle-core.js +2 -0
- data/lib/public/swagger/swagger-ui-es-bundle-core.js.map +1 -0
- data/lib/public/swagger/swagger-ui-es-bundle.js +3 -0
- data/lib/public/swagger/swagger-ui-es-bundle.js.map +1 -0
- data/lib/public/swagger/swagger-ui-standalone-preset.js +3 -0
- data/lib/public/swagger/swagger-ui-standalone-preset.js.map +1 -0
- data/lib/public/swagger/swagger-ui.css +4 -0
- data/lib/public/swagger/swagger-ui.css.map +1 -0
- data/lib/public/swagger/swagger-ui.js +2 -0
- data/lib/public/swagger/swagger-ui.js.map +1 -0
- data/lib/public/swagger/v1/app.html +19 -0
- data/lib/public/swagger/v1/swagger-initializer.js +25 -0
- data/lib/serializers/.DS_Store +0 -0
- data/lib/serializers/action_not_allowed_serializer.rb +18 -0
- data/lib/serializers/api/.DS_Store +0 -0
- data/lib/serializers/api/admin/base_serializer.rb +14 -0
- data/lib/serializers/api/admin/hash_serializer.rb +22 -0
- data/lib/serializers/api/admin/user_serializer.rb +9 -0
- data/lib/serializers/api/v1/base_serializer.rb +14 -0
- data/lib/serializers/api/v1/hash_serializer.rb +22 -0
- data/lib/serializers/api/v1/user_serializer.rb +9 -0
- data/lib/serializers/record_not_found_serializer.rb +28 -0
- data/lib/serializers/validation_error_serializer.rb +45 -0
- data/lib/services/api/admin/generate_access_token_service.rb +34 -0
- data/lib/services/api/admin/generate_refresh_token_service.rb +24 -0
- data/lib/services/api/authorize_request_service.rb +35 -0
- data/lib/services/api/v1/generate_access_token_service.rb +34 -0
- data/lib/services/api/v1/generate_refresh_token_service.rb +24 -0
- data/lib/spec/controllers/api/admin/sessions_controller_spec.rb +125 -0
- data/lib/spec/controllers/api/admin/users_controller_spec.rb +35 -0
- data/lib/spec/controllers/api/v1/sessions_controller_spec.rb +125 -0
- data/lib/spec/controllers/api/v1/users_controller_spec.rb +23 -0
- data/lib/spec/factories/admins.rb +8 -0
- data/lib/spec/factories/devices.rb +7 -0
- data/lib/spec/factories/posts.rb +6 -0
- data/lib/spec/factories/users.rb +8 -0
- data/lib/spec/helpers/request_helpers.rb +7 -0
- data/lib/spec/models/admin_spec.rb +9 -0
- data/lib/spec/models/device_spec.rb +13 -0
- data/lib/spec/models/post_spec.rb +6 -0
- data/lib/spec/models/user_spec.rb +9 -0
- data/lib/spec/rails_helper.rb +66 -0
- data/lib/spec/serializers/api/admin/user_serializer.rb +20 -0
- data/lib/spec/serializers/api/v1/user_serializer.rb +20 -0
- data/lib/spec/spec_helper.rb +94 -0
- data/lib/spec/supports/shared_context.rb +19 -0
- data/lib/spec/supports/shared_example/admin_authentication.rb +47 -0
- data/lib/spec/supports/shared_example/user_authentication.rb +47 -0
- 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,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,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
|