incline 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +186 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +208 -0
- data/Rakefile +37 -0
- data/app/assets/fonts/incline/.keep +0 -0
- data/app/assets/images/incline/.keep +0 -0
- data/app/assets/images/incline/barcode-B.svg +181 -0
- data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
- data/app/assets/javascripts/incline/application.js +30 -0
- data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
- data/app/assets/javascripts/incline/datatables.js +22193 -0
- data/app/assets/javascripts/incline/escapeHtml.js +10 -0
- data/app/assets/javascripts/incline/inline_actions.js +479 -0
- data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
- data/app/assets/javascripts/incline/jquery.number.js +764 -0
- data/app/assets/javascripts/incline/regexMask.js +27 -0
- data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
- data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
- data/app/assets/stylesheets/incline/application.css +18 -0
- data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
- data/app/assets/stylesheets/incline/custom.scss +279 -0
- data/app/assets/stylesheets/incline/datatables.css +494 -0
- data/app/assets/stylesheets/incline/datepicker3.css +790 -0
- data/app/assets/stylesheets/incline/select2.css +484 -0
- data/app/controllers/incline/access_groups_controller.rb +127 -0
- data/app/controllers/incline/access_test_controller.rb +30 -0
- data/app/controllers/incline/account_activations_controller.rb +28 -0
- data/app/controllers/incline/application_controller.rb +11 -0
- data/app/controllers/incline/contact_controller.rb +34 -0
- data/app/controllers/incline/password_resets_controller.rb +113 -0
- data/app/controllers/incline/security_controller.rb +100 -0
- data/app/controllers/incline/sessions_controller.rb +50 -0
- data/app/controllers/incline/users_controller.rb +304 -0
- data/app/controllers/incline/welcome_controller.rb +19 -0
- data/app/helpers/incline/.keep +0 -0
- data/app/mailers/incline/application_mailer_base.rb +11 -0
- data/app/mailers/incline/contact_form.rb +19 -0
- data/app/mailers/incline/user_mailer.rb +45 -0
- data/app/models/incline/access_group.rb +121 -0
- data/app/models/incline/access_group_group_member.rb +12 -0
- data/app/models/incline/access_group_user_member.rb +10 -0
- data/app/models/incline/action_group.rb +12 -0
- data/app/models/incline/action_security.rb +222 -0
- data/app/models/incline/contact_message.rb +37 -0
- data/app/models/incline/disable_info.rb +20 -0
- data/app/models/incline/password_reset.rb +14 -0
- data/app/models/incline/password_reset_request.rb +14 -0
- data/app/models/incline/user.rb +437 -0
- data/app/models/incline/user_login_history.rb +30 -0
- data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
- data/app/views/incline/access_groups/_form.html.erb +19 -0
- data/app/views/incline/access_groups/_list.html.erb +60 -0
- data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
- data/app/views/incline/access_groups/edit.html.erb +2 -0
- data/app/views/incline/access_groups/index.html.erb +6 -0
- data/app/views/incline/access_groups/index.json.jbuilder +16 -0
- data/app/views/incline/access_groups/new.html.erb +2 -0
- data/app/views/incline/access_groups/show.html.erb +9 -0
- data/app/views/incline/access_groups/show.json.jbuilder +11 -0
- data/app/views/incline/contact/new.html.erb +22 -0
- data/app/views/incline/contact_form/contact.html.erb +16 -0
- data/app/views/incline/contact_form/contact.text.erb +13 -0
- data/app/views/incline/password_resets/edit.html.erb +16 -0
- data/app/views/incline/password_resets/new.html.erb +12 -0
- data/app/views/incline/security/_details.json.jbuilder +7 -0
- data/app/views/incline/security/_form.html.erb +20 -0
- data/app/views/incline/security/_list.html.erb +89 -0
- data/app/views/incline/security/_messages.json.jbuilder +6 -0
- data/app/views/incline/security/edit.html.erb +2 -0
- data/app/views/incline/security/index.html.erb +6 -0
- data/app/views/incline/security/index.json.jbuilder +16 -0
- data/app/views/incline/security/show.html.erb +31 -0
- data/app/views/incline/security/show.json.jbuilder +11 -0
- data/app/views/incline/sessions/new.html.erb +26 -0
- data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
- data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
- data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
- data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
- data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
- data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
- data/app/views/incline/users/_details.json.jbuilder +32 -0
- data/app/views/incline/users/_form.html.erb +21 -0
- data/app/views/incline/users/_list.html.erb +102 -0
- data/app/views/incline/users/_messages.json.jbuilder +6 -0
- data/app/views/incline/users/disable_confirm.html.erb +19 -0
- data/app/views/incline/users/edit.html.erb +5 -0
- data/app/views/incline/users/index.html.erb +6 -0
- data/app/views/incline/users/index.json.jbuilder +16 -0
- data/app/views/incline/users/new.html.erb +5 -0
- data/app/views/incline/users/show.html.erb +12 -0
- data/app/views/incline/users/show.json.jbuilder +11 -0
- data/app/views/incline/welcome/home.html.erb +5 -0
- data/app/views/layouts/application.html.erb +1 -0
- data/app/views/layouts/incline/_account_menu.html.erb +18 -0
- data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/app/views/layouts/incline/_footer.html.erb +13 -0
- data/app/views/layouts/incline/_header.html.erb +21 -0
- data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
- data/app/views/layouts/incline/_incline_app.html.erb +25 -0
- data/app/views/layouts/incline/_messages.html.erb +3 -0
- data/app/views/layouts/incline/_shim.html.erb +3 -0
- data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
- data/app/views/layouts/incline/application.html.erb +1 -0
- data/app/views/layouts/mailer.html.erb +2 -0
- data/app/views/layouts/mailer.text.erb +2 -0
- data/bin/rails +12 -0
- data/bin/test_scaffold.sh +10 -0
- data/config/routes.rb +61 -0
- data/db/migrate/20170511230126_create_incline_users.rb +26 -0
- data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
- data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
- data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
- data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
- data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
- data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
- data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
- data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
- data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
- data/db/seeds.rb +81 -0
- data/exe/new_incline_app +42 -0
- data/lib/generators/incline/install_generator.rb +259 -0
- data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
- data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.css +17 -0
- data/lib/generators/incline/templates/incline_application.html.erb +1 -0
- data/lib/generators/incline/templates/incline_application.js +12 -0
- data/lib/generators/incline/templates/incline_database.yml +25 -0
- data/lib/generators/incline/templates/incline_email.yml +20 -0
- data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
- data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
- data/lib/generators/incline/templates/incline_users.yml +64 -0
- data/lib/generators/incline/templates/incline_version.rb +3 -0
- data/lib/incline/auth_engine_base.rb +52 -0
- data/lib/incline/data_tables_request.rb +336 -0
- data/lib/incline/date_time_formats.rb +6 -0
- data/lib/incline/engine.rb +212 -0
- data/lib/incline/errors.rb +15 -0
- data/lib/incline/extensions/action_controller_base.rb +526 -0
- data/lib/incline/extensions/action_mailer_base.rb +66 -0
- data/lib/incline/extensions/action_view_base.rb +489 -0
- data/lib/incline/extensions/active_record_base.rb +308 -0
- data/lib/incline/extensions/application.rb +137 -0
- data/lib/incline/extensions/application_configuration.rb +50 -0
- data/lib/incline/extensions/connection_adapter.rb +55 -0
- data/lib/incline/extensions/date_time_value.rb +123 -0
- data/lib/incline/extensions/date_value.rb +77 -0
- data/lib/incline/extensions/decimal_value.rb +55 -0
- data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
- data/lib/incline/extensions/float_value.rb +59 -0
- data/lib/incline/extensions/form_builder.rb +617 -0
- data/lib/incline/extensions/integer_value.rb +54 -0
- data/lib/incline/extensions/jbuilder_generator.rb +38 -0
- data/lib/incline/extensions/jbuilder_template.rb +39 -0
- data/lib/incline/extensions/main_app.rb +40 -0
- data/lib/incline/extensions/numeric.rb +63 -0
- data/lib/incline/extensions/object.rb +31 -0
- data/lib/incline/extensions/resource_route_generator.rb +53 -0
- data/lib/incline/extensions/session.rb +113 -0
- data/lib/incline/extensions/string.rb +50 -0
- data/lib/incline/extensions/test_case.rb +764 -0
- data/lib/incline/extensions/time_zone_converter.rb +40 -0
- data/lib/incline/global_status.rb +236 -0
- data/lib/incline/helpers/route_hash_formatter.rb +46 -0
- data/lib/incline/json_log_formatter.rb +96 -0
- data/lib/incline/json_logger.rb +17 -0
- data/lib/incline/log.rb +153 -0
- data/lib/incline/number_formats.rb +17 -0
- data/lib/incline/recaptcha.rb +346 -0
- data/lib/incline/user_manager.rb +212 -0
- data/lib/incline/validators/email_validator.rb +45 -0
- data/lib/incline/validators/ip_address_validator.rb +32 -0
- data/lib/incline/validators/recaptcha_validator.rb +37 -0
- data/lib/incline/validators/safe_name_validator.rb +31 -0
- data/lib/incline/version.rb +3 -0
- data/lib/incline/work_path.rb +75 -0
- data/lib/incline.rb +197 -0
- data/lib/tasks/incline_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +43 -0
- data/lib/templates/erb/scaffold/_list.html.erb +81 -0
- data/lib/templates/erb/scaffold/edit.html.erb +1 -0
- data/lib/templates/erb/scaffold/index.html.erb +6 -0
- data/lib/templates/erb/scaffold/new.html.erb +1 -0
- data/lib/templates/erb/scaffold/show.html.erb +34 -0
- data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
- data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
- data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
- data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
- data/test/controllers/incline/access_groups_controller_test.rb +65 -0
- data/test/controllers/incline/access_test_controller_test.rb +53 -0
- data/test/controllers/incline/contact_controller_test.rb +32 -0
- data/test/controllers/incline/security_controller_test.rb +39 -0
- data/test/controllers/incline/welcome_controller_test.rb +16 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +12 -0
- data/test/dummy/app/assets/stylesheets/application.css +17 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
- data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config/application.rb +38 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +34 -0
- data/test/dummy/config/email.yml +24 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +45 -0
- data/test/dummy/config/environments/production.rb +85 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/schema.rb +108 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/extensions/action_controller_base_extensions_test.rb +21 -0
- data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
- data/test/extensions/action_view_base_extensions_test.rb +267 -0
- data/test/extensions/active_record_extensions_test.rb +173 -0
- data/test/extensions/application_configuration_extensions_test.rb +46 -0
- data/test/extensions/application_extensions_test.rb +23 -0
- data/test/extensions/connection_adapter_extensions_test.rb +54 -0
- data/test/extensions/date_time_value_extensions_test.rb +104 -0
- data/test/extensions/date_value_extensions_test.rb +102 -0
- data/test/extensions/decimal_value_extensions_test.rb +85 -0
- data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
- data/test/extensions/float_value_extensions_test.rb +78 -0
- data/test/extensions/form_builder_extensions_test.rb +28 -0
- data/test/extensions/integer_value_extensions_test.rb +78 -0
- data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
- data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
- data/test/extensions/main_app_extensions_test.rb +55 -0
- data/test/extensions/numeric_extensions_test.rb +76 -0
- data/test/extensions/object_extensions_test.rb +104 -0
- data/test/extensions/session_extensions_test.rb +69 -0
- data/test/extensions/string_extensions_test.rb +32 -0
- data/test/extensions/test_case_extensions_test.rb +538 -0
- data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
- data/test/fixtures/incline/access_group_group_members.yml +1 -0
- data/test/fixtures/incline/access_group_user_members.yml +1 -0
- data/test/fixtures/incline/access_groups.yml +13 -0
- data/test/fixtures/incline/action_groups.yml +6 -0
- data/test/fixtures/incline/action_securities.yml +18 -0
- data/test/fixtures/incline/user_login_histories.yml +1 -0
- data/test/fixtures/incline/users.yml +64 -0
- data/test/incline_test.rb +63 -0
- data/test/integration/incline/users_edit_test.rb +180 -0
- data/test/integration/incline/users_login_test.rb +105 -0
- data/test/integration/incline/users_signup_test.rb +147 -0
- data/test/integration/navigation_test.rb +11 -0
- data/test/lib/data_tables_request_test.rb +245 -0
- data/test/lib/date_time_formats_test.rb +111 -0
- data/test/lib/global_status_test.rb +89 -0
- data/test/lib/json_log_formatter_test.rb +43 -0
- data/test/lib/log_test.rb +36 -0
- data/test/lib/recaptcha_test.rb +75 -0
- data/test/lib/user_manager_test.rb +47 -0
- data/test/lib/work_path_test.rb +18 -0
- data/test/models/incline/access_group_group_member_test.rb +30 -0
- data/test/models/incline/access_group_test.rb +60 -0
- data/test/models/incline/access_group_user_member_test.rb +29 -0
- data/test/models/incline/action_group_test.rb +27 -0
- data/test/models/incline/action_security_test.rb +176 -0
- data/test/models/incline/contact_message_test.rb +66 -0
- data/test/models/incline/disable_info_test.rb +29 -0
- data/test/models/incline/password_reset_request_test.rb +35 -0
- data/test/models/incline/password_reset_test.rb +51 -0
- data/test/models/incline/user_login_history_test.rb +31 -0
- data/test/models/incline/user_test.rb +91 -0
- data/test/test_helper.rb +42 -0
- data/test/validators/email_validator_test.rb +102 -0
- data/test/validators/ip_address_validator_test.rb +107 -0
- data/test/validators/recaptcha_validator_test.rb +57 -0
- data/test/validators/safe_name_validator_test.rb +101 -0
- metadata +584 -0
@@ -0,0 +1,526 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
|
5
|
+
##
|
6
|
+
# Adds some extra functionality to the base controller definition.
|
7
|
+
module ActionControllerBase
|
8
|
+
|
9
|
+
##
|
10
|
+
# Adds some class methods to the base action controller.
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
##
|
14
|
+
# Turn on auto API for the controller.
|
15
|
+
def enable_auto_api
|
16
|
+
@enable_auto_api = true
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Turn off auto API for the controller.
|
21
|
+
def disable_auto_api
|
22
|
+
@enable_auto_api = false
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Determines if the controller is configured for auto API.
|
27
|
+
def auto_api?
|
28
|
+
@enable_auto_api ||= false
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Enables or disables HTTP (non-SSL) for actions.
|
33
|
+
#
|
34
|
+
# Pass +false+ to disable HTTP for all actions(default).
|
35
|
+
# Pass +true+ to enable HTTP for all actions.
|
36
|
+
# Pass action names to enable HTTP for specific actions.
|
37
|
+
#
|
38
|
+
# With no arguments, the current setting is returned.
|
39
|
+
#
|
40
|
+
# allow_non_ssl false
|
41
|
+
# allow_non_ssl true
|
42
|
+
# allow_non_ssl :home, :about
|
43
|
+
#
|
44
|
+
def allow_non_ssl(*args)
|
45
|
+
if args.blank?
|
46
|
+
@allow_non_ssl ||= false
|
47
|
+
else
|
48
|
+
@allow_non_ssl = setting_value(args)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Enables anonymous access for actions.
|
54
|
+
#
|
55
|
+
# Pass +false+ to disable anonymous access for all actions(default).
|
56
|
+
# Pass +true+ to allow anonymous access for all actions.
|
57
|
+
# Pass action names to enable anonymous access for specific actions.
|
58
|
+
#
|
59
|
+
# With no arguments, the current setting is returned.
|
60
|
+
#
|
61
|
+
# allow_anon false
|
62
|
+
# allow_anon true
|
63
|
+
# allow_anon :home, :about
|
64
|
+
#
|
65
|
+
def allow_anon(*args)
|
66
|
+
if args.blank?
|
67
|
+
@allow_anon ||= false
|
68
|
+
else
|
69
|
+
@allow_anon = setting_value(args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Enables requiring a system administrator for actions.
|
75
|
+
#
|
76
|
+
# Pass +false+ to allow non-system administrators access for all actions(default).
|
77
|
+
# Pass +true+ to require system administrators for all actions.
|
78
|
+
# Pass action names to require system administrators for specific actions.
|
79
|
+
#
|
80
|
+
# With no arguments, the current setting is returned.
|
81
|
+
#
|
82
|
+
# require_admin false
|
83
|
+
# require_admin true
|
84
|
+
# require_admin :new, :edit, :create, :update, :destroy
|
85
|
+
#
|
86
|
+
def require_admin(*args)
|
87
|
+
if args.blank?
|
88
|
+
@require_admin ||= false
|
89
|
+
else
|
90
|
+
@require_admin = setting_value(args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Enables requiring an anonymous user for actions.
|
96
|
+
#
|
97
|
+
# Pass +false+ to allow logged in users access for all actions(default).
|
98
|
+
# Pass +true+ to require anonymous users for all actions.
|
99
|
+
# Pass action names to require anonymous for specific actions.
|
100
|
+
#
|
101
|
+
# With no arguments, the current setting is returned.
|
102
|
+
#
|
103
|
+
# require_anon false
|
104
|
+
# require_anon true
|
105
|
+
# require_anon :new, :edit, :create, :update, :destroy
|
106
|
+
#
|
107
|
+
def require_anon(*args)
|
108
|
+
if args.blank?
|
109
|
+
@require_anon ||= false
|
110
|
+
else
|
111
|
+
@require_anon = setting_value(args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Determines if the current request can be allowed with an anonymous user.
|
117
|
+
#
|
118
|
+
# Overridden by require_admin_for_request?
|
119
|
+
# Implied by require_anon_for_request?
|
120
|
+
def allow_anon_for?(action)
|
121
|
+
require_anon_for?(action) || setting_for_action(allow_anon, action)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Determines if the current request requires a system administrator.
|
126
|
+
#
|
127
|
+
# Overrides all other access requirements.
|
128
|
+
def require_admin_for?(action)
|
129
|
+
setting_for_action require_admin, action
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Determines if the current request requires an anonymous user.
|
134
|
+
#
|
135
|
+
# Overridden by require_admin_for_request?
|
136
|
+
# Implies allow_anon_for_request?
|
137
|
+
def require_anon_for?(action)
|
138
|
+
setting_for_action require_anon, action
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def setting_value(args)
|
144
|
+
if args.include?(false)
|
145
|
+
false
|
146
|
+
elsif args.include?(true)
|
147
|
+
true
|
148
|
+
else
|
149
|
+
args.map{|v| v.is_a?(::Symbol) ? v : v.to_s.to_sym }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def setting_for_action(setting, action)
|
154
|
+
return false unless setting
|
155
|
+
if setting.is_a?(::Array)
|
156
|
+
return false unless setting.include?(action.to_sym)
|
157
|
+
end
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Enforces SSL and catches Incline::NotLoggedIn exceptions.
|
165
|
+
def self.included(base)
|
166
|
+
base.extend ClassMethods
|
167
|
+
base.class_eval do
|
168
|
+
|
169
|
+
# Force SSL under production environments unless allow_http_for_request returns true.
|
170
|
+
if Rails.env.production?
|
171
|
+
force_ssl unless: :allow_http_for_request?
|
172
|
+
end
|
173
|
+
|
174
|
+
# Process user authorization for all actions except the GET/POST api actions.
|
175
|
+
# These get to be authorized once the actual action is selected.
|
176
|
+
before_action :valid_user?, except: [ :api ]
|
177
|
+
|
178
|
+
undef process_action
|
179
|
+
|
180
|
+
##
|
181
|
+
# Override the default to enable auto-api behavior if desired.
|
182
|
+
def process_action(method_name, *args) #:nodoc:
|
183
|
+
if self.class.auto_api?
|
184
|
+
unless process_api_action(false, nil)
|
185
|
+
super method_name, *args
|
186
|
+
end
|
187
|
+
else
|
188
|
+
super method_name, *args
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
rescue_from ::Incline::NotLoggedIn do |exception|
|
193
|
+
flash[:info] = exception.message
|
194
|
+
store_location
|
195
|
+
redirect_to(incline.login_url)
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Renders the view as a CSV file.
|
203
|
+
#
|
204
|
+
# Set the +filename+ you would like to provide to the client, or leave it nil to use the action name.
|
205
|
+
# Set the +view_name+ you would like to render, or leave it nil to use the action name.
|
206
|
+
def render_csv(filename = nil, view_name = nil)
|
207
|
+
|
208
|
+
filename ||= params[:action]
|
209
|
+
view_name ||= params[:action]
|
210
|
+
filename.downcase!
|
211
|
+
filename += '.csv' unless filename[-4..-1] == '.csv'
|
212
|
+
|
213
|
+
headers['Content-Type'] = 'text/csv'
|
214
|
+
headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
|
215
|
+
|
216
|
+
render view_name, layout: false
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# A redirects to a previously stored location or to the default location.
|
221
|
+
#
|
222
|
+
# Usually this will be used to return to an action after a user logs in.
|
223
|
+
def redirect_back_or(default)
|
224
|
+
redirect_to session[:forwarding_url] || default
|
225
|
+
session.delete :forwarding_url
|
226
|
+
end
|
227
|
+
|
228
|
+
##
|
229
|
+
# Stores the current URL to be used with #redirect_back_or.
|
230
|
+
def store_location
|
231
|
+
session[:forwarding_url] = request.url if request.get?
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
protected
|
238
|
+
|
239
|
+
##
|
240
|
+
# This method maps the requested action into the actual action performed.
|
241
|
+
#
|
242
|
+
# By default, the requested action is returned. If for some reason you want to use a different
|
243
|
+
# action in your API, override this method in your controller and map the actions as appropriate.
|
244
|
+
#
|
245
|
+
# The actions you can expect to translate are 'index', 'new', 'show', and 'edit' for GET requests, and
|
246
|
+
# 'create', 'update', and 'destroy' for POST requests. They will be string values or nil, they will not be
|
247
|
+
# symbols.
|
248
|
+
#
|
249
|
+
# The default behavior causes the API to "fall through" to your standard controller methods.
|
250
|
+
#
|
251
|
+
# The API is accessed by either a POST or a GET request that specifies an `action` parameter. The action
|
252
|
+
# gets translated to the acceptable actions listed above and then run through this method for translation.
|
253
|
+
#
|
254
|
+
def map_api_action(requested_action) #:doc:
|
255
|
+
requested_action
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
##
|
260
|
+
# Authorizes access for the action.
|
261
|
+
#
|
262
|
+
# * With no arguments, this will validate that a user is currently logged in, but does not check their permission.
|
263
|
+
# * With an argument of true, this will validate that the user currently logged in is an administrator.
|
264
|
+
# * With one or more strings, this will validate that the user currently logged in has at least one or more
|
265
|
+
# of the named permissions.
|
266
|
+
#
|
267
|
+
# authorize!
|
268
|
+
# authorize! true
|
269
|
+
# authorize! "Safety Manager", "HR Manager"
|
270
|
+
#
|
271
|
+
# If no user is logged in, then the user will be redirected to the login page and the method will return false.
|
272
|
+
# If a user is logged in, but is not authorized, then the user will be redirected to the home page and the method
|
273
|
+
# will return false.
|
274
|
+
# If the user is authorized, the method will return true.
|
275
|
+
def authorize!(*accepted_groups) #:doc:
|
276
|
+
begin
|
277
|
+
|
278
|
+
# an authenticated user must exist.
|
279
|
+
unless logged_in?
|
280
|
+
store_location
|
281
|
+
|
282
|
+
raise_not_logged_in "You need to login to access '#{request.fullpath}'.",
|
283
|
+
'nobody is logged in'
|
284
|
+
end
|
285
|
+
|
286
|
+
if system_admin?
|
287
|
+
log_authorize_success 'user is system admin'
|
288
|
+
else
|
289
|
+
# clean up the group list.
|
290
|
+
accepted_groups ||= []
|
291
|
+
accepted_groups.flatten!
|
292
|
+
accepted_groups.delete false
|
293
|
+
accepted_groups.delete ''
|
294
|
+
|
295
|
+
if accepted_groups.include?(true)
|
296
|
+
# group_list contains "true" so only a system admin may continue.
|
297
|
+
raise_authorize_failure "Your are not authorized to access '#{request.fullpath}'.",
|
298
|
+
'requires system administrator'
|
299
|
+
|
300
|
+
elsif accepted_groups.blank?
|
301
|
+
# group_list is empty or contained nothing but empty strings and boolean false.
|
302
|
+
# everyone can continue.
|
303
|
+
log_authorize_success 'only requires authenticated user'
|
304
|
+
|
305
|
+
else
|
306
|
+
# the group list contains one or more authorized groups.
|
307
|
+
# we want them to all be uppercase strings.
|
308
|
+
accepted_groups = accepted_groups.map{|v| v.to_s.upcase}.sort
|
309
|
+
result = current_user.has_any_group?(*accepted_groups)
|
310
|
+
unless result
|
311
|
+
raise_authorize_failure "You are not authorized to access '#{request.fullpath}'.",
|
312
|
+
"requires one of: #{accepted_groups.inspect}"
|
313
|
+
end
|
314
|
+
log_authorize_success "user has #{result.inspect}"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
rescue ::Incline::NotAuthorized => err
|
319
|
+
|
320
|
+
flash[:danger] = err.message
|
321
|
+
redirect_to root_url and return false
|
322
|
+
end
|
323
|
+
true
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
##
|
328
|
+
# Is the current request for JSON data?
|
329
|
+
#
|
330
|
+
# Redirects are generally bad when JSON data is requested.
|
331
|
+
# For instance a `create` request in JSON format should return data, not redirect to `show`.
|
332
|
+
def json_request? #:doc:
|
333
|
+
request.format.to_s.downcase == 'json'
|
334
|
+
end
|
335
|
+
|
336
|
+
##
|
337
|
+
# Is the current request an inline request?
|
338
|
+
#
|
339
|
+
# JSON requests are always considered inline, otherwise we check to see if the "inline" parameter is set to a true value.
|
340
|
+
#
|
341
|
+
# Primarily this would be used to strip the layour from rendered content.
|
342
|
+
def inline_request?
|
343
|
+
json_request? || params[:inline].to_bool
|
344
|
+
end
|
345
|
+
|
346
|
+
##
|
347
|
+
# Determines if the current request can be allowed via HTTP (non-SSL).
|
348
|
+
def allow_http_for_request? #:doc:
|
349
|
+
self.class.setting_for_action self.class.allow_non_ssl, params[:action]
|
350
|
+
end
|
351
|
+
|
352
|
+
##
|
353
|
+
# Determines if the current request can be allowed with an anonymous user.
|
354
|
+
#
|
355
|
+
# Overridden by require_admin_for_request?
|
356
|
+
# Implied by require_anon_for_request?
|
357
|
+
def allow_anon_for_request? #:doc:
|
358
|
+
self.class.allow_anon_for? params[:action]
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# Determines if the current request requires a system administrator.
|
363
|
+
#
|
364
|
+
# Overrides all other access requirements.
|
365
|
+
def require_admin_for_request? #:doc:
|
366
|
+
self.class.require_admin_for? params[:action]
|
367
|
+
end
|
368
|
+
|
369
|
+
##
|
370
|
+
# Determines if the current request requires an anonymous user.
|
371
|
+
#
|
372
|
+
# Overridden by require_admin_for_request?
|
373
|
+
# Implies allow_anon_for_request?
|
374
|
+
def require_anon_for_request? #:doc:
|
375
|
+
self.class.require_anon_for? params[:action]
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
private
|
380
|
+
|
381
|
+
##
|
382
|
+
# Validates that the current user is authorized for the current request.
|
383
|
+
#
|
384
|
+
# This method is called for every action except the :api action.
|
385
|
+
# For the :api action, this method will not be called until the actual requested action is performed.
|
386
|
+
#
|
387
|
+
# One of four scenarios are possible:
|
388
|
+
# 1. If the +require_admin+ method applies to the current action, then a system administrator must be logged in.
|
389
|
+
# 1. If a nobody is logged in, then the user will be redirected to the login url.
|
390
|
+
# 2. If a system administrator is logged in, then access is granted.
|
391
|
+
# 3. Non-system administrators will be redirected to the root url.
|
392
|
+
# 2. If the +require_anon+ method applies to the current action, then a user cannot be logged in.
|
393
|
+
# 1. If a user is logged in, a warning message is set and the user is redirected to their account.
|
394
|
+
# 2. If no user is logged in, then access is granted.
|
395
|
+
# 3. If the +allow_anon+ method applies to the current action, then access is granted.
|
396
|
+
# 4. The action doesn't require a system administrator, but does require a valid user to be logged in.
|
397
|
+
# 1. If nobody is logged in, then the user will be redirected to the login url.
|
398
|
+
# 2. If a system administrator is logged in, then access is granted.
|
399
|
+
# 3. If the action doesn't have any required permissions, then access is granted to any logged in user.
|
400
|
+
# 4. If the action has required permissions and the logged in user shares at least one, then access is granted.
|
401
|
+
# 5. Users without at least one required permission are redirected to the root url.
|
402
|
+
#
|
403
|
+
# Two of the scenarios are configured at design time. If you use +require_admin+ or +allow_anon+,
|
404
|
+
# they cannot be changed at runtime. The idea is that anything that allows anonymous access will always allow
|
405
|
+
# anonymous access during runtime and anything that requires admin access will always require admin access during
|
406
|
+
# runtime.
|
407
|
+
#
|
408
|
+
# The third scenario is what would be used by most actions. Using the +admin+ controller, which requires admin
|
409
|
+
# access, you can customize the permissions required for each available route. Using the +users+ controller,
|
410
|
+
# admins can assign permissions to other users.
|
411
|
+
#
|
412
|
+
def valid_user? #:doc:
|
413
|
+
if require_admin_for_request?
|
414
|
+
authorize! true
|
415
|
+
elsif require_anon_for_request?
|
416
|
+
if logged_in?
|
417
|
+
flash[:warning] = 'The specified action cannot be performed while logged in.'
|
418
|
+
redirect_to current_user
|
419
|
+
end
|
420
|
+
elsif allow_anon_for_request?
|
421
|
+
true
|
422
|
+
else
|
423
|
+
action = Incline::ActionSecurity.valid_items[self.class.controller_path, params[:action]]
|
424
|
+
if action && action.groups.count > 0
|
425
|
+
authorize! action.groups.pluck(:name)
|
426
|
+
else
|
427
|
+
authorize!
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
|
433
|
+
def process_api_action(raise_on_invalid_action = true, default_get_action = 'index')
|
434
|
+
api_action =
|
435
|
+
map_api_action(
|
436
|
+
if request.post?
|
437
|
+
# A post request can create, update, or destroy.
|
438
|
+
# In addition we allow index to post since DataTables can send quite a bit of data with server-side
|
439
|
+
# processing.
|
440
|
+
# The post action can be provided as a query parameter or a form parameter with the form parameter
|
441
|
+
# taking priority.
|
442
|
+
{
|
443
|
+
nil => 'index',
|
444
|
+
'list' => 'index',
|
445
|
+
'index' => 'index',
|
446
|
+
'new' => 'create',
|
447
|
+
'create' => 'create',
|
448
|
+
'edit' => 'update',
|
449
|
+
'update' => 'update',
|
450
|
+
'remove' => 'destroy',
|
451
|
+
'destroy' => 'destroy'
|
452
|
+
}[request.request_parameters.delete('action') || request.query_parameters.delete('action')]
|
453
|
+
elsif request.get?
|
454
|
+
# For the most part, these shouldn't be used except for maybe index and show.
|
455
|
+
# The new and edit actions could be used if for some reason you need to supply data to the ajax form
|
456
|
+
# calling these actions, e.g. - a list of locations.
|
457
|
+
# Datatables Editor does not use any of them.
|
458
|
+
# Datatables will simple be requesting the index action in JSON format.
|
459
|
+
# To remain consistent though, you can use '?action=list' to perform the same feat.
|
460
|
+
{
|
461
|
+
'list' => 'index',
|
462
|
+
'index' => 'index',
|
463
|
+
'new' => 'new',
|
464
|
+
'show' => 'show',
|
465
|
+
'edit' => 'edit'
|
466
|
+
}[request.query_parameters.delete('action')] || default_get_action
|
467
|
+
else
|
468
|
+
nil
|
469
|
+
end
|
470
|
+
)
|
471
|
+
|
472
|
+
if api_action
|
473
|
+
# Datatables Editor sends the 'data' in the 'data' parameter.
|
474
|
+
# We simple want to move that up a level so `params[:data][:user][:name]` becomes `params[:user][:name]`.
|
475
|
+
data = request.params.delete('data')
|
476
|
+
unless data.blank?
|
477
|
+
# get the first entry in the hash.
|
478
|
+
id, item = data.first
|
479
|
+
|
480
|
+
# if the id is in AAAAA_NNN format, then we can extract the ID from it.
|
481
|
+
if id.include?('_')
|
482
|
+
params[:id] = id.split('_').last.to_i
|
483
|
+
end
|
484
|
+
|
485
|
+
# merge the item data into the params array.
|
486
|
+
params.merge! item
|
487
|
+
end
|
488
|
+
|
489
|
+
# since we are processing for an API request, we should return JSON.
|
490
|
+
request.format = :json
|
491
|
+
|
492
|
+
# finally, we'll start over on processing the stack.
|
493
|
+
# This should ensure the appropriate `before_action` filters are called for the new action.
|
494
|
+
process api_action
|
495
|
+
else
|
496
|
+
# raise an error.
|
497
|
+
raise Incline::InvalidApiCall, 'Invalid API Action' if raise_on_invalid_action
|
498
|
+
nil
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def raise_authorize_failure(message, log_message = nil)
|
503
|
+
log_authorize_failure message, log_message
|
504
|
+
raise Incline::NotAuthorized.new(message)
|
505
|
+
end
|
506
|
+
|
507
|
+
def raise_not_logged_in(message, log_message = nil)
|
508
|
+
log_authorize_failure message, log_message
|
509
|
+
raise Incline::NotLoggedIn.new(message)
|
510
|
+
end
|
511
|
+
|
512
|
+
def log_authorize_failure(message, log_message = nil)
|
513
|
+
log_message ||= message
|
514
|
+
Incline::Log::info "AUTH(FAILURE): #{request.fullpath}, #{current_user}, #{log_message}"
|
515
|
+
end
|
516
|
+
|
517
|
+
def log_authorize_success(message)
|
518
|
+
Incline::Log::info "AUTH(SUCCESS): #{request.fullpath}, #{current_user}, #{message}"
|
519
|
+
end
|
520
|
+
|
521
|
+
end
|
522
|
+
|
523
|
+
end
|
524
|
+
|
525
|
+
ActionController::Base.include Incline::Extensions::ActionControllerBase
|
526
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'action_mailer'
|
2
|
+
|
3
|
+
module Incline::Extensions
|
4
|
+
|
5
|
+
##
|
6
|
+
# Adds the default_hostname, default_sender, and default_recipient methods to the ApplicationMailer::Base class.
|
7
|
+
module ActionMailerBase
|
8
|
+
|
9
|
+
##
|
10
|
+
# Adds the extra class methods to the ApplicationMailer::Base class.
|
11
|
+
module ClassMethods
|
12
|
+
##
|
13
|
+
# Gets the default hostname for messages.
|
14
|
+
def default_hostname
|
15
|
+
@default_hostname ||= Incline::email_config[:default_hostname]
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Gets the default sender for messages.
|
20
|
+
def default_sender
|
21
|
+
@default_sender ||= Incline::email_config[:sender]
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Gets the default recipient for messages.
|
26
|
+
def default_recipient
|
27
|
+
@default_recipient ||= Incline::email_config[:default_recipient]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Sets the default from and to address according to the configuration.
|
33
|
+
def self.included(base)
|
34
|
+
base.extend ClassMethods
|
35
|
+
|
36
|
+
class << self
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
if method_defined?(:inherited)
|
41
|
+
alias_method :incline_original_inherited, :inherited
|
42
|
+
else
|
43
|
+
def incline_original_inherited(subclass)
|
44
|
+
# Do nothing.
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def inherited(subclass)
|
49
|
+
incline_original_inherited subclass
|
50
|
+
|
51
|
+
default(
|
52
|
+
{
|
53
|
+
from: default_sender,
|
54
|
+
to: default_recipient
|
55
|
+
}
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
ActionMailer::Base.include Incline::Extensions::ActionMailerBase
|