From 9eedec3f87243a26b8e15eb45d59addff29809e3 Mon Sep 17 00:00:00 2001 From: sshmm Date: Sat, 5 Nov 2022 23:48:43 +0200 Subject: [PATCH 1/5] Add sanitized markdown support for epoch statement --- api/hasura/actions/_handlers/updateUser.ts | 10 +- package.json | 3 + src/pages/GivePage/EpochStatementDrawer.tsx | 59 +- yarn.lock | 1060 ++++++++++++++++++- 4 files changed, 1109 insertions(+), 23 deletions(-) diff --git a/api/hasura/actions/_handlers/updateUser.ts b/api/hasura/actions/_handlers/updateUser.ts index 937e8bcd78..e631c234ae 100644 --- a/api/hasura/actions/_handlers/updateUser.ts +++ b/api/hasura/actions/_handlers/updateUser.ts @@ -1,6 +1,7 @@ import assert from 'assert'; import type { VercelRequest, VercelResponse } from '@vercel/node'; +import sanitizeHtml from 'sanitize-html'; import { adminClient } from '../../../../api-lib/gql/adminClient'; import { errorResponse } from '../../../../api-lib/HttpError'; @@ -21,7 +22,7 @@ async function handler(req: VercelRequest, res: VercelResponse) { ).parse(req.body); // Validate no epoches are active for the requested user - const { circle_id } = payload; + const { circle_id, bio } = payload; const { hasuraAddress: address } = session_variables; const { @@ -41,6 +42,7 @@ async function handler(req: VercelRequest, res: VercelResponse) { id: true, fixed_non_receiver: true, give_token_received: true, + bio: true, }, ], }); @@ -52,14 +54,18 @@ async function handler(req: VercelRequest, res: VercelResponse) { }); } + let sanitizedBio = undefined; // Update the state after all external validations have passed - + if (!!bio?.length && bio !== user.bio) { + sanitizedBio = sanitizeHtml(bio); + } const mutationResult = await adminClient.mutate( { update_users: [ { _set: { ...payload, + bio: sanitizedBio ?? bio, // reset give_token_received if a user is opted out of an // active epoch give_token_received: diff --git a/package.json b/package.json index c910e37cf1..7b08b2200e 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "@typeform/embed-react": "^1.18.0", "@types/morgan": "^1.9.3", "@types/react-helmet": "^6.1.5", + "@types/sanitize-html": "^2.6.2", + "@uiw/react-markdown-preview": "^4.1.5", "@web3-react/core": "6.1.9", "@web3-react/injected-connector": "6.0.7", "@web3-react/walletconnect-connector": "6.2.13", @@ -77,6 +79,7 @@ "react-transition-group": "^4.4.5", "react-virtualized-auto-sizer": "1.0.5", "recoil": "0.4.1", + "sanitize-html": "^2.7.3", "sharp": "^0.30.5", "siwe": "^2.0.3", "stream": "^0.0.2", diff --git a/src/pages/GivePage/EpochStatementDrawer.tsx b/src/pages/GivePage/EpochStatementDrawer.tsx index c2c2743535..1b446ddda3 100644 --- a/src/pages/GivePage/EpochStatementDrawer.tsx +++ b/src/pages/GivePage/EpochStatementDrawer.tsx @@ -1,9 +1,11 @@ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; +import MarkdownPreview from '@uiw/react-markdown-preview'; import { updateUser } from 'lib/gql/mutations'; import debounce from 'lodash/debounce'; import { useMutation, useQuery } from 'react-query'; import { NavLink } from 'react-router-dom'; +import sanitizeHtml from 'sanitize-html'; import { ApeInfoTooltip } from '../../components'; import { Check, X } from '../../icons/__generated'; @@ -67,6 +69,7 @@ export const EpochStatementDrawer = ({ // saveTimeout is the timeout handle for the buffered async saving const [saving, setSaving] = useState('stable'); + const [showMarkdown, setShowMarkDown] = useState(true); const { mutate: updateEpochStatement } = useMutation( async (bio: string) => updateUser({ circle_id: member.circle_id, bio }), @@ -100,6 +103,12 @@ export const EpochStatementDrawer = ({ [saveStatement] ); + useEffect(() => { + if (!showMarkdown) { + document?.getElementById('epoch_statement')?.focus(); + } + }, [showMarkdown]); + return ( Epoch Statement -