ibrain-core 0.1.0

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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +75 -0
  4. data/Rakefile +7 -0
  5. data/app/controllers/concerns/ibrain_errors.rb +23 -0
  6. data/app/controllers/concerns/ibrain_handler.rb +42 -0
  7. data/app/controllers/ibrain/base_controller.rb +28 -0
  8. data/app/controllers/ibrain/graphql_controller.rb +55 -0
  9. data/app/graphql/ibrain/base_schema.rb +52 -0
  10. data/app/graphql/ibrain/extentions/default_value.rb +15 -0
  11. data/app/graphql/ibrain/interfaces/base_interface.rb +5 -0
  12. data/app/graphql/ibrain/interfaces/person_interface.rb +15 -0
  13. data/app/graphql/ibrain/interfaces/record_interface.rb +10 -0
  14. data/app/graphql/ibrain/lazy/base.rb +8 -0
  15. data/app/graphql/ibrain/loaders/association_loader.rb +61 -0
  16. data/app/graphql/ibrain/mutations/base_mutation.rb +35 -0
  17. data/app/graphql/ibrain/policies/base_policy.rb +45 -0
  18. data/app/graphql/ibrain/policies/graphql_policy.rb +8 -0
  19. data/app/graphql/ibrain/resolvers/base_aggregate.rb +9 -0
  20. data/app/graphql/ibrain/resolvers/base_resolver.rb +15 -0
  21. data/app/graphql/ibrain/types/aggregate_type.rb +9 -0
  22. data/app/graphql/ibrain/types/base_argument.rb +11 -0
  23. data/app/graphql/ibrain/types/base_connection.rb +16 -0
  24. data/app/graphql/ibrain/types/base_edge.rb +10 -0
  25. data/app/graphql/ibrain/types/base_enum.rb +8 -0
  26. data/app/graphql/ibrain/types/base_field.rb +15 -0
  27. data/app/graphql/ibrain/types/base_input_object.rb +9 -0
  28. data/app/graphql/ibrain/types/base_interface.rb +14 -0
  29. data/app/graphql/ibrain/types/base_node.rb +13 -0
  30. data/app/graphql/ibrain/types/base_object.rb +14 -0
  31. data/app/graphql/ibrain/types/base_query_type.rb +14 -0
  32. data/app/graphql/ibrain/types/base_scalar.rb +8 -0
  33. data/app/graphql/ibrain/types/base_union.rb +10 -0
  34. data/app/graphql/ibrain/types/filter_type.rb +8 -0
  35. data/app/graphql/ibrain/types/node_type.rb +11 -0
  36. data/app/graphql/ibrain/util/field_combiner.rb +13 -0
  37. data/app/graphql/ibrain/util/query_combiner.rb +13 -0
  38. data/app/graphql/mutations/insert_user.rb +18 -0
  39. data/app/models/ibrain/ability.rb +51 -0
  40. data/app/models/ibrain/application_record.rb +7 -0
  41. data/app/models/ibrain/base.rb +47 -0
  42. data/app/models/ibrain/concerns/ransackable_attributes.rb +22 -0
  43. data/app/models/ibrain/concerns/soft_deletable.rb +16 -0
  44. data/app/models/ibrain/concerns/user_api_authentication.rb +23 -0
  45. data/app/models/ibrain/concerns/user_methods.rb +25 -0
  46. data/app/models/ibrain/legacy_user.rb +19 -0
  47. data/app/models/ibrain/role.rb +14 -0
  48. data/app/models/ibrain/role_user.rb +18 -0
  49. data/config/initializers/friendly_id.rb +87 -0
  50. data/config/locales/en.yml +10 -0
  51. data/config/locales/jp.yml +10 -0
  52. data/config/locales/vi.yml +10 -0
  53. data/config/routes.rb +9 -0
  54. data/lib/generators/ibrain/graphql/core.rb +75 -0
  55. data/lib/generators/ibrain/graphql/mutation_generator.rb +58 -0
  56. data/lib/generators/ibrain/graphql/object_generator.rb +80 -0
  57. data/lib/generators/ibrain/graphql/resolver_generator.rb +33 -0
  58. data/lib/generators/ibrain/graphql/resolvers_generator.rb +59 -0
  59. data/lib/generators/ibrain/graphql/templates/aggregate.erb +10 -0
  60. data/lib/generators/ibrain/graphql/templates/mutation.erb +16 -0
  61. data/lib/generators/ibrain/graphql/templates/object.erb +11 -0
  62. data/lib/generators/ibrain/graphql/templates/resolver.erb +15 -0
  63. data/lib/generators/ibrain/graphql/templates/resolvers.erb +13 -0
  64. data/lib/generators/ibrain/graphql/type_generator.rb +101 -0
  65. data/lib/generators/ibrain/install/install_generator.rb +189 -0
  66. data/lib/generators/ibrain/install/templates/config/database.tt +23 -0
  67. data/lib/generators/ibrain/install/templates/config/initializers/cors.tt +25 -0
  68. data/lib/generators/ibrain/install/templates/config/initializers/ibrain.rb.tt +55 -0
  69. data/lib/generators/ibrain/install/templates/config/puma.tt +43 -0
  70. data/lib/generators/ibrain/install/templates/graphql/app_schema.rb.tt +4 -0
  71. data/lib/generators/ibrain/install/templates/graphql/types/mutation_type.rb.tt +10 -0
  72. data/lib/generators/ibrain/install/templates/graphql/types/query_type.rb.tt +13 -0
  73. data/lib/ibrain/app_configuration.rb +66 -0
  74. data/lib/ibrain/config.rb +5 -0
  75. data/lib/ibrain/core/class_constantizer.rb +41 -0
  76. data/lib/ibrain/core/controller_helpers/auth.rb +64 -0
  77. data/lib/ibrain/core/controller_helpers/current_host.rb +17 -0
  78. data/lib/ibrain/core/controller_helpers/response.rb +52 -0
  79. data/lib/ibrain/core/controller_helpers/strong_parameters.rb +21 -0
  80. data/lib/ibrain/core/engine.rb +16 -0
  81. data/lib/ibrain/core/environment.rb +17 -0
  82. data/lib/ibrain/core/environment_extension.rb +27 -0
  83. data/lib/ibrain/core/role_configuration.rb +72 -0
  84. data/lib/ibrain/core/validators/email.rb +23 -0
  85. data/lib/ibrain/core/version.rb +17 -0
  86. data/lib/ibrain/core/versioned_value.rb +73 -0
  87. data/lib/ibrain/core.rb +86 -0
  88. data/lib/ibrain/encryptor.rb +27 -0
  89. data/lib/ibrain/i18n.rb +17 -0
  90. data/lib/ibrain/logger.rb +23 -0
  91. data/lib/ibrain/permission_sets/base.rb +33 -0
  92. data/lib/ibrain/permission_sets/super_user.rb +11 -0
  93. data/lib/ibrain/permission_sets.rb +4 -0
  94. data/lib/ibrain/permitted_attributes.rb +26 -0
  95. data/lib/ibrain/preferences/configuration.rb +170 -0
  96. data/lib/ibrain/preferences/preferable.rb +183 -0
  97. data/lib/ibrain/preferences/preferable_class_methods.rb +140 -0
  98. data/lib/ibrain/user_class_handle.rb +29 -0
  99. data/lib/ibrain_core.rb +3 -0
  100. data/lib/tasks/ibrain/auto_annotate_models.rake +61 -0
  101. data/lib/tasks/ibrain/core_tasks.rake +5 -0
  102. data/lib/tasks/ibrain/ridgepole.rake +37 -0
  103. metadata +293 -0
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'type_generator'
4
+
5
+ module Ibrain
6
+ module Graphql
7
+ # Generate an object type by name,
8
+ # with the specified fields.
9
+ #
10
+ # ```
11
+ # rails g graphql:object PostType name:String!
12
+ # ```
13
+ #
14
+ # Add the Node interface with `--node`.
15
+ class ObjectGenerator < TypeGeneratorBase
16
+ desc "Create a GraphQL::ObjectType with the given name and fields." \
17
+ "If the given type name matches an existing ActiveRecord model, the generated type will automatically include fields for the models database columns."
18
+ source_root File.expand_path('templates', __dir__)
19
+
20
+ argument :custom_fields,
21
+ type: :array,
22
+ default: [],
23
+ banner: "name:type name:type ...",
24
+ desc: "Fields for this object (type may be expressed as Ruby or GraphQL)"
25
+
26
+ class_option :node,
27
+ type: :boolean,
28
+ default: false,
29
+ desc: "Include the Relay Node interface"
30
+
31
+ def create_type_file
32
+ template "object.erb", "#{options[:directory]}/types/objects/#{type_file_name}.rb"
33
+ end
34
+
35
+ def fields
36
+ columns = []
37
+ columns += klass.columns.map { |c| generate_column_string(c) } if class_exists?
38
+ columns + custom_fields
39
+ end
40
+
41
+ def self.normalize_type_expression(type_expression, mode:, null: true)
42
+ case type_expression
43
+ when "Text", "Json", "json"
44
+ ["String", null]
45
+ when "Decimal"
46
+ ["Float", null]
47
+ when "DateTime", "Datetime"
48
+ ["GraphQL::Types::ISO8601DateTime", null]
49
+ when "Date"
50
+ ["GraphQL::Types::ISO8601Date", null]
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def generate_column_string(column)
59
+ name = column.name
60
+ required = column.null ? "" : "!"
61
+ type = column_type_string(column)
62
+ "#{name}:#{required}#{type}"
63
+ end
64
+
65
+ def column_type_string(column)
66
+ column.name == "id" ? "ID" : column.type.to_s.camelize
67
+ end
68
+
69
+ def class_exists?
70
+ klass.is_a?(Class) && klass.ancestors.include?(ActiveRecord::Base)
71
+ rescue NameError
72
+ false
73
+ end
74
+
75
+ def klass
76
+ @klass ||= Module.const_get(type_name.camelize)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # frozen_string_literal: true'
4
+
5
+ require_relative 'resolvers_generator'
6
+
7
+ module Ibrain
8
+ module Graphql
9
+ # TODO: What other options should be supported?
10
+ #
11
+ # @example Generate a `GraphQL::Schema::Resolver` by name
12
+ # rails g graphql:resolver PostsResolver
13
+ class ResolverGenerator < ResolversGenerator
14
+ source_root File.expand_path('templates', __dir__)
15
+
16
+ def create_resolver_file
17
+ if @behavior == :revoke
18
+ log :gsub, "#{options[:directory]}/types/query_type.rb"
19
+ else
20
+ create_resolver_root_type
21
+ end
22
+
23
+ template "resolver.erb", "#{options[:directory]}/resolvers/#{file_name}.rb"
24
+
25
+ sentinel = /class .*QueryType\s*<\s*[^\s]+?\n/m
26
+ in_root do
27
+ gsub_file "#{options[:directory]}/types/query_type.rb", / \# TODO: Add Resolvers as fields\s*\n/m, ""
28
+ inject_into_file "#{options[:directory]}/types/query_type.rb", " field :#{field_name}, resolver: Resolvers::#{resolver_name}\n\n", after: sentinel, verbose: false, force: false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/named_base'
5
+ require_relative 'core'
6
+
7
+ module Ibrain
8
+ module Graphql
9
+ # TODO: What other options should be supported?
10
+ #
11
+ # @example Generate a `GraphQL::Schema::Resolver` by name
12
+ # rails g graphql:resolver PostsResolver
13
+ class ResolversGenerator < Rails::Generators::Base
14
+ include Core
15
+
16
+ desc "Create a resolver by name"
17
+ source_root File.expand_path('templates', __dir__)
18
+
19
+ argument :name, type: :string
20
+ class_option :model, type: :string, default: nil
21
+
22
+ def initialize(args, *options) # :nodoc:
23
+ # Unfreeze name in case it's given as a frozen string
24
+ args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?
25
+ super
26
+
27
+ assign_names!(name)
28
+ end
29
+
30
+ attr_reader :file_name, :resolver_name, :field_name, :model_name
31
+
32
+ def create_resolver_file
33
+ if @behavior == :revoke
34
+ log :gsub, "#{options[:directory]}/types/query_type.rb"
35
+ else
36
+ create_resolver_root_type
37
+ end
38
+
39
+ template "resolvers.erb", "#{options[:directory]}/resolvers/#{file_name}.rb"
40
+ template "aggregate.erb", "#{options[:directory]}/resolvers/#{file_name}_aggregate.rb"
41
+
42
+ sentinel = /class .*QueryType\s*<\s*[^\s]+?\n/m
43
+ in_root do
44
+ gsub_file "#{options[:directory]}/types/query_type.rb", / \# TODO: Add Resolvers as fields\s*\n/m, ""
45
+ inject_into_file "#{options[:directory]}/types/query_type.rb", " field :#{field_name}, resolver: Resolvers::#{resolver_name}\n field :#{field_name}_aggregate, resolver: Resolvers::#{resolver_name}Aggregate\n\n", after: sentinel, verbose: false, force: false
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def assign_names!(name)
52
+ @field_name = name.camelize.underscore
53
+ @resolver_name = name.camelize(:upper)
54
+ @file_name = name.camelize.underscore
55
+ @model_name = options[:model].blank? ? 'Post' : options[:model].capitalize
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Resolvers
3
+ class <%= "#{resolver_name}Aggregate" %> < Ibrain::Resolvers::BaseAggregate
4
+ # define resolve method
5
+ def resolve(args)
6
+ <%= model_name.capitalize %>.ransack(args[:filter]).result
7
+ end
8
+ end
9
+ end
10
+ <% end -%>
@@ -0,0 +1,16 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Mutations
3
+ class <%= mutation_name %> < Ibrain::Mutations::BaseMutation
4
+ # TODO: define return fields
5
+ field :<%= model_name.underscore %>, Types::<%= model_name %>Type, null: false
6
+
7
+ # TODO: define arguments
8
+ # argument :name, String, required: true
9
+
10
+ # TODO: define resolve method
11
+ def resolve(args)
12
+ # TODO: define logic
13
+ end
14
+ end
15
+ end
16
+ <% end -%>
@@ -0,0 +1,11 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Types
3
+ module Objects
4
+ class <%= type_ruby_name.split('::')[-1] %> < Ibrain::Types::BaseObject
5
+ implements Ibrain::Interfaces::RecordInterface
6
+
7
+ <% normalized_fields.each do |f| %> <%= f.to_ruby %>
8
+ <% end %>end
9
+ end
10
+ end
11
+ <% end -%>
@@ -0,0 +1,15 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Resolvers
3
+ class <%= resolver_name %> < Ibrain::Resolvers::BaseResolver
4
+ # TODO: define return fields
5
+ type Types::Objects::<%= model_name.capitalize %>Type, null: false
6
+
7
+ argument :id, ID, required: false
8
+
9
+ # TODO: define resolve method
10
+ def resolve(args)
11
+ <%= model_name.capitalize %>.find args[:id]
12
+ end
13
+ end
14
+ end
15
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Resolvers
3
+ class <%= resolver_name %> < <%= "#{resolver_name}Aggregate" %>
4
+ # TODO: define return fields
5
+ type [Types::Objects::<%= model_name.capitalize %>Type], null: false
6
+
7
+ # TODO: define resolve method
8
+ def resolve(args)
9
+ super(args).limit(args[:limit]).offset(args[:offset])
10
+ end
11
+ end
12
+ end
13
+ <% end -%>
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/base'
5
+ require 'graphql'
6
+ require 'active_support'
7
+ require 'active_support/core_ext/string/inflections'
8
+ require_relative 'core'
9
+
10
+ module Ibrain
11
+ module Graphql
12
+ class TypeGeneratorBase < Rails::Generators::Base
13
+ include Core
14
+
15
+ argument :type_name,
16
+ type: :string,
17
+ banner: "TypeName",
18
+ desc: "Name of this object type (expressed as Ruby or GraphQL)"
19
+
20
+ # Take a type expression in any combination of GraphQL or Ruby styles
21
+ # and return it in a specified output style
22
+ # TODO: nullability / list with `mode: :graphql` doesn't work
23
+ # @param type_expresson [String]
24
+ # @param mode [Symbol]
25
+ # @param null [Boolean]
26
+ # @return [(String, Boolean)] The type expression, followed by `null:` value
27
+ def self.normalize_type_expression(type_expression, mode:, null: true)
28
+ if type_expression.start_with?("!")
29
+ normalize_type_expression(type_expression[1..-1], mode: mode, null: false)
30
+ elsif type_expression.end_with?("!")
31
+ normalize_type_expression(type_expression[0..-2], mode: mode, null: false)
32
+ elsif type_expression.start_with?("[") && type_expression.end_with?("]")
33
+ name, is_null = normalize_type_expression(type_expression[1..-2], mode: mode, null: null)
34
+ ["[#{name}]", is_null]
35
+ elsif type_expression.end_with?("Type")
36
+ normalize_type_expression(type_expression[0..-5], mode: mode, null: null)
37
+ elsif type_expression.start_with?("Types::")
38
+ normalize_type_expression(type_expression[7..-1], mode: mode, null: null)
39
+ elsif type_expression.start_with?("types.")
40
+ normalize_type_expression(type_expression[6..-1], mode: mode, null: null)
41
+ else
42
+ case mode
43
+ when :ruby
44
+ case type_expression
45
+ when "Int"
46
+ ["Integer", null]
47
+ when "Integer", "Float", "Boolean", "String", "ID"
48
+ [type_expression, null]
49
+ else
50
+ ["Types::#{type_expression.camelize}Type", null]
51
+ end
52
+ when :graphql
53
+ [type_expression.camelize, null]
54
+ else
55
+ raise "Unexpected normalize mode: #{mode}"
56
+ end
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # @return [String] The user-provided type name, normalized to Ruby code
63
+ def type_ruby_name
64
+ @type_ruby_name ||= self.class.normalize_type_expression(type_name, mode: :ruby)[0]
65
+ end
66
+
67
+ # @return [String] The user-provided type name, as a GraphQL name
68
+ def type_graphql_name
69
+ @type_graphql_name ||= self.class.normalize_type_expression(type_name, mode: :graphql)[0]
70
+ end
71
+
72
+ # @return [String] The user-provided type name, as a file name (without extension)
73
+ def type_file_name
74
+ @type_file_name ||= "#{type_graphql_name}Type".underscore
75
+ end
76
+
77
+ # @return [Array<NormalizedField>] User-provided fields, in `(name, Ruby type name)` pairs
78
+ def normalized_fields
79
+ skip_fields = ["created_at:!Datetime", "updated_at:!Datetime"]
80
+
81
+ @normalized_fields ||= fields.reject { |f| skip_fields.include?(f) }.map { |f|
82
+ name, raw_type = f.split(":", 2)
83
+ type_expr, null = self.class.normalize_type_expression(raw_type, mode: :ruby)
84
+ NormalizedField.new(name, type_expr, null)
85
+ }
86
+ end
87
+
88
+ class NormalizedField
89
+ def initialize(name, type_expr, null)
90
+ @name = name
91
+ @type_expr = type_expr
92
+ @null = null
93
+ end
94
+
95
+ def to_ruby
96
+ "field :#{@name}, #{@type_expr}, null: #{@null}"
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,189 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'ibrain/logger'
5
+
6
+ module Ibrain
7
+ # @private
8
+ class InstallGenerator < Rails::Generators::Base
9
+ CORE_MOUNT_ROUTE = "mount Ibrain::Core::Engine"
10
+ source_root File.expand_path('templates', __dir__)
11
+
12
+ class_option :user_class, type: :string
13
+ class_option :with_authentication, type: :boolean, default: true
14
+ class_option :with_rubocop, type: :boolean, default: true
15
+ class_option :with_graphql, type: :boolean, default: false
16
+ class_option :with_annotation, type: :boolean, default: true
17
+ class_option :with_sendgrid, type: :boolean, default: false
18
+ class_option :enforce_available_locales, type: :boolean, default: nil
19
+ class_option :with_ridgepole, type: :boolean, default: true
20
+
21
+ def additional_tweaks
22
+ return unless File.exist? 'public/robots.txt'
23
+
24
+ append_file "public/robots.txt", <<-ROBOTS.strip_heredoc
25
+ User-agent: *
26
+ Disallow: /user
27
+ Disallow: /account
28
+ Disallow: /api
29
+ Disallow: /password
30
+ ROBOTS
31
+ end
32
+
33
+ def create_overrides_directory
34
+ empty_directory "app/overrides"
35
+ end
36
+
37
+ def configure_application
38
+ application <<-RUBY
39
+ # Load application's model / class decorators
40
+ initializer 'ibrain.decorators' do |app|
41
+ config.to_prepare do
42
+ Dir.glob(Rails.root.join('app/**/*_decorator*.rb')) do |path|
43
+ require_dependency(path)
44
+ end
45
+ end
46
+ end
47
+ RUBY
48
+
49
+ if !options[:enforce_available_locales].nil?
50
+ application <<-RUBY
51
+ I18n.enforce_available_locales = #{options[:enforce_available_locales]}
52
+ RUBY
53
+ end
54
+ end
55
+
56
+ def plugin_install_preparation
57
+ @plugins_to_be_installed = []
58
+ @plugin_generators_to_run = []
59
+ end
60
+
61
+ def install_auth_plugin
62
+ if options[:with_authentication] && (options[:auto_accept] || !no?("
63
+ Ibrain has a default authentication extension that uses Devise.
64
+ You can find more info at https://github.com/john-techfox/ibrain-auth.git.
65
+
66
+ Would you like to install it? (Y/n)"))
67
+
68
+ @plugins_to_be_installed << 'ibrain-auth' unless system('gem list | grep ibrain-auth')
69
+ @plugin_generators_to_run << 'ibrain:auth:install'
70
+ end
71
+ end
72
+
73
+ def run_bundle_install_if_needed_by_plugins
74
+ @plugins_to_be_installed.each do |plugin_name|
75
+ gem plugin_name
76
+ end
77
+
78
+ if options[:with_rubocop]
79
+ append_gem('rubocop', '1.23.0', 'development')
80
+ append_gem('rubocop-performance', '1.12.0', 'development')
81
+ append_gem('rubocop-rails', '2.12.4', 'development')
82
+ end
83
+
84
+ if options[:with_graphql]
85
+ append_gem('graphql', '1.12.6')
86
+ append_gem('graphql-batch', '0.4.3')
87
+ append_gem('graphql-guard', '2.0.0')
88
+ append_gem('graphql-rails-generators', '1.1.2', 'development')
89
+ append_gem('graphiql-rails', '1.8.0', 'development')
90
+ end
91
+
92
+ append_gem('annotate', '3.1.1', 'development') if options[:with_annotation]
93
+ append_gem('sendgrid-ruby', '6.6.0') if options[:with_sendgrid]
94
+
95
+ if options[:with_ridgepole]
96
+ append_gem('ridgepole', '1.0.0', 'development')
97
+ else
98
+ remove_gem('ridgepole')
99
+ end
100
+
101
+ bundle_cleanly{ run "bundle install" } if @plugins_to_be_installed.any?
102
+ run "spring stop" if defined?(Spring)
103
+
104
+ @plugin_generators_to_run.each do |plugin_generator_name|
105
+ generate plugin_generator_name.to_s
106
+ end
107
+ end
108
+
109
+ def install_routes
110
+ routes_file_path = File.join('config', 'routes.rb')
111
+ unless File.read(routes_file_path).include? CORE_MOUNT_ROUTE
112
+ insert_into_file routes_file_path, after: "Rails.application.routes.draw do\n" do
113
+ <<-RUBY
114
+ # This line mounts Ibrain's routes at the root of your application.
115
+ # This means, any requests to URLs such as /graphql, will go to Ibrain::GraphqlController,
116
+ # any requests to URLS such as /auth, will go to Ibrain::AuthController,
117
+ # If you would like to change where this engine is mounted, simply change the :at option to something different.
118
+ #
119
+ # We ask that you don't use the :as option here, as Ibrain relies on it being the default of "ibrain"
120
+ #{CORE_MOUNT_ROUTE}, at: '/'
121
+
122
+ # Please contact to Tai Nguyen Van <tainv@its-global.vn> if you have any question?
123
+ RUBY
124
+ end
125
+ end
126
+
127
+ unless options[:quiet]
128
+ Ibrain::Logger.info "*" * 50
129
+ Ibrain::Logger.info "We added the following line to your application's config/routes.rb file:"
130
+ Ibrain::Logger.info " "
131
+ Ibrain::Logger.info " #{CORE_MOUNT_ROUTE}, at: '/'"
132
+ end
133
+ end
134
+
135
+ def add_files
136
+ template 'config/initializers/ibrain.rb.tt', 'config/initializers/ibrain.rb', { skip: true }
137
+ template 'config/initializers/cors.tt', 'config/initializers/cors.rb', { skip: true }
138
+ template 'config/puma.tt', 'config/puma.rb', { skip: true }
139
+ yml_template 'config/database.tt', 'config/database.yml', { skip: true }
140
+ template '.rubocop.yml.tt', '.rubocop.yml', { skip: true } if options[:with_rubocop]
141
+
142
+ if options[:with_graphql]
143
+ template 'graphql/app_schema.rb.tt', 'app/graphql/app_schema.rb', { skip: true }
144
+ template 'graphql/types/mutation_type.rb.tt', 'app/graphql/types/mutation_type.rb', { skip: true }
145
+ template 'graphql/types/query_type.rb.tt', 'app/graphql/types/query_type.rb', { skip: true }
146
+ end
147
+ end
148
+
149
+ def complete
150
+ unless options[:quiet]
151
+ Ibrain::Logger.info "*" * 50
152
+ Ibrain::Logger.info "Ibrain has been installed successfully. You're all ready to go!"
153
+ Ibrain::Logger.info " "
154
+ Ibrain::Logger.info "Enjoy!"
155
+ end
156
+ end
157
+
158
+ private
159
+
160
+ def bundle_cleanly(&block)
161
+ Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&block) : Bundler.with_clean_env(&block)
162
+ end
163
+
164
+ def append_gem(name, version, group_name = nil)
165
+ shell_command = ["\ngem '#{name}', '~> #{version}'"]
166
+ shell_command.push("group: :#{group_name}") if group_name.present?
167
+ string_command = shell_command.join(', ')
168
+ gems = Gem.loaded_specs.values.map(&:full_name).join(' ')
169
+
170
+ system( `echo "#{string_command}" >> Gemfile` ) unless gems.include?("#{name}-")
171
+ end
172
+
173
+ def remove_gem(name)
174
+ gems = Gem.loaded_specs.values.map(&:full_name).join(' ')
175
+
176
+ system( "bundle remove #{name}" ) if gems.include?("#{name}-")
177
+ end
178
+
179
+ def yml_template(source, *args)
180
+ config = args.last.is_a?(Hash) ? args.pop : {}
181
+ destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/o, "")
182
+ source = File.expand_path(find_in_source_paths(source.to_s))
183
+
184
+ create_file destination, nil, config do
185
+ File.read(source)
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,23 @@
1
+ default: &default
2
+ adapter: <%= ENV.fetch("DATABASE_ADAPTER") { 'postgresql' } %>
3
+ encoding: utf8mb4
4
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
5
+ host: <%= ENV.fetch('DATABASE_HOSTNAME') { 'localhost' }%>
6
+ username: <%= ENV.fetch('DATABASE_USERNAME') { 'ibrain' }%>
7
+ password: <%= ENV.fetch('DATABASE_PASSWORD') { 'ibrain-password' }%>
8
+
9
+ development:
10
+ <<: *default
11
+ database: <%= ENV.fetch('DATABASE_NAME') { 'ibrain_development' }%>
12
+
13
+ staging:
14
+ <<: *default
15
+ database: <%= ENV.fetch('DATABASE_NAME') { 'ibrain_staging' }%>
16
+
17
+ test:
18
+ <<: *default
19
+ database: <%= ENV.fetch('DATABASE_NAME') { 'ibrain_test' }%>
20
+
21
+ production:
22
+ <<: *default
23
+ database: <%= ENV.fetch('DATABASE_NAME') { 'ibrain_production' }%>
@@ -0,0 +1,25 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Avoid CORS issues when API is called from the frontend app.
4
+ # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
5
+
6
+ # Read more: https://github.com/cyu/rack-cors
7
+
8
+ Rails.application.config.middleware.insert_before 0, Rack::Cors do
9
+ allow do
10
+ origins '*'
11
+
12
+ resource '*',
13
+ headers: :any,
14
+ methods: [:get, :post, :put, :patch, :delete, :options, :head],
15
+ expose: %w[
16
+ X-Requested-With
17
+ Content-Type
18
+ Authorization
19
+ Accept
20
+ Accept-Encoding
21
+ Access-Control-Allow-Credentials
22
+ ],
23
+ credentials: true
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ # Ibrain version defaults for preferences that are not overridden
2
+ Ibrain.load_defaults '<%= Ibrain.ibrain_version %>'
3
+
4
+ Ibrain.config do |config|
5
+ # Core:
6
+ # from address for emails
7
+ config.mails_from = "info@example.com"
8
+
9
+ # Uncomment to stop tracking inventory levels in the application
10
+ # config.track_inventory_levels = false
11
+
12
+ # When set, data caches are only invalidated when they fall below or rise
13
+ # above the inventory_cache_threshold that is set. Default is to invalidate cache on
14
+ # any inventory changes.
15
+ # config.inventory_cache_threshold = 3
16
+
17
+ # Defaults
18
+ # Permission Sets:
19
+
20
+ # Uncomment and customize the following line to add custom permission sets
21
+ # to a custom users role:
22
+ # config.roles.assign_permissions :role_name, ['Ibrain::PermissionSets::CustomPermissionSet']
23
+
24
+ # @!attribute [rw] guest_token_cookie_options
25
+ # @return [Hash] Add additional guest_token cookie options here (ie. domain or path)
26
+ # config.guest_token_cookie_options = {}
27
+
28
+ # @!attribute [rw] generate_api_key_for_all_roles
29
+ # @return [Boolean] Allow generating api key automatically for user
30
+ # at role_user creation for all roles. (default: +false+)
31
+ # config.generate_api_key_for_all_roles = false
32
+
33
+ # Graphql Policy Object
34
+ # config.graphql_policy = 'Ibrain::Policies::GraphqlPolicy'
35
+
36
+ # Api version for route config
37
+ # config.api_version = 'v1'
38
+
39
+ # Graphql Schema name
40
+ # config.graphql_schema = 'Ibrain::BaseSchema'
41
+
42
+ # Graphql Encryptor key
43
+ # config.ibrain_encryptor_key = Rails.application.secrets.secret_key_base.byteslice(0..31)
44
+ end
45
+
46
+ <% if defined?(Ibrain::Api::Engine) -%>
47
+ Ibrain::Api::Config.configure do |config|
48
+ # Localization
49
+ config.locale = 'en'
50
+
51
+ config.requires_authentication = true
52
+ end
53
+ <% end -%>
54
+
55
+ Ibrain.user_class = <%= (options[:user_class].blank? ? "Ibrain::LegacyUser" : options[:user_class]).inspect %>