From acf565be7bc6042e69a141bbad06f8f194bb1c48 Mon Sep 17 00:00:00 2001 From: evazion Date: Sat, 15 Jan 2022 23:20:15 -0600 Subject: [PATCH] Fix #4678: Validate custom CSS. * Make it an error to add invalid custom CSS to your account. * Add a fix script to remove custom CSS from all accounts with invalid CSS. --- Gemfile | 1 + Gemfile.lock | 1 + app/controllers/users_controller.rb | 2 +- app/logical/custom_css.rb | 15 +++++++++++++ app/models/user.rb | 13 ++++++++++++ app/views/users/custom_style.css.erb | 4 +++- script/fixes/091_delete_invalid_custom_css.rb | 21 +++++++++++++++++++ test/unit/user_test.rb | 15 +++++++++++++ 8 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 app/logical/custom_css.rb create mode 100755 script/fixes/091_delete_invalid_custom_css.rb diff --git a/Gemfile b/Gemfile index e1df61667..57f00deb1 100644 --- a/Gemfile +++ b/Gemfile @@ -55,6 +55,7 @@ gem "pry-rails" gem "ffi" gem "rbtrace" gem "good_job" +gem "crass" group :development do gem 'rubocop', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 0abafe316..0c7c7a039 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -553,6 +553,7 @@ DEPENDENCIES capybara clockwork codecov + crass daemons derailed_benchmarks diff-lcs diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 95b8a8be8..e2da988b4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -113,7 +113,7 @@ class UsersController < ApplicationController end def custom_style - @css = CurrentUser.user.custom_style + @custom_css = CurrentUser.user.custom_css expires_in 10.years end diff --git a/app/logical/custom_css.rb b/app/logical/custom_css.rb new file mode 100644 index 000000000..aa800a471 --- /dev/null +++ b/app/logical/custom_css.rb @@ -0,0 +1,15 @@ +class CustomCss + attr_reader :css + + def initialize(css) + @css = css + end + + def valid? + css.blank? || parsed_css.none? { |node| node[:node] == :error } + end + + def parsed_css + @parsed_css ||= Crass.parse(css, preserve_comments: true) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 6f2775f79..9069ce2e4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -106,6 +106,7 @@ class User < ApplicationRecord validates :password, confirmation: true validates :comment_threshold, inclusion: { in: (-100..5) } validate :validate_enable_private_favorites, on: :update + validate :validate_custom_css, if: :custom_style_changed? before_validation :normalize_blacklisted_tags before_create :promote_to_owner_if_first_user has_many :artist_versions, foreign_key: :updater_id @@ -601,6 +602,18 @@ class User < ApplicationRecord end end + concerning :CustomCssMethods do + def custom_css + CustomCss.new(custom_style) + end + + def validate_custom_css + if !custom_css.valid? + errors.add(:base, "Custom CSS contains a syntax error. Validate it with https://codebeautify.org/cssvalidate") + end + end + end + module SearchMethods def search(params) params = params.dup diff --git a/app/views/users/custom_style.css.erb b/app/views/users/custom_style.css.erb index 84bb09149..84c8dac95 100644 --- a/app/views/users/custom_style.css.erb +++ b/app/views/users/custom_style.css.erb @@ -1 +1,3 @@ -<%= raw @css %> +<% if @custom_css.valid? %> + <%= raw @custom_css.css %> +<% end %> diff --git a/script/fixes/091_delete_invalid_custom_css.rb b/script/fixes/091_delete_invalid_custom_css.rb new file mode 100755 index 000000000..3f35b443e --- /dev/null +++ b/script/fixes/091_delete_invalid_custom_css.rb @@ -0,0 +1,21 @@ +#!/usr/bin/env ruby + +require_relative "base" + +with_confirmation do + users = User.where("custom_style != ''").select { |user| !user.custom_css.valid? } + + users.each do |user| + Dmail.create_automated(to: user, title: "Action required: Your custom CSS is invalid", body: <<~EOS) + Hi, + + The custom CSS in your account settings is invalid and has been removed from your account. To restore it, go to https://codebeautify.org/cssvalidate, copy and paste the CSS below, and fix any errors that are shown. Then, go to your account settings at https://danbooru.donmai.us/settings, click the Advanced tab, and re-add your custom CSS. + + [code] + #{user.custom_style} + [/code] + EOS + + user.update!(custom_style: "") + end +end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index cfa83b76a..1006bc6cb 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -268,5 +268,20 @@ class UserTest < ActiveSupport::TestCase assert_equal([user3.id], User.search(name: "bar\\\*baz").map(&:id)) end end + + context "custom CSS" do + should "raise a validation error on invalid custom CSS" do + user = build(:user, custom_style: "}}}") + + assert_equal(true, user.invalid?) + assert_match(/Custom CSS contains a syntax error/, user.errors[:base].first) + end + + should "allow blank CSS" do + user = build(:user, custom_style: " ") + + assert_equal(true, user.valid?) + end + end end end