incline 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
11
|
+
* file per style scope.
|
|
12
|
+
*
|
|
13
|
+
* This manifest inherits the default behavior of the Incline gem.
|
|
14
|
+
*
|
|
15
|
+
*= require incline/application
|
|
16
|
+
*= require_self
|
|
17
|
+
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render 'layouts/incline/incline_app' %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// This manifest inherits the default functionality from the Incline gem.
|
|
8
|
+
//
|
|
9
|
+
//= require incline/application
|
|
10
|
+
|
|
11
|
+
// Require any addition scripts you want/need, but you probably do not want to use "require_tree ." since that may
|
|
12
|
+
// lead to over-bloated JS code.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SQLite version 3.x
|
|
2
|
+
# gem install sqlite3
|
|
3
|
+
#
|
|
4
|
+
# Ensure the SQLite 3 gem is defined in your Gemfile
|
|
5
|
+
# gem 'sqlite3'
|
|
6
|
+
#
|
|
7
|
+
default: &default
|
|
8
|
+
adapter: sqlite3
|
|
9
|
+
pool: 5
|
|
10
|
+
timeout: 5000
|
|
11
|
+
|
|
12
|
+
development:
|
|
13
|
+
<<: *default
|
|
14
|
+
database: db/development.sqlite3
|
|
15
|
+
|
|
16
|
+
# Warning: The database defined as "test" will be erased and
|
|
17
|
+
# re-generated from your development database when you run "rake".
|
|
18
|
+
# Do not set this db to the same as development or production.
|
|
19
|
+
test:
|
|
20
|
+
<<: *default
|
|
21
|
+
database: db/test.sqlite3
|
|
22
|
+
|
|
23
|
+
production:
|
|
24
|
+
<<: *default
|
|
25
|
+
database: db/production.sqlite3
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
default: &default
|
|
2
|
+
default_url: www.example.com
|
|
3
|
+
default_recipient: someone@example.com
|
|
4
|
+
sender: noreply@example.com
|
|
5
|
+
server: mail.example.com
|
|
6
|
+
auth: :plain
|
|
7
|
+
start_tls: false
|
|
8
|
+
ssl: true
|
|
9
|
+
port: 465
|
|
10
|
+
user: <%= (Rails.application.secrets['email'] || {})['user'] %>
|
|
11
|
+
password: <%= (Rails.application.secrets['email'] || {})['password'] %>
|
|
12
|
+
|
|
13
|
+
development:
|
|
14
|
+
<<: *default
|
|
15
|
+
|
|
16
|
+
test:
|
|
17
|
+
<<: *default
|
|
18
|
+
|
|
19
|
+
production:
|
|
20
|
+
<<: *default
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
|
2
|
+
|
|
3
|
+
one:
|
|
4
|
+
name: George Jetson
|
|
5
|
+
email: george@example.com
|
|
6
|
+
activated: true
|
|
7
|
+
enabled: true
|
|
8
|
+
system_admin: false
|
|
9
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
10
|
+
activated_at: <%= 20.days.ago %>
|
|
11
|
+
last_login_at: <%= 5.hours.ago %>
|
|
12
|
+
last_login_ip: 10.20.30.40
|
|
13
|
+
|
|
14
|
+
two:
|
|
15
|
+
name: Fred Flintstone
|
|
16
|
+
email: fred@example.com
|
|
17
|
+
activated: true
|
|
18
|
+
enabled: true
|
|
19
|
+
system_admin: false
|
|
20
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
21
|
+
activated_at: <%= 9.days.ago %>
|
|
22
|
+
last_login_at: <%= 3.days.ago %>
|
|
23
|
+
last_login_ip: 1:2::3:4
|
|
24
|
+
|
|
25
|
+
admin:
|
|
26
|
+
name: Sys Admin
|
|
27
|
+
email: admin@example.com
|
|
28
|
+
activated: true
|
|
29
|
+
enabled: true
|
|
30
|
+
system_admin: true
|
|
31
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
32
|
+
activated_at: <%= 30.days.ago %>
|
|
33
|
+
|
|
34
|
+
basic:
|
|
35
|
+
name: Basic User
|
|
36
|
+
email: basic@example.com
|
|
37
|
+
activated: true
|
|
38
|
+
enabled: true
|
|
39
|
+
system_admin: false
|
|
40
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
41
|
+
activated_at: <%= 10.days.ago %>
|
|
42
|
+
|
|
43
|
+
disabled:
|
|
44
|
+
name: Bad User
|
|
45
|
+
email: bad@example.com
|
|
46
|
+
activated: true
|
|
47
|
+
enabled: false
|
|
48
|
+
system_admin: false
|
|
49
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
50
|
+
disabled_by: admin@example.com
|
|
51
|
+
disabled_at: <%= 30.days.ago %>
|
|
52
|
+
activated_at: <%= 31.days.ago %>
|
|
53
|
+
|
|
54
|
+
recently_disabled:
|
|
55
|
+
name: Recent User
|
|
56
|
+
email: recent@example.com
|
|
57
|
+
activated: true
|
|
58
|
+
enabled: false
|
|
59
|
+
system_admin: false
|
|
60
|
+
password_digest: <%= Incline::User::digest 'Password123' %>
|
|
61
|
+
disabled_by: admin@example.com
|
|
62
|
+
disabled_at: <%= 1.days.ago %>
|
|
63
|
+
activated_at: <%= 3.days.ago %>
|
|
64
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
module Incline
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# Defines an auth engine.
|
|
6
|
+
class AuthEngineBase
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# The auth engine initializer should take a hash of parameters.
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
@options = options || {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# The authenticate method takes an email and password to authenticate a user and the client IP for logging purposes.
|
|
16
|
+
def authenticate(email, password, client_ip)
|
|
17
|
+
nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Logs a failure message for a user. The user can either be an Incline::User model or the email address used
|
|
24
|
+
# in the attempt.
|
|
25
|
+
def add_failure_to(user, message, client_ip) # :doc:
|
|
26
|
+
Incline::Log::info "LOGIN(#{user}) FAILURE FROM #{client_ip}: #{message}"
|
|
27
|
+
history_length = 2
|
|
28
|
+
unless user.is_a?(::Incline::User)
|
|
29
|
+
message = "[email: #{user}] #{message}"
|
|
30
|
+
user = User.anonymous
|
|
31
|
+
history_length = 6
|
|
32
|
+
end
|
|
33
|
+
purge_old_history_for user, history_length
|
|
34
|
+
user.login_histories.create(ip_address: client_ip, successful: false, message: message)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Logs a success message for a user.
|
|
39
|
+
def add_success_to(user, message, client_ip) # :doc:
|
|
40
|
+
Incline::Log::info "LOGIN(#{user}) SUCCESS FROM #{client_ip}: #{message}"
|
|
41
|
+
purge_old_history_for user
|
|
42
|
+
user.login_histories.create(ip_address: client_ip, successful: true, message: message)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def purge_old_history_for(user, max_months = 2)
|
|
48
|
+
user.login_histories.where('"incline_user_login_histories"."created_at" <= ?', Time.now - max_months.months).delete_all
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
module Incline
|
|
2
|
+
##
|
|
3
|
+
# Parses the parameters sent by a request from datatables.
|
|
4
|
+
class DataTablesRequest
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Draw counter.
|
|
8
|
+
def draw
|
|
9
|
+
@config[:draw]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# First record to return.
|
|
14
|
+
def start
|
|
15
|
+
@config[:start]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Number of records to return.
|
|
20
|
+
#
|
|
21
|
+
# Can be any positive value, or -1 to indicate that all records should be returned.
|
|
22
|
+
def length
|
|
23
|
+
@config[:length]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Text or regular expression to search with.
|
|
28
|
+
def search
|
|
29
|
+
@config[:search]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# The columns requested.
|
|
34
|
+
def columns
|
|
35
|
+
@config[:columns]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# The row ordering.
|
|
40
|
+
def ordering
|
|
41
|
+
@config[:order]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
# If we are searching for a specific ID, this is the ID to locate.
|
|
46
|
+
#
|
|
47
|
+
#
|
|
48
|
+
def locate_id
|
|
49
|
+
@config[:locate_id]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Initializes the data tables request parameters.
|
|
54
|
+
def initialize(params = {}, &block)
|
|
55
|
+
raise ArgumentError, 'A block is required to return the starting ActiveRecord scope.' unless block_given?
|
|
56
|
+
|
|
57
|
+
@config = {}
|
|
58
|
+
@config[:starting_scope] = block
|
|
59
|
+
|
|
60
|
+
params = params.deep_symbolize_keys
|
|
61
|
+
|
|
62
|
+
force_regex = params[:force_regex]
|
|
63
|
+
|
|
64
|
+
if params[:draw]
|
|
65
|
+
@config[:draw] = params[:draw].to_s.to_i
|
|
66
|
+
@config[:start] = params[:start].to_s.to_i
|
|
67
|
+
@config[:length] = params[:length].to_s.to_i
|
|
68
|
+
@config[:locate_id] = params[:locate_id].to_s.to_i
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
tmp = params[:search]
|
|
72
|
+
if tmp && !tmp[:value].blank?
|
|
73
|
+
if tmp[:regex].to_bool || force_regex
|
|
74
|
+
@config[:search] =
|
|
75
|
+
if tmp[:value].is_a?(::Regexp)
|
|
76
|
+
tmp[:value]
|
|
77
|
+
else
|
|
78
|
+
begin
|
|
79
|
+
Regexp.new(tmp[:value].to_s, Regexp::IGNORECASE)
|
|
80
|
+
rescue RegexpError
|
|
81
|
+
tmp[:value].to_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
elsif tmp
|
|
85
|
+
@config[:search] = tmp[:value].to_s
|
|
86
|
+
end
|
|
87
|
+
else
|
|
88
|
+
@config[:search] = nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
tmp = params[:columns]
|
|
92
|
+
@config[:columns] = [ ]
|
|
93
|
+
if tmp
|
|
94
|
+
tmp = tmp.each_with_index.to_a.map{|(a,b)| [b.to_s,a]}.to_h.deep_symbolize_keys if tmp.is_a?(::Array)
|
|
95
|
+
tmp.each do |id, col|
|
|
96
|
+
col[:id] = id.to_s.to_i
|
|
97
|
+
col[:name] = col[:data] if col[:name].blank?
|
|
98
|
+
col[:searchable] = col[:searchable].to_bool
|
|
99
|
+
col[:orderable] = col[:orderable].to_bool
|
|
100
|
+
|
|
101
|
+
if col[:search] && !col[:search][:value].blank?
|
|
102
|
+
if col[:search][:regex].to_bool || force_regex
|
|
103
|
+
col[:search] =
|
|
104
|
+
if col[:search][:value].is_a?(::Regexp)
|
|
105
|
+
col[:search][:value]
|
|
106
|
+
else
|
|
107
|
+
begin
|
|
108
|
+
Regexp.new(col[:search][:value].to_s, Regexp::IGNORECASE)
|
|
109
|
+
rescue RegexpError
|
|
110
|
+
col[:search][:value].to_s
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
else
|
|
114
|
+
col[:search] = col[:search][:value].to_s
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
col[:search] = nil
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
@config[:columns] << col
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
@config[:columns].freeze
|
|
124
|
+
|
|
125
|
+
tmp = params[:order]
|
|
126
|
+
@config[:order] = { }
|
|
127
|
+
if tmp
|
|
128
|
+
tmp = tmp.each_with_index.to_a.map{|(a,b)| [b.to_s,a]}.to_h.deep_symbolize_keys if tmp.is_a?(::Array)
|
|
129
|
+
tmp.each do |_, order|
|
|
130
|
+
col_id = order[:column].to_i
|
|
131
|
+
col = columns.find{|c| c[:id] == col_id}
|
|
132
|
+
if col
|
|
133
|
+
@config[:order][col[:name]] = ((order[:dir] || 'asc').downcase).to_sym
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
@config[:order].freeze
|
|
138
|
+
else
|
|
139
|
+
@config[:draw] = :not_provided
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
##
|
|
145
|
+
# Where the data tables parameters provided?
|
|
146
|
+
def provided?
|
|
147
|
+
draw != :not_provided
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
# Refreshes the data and returns the request instance.
|
|
152
|
+
def refresh!
|
|
153
|
+
records true
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
##
|
|
158
|
+
# If #locate_id is non-zero, this is the record number for the specified ID using our filtering parameters.
|
|
159
|
+
#
|
|
160
|
+
# This will be an absolute zero-based record number for the ID. It can be used to figure out the page that the
|
|
161
|
+
# record would appear on.
|
|
162
|
+
def record_location(refresh = false)
|
|
163
|
+
@config[:record_location] = nil if refresh
|
|
164
|
+
@config[:record_location] ||= find_record
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# Gets the records returned by this request.
|
|
169
|
+
def records(refresh = false)
|
|
170
|
+
@config[:records] = nil if refresh
|
|
171
|
+
@config[:records] ||= load_records
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
##
|
|
175
|
+
# Gets the total number of records before filtering.
|
|
176
|
+
def records_total
|
|
177
|
+
records
|
|
178
|
+
@config[:records_total]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
##
|
|
182
|
+
# Gets the total number of records after filtering.
|
|
183
|
+
def records_filtered
|
|
184
|
+
records
|
|
185
|
+
@config[:records_filtered]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
##
|
|
189
|
+
# The error message, if any?
|
|
190
|
+
def error
|
|
191
|
+
records
|
|
192
|
+
@config[:error]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
##
|
|
196
|
+
# Is there an error to display?
|
|
197
|
+
def error?
|
|
198
|
+
!error.blank?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
private
|
|
202
|
+
|
|
203
|
+
##
|
|
204
|
+
# Find the record represented by #locate_id.
|
|
205
|
+
def find_record(relation = nil)
|
|
206
|
+
return -1 if locate_id == 0
|
|
207
|
+
|
|
208
|
+
dataset = load_records(relation, false)
|
|
209
|
+
return -1 if dataset.blank?
|
|
210
|
+
|
|
211
|
+
return -1 unless dataset.first.respond_to?(:id)
|
|
212
|
+
|
|
213
|
+
dataset.index{|item| item.id == locate_id} || -1
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# Applies the request against an ActiveRecord::Relation object.
|
|
218
|
+
#
|
|
219
|
+
# Returns the results of executing the necessary queries and filters as an array of models.
|
|
220
|
+
def load_records(relation = nil, paging = true)
|
|
221
|
+
begin
|
|
222
|
+
# reset values.
|
|
223
|
+
# @config[:records] is set to the return of this method, we we won't change that here.
|
|
224
|
+
@config[:records_total] = 0
|
|
225
|
+
@config[:records_filtered] = 0
|
|
226
|
+
@config[:error] = nil
|
|
227
|
+
|
|
228
|
+
Incline::Log::debug "Loading records for data tables request #{draw}."
|
|
229
|
+
|
|
230
|
+
# Get the default starting scope if necessary.
|
|
231
|
+
relation ||= @config[:starting_scope].call
|
|
232
|
+
|
|
233
|
+
# store the unfiltered count.
|
|
234
|
+
@config[:records_total] = relation.count
|
|
235
|
+
|
|
236
|
+
# If any of these is true, then filtering must be done locally in our code.
|
|
237
|
+
filter_local = (
|
|
238
|
+
# main search is a regex.
|
|
239
|
+
search.is_a?(::Regexp) ||
|
|
240
|
+
# one or more column searches is a regex.
|
|
241
|
+
columns.select{|c| c[:search].is_a?(::Regexp)}.any? ||
|
|
242
|
+
# one or more searchable columns is not in the database model.
|
|
243
|
+
columns.reject {|c| !c[:searchable] || relation.model.column_names.include?(c[:name].to_s)}.any?
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
Incline::Log::debug "Filtering will be done #{filter_local ? 'application' : 'database'}-side."
|
|
247
|
+
|
|
248
|
+
unless filter_local
|
|
249
|
+
### Database Side Individual Filtering (AND) ###
|
|
250
|
+
columns.reject{|c| c[:search].blank? || c[:name].blank?}.each do |col|
|
|
251
|
+
relation = relation.where("(UPPER(\"#{col[:name]}\") LIKE ?)", "%#{col[:search].upcase}%")
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
### Database Side Multiple Filtering (OR) ###
|
|
255
|
+
unless search.blank?
|
|
256
|
+
srch = "%#{search.upcase}%"
|
|
257
|
+
cols = columns.select{|c| c[:searchable]}.map{|c| c[:name].to_s }.reject{|c| c.blank?}
|
|
258
|
+
if cols.any?
|
|
259
|
+
relation = relation.where(
|
|
260
|
+
cols.map{|c| "(UPPER(\"#{c}\") LIKE ?)"}.join(' OR '),
|
|
261
|
+
*(cols.map{ srch })
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
### Database Side Ordering ###
|
|
268
|
+
if ordering.blank?
|
|
269
|
+
relation = relation.order(id: :asc)
|
|
270
|
+
else
|
|
271
|
+
relation = relation.order(ordering)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Now we have two paths, if we are filtering locally, we need to return everything up to this point and
|
|
275
|
+
# perform our filters before limiting the results.
|
|
276
|
+
# If we filtered at the database, then we can limit the results there as well.
|
|
277
|
+
if filter_local
|
|
278
|
+
# execute the query
|
|
279
|
+
relation = relation.to_a
|
|
280
|
+
|
|
281
|
+
### Local Individual Filtering (AND) ###
|
|
282
|
+
columns.reject{|c| c[:search].blank? || c[:name].blank?}.each do |col|
|
|
283
|
+
name = col[:name].to_s
|
|
284
|
+
srch = col[:search]
|
|
285
|
+
relation =
|
|
286
|
+
if srch.is_a?(::Regexp)
|
|
287
|
+
relation.select { |item| item.respond_to?(name) && item.send(name) =~ srch }
|
|
288
|
+
else
|
|
289
|
+
relation.select { |item| item.respond_to?(name) && item.send(name).to_s.include?(srch) }
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
### Local Multiple Filtering ###
|
|
294
|
+
unless search.blank?
|
|
295
|
+
cols = columns.select{|c| c[:searchable]}.map{|c| c[:name].to_s }.reject{|c| c.blank?}
|
|
296
|
+
relation =
|
|
297
|
+
if search.is_a?(::Regexp)
|
|
298
|
+
relation.select{|item| cols.find{|col| item.respond_to?(col) && item.send(col) =~ search} }
|
|
299
|
+
else
|
|
300
|
+
relation.select{|item| cols.find{|col| item.respond_to?(col) && item.send(col).to_s.include?(search) }}
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# store the filtered count.
|
|
305
|
+
@config[:records_filtered] = relation.count
|
|
306
|
+
|
|
307
|
+
if paging
|
|
308
|
+
# apply limits and return.
|
|
309
|
+
relation = relation[start..-1]
|
|
310
|
+
if length > 0
|
|
311
|
+
relation = relation[0...length]
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
relation
|
|
315
|
+
else
|
|
316
|
+
# store the filtered count.
|
|
317
|
+
@config[:records_filtered] = relation.count
|
|
318
|
+
|
|
319
|
+
if paging
|
|
320
|
+
# apply limits and return.
|
|
321
|
+
relation = relation.offset(start)
|
|
322
|
+
if length > 0
|
|
323
|
+
relation = relation.limit(length)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
relation.to_a
|
|
327
|
+
end
|
|
328
|
+
rescue =>err
|
|
329
|
+
@config[:error] = err.message
|
|
330
|
+
Incline::Log::error err
|
|
331
|
+
[ ]
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
end
|
|
336
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
module Incline
|
|
2
|
+
module DateTimeFormats
|
|
3
|
+
US_DATE_FORMAT = /\A(?<MONTH>\d{1,2})\/(?<DAY>\d{1,2})\/(?<YEAR>(?:\d{2}|\d{4}))(?:\s+(?<HOUR>\d{1,2}):(?<MINUTE>\d{1,2})(?::(?<SECOND>\d{1,2})(?:\.(?<FRACTION>\d+))?)?(?:\s*(?<AMPM>[AP])M?)?)?\z/i
|
|
4
|
+
ALMOST_ISO_DATE_FORMAT = /\A(?<YEAR>\d{2,4})-(?<MONTH>\d{1,2})-(?<DAY>\d{1,2})(?:(T|\s+)(?<HOUR>\d{1,2}):(?<MINUTE>\d{1,2})(?::(?<SECOND>\d{1,2})(?:\.(?<FRACTION>\d+))?)?(?:\s*(?<AMPM>[AP])M?)?(?:\s*(?<TZ>(?:Z|[+-]\d{2}:?\d{2})))?)?\z/
|
|
5
|
+
end
|
|
6
|
+
end
|