diff --git a/client/package-lock.json b/client/package-lock.json index 76fb1f9..c0bc051 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9125,10 +9125,13 @@ "unc-path-regex": "^0.1.2" } }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + "is-url-superb": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-3.0.0.tgz", + "integrity": "sha512-3faQP+wHCGDQT1qReM5zCPx2mxoal6DzbzquFlCYJLWyy4WPTved33ea2xFbX37z4NoriEwZGIYhFtx8RUB5wQ==", + "requires": { + "url-regex": "^5.0.0" + } }, "is-utf8": { "version": "0.2.1", @@ -16371,6 +16374,11 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "tlds": { + "version": "1.203.1", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.203.1.tgz", + "integrity": "sha512-7MUlYyGJ6rSitEZ3r1Q1QNV8uSIzapS8SmmhSusBuIc7uIxPPwsKllEP0GRp1NS6Ik6F+fRZvnjDWm3ecv2hDw==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -17010,6 +17018,22 @@ "prepend-http": "^1.0.1" } }, + "url-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-5.0.0.tgz", + "integrity": "sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g==", + "requires": { + "ip-regex": "^4.1.0", + "tlds": "^1.203.0" + }, + "dependencies": { + "ip-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.1.0.tgz", + "integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==" + } + } + }, "url-set-query": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", diff --git a/client/package.json b/client/package.json index dff3e63..3b56ff2 100644 --- a/client/package.json +++ b/client/package.json @@ -23,7 +23,7 @@ "ethereum-blockies": "github:MyEtherWallet/blockies", "filesize": "^4.1.2", "history": "^4.9.0", - "is-url": "^1.2.4", + "is-url-superb": "^3.0.0", "moment": "^2.24.0", "query-string": "^6.8.2", "react": "16.8.6", diff --git a/client/src/components/atoms/Form/Input.tsx b/client/src/components/atoms/Form/Input.tsx index a9dd129..4992101 100644 --- a/client/src/components/atoms/Form/Input.tsx +++ b/client/src/components/atoms/Form/Input.tsx @@ -30,6 +30,7 @@ interface InputProps { rows?: number group?: any multiple?: boolean + pattern?: string } interface InputState { diff --git a/client/src/routes/Publish/Files/ItemForm.tsx b/client/src/routes/Publish/Files/ItemForm.tsx index b4e8b0f..fbf8677 100644 --- a/client/src/routes/Publish/Files/ItemForm.tsx +++ b/client/src/routes/Publish/Files/ItemForm.tsx @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react' -import isUrl from 'is-url' +import isUrl from 'is-url-superb' import Input from '../../../components/atoms/Form/Input' import Button from '../../../components/atoms/Button' import styles from './ItemForm.module.scss' @@ -37,7 +37,7 @@ export default class ItemForm extends PureComponent< return } - if (url && !isUrl(url)) { + if (url && !url.includes('ipfs://') && !isUrl(url)) { this.setState({ noUrl: true }) return } diff --git a/server/.env.example b/server/.env.example index 28c38a0..53927a2 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1 +1,2 @@ SENDGRID_API_KEY='xxx' +IPFS_GATEWAY_URL='https://gateway.ipfs.io' diff --git a/server/README.md b/server/README.md index 521b971..7172b1d 100644 --- a/server/README.md +++ b/server/README.md @@ -4,12 +4,12 @@ This folder contains server component written in TypeScript using [Express](https://expressjs.com). The server provides various microservices. -- [Get Started](#Get-Started) -- [✨ API Documentation](#-API-Documentation) - - [Url Checker](#Url-Checker) - - [Report](#Report) -- [🎁 Contributing](#-Contributing) -- [🏛 License](#-License) +- [Get Started](#get-started) +- [✨ API Documentation](#-api-documentation) + - [Url Checker](#url-checker) + - [Report](#report) +- [🎁 Contributing](#-contributing) +- [🏛 License](#-license) ## Get Started @@ -36,6 +36,12 @@ Url Checker returns size and additional information about requested file. This s } ``` +```json +{ + "url": "ipfs://QmQfpdcMWnLTXKKW9GPV7NgtEugghgD6HgzSF6gSrp2mL9" +} +``` + **Response: Success** ```json diff --git a/server/src/config/config.ts b/server/src/config/config.ts index ef9bbe0..9f44d55 100644 --- a/server/src/config/config.ts +++ b/server/src/config/config.ts @@ -1,7 +1,9 @@ +import 'dotenv/config' + const config = { - app: { - port: 4000 - } + app: { port: 4000 }, + sendgridApiKey: process.env.SENDGRID_API_KEY, + ipfsGatewayUrl: process.env.IPFS_GATEWAY_URL || 'https://gateway.ipfs.io' } export default config diff --git a/server/src/routes/ReportRouter.ts b/server/src/routes/ReportRouter.ts index 9751da2..3bdd1bb 100644 --- a/server/src/routes/ReportRouter.ts +++ b/server/src/routes/ReportRouter.ts @@ -1,8 +1,8 @@ import { Router, Request, Response } from 'express' import SendgridMail from '@sendgrid/mail' -import 'dotenv/config' +import config from '../config/config' -SendgridMail.setApiKey(process.env.SENDGRID_API_KEY) +SendgridMail.setApiKey(config.sendgridApiKey) export class ReportRouter { public router: Router diff --git a/server/src/routes/UrlCheckRouter.ts b/server/src/routes/UrlCheckRouter.ts index dbe6eff..00e1a12 100644 --- a/server/src/routes/UrlCheckRouter.ts +++ b/server/src/routes/UrlCheckRouter.ts @@ -1,5 +1,6 @@ import { Router, Request, Response } from 'express' import request from 'request' +import config from '../config/config' export class UrlCheckRouter { public router: Router @@ -12,13 +13,22 @@ export class UrlCheckRouter { } public checkUrl(req: Request, res: Response) { - if (!req.body.url) { + let { url } = req.body + + if (!url) { return res.send({ status: 'error', message: 'missing url' }) } + + // map native IPFS URLs to gateway URLs + if (url.includes('ipfs://')) { + const cid = url.split('ipfs://')[1] + url = `${config.ipfsGatewayUrl}/ipfs/${cid}` + } + request( { method: 'HEAD', - url: req.body.url, + url, headers: { Range: 'bytes=0-' } }, (error, response) => {