alchemy_cms 3.2.0.beta → 3.2.0.rc1
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 +4 -4
- data/.rubocop.yml +661 -863
- data/README.md +5 -63
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +11 -10
- data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +6 -0
- data/app/assets/stylesheets/alchemy/_extends.scss +0 -6
- data/app/assets/stylesheets/alchemy/_mixins.scss +6 -0
- data/app/assets/stylesheets/alchemy/buttons.scss +1 -1
- data/app/assets/stylesheets/alchemy/elements.scss +1 -1
- data/app/assets/stylesheets/alchemy/menubar.scss +1 -1
- data/app/assets/stylesheets/alchemy/selects.scss +5 -1
- data/app/assets/stylesheets/alchemy/upload.scss +1 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/base_controller.rb +4 -57
- data/app/controllers/alchemy/messages_controller.rb +2 -2
- data/app/controllers/alchemy/pages_controller.rb +22 -31
- data/app/controllers/alchemy/pictures_controller.rb +2 -2
- data/app/helpers/alchemy/admin/base_helper.rb +7 -0
- data/app/helpers/alchemy/admin/elements_helper.rb +31 -15
- data/app/helpers/alchemy/admin/pages_helper.rb +17 -0
- data/app/helpers/alchemy/base_helper.rb +0 -28
- data/app/helpers/alchemy/pages_helper.rb +18 -12
- data/app/helpers/alchemy/url_helper.rb +2 -2
- data/app/models/alchemy/cell.rb +1 -1
- data/app/models/alchemy/content/factory.rb +12 -6
- data/app/models/alchemy/element.rb +3 -3
- data/app/models/alchemy/element/definitions.rb +1 -1
- data/app/models/alchemy/element_to_page.rb +7 -0
- data/app/models/alchemy/language.rb +1 -1
- data/app/models/alchemy/page.rb +8 -1
- data/app/models/alchemy/page/page_cells.rb +2 -2
- data/app/models/alchemy/page/page_elements.rb +23 -5
- data/app/models/alchemy/page/page_natures.rb +3 -3
- data/app/models/alchemy/page/page_scopes.rb +1 -1
- data/app/models/alchemy/picture.rb +1 -1
- data/app/views/alchemy/admin/pages/_create_language_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -1
- data/app/views/alchemy/breadcrumb/_page.html.erb +3 -2
- data/app/views/alchemy/breadcrumb/_separator.html.erb +1 -0
- data/app/views/alchemy/breadcrumb/_wrapper.html.erb +13 -0
- data/app/views/alchemy/language_links/_language.html.erb +1 -1
- data/app/views/alchemy/navigation/_link.html.erb +1 -1
- data/app/views/alchemy/pages/show.rss.builder +5 -7
- data/app/views/layouts/alchemy/admin.html.erb +5 -0
- data/config/routes.rb +13 -10
- data/lib/alchemy/configuration_methods.rb +29 -0
- data/lib/alchemy/controller_actions.rb +12 -4
- data/lib/alchemy/engine.rb +3 -0
- data/lib/alchemy/errors.rb +1 -1
- data/lib/alchemy/essence.rb +14 -12
- data/lib/alchemy/on_page_layout.rb +58 -0
- data/lib/alchemy/page_layout.rb +1 -1
- data/lib/alchemy/permissions.rb +21 -16
- data/lib/alchemy/routing_constraints.rb +49 -0
- data/lib/alchemy/seeder.rb +4 -2
- data/lib/alchemy/ssl_protection.rb +30 -0
- data/lib/alchemy/test_support/essence_shared_examples.rb +118 -25
- data/lib/alchemy/test_support/factories.rb +5 -8
- data/lib/alchemy/test_support/integration_helpers.rb +16 -10
- data/lib/alchemy/upgrader/three_point_two.rb +34 -4
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/{scaffold → install}/files/_article_editor.html.erb +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/_article_view.html.erb +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/_standard.html.erb +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.de.yml +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.elements.css.scss +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.en.yml +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/alchemy.es.yml +0 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/files/application.html.erb +0 -0
- data/lib/rails/generators/alchemy/install/install_generator.rb +69 -0
- data/lib/rails/generators/alchemy/{scaffold/files/elements.yml → install/templates/elements.yml.tt} +2 -0
- data/lib/rails/generators/alchemy/{scaffold → install}/templates/page_layouts.yml.tt +2 -0
- data/lib/rails/generators/alchemy/views/views_generator.rb +41 -0
- data/lib/rails/templates/alchemy.rb +2 -2
- data/lib/tasks/alchemy/db.rake +0 -5
- data/lib/tasks/alchemy/install.rake +10 -5
- data/lib/tasks/alchemy/tidy.rake +2 -0
- data/spec/controllers/admin/attachments_controller_spec.rb +1 -1
- data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
- data/spec/controllers/admin/contents_controller_spec.rb +1 -1
- data/spec/controllers/admin/dashboard_controller_spec.rb +2 -2
- data/spec/controllers/admin/elements_controller_spec.rb +1 -1
- data/spec/controllers/admin/essence_files_controller_spec.rb +1 -1
- data/spec/controllers/admin/essence_pictures_controller_spec.rb +1 -1
- data/spec/controllers/admin/languages_controller_spec.rb +1 -1
- data/spec/controllers/admin/layoutpages_controller_spec.rb +1 -1
- data/spec/controllers/admin/pages_controller_spec.rb +4 -4
- data/spec/controllers/admin/pictures_controller_spec.rb +1 -1
- data/spec/controllers/admin/resources_controller_spec.rb +1 -1
- data/spec/controllers/admin/trash_controller_spec.rb +1 -1
- data/spec/controllers/alchemy/admin/tags_controller_spec.rb +1 -1
- data/spec/controllers/attachments_controller_spec.rb +1 -1
- data/spec/controllers/base_controller_spec.rb +22 -0
- data/spec/controllers/elements_controller_spec.rb +1 -1
- data/spec/controllers/pages_controller_spec.rb +15 -16
- data/spec/controllers/pictures_controller_spec.rb +212 -162
- data/spec/dummy/app/controllers/login_controller.rb +5 -0
- data/spec/dummy/app/models/dummy_model.rb +3 -0
- data/spec/dummy/config/alchemy/cells.yml +4 -1
- data/spec/dummy/config/alchemy/elements.yml +8 -0
- data/spec/dummy/config/alchemy/page_layouts.yml +5 -1
- data/spec/dummy/config/routes.rb +1 -2
- data/spec/dummy/db/migrate/20150412103152_create_dummy_model.rb +7 -0
- data/spec/dummy/db/schema.rb +30 -26
- data/spec/features/admin/dashboard_spec.rb +11 -9
- data/spec/features/admin/language_tree_feature_spec.rb +5 -6
- data/spec/features/admin/legacy_page_url_management_spec.rb +1 -1
- data/spec/features/admin/link_overlay_spec.rb +1 -1
- data/spec/features/admin/locale_select_feature_spec.rb +1 -1
- data/spec/features/admin/modules_integration_spec.rb +1 -1
- data/spec/features/admin/navigation_feature_spec.rb +1 -1
- data/spec/features/admin/page_creation_feature_spec.rb +1 -1
- data/spec/features/admin/page_editing_feature_spec.rb +3 -3
- data/spec/features/admin/picture_library_integration_spec.rb +1 -1
- data/spec/features/admin/resources_integration_spec.rb +1 -1
- data/spec/features/admin/site_select_feature_spec.rb +32 -0
- data/spec/features/admin/tinymce_feature_spec.rb +1 -3
- data/spec/features/page_feature_spec.rb +36 -27
- data/spec/features/security_spec.rb +1 -1
- data/spec/features/translation_integration_spec.rb +3 -3
- data/spec/helpers/admin/elements_helper_spec.rb +103 -26
- data/spec/helpers/admin/pages_helper_spec.rb +32 -1
- data/spec/helpers/base_helper_spec.rb +0 -45
- data/spec/helpers/pages_helper_spec.rb +18 -17
- data/spec/helpers/url_helper_spec.rb +8 -5
- data/spec/libraries/controller_actions_spec.rb +2 -2
- data/spec/libraries/on_page_layout_spec.rb +112 -0
- data/spec/libraries/page_layout_spec.rb +5 -1
- data/spec/libraries/permissions_spec.rb +13 -15
- data/spec/models/cell_spec.rb +4 -0
- data/spec/models/content_spec.rb +6 -0
- data/spec/models/dummy_model_spec.rb +11 -0
- data/spec/models/element_spec.rb +6 -1
- data/spec/models/element_to_page_spec.rb +14 -0
- data/spec/models/page_spec.rb +111 -19
- data/spec/routing/routing_spec.rb +120 -101
- data/spec/spec_helper.rb +3 -3
- metadata +36 -21
- data/app/views/alchemy/breadcrumb/_spacer.html.erb +0 -1
- data/lib/alchemy/capistrano.rb +0 -230
- data/lib/alchemy/test_support/auth_helpers.rb +0 -35
- data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +0 -90
- data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +0 -113
- data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +0 -63
- data/spec/dummy/app/controllers/errors_controller.rb +0 -5
data/lib/rails/generators/alchemy/{scaffold/files/elements.yml → install/templates/elements.yml.tt}
RENAMED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# For further informations please see http://guides.alchemy-cms.com/create_elements.html
|
|
4
4
|
|
|
5
|
+
<%- unless @options[:skip_demo_files] -%>
|
|
5
6
|
- name: article
|
|
6
7
|
hint: true
|
|
7
8
|
unique: true
|
|
@@ -17,3 +18,4 @@
|
|
|
17
18
|
type: EssenceRichtext
|
|
18
19
|
default: :article_text
|
|
19
20
|
hint: true
|
|
21
|
+
<%- end -%>
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
#
|
|
3
3
|
# For further informations please see http://guides.alchemy-cms.com/create_page_layouts.html
|
|
4
4
|
|
|
5
|
+
<%- unless @options[:skip_demo_files] -%>
|
|
5
6
|
- name: <%= Alchemy::Config.get(:default_language)['page_layout'] %>
|
|
6
7
|
unique: true
|
|
7
8
|
elements: [article]
|
|
8
9
|
autogenerate: [article]
|
|
10
|
+
<%- end -%>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'rails'
|
|
2
|
+
|
|
3
|
+
module Alchemy
|
|
4
|
+
module Generators
|
|
5
|
+
class ViewsGenerator < ::Rails::Generators::Base
|
|
6
|
+
ALCHEMY_VIEWS = %w(breadcrumb language_links messages navigation)
|
|
7
|
+
|
|
8
|
+
desc "Generates Alchemy views for #{ALCHEMY_VIEWS.to_sentence}."
|
|
9
|
+
|
|
10
|
+
class_option :only,
|
|
11
|
+
type: :array,
|
|
12
|
+
default: nil,
|
|
13
|
+
desc: "List of views to copy. Available views are #{ALCHEMY_VIEWS.to_sentence}."
|
|
14
|
+
|
|
15
|
+
class_option :except,
|
|
16
|
+
type: :array,
|
|
17
|
+
default: nil,
|
|
18
|
+
desc: "List of views not to copy. Available views are #{ALCHEMY_VIEWS.to_sentence}."
|
|
19
|
+
|
|
20
|
+
source_root File.expand_path("../../../../../app/views/alchemy", File.dirname(__FILE__))
|
|
21
|
+
|
|
22
|
+
def copy_alchemy_views
|
|
23
|
+
views_to_copy.each do |dir|
|
|
24
|
+
directory dir, Rails.root.join('app/views/alchemy', dir)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def views_to_copy
|
|
31
|
+
if @options['except']
|
|
32
|
+
ALCHEMY_VIEWS - @options['except']
|
|
33
|
+
elsif @options['only']
|
|
34
|
+
ALCHEMY_VIEWS.select { |v| @options['only'].include?(v) }
|
|
35
|
+
else
|
|
36
|
+
ALCHEMY_VIEWS
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# This rails template installs Alchemy and all depending gems.
|
|
2
2
|
require File.expand_path("../../../alchemy/version", __FILE__)
|
|
3
3
|
|
|
4
|
-
gem "alchemy_cms", github: "AlchemyCMS/alchemy_cms", branch: "
|
|
4
|
+
gem "alchemy_cms", github: "AlchemyCMS/alchemy_cms", branch: "3.2-stable"
|
|
5
5
|
gem "alchemy-devise", github: "AlchemyCMS/alchemy-devise", branch: "master"
|
|
6
6
|
|
|
7
|
-
gem "capistrano", "
|
|
7
|
+
gem "capistrano-alchemy", github: "AlchemyCMS/capistrano-alchemy", branch: "master", group: "development"
|
data/lib/tasks/alchemy/db.rake
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
require 'shellwords'
|
|
2
|
-
require 'alchemy/seeder'
|
|
3
2
|
require 'alchemy/tasks/helpers'
|
|
4
3
|
include Alchemy::Tasks::Helpers
|
|
5
4
|
|
|
6
5
|
namespace :alchemy do
|
|
7
6
|
namespace :db do
|
|
8
|
-
desc "Seeds your database with essential data for Alchemy CMS."
|
|
9
|
-
task :seed => :environment do
|
|
10
|
-
Alchemy::Seeder.seed!
|
|
11
|
-
end
|
|
12
7
|
|
|
13
8
|
desc "Dumps the database to STDOUT (Pass DUMP_FILENAME to store the dump into a file)."
|
|
14
9
|
task :dump => :environment do
|
|
@@ -20,26 +20,32 @@ class Alchemy::InstallTask < Thor
|
|
|
20
20
|
match = "default_language:\n code: #{code}\n name: #{name}"
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
|
-
end
|
|
24
23
|
|
|
24
|
+
def inject_seeder
|
|
25
|
+
append_file "./db/seeds.rb", "Alchemy::Seeder.seed!\n"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
namespace :alchemy do
|
|
28
31
|
|
|
29
32
|
desc "Installs Alchemy CMS into your app."
|
|
30
33
|
task :install do
|
|
34
|
+
install_helper = Alchemy::InstallTask.new
|
|
35
|
+
|
|
31
36
|
unless ENV['from_binary']
|
|
32
37
|
puts "\nAlchemy Installer"
|
|
33
38
|
puts "-----------------"
|
|
34
39
|
end
|
|
35
40
|
Rake::Task["alchemy:mount"].invoke
|
|
36
|
-
system("rails g alchemy:
|
|
37
|
-
|
|
41
|
+
system("rails g alchemy:install#{ ENV['from_binary'] ? ' --force' : '' }") || exit!(1)
|
|
42
|
+
install_helper.set_primary_language
|
|
38
43
|
Rake::Task["db:create"].invoke
|
|
39
44
|
# We can't invoke this rake task, because Rails will use wrong engine names otherwise
|
|
40
45
|
`bundle exec rake railties:install:migrations`
|
|
41
46
|
Rake::Task["db:migrate"].invoke
|
|
42
|
-
|
|
47
|
+
install_helper.inject_seeder
|
|
48
|
+
Rake::Task["db:seed"].invoke
|
|
43
49
|
unless ENV['from_binary']
|
|
44
50
|
puts "\nAlchemy successfully installed."
|
|
45
51
|
puts "\nNow start the server with:"
|
|
@@ -52,5 +58,4 @@ namespace :alchemy do
|
|
|
52
58
|
task :mount do
|
|
53
59
|
Alchemy::InstallTask.new.inject_routes
|
|
54
60
|
end
|
|
55
|
-
|
|
56
61
|
end
|
data/lib/tasks/alchemy/tidy.rake
CHANGED
|
@@ -2,9 +2,9 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module Alchemy
|
|
4
4
|
describe Admin::DashboardController do
|
|
5
|
-
let(:user) {
|
|
5
|
+
let(:user) { build(:alchemy_dummy_user, :as_admin) }
|
|
6
6
|
|
|
7
|
-
before {
|
|
7
|
+
before { authorize_user(user) }
|
|
8
8
|
|
|
9
9
|
describe '#index' do
|
|
10
10
|
before do
|
|
@@ -7,7 +7,7 @@ module Alchemy
|
|
|
7
7
|
let(:element_in_clipboard) { create(:element, :page_id => alchemy_page.id) }
|
|
8
8
|
let(:clipboard) { session[:alchemy_clipboard] = {} }
|
|
9
9
|
|
|
10
|
-
before {
|
|
10
|
+
before { authorize_user(:as_author) }
|
|
11
11
|
|
|
12
12
|
describe '#index' do
|
|
13
13
|
let(:alchemy_page) { build_stubbed(:page) }
|
|
@@ -12,7 +12,7 @@ module Alchemy
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
context 'a member' do
|
|
15
|
-
before {
|
|
15
|
+
before { authorize_user(build(:alchemy_dummy_user)) }
|
|
16
16
|
|
|
17
17
|
it 'can not access page tree' do
|
|
18
18
|
alchemy_get :index
|
|
@@ -21,9 +21,9 @@ module Alchemy
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
context 'with logged in editor user' do
|
|
24
|
-
let(:user) {
|
|
24
|
+
let(:user) { build(:alchemy_dummy_user, :as_editor) }
|
|
25
25
|
|
|
26
|
-
before {
|
|
26
|
+
before { authorize_user(user) }
|
|
27
27
|
|
|
28
28
|
describe '#index' do
|
|
29
29
|
let(:language) { build_stubbed(:language) }
|
|
@@ -367,7 +367,7 @@ module Alchemy
|
|
|
367
367
|
|
|
368
368
|
describe '#edit' do
|
|
369
369
|
let!(:page) { create(:page) }
|
|
370
|
-
let!(:other_user) { create(:
|
|
370
|
+
let!(:other_user) { create(:alchemy_dummy_user, :as_author) }
|
|
371
371
|
|
|
372
372
|
context 'if page is locked by another user' do
|
|
373
373
|
before { page.lock_to!(other_user) }
|
|
@@ -47,7 +47,7 @@ module Alchemy
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
context "as member user" do
|
|
50
|
-
before {
|
|
50
|
+
before { authorize_user(build(:alchemy_dummy_user)) }
|
|
51
51
|
|
|
52
52
|
it "should be possible to download attachments from restricted pages" do
|
|
53
53
|
alchemy_get :download, :id => attachment.id
|
|
@@ -25,5 +25,27 @@ module Alchemy
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
describe "#configuration" do
|
|
29
|
+
it "returns certain configuration options" do
|
|
30
|
+
allow(Config).to receive(:show).and_return({"some_option" => true})
|
|
31
|
+
expect(controller.configuration(:some_option)).to eq(true)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#multi_language?" do
|
|
36
|
+
context "if more than one published language exists" do
|
|
37
|
+
it "returns true" do
|
|
38
|
+
allow(Alchemy::Language).to receive(:published).and_return double(count: 2)
|
|
39
|
+
expect(controller.multi_language?).to eq(true)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "if less than two published languages exists" do
|
|
44
|
+
it "returns false" do
|
|
45
|
+
allow(Alchemy::Language).to receive(:published).and_return double(count: 1)
|
|
46
|
+
expect(controller.multi_language?).to eq(false)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
28
50
|
end
|
|
29
51
|
end
|
|
@@ -12,11 +12,12 @@ module Alchemy
|
|
|
12
12
|
context 'an author' do
|
|
13
13
|
let(:unpublic) { create(:page, parent: default_language_root) }
|
|
14
14
|
|
|
15
|
-
before {
|
|
15
|
+
before { authorize_user(:as_author) }
|
|
16
16
|
|
|
17
17
|
it "should not be able to visit a unpublic page" do
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
expect {
|
|
19
|
+
alchemy_get :show, urlname: unpublic.urlname
|
|
20
|
+
}.to raise_error(ActionController::RoutingError)
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
|
|
@@ -75,18 +76,18 @@ module Alchemy
|
|
|
75
76
|
|
|
76
77
|
context "with incorrect levelnames in params" do
|
|
77
78
|
it "should render a 404 page" do
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
expect {
|
|
80
|
+
alchemy_get :show, {urlname: 'catalog/faqs/screwdriver'}
|
|
81
|
+
}.to raise_error(ActionController::RoutingError)
|
|
81
82
|
end
|
|
82
83
|
end
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
context "when a non-existent page is requested" do
|
|
86
87
|
it "should rescue a RoutingError with rendering a 404 page." do
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
expect {
|
|
89
|
+
alchemy_get :show, {urlname: 'doesntexist'}
|
|
90
|
+
}.to raise_error(ActionController::RoutingError)
|
|
90
91
|
end
|
|
91
92
|
end
|
|
92
93
|
|
|
@@ -139,14 +140,14 @@ module Alchemy
|
|
|
139
140
|
|
|
140
141
|
it "should redirect permanently to page that belongs to legacy page url even if url has an unknown format & get parameters" do
|
|
141
142
|
expect(request).to receive(:fullpath).at_least(:once).and_return(legacy_url4.urlname)
|
|
142
|
-
alchemy_get :show, urlname:
|
|
143
|
+
alchemy_get :show, urlname: legacy_url4.urlname
|
|
143
144
|
expect(response.status).to eq(301)
|
|
144
145
|
expect(response).to redirect_to("/#{second_page.urlname}")
|
|
145
146
|
end
|
|
146
147
|
|
|
147
148
|
it "should not pass query string for legacy routes" do
|
|
148
149
|
expect(request).to receive(:fullpath).at_least(:once).and_return(legacy_url3.urlname)
|
|
149
|
-
alchemy_get :show, urlname:
|
|
150
|
+
alchemy_get :show, urlname: legacy_url4.urlname
|
|
150
151
|
expect(URI.parse(response["Location"]).query).to be_nil
|
|
151
152
|
end
|
|
152
153
|
|
|
@@ -184,12 +185,12 @@ module Alchemy
|
|
|
184
185
|
|
|
185
186
|
context "with no lang parameter present" do
|
|
186
187
|
it "should store defaults language id in the session." do
|
|
187
|
-
alchemy_get :show, urlname:
|
|
188
|
+
alchemy_get :show, urlname: page.urlname
|
|
188
189
|
expect(controller.session[:alchemy_language_id]).to eq(Language.default.id)
|
|
189
190
|
end
|
|
190
191
|
|
|
191
192
|
it "should store default language as class var." do
|
|
192
|
-
alchemy_get :show, urlname:
|
|
193
|
+
alchemy_get :show, urlname: page.urlname
|
|
193
194
|
expect(Language.current).to eq(Language.default)
|
|
194
195
|
end
|
|
195
196
|
end
|
|
@@ -209,10 +210,8 @@ module Alchemy
|
|
|
209
210
|
end
|
|
210
211
|
|
|
211
212
|
context 'with user logged in' do
|
|
212
|
-
let(:author_user) { mock_model(Alchemy.user_class, cache_key: 'bbb') }
|
|
213
|
-
|
|
214
213
|
before do
|
|
215
|
-
|
|
214
|
+
authorize_user(mock_model(Alchemy.user_class, cache_key: 'bbb'))
|
|
216
215
|
end
|
|
217
216
|
|
|
218
217
|
it "returns another etag for response headers" do
|
|
@@ -19,12 +19,37 @@ module Alchemy
|
|
|
19
19
|
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/80x60.png', __FILE__), 'image/png'))
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
before { sign_in(editor_user) }
|
|
23
|
-
|
|
24
22
|
it "renders the original image without any resizing" do
|
|
25
23
|
alchemy_get :zoom, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
26
24
|
expect(response.body[0x10..0x18].unpack('NN')).to eq([80, 60])
|
|
27
25
|
end
|
|
26
|
+
|
|
27
|
+
context "Requesting a picture that is assigned with restricted pages only" do
|
|
28
|
+
before do
|
|
29
|
+
essence = restricted_element.contents.where(name: 'image').first.essence
|
|
30
|
+
essence.picture_id = picture.id
|
|
31
|
+
essence.save
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "as guest user" do
|
|
35
|
+
it "should not render the picture, but redirect to login path" do
|
|
36
|
+
alchemy_get :zoom, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
37
|
+
expect(response.status).to eq(302)
|
|
38
|
+
expect(response).to redirect_to(Alchemy.login_path)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "as member user" do
|
|
43
|
+
before do
|
|
44
|
+
authorize_user(build(:alchemy_dummy_user))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should render the picture" do
|
|
48
|
+
alchemy_get :zoom, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
49
|
+
expect(response.status).to eq(200)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
28
53
|
end
|
|
29
54
|
|
|
30
55
|
describe '#show' do
|
|
@@ -35,222 +60,247 @@ module Alchemy
|
|
|
35
60
|
request.session_options.fetch(:skip) { false }
|
|
36
61
|
}.to(true)
|
|
37
62
|
end
|
|
38
|
-
end
|
|
39
63
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
64
|
+
context "Requesting a picture with tempared security token" do
|
|
65
|
+
it "should render status 400" do
|
|
66
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: '14m4b4dh4ck3r'
|
|
67
|
+
expect(response.status).to eq(400)
|
|
68
|
+
end
|
|
44
69
|
end
|
|
45
|
-
end
|
|
46
70
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
71
|
+
context "Requesting a picture with another format then the original image" do
|
|
72
|
+
it "should convert the picture format" do
|
|
73
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :jpeg, sh: picture.security_token
|
|
74
|
+
expect(response.content_type).to eq('image/jpeg')
|
|
75
|
+
end
|
|
51
76
|
end
|
|
52
|
-
end
|
|
53
77
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
context "Requesting a picture with not allowed format" do
|
|
79
|
+
it "should raise error" do
|
|
80
|
+
expect {
|
|
81
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :wim, sh: picture.security_token
|
|
82
|
+
}.to raise_error(ActionController::UnknownFormat)
|
|
83
|
+
end
|
|
59
84
|
end
|
|
60
|
-
end
|
|
61
85
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
context "Requesting a picture that has no image file attached" do
|
|
87
|
+
before do
|
|
88
|
+
expect(picture).to receive(:image_file).and_return(nil)
|
|
89
|
+
expect(Picture).to receive(:find).and_return(picture)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "raises missing file error" do
|
|
93
|
+
expect {
|
|
94
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
95
|
+
}.to raise_error(Alchemy::MissingImageFileError)
|
|
96
|
+
end
|
|
65
97
|
end
|
|
66
98
|
|
|
67
|
-
|
|
99
|
+
context "Requesting a picture with crop_from and crop_size parameters" do
|
|
100
|
+
let(:picture) do
|
|
101
|
+
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/500x500.png', __FILE__), 'image/png'))
|
|
102
|
+
end
|
|
68
103
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
104
|
+
it "renders the cropped picture" do
|
|
105
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, crop: 'crop', size: '123x44', crop_size: '123x44',
|
|
106
|
+
crop_from: '0x0', format: :png,
|
|
107
|
+
sh: picture.security_token(crop_size: '123x44', crop_from: '0x0', crop: true, size: '123x44')
|
|
108
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([123, 44])
|
|
73
109
|
end
|
|
74
110
|
end
|
|
75
111
|
|
|
76
|
-
context
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq([120, 120])
|
|
112
|
+
context "Requesting a picture with crop_from and crop_size parameters with different size param" do
|
|
113
|
+
let(:picture) do
|
|
114
|
+
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/500x500.png', __FILE__), 'image/png'))
|
|
80
115
|
end
|
|
81
|
-
end
|
|
82
116
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
117
|
+
it "renders the cropped picture" do
|
|
118
|
+
alchemy_get :show,
|
|
119
|
+
id: picture.id,
|
|
120
|
+
name: picture.urlname,
|
|
121
|
+
crop: 'crop',
|
|
122
|
+
size: '100x100',
|
|
123
|
+
crop_size: '200x200',
|
|
124
|
+
crop_from: '0x0',
|
|
125
|
+
format: :png,
|
|
126
|
+
sh: picture.security_token(
|
|
127
|
+
crop_size: '200x200',
|
|
128
|
+
crop_from: '0x0',
|
|
129
|
+
crop: true,
|
|
130
|
+
size: '100x100'
|
|
131
|
+
)
|
|
132
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq [100, 100]
|
|
87
133
|
end
|
|
88
134
|
end
|
|
89
135
|
|
|
90
|
-
context
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq([93, 93])
|
|
136
|
+
context "Requesting a picture with crop_from and crop_size parameters with larger size param" do
|
|
137
|
+
let(:picture) do
|
|
138
|
+
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/500x500.png', __FILE__), 'image/png'))
|
|
94
139
|
end
|
|
95
|
-
end
|
|
96
140
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
141
|
+
it "renders the cropped picture without upsampling" do
|
|
142
|
+
alchemy_get :show,
|
|
143
|
+
id: picture.id,
|
|
144
|
+
name: picture.urlname,
|
|
145
|
+
crop: 'crop',
|
|
146
|
+
size: '400x400',
|
|
147
|
+
crop_size: '200x200',
|
|
148
|
+
crop_from: '0x0',
|
|
149
|
+
format: :png,
|
|
150
|
+
sh: picture.security_token(
|
|
151
|
+
crop_size: '200x200',
|
|
152
|
+
crop_from: '0x0',
|
|
153
|
+
crop: true,
|
|
154
|
+
size: '400x400'
|
|
155
|
+
)
|
|
156
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq [200, 200]
|
|
101
157
|
end
|
|
102
158
|
end
|
|
103
|
-
end
|
|
104
159
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
160
|
+
context "Requesting a picture with crop_from and crop_size parameters with larger size param and upsample set" do
|
|
161
|
+
let(:picture) do
|
|
162
|
+
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/500x500.png', __FILE__), 'image/png'))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "renders the cropped picture with upsampling" do
|
|
166
|
+
alchemy_get :show,
|
|
167
|
+
id: picture.id,
|
|
168
|
+
name: picture.urlname,
|
|
169
|
+
crop: 'crop',
|
|
170
|
+
size: '400x400',
|
|
171
|
+
crop_size: '200x200',
|
|
172
|
+
crop_from: '0x0',
|
|
173
|
+
format: :png,
|
|
174
|
+
upsample: 'true',
|
|
175
|
+
sh: picture.security_token(
|
|
176
|
+
crop_size: '200x200',
|
|
177
|
+
crop_from: '0x0',
|
|
178
|
+
crop: true,
|
|
179
|
+
size: '400x400',
|
|
180
|
+
upsample: 'true'
|
|
181
|
+
)
|
|
182
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq [400, 400]
|
|
183
|
+
end
|
|
109
184
|
end
|
|
110
185
|
|
|
111
|
-
|
|
112
|
-
|
|
186
|
+
context "Requesting a picture that is not assigned with any page" do
|
|
187
|
+
it "should render the picture" do
|
|
113
188
|
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
114
|
-
|
|
189
|
+
expect(response.status).to eq(200)
|
|
190
|
+
end
|
|
115
191
|
end
|
|
116
|
-
end
|
|
117
192
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
193
|
+
context "Requesting a picture that is assigned on restricted and non-restricted pages" do
|
|
194
|
+
before do
|
|
195
|
+
essence = element.contents.where(name: 'image').first.essence
|
|
196
|
+
essence.picture_id = picture.id
|
|
197
|
+
essence.save
|
|
122
198
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq([123, 44])
|
|
128
|
-
end
|
|
129
|
-
end
|
|
199
|
+
essence = restricted_element.contents.where(name: 'image').first.essence
|
|
200
|
+
essence.picture_id = picture.id
|
|
201
|
+
essence.save
|
|
202
|
+
end
|
|
130
203
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
204
|
+
context "as guest user" do
|
|
205
|
+
it "should render the picture" do
|
|
206
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
207
|
+
expect(response.status).to eq(200)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
134
210
|
end
|
|
135
211
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
crop_size: '200x200',
|
|
143
|
-
crop_from: '0x0',
|
|
144
|
-
format: :png,
|
|
145
|
-
sh: picture.security_token(
|
|
146
|
-
crop_size: '200x200',
|
|
147
|
-
crop_from: '0x0',
|
|
148
|
-
crop: true,
|
|
149
|
-
size: '100x100'
|
|
150
|
-
)
|
|
151
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq [100, 100]
|
|
152
|
-
end
|
|
153
|
-
end
|
|
212
|
+
context "Requesting a picture that is assigned with restricted pages only" do
|
|
213
|
+
before do
|
|
214
|
+
essence = restricted_element.contents.where(name: 'image').first.essence
|
|
215
|
+
essence.picture_id = picture.id
|
|
216
|
+
essence.save
|
|
217
|
+
end
|
|
154
218
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
219
|
+
context "as guest user" do
|
|
220
|
+
it "should not render the picture, but redirect to login path" do
|
|
221
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
222
|
+
expect(response.status).to eq(302)
|
|
223
|
+
expect(response).to redirect_to(Alchemy.login_path)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
159
226
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
crop_size: '200x200',
|
|
171
|
-
crop_from: '0x0',
|
|
172
|
-
crop: true,
|
|
173
|
-
size: '400x400'
|
|
174
|
-
)
|
|
175
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq [200, 200]
|
|
227
|
+
context "as member user" do
|
|
228
|
+
before do
|
|
229
|
+
authorize_user(build(:alchemy_dummy_user))
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should render the picture" do
|
|
233
|
+
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
234
|
+
expect(response.status).to eq(200)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
176
237
|
end
|
|
177
238
|
end
|
|
178
239
|
|
|
179
|
-
|
|
240
|
+
describe '#thumbnail' do
|
|
180
241
|
let(:picture) do
|
|
181
242
|
create(:picture, image_file: fixture_file_upload(File.expand_path('../../fixtures/500x500.png', __FILE__), 'image/png'))
|
|
182
243
|
end
|
|
183
244
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
id: picture.id,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
size: '400x400',
|
|
190
|
-
crop_size: '200x200',
|
|
191
|
-
crop_from: '0x0',
|
|
192
|
-
format: :png,
|
|
193
|
-
upsample: 'true',
|
|
194
|
-
sh: picture.security_token(
|
|
195
|
-
crop_size: '200x200',
|
|
196
|
-
crop_from: '0x0',
|
|
197
|
-
crop: true,
|
|
198
|
-
size: '400x400',
|
|
199
|
-
upsample: 'true'
|
|
200
|
-
)
|
|
201
|
-
expect(response.body[0x10..0x18].unpack('NN')).to eq [400, 400]
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
context "Requesting a picture that is not assigned with any page" do
|
|
206
|
-
it "should render the picture" do
|
|
207
|
-
alchemy_get :show, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
208
|
-
expect(response.status).to eq(200)
|
|
245
|
+
context 'with size param set to small' do
|
|
246
|
+
it "resizes the image to 80x60 while maintaining aspect ratio" do
|
|
247
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, size: 'small', format: :png, sh: picture.security_token(size: 'small')
|
|
248
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([60, 60])
|
|
249
|
+
end
|
|
209
250
|
end
|
|
210
|
-
end
|
|
211
251
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
essence = restricted_element.contents.where(name: 'image').first.essence
|
|
219
|
-
essence.picture_id = picture.id
|
|
220
|
-
essence.save
|
|
252
|
+
context 'with size param set to medium' do
|
|
253
|
+
it "resizes the image to 160x120 while maintaining aspect ratio" do
|
|
254
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, size: 'medium', format: :png, sh: picture.security_token(size: 'medium')
|
|
255
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([120, 120])
|
|
256
|
+
end
|
|
221
257
|
end
|
|
222
258
|
|
|
223
|
-
context
|
|
224
|
-
it "
|
|
225
|
-
alchemy_get :
|
|
226
|
-
expect(response.
|
|
259
|
+
context 'with size param set to large' do
|
|
260
|
+
it "resizes the image to 240x180 while maintaining aspect ratio" do
|
|
261
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, size: 'large', format: :png, sh: picture.security_token(size: 'large')
|
|
262
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([180, 180])
|
|
227
263
|
end
|
|
228
264
|
end
|
|
229
|
-
end
|
|
230
265
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
266
|
+
context 'with size param set to nil' do
|
|
267
|
+
it "resizes the image to 111x93 while maintaining aspect ratio" do
|
|
268
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
269
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([93, 93])
|
|
270
|
+
end
|
|
236
271
|
end
|
|
237
272
|
|
|
238
|
-
context
|
|
239
|
-
it "
|
|
240
|
-
alchemy_get :
|
|
241
|
-
expect(response.
|
|
242
|
-
expect(response).to redirect_to(Alchemy.login_path)
|
|
273
|
+
context 'with size param set to another value' do
|
|
274
|
+
it "resizes the image to the given size while maintaining aspect ratio" do
|
|
275
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, size: '33x33', format: :png, sh: picture.security_token(size: '33x33')
|
|
276
|
+
expect(response.body[0x10..0x18].unpack('NN')).to eq([33, 33])
|
|
243
277
|
end
|
|
244
278
|
end
|
|
245
279
|
|
|
246
|
-
context "
|
|
280
|
+
context "Requesting a picture that is assigned with restricted pages only" do
|
|
247
281
|
before do
|
|
248
|
-
|
|
282
|
+
essence = restricted_element.contents.where(name: 'image').first.essence
|
|
283
|
+
essence.picture_id = picture.id
|
|
284
|
+
essence.save
|
|
249
285
|
end
|
|
250
286
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
287
|
+
context "as guest user" do
|
|
288
|
+
it "should not render the picture, but redirect to login path" do
|
|
289
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
290
|
+
expect(response.status).to eq(302)
|
|
291
|
+
expect(response).to redirect_to(Alchemy.login_path)
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
context "as member user" do
|
|
296
|
+
before do
|
|
297
|
+
authorize_user(build(:alchemy_dummy_user))
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it "should render the picture" do
|
|
301
|
+
alchemy_get :thumbnail, id: picture.id, name: picture.urlname, format: :png, sh: picture.security_token
|
|
302
|
+
expect(response.status).to eq(200)
|
|
303
|
+
end
|
|
254
304
|
end
|
|
255
305
|
end
|
|
256
306
|
end
|