← Back to Upcase

Html-editor for Rails form field


(Acandael Acandael) #1

Hi,

My client asked more editing features for a form field, like making text bold, italic, etc …

So I’m thinking about implementing an html-editor for a Rails form field.

Does anyone have experience with this, and which html-editor do you recommend?

Thanks for your help,

Anthony


(Geoff Harcourt) #2

Hi @acandael_acanda, if I’m understanding your question, your client needs to be able to submit HTML to you through a form. There are a few good HTML editors available. Basecamp uses wysihtml5. I am using Ace right now, which has been packaged for Rails in this gem: https://github.com/codykrieger/ace-rails-ap.

If you are going to be displaying back the client’s submitted input (particularly if anyone who isn’t the original submitter can look at HTML that a user created), you need to be very concerned about script injection. I’m sure other folks here might have some useful ideas, but at a bare minimum I would use loofah and loofah-activerecord to enforce some santization against XSS attacks.

Your worst case scenario here is that a user submits malicious input containing an XSS attack, and then an administrator views the page and gets their account hijacked, so make sure you are scrubbing user input.

Hope this helps.


(Acandael Acandael) #3

Hi Geoff, thanks for the advice. The form will only be edited by admin users, so I don’t think script injection is a big concern, unless of course someone would hack an admin account.

The application is for a university research-group
The form field where I want to implement a html-editor is called ‘reference’ and is a reference to a scientific publication. Because the reference needs to adhere to scientific reference notiation (title needs to be italic etc …) the client asked me for html-editing functionality. The form looks like this:

<%= form_for [:admin, @publication] do |f| %>
  <fieldset>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :reference %>
    <%= f.text_area :reference %>
  </div>
  <div>
    <%= f.label :research_project %>
    <%= f.collection_select :research_project_id, ResearchProject.all, :id, :title, prompt: true %>
  </div>
  <% if @publication.new_record? %>
    <%= f.submit "Add Publication" %>
  <% else %>
    <%= f.submit "Update Publication" %>
  <% end %>
  <%= link_to 'Cancel', admin_publications_path %>
</fieldset>
<% end %>

greetings,

Anthony


(Acandael Acandael) #4

After some investigation, I decided to use the Froala Editor . It’s an editor based jQuery and Font-Awesome. It was really easy to setup, thanks to the wysiwyg-rails gem . It was literaly implemented in 5 minutes.

To implement the editor on my form-field, I just needed to include this jQuery:

<script>
    $(function() {
      $('#publication_reference').editable({
        inlineMode: false,

         // Set custom buttons with separator between them. Also include the name
        // of the buttons  defined in customButtons.
             buttons: ['bold', 'italic']
      })
    });
</script>

The only thing I have to figure out right now is to make the html tags that where inserted by the editor, get interpreted on the page, and not literaly printed as is the case right now.

Is there a way to make Rails encode the html and not literally print it out?

greetings,

Anthony


(Acandael Acandael) #5

that was too easy :smiley:

<p><%= raw @publication.reference %></p> 

(Acandael Acandael) #6

So Geoff, if I use the Loofa Gem, how would I sanitize my :reference textarea form field?

Thanks for your help,

Anthony


(Geoff Harcourt) #7

@acandael_acanda, try Loofah::Scrubber: https://github.com/flavorjones/loofah

This is one of the few scenarios where a model before_save callback is warranted, since you never want to save un-sanitized input. I would write a test where you attempt to save reference with HTML that includes a <script> tag, then confirm it didn’t get saved intact. Loofah does much more complicated scrubbing than this, but that simple test will confirm that Loofah is interacting with and scrubbing your field.


(Geoff Harcourt) #8

Aaaand right on schedule, Rails 4.2 is going to include Loofah for out of the box HTML santization:


(Acandael Acandael) #9

Thanks Geof for the information, but what’s not fully clear to me is how to use the scrub! method on a form input field. Should I apply the scrub! method somehow on the form input field itself in the View, or should should I implement it in the Controller and parse the input from the params hash? As you see, not fully clear to me yet :smiley:

greetings,

Anthony


(Geoff Harcourt) #10

Hi Anthony,

I’d use the scrubbing in your model as a before_save callback, since you will never want to save a model without sanitized HTML.

-Geoff


(Acandael Acandael) #11

I installed the loofah gem. I couldn’t install the loofah-activerecord gem, it doesn’t seem too work for Rails 4 applications.

In my Publication model, I defined a before_save callback:

before_save :scrub_reference

and I defined this private method on my Publication model:

class Publication < ActiveRecord::Base
  before_save :scrub_reference
  ...

  private

  def scrub_reference
    Loofah.scrub_fragment(self.reference, :prune)
  end
end

I wrote a integration test:

scenario 'admin should not be able to add publication with script input' do
  find("input[@value='Add Publication']").click
  fill_in 'Title', with: "new publication" 
  fill_in 'Reference', with: "<script>alert('hello there');</script>" 
  click_button 'Add Publication'
  expect((Publication.last).reference).not_to eq("<script>alert('hello there');</script>")
end

But when I run this test I get a failure:

1) Admin interacts with publications admin should not be able to add publication with script input
 Failure/Error: expect((Publication.last).reference).not_to eq("<script>alert('hello there');</script>")
   
   expected: value != "<script>alert('hello there');</script>"
        got: "<script>alert('hello there');</script>"
   
   (compared using ==)
 # ./spec/features/admin_handles_publications_spec.rb:48:in `block (2 levels) in <top (required)>'

Finished in 0.68114 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/features/admin_handles_publications_spec.rb:43 # Admin interacts with publications admin     should not be able to add publication with script input

I’m not sure if I’m implementing the scrub method the right way in my model. Not quite sure how I should pass it the reference fragment

greetings,

Anthony


(Geoff Harcourt) #12

Not absolutely sure what’s wrong here, but I think in your test you should be ensuring that you’re looking consistently at escaped/unescaped values.