Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Content editing in Symfony

Content editing in Symfony

Content editing is the process of letting users create rich content directly from your project. It goes from allowing users to write simple text comments to letting users write rich documents collaboratively in real-time. Due to the inherent risks of displaying user content on your platform, it is a difficult problem to tackle in a secure, scalable and feature-rich way.

Let's discuss how the HtmlSanitizer component, Symfony UX and Mercure can be used together to build amazing editing experiences for your users.

Titouan Galopin

November 18, 2022
Tweet

More Decks by Titouan Galopin

Other Decks in Technology

Transcript

  1. Content
    editing in
    Symfony

    View Slide

  2. Hello!
    I am Titouan Galopin
    Symfony UX initiative lead
    Selency // Citipo
    2

    View Slide

  3. Agenda
    1. Know your content
    2. Security concerns
    3. Choosing an editor
    4. The state of the art: block-based editors
    5. Live editing with Symfony UX and Mercure
    3

    View Slide

  4. 1
    Know your content
    4

    View Slide

  5. Content editing isn’t a technical
    challenge, it’s an architecture one
    5

    View Slide

  6. ● Article comments
    ● Restaurant reviews
    ● Social post
    ● Document writing
    ● CMS
    ● …
    Many use cases
    6

    View Slide

  7. ⬡ Stylable content vs Plain text?
    Should your users be able to insert bold/italic? Links?
    Images? …
    Questions to ask yourself
    7

    View Slide

  8. Questions to ask yourself
    8
    ⬡ Stylable content vs Plain text?
    ⬡ Feature-rich content vs Markdown?
    Markdown is great but it’s difficult to use for non-technical
    users, and will it be enough?

    View Slide

  9. Questions to ask yourself
    9
    ⬡ Stylable content vs Plain text?
    ⬡ Feature-rich content vs Markdown?
    ⬡ Programmatic content manipulation?
    Will you need to manipulate the content programmatically
    (move elements, migrate to a new editor, upgrade your
    current editor, …)? (Most likely yes)

    View Slide

  10. Questions to ask yourself
    10
    ⬡ Stylable content vs Plain text?
    ⬡ Feature-rich content vs Markdown?
    ⬡ Programmatic content manipulation?
    ⬡ Translation?
    Automatic/manual content translation?

    View Slide

  11. Questions to ask yourself
    11
    ⬡ Stylable content vs Plain text?
    ⬡ Feature-rich content vs Markdown?
    ⬡ Programmatic content manipulation?
    ⬡ Translation?
    ⬡ Different display on mobile vs desktop?
    Should some blocks have a different structure on mobile?

    View Slide

  12. Questions to ask yourself
    12
    ⬡ Stylable content vs Plain text?
    ⬡ Feature-rich content vs Markdown?
    ⬡ Programmatic content manipulation?
    ⬡ Translation?
    ⬡ Different display on mobile vs desktop?
    ⬡ Display in non-Web contexts (mobile/desktop app, …)?

    View Slide

  13. Answers to these questions are
    both technical and human
    Content editors are one of the
    most complex UX challenge
    13

    View Slide

  14. 2
    Security concerns
    14

    View Slide

  15. A content editor is a big
    security risk
    You must implement
    dedicated security
    15

    View Slide

  16. Biggest risk:
    Cross-site scripting
    Inject JavaScript code into Web pages viewed by
    other users to extract information (session cookie,
    password, emails, …) from your users.
    16

    View Slide

  17. But also …
    CSS display attack
    Inject CSS into pages to render them unusable or log
    the keystrokes of visitors.
    17

    View Slide

  18. But also …
    Click-hijacking attack
    Inject HTML/CSS into pages to change the target of
    a legitimate link somewhere in the page (for instance
    the login button) to a phishing page.
    18

    View Slide

  19. But also …
    DDoS attacks
    Libraries to sanitize user content are complex and
    CPU-intensive (HTML parsing and manipulation). It’s
    a great place to DDoS a platform.
    19

    View Slide

  20. 20
    Implementing
    security

    View Slide

  21. Simplest option
    Twig escape filter (or htmlentities) if you don’t need
    to accept HTML (plain text/markdown/…).
    You should use this when you can.
    21

    View Slide

  22. HTML sanitizing
    When you need to accept HTML (rich-content), you
    need to distinguish safe from unsafe HTML.
    This is what’s called HTML Sanitizing.
    22

    View Slide

  23. Symfony HtmlSanitizer
    The HTML Sanitizer component aims at sanitizing
    untrusted HTML code (e.g. created by a WYSIWYG
    editor in the browser) into HTML that can be trusted.
    23

    View Slide

  24. HtmlSanitizer is useful to:
    ● Prevent security issues (XSS, CSRF, data
    extraction, …)
    ● Prevent display problems (ensure content
    consistency)
    ● Output valid, standard HTML from potentially
    invalid WYSIWYG editor one
    24

    View Slide

  25. Usage
    25

    View Slide

  26. 26

    View Slide

  27. 27
    As a service

    View Slide

  28. 28
    In a form

    View Slide

  29. 29
    As a Twig filter

    View Slide

  30. Configuration
    30

    View Slide

  31. 31
    Create a custom sanitizer

    View Slide

  32. 32
    Configure
    allowed

    View Slide

  33. 33
    Configure
    allowed

    and
    forbidden
    elements

    View Slide

  34. 34
    Configure
    allowed links to
    prevent phishing
    and privacy
    issues

    View Slide

  35. 35
    Configure
    allowed media to
    prevent phishing
    and privacy
    issues

    View Slide

  36. Tip: you should apply
    sanitizing before storing
    and before display
    36

    View Slide

  37. Before storing
    To store safe HTML in the database
    37

    View Slide

  38. Before displaying
    Because:
    1. Content can be manipulated from outside your
    application (manually, script missing the sanitizer, …)
    2. Because some databases have unpredictable
    behaviors
    Ex: MySQL transforms UTF-8 character ⟨ to ASCII < when storing in a non-UTF8 field
    38

    View Slide

  39. 3
    Choosing an editor
    39

    View Slide

  40. The editor you choose should match
    your technical and UX needs
    40

    View Slide

  41. 41
    Plain-text

    View Slide

  42. Simplest option (textarea)
    ● Easy-to-use for everyone
    ● Can be enough, especially with modern emoji
    support
    ● Very limited styling
    42

    View Slide

  43. Implementation
    ● Editor: standard textarea
    ● Display: Twig + escape filter
    43

    View Slide

  44. 44
    Markup
    language

    View Slide

  45. Great for technical users
    ● Great UX for tech users (ex: Markdown + CodeMirror)
    ● Flexible without too much JavaScript complexity
    ● Not usable by non-tech users
    ● Requires HTML sanitization for security
    45

    View Slide

  46. 46
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer

    View Slide

  47. 47
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer
    ● Symfony UX +
    CodeMirror

    View Slide

  48. 48
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer
    ● Symfony UX +
    CodeMirror

    View Slide

  49. 49
    Implementation
    Display:
    ● Twig +
    league/
    commonmark +
    HtmlSanitizer

    View Slide

  50. 50
    WYSIWYG

    View Slide

  51. UX-friendly for everyone
    ● Easy-to-use by anyone
    ● Requires a complex JavaScript library
    ● Requires HTML sanitization for security
    ● Difficult to manipulate the generated content
    51

    View Slide

  52. 52
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer

    View Slide

  53. 53
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer
    ● Symfony UX +
    CKEditor

    View Slide

  54. 54
    Implementation
    Editor:
    ● TextareaType +
    HtmlSanitizer
    ● Symfony UX +
    CKEditor

    View Slide

  55. 55
    Implementation
    Display:
    ● Twig +
    HtmlSanitizer

    View Slide

  56. Problems
    1. How can I add a around tweets on display?
    2. How can I upgrade my editor version without
    breaking existing content?
    3. How can I display content in a non-Web context?
    4. How can I allow multiple people to edit
    collaboratively?
    56

    View Slide

  57. HTML is not easy to manipulate
    57

    View Slide

  58. 4
    The state of the art:
    block-based editors
    58

    View Slide

  59. The idea
    Content is stored as JSON
    blocks, containing HTML only
    when necessary
    59

    View Slide

  60. The rendered HTML is only built
    at display
    60

    View Slide

  61. By using JSON blocks:
    ● Easier to manipulate (“add a around tweets”)
    ● Can display content outside the Web
    ● Ease content migration during upgrades
    ● Make live collaboration possible
    61

    View Slide

  62. Example:
    Quill Rich Text Editor
    62

    View Slide

  63. 63

    View Slide

  64. Deltas
    Deltas are an expressive format to
    describe Quill’s contents and changes
    64

    View Slide

  65. 65
    Describes content…

    View Slide

  66. 66
    …but also changes

    View Slide

  67. Security
    Blocks content should still be:
    ● Escaped (Twig/htmlentities) if they
    won’t contain any HTML
    ● Sanitized if they will
    67

    View Slide

  68. Implementation
    Very similar to CKEditor: Symfony UX to
    instantiate, Symfony Form to extract the
    data
    68

    View Slide

  69. Storage
    Store the content as JSON in your
    database: easy manipulation!
    69

    View Slide

  70. Display
    Use Quill JS library to render blocks as
    safe HTML … or implement your own logic
    to display on other platforms!
    70

    View Slide

  71. Solutions
    1. How can I add a around tweets on display?
    2. How can I upgrade my editor version without
    breaking existing content?
    3. How can I display content in a non-Web context?
    => Now very easy!
    4. How can I allow multiple people to edit the same
    content collaboratively?

    71

    View Slide

  72. 5
    Live editing with Symfony UX
    and Mercure
    72

    View Slide

  73. Deltas allow us to live stream
    changes across users!
    73

    View Slide

  74. 74
    Collaborative editor

    View Slide

  75. 75
    Collaborative editor
    This is a Delta
    change: small,
    easy bit to
    synchronize the
    editor state
    between users

    View Slide

  76. Conclusion
    76

    View Slide

  77. Conclusion
    ● For simple needs: plain text + escape is enough (a
    content editor isn’t necessarily worth it)
    77

    View Slide

  78. Conclusion
    ● For simple needs: plain text + escape is enough (a
    content editor isn’t necessarily worth it)
    ● For tech users: Markdown + HtmlSanitizer with a
    code editor is great and flexible
    78

    View Slide

  79. Conclusion
    ● For simple needs: plain text + escape is enough (a
    content editor isn’t necessarily worth it)
    ● For tech users: Markdown + HtmlSanitizer with a
    code editor is great and flexible
    ● Otherwise: always choose a block-based editor
    (much more flexible) and use sanitization
    79

    View Slide

  80. 80
    Thanks!
    Any questions?
    You can find me at:
    @tgalopin
    [email protected]
    Slides design by SlidesCarnival

    View Slide