alchemy_cms 2.3.2 → 2.4.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -2
- data/.travis.yml +1 -5
- data/Gemfile +4 -4
- data/README.md +22 -15
- data/alchemy_cms.gemspec +38 -38
- data/app/assets/javascripts/alchemy/alchemy.base.js +2 -2
- data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +31 -0
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +1 -1
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js +24 -15
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +9 -3
- data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +2 -2
- data/app/assets/javascripts/alchemy/alchemy.js +1 -0
- data/app/assets/javascripts/alchemy/alchemy.menubar.js +4 -12
- data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +32 -0
- data/app/assets/javascripts/alchemy/alchemy.windows.js +4 -4
- data/app/assets/stylesheets/alchemy/_defaults.scss +0 -1
- data/app/assets/stylesheets/alchemy/alchemy.css +2 -1
- data/app/assets/stylesheets/alchemy/base.css.scss +2 -54
- data/app/assets/stylesheets/alchemy/elements.css.scss +8 -5
- data/app/assets/stylesheets/alchemy/errors.css.scss +51 -0
- data/app/assets/stylesheets/alchemy/flash.css.scss +0 -2
- data/app/assets/stylesheets/alchemy/form_elements.css.scss +31 -75
- data/app/assets/stylesheets/alchemy/icons.css.scss +5 -5
- data/app/assets/stylesheets/alchemy/menubar.css.scss +0 -2
- data/app/assets/stylesheets/alchemy/sitemap.css.scss +0 -1
- data/app/assets/stylesheets/alchemy/tables.css.scss +3 -1
- data/app/controllers/alchemy/admin/base_controller.rb +19 -12
- data/app/controllers/alchemy/admin/elements_controller.rb +52 -24
- data/app/controllers/alchemy/admin/pages_controller.rb +11 -5
- data/app/controllers/alchemy/admin/resources_controller.rb +3 -4
- data/app/controllers/alchemy/admin/users_controller.rb +1 -0
- data/app/controllers/alchemy/base_controller.rb +34 -8
- data/app/controllers/alchemy/pictures_controller.rb +16 -1
- data/app/controllers/alchemy/user_sessions_controller.rb +6 -1
- data/app/helpers/alchemy/base_helper.rb +14 -0
- data/app/helpers/alchemy/elements_helper.rb +10 -5
- data/app/helpers/alchemy/pages_helper.rb +1 -2
- data/app/helpers/alchemy/url_helper.rb +43 -24
- data/app/models/alchemy/element.rb +23 -16
- data/app/models/alchemy/page.rb +25 -14
- data/app/models/alchemy/picture.rb +24 -0
- data/app/views/alchemy/admin/contents/create.js.erb +1 -1
- data/app/views/alchemy/admin/elements/_new_element_form.html.erb +1 -1
- data/app/views/alchemy/admin/elements/create.js.erb +11 -3
- data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
- data/app/views/alchemy/admin/elements/new.html.erb +1 -1
- data/app/views/alchemy/admin/elements/update.js.erb +1 -1
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
- data/app/views/alchemy/admin/languages/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/configure.html.erb +10 -6
- data/app/views/alchemy/admin/pages/configure_external.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -2
- data/app/views/alchemy/admin/pages/new.html.erb +2 -2
- data/app/views/alchemy/admin/pages/update.js.erb +10 -2
- data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +5 -5
- data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +2 -1
- data/app/views/alchemy/admin/pictures/_picture.html.erb +2 -2
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +2 -1
- data/app/views/alchemy/admin/pictures/show_in_window.html.erb +3 -2
- data/app/views/alchemy/admin/resources/_form.html.erb +1 -1
- data/app/views/alchemy/admin/users/_table.html.erb +4 -4
- data/app/views/alchemy/admin/users/edit.html.erb +1 -1
- data/app/views/alchemy/admin/users/new.html.erb +1 -1
- data/app/views/alchemy/base/error_notice.js.erb +1 -1
- data/app/views/alchemy/base/remote_errors.js.erb +2 -3
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +10 -7
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +24 -21
- data/app/views/layouts/alchemy/admin.html.erb +9 -31
- data/bin/alchemy +20 -24
- data/config/alchemy/config.yml +6 -0
- data/config/alchemy/page_layouts.yml +2 -0
- data/config/authorization_rules.rb +1 -1
- data/config/locales/alchemy.de.yml +3 -0
- data/config/locales/alchemy.en.yml +4 -1
- data/db/migrate/20121026100815_alchemy_two_point_three.rb +312 -0
- data/lib/alchemy/mount_point.rb +9 -3
- data/lib/alchemy/page_layout.rb +89 -73
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +45 -12
- data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +3 -1
- data/lib/rails/generators/alchemy/essence/essence_generator.rb +51 -0
- data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +18 -0
- data/lib/rails/generators/alchemy/essence/templates/view.html.erb +2 -0
- data/lib/rails/templates/alchemy.rb +1 -1
- data/lib/tasks/install.rake +57 -2
- data/spec/controllers/admin/elements_controller_spec.rb +170 -22
- data/spec/controllers/admin/trash_controller_spec.rb +1 -1
- data/spec/controllers/admin/users_controller_spec.rb +36 -0
- data/spec/controllers/base_controller_spec.rb +12 -1
- data/spec/controllers/elements_controller_spec.rb +17 -13
- data/spec/controllers/pictures_controller_spec.rb +4 -4
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/db/migrate/20121026100815_alchemy_two_point_three.rb +312 -0
- data/spec/dummy/db/migrate/20121026104128_create_events.rb +19 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/factories.rb +0 -1
- data/spec/helpers/base_helper_spec.rb +48 -0
- data/spec/helpers/elements_helper_spec.rb +14 -3
- data/spec/helpers/url_helper_spec.rb +8 -3
- data/spec/integration/picture_security_spec.rb +35 -0
- data/spec/integration/translation_integration_spec.rb +6 -5
- data/spec/models/element_spec.rb +5 -5
- data/spec/models/page_layout_spec.rb +10 -16
- data/spec/models/page_spec.rb +25 -2
- data/spec/models/picture_spec.rb +24 -2
- data/spec/routing_spec.rb +115 -115
- data/spec/support/alchemy/specs_helpers.rb +4 -4
- data/{app/assets/images/alchemy → vendor/assets/images}/Jcrop.gif +0 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +19 -243
- data/vendor/assets/javascripts/jquery_plugins/jquery.selectboxit.min.js +1 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +6 -6
- data/vendor/assets/stylesheets/jquery.Jcrop.min.css +28 -0
- metadata +48 -82
- data/app/assets/javascripts/alchemy/alchemy.buttons.js +0 -50
- data/app/assets/stylesheets/alchemy/jquery.Jcrop.css.scss +0 -54
- data/app/helpers/alchemy/pictures_helper.rb +0 -19
- data/db/migrate/20100607143125_create_pages.rb +0 -34
- data/db/migrate/20100607144254_create_elements.rb +0 -20
- data/db/migrate/20100607145256_create_contents.rb +0 -18
- data/db/migrate/20100607145719_create_users.rb +0 -32
- data/db/migrate/20100607150611_create_pictures.rb +0 -16
- data/db/migrate/20100607150812_create_attachments.rb +0 -16
- data/db/migrate/20100607153647_create_folded_pages.rb +0 -13
- data/db/migrate/20100607161345_create_essence_texts.rb +0 -19
- data/db/migrate/20100607162339_create_elements_pages.rb +0 -12
- data/db/migrate/20100607193638_create_essence_pictures.rb +0 -23
- data/db/migrate/20100607193646_create_essence_richtexts.rb +0 -16
- data/db/migrate/20100607193653_create_essence_htmls.rb +0 -13
- data/db/migrate/20100609111653_create_essence_dates.rb +0 -13
- data/db/migrate/20100609111809_create_essence_files.rb +0 -15
- data/db/migrate/20100609111821_create_essence_flashes.rb +0 -16
- data/db/migrate/20100609111837_create_essence_videos.rb +0 -18
- data/db/migrate/20100616150753_create_essence_audios.rb +0 -17
- data/db/migrate/20100812085225_add_crop_from_and_crop_size_to_essence_pictures.rb +0 -11
- data/db/migrate/20100909140701_change_essence_htmls_source_column_type.rb +0 -9
- data/db/migrate/20101109150312_alter_pages_visible_column_default.rb +0 -9
- data/db/migrate/20101109151812_create_languages.rb +0 -19
- data/db/migrate/20101216151419_add_language_id_to_pages.rb +0 -27
- data/db/migrate/20101216155216_add_index_to_languages.rb +0 -9
- data/db/migrate/20101216173323_add_default_to_languages.rb +0 -9
- data/db/migrate/20101218130049_add_urlname_index_to_pages.rb +0 -9
- data/db/migrate/20110115123343_remove_css_class_default_from_essence_pictures.rb +0 -11
- data/db/migrate/20110224105120_change_pages_visible_default.rb +0 -11
- data/db/migrate/20110228182659_remove_default_page_layout_from_pages.rb +0 -11
- data/db/migrate/20110414163140_remove_display_name_from_elements.rb +0 -11
- data/db/migrate/20110511100516_rename_essence_texts_title_to_link_title.rb +0 -9
- data/db/migrate/20110529130429_create_cells.rb +0 -14
- data/db/migrate/20110529130500_add_cell_id_to_elements.rb +0 -11
- data/db/migrate/20110530102804_change_pages_page_layout_column.rb +0 -11
- data/db/migrate/20110707190728_add_render_size_to_essence_pictures.rb +0 -9
- data/db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb +0 -19
- data/db/migrate/20110919110451_add_default_role_to_users.rb +0 -9
- data/db/migrate/20111116125112_namespace_alchemy_models.rb +0 -23
- data/db/migrate/20120216135355_add_country_code_to_languages.rb +0 -9
- data/db/migrate/20120608085509_create_alchemy_essence_selects.rb +0 -11
- data/db/migrate/20120611221734_create_alchemy_essence_booleans.rb +0 -11
- data/db/migrate/20120704181529_add_upload_hash_to_alchemy_picture.rb +0 -5
- data/db/migrate/20120705214247_acts_as_taggable_on_migration.rb +0 -28
- data/db/migrate/20120728185830_add_cached_tag_list_to_alchemy_pictures.rb +0 -5
- data/db/migrate/20120831135441_set_alchemy_languages_country_code_default_to_empty_string.rb +0 -9
- data/spec/helpers/pictures_helper_spec.rb +0 -14
- data/vendor/assets/javascripts/jquery_plugins/jquery.selectBoxIt.js +0 -1909
@@ -32,7 +32,7 @@ table tr td.tools {
|
|
32
32
|
@include disable-user-select;
|
33
33
|
}
|
34
34
|
|
35
|
-
td.label, td.input, td.submit, td.select, td.value {
|
35
|
+
td.label, td.input, td.submit, td.select, td.value, td.note {
|
36
36
|
padding: 2px 0;
|
37
37
|
vertical-align: top;
|
38
38
|
}
|
@@ -45,6 +45,8 @@ td.input, td.submit, td.select, td.value {
|
|
45
45
|
}
|
46
46
|
}
|
47
47
|
|
48
|
+
td.submit p.foot_note { float: left; padding-top: 1em }
|
49
|
+
|
48
50
|
td.label {
|
49
51
|
white-space: nowrap;
|
50
52
|
width: 80px;
|
@@ -3,14 +3,14 @@ module Alchemy
|
|
3
3
|
class BaseController < Alchemy::BaseController
|
4
4
|
|
5
5
|
include Userstamp
|
6
|
-
|
6
|
+
before_filter { enforce_ssl if ssl_required? && !request.ssl? }
|
7
7
|
before_filter :set_translation
|
8
8
|
|
9
9
|
helper_method :clipboard_empty?, :trash_empty?, :get_clipboard, :is_admin?
|
10
10
|
|
11
11
|
filter_access_to :all
|
12
12
|
|
13
|
-
rescue_from Exception, :with => :exception_handler
|
13
|
+
rescue_from Exception, :with => :exception_handler unless Rails.env == 'test'
|
14
14
|
|
15
15
|
layout 'alchemy/admin'
|
16
16
|
|
@@ -24,16 +24,13 @@ module Alchemy
|
|
24
24
|
|
25
25
|
# Logs the current exception to the error log.
|
26
26
|
def exception_logger(e)
|
27
|
-
|
28
|
-
e.backtrace.each
|
29
|
-
message += "#{line}\n"
|
30
|
-
end
|
31
|
-
logger.error(message)
|
27
|
+
Rails.logger.error("\n#{e.class} #{e.message} in #{e.backtrace.first}")
|
28
|
+
Rails.logger.error(e.backtrace[1..50].each { |l| l.gsub(/#{Rails.root.to_s}/, '') }.join("\n"))
|
32
29
|
end
|
33
30
|
|
34
31
|
# Displays an error notice in the Alchemy backend.
|
35
32
|
def show_error_notice(e)
|
36
|
-
@notice = "Error: #{e}"
|
33
|
+
@notice = "Error: #{e.message[0..99]}"
|
37
34
|
@trace = e.backtrace
|
38
35
|
if request.xhr?
|
39
36
|
render :action => "error_notice", :layout => false
|
@@ -86,18 +83,28 @@ module Alchemy
|
|
86
83
|
current_user.admin?
|
87
84
|
end
|
88
85
|
|
89
|
-
|
86
|
+
# Displays errors in a #errors div if any errors are present on the object.
|
87
|
+
# Or redirects to the given redirect url.
|
88
|
+
def render_errors_or_redirect(object, redirect_url, flash_notice)
|
90
89
|
if object.errors.empty?
|
91
90
|
@redirect_url = redirect_url
|
92
91
|
flash[:notice] = t(flash_notice)
|
93
92
|
render :action => :redirect
|
94
93
|
else
|
95
|
-
render_remote_errors(object
|
94
|
+
render_remote_errors(object)
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
99
|
-
|
100
|
-
|
98
|
+
# Displays an unordered list of objects errors in an errors div.
|
99
|
+
#
|
100
|
+
# Note: You have to have a hidden div with the id +#errors+ in your form, to make this work.
|
101
|
+
#
|
102
|
+
# You can pass a div id as second argument to display the errors in alternative div.
|
103
|
+
#
|
104
|
+
# Hint: If you use an alternative div, please use the +errors+ css class to get the correct styling.
|
105
|
+
#
|
106
|
+
def render_remote_errors(object, error_div_id = nil)
|
107
|
+
@error_div_id = error_div_id || '#errors'
|
101
108
|
@errors = ("<ul>" + object.errors.full_messages.map { |e| "<li>#{e}</li>" }.join + "</ul>").html_safe
|
102
109
|
render :action => :remote_errors
|
103
110
|
end
|
@@ -37,30 +37,31 @@ module Alchemy
|
|
37
37
|
# Creates a element as discribed in config/alchemy/elements.yml on page via AJAX.
|
38
38
|
def create
|
39
39
|
@page = Page.find(params[:element][:page_id])
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
Element.transaction do
|
41
|
+
if @paste_from_clipboard = params[:paste_from_clipboard].present?
|
42
|
+
@element = paste_element_from_clipboard
|
43
|
+
else
|
44
|
+
@element = Element.new_from_scratch(params[:element])
|
45
|
+
if @page.can_have_cells?
|
46
|
+
@cell = find_or_create_cell
|
47
|
+
@element.cell = @cell
|
48
|
+
end
|
49
|
+
@element.save!
|
50
|
+
end
|
51
|
+
if @insert_at_top = @page.definition['insert_elements_at'] == 'top'
|
52
|
+
@element.move_to_top
|
49
53
|
end
|
50
|
-
else
|
51
|
-
@element = Element.new_from_scratch(params[:element])
|
52
54
|
end
|
53
|
-
|
54
|
-
if @element.
|
55
|
+
@cell_name = @cell.nil? ? "for_other_elements" : @cell.name
|
56
|
+
if @element.valid?
|
55
57
|
render :action => :create
|
56
58
|
else
|
57
|
-
render_remote_errors(@element, '
|
59
|
+
render_remote_errors(@element, params[:paste_from_clipboard].nil? ? nil : '#paste_element_errors')
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
# Saves all contents in the elements by calling
|
63
|
+
# Saves all contents in the elements by calling save_contents.
|
62
64
|
# And then updates the element itself.
|
63
|
-
# If a Ferret::FileNotFoundError raises we gonna catch it and rebuilding the index.
|
64
65
|
def update
|
65
66
|
@element = Element.find_by_id(params[:id])
|
66
67
|
if @element.save_contents(params)
|
@@ -102,16 +103,26 @@ module Alchemy
|
|
102
103
|
|
103
104
|
private
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
if
|
109
|
-
|
110
|
-
@element.cell = @cell
|
111
|
-
return true
|
106
|
+
# Returns the cell for element name in params.
|
107
|
+
# Creates the cell if necessary.
|
108
|
+
def find_or_create_cell
|
109
|
+
if @paste_from_clipboard
|
110
|
+
element_with_cell_name = params[:paste_from_clipboard]
|
112
111
|
else
|
113
|
-
|
112
|
+
element_with_cell_name = params[:element][:name]
|
113
|
+
end
|
114
|
+
if element_with_cell_name.blank?
|
115
|
+
raise "No element with cell name given. Please provide the cell name after the element name (or id) seperated by #."
|
116
|
+
end
|
117
|
+
unless element_with_cell_name.include?('#')
|
118
|
+
return nil
|
114
119
|
end
|
120
|
+
cell_name = element_with_cell_name.split('#').last
|
121
|
+
cell_definition = Cell.definition_for(cell_name)
|
122
|
+
if cell_definition.blank?
|
123
|
+
raise "Cell definition not found for #{cell_name}"
|
124
|
+
end
|
125
|
+
@page.cells.find_or_create_by_name(cell_definition['name'])
|
115
126
|
end
|
116
127
|
|
117
128
|
def element_from_clipboard
|
@@ -119,6 +130,23 @@ module Alchemy
|
|
119
130
|
@clipboard.get(:elements, params[:paste_from_clipboard])
|
120
131
|
end
|
121
132
|
|
133
|
+
def paste_element_from_clipboard
|
134
|
+
@source_element = Element.find(element_from_clipboard[:id])
|
135
|
+
new_attributes = {:page_id => @page.id}
|
136
|
+
if @page.can_have_cells?
|
137
|
+
new_attributes = new_attributes.merge({:cell_id => find_or_create_cell.id})
|
138
|
+
end
|
139
|
+
element = Element.copy(@source_element, new_attributes)
|
140
|
+
cut_element if element_from_clipboard[:action] == 'cut'
|
141
|
+
element
|
142
|
+
end
|
143
|
+
|
144
|
+
def cut_element
|
145
|
+
@cutted_element_id = @source_element.id
|
146
|
+
@clipboard.remove :elements, @source_element.id
|
147
|
+
@source_element.destroy
|
148
|
+
end
|
149
|
+
|
122
150
|
end
|
123
151
|
end
|
124
152
|
end
|
@@ -34,11 +34,14 @@ module Alchemy
|
|
34
34
|
# Setting the locale to pages language. so the page content has its correct translation
|
35
35
|
::I18n.locale = @page.language_code
|
36
36
|
render :layout => layout_for_page
|
37
|
+
rescue Exception => e
|
38
|
+
exception_logger(e)
|
39
|
+
render :file => Rails.root.join('public', '500.html'), :status => 500, :layout => false
|
37
40
|
end
|
38
41
|
|
39
42
|
def new
|
40
43
|
@page = Page.new(:layoutpage => params[:layoutpage] == 'true', :parent_id => params[:parent_id])
|
41
|
-
@page_layouts = PageLayout.
|
44
|
+
@page_layouts = PageLayout.layouts_for_select(session[:language_id], @page.layoutpage?)
|
42
45
|
@clipboard_items = Page.all_from_clipboard_for_select(get_clipboard[:pages], session[:language_id], @page.layoutpage?)
|
43
46
|
render :layout => false
|
44
47
|
end
|
@@ -49,18 +52,18 @@ module Alchemy
|
|
49
52
|
params[:page][:language_code] ||= parent.language ? parent.language.code : Language.get_default.code
|
50
53
|
if !params[:paste_from_clipboard].blank?
|
51
54
|
source_page = Page.find(params[:paste_from_clipboard])
|
52
|
-
page = Page.copy(source_page, {
|
55
|
+
@page = Page.copy(source_page, {
|
53
56
|
:name => params[:page][:name].blank? ? source_page.name + ' (' + t('Copy') + ')' : params[:page][:name],
|
54
57
|
:urlname => '',
|
55
58
|
:title => '',
|
56
59
|
:parent_id => params[:page][:parent_id],
|
57
60
|
:language => parent.language
|
58
61
|
})
|
59
|
-
source_page.copy_children_to(page) unless source_page.children.blank?
|
62
|
+
source_page.copy_children_to(@page) unless source_page.children.blank?
|
60
63
|
else
|
61
|
-
page = Page.create(params[:page])
|
64
|
+
@page = Page.create(params[:page])
|
62
65
|
end
|
63
|
-
render_errors_or_redirect(page,
|
66
|
+
render_errors_or_redirect(@page, @page.valid? ? edit_admin_page_path(@page) : admin_pages_path, t("Page created", :name => @page.name))
|
64
67
|
end
|
65
68
|
|
66
69
|
# Edit the content of the page and all its elements and contents.
|
@@ -82,12 +85,15 @@ module Alchemy
|
|
82
85
|
if @page.redirects_to_external?
|
83
86
|
render :action => 'configure_external', :layout => false
|
84
87
|
else
|
88
|
+
@page_layouts = PageLayout.layouts_with_own_for_select(@page.page_layout, session[:language_id], @page.layoutpage?)
|
85
89
|
render :layout => false
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
89
93
|
def update
|
90
94
|
# fetching page via before filter
|
95
|
+
# storing old page_layout value, because unfurtunally rails @page.changes does not work here.
|
96
|
+
@old_page_layout = @page.page_layout
|
91
97
|
if @page.update_attributes(params[:page])
|
92
98
|
@notice = t("Page saved", :name => @page.name)
|
93
99
|
@while_page_edit = request.referer.include?('edit')
|
@@ -63,10 +63,9 @@ module Alchemy
|
|
63
63
|
@_resource_handler ||= Alchemy::Resource.new(controller_path, alchemy_module)
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
protected
|
67
67
|
|
68
|
-
|
69
|
-
def render_errors_or_redirect(object, redirect_url, flash_notice, button = nil)
|
68
|
+
def render_errors_or_redirect(object, redirect_url, flash_notice)
|
70
69
|
if object.errors.empty?
|
71
70
|
@redirect_url = redirect_url
|
72
71
|
flash[:notice] = t(flash_notice)
|
@@ -76,7 +75,7 @@ module Alchemy
|
|
76
75
|
end
|
77
76
|
else
|
78
77
|
respond_to do |format|
|
79
|
-
format.js { render_remote_errors(object
|
78
|
+
format.js { render_remote_errors(object) }
|
80
79
|
format.html { render :action => :new }
|
81
80
|
end
|
82
81
|
end
|
@@ -51,6 +51,7 @@ module Alchemy
|
|
51
51
|
|
52
52
|
def update
|
53
53
|
# User is fetched via before filter
|
54
|
+
params[:user].delete(:role) unless permitted_to?(:update_role)
|
54
55
|
@user.update_attributes(params[:user])
|
55
56
|
Notifications.admin_user_created(@user).deliver if params[:send_credentials]
|
56
57
|
render_errors_or_redirect(
|
@@ -15,15 +15,19 @@ module Alchemy
|
|
15
15
|
def current_server
|
16
16
|
# For local development server
|
17
17
|
if request.port != 80
|
18
|
-
"
|
18
|
+
"#{request.protocol}#{request.host}:#{request.port}"
|
19
19
|
# For remote production server
|
20
20
|
else
|
21
|
-
"
|
21
|
+
"#{request.protocol}#{request.host}"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
# Returns the configuratin value of given key.
|
26
|
+
#
|
27
|
+
# Config file is in +config/alchemy/config.yml+
|
28
|
+
#
|
25
29
|
def configuration(name)
|
26
|
-
|
30
|
+
Alchemy::Config.get(name)
|
27
31
|
end
|
28
32
|
|
29
33
|
def multi_language?
|
@@ -56,6 +60,8 @@ module Alchemy
|
|
56
60
|
session[:current_locale] = ::I18n.locale = params[:locale]
|
57
61
|
elsif current_user && current_user.language.present?
|
58
62
|
::I18n.locale = current_user.language
|
63
|
+
elsif Rails.env == 'test' # OMG I hate to do this. But it helps...
|
64
|
+
::I18n.locale = 'en'
|
59
65
|
else
|
60
66
|
::I18n.locale = request.env['HTTP_ACCEPT_LANGUAGE'].try(:scan, /^[a-z]{2}/).try(:first)
|
61
67
|
end
|
@@ -66,8 +72,7 @@ module Alchemy
|
|
66
72
|
if params[:lang].blank? and session[:language_id].blank?
|
67
73
|
set_language_to_default
|
68
74
|
elsif !params[:lang].blank?
|
69
|
-
set_language_from(params[:lang])
|
70
|
-
::I18n.locale = params[:lang]
|
75
|
+
::I18n.locale = set_language_from(params[:lang])
|
71
76
|
end
|
72
77
|
end
|
73
78
|
|
@@ -95,9 +100,8 @@ module Alchemy
|
|
95
100
|
|
96
101
|
def store_language_in_session(language)
|
97
102
|
if language && language.id
|
98
|
-
return if language.id == session[:language_id]
|
99
|
-
session[:language_code] = language.code
|
100
103
|
session[:language_id] = language.id
|
104
|
+
session[:language_code] = language.code
|
101
105
|
else
|
102
106
|
logger.warn "!!!! Language not found for #{language.inspect}. Setting to default!"
|
103
107
|
set_language_to_default
|
@@ -159,6 +163,28 @@ module Alchemy
|
|
159
163
|
render :file => Rails.root.join("public/404.html"), :status => 404, :layout => !@page.nil?
|
160
164
|
end
|
161
165
|
|
166
|
+
# Enforce ssl for login and all admin modules.
|
167
|
+
#
|
168
|
+
# Default is +false+
|
169
|
+
#
|
170
|
+
# === Usage
|
171
|
+
#
|
172
|
+
# #config.yml
|
173
|
+
# require_ssl: true
|
174
|
+
#
|
175
|
+
# === Note
|
176
|
+
#
|
177
|
+
# You have to create a ssl certificate if you want to use the ssl protection
|
178
|
+
#
|
179
|
+
def ssl_required?
|
180
|
+
(Rails.env == 'production' || Rails.env == 'staging') && configuration(:require_ssl)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Redirects request to ssl.
|
184
|
+
def enforce_ssl
|
185
|
+
redirect_to url_for(protocol: 'https')
|
186
|
+
end
|
187
|
+
|
162
188
|
protected
|
163
189
|
|
164
190
|
def permission_denied
|
@@ -171,7 +197,7 @@ module Alchemy
|
|
171
197
|
elsif request.xhr?
|
172
198
|
respond_to do |format|
|
173
199
|
format.js {
|
174
|
-
render :js => "Alchemy.growl('#{t('You are not authorized')}', 'warning'); Alchemy.
|
200
|
+
render :js => "Alchemy.growl('#{t('You are not authorized')}', 'warning'); Alchemy.Buttons.enable();"
|
175
201
|
}
|
176
202
|
format.html {
|
177
203
|
render :partial => 'alchemy/admin/partials/flash', :locals => {:message => t('You are not authorized'), :flash_type => 'warning'}
|
@@ -3,7 +3,7 @@ module Alchemy
|
|
3
3
|
|
4
4
|
caches_page :show, :thumbnail, :zoom
|
5
5
|
|
6
|
-
before_filter :load_picture
|
6
|
+
before_filter :load_picture, :ensure_secure_params
|
7
7
|
|
8
8
|
filter_access_to :show, :attribute_check => true, :model => Alchemy::Picture, :load_method => :load_picture
|
9
9
|
filter_access_to :thumbnail
|
@@ -60,5 +60,20 @@ module Alchemy
|
|
60
60
|
@picture ||= Picture.find(params[:id])
|
61
61
|
end
|
62
62
|
|
63
|
+
def ensure_secure_params
|
64
|
+
token = params[:sh]
|
65
|
+
digest = Digest::SHA1.hexdigest(secured_params)[0..15]
|
66
|
+
bad_request unless token && (token == digest)
|
67
|
+
end
|
68
|
+
|
69
|
+
def secured_params
|
70
|
+
[params[:id], params[:size], params[:crop], params[:crop_from], params[:crop_size], Rails.configuration.secret_token].join('-')
|
71
|
+
end
|
72
|
+
|
73
|
+
def bad_request
|
74
|
+
render :text => "Bad picture parameters in #{request.path}", :status => 400
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
|
63
78
|
end
|
64
79
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Alchemy
|
2
2
|
class UserSessionsController < Alchemy::BaseController
|
3
3
|
|
4
|
+
before_filter { enforce_ssl if ssl_required? && !request.ssl? }
|
4
5
|
before_filter :set_translation
|
5
6
|
before_filter :check_user_count, :only => :login
|
6
7
|
|
@@ -20,9 +21,13 @@ module Alchemy
|
|
20
21
|
if params[:send_credentials]
|
21
22
|
Notifications.admin_user_created(@user).deliver
|
22
23
|
end
|
24
|
+
flash[:notice] = t('Successfully signup admin user')
|
23
25
|
redirect_to admin_dashboard_path
|
24
26
|
end
|
25
27
|
end
|
28
|
+
rescue Errno::ECONNREFUSED => e
|
29
|
+
flash[:error] = t(:signup_mail_delivery_error)
|
30
|
+
redirect_to admin_dashboard_path
|
26
31
|
end
|
27
32
|
|
28
33
|
def login
|
@@ -63,7 +68,7 @@ module Alchemy
|
|
63
68
|
redirect_to root_url
|
64
69
|
end
|
65
70
|
|
66
|
-
|
71
|
+
private
|
67
72
|
|
68
73
|
def check_user_count
|
69
74
|
if User.count == 0
|
@@ -45,6 +45,20 @@ module Alchemy
|
|
45
45
|
content_tag('span', '', :class => "icon #{icon_class}")
|
46
46
|
end
|
47
47
|
|
48
|
+
# Returns a div with an icon and the passed content
|
49
|
+
# The default message type is info, but you can also pass
|
50
|
+
# other types like :warning or :error
|
51
|
+
#
|
52
|
+
# === Usage:
|
53
|
+
#
|
54
|
+
# <%= render_message :warning do
|
55
|
+
# <p>Caution! This is a warning!</p>
|
56
|
+
# <% end %>
|
57
|
+
#
|
58
|
+
def render_message(type = :info, &blk)
|
59
|
+
content_tag :div, render_icon(type) + capture(&blk), :class => "#{type} message"
|
60
|
+
end
|
61
|
+
|
48
62
|
# Returns an array of all pages in the same branch from current.
|
49
63
|
# I.e. used to find the active page in navigation.
|
50
64
|
def breadcrumb(current)
|