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,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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::BaseController < ApplicationController
4
+ attr_reader :current_admin
5
+ end
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::Admin::UsersController < Api::Admin::BaseController
4
+ def index
5
+ meta, users = paginate(User.all)
6
+
7
+ render_jsonapi users, type: :user_list, meta: meta
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::BaseController < ApplicationController
4
+ attr_reader :current_user
5
+ 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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Api::V1::UsersController < Api::V1::BaseController
4
+ def show
5
+ render_jsonapi current_user, type: :user_details
6
+ end
7
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaseConcern
4
+ extend ActiveSupport::Concern
5
+
6
+ include JsonRenderer
7
+ include RescueException
8
+ include Pagination
9
+ end
@@ -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
data/lib/db/seeds.rb ADDED
@@ -0,0 +1,7 @@
1
+ # Create user
2
+ 5.times do |index|
3
+ User.create email: "user1#{index}@gmail.vn", password: "Aa@123456"
4
+ end
5
+
6
+ # Create Admin
7
+ Admin.create email: "admin@gmail.vn", password: "Aa@123456"