Skip to content

Commit

Permalink
Merge pull request #4224 from serlo/refactor/add-image-proxy
Browse files Browse the repository at this point in the history
refactor(editor): add image proxy for privacy (serlo-only)
  • Loading branch information
elbotho authored Nov 4, 2024
2 parents 082779b + 34733cf commit b6114b8
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 9 deletions.
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}/image?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

0 comments on commit b6114b8

Please sign in to comment.