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,57 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
code:
|
4
|
+
default: 1000
|
5
|
+
confirmation: 1001 # ActiveRecord Validation 1001 - 1049
|
6
|
+
accepted: 1002
|
7
|
+
blank: 1003
|
8
|
+
present: 1004
|
9
|
+
too_short: 1005
|
10
|
+
too_long: 1006
|
11
|
+
wrong_length: 1007
|
12
|
+
taken: 1008
|
13
|
+
invalid: 1009
|
14
|
+
inclusion: 1010
|
15
|
+
exclusion: 1011
|
16
|
+
required: 1012
|
17
|
+
not_a_number: 1013
|
18
|
+
greater_than: 1014
|
19
|
+
greater_than_or_equal_to: 1015
|
20
|
+
equal_to: 1016
|
21
|
+
less_than: 1017
|
22
|
+
less_than_or_equal_to: 1018
|
23
|
+
other_than: 1019
|
24
|
+
not_an_integer: 1020
|
25
|
+
odd: 1021
|
26
|
+
even: 1022
|
27
|
+
active_record: # Other ActiveRecord errors 1050 - 1199
|
28
|
+
not_unique:
|
29
|
+
code: 1050
|
30
|
+
message: Resource is existing.
|
31
|
+
not_found:
|
32
|
+
code: 1051
|
33
|
+
message: Resourse is not found.
|
34
|
+
params: # Request, Params, Controller, Action errors 1200 - 1299
|
35
|
+
invalid:
|
36
|
+
code: 1200
|
37
|
+
message: Invalid parameters.
|
38
|
+
route:
|
39
|
+
not_found:
|
40
|
+
code: 1299
|
41
|
+
message: Page not found.
|
42
|
+
action:
|
43
|
+
unauthorized:
|
44
|
+
code: 1201
|
45
|
+
message: Please log in.
|
46
|
+
not_allowed:
|
47
|
+
code: 1202
|
48
|
+
message: You are not allow to do this action
|
49
|
+
invalid_email:
|
50
|
+
code: 1203
|
51
|
+
message: Invalid email or password
|
52
|
+
invalid_token:
|
53
|
+
code: 1204
|
54
|
+
message: Invalid Token
|
55
|
+
token_expired:
|
56
|
+
code: 1205
|
57
|
+
message: Token Expired
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Rails.application.routes.draw do
|
4
|
+
namespace :api, format: :json do
|
5
|
+
namespace :v1 do
|
6
|
+
devise_for :users, skip: :all
|
7
|
+
post 'sign_in', to: 'sessions#create'
|
8
|
+
post 'refresh', to: 'sessions#refresh'
|
9
|
+
delete 'logout', to: 'sessions#destroy'
|
10
|
+
|
11
|
+
resources :users, only: :show
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :admin, format: :json do
|
15
|
+
devise_for :admins, skip: :all
|
16
|
+
post 'sign_in', to: 'sessions#create'
|
17
|
+
post 'refresh', to: 'sessions#refresh'
|
18
|
+
delete 'logout', to: 'sessions#destroy'
|
19
|
+
|
20
|
+
resources :users, only: :index
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/app-docs', to: redirect('/swagger/v1/app.html')
|
25
|
+
get '/admin-docs', to: redirect('/swagger/admin/admin.html')
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
pagy:
|
2
|
+
instances:
|
3
|
+
vars: vars
|
4
|
+
items_default: 30
|
5
|
+
page_default: 1
|
6
|
+
|
7
|
+
authorization:
|
8
|
+
access_token_type: Bearer
|
9
|
+
|
10
|
+
user:
|
11
|
+
authenticate:
|
12
|
+
access_token:
|
13
|
+
exp: 4 #hours
|
14
|
+
refresh_token:
|
15
|
+
exp: 30 #days
|
16
|
+
|
17
|
+
admin:
|
18
|
+
authenticate:
|
19
|
+
access_token:
|
20
|
+
exp: 4 #hours
|
21
|
+
refresh_token:
|
22
|
+
exp: 30 #days
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Api::Admin::SessionsController < Api::Admin::BaseController
|
4
|
+
skip_before_action :authorize_request!, only: %i[create refresh]
|
5
|
+
before_action :authorize_refresh_token_request!, only: :refresh
|
6
|
+
|
7
|
+
def create
|
8
|
+
raise Api::Error::Runtime, :invalid_email unless admin&.valid_password?(params[:admin][:password])
|
9
|
+
|
10
|
+
device = admin.devices.build admin_params.except(:email, :password)
|
11
|
+
refresh_token = Api::Admin::GenerateRefreshTokenService.new(device).execute
|
12
|
+
args = {resource: admin, refresh_token: refresh_token, device_id: device.id}
|
13
|
+
|
14
|
+
render_jsonapi Api::Admin::GenerateAccessTokenService.new(args).execute
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
current_admin.devices.delete_all
|
19
|
+
|
20
|
+
render_jsonapi({})
|
21
|
+
end
|
22
|
+
|
23
|
+
def refresh
|
24
|
+
refresh_token = Api::Admin::GenerateRefreshTokenService.new(current_device).execute
|
25
|
+
args = {resource: current_device.resourceable, refresh_token: refresh_token, device_id: current_device.id}
|
26
|
+
|
27
|
+
render_jsonapi Api::Admin::GenerateAccessTokenService.new(args).execute
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def admin
|
33
|
+
@admin ||= Admin.find_by email: params[:admin][:email]
|
34
|
+
end
|
35
|
+
|
36
|
+
def admin_params
|
37
|
+
params.require(:admin).permit(:email, :password, :platform)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Api::V1::SessionsController < Api::V1::BaseController
|
4
|
+
skip_before_action :authorize_request!, only: %i[create refresh]
|
5
|
+
before_action :authorize_refresh_token_request!, only: :refresh
|
6
|
+
|
7
|
+
def create
|
8
|
+
raise Api::Error::Runtime, :invalid_email unless user&.valid_password?(params[:user][:password])
|
9
|
+
|
10
|
+
device = user.devices.build user_params.except(:email, :password)
|
11
|
+
refresh_token = Api::V1::GenerateRefreshTokenService.new(device).execute
|
12
|
+
args = {resource: user, refresh_token: refresh_token, device_id: device.id}
|
13
|
+
|
14
|
+
render_jsonapi Api::V1::GenerateAccessTokenService.new(args).execute
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
current_user.devices.delete_all
|
19
|
+
|
20
|
+
render_jsonapi({})
|
21
|
+
end
|
22
|
+
|
23
|
+
def refresh
|
24
|
+
refresh_token = Api::V1::GenerateRefreshTokenService.new(current_device).execute
|
25
|
+
args = {resource: current_device.resourceable, refresh_token: refresh_token, device_id: current_device.id}
|
26
|
+
|
27
|
+
render_jsonapi Api::V1::GenerateAccessTokenService.new(args).execute
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def user
|
33
|
+
@user ||= User.find_by email: params[:user][:email]
|
34
|
+
end
|
35
|
+
|
36
|
+
def user_params
|
37
|
+
params.require(:user).permit(:email, :password, :platform)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ApplicationController < ActionController::API
|
4
|
+
include BaseConcern
|
5
|
+
|
6
|
+
before_action :authorize_request!
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
attr_reader :current_device
|
11
|
+
|
12
|
+
def authorize_request!
|
13
|
+
resource_type = request.path.split("/")[2] == "admin" ? "admin" : "user"
|
14
|
+
authorization_header = request.headers["Authorization"]
|
15
|
+
instance_variable_set "@current_#{resource_type}",
|
16
|
+
Api::AuthorizeRequestService.new(
|
17
|
+
authorization_header: authorization_header,
|
18
|
+
resource_type: resource_type
|
19
|
+
).perform
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize_refresh_token_request!
|
23
|
+
@current_device = Device.find_by(refresh_token: refresh_token)
|
24
|
+
raise JWT::DecodeError, :refresh_token_invalid unless current_device
|
25
|
+
end
|
26
|
+
|
27
|
+
def refresh_token
|
28
|
+
JsonWebToken.decode(params[:refresh_token])[:refresh_token]
|
29
|
+
end
|
30
|
+
end
|
Binary file
|
File without changes
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonRenderer
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class DataSanitizer
|
7
|
+
def initialize(object, options, api_version)
|
8
|
+
@object = object
|
9
|
+
@options = options
|
10
|
+
@root = options[:root]
|
11
|
+
@api_version = api_version
|
12
|
+
end
|
13
|
+
|
14
|
+
def sanitize
|
15
|
+
case object
|
16
|
+
when ActiveRecord::Relation, Array
|
17
|
+
@root ||= klass_name.tableize
|
18
|
+
{root => sanitized_array_data}
|
19
|
+
when Hash
|
20
|
+
root ? {root => sanitized_data} : sanitized_data
|
21
|
+
else
|
22
|
+
@root ||= klass_name.underscore
|
23
|
+
{root => sanitized_data}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :object, :options, :api_version, :root
|
30
|
+
|
31
|
+
def sanitized_data
|
32
|
+
@sanitized_data ||= serializer.new object, opts
|
33
|
+
end
|
34
|
+
|
35
|
+
def sanitized_array_data
|
36
|
+
@sanitized_array_data = ActiveModel::Serializer::CollectionSerializer.new(object, opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
def klass_name
|
40
|
+
@klass_name ||= (object.respond_to?(:klass) ? object.klass : object.class).name
|
41
|
+
end
|
42
|
+
|
43
|
+
def serializer
|
44
|
+
@serializer ||=
|
45
|
+
unless klass_name == Array.name
|
46
|
+
options[:serializer] || "Api::#{api_version}::#{klass_name}Serializer".constantize
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def opts
|
51
|
+
@opts ||= options.except(:success, :status, :meta, :root).merge namespace: "Api::#{api_version}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
included do
|
58
|
+
def render_jsonapi(object, options = {})
|
59
|
+
success = options.fetch :success, true
|
60
|
+
meta = options.fetch :meta, {}
|
61
|
+
status = options.fetch :status, :ok
|
62
|
+
data_serializer = DataSanitizer.new(object, options, api_version).sanitize
|
63
|
+
|
64
|
+
response_data = {
|
65
|
+
success: success,
|
66
|
+
data: data_serializer,
|
67
|
+
meta: meta
|
68
|
+
}
|
69
|
+
render json: response_data, status: status
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def api_version
|
74
|
+
@api_version ||= request.path.split("/")[2].upcase.capitalize
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pagination
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include Pagy::Backend
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
included do
|
10
|
+
def paginate(relation)
|
11
|
+
options = {page: page, items: items, outset: params[:outset]}
|
12
|
+
options[:count] = params[:count] if params[:count].to_i.positive?
|
13
|
+
|
14
|
+
pagy_info, records = pagy relation, options
|
15
|
+
[pagy_repsonse(pagy_info), records]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def pagy_repsonse(pagy)
|
22
|
+
pagy.instance_values.except Settings.pagy.instances.vars
|
23
|
+
end
|
24
|
+
|
25
|
+
def page
|
26
|
+
@page ||= params[:page].to_i < 1 ? Settings.pagy.page_default : params[:page]
|
27
|
+
end
|
28
|
+
|
29
|
+
def items
|
30
|
+
@items ||= params[:items].to_i < 1 ? Settings.pagy.items_default : params[:items]
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RescueException
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
rescue_from ActionController::ParameterMissing do |_error|
|
8
|
+
render_invalid_params_response
|
9
|
+
end
|
10
|
+
rescue_from(JWT::DecodeError, with: :render_jwt_invalid)
|
11
|
+
rescue_from(JWT::ExpiredSignature, with: :render_jwt_expired)
|
12
|
+
rescue_from(
|
13
|
+
ActiveRecord::RecordInvalid,
|
14
|
+
ActiveRecord::RecordNotDestroyed,
|
15
|
+
with: :render_unprocessable_entity_response
|
16
|
+
)
|
17
|
+
rescue_from ActiveRecord::RecordNotUnique, with: :render_existing_resource_response
|
18
|
+
rescue_from ActiveRecord::RecordNotFound, with: :render_resource_not_found_response
|
19
|
+
rescue_from(
|
20
|
+
Api::Error::Runtime,
|
21
|
+
with: :render_execute_failed_response
|
22
|
+
)
|
23
|
+
rescue_from ActionController::RoutingError, with: :render_routing_error_response
|
24
|
+
rescue_from Api::Error::ActionNotAllowed, with: :render_action_not_allowed_response
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def render_invalid_params_response(status: :bad_request)
|
29
|
+
error = Api::BaseError.new I18n.t("errors.params.invalid")
|
30
|
+
render json: error.to_hash, status: status
|
31
|
+
end
|
32
|
+
|
33
|
+
def render_unprocessable_entity_response(exception, status: :bad_request)
|
34
|
+
render json: ActiveRecordValidation::Error.new(exception.record).to_hash, status: status
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_existing_resource_response(_exception, status: :bad_request)
|
38
|
+
error = Api::BaseError.new I18n.t("errors.active_record.not_unique")
|
39
|
+
render json: error.to_hash, status: status
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_execute_failed_response(exception, status: :bad_request)
|
43
|
+
render json: exception.to_hash, status: status
|
44
|
+
end
|
45
|
+
|
46
|
+
def render_resource_not_found_response(exception, status: :not_found)
|
47
|
+
render json: Api::Error::RecordNotFound.new(exception).to_hash, status: status
|
48
|
+
end
|
49
|
+
|
50
|
+
def render_routing_error_response(_exception, status: :not_found)
|
51
|
+
error = Api::BaseError.new I18n.t("errors.route.not_found")
|
52
|
+
render json: error.to_hash, status: status
|
53
|
+
end
|
54
|
+
|
55
|
+
def doorkeeper_unauthorized_render_options(error: nil) # rubocop:disable Lint/UnusedMethodArgument
|
56
|
+
{json: Api::BaseError.new(I18n.t("errors.action.unauthorized")).to_hash}
|
57
|
+
end
|
58
|
+
|
59
|
+
def render_action_not_allowed_response(exception, status: :forbidden)
|
60
|
+
render json: Api::Error::ActionNotAllowed.new(exception).to_hash, status: status
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_jwt_invalid(_exception, status: :unauthorized)
|
64
|
+
error = Api::BaseError.new I18n.t("errors.action.invalid_token")
|
65
|
+
render json: error.to_hash, status: status
|
66
|
+
end
|
67
|
+
|
68
|
+
def render_jwt_expired(_exception, status: :unauthorized)
|
69
|
+
error = Api::BaseError.new I18n.t("errors.action.token_expired")
|
70
|
+
render json: error.to_hash, status: status
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
|
4
|
+
def change
|
5
|
+
create_table :users do |t|
|
6
|
+
## Database authenticatable
|
7
|
+
t.string :email, null: false, default: ''
|
8
|
+
t.string :encrypted_password, null: false, default: ''
|
9
|
+
t.datetime :deleted_at
|
10
|
+
|
11
|
+
## Recoverable
|
12
|
+
t.string :reset_password_token
|
13
|
+
t.datetime :reset_password_sent_at
|
14
|
+
|
15
|
+
## Rememberable
|
16
|
+
# t.datetime :remember_created_at
|
17
|
+
|
18
|
+
## Trackable
|
19
|
+
# t.integer :sign_in_count, default: 0, null: false
|
20
|
+
# t.datetime :current_sign_in_at
|
21
|
+
# t.datetime :last_sign_in_at
|
22
|
+
# t.string :current_sign_in_ip
|
23
|
+
# t.string :last_sign_in_ip
|
24
|
+
|
25
|
+
## Confirmable
|
26
|
+
# t.string :confirmation_token
|
27
|
+
# t.datetime :confirmed_at
|
28
|
+
# t.datetime :confirmation_sent_at
|
29
|
+
# t.string :unconfirmed_email # Only if using reconfirmable
|
30
|
+
|
31
|
+
## Lockable
|
32
|
+
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
33
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
34
|
+
# t.datetime :locked_at
|
35
|
+
|
36
|
+
t.timestamps null: false
|
37
|
+
end
|
38
|
+
|
39
|
+
add_index :users, :email, unique: true
|
40
|
+
add_index :users, :reset_password_token, unique: true
|
41
|
+
add_index :users, :deleted_at, unique: true
|
42
|
+
|
43
|
+
# add_index :users, :confirmation_token, unique: true
|
44
|
+
# add_index :users, :unlock_token, unique: true
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateDevices < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :devices do |t|
|
4
|
+
t.string :refresh_token
|
5
|
+
t.integer :platform, default: 0
|
6
|
+
t.references :resourceable, polymorphic: true
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :devices, :refresh_token, unique: true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreatePosts < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :posts do |t|
|
4
|
+
t.string :title
|
5
|
+
t.text :content
|
6
|
+
t.bigint :author_id, null: false
|
7
|
+
t.datetime :deleted_at
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :posts, :author_id, unique: true
|
13
|
+
add_index :posts, :deleted_at, unique: true
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class DeviseCreateAdmins < ActiveRecord::Migration[7.0]
|
4
|
+
def change
|
5
|
+
create_table :admins do |t|
|
6
|
+
## Database authenticatable
|
7
|
+
t.string :email, null: false, default: ""
|
8
|
+
t.string :encrypted_password, null: false, default: ""
|
9
|
+
|
10
|
+
## Recoverable
|
11
|
+
t.string :reset_password_token
|
12
|
+
t.datetime :reset_password_sent_at
|
13
|
+
t.datetime :deleted_at
|
14
|
+
## Rememberable
|
15
|
+
#t.datetime :remember_created_at
|
16
|
+
|
17
|
+
## Trackable
|
18
|
+
# t.integer :sign_in_count, default: 0, null: false
|
19
|
+
# t.datetime :current_sign_in_at
|
20
|
+
# t.datetime :last_sign_in_at
|
21
|
+
# t.string :current_sign_in_ip
|
22
|
+
# t.string :last_sign_in_ip
|
23
|
+
|
24
|
+
## Confirmable
|
25
|
+
# t.string :confirmation_token
|
26
|
+
# t.datetime :confirmed_at
|
27
|
+
# t.datetime :confirmation_sent_at
|
28
|
+
# t.string :unconfirmed_email # Only if using reconfirmable
|
29
|
+
|
30
|
+
## Lockable
|
31
|
+
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
32
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
33
|
+
# t.datetime :locked_at
|
34
|
+
|
35
|
+
|
36
|
+
t.timestamps null: false
|
37
|
+
end
|
38
|
+
|
39
|
+
add_index :admins, :email, unique: true
|
40
|
+
add_index :admins, :reset_password_token, unique: true
|
41
|
+
add_index :admins, :deleted_at, unique: true
|
42
|
+
|
43
|
+
# add_index :admins, :confirmation_token, unique: true
|
44
|
+
# add_index :admins, :unlock_token, unique: true
|
45
|
+
end
|
46
|
+
end
|
data/lib/db/schema.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
6
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
9
|
+
# migrations use external dependencies or application code.
|
10
|
+
#
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
12
|
+
|
13
|
+
ActiveRecord::Schema[7.0].define(version: 2023_03_03_165318) do
|
14
|
+
create_table "admins", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
15
|
+
t.string "email", default: "", null: false
|
16
|
+
t.string "encrypted_password", default: "", null: false
|
17
|
+
t.string "reset_password_token"
|
18
|
+
t.datetime "reset_password_sent_at"
|
19
|
+
t.datetime "deleted_at"
|
20
|
+
t.datetime "created_at", null: false
|
21
|
+
t.datetime "updated_at", null: false
|
22
|
+
t.index ["deleted_at"], name: "index_admins_on_deleted_at", unique: true
|
23
|
+
t.index ["email"], name: "index_admins_on_email", unique: true
|
24
|
+
t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true
|
25
|
+
end
|
26
|
+
|
27
|
+
create_table "devices", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
28
|
+
t.string "refresh_token"
|
29
|
+
t.integer "platform", default: 0
|
30
|
+
t.string "resourceable_type"
|
31
|
+
t.bigint "resourceable_id"
|
32
|
+
t.datetime "created_at", null: false
|
33
|
+
t.datetime "updated_at", null: false
|
34
|
+
t.index ["refresh_token"], name: "index_devices_on_refresh_token", unique: true
|
35
|
+
t.index ["resourceable_type", "resourceable_id"], name: "index_devices_on_resourceable"
|
36
|
+
end
|
37
|
+
|
38
|
+
create_table "posts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
39
|
+
t.string "title"
|
40
|
+
t.text "content"
|
41
|
+
t.bigint "author_id", null: false
|
42
|
+
t.datetime "deleted_at"
|
43
|
+
t.datetime "created_at", null: false
|
44
|
+
t.datetime "updated_at", null: false
|
45
|
+
t.index ["author_id"], name: "index_posts_on_author_id", unique: true
|
46
|
+
t.index ["deleted_at"], name: "index_posts_on_deleted_at", unique: true
|
47
|
+
end
|
48
|
+
|
49
|
+
create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
50
|
+
t.string "email", default: "", null: false
|
51
|
+
t.string "encrypted_password", default: "", null: false
|
52
|
+
t.datetime "deleted_at"
|
53
|
+
t.string "reset_password_token"
|
54
|
+
t.datetime "reset_password_sent_at"
|
55
|
+
t.datetime "created_at", null: false
|
56
|
+
t.datetime "updated_at", null: false
|
57
|
+
t.index ["deleted_at"], name: "index_users_on_deleted_at", unique: true
|
58
|
+
t.index ["email"], name: "index_users_on_email", unique: true
|
59
|
+
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|