ibrain-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +75 -0
- data/Rakefile +7 -0
- data/app/controllers/concerns/ibrain_errors.rb +23 -0
- data/app/controllers/concerns/ibrain_handler.rb +42 -0
- data/app/controllers/ibrain/base_controller.rb +28 -0
- data/app/controllers/ibrain/graphql_controller.rb +55 -0
- data/app/graphql/ibrain/base_schema.rb +52 -0
- data/app/graphql/ibrain/extentions/default_value.rb +15 -0
- data/app/graphql/ibrain/interfaces/base_interface.rb +5 -0
- data/app/graphql/ibrain/interfaces/person_interface.rb +15 -0
- data/app/graphql/ibrain/interfaces/record_interface.rb +10 -0
- data/app/graphql/ibrain/lazy/base.rb +8 -0
- data/app/graphql/ibrain/loaders/association_loader.rb +61 -0
- data/app/graphql/ibrain/mutations/base_mutation.rb +35 -0
- data/app/graphql/ibrain/policies/base_policy.rb +45 -0
- data/app/graphql/ibrain/policies/graphql_policy.rb +8 -0
- data/app/graphql/ibrain/resolvers/base_aggregate.rb +9 -0
- data/app/graphql/ibrain/resolvers/base_resolver.rb +15 -0
- data/app/graphql/ibrain/types/aggregate_type.rb +9 -0
- data/app/graphql/ibrain/types/base_argument.rb +11 -0
- data/app/graphql/ibrain/types/base_connection.rb +16 -0
- data/app/graphql/ibrain/types/base_edge.rb +10 -0
- data/app/graphql/ibrain/types/base_enum.rb +8 -0
- data/app/graphql/ibrain/types/base_field.rb +15 -0
- data/app/graphql/ibrain/types/base_input_object.rb +9 -0
- data/app/graphql/ibrain/types/base_interface.rb +14 -0
- data/app/graphql/ibrain/types/base_node.rb +13 -0
- data/app/graphql/ibrain/types/base_object.rb +14 -0
- data/app/graphql/ibrain/types/base_query_type.rb +14 -0
- data/app/graphql/ibrain/types/base_scalar.rb +8 -0
- data/app/graphql/ibrain/types/base_union.rb +10 -0
- data/app/graphql/ibrain/types/filter_type.rb +8 -0
- data/app/graphql/ibrain/types/node_type.rb +11 -0
- data/app/graphql/ibrain/util/field_combiner.rb +13 -0
- data/app/graphql/ibrain/util/query_combiner.rb +13 -0
- data/app/graphql/mutations/insert_user.rb +18 -0
- data/app/models/ibrain/ability.rb +51 -0
- data/app/models/ibrain/application_record.rb +7 -0
- data/app/models/ibrain/base.rb +47 -0
- data/app/models/ibrain/concerns/ransackable_attributes.rb +22 -0
- data/app/models/ibrain/concerns/soft_deletable.rb +16 -0
- data/app/models/ibrain/concerns/user_api_authentication.rb +23 -0
- data/app/models/ibrain/concerns/user_methods.rb +25 -0
- data/app/models/ibrain/legacy_user.rb +19 -0
- data/app/models/ibrain/role.rb +14 -0
- data/app/models/ibrain/role_user.rb +18 -0
- data/config/initializers/friendly_id.rb +87 -0
- data/config/locales/en.yml +10 -0
- data/config/locales/jp.yml +10 -0
- data/config/locales/vi.yml +10 -0
- data/config/routes.rb +9 -0
- data/lib/generators/ibrain/graphql/core.rb +75 -0
- data/lib/generators/ibrain/graphql/mutation_generator.rb +58 -0
- data/lib/generators/ibrain/graphql/object_generator.rb +80 -0
- data/lib/generators/ibrain/graphql/resolver_generator.rb +33 -0
- data/lib/generators/ibrain/graphql/resolvers_generator.rb +59 -0
- data/lib/generators/ibrain/graphql/templates/aggregate.erb +10 -0
- data/lib/generators/ibrain/graphql/templates/mutation.erb +16 -0
- data/lib/generators/ibrain/graphql/templates/object.erb +11 -0
- data/lib/generators/ibrain/graphql/templates/resolver.erb +15 -0
- data/lib/generators/ibrain/graphql/templates/resolvers.erb +13 -0
- data/lib/generators/ibrain/graphql/type_generator.rb +101 -0
- data/lib/generators/ibrain/install/install_generator.rb +189 -0
- data/lib/generators/ibrain/install/templates/config/database.tt +23 -0
- data/lib/generators/ibrain/install/templates/config/initializers/cors.tt +25 -0
- data/lib/generators/ibrain/install/templates/config/initializers/ibrain.rb.tt +55 -0
- data/lib/generators/ibrain/install/templates/config/puma.tt +43 -0
- data/lib/generators/ibrain/install/templates/graphql/app_schema.rb.tt +4 -0
- data/lib/generators/ibrain/install/templates/graphql/types/mutation_type.rb.tt +10 -0
- data/lib/generators/ibrain/install/templates/graphql/types/query_type.rb.tt +13 -0
- data/lib/ibrain/app_configuration.rb +66 -0
- data/lib/ibrain/config.rb +5 -0
- data/lib/ibrain/core/class_constantizer.rb +41 -0
- data/lib/ibrain/core/controller_helpers/auth.rb +64 -0
- data/lib/ibrain/core/controller_helpers/current_host.rb +17 -0
- data/lib/ibrain/core/controller_helpers/response.rb +52 -0
- data/lib/ibrain/core/controller_helpers/strong_parameters.rb +21 -0
- data/lib/ibrain/core/engine.rb +16 -0
- data/lib/ibrain/core/environment.rb +17 -0
- data/lib/ibrain/core/environment_extension.rb +27 -0
- data/lib/ibrain/core/role_configuration.rb +72 -0
- data/lib/ibrain/core/validators/email.rb +23 -0
- data/lib/ibrain/core/version.rb +17 -0
- data/lib/ibrain/core/versioned_value.rb +73 -0
- data/lib/ibrain/core.rb +86 -0
- data/lib/ibrain/encryptor.rb +27 -0
- data/lib/ibrain/i18n.rb +17 -0
- data/lib/ibrain/logger.rb +23 -0
- data/lib/ibrain/permission_sets/base.rb +33 -0
- data/lib/ibrain/permission_sets/super_user.rb +11 -0
- data/lib/ibrain/permission_sets.rb +4 -0
- data/lib/ibrain/permitted_attributes.rb +26 -0
- data/lib/ibrain/preferences/configuration.rb +170 -0
- data/lib/ibrain/preferences/preferable.rb +183 -0
- data/lib/ibrain/preferences/preferable_class_methods.rb +140 -0
- data/lib/ibrain/user_class_handle.rb +29 -0
- data/lib/ibrain_core.rb +3 -0
- data/lib/tasks/ibrain/auto_annotate_models.rake +61 -0
- data/lib/tasks/ibrain/core_tasks.rake +5 -0
- data/lib/tasks/ibrain/ridgepole.rake +37 -0
- 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 %>
|