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,43 @@
|
|
1
|
+
# Puma can serve each request in a thread from an internal thread pool.
|
2
|
+
# The `threads` method setting takes two numbers: a minimum and maximum.
|
3
|
+
# Any libraries that use thread pools should be configured to match
|
4
|
+
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
5
|
+
# and maximum; this matches the default thread size of Active Record.
|
6
|
+
#
|
7
|
+
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
|
8
|
+
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
|
9
|
+
threads min_threads_count, max_threads_count
|
10
|
+
|
11
|
+
# Specifies the `worker_timeout` threshold that Puma will use to wait before
|
12
|
+
# terminating a worker in development environments.
|
13
|
+
#
|
14
|
+
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
|
15
|
+
|
16
|
+
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
17
|
+
#
|
18
|
+
port ENV.fetch("PORT") { 3000 }
|
19
|
+
|
20
|
+
# Specifies the `environment` that Puma will run in.
|
21
|
+
#
|
22
|
+
environment ENV.fetch("RAILS_ENV") { "development" }
|
23
|
+
|
24
|
+
# Specifies the `pidfile` that Puma will use.
|
25
|
+
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
|
26
|
+
|
27
|
+
# Specifies the number of `workers` to boot in clustered mode.
|
28
|
+
# Workers are forked web server processes. If using threads and workers together
|
29
|
+
# the concurrency of the application would be max `threads` * `workers`.
|
30
|
+
# Workers do not work on JRuby or Windows (both of which do not support
|
31
|
+
# processes).
|
32
|
+
#
|
33
|
+
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
34
|
+
|
35
|
+
# Use the `preload_app!` method when specifying a `workers` number.
|
36
|
+
# This directive tells Puma to first boot the application and load code
|
37
|
+
# before forking the application. This takes advantage of Copy On Write
|
38
|
+
# process behavior so workers use less memory.
|
39
|
+
#
|
40
|
+
# preload_app!
|
41
|
+
|
42
|
+
# Allow puma to be restarted by `rails restart` command.
|
43
|
+
plugin :tmp_restart
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Types
|
2
|
+
class QueryType < Ibrain::Types::BaseObject
|
3
|
+
# Add `node(id: ID!) and `nodes(ids: [ID!]!)`
|
4
|
+
include GraphQL::Types::Relay::HasNodeField
|
5
|
+
include GraphQL::Types::Relay::HasNodesField
|
6
|
+
|
7
|
+
# Add root-level fields here.
|
8
|
+
# They will be entry points for queries on your schema.
|
9
|
+
|
10
|
+
# Example with user resolvers
|
11
|
+
# field :users, resolver: Resolvers::UsersResolver
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This is the primary location for defining ibrain preferences
|
4
|
+
#
|
5
|
+
# The expectation is that this is created once and stored in
|
6
|
+
# the ibrain environment
|
7
|
+
#
|
8
|
+
# setters:
|
9
|
+
# a.color = :blue
|
10
|
+
# a[:color] = :blue
|
11
|
+
# a.set :color = :blue
|
12
|
+
# a.preferred_color = :blue
|
13
|
+
#
|
14
|
+
# getters:
|
15
|
+
# a.color
|
16
|
+
# a[:color]
|
17
|
+
# a.get :color
|
18
|
+
# a.preferred_color
|
19
|
+
#
|
20
|
+
require 'ibrain/preferences/configuration'
|
21
|
+
require 'ibrain/core/environment'
|
22
|
+
|
23
|
+
module Ibrain
|
24
|
+
class AppConfiguration < Preferences::Configuration
|
25
|
+
# Preferences (alphabetized to more easily lookup particular preferences)
|
26
|
+
|
27
|
+
# @!attribute [rw] guest_token_cookie_options
|
28
|
+
# @return [Hash] Add additional guest_token cookie options here (ie. domain or path)
|
29
|
+
preference :guest_token_cookie_options, :hash, default: {}
|
30
|
+
|
31
|
+
# @!attribute [rw] generate_api_key_for_all_roles
|
32
|
+
# @return [Boolean] Allow generating api key automatically for user
|
33
|
+
# at role_user creation for all roles. (default: +false+)
|
34
|
+
preference :generate_api_key_for_all_roles, :boolean, default: false
|
35
|
+
|
36
|
+
# @!attribute [rw] mails_from
|
37
|
+
# @return [String] Email address used as +From:+ field in transactional emails.
|
38
|
+
preference :mails_from, :string, default: 'ibrain@example.com'
|
39
|
+
|
40
|
+
preference :graphql_policy, :string, default: 'Ibrain::Policies::GraphqlPolicy'
|
41
|
+
|
42
|
+
# Api version for route config
|
43
|
+
preference :api_version, :string, default: 'v1'
|
44
|
+
|
45
|
+
# Graphql Schema name
|
46
|
+
preference :graphql_schema, :string, default: 'Ibrain::BaseSchema'
|
47
|
+
|
48
|
+
# Graphql Encryptor key
|
49
|
+
preference :ibrain_encryptor_key, :string, default: nil
|
50
|
+
|
51
|
+
def static_model_preferences
|
52
|
+
@static_model_preferences ||= Ibrain::Preferences::StaticModelPreferences.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def roles
|
56
|
+
@roles ||= Ibrain::RoleConfiguration.new.tap do |roles|
|
57
|
+
roles.assign_permissions :default, ['Ibrain::PermissionSets::DefaultCustomer']
|
58
|
+
roles.assign_permissions :admin, ['Ibrain::PermissionSets::SuperUser']
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def environment
|
63
|
+
@environment ||= Ibrain::Core::Environment.new(self)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/module'
|
4
|
+
|
5
|
+
module Ibrain
|
6
|
+
module Core
|
7
|
+
module ClassConstantizer
|
8
|
+
class Set
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@collection = ::Set.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(klass)
|
16
|
+
@collection << klass.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def concat(klasses)
|
20
|
+
klasses.each do |klass|
|
21
|
+
self << klass
|
22
|
+
end
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
delegate :clear, :empty?, to: :@collection
|
28
|
+
|
29
|
+
def delete(object)
|
30
|
+
@collection.delete(object.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def each
|
34
|
+
@collection.each do |klass|
|
35
|
+
yield klass.constantize
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
module Core
|
5
|
+
module ControllerHelpers
|
6
|
+
module Auth
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include Response
|
9
|
+
|
10
|
+
# @!attribute [rw] fallback_on_unauthorized
|
11
|
+
# @!scope class
|
12
|
+
# Extension point for overriding behaviour of access denied errors.
|
13
|
+
# Default behaviour is to redirect back or to "/unauthorized" with a flash
|
14
|
+
# message.
|
15
|
+
# @return [Proc] action to take when access denied error is raised.
|
16
|
+
|
17
|
+
included do
|
18
|
+
before_action :set_guest_token
|
19
|
+
helper_method :try_ibrain_current_user
|
20
|
+
|
21
|
+
class_attribute :fallback_on_unauthorized
|
22
|
+
self.fallback_on_unauthorized = -> do
|
23
|
+
error = ::Struct.new(
|
24
|
+
message: I18n.t('ibrain.authorization_failure')
|
25
|
+
)
|
26
|
+
|
27
|
+
render_json_error(error, :unauthorized)
|
28
|
+
end
|
29
|
+
|
30
|
+
rescue_from CanCan::AccessDenied do
|
31
|
+
instance_exec(&fallback_on_unauthorized)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Needs to be overriden so that we use Brain's Ability rather than anyone else's.
|
36
|
+
def current_ability
|
37
|
+
@current_ability ||= Ibrain::Ability.new(try_ibrain_current_user)
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_guest_token
|
41
|
+
# if cookies.signed[:guest_token].blank?
|
42
|
+
# cookies.permanent.signed[:guest_token] = Ibrain::Config[:guest_token_cookie_options].merge(
|
43
|
+
# value: SecureRandom.urlsafe_base64(nil, false),
|
44
|
+
# httponly: true
|
45
|
+
# )
|
46
|
+
# end
|
47
|
+
end
|
48
|
+
|
49
|
+
# proxy method to *possible* ibrain_current_user method
|
50
|
+
# Authentication extensions (such as ibrain-auth) are meant to provide ibrain_current_user
|
51
|
+
def try_ibrain_current_user
|
52
|
+
# This one will be defined by apps looking to hook into Ibrain
|
53
|
+
# As per authentication_helpers.rb
|
54
|
+
if respond_to?(:ibrain_current_user, true)
|
55
|
+
ibrain_current_user
|
56
|
+
# This one will be defined by Devise
|
57
|
+
elsif respond_to?(:current_ibrain_user, true)
|
58
|
+
current_ibrain_user
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
module Core
|
5
|
+
module ControllerHelpers
|
6
|
+
module CurrentHost
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
before_action do
|
11
|
+
ActiveStorage::Current.host = request.base_url
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
module Core
|
5
|
+
module ControllerHelpers
|
6
|
+
module Response
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
helper_method :render_json_error
|
11
|
+
helper_method :render_json_ok
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def render_json_error(error, status)
|
17
|
+
e_message = error.try(:record).try(:errors).try(:full_messages).try(:first)
|
18
|
+
e_message = error.try(:message) if e_message.blank?
|
19
|
+
|
20
|
+
backtrace = error.try(:backtrace).try(:join, "\n")
|
21
|
+
|
22
|
+
Ibrain::Logger.error e_message
|
23
|
+
Ibrain::Logger.error backtrace
|
24
|
+
|
25
|
+
render json: {
|
26
|
+
errors: [{
|
27
|
+
message: e_message,
|
28
|
+
extensions: {
|
29
|
+
code: status,
|
30
|
+
exception: {
|
31
|
+
stacktrace: [
|
32
|
+
backtrace
|
33
|
+
]
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}],
|
37
|
+
message: e_message,
|
38
|
+
data: nil
|
39
|
+
}, status: status
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_json_ok(data, message, errors = [])
|
43
|
+
render json: {
|
44
|
+
errors: errors,
|
45
|
+
message: message || I18n.t('ibrain.system.message.ok'),
|
46
|
+
data: data.as_json
|
47
|
+
}, status: :ok
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
module Core
|
5
|
+
module ControllerHelpers
|
6
|
+
module StrongParameters
|
7
|
+
def permitted_attributes
|
8
|
+
Ibrain::PermittedAttributes
|
9
|
+
end
|
10
|
+
|
11
|
+
delegate(*Ibrain::PermittedAttributes::ATTRIBUTES,
|
12
|
+
to: :permitted_attributes,
|
13
|
+
prefix: :permitted)
|
14
|
+
|
15
|
+
def permitted_user_attributes
|
16
|
+
permitted_attributes.user_attributes
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ibrain/config'
|
4
|
+
|
5
|
+
module Ibrain
|
6
|
+
module Core
|
7
|
+
class Engine < ::Rails::Engine
|
8
|
+
isolate_namespace Ibrain
|
9
|
+
config.generators.api_only = true
|
10
|
+
|
11
|
+
initializer "ibrain.environment", before: :load_config_initializers do |app|
|
12
|
+
app.config.ibrain = Ibrain::Config.environment
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ibrain/core/environment_extension'
|
4
|
+
|
5
|
+
module Ibrain
|
6
|
+
module Core
|
7
|
+
class Environment
|
8
|
+
include EnvironmentExtension
|
9
|
+
|
10
|
+
attr_accessor :preferences
|
11
|
+
|
12
|
+
def initialize(ibrain_config)
|
13
|
+
@preferences = ibrain_config
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ibrain/core/class_constantizer'
|
4
|
+
|
5
|
+
module Ibrain
|
6
|
+
module Core
|
7
|
+
module EnvironmentExtension
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def add_class_set(name)
|
12
|
+
define_method(name) do
|
13
|
+
set = instance_variable_get("@#{name}")
|
14
|
+
set ||= send("#{name}=", [])
|
15
|
+
set
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method("#{name}=") do |klasses|
|
19
|
+
set = ClassConstantizer::Set.new
|
20
|
+
set.concat(klasses)
|
21
|
+
instance_variable_set("@#{name}", set)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'ibrain/core/class_constantizer'
|
5
|
+
|
6
|
+
module Ibrain
|
7
|
+
# A class responsible for associating {Ibrain::Role} with a list of permission sets.
|
8
|
+
#
|
9
|
+
# @see Ibrain::PermissionSets
|
10
|
+
#
|
11
|
+
# @example Adding order, data, and user display to customer service users.
|
12
|
+
# Ibrain::RoleConfiguration.configure do |config|
|
13
|
+
# config.assign_permissions :customer_service, [
|
14
|
+
# Ibrain::PermissionSets::UserDisplay,
|
15
|
+
# ]
|
16
|
+
# end
|
17
|
+
class RoleConfiguration
|
18
|
+
# An internal structure for the association between a role and a
|
19
|
+
# set of permissions.
|
20
|
+
class Role
|
21
|
+
attr_reader :name, :permission_sets
|
22
|
+
|
23
|
+
def initialize(name, permission_sets)
|
24
|
+
@name = name
|
25
|
+
@permission_sets = Ibrain::Core::ClassConstantizer::Set.new
|
26
|
+
@permission_sets.concat permission_sets
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :roles
|
31
|
+
|
32
|
+
# Given a CanCan::Ability, and a user, determine what permissions sets can
|
33
|
+
# be activated on the ability, then activate them.
|
34
|
+
#
|
35
|
+
# This performs can/cannot declarations on the ability, and can modify its
|
36
|
+
# internal permissions.
|
37
|
+
#
|
38
|
+
# @param ability [CanCan::Ability] the ability to invoke declarations on
|
39
|
+
# @param user [#roles] the user that holds the roles association.
|
40
|
+
def activate_permissions!(ability, user)
|
41
|
+
ibrain_roles = ['default'] | user.roles.map(&:name)
|
42
|
+
applicable_permissions = Set.new
|
43
|
+
|
44
|
+
ibrain_roles.each do |role_name|
|
45
|
+
applicable_permissions |= roles[role_name].permission_sets
|
46
|
+
end
|
47
|
+
|
48
|
+
applicable_permissions.each do |permission_set|
|
49
|
+
permission_set.new(ability).activate!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Not public due to the fact this class is a Singleton
|
54
|
+
# @!visibility private
|
55
|
+
def initialize
|
56
|
+
@roles = Hash.new do |hash, name|
|
57
|
+
hash[name] = Role.new(name, Set.new)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Assign permission sets for a {Ibrain::Role} that has the name of role_name
|
62
|
+
# @param role_name [Symbol, String] The name of the role to associate permissions with
|
63
|
+
# @param permission_sets [Array<Ibrain::PermissionSets::Base>, Set<Ibrain::PermissionSets::Base>]
|
64
|
+
# A list of permission sets to activate if the user has the role indicated by role_name
|
65
|
+
def assign_permissions(role_name, permission_sets)
|
66
|
+
name = role_name.to_s
|
67
|
+
|
68
|
+
roles[name].permission_sets.concat permission_sets
|
69
|
+
roles[name]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
# == An ActiveModel Email Validator
|
5
|
+
#
|
6
|
+
# === Usage
|
7
|
+
#
|
8
|
+
# require 'ibrain/core/validators/email'
|
9
|
+
#
|
10
|
+
# class Person < ApplicationRecord
|
11
|
+
# validates :email_address, 'ibrain/email' => true
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
class EmailValidator < ActiveModel::EachValidator
|
15
|
+
EMAIL_REGEXP = URI::MailTo::EMAIL_REGEXP
|
16
|
+
|
17
|
+
def validate_each(record, attribute, value)
|
18
|
+
unless EMAIL_REGEXP.match? value
|
19
|
+
record.errors.add(attribute, :invalid, **{ value: value }.merge!(options))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
VERSION = "0.1.0"
|
5
|
+
|
6
|
+
def self.ibrain_version
|
7
|
+
VERSION
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.previous_ibrain_minor_version
|
11
|
+
'0.1.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.ibrain_gem_version
|
15
|
+
Gem::Version.new(ibrain_version)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ibrain
|
4
|
+
module Core
|
5
|
+
# Wrapper for a value that can be different depending on the Ibrain version
|
6
|
+
#
|
7
|
+
# Some configuration defaults can be added or changed when a new Ibrain
|
8
|
+
# version is released. This class encapsulates getting the correct value for a
|
9
|
+
# given Ibrain version.
|
10
|
+
#
|
11
|
+
# The way it works is you provide an initial value in time, plus the version
|
12
|
+
# boundary where it got changed. Then you can fetch the value providing the
|
13
|
+
# desired Ibrain version:
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# value = VersionedValue.new(true, "3.0.0" => false)
|
17
|
+
# value.call("2.7.0") # => true
|
18
|
+
# value.call("3.0.0") # => false
|
19
|
+
# value.call("3.1.0") # => false
|
20
|
+
#
|
21
|
+
# Remember that you must provide the exact boundary when a value got changed,
|
22
|
+
# which could easily be during a pre-release:
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# value = VersionedValue.new(true, "3.0.0" => false)
|
26
|
+
# value.call("3.0.0.alpha") # => true
|
27
|
+
#
|
28
|
+
# value = VersionedValue.new(true, "3.0.0.alpha" => false)
|
29
|
+
# value.call("3.0.0.alpha") # => false
|
30
|
+
#
|
31
|
+
# Multiple boundaries can also be provided:
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# value = VersionedValue.new(0, "2.0.0" => 1, "3.0.0" => 2)
|
35
|
+
# value.call("1.0.0") # => 0
|
36
|
+
# value.call("2.1.0") # => 1
|
37
|
+
# value.call("3.0.0") # => 2
|
38
|
+
class VersionedValue
|
39
|
+
attr_reader :boundaries
|
40
|
+
|
41
|
+
# @param initial_value [Any]
|
42
|
+
# @param boundary [Hash<String, Any>] Map from version number to new value
|
43
|
+
def initialize(initial_value, boundaries = {})
|
44
|
+
@boundaries = { '0' => initial_value }
|
45
|
+
.merge(boundaries)
|
46
|
+
.transform_keys { |version| to_gem_version(version) }
|
47
|
+
.sort.to_h
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param ibrain_version [String]
|
51
|
+
def call(ibrain_version = Ibrain.ibrain_version)
|
52
|
+
ibrain_version = to_gem_version(ibrain_version)
|
53
|
+
boundaries.fetch(
|
54
|
+
boundaries
|
55
|
+
.keys
|
56
|
+
.reduce do |target, following|
|
57
|
+
if target <= ibrain_version && ibrain_version < following
|
58
|
+
target
|
59
|
+
else
|
60
|
+
following
|
61
|
+
end
|
62
|
+
end
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def to_gem_version(string)
|
69
|
+
Gem::Version.new(string)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/ibrain/core.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_controller/railtie"
|
4
|
+
require "action_mailer/railtie"
|
5
|
+
require "active_job/railtie"
|
6
|
+
require "active_model/railtie"
|
7
|
+
require "active_record/railtie"
|
8
|
+
require "active_storage/engine"
|
9
|
+
require 'activerecord/session_store'
|
10
|
+
|
11
|
+
require 'awesome_nested_set'
|
12
|
+
require 'cancan'
|
13
|
+
require 'friendly_id'
|
14
|
+
require 'kaminari/activerecord'
|
15
|
+
require 'rack/cors'
|
16
|
+
require 'ransack'
|
17
|
+
|
18
|
+
module Ibrain
|
19
|
+
mattr_accessor :user_class
|
20
|
+
|
21
|
+
def self.user_class
|
22
|
+
case @@user_class
|
23
|
+
when Class
|
24
|
+
raise "Ibrain.user_class MUST be a String or Symbol object, not a Class object."
|
25
|
+
when String, Symbol
|
26
|
+
@@user_class.to_s.constantize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Load the same version defaults for all available Ibrain components
|
31
|
+
#
|
32
|
+
# @see Ibrain::Preferences::Configuration#load_defaults
|
33
|
+
def self.load_defaults(version)
|
34
|
+
Ibrain::Config.load_defaults(version)
|
35
|
+
Ibrain::Api::Config.load_defaults(version) if defined?(Ibrain::Api::Config)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Used to configure Ibrain.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
#
|
42
|
+
# Ibrain.config do |config|
|
43
|
+
# config.track_inventory_levels = false
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# This method is defined within the core gem on purpose.
|
47
|
+
# Some people may only wish to use the Core part of Ibrain.
|
48
|
+
def self.config(&_block)
|
49
|
+
yield(Ibrain::Config)
|
50
|
+
end
|
51
|
+
|
52
|
+
module Core
|
53
|
+
def self.does_ibrain_initializer_exist?(rails_paths, initializer_name)
|
54
|
+
rails_paths['config/initializers'].any? do |path|
|
55
|
+
File.exist?(Pathname.new(path).join(initializer_name))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private_class_method :does_ibrain_initializer_exist?
|
60
|
+
|
61
|
+
class GatewayError < RuntimeError; end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
require "ibrain/core/version"
|
66
|
+
|
67
|
+
require 'ibrain/core/class_constantizer'
|
68
|
+
require 'ibrain/core/environment_extension'
|
69
|
+
require 'ibrain/core/environment'
|
70
|
+
|
71
|
+
require "ibrain/core/engine"
|
72
|
+
|
73
|
+
require 'ibrain/i18n'
|
74
|
+
require 'ibrain/permitted_attributes'
|
75
|
+
require 'ibrain/permission_sets'
|
76
|
+
require 'ibrain/logger'
|
77
|
+
|
78
|
+
require 'ibrain/core/controller_helpers/response'
|
79
|
+
require 'ibrain/core/controller_helpers/current_host'
|
80
|
+
require 'ibrain/core/controller_helpers/strong_parameters'
|
81
|
+
require 'ibrain/core/controller_helpers/auth'
|
82
|
+
require 'ibrain/core/role_configuration'
|
83
|
+
|
84
|
+
require 'ibrain/core/validators/email'
|
85
|
+
require 'ibrain/user_class_handle'
|
86
|
+
require 'ibrain/encryptor'
|