next_on_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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +591 -0
  4. data/Rakefile +32 -0
  5. data/app/controllers/next_on_rails/application_controller.rb +21 -0
  6. data/app/controllers/next_on_rails/devise_token_auth_override/concerns/current_resource_serializer.rb +15 -0
  7. data/app/controllers/next_on_rails/devise_token_auth_override/confirmations_controller.rb +4 -0
  8. data/app/controllers/next_on_rails/devise_token_auth_override/omniauth_callbacks_controller.rb +7 -0
  9. data/app/controllers/next_on_rails/devise_token_auth_override/passwords_controller.rb +23 -0
  10. data/app/controllers/next_on_rails/devise_token_auth_override/registrations_controller.rb +33 -0
  11. data/app/controllers/next_on_rails/devise_token_auth_override/sessions_controller.rb +27 -0
  12. data/app/controllers/next_on_rails/devise_token_auth_override/token_validations_controller.rb +13 -0
  13. data/app/controllers/next_on_rails/devise_token_auth_override/unlocks_controller.rb +23 -0
  14. data/app/controllers/next_on_rails/merger_controller.rb +36 -0
  15. data/app/serializers/next_on_rails/active_model_errors_serializer.rb +45 -0
  16. data/app/serializers/next_on_rails/errors_serializer.rb +16 -0
  17. data/config/routes.rb +12 -0
  18. data/lib/generators/nor/backend/backend_generator.rb +129 -0
  19. data/lib/generators/nor/backend/templates/Procfile +2 -0
  20. data/lib/generators/nor/backend/templates/application_controller.rb +2 -0
  21. data/lib/generators/nor/backend/templates/cors.rb +23 -0
  22. data/lib/generators/nor/backend/templates/current_user_serializer.rb.tt +8 -0
  23. data/lib/generators/nor/backend/templates/user.rb.tt +8 -0
  24. data/lib/generators/nor/backend/templates/user_migration.rb.tt +53 -0
  25. data/lib/generators/nor/backend/templates/user_serializer.rb.tt +11 -0
  26. data/lib/generators/nor/frontend/frontend_generator.rb +60 -0
  27. data/lib/generators/nor/frontend/templates/frontend/components/flash.js +29 -0
  28. data/lib/generators/nor/frontend/templates/frontend/components/inputs.js +69 -0
  29. data/lib/generators/nor/frontend/templates/frontend/components/login-form.js +23 -0
  30. data/lib/generators/nor/frontend/templates/frontend/components/registration-form.js +49 -0
  31. data/lib/generators/nor/frontend/templates/frontend/next-on-rails.config.js +3 -0
  32. data/lib/generators/nor/frontend/templates/frontend/next.config.js +20 -0
  33. data/lib/generators/nor/frontend/templates/frontend/pages/_app.js +3 -0
  34. data/lib/generators/nor/frontend/templates/frontend/pages/index.js +57 -0
  35. data/lib/generators/nor/frontend/templates/frontend/server.js +31 -0
  36. data/lib/generators/nor/frontend/templates/frontend/stylesheets/application.scss +2 -0
  37. data/lib/generators/nor/install/USAGE +30 -0
  38. data/lib/generators/nor/install/install_generator.rb +8 -0
  39. data/lib/generators/nor/scaffold/USAGE +10 -0
  40. data/lib/generators/nor/scaffold/scaffold_generator.rb +53 -0
  41. data/lib/generators/nor/scaffold/templates/controller.rb.tt +40 -0
  42. data/lib/generators/nor/scaffold/templates/frontend/components/details.js.tt +20 -0
  43. data/lib/generators/nor/scaffold/templates/frontend/components/form.js.tt +17 -0
  44. data/lib/generators/nor/scaffold/templates/frontend/pages/crud.js.tt +123 -0
  45. data/lib/generators/nor/scaffold/templates/frontend/pages/edit.js.tt +55 -0
  46. data/lib/generators/nor/scaffold/templates/frontend/pages/index.js.tt +88 -0
  47. data/lib/generators/nor/scaffold/templates/frontend/pages/new.js.tt +51 -0
  48. data/lib/generators/nor/scaffold/templates/frontend/pages/show.js.tt +43 -0
  49. data/lib/next_on_rails.rb +12 -0
  50. data/lib/next_on_rails/engine.rb +5 -0
  51. data/lib/next_on_rails/version.rb +3 -0
  52. data/lib/tasks/next_on_rails_tasks.rake +4 -0
  53. metadata +235 -0
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'NextOnRails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -0,0 +1,21 @@
1
+ module NextOnRails
2
+ class ApplicationController < ActionController::API
3
+ include DeviseTokenAuth::Concerns::SetUserByToken
4
+
5
+ # rescue_from CanCan::AccessDenied do |_exception|
6
+ # head :forbidden
7
+ # end
8
+
9
+ protected
10
+
11
+ def render_resource(resource, serializer_options = {}, render_options = {})
12
+ serializer = serializer_options.delete(:serializer) || "#{resource.model_name}Serializer"
13
+ serializer = serializer.classify.constantize
14
+ if resource.errors.empty?
15
+ render json: serializer.new(resource, **serializer_options), **render_options
16
+ else
17
+ render json: ActiveModelErrorsSerializer.new(resource), status: :unprocessable_entity
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module NextOnRails
2
+ module DeviseTokenAuthOverride
3
+ module Concerns
4
+ module CurrentResourceSerializer
5
+ extend ActiveSupport::Concern
6
+
7
+ private
8
+
9
+ def current_resource_serializer(resource)
10
+ "Current#{resource.class}Serializer".constantize
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::ConfirmationsController < DeviseTokenAuth::ConfirmationsController
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController
3
+ def omniauth_failure
4
+ render json: params[:message] || 'An error occurred', status: :unprocessable_entity
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::PasswordsController < DeviseTokenAuth::PasswordsController
3
+ def render_create_success
4
+ head :ok
5
+ end
6
+
7
+ def render_update_success
8
+ head :ok
9
+ end
10
+
11
+ def render_create_error
12
+ render json: ActiveModelErrorsSerializer.new(@resource), status: :unprocessable_entity
13
+ end
14
+
15
+ def render_update_error
16
+ render json: ActiveModelErrorsSerializer.new(@resource), status: :unprocessable_entity
17
+ end
18
+
19
+ def render_error(status, message, _data = nil)
20
+ render json: ErrorsSerializer.new(message), status: status
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::RegistrationsController < DeviseTokenAuth::RegistrationsController
3
+ include DeviseTokenAuthOverride::Concerns::CurrentResourceSerializer
4
+
5
+ def render_create_success
6
+ render json: current_resource_serializer(@resource).new(@resource), status: :created
7
+ end
8
+
9
+ def render_create_error
10
+ render json: ActiveModelErrorsSerializer.new(@resource), status: :unprocessable_entity
11
+ end
12
+
13
+ def render_update_success
14
+ render json: current_resource_serializer(@resource).new(@resource), status: :ok
15
+ end
16
+
17
+ def render_update_error
18
+ render json: ActiveModelErrorsSerializer.new(@resource), status: :unprocessable_entity
19
+ end
20
+
21
+ def render_error(status, message, _data = nil)
22
+ render json: ErrorsSerializer.new(message), status: status
23
+ end
24
+
25
+ def sign_up_params
26
+ params.permit(:email, :password, :password_confirmation)
27
+ end
28
+
29
+ def account_update_params
30
+ params.permit(:email, :password, :password_confirmation, :current_password, :username)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::SessionsController < DeviseTokenAuth::SessionsController
3
+ include DeviseTokenAuthOverride::Concerns::CurrentResourceSerializer
4
+
5
+ def render_new_error
6
+ head :method_not_allowed
7
+ end
8
+
9
+ def render_create_success
10
+ render json: current_resource_serializer(@resource).new(@resource), status: :ok
11
+ end
12
+
13
+ def render_destroy_success
14
+ head :ok
15
+ end
16
+
17
+ def render_error(status, message, _data = nil)
18
+ render json: ErrorsSerializer.new(message), status: status
19
+ end
20
+
21
+ private
22
+
23
+ def resource_params
24
+ params.permit(:email, :password)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::TokenValidationsController < DeviseTokenAuth::TokenValidationsController
3
+ include DeviseTokenAuthOverride::Concerns::CurrentResourceSerializer
4
+
5
+ def render_validate_token_success
6
+ render json: current_resource_serializer(@resource).new(@resource), status: :ok
7
+ end
8
+
9
+ def render_error(status, message, _data = nil)
10
+ render json: ErrorsSerializer.new(message), status: status
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module NextOnRails
2
+ class DeviseTokenAuthOverride::UnlocksController < DeviseTokenAuth::UnlocksController
3
+ def render_create_success
4
+ head :ok
5
+ end
6
+
7
+ def render_create_error
8
+ render json: ActiveModelErrorsSerializer.new(@resource), status: :unprocessable_entity
9
+ end
10
+
11
+ def render_error(status, message, _data = nil)
12
+ render json: ErrorsSerializer.new(message), status: status
13
+ end
14
+
15
+ private
16
+
17
+ # Hope in this issue:
18
+ # https://github.com/lynndylanhurley/devise_token_auth/issues/1274
19
+ def after_unlock_path_for(_resource)
20
+ DeviseTokenAuth.default_confirm_success_url
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ module NextOnRails
2
+ class MergerController < ApplicationController
3
+ rescue_from NameError do
4
+ head :bad_request
5
+ end
6
+
7
+ def merge
8
+ json = {}
9
+ resources.each do |resource, _params|
10
+ json[resource] = "$$$#{resource}$$$"
11
+ end
12
+ json = { merge: json }.to_json
13
+ resources.each do |resource, params|
14
+ response_string_json = response_from_controller(resource, params)
15
+ json.gsub!("\"$$$#{resource}$$$\"", response_string_json)
16
+ end
17
+ render json: json
18
+ end
19
+
20
+ private
21
+
22
+ def response_from_controller(resource_name, resource_params)
23
+ action = resource_name == resource_name.singularize ? :show : :index
24
+ controller = "#{resource_name.classify.pluralize}Controller".constantize.new
25
+ controller.params = resource_params
26
+ return { data: {} }.to_json if action == :show && resource_params[:id].blank?
27
+
28
+ controller.dispatch(action, request, ActionDispatch::Response.new)
29
+ return controller.response.body
30
+ end
31
+
32
+ def resources
33
+ params.require(:resources).permit!
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ module NextOnRails
2
+ class ActiveModelErrorsSerializer
3
+ def initialize(model)
4
+ @model = model
5
+ end
6
+
7
+ def serializable_hash
8
+ i = -1
9
+ full_messages = @model.errors.full_messages
10
+ errors = @model.errors.messages.map do |field, error_messages|
11
+ error_messages.map do |error_message|
12
+ i += 1
13
+ {
14
+ title: error_message,
15
+ detail: full_messages[i],
16
+ attribute: field,
17
+ source: { pointer: "/data/attributes/#{field}" }
18
+ }
19
+ end
20
+ end
21
+ @model.class.reflect_on_all_associations.each do |relationship|
22
+ Array.wrap(@model.send(relationship.name)).each_with_index do |child, index|
23
+ i = -1
24
+ full_messages = @model.errors.full_messages
25
+ errors << child.errors.messages.map do |field, error_messages|
26
+ error_messages.map do |error_message|
27
+ i += 1
28
+ {
29
+ title: error_message,
30
+ detail: full_messages[i],
31
+ attribute: "#{child.model_name.plural}[#{index}].#{field}",
32
+ source: { pointer: "/data/attributes/#{child.model_name.plural}[#{index}].#{field}" }
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ return { errors: errors.flatten, hash_errors: @model.errors.as_json }
39
+ end
40
+
41
+ def to_json(options = nil)
42
+ self.serializable_hash.to_json(options)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,16 @@
1
+ module NextOnRails
2
+ class ErrorsSerializer
3
+ def initialize(*messages)
4
+ @messages = messages
5
+ end
6
+
7
+ def serializable_hash
8
+ # return { errors: [{ detail: @message }] }
9
+ return { errors: @messages.map { |message| { detail: message } } }
10
+ end
11
+
12
+ def to_json(options = nil)
13
+ self.serializable_hash.to_json(options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ NextOnRails::Engine.routes.draw do
2
+ # mount_devise_token_auth_for 'User', at: 'auth', controllers: {
3
+ # confirmations: 'next_on_rails/devise_token_auth_override/confirmations',
4
+ # omniauth_callbacks: 'next_on_rails/devise_token_auth_override/omniauth_callbacks',
5
+ # passwords: 'next_on_rails/devise_token_auth_override/passwords',
6
+ # registrations: 'next_on_rails/devise_token_auth_override/registrations',
7
+ # sessions: 'next_on_rails/devise_token_auth_override/sessions',
8
+ # token_validations: 'next_on_rails/devise_token_auth_override/token_validations',
9
+ # unlocks: 'next_on_rails/devise_token_auth_override/unlocks'
10
+ # }
11
+ get :merge, to: 'merger#merge'
12
+ end
@@ -0,0 +1,129 @@
1
+ module Nor
2
+ class BackendGenerator < Rails::Generators::Base
3
+ include Rails::Generators::Migration
4
+
5
+ attr_reader :user_class, :mount_path
6
+
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def initialize(args, *options)
10
+ raise 'Next On Rails can be installed only on a Rails API app! Please create a new app with `rails new APPNAME --api`' unless rails_api?
11
+
12
+ super
13
+ @user_class = args[0] || 'User'
14
+ @mount_path = args[1] || 'auth'
15
+ end
16
+
17
+ def install_user
18
+ model_file = "app/models/#{user_class.singularize.gsub('::', '').underscore}.rb"
19
+ template 'user.rb', model_file unless File.exist?(model_file)
20
+
21
+ migration_file = "devise_token_auth_create_#{user_class.pluralize.gsub('::', '').underscore}"
22
+ migration_template 'user_migration.rb', File.join('db', 'migrate', "#{migration_file}.rb") unless self.class.migration_exists?('db/migrate', migration_file)
23
+ end
24
+
25
+ def install_devise_token_auth
26
+ generate 'devise_token_auth:install', @user_class, @mount_path
27
+ config = <<~CONFIG
28
+
29
+ \s\s# Configure default URLs and redirects
30
+ \s\sconfig.default_confirm_success_url = 'http://localhost:3001/'
31
+ \s\sconfig.default_password_reset_url = 'http://localhost:3001/change-password'
32
+ \s\sconfig.redirect_whitelist = ['http://localhost:3001/*']
33
+
34
+ \s\s# If config.check_current_password_before_update is set to :attributes the
35
+ \s\s# current_password param is checked before any update, if it is set to
36
+ \s\s# :password the current_password param is checked only if the request
37
+ \s\s# updates user password. Default current_password is never checked.
38
+ \s\sconfig.check_current_password_before_update = :password
39
+ CONFIG
40
+ insert_into_file 'config/initializers/devise_token_auth.rb', config, before: /end$/
41
+ end
42
+
43
+ def install_routes
44
+ custom_routes = <<~ROUTES
45
+ , controllers: {
46
+ confirmations: 'next_on_rails/devise_token_auth_override/confirmations',
47
+ omniauth_callbacks: 'next_on_rails/devise_token_auth_override/omniauth_callbacks',
48
+ passwords: 'next_on_rails/devise_token_auth_override/passwords',
49
+ registrations: 'next_on_rails/devise_token_auth_override/registrations',
50
+ sessions: 'next_on_rails/devise_token_auth_override/sessions',
51
+ token_validations: 'next_on_rails/devise_token_auth_override/token_validations',
52
+ unlocks: 'next_on_rails/devise_token_auth_override/unlocks'
53
+ }
54
+ mount NextOnRails::Engine => '/'
55
+ ROUTES
56
+ insert_into_file 'config/routes.rb', custom_routes, after: "mount_devise_token_auth_for '#{@user_class}', at: '#{@mount_path}'"
57
+ end
58
+
59
+ def install_application_controller
60
+ remove_file 'app/controllers/application_controller.rb'
61
+ template 'application_controller.rb', 'app/controllers/application_controller.rb'
62
+ end
63
+
64
+ def install_devise_config
65
+ template File.join(Gem.loaded_specs['devise'].full_gem_path, 'lib/generators/templates/devise.rb'), 'config/initializers/devise.rb'
66
+ gsub_file 'config/initializers/devise.rb', "require 'devise/orm/'", "# require 'devise/orm/'" if File.exist?('config/initializers/devise.rb')
67
+ end
68
+
69
+ def install_cors_config
70
+ config = <<~CONFIG
71
+ Rails.application.config.middleware.insert_before 0, Rack::Cors do
72
+ allow do
73
+ origins 'localhost:3001'
74
+
75
+ resource '*',
76
+ headers: :any,
77
+ methods: [:get, :post, :put, :patch, :delete, :options, :head],
78
+ expose: [
79
+ DeviseTokenAuth.headers_names[:'access-token'],
80
+ DeviseTokenAuth.headers_names[:client],
81
+ DeviseTokenAuth.headers_names[:expiry],
82
+ DeviseTokenAuth.headers_names[:uid],
83
+ DeviseTokenAuth.headers_names[:'token-type']
84
+ ]
85
+ end
86
+ end
87
+ CONFIG
88
+ append_to_file 'config/initializers/cors.rb', config
89
+ end
90
+
91
+ def install_user_serializer
92
+ template 'user_serializer.rb', "app/serializers/#{@user_class.underscore}_serializer.rb"
93
+ template 'current_user_serializer.rb', "app/serializers/current_#{@user_class.underscore}_serializer.rb"
94
+ end
95
+
96
+ def remove_wrap_parameters
97
+ gsub_file 'config/initializers/wrap_parameters.rb', 'wrap_parameters format: [:json]', 'wrap_parameters format: []'
98
+ end
99
+
100
+ def setup_gems
101
+ gem_group :development do
102
+ gem 'foreman'
103
+ gem 'letter_opener'
104
+ end
105
+ template 'Procfile'
106
+ config = <<~CONFIG
107
+
108
+ \s\s# Mailer setup
109
+ \s\sconfig.action_mailer.preview_path = Rails.root.join('test', 'mailers', 'previews')
110
+ \s\sconfig.action_mailer.delivery_method = :letter_opener
111
+ \s\sconfig.action_mailer.raise_delivery_errors = true
112
+ \s\sconfig.action_mailer.default_url_options = { host: 'http://localhost:3000' }
113
+ CONFIG
114
+ insert_into_file 'config/environments/development.rb', config, before: /end$/
115
+ end
116
+
117
+ def self.next_migration_number(_path)
118
+ Time.zone.now.utc.strftime('%Y%m%d%H%M%S')
119
+ end
120
+
121
+ protected
122
+
123
+ def rails_api?
124
+ filename = 'config/application.rb'
125
+ str = 'config.api_only = true'
126
+ str.in?(File.read(filename))
127
+ end
128
+ end
129
+ end