active_scaffold-sequel 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +179 -0
- data/MIT-LICENSE +20 -0
- data/README +36 -0
- data/app/assets/images/active_scaffold/add.gif +0 -0
- data/app/assets/images/active_scaffold/arrow_down.gif +0 -0
- data/app/assets/images/active_scaffold/arrow_up.gif +0 -0
- data/app/assets/images/active_scaffold/close.gif +0 -0
- data/app/assets/images/active_scaffold/close_touch.png +0 -0
- data/app/assets/images/active_scaffold/config.png +0 -0
- data/app/assets/images/active_scaffold/cross.png +0 -0
- data/app/assets/images/active_scaffold/gears.png +0 -0
- data/app/assets/images/active_scaffold/indicator-small.gif +0 -0
- data/app/assets/images/active_scaffold/indicator.gif +0 -0
- data/app/assets/images/active_scaffold/magnifier.png +0 -0
- data/app/assets/javascripts/active_scaffold.js.erb +19 -0
- data/app/assets/javascripts/jquery/active_scaffold.js +1057 -0
- data/app/assets/javascripts/jquery/date_picker_bridge.js.erb +24 -0
- data/app/assets/javascripts/jquery/draggable_lists.js +27 -0
- data/app/assets/javascripts/jquery/jquery.editinplace.js +743 -0
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +7 -0
- data/app/assets/javascripts/prototype/active_scaffold.js +1052 -0
- data/app/assets/javascripts/prototype/dhtml_history.js +870 -0
- data/app/assets/javascripts/prototype/form_enhancements.js +117 -0
- data/app/assets/javascripts/prototype/rico_corner.js +370 -0
- data/app/assets/javascripts/prototype/tiny_mce_bridge.js +7 -0
- data/app/assets/stylesheets/active_scaffold-ie.css +35 -0
- data/app/assets/stylesheets/active_scaffold.css.scss +14 -0
- data/app/assets/stylesheets/active_scaffold_colors.css.scss +395 -0
- data/app/assets/stylesheets/active_scaffold_extensions.css.erb +2 -0
- data/app/assets/stylesheets/active_scaffold_images.css.scss +43 -0
- data/app/assets/stylesheets/active_scaffold_layout.css +912 -0
- data/app/assets/stylesheets/blue-theme.css +74 -0
- data/config/locales/de.yml +114 -0
- data/config/locales/en.yml +118 -0
- data/config/locales/es.yml +120 -0
- data/config/locales/fr.yml +121 -0
- data/config/locales/hu.yml +74 -0
- data/config/locales/ja.yml +73 -0
- data/config/locales/ru.yml +123 -0
- data/frontends/default/views/_action_group.html.erb +24 -0
- data/frontends/default/views/_add_existing_form.html.erb +30 -0
- data/frontends/default/views/_base_form.html.erb +51 -0
- data/frontends/default/views/_create_form.html.erb +8 -0
- data/frontends/default/views/_create_form_on_list.html.erb +6 -0
- data/frontends/default/views/_field_search.html.erb +32 -0
- data/frontends/default/views/_form.html.erb +24 -0
- data/frontends/default/views/_form_association.html.erb +15 -0
- data/frontends/default/views/_form_association_footer.html.erb +47 -0
- data/frontends/default/views/_form_attribute.html.erb +20 -0
- data/frontends/default/views/_form_hidden_attribute.html.erb +2 -0
- data/frontends/default/views/_form_messages.html.erb +5 -0
- data/frontends/default/views/_horizontal_subform.html.erb +28 -0
- data/frontends/default/views/_horizontal_subform_footer.html.erb +0 -0
- data/frontends/default/views/_horizontal_subform_header.html.erb +11 -0
- data/frontends/default/views/_horizontal_subform_record.html.erb +38 -0
- data/frontends/default/views/_human_conditions.html.erb +1 -0
- data/frontends/default/views/_list.html.erb +18 -0
- data/frontends/default/views/_list_actions.html.erb +15 -0
- data/frontends/default/views/_list_calculations.html.erb +16 -0
- data/frontends/default/views/_list_column_headings.html.erb +12 -0
- data/frontends/default/views/_list_header.html.erb +10 -0
- data/frontends/default/views/_list_inline_adapter.html.erb +10 -0
- data/frontends/default/views/_list_messages.html.erb +30 -0
- data/frontends/default/views/_list_pagination.html.erb +11 -0
- data/frontends/default/views/_list_pagination_links.html.erb +9 -0
- data/frontends/default/views/_list_record.html.erb +14 -0
- data/frontends/default/views/_list_record_columns.html.erb +8 -0
- data/frontends/default/views/_list_with_header.html.erb +36 -0
- data/frontends/default/views/_messages.html.erb +10 -0
- data/frontends/default/views/_render_field.js.erb +20 -0
- data/frontends/default/views/_row.html.erb +6 -0
- data/frontends/default/views/_search.html.erb +34 -0
- data/frontends/default/views/_search_attribute.html.erb +10 -0
- data/frontends/default/views/_show.html.erb +8 -0
- data/frontends/default/views/_show_columns.html.erb +15 -0
- data/frontends/default/views/_update_actions.html.erb +9 -0
- data/frontends/default/views/_update_form.html.erb +6 -0
- data/frontends/default/views/_vertical_subform.html.erb +12 -0
- data/frontends/default/views/_vertical_subform_record.html.erb +38 -0
- data/frontends/default/views/action_confirmation.html.erb +13 -0
- data/frontends/default/views/add_existing.js.erb +18 -0
- data/frontends/default/views/add_existing_form.html.erb +5 -0
- data/frontends/default/views/create.html.erb +5 -0
- data/frontends/default/views/delete.html.erb +13 -0
- data/frontends/default/views/destroy.js.erb +24 -0
- data/frontends/default/views/edit_associated.js.erb +12 -0
- data/frontends/default/views/field_search.html.erb +5 -0
- data/frontends/default/views/form_messages.js.erb +1 -0
- data/frontends/default/views/list.html.erb +1 -0
- data/frontends/default/views/on_action_update.js.erb +13 -0
- data/frontends/default/views/on_create.js.erb +47 -0
- data/frontends/default/views/on_mark_all.js.erb +12 -0
- data/frontends/default/views/on_update.js.erb +31 -0
- data/frontends/default/views/refresh_list.js.erb +1 -0
- data/frontends/default/views/render_field.js.erb +1 -0
- data/frontends/default/views/search.html.erb +5 -0
- data/frontends/default/views/show.html.erb +5 -0
- data/frontends/default/views/update.html.erb +8 -0
- data/frontends/default/views/update_column.js.erb +16 -0
- data/frontends/default/views/update_row.js.erb +1 -0
- data/lib/active_scaffold/actions/common_search.rb +25 -0
- data/lib/active_scaffold/actions/core.rb +197 -0
- data/lib/active_scaffold/actions/create.rb +148 -0
- data/lib/active_scaffold/actions/delete.rb +76 -0
- data/lib/active_scaffold/actions/field_search.rb +82 -0
- data/lib/active_scaffold/actions/list.rb +196 -0
- data/lib/active_scaffold/actions/mark.rb +75 -0
- data/lib/active_scaffold/actions/nested.rb +245 -0
- data/lib/active_scaffold/actions/search.rb +48 -0
- data/lib/active_scaffold/actions/show.rb +61 -0
- data/lib/active_scaffold/actions/subform.rb +23 -0
- data/lib/active_scaffold/actions/update.rb +150 -0
- data/lib/active_scaffold/active_record_permissions.rb +136 -0
- data/lib/active_scaffold/attribute_params.rb +208 -0
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +39 -0
- data/lib/active_scaffold/bridges/ancestry.rb +5 -0
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +67 -0
- data/lib/active_scaffold/bridges/calendar_date_select.rb +24 -0
- data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +107 -0
- data/lib/active_scaffold/bridges/cancan.rb +15 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +31 -0
- data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge_helpers.rb +10 -0
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +45 -0
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +17 -0
- data/lib/active_scaffold/bridges/carrierwave.rb +12 -0
- data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +358 -0
- data/lib/active_scaffold/bridges/country_helper.rb +9 -0
- data/lib/active_scaffold/bridges/date_picker/ext.rb +45 -0
- data/lib/active_scaffold/bridges/date_picker/helper.rb +180 -0
- data/lib/active_scaffold/bridges/date_picker.rb +23 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +34 -0
- data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge_helpers.rb +10 -0
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +27 -0
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +16 -0
- data/lib/active_scaffold/bridges/dragonfly.rb +9 -0
- data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +48 -0
- data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +57 -0
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +34 -0
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +26 -0
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +43 -0
- data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +9 -0
- data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +15 -0
- data/lib/active_scaffold/bridges/file_column.rb +11 -0
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +27 -0
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +16 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +36 -0
- data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +24 -0
- data/lib/active_scaffold/bridges/paperclip.rb +12 -0
- data/lib/active_scaffold/bridges/record_select/helpers.rb +86 -0
- data/lib/active_scaffold/bridges/record_select.rb +11 -0
- data/lib/active_scaffold/bridges/semantic_attributes/column.rb +20 -0
- data/lib/active_scaffold/bridges/semantic_attributes.rb +5 -0
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +209 -0
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +46 -0
- data/lib/active_scaffold/bridges/tiny_mce.rb +17 -0
- data/lib/active_scaffold/bridges.rb +61 -0
- data/lib/active_scaffold/config/base.rb +71 -0
- data/lib/active_scaffold/config/core.rb +219 -0
- data/lib/active_scaffold/config/create.rb +44 -0
- data/lib/active_scaffold/config/delete.rb +33 -0
- data/lib/active_scaffold/config/field_search.rb +76 -0
- data/lib/active_scaffold/config/form.rb +48 -0
- data/lib/active_scaffold/config/list.rb +196 -0
- data/lib/active_scaffold/config/mark.rb +35 -0
- data/lib/active_scaffold/config/nested.rb +42 -0
- data/lib/active_scaffold/config/search.rb +73 -0
- data/lib/active_scaffold/config/show.rb +32 -0
- data/lib/active_scaffold/config/subform.rb +35 -0
- data/lib/active_scaffold/config/update.rb +41 -0
- data/lib/active_scaffold/configurable.rb +29 -0
- data/lib/active_scaffold/constraints.rb +170 -0
- data/lib/active_scaffold/data_structures/action_columns.rb +140 -0
- data/lib/active_scaffold/data_structures/action_link.rb +179 -0
- data/lib/active_scaffold/data_structures/action_links.rb +185 -0
- data/lib/active_scaffold/data_structures/actions.rb +45 -0
- data/lib/active_scaffold/data_structures/bridge.rb +22 -0
- data/lib/active_scaffold/data_structures/column.rb +389 -0
- data/lib/active_scaffold/data_structures/columns.rb +75 -0
- data/lib/active_scaffold/data_structures/error_message.rb +24 -0
- data/lib/active_scaffold/data_structures/nested_info.rb +130 -0
- data/lib/active_scaffold/data_structures/set.rb +57 -0
- data/lib/active_scaffold/data_structures/sorting.rb +172 -0
- data/lib/active_scaffold/engine.rb +4 -0
- data/lib/active_scaffold/extensions/action_controller_rendering.rb +22 -0
- data/lib/active_scaffold/extensions/action_view_rendering.rb +115 -0
- data/lib/active_scaffold/extensions/active_record_offset.rb +12 -0
- data/lib/active_scaffold/extensions/array.rb +7 -0
- data/lib/active_scaffold/extensions/cache_association.rb +16 -0
- data/lib/active_scaffold/extensions/localize.rb +10 -0
- data/lib/active_scaffold/extensions/name_option_for_datetime.rb +12 -0
- data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +7 -0
- data/lib/active_scaffold/extensions/paginator_extensions.rb +26 -0
- data/lib/active_scaffold/extensions/routing_mapper.rb +48 -0
- data/lib/active_scaffold/extensions/to_label.rb +8 -0
- data/lib/active_scaffold/extensions/unsaved_associated.rb +60 -0
- data/lib/active_scaffold/extensions/unsaved_record.rb +20 -0
- data/lib/active_scaffold/extensions/usa_state.rb +46 -0
- data/lib/active_scaffold/finder.rb +372 -0
- data/lib/active_scaffold/helpers/association_helpers.rb +48 -0
- data/lib/active_scaffold/helpers/controller_helpers.rb +88 -0
- data/lib/active_scaffold/helpers/form_column_helpers.rb +321 -0
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +62 -0
- data/lib/active_scaffold/helpers/id_helpers.rb +127 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +340 -0
- data/lib/active_scaffold/helpers/pagination_helpers.rb +55 -0
- data/lib/active_scaffold/helpers/search_column_helpers.rb +267 -0
- data/lib/active_scaffold/helpers/show_column_helpers.rb +50 -0
- data/lib/active_scaffold/helpers/view_helpers.rb +342 -0
- data/lib/active_scaffold/marked_model.rb +38 -0
- data/lib/active_scaffold/paginator.rb +136 -0
- data/lib/active_scaffold/responds_to_parent.rb +70 -0
- data/lib/active_scaffold/version.rb +9 -0
- data/lib/active_scaffold.rb +368 -0
- data/lib/active_scaffold_env.rb +11 -0
- data/lib/generators/active_scaffold/USAGE +29 -0
- data/lib/generators/active_scaffold/active_scaffold_generator.rb +20 -0
- data/lib/generators/active_scaffold_controller/USAGE +19 -0
- data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +29 -0
- data/lib/generators/active_scaffold_controller/templates/controller.rb +4 -0
- data/lib/generators/active_scaffold_controller/templates/helper.rb +2 -0
- data/public/blank.html +33 -0
- data/shoulda_macros/macros.rb +136 -0
- data/test/bridges/active_scaffold_dependent_protect_test.rb +34 -0
- data/test/bridges/bridge_test.rb +90 -0
- data/test/bridges/company.rb +81 -0
- data/test/bridges/paperclip_test.rb +68 -0
- data/test/bridges/tiny_mce_test.rb +27 -0
- data/test/bridges/unobtrusive_date_picker_test.rb +49 -0
- data/test/bridges/validation_reflection_test.rb +57 -0
- data/test/config/base_test.rb +15 -0
- data/test/config/core_test.rb +58 -0
- data/test/config/create_test.rb +58 -0
- data/test/config/delete_test.rb +33 -0
- data/test/config/field_search_test.rb +47 -0
- data/test/config/list_test.rb +129 -0
- data/test/config/nested_test.rb +62 -0
- data/test/config/search_test.rb +60 -0
- data/test/config/show_test.rb +43 -0
- data/test/config/subform_test.rb +17 -0
- data/test/config/update_test.rb +40 -0
- data/test/const_mocker.rb +36 -0
- data/test/data_structures/action_columns_test.rb +113 -0
- data/test/data_structures/action_link_test.rb +78 -0
- data/test/data_structures/action_links_test.rb +78 -0
- data/test/data_structures/actions_test.rb +25 -0
- data/test/data_structures/association_column_test.rb +42 -0
- data/test/data_structures/column_test.rb +185 -0
- data/test/data_structures/columns_test.rb +69 -0
- data/test/data_structures/error_message_test.rb +28 -0
- data/test/data_structures/set_test.rb +86 -0
- data/test/data_structures/sorting_test.rb +126 -0
- data/test/data_structures/standard_column_test.rb +24 -0
- data/test/data_structures/virtual_column_test.rb +23 -0
- data/test/extensions/active_record_test.rb +45 -0
- data/test/extensions/array_test.rb +12 -0
- data/test/helpers/form_column_helpers_test.rb +31 -0
- data/test/helpers/list_column_helpers_test.rb +42 -0
- data/test/helpers/pagination_helpers_test.rb +59 -0
- data/test/misc/active_record_permissions_test.rb +154 -0
- data/test/misc/attribute_params_test.rb +146 -0
- data/test/misc/configurable_test.rb +96 -0
- data/test/misc/constraints_test.rb +193 -0
- data/test/misc/finder_test.rb +92 -0
- data/test/misc/lang_test.rb +11 -0
- data/test/mock_app/app/controllers/application_controller.rb +10 -0
- data/test/mock_app/app/helpers/application_helper.rb +3 -0
- data/test/mock_app/config/boot.rb +110 -0
- data/test/mock_app/config/database.yml +16 -0
- data/test/mock_app/config/environment.rb +43 -0
- data/test/mock_app/config/environments/development.rb +17 -0
- data/test/mock_app/config/environments/production.rb +28 -0
- data/test/mock_app/config/environments/test.rb +28 -0
- data/test/mock_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/mock_app/config/initializers/inflections.rb +10 -0
- data/test/mock_app/config/initializers/mime_types.rb +5 -0
- data/test/mock_app/config/initializers/new_rails_defaults.rb +19 -0
- data/test/mock_app/config/initializers/session_store.rb +15 -0
- data/test/mock_app/config/locales/en.yml +5 -0
- data/test/mock_app/config/routes.rb +43 -0
- data/test/mock_app/db/test.sqlite3 +1 -0
- data/test/mock_app/public/blank.html +33 -0
- data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +2 -0
- data/test/mock_app/public/images/active_scaffold/default/add.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/arrow_down.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/arrow_up.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/close.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/cross.png +0 -0
- data/test/mock_app/public/images/active_scaffold/default/indicator-small.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/indicator.gif +0 -0
- data/test/mock_app/public/images/active_scaffold/default/magnifier.png +0 -0
- data/test/mock_app/public/javascripts/active_scaffold/DO_NOT_EDIT +2 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +532 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +867 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +117 -0
- data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +370 -0
- data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +2 -0
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +35 -0
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +848 -0
- data/test/model_stub.rb +55 -0
- data/test/run_all.rb +8 -0
- data/test/test_helper.rb +39 -0
- data/vendor/assets/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +1276 -0
- data/vendor/assets/stylesheets/jquery-ui.css +568 -0
- metadata +502 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# This module attempts to create permissions conventions for your ActiveRecord models. It supports english-based
|
|
2
|
+
# methods that let you restrict access per-model, per-record, per-column, per-action, and per-user. All at once.
|
|
3
|
+
#
|
|
4
|
+
# You may define instance methods in the following formats:
|
|
5
|
+
# def #{column}_authorized_for_#{action}?
|
|
6
|
+
# def #{column}_authorized?
|
|
7
|
+
# def authorized_for_#{action}?
|
|
8
|
+
#
|
|
9
|
+
# Your methods should allow for the following special cases:
|
|
10
|
+
# * cron scripts
|
|
11
|
+
# * guest users (or nil current_user objects)
|
|
12
|
+
module ActiveScaffold
|
|
13
|
+
module ModelPermissions
|
|
14
|
+
# ModelPermissions needs to know what method on your ApplicationController will return the current user,
|
|
15
|
+
# if available. This defaults to the :current_user method. You may configure this in your environment.rb if you
|
|
16
|
+
# have a different setup.
|
|
17
|
+
def self.current_user_method=(v); @@current_user_method = v; end
|
|
18
|
+
def self.current_user_method; @@current_user_method; end
|
|
19
|
+
@@current_user_method = :current_user
|
|
20
|
+
|
|
21
|
+
# Whether the default permission is permissive or not
|
|
22
|
+
# If set to true, then everything's allowed until configured otherwise
|
|
23
|
+
def self.default_permission=(v); @@default_permission = v; end
|
|
24
|
+
def self.default_permission; @@default_permission; end
|
|
25
|
+
@@default_permission = true
|
|
26
|
+
|
|
27
|
+
# This is a module aimed at making the current_user available to ActiveRecord models for permissions.
|
|
28
|
+
module ModelUserAccess
|
|
29
|
+
module Controller
|
|
30
|
+
def self.included(base)
|
|
31
|
+
base.prepend_before_filter :assign_current_user_to_models
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# We need to give the ActiveRecord classes a handle to the current user. We don't want to just pass the object,
|
|
35
|
+
# because the object may change (someone may log in or out). So we give ActiveRecord a proc that ties to the
|
|
36
|
+
# current_user_method on this ApplicationController.
|
|
37
|
+
def assign_current_user_to_models
|
|
38
|
+
Sequel::Model.current_user_proc = proc {send(ModelPermissions.current_user_method)}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module Model
|
|
43
|
+
def self.included(base)
|
|
44
|
+
base.extend ClassMethods
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ClassMethods
|
|
48
|
+
# The proc to call that retrieves the current_user from the ApplicationController.
|
|
49
|
+
attr_accessor :current_user_proc
|
|
50
|
+
|
|
51
|
+
# Class-level access to the current user
|
|
52
|
+
def current_user
|
|
53
|
+
Sequel::Model.current_user_proc.call if Sequel::Model.current_user_proc
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Instance-level access to the current user
|
|
58
|
+
def current_user
|
|
59
|
+
self.class.current_user
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module Permissions
|
|
65
|
+
def self.included(base)
|
|
66
|
+
base.extend SecurityMethods
|
|
67
|
+
base.send :include, SecurityMethods
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Because any class-level queries get delegated to the instance level via a new record,
|
|
71
|
+
# it's useful to know when the authorization query is meant for a specific record or not.
|
|
72
|
+
# But using new? is confusing, even though accurate. So this is basically just a wrapper.
|
|
73
|
+
def existing_record_check?
|
|
74
|
+
!new?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
module SecurityMethods
|
|
78
|
+
# A generic authorization query. This is what will be called programatically, since
|
|
79
|
+
# the actual permission methods can't be guaranteed to exist. And because we want to
|
|
80
|
+
# intelligently combine multiple applicable methods.
|
|
81
|
+
#
|
|
82
|
+
# options[:crud_type] should be a CRUD verb (:create, :read, :update, :destroy)
|
|
83
|
+
# options[:column] should be the name of a model attribute
|
|
84
|
+
# options[:action] is the name of a method
|
|
85
|
+
def authorized_for?(options = {})
|
|
86
|
+
raise ArgumentError, "unknown crud type #{options[:crud_type]}" if options[:crud_type] and ![:create, :read, :update, :delete].include?(options[:crud_type])
|
|
87
|
+
|
|
88
|
+
# column_authorized_for_crud_type? has the highest priority over other methods,
|
|
89
|
+
# you can disable a crud verb and enable that verb for a column
|
|
90
|
+
# (for example, disable update and enable inplace_edit in a column)
|
|
91
|
+
method = column_and_crud_type_security_method(options[:column], options[:crud_type])
|
|
92
|
+
return send(method) if method and respond_to?(method)
|
|
93
|
+
|
|
94
|
+
# authorized_for_action? has higher priority than other methods,
|
|
95
|
+
# you can disable a crud verb and enable an action with that crud verb
|
|
96
|
+
# (for example, disable update and enable an action with update as crud type)
|
|
97
|
+
method = action_security_method(options[:action])
|
|
98
|
+
return send(method) if method and respond_to?(method)
|
|
99
|
+
|
|
100
|
+
# collect other possibly-related methods that actually exist
|
|
101
|
+
methods = [
|
|
102
|
+
column_security_method(options[:column]),
|
|
103
|
+
crud_type_security_method(options[:crud_type]),
|
|
104
|
+
].compact.select {|m| respond_to?(m)}
|
|
105
|
+
|
|
106
|
+
# if any method returns false, then return false
|
|
107
|
+
return false if methods.any? {|m| !send(m)}
|
|
108
|
+
|
|
109
|
+
# if any method actually exists then it must've returned true, so return true
|
|
110
|
+
return true unless methods.empty?
|
|
111
|
+
|
|
112
|
+
# if no method exists, return the default permission
|
|
113
|
+
return ModelPermissions.default_permission
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def column_security_method(column)
|
|
119
|
+
"#{column}_authorized?" if column
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def crud_type_security_method(crud_type)
|
|
123
|
+
"authorized_for_#{crud_type}?" if crud_type
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def action_security_method(action)
|
|
127
|
+
"authorized_for_#{action}?" if action
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def column_and_crud_type_security_method(column, crud_type)
|
|
131
|
+
"#{column}_authorized_for_#{crud_type}?" if column and crud_type
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
module ActiveScaffold
|
|
2
|
+
# Provides support for param hashes assumed to be model attributes.
|
|
3
|
+
# Support is primarily needed for creating/editing associated records using a nested hash structure.
|
|
4
|
+
#
|
|
5
|
+
# Paradigm Params Hash (should write unit tests on this):
|
|
6
|
+
# params[:record] = {
|
|
7
|
+
# # a simple record attribute
|
|
8
|
+
# 'name' => 'John',
|
|
9
|
+
# # a plural association hash
|
|
10
|
+
# 'roles' => {
|
|
11
|
+
# # associate with an existing role
|
|
12
|
+
# '5' => {'id' => 5}
|
|
13
|
+
# # associate with an existing role and edit it
|
|
14
|
+
# '6' => {'id' => 6, 'name' => 'designer'}
|
|
15
|
+
# # create and associate a new role
|
|
16
|
+
# '124521' => {'name' => 'marketer'}
|
|
17
|
+
# }
|
|
18
|
+
# # a singular association hash
|
|
19
|
+
# 'location' => {'id' => 12, 'city' => 'New York'}
|
|
20
|
+
# }
|
|
21
|
+
#
|
|
22
|
+
# Simpler association structures are also supported, like:
|
|
23
|
+
# params[:record] = {
|
|
24
|
+
# # a simple record attribute
|
|
25
|
+
# 'name' => 'John',
|
|
26
|
+
# # a plural association ... all ids refer to existing records
|
|
27
|
+
# 'roles' => ['5', '6'],
|
|
28
|
+
# # a singular association ... all ids refer to existing records
|
|
29
|
+
# 'location' => '12'
|
|
30
|
+
# }
|
|
31
|
+
module AttributeParams
|
|
32
|
+
protected
|
|
33
|
+
# Takes attributes (as from params[:record]) and applies them to the parent_record. Also looks for
|
|
34
|
+
# association attributes and attempts to instantiate them as associated objects.
|
|
35
|
+
#
|
|
36
|
+
# This is a secure way to apply params to a record, because it's based on a loop over the columns
|
|
37
|
+
# set. The columns set will not yield unauthorized columns, and it will not yield unregistered columns.
|
|
38
|
+
def update_record_from_params(parent_record, columns, attributes)
|
|
39
|
+
crud_type = parent_record.new? ? :create : :update
|
|
40
|
+
return parent_record unless parent_record.authorized_for?(:crud_type => crud_type)
|
|
41
|
+
|
|
42
|
+
multi_parameter_attributes = {}
|
|
43
|
+
attributes.each do |k, v|
|
|
44
|
+
next unless k.include? '('
|
|
45
|
+
column_name = k.split('(').first.to_sym
|
|
46
|
+
multi_parameter_attributes[column_name] ||= []
|
|
47
|
+
multi_parameter_attributes[column_name] << [k, v]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
columns.each :for => parent_record, :crud_type => crud_type, :flatten => true do |column|
|
|
51
|
+
# Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
|
|
52
|
+
unless column.params.empty?
|
|
53
|
+
column.params.each{|p| parent_record.send("#{p}=", attributes[p]) if attributes.has_key? p}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if multi_parameter_attributes.has_key? column.name
|
|
57
|
+
parent_record.send(:assign_multiparameter_attributes, multi_parameter_attributes[column.name])
|
|
58
|
+
elsif attributes.has_key? column.name
|
|
59
|
+
value = column_value_from_param_value(parent_record, column, attributes[column.name])
|
|
60
|
+
|
|
61
|
+
# we avoid assigning a value that already exists because otherwise has_one associations will break (AR bug in has_one_association.rb#replace)
|
|
62
|
+
parent_record.send("#{column.name}=", value) unless parent_record.send(column.name) == value
|
|
63
|
+
|
|
64
|
+
elsif column.plural_association? and not parent_record.new?
|
|
65
|
+
parent_record.send("remove_all_#{column.name}")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if parent_record.new?
|
|
70
|
+
parent_record.class.association_reflections.each do |name, props|
|
|
71
|
+
next unless [:one_to_one, :one_to_many].include?(props[:type]) and props[:join_table].nil?
|
|
72
|
+
next unless association_proxy = parent_record.send(name)
|
|
73
|
+
|
|
74
|
+
raise ActiveScaffold::ReverseAssociationRequired, "Association #{name} in class #{parent_record.class.name}: In order to support :one_to_one and :one_to_many where the parent record is new and the child record(s) validate the presence of the parent, ActiveScaffold requires the reverse association (the many_to_one)." unless props.reciprocal
|
|
75
|
+
|
|
76
|
+
association_proxy = [association_proxy] if props[:type] == :one_to_one
|
|
77
|
+
association_proxy.each {|record| record.send("#{props.reciprocal}=", parent_record)}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
parent_record
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def manage_nested_record_from_params(parent_record, column, attributes)
|
|
85
|
+
record = find_or_create_for_params(attributes, column, parent_record)
|
|
86
|
+
if record
|
|
87
|
+
record_columns = active_scaffold_config_for(column.association.associated_class).subform.columns
|
|
88
|
+
record_columns.constraint_columns = [column.association.reciprocal]
|
|
89
|
+
update_record_from_params(record, record_columns, attributes)
|
|
90
|
+
record.unsaved = true
|
|
91
|
+
end
|
|
92
|
+
record
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def column_value_from_param_value(parent_record, column, value)
|
|
96
|
+
# convert the value, possibly by instantiating associated objects
|
|
97
|
+
if value.is_a?(Hash)
|
|
98
|
+
column_value_from_param_hash_value(parent_record, column, value)
|
|
99
|
+
else
|
|
100
|
+
column_value_from_param_simple_value(parent_record, column, value)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def column_value_from_param_simple_value(parent_record, column, value)
|
|
105
|
+
if column.singular_association?
|
|
106
|
+
# it's a single id
|
|
107
|
+
column.association.associated_class[value] if value and not value.empty?
|
|
108
|
+
elsif column.plural_association?
|
|
109
|
+
column_plural_assocation_value_from_value(column, value)
|
|
110
|
+
elsif column.number? && [:i18n_number, :currency].include?(column.options[:format])
|
|
111
|
+
self.class.i18n_number_to_native_format(value)
|
|
112
|
+
else
|
|
113
|
+
# convert empty strings into nil. this works better with 'null => true' columns (and validations),
|
|
114
|
+
# and 'null => false' columns should just convert back to an empty string.
|
|
115
|
+
# ... but we can at least check the ConnectionAdapter::Column object to see if nulls are allowed
|
|
116
|
+
value = nil if value.is_a? String and value.empty? and !column.column.nil? and column.column[:allow_null]
|
|
117
|
+
value
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def column_plural_assocation_value_from_value(column, value)
|
|
122
|
+
# it's an array of ids
|
|
123
|
+
if value and not value.empty?
|
|
124
|
+
ids = value.select {|id| id.respond_to?(:empty?) ? !id.empty? : true}
|
|
125
|
+
if ids.empty?
|
|
126
|
+
[]
|
|
127
|
+
else
|
|
128
|
+
klass = column.association.associated_class
|
|
129
|
+
klass.filter(klass.primary_key => ids)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def column_value_from_param_hash_value(parent_record, column, value)
|
|
135
|
+
# this is just for backwards compatibility. we should clean this up in 2.0.
|
|
136
|
+
if column.form_ui == :select
|
|
137
|
+
klass = column.association.associated_class
|
|
138
|
+
if column.singular_association?
|
|
139
|
+
value[:id]
|
|
140
|
+
value[:id].blank? ? nil : klass[value[:id]]
|
|
141
|
+
else
|
|
142
|
+
ids = (value.values.collect {|hash| hash[:id]})
|
|
143
|
+
ids.blank? ? nil : klass.filter(klass.primary_key => ids)
|
|
144
|
+
end
|
|
145
|
+
elsif column.singular_association?
|
|
146
|
+
manage_nested_record_from_params(parent_record, column, value)
|
|
147
|
+
elsif column.plural_association?
|
|
148
|
+
value.collect {|key_value_pair| manage_nested_record_from_params(parent_record, column, key_value_pair[1])}.compact
|
|
149
|
+
else
|
|
150
|
+
value
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Attempts to create or find an instance of klass (which must be an ActiveRecord object) from the
|
|
155
|
+
# request parameters given. If params[:id] exists it will attempt to find an existing object
|
|
156
|
+
# otherwise it will build a new one.
|
|
157
|
+
def find_or_create_for_params(params, parent_column, parent_record)
|
|
158
|
+
current = parent_record.send(parent_column.name)
|
|
159
|
+
klass = parent_column.association.associated_class
|
|
160
|
+
pk = klass.primary_key.to_sym
|
|
161
|
+
return nil if parent_column.show_blank_record?(current) and attributes_hash_is_empty?(params, klass)
|
|
162
|
+
|
|
163
|
+
if params.has_key? pk
|
|
164
|
+
# modifying the current object of a singular association
|
|
165
|
+
pk_val = params[pk]
|
|
166
|
+
if current and current.is_a? Sequel::Model and current.id.to_s == pk_val
|
|
167
|
+
current
|
|
168
|
+
# modifying one of the current objects in a plural association
|
|
169
|
+
elsif current and current.respond_to?(:any?) and current.any? {|o| o.id.to_s == pk_val}
|
|
170
|
+
current.detect {|o| o.id.to_s == pk_val}
|
|
171
|
+
# attaching an existing but not-current object
|
|
172
|
+
else
|
|
173
|
+
klass[pk_val]
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
build_associated(parent_column, parent_record) if klass.authorized_for?(:crud_type => :create)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
# Determines whether the given attributes hash is "empty".
|
|
180
|
+
# This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.
|
|
181
|
+
def attributes_hash_is_empty?(hash, klass)
|
|
182
|
+
ignore_column_types = [:boolean]
|
|
183
|
+
hash.all? do |key,value|
|
|
184
|
+
# convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
|
|
185
|
+
parts = key.to_s.split('(')
|
|
186
|
+
#old style date form management... ignore them too
|
|
187
|
+
ignore_column_types = [:boolean, :datetime, :date, :time] if parts.length > 1
|
|
188
|
+
column_name = parts.first.to_sym
|
|
189
|
+
column = klass.db_schema[column_name]
|
|
190
|
+
|
|
191
|
+
# booleans and datetimes will always have a value. so we ignore them when checking whether the hash is empty.
|
|
192
|
+
# this could be a bad idea. but the current situation (excess record entry) seems worse.
|
|
193
|
+
next true if column and ignore_column_types.include?(column[:type])
|
|
194
|
+
|
|
195
|
+
# defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
|
|
196
|
+
next true if column and value == column[:ruby_default].to_s
|
|
197
|
+
|
|
198
|
+
if value.is_a?(Hash)
|
|
199
|
+
attributes_hash_is_empty?(value, klass)
|
|
200
|
+
elsif value.is_a?(Array)
|
|
201
|
+
value.any? {|id| id.respond_to?(:empty?) ? !id.empty? : true}
|
|
202
|
+
else
|
|
203
|
+
value.respond_to?(:empty?) ? value.empty? : false
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ActiveScaffold::Config::Core.class_eval do
|
|
2
|
+
def initialize_with_ancestry(model_id)
|
|
3
|
+
initialize_without_ancestry(model_id)
|
|
4
|
+
|
|
5
|
+
return unless self.model.respond_to? :ancestry_column
|
|
6
|
+
|
|
7
|
+
self.columns << :parent_id
|
|
8
|
+
self.columns[:parent_id].form_ui = :ancestry
|
|
9
|
+
update.columns.exclude :ancestry
|
|
10
|
+
create.columns.exclude :ancestry, :parent_id
|
|
11
|
+
list.columns.exclude :ancestry, :parent_id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
alias_method_chain :initialize, :ancestry
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module ActiveScaffold::Bridges
|
|
18
|
+
class Ancestry
|
|
19
|
+
module FormColumnHelpers
|
|
20
|
+
def active_scaffold_input_ancestry(column, options)
|
|
21
|
+
select_options = []
|
|
22
|
+
select_control_options = {:selected => @record.parent_id}
|
|
23
|
+
select_control_options[:include_blank] = as_(:_select_) if @record.parent_id.nil?
|
|
24
|
+
traverse_ancestry = proc do|key, value|
|
|
25
|
+
unless key == @record
|
|
26
|
+
select_options << ["#{'__' * key.depth}#{key.to_label}", key.id]
|
|
27
|
+
value.each(&traverse_ancestry) if value.is_a?(Hash) && !value.empty?
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
@record.class.arrange.each(&traverse_ancestry)
|
|
31
|
+
select(:record, :ancestry, select_options, select_control_options, options)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
ActionView::Base.class_eval do
|
|
38
|
+
include ActiveScaffold::Bridges::Ancestry::FormColumnHelpers
|
|
39
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module ActiveScaffold::Config
|
|
2
|
+
class Core < Base
|
|
3
|
+
|
|
4
|
+
def initialize_with_calendar_date_select(model_id)
|
|
5
|
+
initialize_without_calendar_date_select(model_id)
|
|
6
|
+
|
|
7
|
+
calendar_date_select_fields = self.model.db_schema.collect {|name,properties| name if [:date, :datetime].include?(properties[:type])}.compact
|
|
8
|
+
# check to see if file column was used on the model
|
|
9
|
+
return if calendar_date_select_fields.empty?
|
|
10
|
+
|
|
11
|
+
# automatically set the forum_ui to a file column
|
|
12
|
+
calendar_date_select_fields.each{|field|
|
|
13
|
+
self.columns[field].form_ui = :calendar_date_select
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
alias_method_chain :initialize, :calendar_date_select
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
module ActiveScaffold
|
|
24
|
+
module Bridges
|
|
25
|
+
class CalendarDateSelect
|
|
26
|
+
# Helpers that assist with the rendering of a Form Column
|
|
27
|
+
module FormColumnHelpers
|
|
28
|
+
def active_scaffold_input_calendar_date_select(column, options)
|
|
29
|
+
options[:class] = "#{options[:class]} text-input".strip
|
|
30
|
+
calendar_date_select("record", column.name, options.merge(column.options))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
module SearchColumnHelpers
|
|
35
|
+
def active_scaffold_search_date_bridge_calendar_control(column, options, current_search, name)
|
|
36
|
+
if current_search.is_a? Hash
|
|
37
|
+
value = controller.class.condition_value_for_datetime(current_search[name], column.column[:type] == :date ? :to_date : :to_time)
|
|
38
|
+
else
|
|
39
|
+
value = current_search
|
|
40
|
+
end
|
|
41
|
+
calendar_date_select("record", column.name,
|
|
42
|
+
{:name => "#{options[:name]}[#{name}]",
|
|
43
|
+
:value => (value ? l(value) : nil),
|
|
44
|
+
:class => 'text-input',
|
|
45
|
+
:id => "#{options[:id]}_#{name}",
|
|
46
|
+
:time => column_datetime?(column) ? true : false,
|
|
47
|
+
:style => "display:#{(options[:show].nil? || options[:show]) ? '' : 'none'}"})
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
ActionView::Base.class_eval do
|
|
55
|
+
include ActiveScaffold::Bridges::CalendarDateSelect::FormColumnHelpers
|
|
56
|
+
include ActiveScaffold::Bridges::Shared::DateBridge::SearchColumnHelpers
|
|
57
|
+
alias_method :active_scaffold_search_calendar_date_select, :active_scaffold_search_date_bridge
|
|
58
|
+
include ActiveScaffold::Bridges::Shared::DateBridge::HumanConditionHelpers
|
|
59
|
+
alias_method :active_scaffold_human_condition_calendar_date_select, :active_scaffold_human_condition_date_bridge
|
|
60
|
+
include ActiveScaffold::Bridges::CalendarDateSelect::SearchColumnHelpers
|
|
61
|
+
include ActiveScaffold::Bridges::CalendarDateSelect::ViewHelpers
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
ActiveScaffold::Finder::ClassMethods.module_eval do
|
|
65
|
+
include ActiveScaffold::Bridges::Shared::DateBridge::Finder::ClassMethods
|
|
66
|
+
alias_method :condition_for_calendar_date_select_type, :condition_for_date_bridge_type
|
|
67
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class ActiveScaffold::Bridges::CalendarDateSelect < ActiveScaffold::DataStructures::Bridge
|
|
2
|
+
def self.install
|
|
3
|
+
# check to see if the old bridge was installed. If so, warn them
|
|
4
|
+
# we can detect this by checking to see if the bridge was installed before calling this code
|
|
5
|
+
|
|
6
|
+
if ActiveScaffold::Config::Core.instance_methods.include?("initialize_with_calendar_date_select")
|
|
7
|
+
raise RuntimeError, "We've detected that you have active_scaffold_calendar_date_select_bridge installed. This plugin has been moved to core. Please remove active_scaffold_calendar_date_select_bridge to prevent any conflicts"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
require File.join(File.dirname(__FILE__), "calendar_date_select/as_cds_bridge.rb")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.install?
|
|
14
|
+
super && ActiveScaffold.js_framework == :prototype
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.stylesheets
|
|
18
|
+
calendar_date_select_stylesheets
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.javascripts
|
|
22
|
+
calendar_date_select_javascripts
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module ActiveScaffold::Bridges
|
|
2
|
+
class Cancan
|
|
3
|
+
|
|
4
|
+
# controller level authorization
|
|
5
|
+
# As already has callbacks to ensure authorization at controller method via "authorization_method"
|
|
6
|
+
# but let's include this too, just in case, no sure how performance is affected tough :TODO benchmark
|
|
7
|
+
module ClassMethods
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
included do
|
|
10
|
+
alias_method_chain :active_scaffold, :cancan
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def active_scaffold_with_cancan(model_id = nil, &block)
|
|
14
|
+
active_scaffold_without_cancan(model_id, &block)
|
|
15
|
+
authorize_resource(
|
|
16
|
+
:class => active_scaffold_config.model,
|
|
17
|
+
:instance => :record
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# beginning of chain integration
|
|
23
|
+
module Actions
|
|
24
|
+
module Core
|
|
25
|
+
extend ActiveSupport::Concern
|
|
26
|
+
included do
|
|
27
|
+
alias_method_chain :beginning_of_chain, :cancan
|
|
28
|
+
end
|
|
29
|
+
# :TODO can this be expanded more ?
|
|
30
|
+
def beginning_of_chain_with_cancan
|
|
31
|
+
beginning_of_chain_without_cancan.accessible_by(current_ability)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# This is a module aimed at making the current_ability available to ActiveRecord models for permissions.
|
|
37
|
+
module ModelUserAccess
|
|
38
|
+
module Controller
|
|
39
|
+
extend ActiveSupport::Concern
|
|
40
|
+
included do
|
|
41
|
+
prepend_before_filter :assign_current_ability_to_models
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# We need to give the ActiveRecord classes a handle to the current ability. We don't want to just pass the object,
|
|
45
|
+
# because the object may change (someone may log in or out). So we give ActiveRecord a proc that ties to the
|
|
46
|
+
# current_ability_method on this ApplicationController.
|
|
47
|
+
def assign_current_ability_to_models
|
|
48
|
+
::Sequel::Model.current_ability_proc = proc {send(:current_ability)}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module Model
|
|
53
|
+
extend ActiveSupport::Concern
|
|
54
|
+
|
|
55
|
+
module ClassMethods
|
|
56
|
+
# The proc to call that retrieves the current_ability from the ApplicationController.
|
|
57
|
+
attr_accessor :current_ability_proc
|
|
58
|
+
|
|
59
|
+
# Class-level access to the current ability
|
|
60
|
+
def current_ability
|
|
61
|
+
::Sequel::Model.current_ability_proc.call if ::Sequel::Model.current_ability_proc
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Instance-level access to the current ability
|
|
66
|
+
def current_ability; self.class.current_ability end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# plug into AS#authorized_for calls
|
|
72
|
+
module ActiveRecord
|
|
73
|
+
extend ActiveSupport::Concern
|
|
74
|
+
included do
|
|
75
|
+
extend SecurityMethods
|
|
76
|
+
include SecurityMethods
|
|
77
|
+
alias_method_chain :authorized_for?, :cancan
|
|
78
|
+
class << self
|
|
79
|
+
alias_method_chain :authorized_for?, :cancan
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
module SecurityMethods
|
|
84
|
+
class InvalidArgument < StandardError; end
|
|
85
|
+
|
|
86
|
+
# is usually called with :crud_type and :column, or :action
|
|
87
|
+
# {:crud_type=>:update, :column=>"some_colum_name"}
|
|
88
|
+
# {:action=>"edit"}
|
|
89
|
+
# to allow access cancan must allow both :crud_type and :action
|
|
90
|
+
# if cancan says "no", it delegates to default AS behavior
|
|
91
|
+
def authorized_for_with_cancan?(options = {})
|
|
92
|
+
raise InvalidArgument if options[:crud_type].blank? and options[:action].blank?
|
|
93
|
+
if current_ability.present?
|
|
94
|
+
crud_type_result = options[:crud_type].nil? ? true : current_ability.can?(options[:crud_type], self)
|
|
95
|
+
action_result = options[:action].nil? ? true : current_ability.can?(options[:action].to_sym, self)
|
|
96
|
+
else
|
|
97
|
+
crud_type_result, action_result = false, false
|
|
98
|
+
end
|
|
99
|
+
default_result = authorized_for_without_cancan?(options)
|
|
100
|
+
result = (crud_type_result && action_result) || default_result
|
|
101
|
+
return result
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class ActiveScaffold::Bridges::Cancan < ActiveScaffold::DataStructures::Bridge
|
|
2
|
+
def self.install
|
|
3
|
+
require File.join(File.dirname(__FILE__), "cancan", "cancan_bridge.rb")
|
|
4
|
+
|
|
5
|
+
ActiveScaffold::ClassMethods.send :include, ActiveScaffold::Bridges::Cancan::ClassMethods
|
|
6
|
+
ActiveScaffold::Actions::Core.send :include, ActiveScaffold::Bridges::Cancan::Actions::Core
|
|
7
|
+
ActiveScaffold::Actions::Nested.send :include, ActiveScaffold::Bridges::Cancan::Actions::Core
|
|
8
|
+
ActionController::Base.send :include, ActiveScaffold::Bridges::Cancan::ModelUserAccess::Controller
|
|
9
|
+
::Sequel::Model.send :include, ActiveScaffold::Bridges::Cancan::ModelUserAccess::Model
|
|
10
|
+
::Sequel::Model.send :include, ActiveScaffold::Bridges::Cancan::ActiveRecord
|
|
11
|
+
end
|
|
12
|
+
def self.install?
|
|
13
|
+
Object.const_defined? 'CanCan'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module ActiveScaffold
|
|
2
|
+
module Bridges
|
|
3
|
+
class Carrierwave
|
|
4
|
+
module CarrierwaveBridge
|
|
5
|
+
def initialize_with_carrierwave(model_id)
|
|
6
|
+
initialize_without_carrierwave(model_id)
|
|
7
|
+
return unless self.model.respond_to?(:uploaders) && self.model.uploaders.present?
|
|
8
|
+
|
|
9
|
+
self.update.multipart = true
|
|
10
|
+
self.create.multipart = true
|
|
11
|
+
|
|
12
|
+
self.model.uploaders.keys.each do |field|
|
|
13
|
+
configure_carrierwave_field(field.to_sym)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.included(base)
|
|
18
|
+
base.alias_method_chain :initialize, :carrierwave
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
def configure_carrierwave_field(field)
|
|
23
|
+
self.columns << field
|
|
24
|
+
self.columns[field].form_ui ||= :carrierwave # :TODO thumbnail
|
|
25
|
+
self.columns[field].params.add "#{field}_cache"
|
|
26
|
+
self.columns[field].params.add "remove_#{field}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|