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
|