diff --git a/.github/issue_template.md b/.github/issue_template.md index bdcd4cee9..b77901b0b 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,16 +1,13 @@ -*Note:* For general questions and feature requests please leave a message -on Gitter: https://gitter.im/comfy/comfortable-mexican-sofa - ### Expected behavior Tell us what should happen ### Actual behavior -Tell us what happens instead +Tell us what does happen ### Steps to reproduce Things that help: -* Describe issue in detail. +* Describe the issue in detail. * Add relevant code snippets. * Create a failing test case. diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml new file mode 100644 index 000000000..9dd276b64 --- /dev/null +++ b/.github/workflows/coveralls.yml @@ -0,0 +1,40 @@ +name: "Coveralls" +on: + push: + branches: + - main + pull_request: + +jobs: + coveralls: + strategy: + matrix: + ruby-version: + - "3.3" + rails-version: + - "7.1" + continue-on-error: [true] + name: ${{ format('Coverage (Ruby {0}, Rails {1})', matrix.ruby-version, matrix.rails-version) }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.continue-on-error }} + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.rails-version }}.gemfile + RAILS_ENV: test + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Install Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + + - name: Run tests, report coverage + run: | + bin/bundle install --retry 3 --quiet + bin/bundle exec rails db:drop + bin/bundle exec rails db:create + bin/bundle exec rails db:migrate + bin/bundle exec rails test:db diff --git a/.github/workflows/rubyonrails.yml b/.github/workflows/rubyonrails.yml new file mode 100644 index 000000000..a3fee4014 --- /dev/null +++ b/.github/workflows/rubyonrails.yml @@ -0,0 +1,51 @@ +name: "Rails CI" +on: + push: + branches: + - main + pull_request: + +jobs: + build_test_lint_audit: + strategy: + matrix: + ruby-version: + - "3.1" + - "3.2" + - "3.3" + rails-version: + - "6.1" + - "7.1" + - "7.2" + continue-on-error: [true] + name: ${{ format('Tests (Ruby {0}, Rails {1})', matrix.ruby-version, matrix.rails-version) }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.continue-on-error }} + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.rails-version }}.gemfile + RAILS_ENV: test + SKIP_COV: true + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Install Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + + - name: Run tests + run: | + bin/bundle install --retry 3 --quiet + bin/bundle exec rails db:drop + bin/bundle exec rails db:create + bin/bundle exec rails db:migrate + bin/bundle exec rails test:db + + - name: Lint the code + run: bin/bundle exec rubocop --parallel + + - name: Audit for security + run: | + bin/bundle exec brakeman -q -w3 + bin/bundle exec bundler-audit --update --gemfile-lock gemfiles/${{ matrix.rails-version }}.gemfile.lock diff --git a/.gitignore b/.gitignore index 2a8992be4..d58f34cd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .bundle -db/*.sqlite3 -log/*.log +db/*.sqlite3* +log/* tmp/**/* .DS_Store db/schema.rb diff --git a/.rubocop.yml b/.rubocop.yml index 5fac3b135..fc31fcc6a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,100 +1,75 @@ +require: + # - rubocop-rails + # - rubocop-minitest + AllCops: - TargetRubyVersion: 2.3 + TargetRubyVersion: 3.0 + NewCops: enable Exclude: - bin/* - db/schema.rb - db/migrate/**/* - test/fixtures/**/* - tmp/**/* + - vendor/bundle/**/* -# -- Performance --------------------------------------------------------------- -Performance/Casecmp: - Enabled: false - -# -- Metrics ------------------------------------------------------------------- -Metrics/PerceivedComplexity: - Enabled: false - -Metrics/MethodLength: - Enabled: false - -Metrics/MethodLength: - Enabled: false - -Metrics/ParameterLists: - Enabled: false - -Metrics/LineLength: - Max: 120 +# -- Layout -------------------------------------------------------------------- +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent -Metrics/CyclomaticComplexity: - Enabled: false +Layout/LineLength: + Max: 148 -Metrics/ClassLength: - Enabled: false +Layout/MultilineMethodCallIndentation: + EnforcedStyle: indented -Metrics/BlockLength: - Enabled: false +Layout/AccessModifierIndentation: + EnforcedStyle: outdent +# -- Metrics ------------------------------------------------------------------- Metrics/AbcSize: Enabled: false -# -- Layout -------------------------------------------------------------------- -Layout/MultilineOperationIndentation: - Enabled: false - -Layout/MultilineMethodCallIndentation: - EnforcedStyle: indented +Metrics/BlockLength: + Max: 45 -Layout/MultilineHashBraceLayout: +Metrics/ClassLength: Enabled: false -Layout/IndentArray: - EnforcedStyle: consistent - -Layout/EmptyLinesAroundModuleBody: - EnforcedStyle: empty_lines_except_namespace +Metrics/CyclomaticComplexity: + Max: 12 -Layout/EmptyLinesAroundExceptionHandlingKeywords: +Metrics/MethodLength: Enabled: false -Layout/EmptyLinesAroundClassBody: - EnforcedStyle: empty_lines_except_namespace +Metrics/PerceivedComplexity: + Max: 15 -Layout/AlignParameters: +# -- Naming -------------------------------------------------------------------- +Naming/MethodParameterName: Enabled: false -Layout/AccessModifierIndentation: - EnforcedStyle: outdent - # -- Style --------------------------------------------------------------------- -Style/StringLiterals: - EnforcedStyle: double_quotes - -Style/RegexpLiteral: - EnforcedStyle: percent_r - -Style/Lambda: - EnforcedStyle: literal - -Style/IfUnlessModifier: - Enabled: false - -Style/GuardClause: +Style/ClassAndModuleChildren: Enabled: false Style/Documentation: Enabled: false -Style/DateTime: +Style/DocumentDynamicEvalDefinition: Enabled: false -Style/ClassAndModuleChildren: +Style/IfUnlessModifier: Enabled: false -Style/AsciiComments: +Style/Lambda: + EnforcedStyle: literal + +Style/OptionalBooleanParameter: Enabled: false -# -- Naming -------------------------------------------------------------------- -Naming/UncommunicativeMethodParamName: +Style/SafeNavigation: Enabled: false + +Style/RegexpLiteral: + EnforcedStyle: percent_r diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8daf935ba..55f86fa6b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Contribute your code to ComfortableMexicanSofa in 5 easy steps: +Contribute your code to ComfortableMediaSurfer in 5 easy steps: ### 1. Fork it diff --git a/Gemfile b/Gemfile index 15a1f2929..9fb971d90 100644 --- a/Gemfile +++ b/Gemfile @@ -1,29 +1,38 @@ # frozen_string_literal: true -source "http://rubygems.org" +source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } gemspec +gem 'rails', '~> 7.2' + group :development, :test do - gem "autoprefixer-rails", "~> 8.1.0" - gem "byebug", "~> 10.0.0", platforms: %i[mri mingw x64_mingw] - gem "capybara", "~> 2.17.0" - gem "kaminari", "~> 1.1.1" - gem "puma", "~> 3.12.2" - gem "rubocop", "~> 0.55.0", require: false - gem "selenium-webdriver", "~> 3.9.0" - gem "sqlite3", "~> 1.4.2" + gem 'autoprefixer-rails', '~> 10.4.16.0' + gem 'byebug', '~> 11.1.0', platforms: %i[mri mingw x64_mingw] + gem 'image_processing', '>= 1.12.0' + gem 'sqlite3', '~> 1.6.7' + # gem 'mysql2', '~> 0.5' + # gem 'pg', '~> 1.5.4' end group :development do - gem "listen", "~> 3.1.5" - gem "web-console", "~> 3.5.1" + gem 'listen', '~> 3.9.0' + gem 'web-console', '~> 4.2' end group :test do - gem "coveralls", "~> 0.8.21", require: false - gem "diffy", "~> 3.2.0" - gem "equivalent-xml", "~> 0.6.0" - gem "mocha", "~> 1.3.0", require: false - gem "rails-controller-testing", "~> 1.0.2" + gem 'brakeman', '~> 6.1.2' + gem 'bundler-audit', '~> 0.9.1' + gem 'coveralls_reborn', '~> 0.28.0', require: false + gem 'cuprite', '>= 0.15' + gem 'equivalent-xml', '~> 0.6.0' + gem 'minitest', '>= 5.23.0' + gem 'minitest-reporters', '>= 1.6.1' + gem 'mocha', '>= 2.3.0', require: false + gem 'rails-controller-testing', '~> 1.0.5' + gem 'rubocop', '~> 1.63.0', require: false + gem 'rubocop-minitest' + gem 'rubocop-rails' + gem 'simplecov', '~> 0.22.0', require: false end diff --git a/LICENSE b/LICENSE index f5a6593fb..fc0acdbb4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-2019 Oleg Khabarov +Copyright (c) 2010-2019 Oleg Khabarov, (c) 2024 Shakacode LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 1ae157882..72a4712d7 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,11 @@ -# ComfortableMexicanSofa +# ComfortableMediaSurfer -ComfortableMexicanSofa is a powerful Ruby on Rails 5.2+ CMS (Content Management System) Engine - -[![Gem Version](https://img.shields.io/gem/v/comfortable_mexican_sofa.svg?style=flat)](http://rubygems.org/gems/comfortable_mexican_sofa) -[![Gem Downloads](https://img.shields.io/gem/dt/comfortable_mexican_sofa.svg?style=flat)](http://rubygems.org/gems/comfortable_mexican_sofa) -[![Build Status](https://img.shields.io/travis/comfy/comfortable-mexican-sofa.svg?branch=master&style=flat)](https://travis-ci.org/comfy/comfortable-mexican-sofa) -[![Coverage Status](https://img.shields.io/coveralls/comfy/comfortable-mexican-sofa.svg?style=flat)](https://coveralls.io/r/comfy/comfortable-mexican-sofa?branch=master) -[![Gitter](https://badges.gitter.im/comfy/comfortable-mexican-sofa.svg)](https://gitter.im/comfy/comfortable-mexican-sofa) +ComfortableMediaSurfer is a powerful Ruby 6.1+ CMS (Content Management System) Engine, picking up where [ComfortableMexicanSofa](https://github.com/comfy/comfortable-mexican-sofa) left off. ## Features -* Simple drop-in integration with Rails 5.2+ apps with minimal configuration -* CMS stays away from the rest of your application +* Simple drop-in integration with Rails 6.1+ apps with minimal configuration +* The CMS keeps clear from the rest of your application * Powerful page templating capability using [Content Tags](https://github.com/comfy/comfortable-mexican-sofa/wiki/Docs:-Content-Tags) * [Multiple Sites](https://github.com/comfy/comfortable-mexican-sofa/wiki/Docs:-Sites) from a single installation * Multi-Language Support (i18n) (ca, cs, da, de, en, es, fi, fr, gr, hr, it, ja, nb, nl, pl, pt-BR, ru, sv, tr, uk, zh-CN, zh-TW) and page localization. @@ -25,12 +19,17 @@ ComfortableMexicanSofa is a powerful Ruby on Rails 5.2+ CMS (Content Management * Image resizing is done with with [ImageMagick](http://www.imagemagick.org/script/download.php), so make sure it's installed. * Pagination is handled by [kaminari](https://github.com/amatsuda/kaminari) or [will_paginate](https://github.com/mislav/will_paginate). Please add one of those to your Gemfile. +## Compatibility + +- Ruby >= 3.0 with Rails >= 6.1 +- On Ruby 3.x, Rails 7.x + is recommended, since performance is noticably better than on 6.x + ## Installation Add gem definition to your Gemfile: ```ruby -gem "comfortable_mexican_sofa", "~> 2.0.0" +gem "comfortable_media_surfer", "~> 3.0.0" ``` Then from the Rails project's root run: @@ -50,7 +49,7 @@ comfy_route :cms, path: "/" After finishing installation you should be able to navigate to http://localhost:3000/admin -Default username and password is 'username' and 'password'. You probably want to change it right away. Admin credentials (among other things) can be found and changed in the cms initializer: [/config/initializers/comfortable\_mexican\_sofa.rb](https://github.com/comfy/comfortable-mexican-sofa/blob/master/config/initializers/comfortable_mexican_sofa.rb) +Default username and password is 'user' and 'pass'. You probably want to change it right away. Admin credentials (among other things) can be found and changed in the cms initializer: [/config/initializers/comfortable\_media\_surfer.rb](https://github.com/shakacode/comfortable-media-surfer/blob/master/config/initializers/comfortable_media_surfer.rb) Before creating pages and populating them with content we need to create a Site. Site defines a hostname, content path and its language. @@ -84,33 +83,27 @@ If you want to add a Blog functionality to your app take a look at #### Old Versions -CMS for Rails 5.1 doesn't have published gem, but you may use [rails 5.1 branch](https://github.com/comfy/comfortable-mexican-sofa/tree/rails5.1) directly. - -If you want to use CMS version 1.12 on Rails 5.2 use [1.13 branch](https://github.com/comfy/comfortable-mexican-sofa/tree/1.13) directly. - -With Rails 4.2 and 5.0 use gem version [1.12.10](https://rubygems.org/gems/comfortable_mexican_sofa/versions/1.12.10) - -With Rails 3.0 use gem version [1.8.5](https://rubygems.org/gems/comfortable_mexican_sofa/versions/1.8.5) - [CHANGELOG](//github.com/comfy/comfortable-mexican-sofa/releases) is documented in Github releases. #### Contributing -ComfortableMexicanSofa repository can be ran like a regular Rails application in +ComfortableMediaSurfer repository can be ran like a regular Rails application in development environment. It's as easy to work on as any other Rails app out there. For more detail take a look at [CONTRIBUTING](CONTRIBUTING.md) -#### Help and Contact - -Gitter: https://gitter.im/comfy/comfortable-mexican-sofa +#### Testing -Twitter: [@GroceryBagHead](https://twitter.com/grocerybaghead) +- `bin/rails db:migrate RAILS_ENV=test` +- `rake db:test:prepare` +- `rake test` #### Acknowledgements -Thanks to [Roman Almeida](https://github.com/nasmorn) for contributing OEM License for [Redactor Text Editor](http://imperavi.com/redactor) +- to [Oleg Khabarov](https://github.com/GBH), the creator of [ComfortableMexicanSofa](https://github.com/comfy/comfortable-mexican-sofa) +- to [Roman Almeida](https://github.com/nasmorn) for contributing OEM License for [Redactor Text Editor](http://imperavi.com/redactor) --- -Copyright 2010-2019 Oleg Khabarov. Released under the [MIT license](LICENSE) +Copyright 2010-2019 Oleg Khabarov, 2024 ShakaCode LLC +Released under the [MIT license](LICENSE) diff --git a/Rakefile b/Rakefile index c4f952387..6d1041e3b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_relative "config/application" +require_relative 'config/application' Rails.application.load_tasks diff --git a/app/assets/javascripts/comfy/admin/cms/wysiwyg.js b/app/assets/javascripts/comfy/admin/cms/wysiwyg.js index 9990a6a4c..3a03d3d33 100644 --- a/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +++ b/app/assets/javascripts/comfy/admin/cms/wysiwyg.js @@ -39,7 +39,14 @@ imageManagerJson, fileUpload, fileManagerJson, - definedLinks + definedLinks, + // allow unsafe tags and the like (prevent redactor stripping divs and other elements) + cleanOnEnter: false, + replaceTags: false, + removeComments: false, + removeNewLines: false, + deniedTags: [], + replaceDivs: false }; }; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f3b172127..9c4e35bac 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true class ApplicationController < ActionController::Base - protect_from_forgery - end diff --git a/app/controllers/comfy/admin/base_controller.rb b/app/controllers/comfy/admin/base_controller.rb index 6a1488d62..8f5b04b00 100644 --- a/app/controllers/comfy/admin/base_controller.rb +++ b/app/controllers/comfy/admin/base_controller.rb @@ -1,14 +1,13 @@ # frozen_string_literal: true -class Comfy::Admin::BaseController < ComfortableMexicanSofa.config.admin_base_controller.to_s.constantize - +class Comfy::Admin::BaseController < ComfortableMediaSurfer.config.admin_base_controller.to_s.constantize include Comfy::Paginate # Authentication module must have `authenticate` method - include ComfortableMexicanSofa.config.admin_auth.to_s.constantize + include ComfortableMediaSurfer.config.admin_auth.to_s.constantize # Authorization module must have `authorize` method - include ComfortableMexicanSofa.config.admin_authorization.to_s.constantize + include ComfortableMediaSurfer.config.admin_authorization.to_s.constantize helper Comfy::Admin::CmsHelper helper Comfy::CmsHelper @@ -17,6 +16,5 @@ class Comfy::Admin::BaseController < ComfortableMexicanSofa.config.admin_base_co before_action :authenticate - layout "comfy/admin/cms" - + layout 'comfy/admin/cms' end diff --git a/app/controllers/comfy/admin/cms/base_controller.rb b/app/controllers/comfy/admin/cms/base_controller.rb index 50f837863..9788d7f99 100644 --- a/app/controllers/comfy/admin/cms/base_controller.rb +++ b/app/controllers/comfy/admin/cms/base_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::BaseController < Comfy::Admin::BaseController - before_action :load_admin_site, :set_locale, :load_seeds, @@ -9,13 +8,14 @@ class Comfy::Admin::Cms::BaseController < Comfy::Admin::BaseController layout :infer_layout - if ComfortableMexicanSofa.config.admin_cache_sweeper.present? - cache_sweeper(*ComfortableMexicanSofa.config.admin_cache_sweeper) + if ComfortableMediaSurfer.config.admin_cache_sweeper.present? + cache_sweeper(*ComfortableMediaSurfer.config.admin_cache_sweeper) end def jump - path = ComfortableMexicanSofa.config.admin_route_redirect + path = ComfortableMediaSurfer.config.admin_route_redirect return redirect_to(path) unless path.blank? + load_admin_site redirect_to comfy_admin_cms_site_pages_path(@site) if @site end @@ -27,29 +27,28 @@ def load_admin_site if (@site = ::Comfy::Cms::Site.find_by(id: id_param) || ::Comfy::Cms::Site.first) session[:site_id] = @site.id else - I18n.locale = ComfortableMexicanSofa.config.admin_locale || I18n.default_locale - flash[:danger] = I18n.t("comfy.admin.cms.base.site_not_found") - return redirect_to(new_comfy_admin_cms_site_path) + I18n.locale = ComfortableMediaSurfer.config.admin_locale || I18n.default_locale + flash[:danger] = I18n.t('comfy.admin.cms.base.site_not_found') + redirect_to(new_comfy_admin_cms_site_path) end end def set_locale - I18n.locale = ComfortableMexicanSofa.config.admin_locale || (@site&.locale) + I18n.locale = ComfortableMediaSurfer.config.admin_locale || @site&.locale true end def load_seeds - return unless ComfortableMexicanSofa.config.enable_seeds + return unless ComfortableMediaSurfer.config.enable_seeds - controllers = %w[layouts pages snippets files].collect { |c| "comfy/admin/cms/" + c } - if controllers.member?(params[:controller]) && params[:action] == "index" - ComfortableMexicanSofa::Seeds::Importer.new(@site.identifier).import! - flash.now[:warning] = I18n.t("comfy.admin.cms.base.seeds_enabled") - end + controllers = %w[layouts pages snippets files].collect { |c| "comfy/admin/cms/#{c}" } + return unless controllers.member?(params[:controller]) && params[:action] == 'index' + + ComfortableMediaSurfer::Seeds::Importer.new(@site.identifier).import! + flash.now[:warning] = I18n.t('comfy.admin.cms.base.seeds_enabled') end def infer_layout - false if params[:layout] == "false" + false if params[:layout] == 'false' end - end diff --git a/app/controllers/comfy/admin/cms/categories_controller.rb b/app/controllers/comfy/admin/cms/categories_controller.rb index 6c8227a4e..bbc3b40da 100644 --- a/app/controllers/comfy/admin/cms/categories_controller.rb +++ b/app/controllers/comfy/admin/cms/categories_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::CategoriesController < Comfy::Admin::Cms::BaseController - before_action :load_category, only: %i[edit update destroy] before_action :authorize @@ -36,5 +35,4 @@ def load_category def category_params params.fetch(:category, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/files_controller.rb b/app/controllers/comfy/admin/cms/files_controller.rb index 0bac6841e..63a717a52 100644 --- a/app/controllers/comfy/admin/cms/files_controller.rb +++ b/app/controllers/comfy/admin/cms/files_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::FilesController < Comfy::Admin::Cms::BaseController - include ::Comfy::ReorderAction self.reorder_action_resource = ::Comfy::Cms::File @@ -17,11 +16,11 @@ def index case params[:source] # Integration with Redactor 1.0 Wysiwyg - when "redactor" + when 'redactor' file_scope = files_scope.limit(100).order(:position) file_hashes = case params[:type] - when "image" + when 'image' file_scope.with_images.collect do |file| { thumb: url_for(file.attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:redactor])), image: url_for(file.attachment), @@ -29,10 +28,10 @@ def index end else file_scope.collect do |file| - { title: file.label, - name: file.attachment.filename, - link: url_for(file.attachment), - size: number_to_human_size(file.attachment.byte_size) } + { title: file.label, + name: file.attachment.filename, + link: url_for(file.attachment), + size: number_to_human_size(file.attachment.byte_size) } end end @@ -42,7 +41,7 @@ def index files_scope = files_scope .includes(:categories) .for_category(params[:categories]) - .order("comfy_cms_files.position") + .order('comfy_cms_files.position') @files = comfy_paginate(files_scope, per_page: 50) end end @@ -52,7 +51,7 @@ def new end def create - categories_scope = @site.categories.of_type("Comfy::Cms::File") + categories_scope = @site.categories.of_type('Comfy::Cms::File') if params[:categories] ids = categories_scope.where(label: params[:categories]).pluck(:id) @@ -60,34 +59,33 @@ def create end # Automatically tagging upload if it's done through redactor - if params[:source] == "redactor" - category = categories_scope.find_or_create_by(label: "wysiwyg") + if params[:source] == 'redactor' + category = categories_scope.find_or_create_by(label: 'wysiwyg') @file.category_ids = [category.id] end @file.save! case params[:source] - when "plupload" - render partial: "file", object: @file - when "redactor" + when 'plupload' + render partial: 'file', object: @file + when 'redactor' render json: { filelink: url_for(@file.attachment), filename: @file.attachment.filename } else - flash[:success] = I18n.t("comfy.admin.cms.files.created") + flash[:success] = I18n.t('comfy.admin.cms.files.created') redirect_to action: :edit, id: @file end - rescue ActiveRecord::RecordInvalid case params[:source] - when "plupload" + when 'plupload' render body: @file.errors.full_messages.to_sentence, status: :unprocessable_entity - when "redactor" + when 'redactor' render body: nil, status: :unprocessable_entity else - flash.now[:danger] = I18n.t("comfy.admin.cms.files.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.files.creation_failure') render action: :new end end @@ -98,10 +96,10 @@ def edit def update if @file.update(file_params) - flash[:success] = I18n.t("comfy.admin.cms.files.updated") + flash[:success] = I18n.t('comfy.admin.cms.files.updated') redirect_to action: :edit, id: @file else - flash.now[:danger] = I18n.t("comfy.admin.cms.files.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.files.update_failure') render action: :edit end end @@ -111,7 +109,7 @@ def destroy respond_to do |format| format.js format.html do - flash[:success] = I18n.t("comfy.admin.cms.files.deleted") + flash[:success] = I18n.t('comfy.admin.cms.files.deleted') redirect_to action: :index end end @@ -126,7 +124,7 @@ def build_file def load_file @file = @site.files.find(params[:id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.files.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.files.not_found') redirect_to action: :index end @@ -138,5 +136,4 @@ def file_params end params.fetch(:file, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/layouts_controller.rb b/app/controllers/comfy/admin/cms/layouts_controller.rb index 94ae72e9b..3d9fd21c8 100644 --- a/app/controllers/comfy/admin/cms/layouts_controller.rb +++ b/app/controllers/comfy/admin/cms/layouts_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::LayoutsController < Comfy::Admin::Cms::BaseController - include ::Comfy::ReorderAction self.reorder_action_resource = ::Comfy::Cms::Layout @@ -11,6 +10,7 @@ class Comfy::Admin::Cms::LayoutsController < Comfy::Admin::Cms::BaseController def index return redirect_to action: :new if @site.layouts.count.zero? + @layouts = @site.layouts.roots.order(:position) end @@ -24,25 +24,25 @@ def edit def create @layout.save! - flash[:success] = I18n.t("comfy.admin.cms.layouts.created") + flash[:success] = I18n.t('comfy.admin.cms.layouts.created') redirect_to action: :edit, id: @layout rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.layouts.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.layouts.creation_failure') render action: :new end def update @layout.update!(layout_params) - flash[:success] = I18n.t("comfy.admin.cms.layouts.updated") + flash[:success] = I18n.t('comfy.admin.cms.layouts.updated') redirect_to action: :edit, id: @layout rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.layouts.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.layouts.update_failure') render action: :edit end def destroy @layout.destroy - flash[:success] = I18n.t("comfy.admin.cms.layouts.deleted") + flash[:success] = I18n.t('comfy.admin.cms.layouts.deleted') redirect_to action: :index end @@ -52,18 +52,17 @@ def build_layout @layout = @site.layouts.new(layout_params) @layout.parent ||= ::Comfy::Cms::Layout.find_by_id(params[:parent_id]) @layout.app_layout ||= @layout.parent.try(:app_layout) - @layout.content ||= "{{ cms:wysiwyg content }}" + @layout.content ||= '{{ cms:wysiwyg content }}' end def load_layout @layout = @site.layouts.find(params[:id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.layouts.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.layouts.not_found') redirect_to action: :index end def layout_params params.fetch(:layout, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/pages_controller.rb b/app/controllers/comfy/admin/cms/pages_controller.rb index f358117aa..d0db5cc8f 100644 --- a/app/controllers/comfy/admin/cms/pages_controller.rb +++ b/app/controllers/comfy/admin/cms/pages_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::PagesController < Comfy::Admin::Cms::BaseController - include ::Comfy::ReorderAction self.reorder_action_resource = ::Comfy::Cms::Page @@ -16,7 +15,7 @@ class Comfy::Admin::Cms::PagesController < Comfy::Admin::Cms::BaseController def index return redirect_to action: :new if site_has_no_pages? - return index_for_redactor if params[:source] == "redactor" + return index_for_redactor if params[:source] == 'redactor' @pages_by_parent = pages_grouped_by_parent @@ -36,27 +35,35 @@ def edit render end + def update_family + @page.siblings.each(&:save!) if @page.siblings + @page.parent.save! if @page.parent + end + def create @page.save! - flash[:success] = I18n.t("comfy.admin.cms.pages.created") + update_family + flash[:success] = I18n.t('comfy.admin.cms.pages.created') redirect_to action: :edit, id: @page rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.pages.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.pages.creation_failure') render action: :new end def update @page.save! - flash[:success] = I18n.t("comfy.admin.cms.pages.updated") + update_family + flash[:success] = I18n.t('comfy.admin.cms.pages.updated') redirect_to action: :edit, id: @page rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.pages.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.pages.update_failure') render action: :edit end def destroy @page.destroy - flash[:success] = I18n.t("comfy.admin.cms.pages.deleted") + update_family + flash[:success] = I18n.t('comfy.admin.cms.pages.deleted') redirect_to action: :index end @@ -65,9 +72,9 @@ def form_fragments @page.layout = @site.layouts.find_by(id: params[:layout_id]) render( - partial: "comfy/admin/cms/fragments/form_fragments", - locals: { record: @page, scope: :page }, - layout: false + partial: 'comfy/admin/cms/fragments/form_fragments', + locals: { record: @page, scope: :page }, + layout: false ) end @@ -86,6 +93,7 @@ def toggle_branch def index_for_redactor tree_walker = ->(page, list, offset) do return unless page.present? + label = "#{'. . ' * offset}#{page.label}" list << { name: label, url: page.url(relative: true) } page.children.each do |child_page| @@ -95,7 +103,7 @@ def index_for_redactor end page_select_options = [{ - name: I18n.t("comfy.admin.cms.pages.form.choose_link"), + name: I18n.t('comfy.admin.cms.pages.form.choose_link'), url: false }] + tree_walker.call(@site.pages.root, [], 0) @@ -111,46 +119,45 @@ def pages_grouped_by_parent end def check_for_layouts - if @site.layouts.count.zero? - flash[:danger] = I18n.t("comfy.admin.cms.pages.layout_not_found") - redirect_to new_comfy_admin_cms_site_layout_path(@site) - end + return unless @site.layouts.count.zero? + + flash[:danger] = I18n.t('comfy.admin.cms.pages.layout_not_found') + redirect_to new_comfy_admin_cms_site_layout_path(@site) end def build_page @page = @site.pages.new(page_params) - @page.parent ||= (@site.pages.find_by_id(params[:parent_id]) || @site.pages.root) - @page.layout ||= (@page.parent&.layout || @site.layouts.first) + @page.parent ||= @site.pages.find_by_id(params[:parent_id]) || @site.pages.root + @page.layout ||= @page.parent&.layout || @site.layouts.first end def load_page @page = @site.pages.find(params[:id]) @page.attributes = page_params rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.pages.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.pages.not_found') redirect_to action: :index end def preview_page - if params[:preview] - layout = @page.layout.app_layout.blank? ? false : @page.layout.app_layout - @cms_site = @page.site - @cms_layout = @page.layout - @cms_page = @page + return unless params[:preview] - # Make sure to use the site locale to render the preview becaue it might - # be different from the admin locale. - I18n.locale = @cms_site.locale + layout = @page.layout.app_layout.blank? ? false : @page.layout.app_layout + @cms_site = @page.site + @cms_layout = @page.layout + @cms_page = @page - # Chrome chokes on content with iframes. Issue #434 - response.headers["X-XSS-Protection"] = "0" + # Make sure to use the site locale to render the preview becaue it might + # be different from the admin locale. + I18n.locale = @cms_site.locale - render inline: @page.render, layout: layout, content_type: "text/html" - end + # Chrome chokes on content with iframes. Issue #434 + response.headers['X-XSS-Protection'] = '0' + + render inline: @page.render, layout: layout, content_type: 'text/html' end def page_params params.fetch(:page, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/revisions/base_controller.rb b/app/controllers/comfy/admin/cms/revisions/base_controller.rb index c168c9192..17483e8d9 100644 --- a/app/controllers/comfy/admin/cms/revisions/base_controller.rb +++ b/app/controllers/comfy/admin/cms/revisions/base_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::Revisions::BaseController < Comfy::Admin::Cms::BaseController - helper_method :record_path before_action :load_record @@ -21,30 +20,29 @@ def show @current_content = @record.revision_fields.each_with_object({}) { |f, c| c[f] = @record.send(f) } @versioned_content = @record.revision_fields.each_with_object({}) { |f, c| c[f] = @revision.data[f] } - render "comfy/admin/cms/revisions/show" + render 'comfy/admin/cms/revisions/show' end def revert @record.restore_from_revision(@revision) - flash[:success] = I18n.t("comfy.admin.cms.revisions.reverted") + flash[:success] = I18n.t('comfy.admin.cms.revisions.reverted') redirect_to record_path end protected def load_record - raise "not implemented" + raise 'not implemented' end def load_revision @revision = @record.revisions.find(params[:id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.revisions.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.revisions.not_found') redirect_to record_path end def record_path - raise "no implemented" + raise 'not implemented' end - end diff --git a/app/controllers/comfy/admin/cms/revisions/layout_controller.rb b/app/controllers/comfy/admin/cms/revisions/layout_controller.rb index cb9ded0a9..73cb7f23b 100644 --- a/app/controllers/comfy/admin/cms/revisions/layout_controller.rb +++ b/app/controllers/comfy/admin/cms/revisions/layout_controller.rb @@ -1,18 +1,16 @@ # frozen_string_literal: true class Comfy::Admin::Cms::Revisions::LayoutController < Comfy::Admin::Cms::Revisions::BaseController - private def load_record @record = @site.layouts.find(params[:layout_id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.revisions.record_not_found") + flash[:danger] = I18n.t('comfy.admin.cms.revisions.record_not_found') redirect_to comfy_admin_cms_site_layouts_path(@site) end def record_path edit_comfy_admin_cms_site_layout_path(@site, @record) end - end diff --git a/app/controllers/comfy/admin/cms/revisions/page_controller.rb b/app/controllers/comfy/admin/cms/revisions/page_controller.rb index e02c8fa5b..4f364e386 100644 --- a/app/controllers/comfy/admin/cms/revisions/page_controller.rb +++ b/app/controllers/comfy/admin/cms/revisions/page_controller.rb @@ -1,17 +1,16 @@ # frozen_string_literal: true class Comfy::Admin::Cms::Revisions::PageController < Comfy::Admin::Cms::Revisions::BaseController - def show @current_content = @record.fragments.each_with_object({}) do |b, c| c[b.identifier] = b.content end @versioned_content = @record.fragments.each_with_object({}) do |b, c| - d = @revision.data["fragments_attributes"].detect { |r| r[:identifier] == b.identifier } + d = @revision.data['fragments_attributes'].detect { |r| r[:identifier] == b.identifier } c[b.identifier] = d.try(:[], :content) end - render "comfy/admin/cms/revisions/show" + render 'comfy/admin/cms/revisions/show' end private @@ -19,12 +18,11 @@ def show def load_record @record = @site.pages.find(params[:page_id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.revisions.record_not_found") + flash[:danger] = I18n.t('comfy.admin.cms.revisions.record_not_found') redirect_to comfy_admin_cms_site_pages_path(@site) end def record_path edit_comfy_admin_cms_site_page_path(@site, @record) end - end diff --git a/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb b/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb index f4a53fcd1..5eafacbd9 100644 --- a/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb +++ b/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb @@ -1,18 +1,16 @@ # frozen_string_literal: true class Comfy::Admin::Cms::Revisions::SnippetController < Comfy::Admin::Cms::Revisions::BaseController - private def load_record @record = @site.snippets.find(params[:snippet_id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.revisions.record_not_found") + flash[:danger] = I18n.t('comfy.admin.cms.revisions.record_not_found') redirect_to comfy_admin_cms_site_snippets_path(@site) end def record_path edit_comfy_admin_cms_site_snippet_path(@site, @record) end - end diff --git a/app/controllers/comfy/admin/cms/revisions/translation_controller.rb b/app/controllers/comfy/admin/cms/revisions/translation_controller.rb index f15182739..9b4f56bd4 100644 --- a/app/controllers/comfy/admin/cms/revisions/translation_controller.rb +++ b/app/controllers/comfy/admin/cms/revisions/translation_controller.rb @@ -1,17 +1,16 @@ # frozen_string_literal: true class Comfy::Admin::Cms::Revisions::TranslationController < Comfy::Admin::Cms::Revisions::BaseController - def show @current_content = @record.fragments.each_with_object({}) do |b, c| c[b.identifier] = b.content end @versioned_content = @record.fragments.each_with_object({}) do |b, c| - d = @revision.data["fragments_attributes"].detect { |r| r[:identifier] == b.identifier } + d = @revision.data['fragments_attributes'].detect { |r| r[:identifier] == b.identifier } c[b.identifier] = d.try(:[], :content) end - render "comfy/admin/cms/revisions/show" + render 'comfy/admin/cms/revisions/show' end private @@ -20,12 +19,11 @@ def load_record @page = @site.pages.find(params[:page_id]) @record = @page.translations.find(params[:translation_id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.revisions.record_not_found") + flash[:danger] = I18n.t('comfy.admin.cms.revisions.record_not_found') redirect_to comfy_admin_cms_site_pages_path(@site) end def record_path edit_comfy_admin_cms_site_page_translation_path(@site, @page, @record) end - end diff --git a/app/controllers/comfy/admin/cms/sites_controller.rb b/app/controllers/comfy/admin/cms/sites_controller.rb index be14eb629..5710f2ad0 100644 --- a/app/controllers/comfy/admin/cms/sites_controller.rb +++ b/app/controllers/comfy/admin/cms/sites_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::SitesController < Comfy::Admin::Cms::BaseController - skip_before_action :load_admin_site, :load_seeds @@ -11,6 +10,7 @@ class Comfy::Admin::Cms::SitesController < Comfy::Admin::Cms::BaseController def index return redirect_to action: :new if ::Comfy::Cms::Site.count.zero? + @site = ::Comfy::Cms::Site.find_by_id(session[:site_id]) @sites = ::Comfy::Cms::Site.all end @@ -25,25 +25,25 @@ def edit def create @site.save! - flash[:success] = I18n.t("comfy.admin.cms.sites.created") + flash[:success] = I18n.t('comfy.admin.cms.sites.created') redirect_to comfy_admin_cms_site_layouts_path(@site) rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.sites.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.sites.creation_failure') render action: :new end def update @site.update!(site_params) - flash[:success] = I18n.t("comfy.admin.cms.sites.updated") + flash[:success] = I18n.t('comfy.admin.cms.sites.updated') redirect_to action: :edit, id: @site rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.sites.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.sites.update_failure') render action: :edit end def destroy @site.destroy - flash[:success] = I18n.t("comfy.admin.cms.sites.deleted") + flash[:success] = I18n.t('comfy.admin.cms.sites.deleted') redirect_to action: :index end @@ -56,14 +56,13 @@ def build_site def load_site @site = ::Comfy::Cms::Site.find(params[:id]) - I18n.locale = ComfortableMexicanSofa.config.admin_locale || @site.locale + I18n.locale = ComfortableMediaSurfer.config.admin_locale || @site.locale rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.sites.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.sites.not_found') redirect_to action: :index end def site_params params.fetch(:site, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/snippets_controller.rb b/app/controllers/comfy/admin/cms/snippets_controller.rb index 8899f9b85..2ab228407 100644 --- a/app/controllers/comfy/admin/cms/snippets_controller.rb +++ b/app/controllers/comfy/admin/cms/snippets_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::SnippetsController < Comfy::Admin::Cms::BaseController - include ::Comfy::ReorderAction self.reorder_action_resource = ::Comfy::Cms::Snippet @@ -11,6 +10,7 @@ class Comfy::Admin::Cms::SnippetsController < Comfy::Admin::Cms::BaseController def index return redirect_to action: :new if @site.snippets.count.zero? + @snippets = @site.snippets.includes(:categories).for_category(params[:categories]).order(:position) end @@ -24,25 +24,25 @@ def edit def create @snippet.save! - flash[:success] = I18n.t("comfy.admin.cms.snippets.created") + flash[:success] = I18n.t('comfy.admin.cms.snippets.created') redirect_to action: :edit, id: @snippet rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.snippets.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.snippets.creation_failure') render action: :new end def update @snippet.update!(snippet_params) - flash[:success] = I18n.t("comfy.admin.cms.snippets.updated") + flash[:success] = I18n.t('comfy.admin.cms.snippets.updated') redirect_to action: :edit, id: @snippet rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.snippets.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.snippets.update_failure') render action: :edit end def destroy @snippet.destroy - flash[:success] = I18n.t("comfy.admin.cms.snippets.deleted") + flash[:success] = I18n.t('comfy.admin.cms.snippets.deleted') redirect_to action: :index end @@ -55,12 +55,11 @@ def build_snippet def load_snippet @snippet = @site.snippets.find(params[:id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.snippets.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.snippets.not_found') redirect_to action: :index end def snippet_params params.fetch(:snippet, {}).permit! end - end diff --git a/app/controllers/comfy/admin/cms/translations_controller.rb b/app/controllers/comfy/admin/cms/translations_controller.rb index 4af036ab2..f5b3d023b 100644 --- a/app/controllers/comfy/admin/cms/translations_controller.rb +++ b/app/controllers/comfy/admin/cms/translations_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Admin::Cms::TranslationsController < Comfy::Admin::Cms::BaseController - helper_method :translation_select_options before_action :load_page @@ -20,25 +19,25 @@ def edit def create @translation.save! - flash[:success] = I18n.t("comfy.admin.cms.translations.created") + flash[:success] = I18n.t('comfy.admin.cms.translations.created') redirect_to action: :edit, id: @translation rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.translations.creation_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.translations.creation_failure') render action: :new end def update @translation.update!(translation_params) - flash[:success] = I18n.t("comfy.admin.cms.translations.updated") + flash[:success] = I18n.t('comfy.admin.cms.translations.updated') redirect_to action: :edit, id: @translation rescue ActiveRecord::RecordInvalid - flash.now[:danger] = I18n.t("comfy.admin.cms.translations.update_failure") + flash.now[:danger] = I18n.t('comfy.admin.cms.translations.update_failure') render action: :edit end def destroy @translation.destroy - flash[:success] = I18n.t("comfy.admin.cms.translations.deleted") + flash[:success] = I18n.t('comfy.admin.cms.translations.deleted') redirect_to edit_comfy_admin_cms_site_page_path(@site, @page) end @@ -47,16 +46,16 @@ def form_fragments @translation.layout = @site.layouts.find_by(id: params[:layout_id]) render( - partial: "comfy/admin/cms/fragments/form_fragments", - locals: { record: @translation, scope: :translation }, - layout: false + partial: 'comfy/admin/cms/fragments/form_fragments', + locals: { record: @translation, scope: :translation }, + layout: false ) end private def translation_select_options - all = ComfortableMexicanSofa.config.locales + all = ComfortableMediaSurfer.config.locales taken = @page.translations.pluck(:locale) + [@site.locale] - [@translation.locale] all.except(*taken).map { |k, v| ["#{v} (#{k})", k] } end @@ -64,7 +63,7 @@ def translation_select_options def load_page @page = @site.pages.find(params[:page_id]) rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.pages.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.pages.not_found') redirect_to comfy_admin_cms_site_pages_path(@site) end @@ -77,7 +76,7 @@ def load_translation @translation = @page.translations.find(params[:id]) @translation.attributes = translation_params rescue ActiveRecord::RecordNotFound - flash[:danger] = I18n.t("comfy.admin.cms.translations.not_found") + flash[:danger] = I18n.t('comfy.admin.cms.translations.not_found') redirect_to edit_comfy_admin_cms_site_page_path(@site, @page) end @@ -86,22 +85,21 @@ def translation_params end def preview_translation - if params[:preview] - layout = @translation.layout.app_layout.blank? ? false : @translation.layout.app_layout - @cms_site = @page.site - @cms_layout = @translation.layout - @cms_page = @page - - # Make sure to use the site locale to render the preview becaue it might - # be different from the admin locale. - I18n.locale = @translation.locale - - # Chrome chokes on content with iframes. Issue #434 - response.headers["X-XSS-Protection"] = "0" - - # raise - render inline: @translation.render, layout: layout, content_type: "text/html" - end - end + return unless params[:preview] + + layout = @translation.layout.app_layout.blank? ? false : @translation.layout.app_layout + @cms_site = @page.site + @cms_layout = @translation.layout + @cms_page = @page + # Make sure to use the site locale to render the preview becaue it might + # be different from the admin locale. + I18n.locale = @translation.locale + + # Chrome chokes on content with iframes. Issue #434 + response.headers['X-XSS-Protection'] = '0' + + # raise + render inline: @translation.render, layout: layout, content_type: 'text/html' + end end diff --git a/app/controllers/comfy/cms/assets_controller.rb b/app/controllers/comfy/cms/assets_controller.rb index d2647d0c4..9194c154a 100644 --- a/app/controllers/comfy/cms/assets_controller.rb +++ b/app/controllers/comfy/cms/assets_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Comfy::Cms::AssetsController < Comfy::Cms::BaseController - skip_before_action :verify_authenticity_token, raise: false before_action :load_cms_layout, @@ -10,11 +9,11 @@ class Comfy::Cms::AssetsController < Comfy::Cms::BaseController after_action :set_cache_control_header def render_css - render body: @cms_layout.css, content_type: "text/css" + render body: @cms_layout.css, content_type: 'text/css' end def render_js - render body: @cms_layout.js, content_type: "application/javascript" + render body: @cms_layout.js, content_type: 'application/javascript' end protected @@ -32,9 +31,8 @@ def use_null_session end def set_cache_control_header - if params[:cache_buster].present? - response.headers["Cache-Control"] = "public, max-age=#{1.year.to_i}" - end - end + return unless params[:cache_buster].present? + response.headers['Cache-Control'] = "public, max-age=#{1.year.to_i}" + end end diff --git a/app/controllers/comfy/cms/base_controller.rb b/app/controllers/comfy/cms/base_controller.rb index 8671acbf7..b8546d545 100644 --- a/app/controllers/comfy/cms/base_controller.rb +++ b/app/controllers/comfy/cms/base_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -class Comfy::Cms::BaseController < ComfortableMexicanSofa.config.public_base_controller.to_s.constantize - +class Comfy::Cms::BaseController < ComfortableMediaSurfer.config.public_base_controller.to_s.constantize before_action :load_cms_site helper Comfy::CmsHelper @@ -16,18 +15,12 @@ def load_cms_site ::Comfy::Cms::Site.find_site(request.host_with_port.downcase, request.fullpath) end - if @cms_site - if @cms_site.path.present? && !params[:site_id] - if params[:cms_path]&.match(%r{\A#{@cms_site.path}}) - params[:cms_path].gsub!(%r{\A#{@cms_site.path}}, "") - params[:cms_path]&.gsub!(%r{\A/}, "") - else - raise ActionController::RoutingError, "Site Not Found" - end - end - else - raise ActionController::RoutingError, "Site Not Found" - end - end + raise ActionController::RoutingError, 'Site Not Found' unless @cms_site + return unless @cms_site.path.present? && !params[:site_id] + raise ActionController::RoutingError, 'Site Not Found' unless params[:cms_path]&.match(%r{\A#{@cms_site.path}}) + + params[:cms_path].gsub!(%r{\A#{@cms_site.path}}, '') + params[:cms_path]&.gsub!(%r{\A/}, '') + end end diff --git a/app/controllers/comfy/cms/content_controller.rb b/app/controllers/comfy/cms/content_controller.rb index 0126d505e..890ca7c3e 100644 --- a/app/controllers/comfy/cms/content_controller.rb +++ b/app/controllers/comfy/cms/content_controller.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true class Comfy::Cms::ContentController < Comfy::Cms::BaseController - # Authentication module must have `authenticate` method - include ComfortableMexicanSofa.config.public_auth.to_s.constantize + include ComfortableMediaSurfer.config.public_auth.to_s.constantize # Authorization module must have `authorize` method - include ComfortableMexicanSofa.config.public_authorization.to_s.constantize + include ComfortableMediaSurfer.config.public_authorization.to_s.constantize before_action :load_seeds before_action :load_cms_page, @@ -25,7 +24,7 @@ def show inline: @cms_page.content_cache, layout: false ) - json_page = @cms_page.as_json(ComfortableMexicanSofa.config.page_to_json_options) + json_page = @cms_page.as_json(ComfortableMediaSurfer.config.page_to_json_options) render json: json_page end end @@ -35,53 +34,57 @@ def show protected def render_page(status = :ok) - render inline: @cms_page.content_cache, - layout: app_layout, - status: status, + render inline: @cms_page.content_cache, + layout: app_layout, + status: status, content_type: mime_type end # it's possible to control mimetype of a page by creating a `mime_type` field def mime_type - mime_block = @cms_page.fragments.detect { |f| f.identifier == "mime_type" } - mime_block&.content&.strip || "text/html" + mime_block = @cms_page.fragments.detect { |f| f.identifier == 'mime_type' } + mime_block&.content&.strip || 'text/html' end def app_layout return false if request.xhr? || !@cms_layout + @cms_layout.app_layout.present? ? @cms_layout.app_layout : false end def load_seeds - return unless ComfortableMexicanSofa.config.enable_seeds - ComfortableMexicanSofa::Seeds::Importer.new(@cms_site.identifier).import! + return unless ComfortableMediaSurfer.config.enable_seeds + + ComfortableMediaSurfer::Seeds::Importer.new(@cms_site.identifier).import! end # Attempting to populate @cms_page and @cms_layout instance variables so they # can be used in view helpers/partials def load_cms_page - unless find_cms_page_by_full_path("/#{params[:cms_path]}") - if find_cms_page_by_full_path("/404") - render_page(:not_found) - else - message = "Page Not Found at: \"#{params[:cms_path]}\"" - raise ActionController::RoutingError, message - end + return if find_cms_page_by_full_path("/#{params[:cms_path]}") + + if find_cms_page_by_full_path('/404') + render_page(:not_found) + else + message = "Page Not Found at: \"#{params[:cms_path]}\"" + raise ActionController::RoutingError, message end end # Getting page and setting content_cache and fragments data if we need to # serve translation data def find_cms_page_by_full_path(full_path) - @cms_page = @cms_site.pages.published.find_by!(full_path: full_path) + @cms_page = if Rails.env == 'development' + @cms_site.pages.find_by!(full_path: full_path) + else + @cms_site.pages.published.find_by!(full_path: full_path) + end @cms_page.translate! @cms_layout = @cms_page.layout @cms_page - rescue ActiveRecord::RecordNotFound nil end - end diff --git a/app/controllers/concerns/comfy/paginate.rb b/app/controllers/concerns/comfy/paginate.rb index 09ba24156..198ba06aa 100644 --- a/app/controllers/concerns/comfy/paginate.rb +++ b/app/controllers/concerns/comfy/paginate.rb @@ -1,16 +1,11 @@ # frozen_string_literal: true module Comfy::Paginate - - # Wrapper to deal with WillPaginate vs Kaminari nonsense def comfy_paginate(scope, per_page: 50) - if defined?(WillPaginate) - scope.paginate(page: params[:page], per_page: per_page) - elsif defined?(Kaminari) + if defined?(Kaminari) scope.page(params[:page]).per(per_page) else scope end end - end diff --git a/app/controllers/concerns/comfy/reorder_action.rb b/app/controllers/concerns/comfy/reorder_action.rb index fb7c20e39..8be841a66 100644 --- a/app/controllers/concerns/comfy/reorder_action.rb +++ b/app/controllers/concerns/comfy/reorder_action.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Comfy::ReorderAction - extend ActiveSupport::Concern included do @@ -13,7 +12,9 @@ def reorder (params.permit(order: [])[:order] || []).each_with_index do |id, index| resource_class.where(id: id).update_all(position: index) end + if resource_class == ::Comfy::Cms::Page + Comfy::Cms::Page.all.each(&:save!) + end head :ok end - end diff --git a/app/helpers/comfy/admin/cms_helper.rb b/app/helpers/comfy/admin/cms_helper.rb index 61d526830..d0225ccfd 100644 --- a/app/helpers/comfy/admin/cms_helper.rb +++ b/app/helpers/comfy/admin/cms_helper.rb @@ -3,10 +3,9 @@ module Comfy module Admin module CmsHelper - - # Wrapper around ComfortableMexicanSofa::FormBuilder + # Wrapper around Comfy::FormBuilder def comfy_form_with(**options, &block) - form_options = options.merge(builder: ComfortableMexicanSofa::FormBuilder) + form_options = options.merge(builder: ComfortableMediaSurfer::FormBuilder) form_options[:bootstrap] = { layout: :horizontal } form_options[:local] = true bootstrap_form_with(**form_options, &block) @@ -15,8 +14,8 @@ def comfy_form_with(**options, &block) def comfy_admin_partial(path, params = {}) render path, params rescue ActionView::MissingTemplate - if ComfortableMexicanSofa.config.reveal_cms_partials - content_tag(:div, class: "comfy-admin-partial") do + if ComfortableMediaSurfer.config.reveal_cms_partials + content_tag(:div, class: 'comfy-admin-partial') do path end end @@ -24,7 +23,7 @@ def comfy_admin_partial(path, params = {}) # Injects some content somewhere inside cms admin area def cms_hook(name, options = {}) - ComfortableMexicanSofa::ViewHooks.render(name, self, options) + ComfortableMediaSurfer::ViewHooks.render(name, self, options) end # @param [String] fragment_id @@ -33,17 +32,19 @@ def cms_hook(name, options = {}) # @return [String] {{ cms:page_file_link #{fragment_id}, ... }} def cms_page_file_link_tag(fragment_id:, attachment:, multiple:) filename = ", filename: \"#{attachment.filename}\"" if multiple - as = ", as: image" if attachment.image? + as = ', as: image' if attachment.image? "{{ cms:page_file_link #{fragment_id}#{filename}#{as} }}" end # @param [Comfy::Cms::File] file # @return [String] {{ cms:file_link #{file.id}, ... }} def cms_file_link_tag(file) - as = ", as: image" if file.attachment.image? - "{{ cms:file_link #{file.id}#{as} }}" + if file.attachment.image? + "{{ cms:image #{file.label} }}" + else + "{{ cms:file_link #{file.id} }}" + end end - end end end diff --git a/app/helpers/comfy/cms_helper.rb b/app/helpers/comfy/cms_helper.rb index 087ca0b61..bb3bed5e7 100644 --- a/app/helpers/comfy/cms_helper.rb +++ b/app/helpers/comfy/cms_helper.rb @@ -2,7 +2,6 @@ module Comfy module CmsHelper - # Raw content of a page fragment. This is how you get content from unrenderable # tags like {{cms:fragment meta, render: false}} # Example: @@ -10,13 +9,14 @@ module CmsHelper # cms_fragment_content(:left_column) # if @cms_page is present def cms_fragment_content(identifier, page = @cms_page) frag = page&.fragments&.detect { |f| f.identifier == identifier.to_s } - return "" unless frag + return '' unless frag + case frag.tag - when "date", "datetime" + when 'date', 'datetime' frag.datetime - when "checkbox" + when 'checkbox' frag.boolean - when "file", "files" + when 'file', 'files' frag.attachments else frag.content @@ -28,7 +28,8 @@ def cms_fragment_content(identifier, page = @cms_page) # text because this is a potentially expensive call. def cms_fragment_render(identifier, page = @cms_page) node = page.fragment_nodes.detect { |n| n.identifier == identifier.to_s } - return "" unless node + return '' unless node + node.renderable = true render inline: page.render([node]) end @@ -39,7 +40,8 @@ def cms_fragment_render(identifier, page = @cms_page) def cms_snippet_content(identifier, cms_site = @cms_site) cms_site ||= cms_site_detect snippet = cms_site&.snippets&.find_by_identifier(identifier) - return "" unless snippet + return '' unless snippet + snippet.content end @@ -48,8 +50,9 @@ def cms_snippet_content(identifier, cms_site = @cms_site) def cms_snippet_render(identifier, cms_site = @cms_site) cms_site ||= cms_site_detect snippet = cms_site&.snippets&.find_by_identifier(identifier) - return "" unless snippet - r = ComfortableMexicanSofa::Content::Renderer.new(snippet) + return '' unless snippet + + r = ComfortableMediaSurfer::Content::Renderer.new(snippet) render inline: r.render(r.nodes(r.tokenize(snippet.content))) end @@ -59,15 +62,10 @@ def cms_site_detect Comfy::Cms::Site.find_site(host, path) end - # Wrapper to deal with Kaminari vs WillPaginate def comfy_paginate(collection) return unless collection - if defined?(WillPaginate) - will_paginate collection - elsif defined?(Kaminari) - paginate collection, theme: "comfy" - end - end + paginate collection, theme: 'comfy' if defined?(Kaminari) + end end end diff --git a/app/models/comfy/cms/categorization.rb b/app/models/comfy/cms/categorization.rb index bd08e7394..e3357e4ae 100644 --- a/app/models/comfy/cms/categorization.rb +++ b/app/models/comfy/cms/categorization.rb @@ -1,16 +1,14 @@ # frozen_string_literal: true class Comfy::Cms::Categorization < ActiveRecord::Base - - self.table_name = "comfy_cms_categorizations" + self.table_name = 'comfy_cms_categorizations' # -- Relationships ----------------------------------------------------------- belongs_to :category belongs_to :categorized, - polymorphic: true + polymorphic: true # -- Validations ------------------------------------------------------------- validates :category_id, - uniqueness: { scope: %i[categorized_type categorized_id] } - + uniqueness: { scope: %i[categorized_type categorized_id] } end diff --git a/app/models/comfy/cms/category.rb b/app/models/comfy/cms/category.rb index 5acc7d47b..f48513069 100644 --- a/app/models/comfy/cms/category.rb +++ b/app/models/comfy/cms/category.rb @@ -1,24 +1,22 @@ # frozen_string_literal: true class Comfy::Cms::Category < ActiveRecord::Base - - self.table_name = "comfy_cms_categories" + self.table_name = 'comfy_cms_categories' # -- Relationships -------------------------------------------------------- belongs_to :site has_many :categorizations, - dependent: :destroy + dependent: :destroy # -- Validations ---------------------------------------------------------- validates :label, - presence: true, - uniqueness: { scope: %i[categorized_type site_id] } + presence: true, + uniqueness: { scope: %i[categorized_type site_id] } validates :categorized_type, - presence: true + presence: true # -- Scopes --------------------------------------------------------------- scope :of_type, ->(type) { where(categorized_type: type) } - end diff --git a/app/models/comfy/cms/file.rb b/app/models/comfy/cms/file.rb index 19b05ce45..2c746ab68 100644 --- a/app/models/comfy/cms/file.rb +++ b/app/models/comfy/cms/file.rb @@ -1,15 +1,14 @@ # frozen_string_literal: true class Comfy::Cms::File < ActiveRecord::Base - - self.table_name = "comfy_cms_files" + self.table_name = 'comfy_cms_files' include Comfy::Cms::WithCategories VARIANT_SIZE = { - redactor: { resize: "100x75^", gravity: "center", crop: "100x75+0+0" }, - thumb: { resize: "200x150^", gravity: "center", crop: "200x150+0+0" }, - icon: { resize: "28x28^", gravity: "center", crop: "28x28+0+0" } + redactor: { resize: '100x75^', gravity: 'center', crop: '100x75+0+0' }, + thumb: { resize: '200x150^', gravity: 'center', crop: '200x150+0+0' }, + icon: { resize: '28x28^', gravity: 'center', crop: '28x28+0+0' } }.freeze # temporary place to store attachment @@ -23,12 +22,9 @@ class Comfy::Cms::File < ActiveRecord::Base # -- Callbacks --------------------------------------------------------------- before_validation :assign_label, on: :create before_create :assign_position - # active_storage attachment behavior changed in rails 6 - see PR#892 for details - if Rails::VERSION::MAJOR >= 6 - before_save :process_attachment - else - after_save :process_attachment - end + # active_storage attachment behavior changed in rails 6 + before_save :process_attachment + after_save :clear_page_content_cache # -- Validations ------------------------------------------------------------- validates :label, presence: true @@ -41,6 +37,12 @@ class Comfy::Cms::File < ActiveRecord::Base where("active_storage_blobs.content_type LIKE 'image/%'").references(:blob) } +private + + def clear_page_content_cache + Comfy::Cms::Page.where(id: site.pages.pluck(:id)).update_all(content_cache: nil) + end + protected def assign_position @@ -51,12 +53,13 @@ def assign_position # TODO: Change db schema not to set blank string def assign_label return if label.present? + self.label = file&.original_filename end def process_attachment return if @file.blank? - attachment.attach(@file) - end + self.attachment = @file + end end diff --git a/app/models/comfy/cms/fragment.rb b/app/models/comfy/cms/fragment.rb index 5115b6704..a1670543c 100644 --- a/app/models/comfy/cms/fragment.rb +++ b/app/models/comfy/cms/fragment.rb @@ -1,30 +1,25 @@ # frozen_string_literal: true class Comfy::Cms::Fragment < ActiveRecord::Base - - self.table_name = "comfy_cms_fragments" + self.table_name = 'comfy_cms_fragments' has_many_attached :attachments - serialize :content + serialize :content, coder: Psych attr_reader :files # -- Callbacks --------------------------------------------------------------- - # active_storage attachment behavior changed in rails 6 - see PR#892 for details - if Rails::VERSION::MAJOR >= 6 - before_save :remove_attachments, :add_attachments - else - after_save :remove_attachments, :add_attachments - end + # active_storage attachment behavior changed in rails 6 + before_save :remove_attachments, :add_attachments # -- Relationships ----------------------------------------------------------- belongs_to :record, polymorphic: true, touch: true # -- Validations ------------------------------------------------------------- validates :identifier, - presence: true, - uniqueness: { scope: :record } + presence: true, + uniqueness: { scope: :record } # -- Instance Methods -------------------------------------------------------- @@ -45,6 +40,7 @@ def file_ids_destroy=(ids) def remove_attachments return unless @file_ids_destroy.present? + attachments.where(id: @file_ids_destroy).destroy_all end @@ -52,12 +48,11 @@ def add_attachments return if @files.blank? # If we're dealing with a single file - if tag == "file" + if tag == 'file' @files = [@files.first] attachments&.purge_later end attachments.attach(@files) end - end diff --git a/app/models/comfy/cms/layout.rb b/app/models/comfy/cms/layout.rb index c4447032a..7e7b6b42e 100644 --- a/app/models/comfy/cms/layout.rb +++ b/app/models/comfy/cms/layout.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true class Comfy::Cms::Layout < ActiveRecord::Base + self.table_name = 'comfy_cms_layouts' - self.table_name = "comfy_cms_layouts" + require_relative '../../../../lib/comfortable_media_surfer/extensions/acts_as_tree' cms_acts_as_tree cms_has_revisions_for :content, :css, :js @@ -19,13 +20,13 @@ class Comfy::Cms::Layout < ActiveRecord::Base # -- Validations ------------------------------------------------------------- validates :site_id, - presence: true + presence: true validates :label, - presence: true + presence: true validates :identifier, - presence: true, - uniqueness: { scope: :site_id }, - format: { with: %r{\A\w[a-z0-9_-]*\z}i } + presence: true, + uniqueness: { scope: :site_id }, + format: { with: %r{\A\w[a-z0-9_-]*\z}i } # -- Class Methods ----------------------------------------------------------- # Tree-like structure for layouts @@ -53,8 +54,8 @@ def self.options_for_select(site, current_layout = nil) def self.app_layouts_for_select(view_paths) view_paths.map(&:to_s).select { |path| path.start_with?(Rails.root.to_s) }.flat_map do |full_path| Dir.glob("#{full_path}/layouts/**/*.html.*").collect do |filename| - filename.gsub!("#{full_path}/layouts/", "") - filename.split("/").last[0...1] == "_" ? nil : filename.split(".").first + filename.gsub!("#{full_path}/layouts/", '') + filename.split('/').last[0...1] == '_' ? nil : filename.split('.').first end.compact.sort end.compact.uniq.sort end @@ -64,19 +65,19 @@ def self.app_layouts_for_select(view_paths) # and merges on the {{cms:tag_type content}} tag (if parent layout has that). # Returns a list of tokens that can be fed into the renderer. def content_tokens - renderer = ComfortableMexicanSofa::Content::Renderer.new(nil) + renderer = ComfortableMediaSurfer::Content::Renderer.new(nil) tokens = renderer.tokenize(content) if parent - fragment_tags = ComfortableMexicanSofa::Content::Tag::Fragment.subclasses.map do |c| - ComfortableMexicanSofa::Content::Renderer.tags.key(c) + fragment_tags = ComfortableMediaSurfer::Content::Tags::Fragment.subclasses.map do |c| + ComfortableMediaSurfer::Content::Renderer.tags.key(c) end parent_tokens = parent.content_tokens replacement_position = parent_tokens.index do |n| n.is_a?(Hash) && - fragment_tags.member?(n[:tag_class]) && - n[:tag_params].split(%r{\s}).first == "content" + fragment_tags.member?(n[:tag_class]) && + n[:tag_params].split(%r{\s}).first == 'content' end if replacement_position @@ -106,8 +107,8 @@ def assign_label def assign_position return if position.to_i.positive? + max = site.layouts.where(parent_id: parent_id).maximum(:position) self.position = max ? max + 1 : 0 end - end diff --git a/app/models/comfy/cms/page.rb b/app/models/comfy/cms/page.rb index 46d7ca061..b793cc402 100644 --- a/app/models/comfy/cms/page.rb +++ b/app/models/comfy/cms/page.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true class Comfy::Cms::Page < ActiveRecord::Base - - self.table_name = "comfy_cms_pages" + self.table_name = 'comfy_cms_pages' include Comfy::Cms::WithFragments include Comfy::Cms::WithCategories @@ -15,11 +14,11 @@ class Comfy::Cms::Page < ActiveRecord::Base # -- Relationships ----------------------------------------------------------- belongs_to :site belongs_to :target_page, - class_name: "Comfy::Cms::Page", - optional: true + class_name: 'Comfy::Cms::Page', + optional: true has_many :translations, - dependent: :destroy + dependent: :destroy # -- Callbacks --------------------------------------------------------------- before_validation :assigns_label, @@ -32,13 +31,13 @@ class Comfy::Cms::Page < ActiveRecord::Base # -- Validations ------------------------------------------------------------- validates :label, - presence: true + presence: true validates :slug, - presence: true, - uniqueness: { scope: :parent_id }, - unless: ->(p) { - p.site && (p.site.pages.count.zero? || p.site.pages.root == self) - } + presence: true, + uniqueness: { scope: :parent_id }, + unless: ->(p) { + p.site && (p.site.pages.count.zero? || p.site.pages.root == self) + } validate :validate_target_page validate :validate_format_of_unescaped_slug @@ -75,7 +74,7 @@ def full_path # Somewhat unique method of identifying a page that is not a full_path def identifier - parent_id.blank? ? "index" : full_path[1..-1].parameterize + parent_id.blank? ? 'index' : full_path[1..].parameterize end # Full url for a page @@ -113,44 +112,49 @@ def assigns_label def assign_parent return unless site + self.parent ||= site.pages.root unless self == site.pages.root || site.pages.count.zero? end def assign_full_path self.full_path = if self.parent - [CGI.escape(self.parent.full_path).gsub("%2F", "/"), slug].join("/").squeeze("/") + [CGI.escape(self.parent.full_path).gsub('%2F', '/'), slug].join('/').squeeze('/') else - "/" + '/' end end def assign_position return unless self.parent return if position.to_i.positive? + max = self.parent.children.maximum(:position) self.position = max ? max + 1 : 0 end def validate_target_page return unless target_page + p = self while p.target_page if (p = p.target_page) == self - return errors.add(:target_page_id, "Invalid Redirect") + return errors.add(:target_page_id, 'Invalid Redirect') end end end def validate_format_of_unescaped_slug return unless slug.present? + unescaped_slug = CGI.unescape(slug) - errors.add(:slug, :invalid) unless unescaped_slug =~ %r{^\p{Alnum}[\.\p{Alnum}\p{Mark}_-]*$}i + errors.add(:slug, :invalid) unless unescaped_slug =~ %r{^\p{Alnum}[.\p{Alnum}\p{Mark}_-]*$}i end # Forcing re-saves for child pages so they can update full_paths def sync_child_full_paths! return unless full_path_previously_changed? + children.each do |p| p.update_attribute(:full_path, p.send(:assign_full_path)) end @@ -166,5 +170,4 @@ def unescape_slug_and_path self.slug = CGI.unescape(slug) unless slug.nil? self.full_path = CGI.unescape(full_path) unless full_path.nil? end - end diff --git a/app/models/comfy/cms/revision.rb b/app/models/comfy/cms/revision.rb index 0a155661c..508fa1591 100644 --- a/app/models/comfy/cms/revision.rb +++ b/app/models/comfy/cms/revision.rb @@ -1,12 +1,10 @@ # frozen_string_literal: true class Comfy::Cms::Revision < ActiveRecord::Base + self.table_name = 'comfy_cms_revisions' - self.table_name = "comfy_cms_revisions" - - serialize :data + serialize :data, coder: Psych # -- Relationships -------------------------------------------------------- belongs_to :record, polymorphic: true - end diff --git a/app/models/comfy/cms/site.rb b/app/models/comfy/cms/site.rb index da11b396d..c0426948c 100644 --- a/app/models/comfy/cms/site.rb +++ b/app/models/comfy/cms/site.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true class Comfy::Cms::Site < ActiveRecord::Base - - self.table_name = "comfy_cms_sites" + self.table_name = 'comfy_cms_sites' # -- Relationships ----------------------------------------------------------- with_options dependent: :destroy do |site| @@ -21,25 +20,26 @@ class Comfy::Cms::Site < ActiveRecord::Base # -- Validations ------------------------------------------------------------- validates :identifier, - presence: true, - uniqueness: true, - format: { with: %r{\A\w[a-z0-9_-]*\z}i } + presence: true, + uniqueness: true, + format: { with: %r{\A\w[a-z0-9_-]*\z}i } validates :label, - presence: true + presence: true validates :hostname, - presence: true, - uniqueness: { scope: :path }, - format: { with: %r{\A[\w.-]+(?:\:\d+)?\z} } + presence: true, + uniqueness: { scope: :path }, + format: { with: %r{\A[\w.-]+(?::\d+)?\z} } # -- Class Methods ----------------------------------------------------------- # returning the Comfy::Cms::Site instance based on host and path def self.find_site(host, path = nil) return Comfy::Cms::Site.first if Comfy::Cms::Site.count == 1 + cms_site = nil - public_cms_path = ComfortableMexicanSofa.configuration.public_cms_path - if path && public_cms_path != "/" - path = path.sub(%r{\A#{public_cms_path}}, "") + public_cms_path = ComfortableMediaSurfer.configuration.public_cms_path + if path && public_cms_path != '/' + path = path.sub(%r{\A#{public_cms_path}}, '') end Comfy::Cms::Site.where(hostname: real_host_from_aliases(host)).each do |site| @@ -54,7 +54,7 @@ def self.find_site(host, path = nil) end def self.real_host_from_aliases(host) - if (aliases = ComfortableMexicanSofa.config.hostname_aliases) + if (aliases = ComfortableMediaSurfer.config.hostname_aliases) aliases.each do |alias_host, hosts| return alias_host if hosts.include?(host) end @@ -64,9 +64,9 @@ def self.real_host_from_aliases(host) # -- Instance Methods -------------------------------------------------------- def url(relative: false) - public_cms_path = ComfortableMexicanSofa.config.public_cms_path || "/" + public_cms_path = ComfortableMediaSurfer.config.public_cms_path || '/' host = "//#{hostname}" - path = ["/", public_cms_path, self.path].compact.join("/").squeeze("/").chomp("/") + path = ['/', public_cms_path, self.path].compact.join('/').squeeze('/').chomp('/') relative ? path.presence : [host, path].join end @@ -85,10 +85,9 @@ def assign_label end def clean_path - self.path ||= "" - self.path.squeeze!("/") - self.path.gsub!(%r{/$}, "") + self.path ||= '' + self.path.squeeze!('/') + self.path.gsub!(%r{/$}, '') self.path = nil if self.path.blank? end - end diff --git a/app/models/comfy/cms/snippet.rb b/app/models/comfy/cms/snippet.rb index 2d33f1e56..a7b509f77 100644 --- a/app/models/comfy/cms/snippet.rb +++ b/app/models/comfy/cms/snippet.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true class Comfy::Cms::Snippet < ActiveRecord::Base - - self.table_name = "comfy_cms_snippets" + self.table_name = 'comfy_cms_snippets' include Comfy::Cms::WithCategories @@ -19,11 +18,11 @@ class Comfy::Cms::Snippet < ActiveRecord::Base # -- Validations ------------------------------------------------------------- validates :label, - presence: true + presence: true validates :identifier, - presence: true, - uniqueness: { scope: :site_id }, - format: { with: %r{\A\w[a-z0-9_-]*\z}i } + presence: true, + uniqueness: { scope: :site_id }, + format: { with: %r{\A\w[a-z0-9_-]*\z}i } protected @@ -41,5 +40,4 @@ def assign_position max = site.snippets.maximum(:position) self.position = max ? max + 1 : 0 end - end diff --git a/app/models/comfy/cms/translation.rb b/app/models/comfy/cms/translation.rb index 276ab9fcd..7de7a23f8 100644 --- a/app/models/comfy/cms/translation.rb +++ b/app/models/comfy/cms/translation.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true class Comfy::Cms::Translation < ActiveRecord::Base - - self.table_name = "comfy_cms_translations" + self.table_name = 'comfy_cms_translations' include Comfy::Cms::WithFragments @@ -21,11 +20,11 @@ class Comfy::Cms::Translation < ActiveRecord::Base # -- Validations ------------------------------------------------------------- validates :label, - presence: true + presence: true validates :locale, - presence: true, - uniqueness: { scope: :page_id } + presence: true, + uniqueness: { scope: :page_id } validate :validate_locale @@ -33,11 +32,11 @@ class Comfy::Cms::Translation < ActiveRecord::Base def validate_locale return unless page + errors.add(:locale) if locale == page.site.locale end def assign_layout self.layout ||= page.layout if page.present? end - end diff --git a/app/models/concerns/comfy/cms/with_categories.rb b/app/models/concerns/comfy/cms/with_categories.rb index 3c649b133..3993a903a 100644 --- a/app/models/concerns/comfy/cms/with_categories.rb +++ b/app/models/concerns/comfy/cms/with_categories.rb @@ -1,17 +1,16 @@ # frozen_string_literal: true module Comfy::Cms::WithCategories - extend ActiveSupport::Concern included do has_many :categorizations, - as: :categorized, - class_name: "Comfy::Cms::Categorization", - dependent: :destroy + as: :categorized, + class_name: 'Comfy::Cms::Categorization', + dependent: :destroy has_many :categories, - through: :categorizations, - class_name: "Comfy::Cms::Category" + through: :categorizations, + class_name: 'Comfy::Cms::Category' attr_writer :category_ids @@ -21,7 +20,7 @@ module Comfy::Cms::WithCategories if (categories = [categories].flatten.compact).present? distinct .joins(categorizations: :category) - .where("comfy_cms_categories.label" => categories) + .where('comfy_cms_categories.label' => categories) end } end @@ -49,5 +48,4 @@ def sync_categories ids_to_remove = existing_ids - ids_to_add categorizations.where(category_id: ids_to_remove).destroy_all end - end diff --git a/app/models/concerns/comfy/cms/with_fragments.rb b/app/models/concerns/comfy/cms/with_fragments.rb index 712d65f8e..32e763f47 100644 --- a/app/models/concerns/comfy/cms/with_fragments.rb +++ b/app/models/concerns/comfy/cms/with_fragments.rb @@ -1,25 +1,24 @@ # frozen_string_literal: true module Comfy::Cms::WithFragments - extend ActiveSupport::Concern included do attr_accessor :fragments_attributes_changed belongs_to :layout, - class_name: "Comfy::Cms::Layout" + class_name: 'Comfy::Cms::Layout' has_many :fragments, - class_name: "Comfy::Cms::Fragment", - as: :record, - autosave: true, - dependent: :destroy + class_name: 'Comfy::Cms::Fragment', + as: :record, + autosave: true, + dependent: :destroy before_save :clear_content_cache validates :layout, - presence: true + presence: true end # Array of fragment hashes in the following format: @@ -78,7 +77,7 @@ def fragments_attributes_was # duplicate tags on the layout. That's wierd (but still works). def fragment_nodes nodes - .select { |n| n.is_a?(ComfortableMexicanSofa::Content::Tag::Fragment) } + .select { |n| n.is_a?(ComfortableMediaSurfer::Content::Tags::Fragment) } .uniq(&:identifier) end @@ -112,7 +111,7 @@ def clear_content_cache protected def renderer - ComfortableMexicanSofa::Content::Renderer.new(self) + ComfortableMediaSurfer::Content::Renderer.new(self) end def nodes @@ -121,5 +120,4 @@ def nodes tokens = layout.content_tokens renderer.nodes(tokens) end - end diff --git a/app/views/comfy/admin/cms/categories/_edit.html.haml b/app/views/comfy/admin/cms/categories/_edit.html.haml index 175dd9e97..04ffc7f39 100644 --- a/app/views/comfy/admin/cms/categories/_edit.html.haml +++ b/app/views/comfy/admin/cms/categories/_edit.html.haml @@ -1,5 +1,5 @@ - url = comfy_admin_cms_site_category_path(@site, category) -= form_with model: @category, scope: :category, url: url, html: {class: "edit-category", id: dom_id(category)} do |form| += form_with model: @category, scope: :category, url: url, html: {class: "edit-category", id: dom_id(category)}, local: false do |form| .input-group = form.text_field :label, class: "form-control form-control-sm", id: nil .input-group-btn diff --git a/app/views/comfy/admin/cms/categories/_index.html.haml b/app/views/comfy/admin/cms/categories/_index.html.haml index 60e9d3835..c37a5af46 100644 --- a/app/views/comfy/admin/cms/categories/_index.html.haml +++ b/app/views/comfy/admin/cms/categories/_index.html.haml @@ -16,7 +16,7 @@ = render "comfy/admin/cms/categories/show", category: category - url = comfy_admin_cms_site_categories_path(@site) - = form_with scope: :category, url: url, html: {id: "new-category"} do |form| + = form_with scope: :category, url: url, html: {id: "new-category"}, local: false do |form| = form.hidden_field :categorized_type, value: type .input-group = form.text_field :label, placeholder: t('.add_placeholder'), class: 'form-control form-control-sm', id: nil diff --git a/app/views/comfy/admin/cms/files/_file.html.haml b/app/views/comfy/admin/cms/files/_file.html.haml index 10b564ebe..c005e2d8f 100644 --- a/app/views/comfy/admin/cms/files/_file.html.haml +++ b/app/views/comfy/admin/cms/files/_file.html.haml @@ -1,7 +1,7 @@ %li{data: {id: file.id}} :ruby file_tag = cms_file_link_tag(file) - thumb_url = url_for(file.attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:thumb])) if file.attachment.variable? + thumb_url = url_for(file.attachment.representation(resize_to_limit: [200, nil])) if file.attachment.variable? .row .col-md-5.item .item-controls.d-none.d-lg-block diff --git a/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml b/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml index de736bbac..c7f87862d 100644 --- a/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml +++ b/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml @@ -25,7 +25,7 @@ .tab-content - frag_index = 0 - - builder_opts = { builder: ComfortableMexicanSofa::FormBuilder, bootstrap: { layout: :horizontal }} + - builder_opts = { builder: ComfortableMediaSurfer::FormBuilder, bootstrap: { layout: :horizontal }} = fields scope, model: record, **builder_opts do |form| - namespace.each_with_index do |(name, tags), index| .tab-pane{id: "ns-#{name}", class: index == 0 ? "active" : nil} @@ -33,6 +33,6 @@ = form.fragment_field(tag, frag_index) - frag_index += 1 -- rescue ComfortableMexicanSofa::Content::Renderer::SyntaxError, ComfortableMexicanSofa::Content::Tag::Error => e +- rescue ComfortableMediaSurfer::Content::Renderer::SyntaxError, ComfortableMediaSurfer::Content::Tag::Error => e .alert.alert-danger = e diff --git a/app/views/comfy/admin/cms/pages/_form.html.haml b/app/views/comfy/admin/cms/pages/_form.html.haml index 113d629ef..595e7ee96 100644 --- a/app/views/comfy/admin/cms/pages/_form.html.haml +++ b/app/views/comfy/admin/cms/pages/_form.html.haml @@ -26,6 +26,6 @@ = comfy_admin_partial "comfy/admin/cms/partials/page_form_after", form: form = form.form_actions do - = submit_tag t(".preview"), name: "preview", formtarget: "comfy-cms-preview", id: nil, class: "btn btn-secondary", data: {disable_with: false} - = submit_tag t(@page.new_record?? ".create" : ".update"), class: "btn btn-primary ml-sm-1", data: {disable_with: false} + = submit_tag t(".preview"), name: "preview", formtarget: "comfy-cms-preview", id: nil, class: "btn btn-secondary" + = submit_tag t(@page.new_record?? ".create" : ".update"), class: "btn btn-primary ml-sm-1" = link_to t(".cancel"), comfy_admin_cms_site_pages_path, class: "btn btn-link" diff --git a/app/views/comfy/admin/cms/sites/_form.html.haml b/app/views/comfy/admin/cms/sites/_form.html.haml index b2f2b62c1..aa952c49f 100644 --- a/app/views/comfy/admin/cms/sites/_form.html.haml +++ b/app/views/comfy/admin/cms/sites/_form.html.haml @@ -5,7 +5,7 @@ = form.text_field :hostname = form.text_field :path -- locales = ComfortableMexicanSofa.config.locales.to_a.collect{|l| ["#{l[1]} (#{l[0]})", l[0]]} +- locales = ComfortableMediaSurfer.config.locales.to_a.collect{|l| ["#{l[1]} (#{l[0]})", l[0]]} = form.select :locale, locales, bootstrap: {custom_control: true} = comfy_admin_partial "comfy/admin/cms/partials/site_form_after", form: form diff --git a/app/views/comfy/admin/cms/snippets/_form.html.haml b/app/views/comfy/admin/cms/snippets/_form.html.haml index 552adc089..c91e564cc 100644 --- a/app/views/comfy/admin/cms/snippets/_form.html.haml +++ b/app/views/comfy/admin/cms/snippets/_form.html.haml @@ -2,12 +2,18 @@ = form.text_field :label, data: {slugify: @snippet.new_record?} = form.text_field :identifier, data: {slug: true} -= form.text_area :content, data: {'cms-cm-mode' => 'text/html'} += form.check_box :markdown + +- if @snippet.markdown + = form.text_area :content, data: {'cms-cm-mode' => 'text/x-markdown'} +- else + = form.text_area :content, data: {'cms-cm-mode' => 'text/html'} = render 'comfy/admin/cms/categories/form', form: form -= comfy_admin_partial "comfy/admin/cms/partials/snippet_form_after", form: form += comfy_admin_partial 'comfy/admin/cms/partials/snippet_form_after', form: form = form.form_actions do = submit_tag t(@snippet.new_record? ? ".create" : ".update"), class: "btn btn-primary" = link_to t(".cancel"), comfy_admin_cms_site_snippets_path, class: "btn btn-link" + \ No newline at end of file diff --git a/app/views/layouts/comfy/admin/cms/_head.html.haml b/app/views/layouts/comfy/admin/cms/_head.html.haml index a78a794fe..b0cf47cd6 100644 --- a/app/views/layouts/comfy/admin/cms/_head.html.haml +++ b/app/views/layouts/comfy/admin/cms/_head.html.haml @@ -1,5 +1,5 @@ %head - %title= ComfortableMexicanSofa.config.cms_title + %title= ComfortableMediaSurfer.config.cms_title %meta{"http-equiv" => "Content-type", content: "text/html; charset=utf-8"} %meta{charset: "utf-8"} diff --git a/app/views/layouts/comfy/admin/cms/_left.html.haml b/app/views/layouts/comfy/admin/cms/_left.html.haml index b2c9ae9e0..3ab3baf8e 100644 --- a/app/views/layouts/comfy/admin/cms/_left.html.haml +++ b/app/views/layouts/comfy/admin/cms/_left.html.haml @@ -35,5 +35,12 @@ = comfy_admin_partial "comfy/admin/cms/partials/navigation_after" .left-footer - = link_to 'ComfortableMexicanSofa', 'https://github.com/comfy', target: '_blank' - %span.version= ComfortableMexicanSofa::VERSION + = link_to 'ComfortableMediaSurfer', 'https://github.com/shakacode/comfortable-media-surfer', target: '_blank' + %span.version= ComfortableMediaSurfer::VERSION + %br + = link_to 'Rails', 'https://rubyonrails.org', target: '_blank' + %span.version= Rails::version + = link_to 'Ruby', 'https://www.ruby-lang.org', target: '_blank' + %span.version= RUBY_VERSION + %br + = Rails.env.upcase + ' - ' + ActiveRecord::Base.connection.adapter_name diff --git a/comfortable_media_surfer.gemspec b/comfortable_media_surfer.gemspec new file mode 100644 index 000000000..0993d4786 --- /dev/null +++ b/comfortable_media_surfer.gemspec @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift File.expand_path('lib', __dir__) +require 'comfortable_media_surfer/version' + +Gem::Specification.new do |spec| + spec.name = 'comfortable_media_surfer' + spec.version = ComfortableMediaSurfer::VERSION + spec.authors = ['Oleg Khabarov', 'Andrew vonderLuft', 'ShakaCode'] + spec.email = ['justin@shakacode.com'] + spec.homepage = 'https://github.com/shakacode/comfortable-media-surfer' + spec.summary = 'Rails 6.1-7.1+ CMS Engine' + spec.description = 'ComfortableMediaSurfer is a powerful Rails 6.1-7.1+ CMS Engine' + spec.license = 'MIT' + + spec.files = `git ls-files -z`.split("\x0").reject do |f| + f.match(%r{^(test|doc)/}) + end + + spec.required_ruby_version = '>= 3.0.0' + spec.metadata['rubygems_mfa_required'] = 'true' + + spec.add_dependency 'active_link_to', '~> 1.0', '>= 1.0.5' + spec.add_dependency 'comfy_bootstrap_form', '~> 4.0', '>= 4.0.0' + spec.add_dependency 'haml-rails', '~> 2.1', '>= 2.1.0' + spec.add_dependency 'image_processing', '~> 1.2', '>= 1.12.2' + spec.add_dependency 'jquery-rails', '~> 4.6', '>= 4.6.0' + spec.add_dependency 'kaminari', '~> 1.2', '>= 1.2.2' + spec.add_dependency 'kramdown', '~> 2.4', '>= 2.4.0' + spec.add_dependency 'mimemagic', '~> 0.4', '>= 0.4.3' + spec.add_dependency 'mini_magick', '~> 4.12', '>= 4.12.0' + spec.add_dependency 'rails', '>= 6.1.0' + spec.add_dependency 'rails-i18n', '>= 6.0.0' + spec.add_dependency 'sassc-rails', '~> 2.1', '>= 2.1.2' + spec.add_dependency 'sprockets-rails', '~> 3.4', '>= 3.4.2' +end diff --git a/comfortable_mexican_sofa.gemspec b/comfortable_mexican_sofa.gemspec deleted file mode 100644 index 0492d7665..000000000 --- a/comfortable_mexican_sofa.gemspec +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -$LOAD_PATH.unshift File.expand_path("lib", __dir__) -require "comfortable_mexican_sofa/version" - -Gem::Specification.new do |s| - s.name = "comfortable_mexican_sofa" - s.version = ComfortableMexicanSofa::VERSION - s.authors = ["Oleg Khabarov"] - s.email = ["oleg@khabarov.ca"] - s.homepage = "http://github.com/comfy/comfortable-mexican-sofa" - s.summary = "Rails 5.2+ CMS Engine" - s.description = "ComfortableMexicanSofa is a powerful Rails 5.2+ CMS Engine" - s.license = "MIT" - - s.files = `git ls-files -z`.split("\x0").reject do |f| - f.match(%r{^(test|doc)/}) - end - - s.required_ruby_version = ">= 2.3.0" - - s.add_dependency "active_link_to", ">= 1.0.0" - s.add_dependency "comfy_bootstrap_form", ">= 4.0.0" - s.add_dependency "haml-rails", ">= 1.0.0" - s.add_dependency "jquery-rails", ">= 4.3.1" - s.add_dependency "kramdown", ">= 1.0.0" - s.add_dependency "mimemagic", ">= 0.3.2" - s.add_dependency "mini_magick", ">= 4.8.0" - s.add_dependency "rails", ">= 5.2.0" - s.add_dependency "rails-i18n", ">= 5.0.0" - s.add_dependency "sassc-rails", ">= 2.0.0" -end diff --git a/config.ru b/config.ru index 3967ee9a7..583d80e03 100644 --- a/config.ru +++ b/config.ru @@ -2,5 +2,5 @@ # This file is used by Rack-based servers to start the application. -require ::File.expand_path("../config/environment", __FILE__) -run ComfortableMexicanSofa::Application +require File.expand_path('config/environment', __dir__) +run ComfortableMediaSurfer::Application diff --git a/config/application.rb b/config/application.rb index d865b23b2..79efd495a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,39 +1,59 @@ # frozen_string_literal: true -require_relative "boot" +require_relative 'boot' -require "rails/all" +require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) -module ComfortableMexicanSofa +module ComfortableMediaSurfer class Application < Rails::Application + # Load defaults based on Rails major/minor version + config.load_defaults Rails.version.scan(%r{^\d+\.\d+}).first.to_f + + # Rails 7.1 compatibility - See config/initializers/new_framework_defaults_7_1.rb + if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1.0') + config.active_record.default_column_serializer = YAML + config.active_record.before_committed_on_all_records = false + config.active_record.commit_transaction_on_non_local_return = false + config.active_record.run_after_transaction_callbacks_in_order_defined = false + config.active_support.message_serializer = :json + config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = true + # config.active_record.allow_deprecated_singular_associations_name = true + # config.active_support.raise_on_invalid_cache_expiration_time = false + # config.active_record.sqlite3_adapter_strict_strings_by_default = false + # config.active_support.cache_format_version = 7.0 + # Please, add to the `ignore` list any other `lib` subdirectories that do + # not contain `.rb` files, or that should not be reloaded or eager loaded. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.add_autoload_paths_to_load_path = false + config.autoload_lib(ignore: %w[generators]) + end - require_relative "../lib/comfortable_mexican_sofa" - - config.load_defaults 5.2 - - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - + # Making sure we don't load our dev routes as part of the engine + config.paths['config/routes.rb'] << 'config/cms_routes.rb' + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") # Ensuring that all ActiveStorage routes are loaded before out globbing route. config.railties_order = [ActiveStorage::Engine, :main_app, :all] - # Making sure we don't load our dev routes as part of the engine - config.paths["config/routes.rb"] << "config/cms_routes.rb" - config.i18n.enforce_available_locales = true + config.active_record.yaml_column_permitted_classes = [ + Symbol, + Date, + Time, + ActiveSupport::TimeWithZone, + ActiveSupport::TimeZone, + ActiveSupport::SafeBuffer + ] end end diff --git a/config/boot.rb b/config/boot.rb index 1c1a70f8f..30e594e23 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -# Set up gems listed in the Gemfile. -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) -File.exist?(ENV["BUNDLE_GEMFILE"]) +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 000000000..f7edb5e02 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: occams_production diff --git a/config/cms_routes.rb b/config/cms_routes.rb index 43aaf5017..66d13ef8e 100644 --- a/config/cms_routes.rb +++ b/config/cms_routes.rb @@ -2,7 +2,7 @@ # We can't have this in config/routes.rb as they will get pulled in into parent # application automatically. We want user to manually place them. -ComfortableMexicanSofa::Application.routes.draw do +ComfortableMediaSurfer::Application.routes.draw do comfy_route :cms_admin comfy_route :cms end diff --git a/config/database.yml b/config/database.yml index 3a3674c54..69d73d241 100644 --- a/config/database.yml +++ b/config/database.yml @@ -8,4 +8,33 @@ test: adapter: sqlite3 database: db/test.sqlite3 pool: 5 - timeout: 10000 \ No newline at end of file + timeout: 10000 + +# default: &default +# adapter: mysql2 +# encoding: utf8mb4 +# pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> +# username: root +# password: +# socket: /tmp/mysql.sock +# +# development: +# <<: *default +# database: comfy_dev +# +# test: +# <<: *default +# database: comfy_test + +# default: &default +# adapter: postgresql +# encoding: unicode +# pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> +# +# development: +# <<: *default +# database: comfy_dev +# +# test: +# <<: *default +# database: comfy_test diff --git a/config/environment.rb b/config/environment.rb index 0e2661b48..229efbfff 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -# Load the rails application -require File.expand_path("application", __dir__) +# Load the Rails application. +require_relative 'application' # Initialize the rails application -ComfortableMexicanSofa::Application.initialize! +ComfortableMediaSurfer::Application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index e690c79f5..fcad87e9d 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,12 +1,14 @@ # frozen_string_literal: true -defined?(ComfortableMexicanSofa::Application) && ComfortableMexicanSofa::Application.configure do +require 'active_support/core_ext/integer/time' + +defined?(ComfortableMediaSurfer::Application) && ComfortableMediaSurfer::Application.configure do # Settings specified here will take precedence over those in config/application.rb. - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. - config.cache_classes = false + config.enable_reloading = true # Do not eager load code on boot. config.eager_load = false @@ -14,14 +16,18 @@ # Show full error reports. config.consider_all_requests_local = true + # Enable server timing + config.server_timing = true + # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. - if Rails.root.join("tmp/caching-dev.txt").exist? + if Rails.root.join('tmp/caching-dev.txt').exist? config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{2.days.to_i}" + 'Cache-Control' => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -29,7 +35,7 @@ config.cache_store = :null_store end - # Store uploaded files on the local file system (see config/storage.yml for options) + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Don't care if the mailer can't send. @@ -40,25 +46,35 @@ # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true # Suppress logger output for asset requests. config.assets.quiet = true - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true - # Use an evented file watcher to asynchronously detect changes in source code, - # routes, locales, etc. This feature depends on the listen gem. - config.file_watcher = ActiveSupport::EventedFileUpdateChecker + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true - config.active_job.queue_adapter = :inline + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true - config.action_view.raise_on_missing_translations = true + if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1.0') + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true + end end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 000000000..478c5fb28 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' + +defined?(ComfortableMediaSurfer::Application) && ComfortableMediaSurfer::Application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.enable_reloading = false + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Enable static file serving from the `/public` folder (turn off if using NGINX/Apache for it). + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress CSS using a preprocessor. + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain. + # config.action_cable.mount_path = nil + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true + + # Log to STDOUT by default + config.logger = ActiveSupport::Logger.new($stdout) + .tap { |logger| logger.formatter = Logger::Formatter.new } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } + + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] + + # Info include generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info') + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "comfy_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } +end diff --git a/config/environments/test.rb b/config/environments/test.rb index 2d319e8bd..22f4a3f15 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,37 +1,50 @@ # frozen_string_literal: true -defined?(ComfortableMexicanSofa::Application) && ComfortableMexicanSofa::Application.configure do +require 'active_support/core_ext/integer/time' + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +defined?(ComfortableMediaSurfer::Application) && ComfortableMediaSurfer::Application.configure do # Settings specified here will take precedence over those in config/application.rb. - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + config.active_job.queue_adapter = :test # added for Rails 7.1 + + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. - config.eager_load = false + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV['CI'].present? # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{1.hour.to_i}" + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + config.action_dispatch.show_exceptions = if Gem::Version.new(Rails.version) < Gem::Version.new('7.1.0') + false + else + :none + end # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false - # Store uploaded files on the local file system in a temporary directory + # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -42,14 +55,20 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] - config.active_job.queue_adapter = :inline + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true - config.action_view.raise_on_missing_translations = true + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true - # TODO: This is temporary fix so TravisCI runs until Rails 5.2.3 is out. - # See: https://github.com/rails/rails/pull/35607 - config.secret_key_base = SecureRandom.hex(64) + if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1.0') + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true + end end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 000000000..bcafccdd3 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_media_surfer.rb similarity index 93% rename from config/initializers/comfortable_mexican_sofa.rb rename to config/initializers/comfortable_media_surfer.rb index 71c6ea87c..a5a04e4c4 100644 --- a/config/initializers/comfortable_mexican_sofa.rb +++ b/config/initializers/comfortable_media_surfer.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -ComfortableMexicanSofa.configure do |config| +ComfortableMediaSurfer.configure do |config| # Title of the admin area - # config.cms_title = 'ComfortableMexicanSofa CMS Engine' + # config.cms_title = 'Comfy CMS Engine' # Controller that is inherited from CmsAdmin::BaseController # config.admin_base_controller = 'ApplicationController' @@ -88,10 +88,10 @@ # } end -# Default credentials for ComfortableMexicanSofa::AccessControl::AdminAuthentication +# Default credentials for ComfortableMediaSurfer::AccessControl::AdminAuthentication # YOU REALLY WANT TO CHANGE THIS BEFORE PUTTING YOUR SITE LIVE -ComfortableMexicanSofa::AccessControl::AdminAuthentication.username = "username" -ComfortableMexicanSofa::AccessControl::AdminAuthentication.password = "password" +ComfortableMediaSurfer::AccessControl::AdminAuthentication.username = 'user' +ComfortableMediaSurfer::AccessControl::AdminAuthentication.password = 'pass' # Uncomment this module and `config.admin_auth` above to use custom admin authentication # module ComfyAdminAuthentication diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..35ab3fd6a --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src style-src) +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..c416e6a62 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += %i[ + passw secret token _key crypt salt certificate otp ssn +] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 000000000..9e049dcc9 --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/config/initializers/json.rb b/config/initializers/json.rb new file mode 100644 index 000000000..754ee2409 --- /dev/null +++ b/config/initializers/json.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module JSON +module_function + + def parse(source, opts = {}) + Parser.new(source, **opts).parse + end +end diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb new file mode 100644 index 000000000..d17bac3a0 --- /dev/null +++ b/config/initializers/new_framework_defaults_7_0.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 7.0 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `7.0`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +# `button_to` view helper will render `