Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(editor): add image proxy for privacy (serlo-only) #4224

Draft
wants to merge 1 commit into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'
import { StaticSlate } from '@editor/plugins/text/static-components/static-slate'
import { cn } from '@editor/utils/cn'
import React from 'react'
Expand All @@ -14,7 +15,7 @@ export function AnswerContent(props: AnswerContentProps) {

if (url) {
return (
<img
<EditorImage
data-qa="plugin-dropzone-image-answer-content-image"
src={url}
className={cn('h-full w-full object-contain', className)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'
import { cn } from '@editor/utils/cn'

import { GridImage } from '../types'
Expand Down Expand Up @@ -35,7 +36,7 @@ export function ImageGrid({
style={isLastImage ? {} : getFlex(leftImage)}
>
<button onClick={() => onImageClick(index)}>
<img
<EditorImage
src={leftImage.src}
alt={leftImage.alt}
className={cn(isLastImage && 'max-h-96')}
Expand All @@ -47,7 +48,10 @@ export function ImageGrid({
{rightImage ? (
<div className="group relative" style={getFlex(rightImage)}>
<button onClick={() => onImageClick(rightIndex)}>
<img src={rightImage.src} alt={`Image ${rightImage.src}`} />
<EditorImage
src={rightImage.src}
alt={`Image ${rightImage.src}`}
/>
</button>
{extraChildren?.[rightIndex]}
{renderHoverOverlay(rightImage.caption, rightIndex)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'

import { GridImage } from '../../types'

interface StaticCarouselProps {
Expand All @@ -14,7 +16,7 @@ export function StaticCarousel({ images, onImageClick }: StaticCarouselProps) {
className="w-full flex-shrink-0 snap-center snap-always text-center"
onClick={() => onImageClick(index)}
>
<img src={src} alt={alt} />
<EditorImage src={src} alt={alt} />
<div className="mt-3">
{caption ? (
<div className="italic text-gray-700 [&_a]:text-brand-400">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'
import { UIEvent, useEffect, useRef } from 'react'

import { GridImage } from '../../types'
Expand Down Expand Up @@ -37,7 +38,7 @@ export function StaticLightboxCarousel({
key={index}
className="w-full flex-shrink-0 snap-center snap-always text-center"
>
<img src={src} alt={alt} />
<EditorImage src={src} alt={alt} />
<div className="mt-3">
{caption ? (
<div className="italic text-gray-100 [&_a]:text-brand-400">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'

import { GridImage } from '../../types'

export function StaticLightboxImage({ caption, src, alt }: GridImage) {
if (!caption) {
return <img src={src} className="max-h-[60vh] bg-white" />
return <EditorImage src={src} className="max-h-[60vh] bg-white" />
}

return (
<div className="text-center">
<img src={src} alt={alt} className="max-h-[60vh] bg-white" />
<EditorImage src={src} alt={alt} className="max-h-[60vh] bg-white" />
<div className="mt-3 italic text-gray-100 [&_a]:text-brand-400">
{caption}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EditorImage } from '@editor/plugins/image/components/editor-image'
import { cn } from '@editor/utils/cn'

import type { GridImage } from '../../types'
Expand All @@ -17,7 +18,7 @@ export function StaticLightboxThumbnail({

return (
<button className="group relative" onClick={onClick}>
<img src={src} alt={alt} className="max-h-[120px] bg-white" />
<EditorImage src={src} alt={alt} className="max-h-[120px] bg-white" />
<div
className={cn(
'absolute inset-0 bg-black bg-opacity-70 group-hover:block',
Expand Down
25 changes: 25 additions & 0 deletions packages/editor/src/plugins/image/components/editor-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { serloDomain } from '@editor/utils/serlo-domain'
import { SerloOnlyFeaturesContext } from '@editor/utils/serlo-extra-context'
import { ImgHTMLAttributes, useContext } from 'react'

/**
* Proxies external editor images via cloudflare worker
* Temporary fix for privacy reasons. Long term we want to upload
* images to our own bucket instead
*/
export function EditorImage(props: ImgHTMLAttributes<HTMLImageElement>) {
const isSerlo = useContext(SerloOnlyFeaturesContext).isSerlo
return <img {...props} src={getSrc(isSerlo, props.src)} />
}

function getSrc(isSerlo?: boolean, src?: string) {
if (!isSerlo || !src) return src

const isAllowed =
src.startsWith('https://assets.serlo.org/') ||
src.startsWith('https://pixabay.com/')

if (isAllowed) return src

return `https://asset-proxy.${serloDomain}/src?url=${encodeURIComponent(src)}`
}
4 changes: 3 additions & 1 deletion packages/editor/src/plugins/image/renderer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useStaticStrings } from '@editor/i18n/static-strings-provider'

import { EditorImage } from './components/editor-image'

interface ImageProps {
image: {
src: string
Expand Down Expand Up @@ -31,7 +33,7 @@ export function ImageRenderer({
<div style={{ maxWidth }} className="mx-auto">
{wrapWithLink(
placeholder ?? (
<img
<EditorImage
className="serlo-img"
src={src}
alt={alt ? alt : altFallbackString}
Expand Down