]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11265 use valid-url library to validate urls
authorStas Vilchik <stas.vilchik@sonarsource.com>
Tue, 16 Oct 2018 09:20:50 +0000 (11:20 +0200)
committerSonarTech <sonartech@sonarsource.com>
Tue, 16 Oct 2018 14:41:53 +0000 (16:41 +0200)
server/sonar-web/package.json
server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx
server/sonar-web/src/main/js/apps/webhooks/components/CreateWebhookForm.tsx
server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts
server/sonar-web/src/main/js/helpers/urls.ts
server/sonar-web/yarn.lock

index f0d1f5c219ace20cc26309efe195eb8c33d79d43..c5e2074a0b82fafbc67bba3f3784651ac53933d4 100644 (file)
@@ -43,6 +43,7 @@
     "remark-slug": "5.0.0",
     "remark-toc": "5.0.0",
     "unist-util-visit": "1.3.1",
+    "valid-url": "1.0.9",
     "whatwg-fetch": "2.0.4"
   },
   "devDependencies": {
@@ -77,6 +78,7 @@
     "@types/react-router": "3.0.13",
     "@types/react-select": "1.2.6",
     "@types/react-virtualized": "9.18.3",
+    "@types/valid-url": "1.0.2",
     "autoprefixer": "8.4.1",
     "babel-core": "7.0.0-bridge.0",
     "babel-jest": "23.6.0",
index 6bacc6727e6adfec3b50e9c489cbc1fc883b540f..cf5026f87ae6ce5c1aaee7c7fe6839bd02004ef7 100644 (file)
@@ -18,6 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import { isWebUri } from 'valid-url';
 import OrganizationDetailsInput from './OrganizationDetailsInput';
 import Step from '../../tutorials/components/Step';
 import ValidationForm, { ChildrenProps } from '../../../components/controls/ValidationForm';
@@ -25,7 +26,6 @@ import { translate } from '../../../helpers/l10n';
 import { ResetButtonLink, SubmitButton } from '../../../components/ui/buttons';
 import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon';
 import DropdownIcon from '../../../components/icons-components/DropdownIcon';
-import { isUrl } from '../../../helpers/urls';
 import { OrganizationBase } from '../../../app/types';
 import { getOrganization } from '../../../api/organizations';
 
@@ -80,7 +80,7 @@ export default class OrganizationDetailsStep extends React.PureComponent<Props,
   handleValidate = ({ avatar, name, key, url }: Values) => {
     const errors: { [P in keyof Values]?: string } = {};
 
-    if (avatar.length > 0 && !isUrl(avatar)) {
+    if (avatar.length > 0 && !isWebUri(avatar)) {
       errors.avatar = translate('onboarding.create_organization.avatar.error');
     }
 
@@ -92,7 +92,7 @@ export default class OrganizationDetailsStep extends React.PureComponent<Props,
       errors.key = translate('onboarding.create_organization.organization_name.error');
     }
 
-    if (url.length > 0 && !isUrl(url)) {
+    if (url.length > 0 && !isWebUri(url)) {
       errors.url = translate('onboarding.create_organization.url.error');
     }
 
index 6a76095990fa5970ab17cc07be8c41e8343c6356..462df320caa7dd2c059120930c9c2717126cfdde 100644 (file)
  */
 import * as React from 'react';
 import { FormikProps } from 'formik';
+import { isWebUri } from 'valid-url';
 import ValidationModal from '../../../components/controls/ValidationModal';
 import InputValidationField from '../../../components/controls/InputValidationField';
 import { Webhook } from '../../../app/types';
-import { isUrl } from '../../../helpers/urls';
 import { translate } from '../../../helpers/l10n';
 
 interface Props {
@@ -53,7 +53,7 @@ export default class CreateWebhookForm extends React.PureComponent<Props> {
       errors.url = translate('webhooks.url.required');
     } else if (!url.startsWith('http://') && !url.startsWith('https://')) {
       errors.url = translate('webhooks.url.bad_protocol');
-    } else if (!isUrl(url)) {
+    } else if (!isWebUri(url)) {
       errors.url = translate('webhooks.url.bad_format');
     }
     return errors;
index 0dc5a089379dcb7b0e8463b71327db1ad9bf9dee..f5c9ef90db2965c2308f8a1007eeff761e1aa6bb 100644 (file)
@@ -23,8 +23,7 @@ import {
   getPathUrlAsString,
   getProjectUrl,
   getQualityGatesUrl,
-  getQualityGateUrl,
-  isUrl
+  getQualityGateUrl
 } from '../urls';
 
 const SIMPLE_COMPONENT_KEY = 'sonarqube';
@@ -118,51 +117,3 @@ describe('#getQualityGate(s)Url', () => {
     });
   });
 });
-
-describe('#isUrl', () => {
-  it('should be valid', () => {
-    expect(isUrl('https://localhost')).toBeTruthy();
-    expect(isUrl('https://localhost/')).toBeTruthy();
-    expect(isUrl('https://localhost:9000')).toBeTruthy();
-    expect(isUrl('https://localhost:9000/')).toBeTruthy();
-    expect(isUrl('https://foo:bar@localhost:9000')).toBeTruthy();
-    expect(isUrl('https://foo@localhost')).toBeTruthy();
-    expect(isUrl('http://foo.com/blah_blah')).toBeTruthy();
-    expect(isUrl('http://foo.com/blah_blah/')).toBeTruthy();
-    expect(isUrl('http://www.example.com/wpstyle/?p=364')).toBeTruthy();
-    expect(isUrl('https://www.example.com/foo/?bar=baz&inga=42&quux')).toBeTruthy();
-    expect(isUrl('http://userid@example.com')).toBeTruthy();
-    expect(isUrl('http://userid@example.com/')).toBeTruthy();
-    expect(isUrl('http://userid:password@example.com:8080')).toBeTruthy();
-    expect(isUrl('http://userid:password@example.com:8080/')).toBeTruthy();
-    expect(isUrl('http://userid@example.com:8080')).toBeTruthy();
-    expect(isUrl('http://userid@example.com:8080/')).toBeTruthy();
-    expect(isUrl('http://userid:password@example.com')).toBeTruthy();
-    expect(isUrl('http://userid:password@example.com/')).toBeTruthy();
-    expect(isUrl('http://142.42.1.1/')).toBeTruthy();
-    expect(isUrl('http://142.42.1.1:8080/')).toBeTruthy();
-    expect(isUrl('http://foo.com/blah_(wikipedia)#cite-1')).toBeTruthy();
-    expect(isUrl('http://foo.com/blah_(wikipedia)_blah#cite-1')).toBeTruthy();
-    expect(isUrl('http://foo.com/(something)?after=parens')).toBeTruthy();
-    expect(isUrl('http://code.google.com/events/#&product=browser')).toBeTruthy();
-    expect(isUrl('http://j.mp')).toBeTruthy();
-    expect(isUrl('http://foo.bar/?q=Test%20URL-encoded%20stuff')).toBeTruthy();
-    expect(isUrl('http://1337.net')).toBeTruthy();
-    expect(isUrl('http://a.b-c.de')).toBeTruthy();
-    expect(isUrl('http://223.255.255.254')).toBeTruthy();
-    expect(isUrl('https://foo_bar.example.com/')).toBeTruthy();
-  });
-
-  it('should not be valid', () => {
-    expect(isUrl('http://')).toBeFalsy();
-    expect(isUrl('http://?')).toBeFalsy();
-    expect(isUrl('http://??')).toBeFalsy();
-    expect(isUrl('http://??/')).toBeFalsy();
-    expect(isUrl('http://#')).toBeFalsy();
-    expect(isUrl('http://##')).toBeFalsy();
-    expect(isUrl('http://##/')).toBeFalsy();
-    expect(isUrl('//')).toBeFalsy();
-    expect(isUrl('///')).toBeFalsy();
-    expect(isUrl('http:// shouldfail.com')).toBeFalsy();
-  });
-});
index de21ce40a5e851eb106cb5e2d8340f234fb7733d..ecb965a112a0f905d21792355b33d0a3a34b009d 100644 (file)
@@ -252,15 +252,3 @@ export function getHomePageUrl(homepage: HomePage) {
   // should never happen, but just in case...
   return '/projects';
 }
-
-export function isUrl(url: string) {
-  try {
-    const elem = document.createElement('a');
-    elem.href = url;
-    return !!(elem.host && elem.hostname && elem.protocol);
-  } catch (error) {
-    // both IE11 & Edge throw an exception when a url contains credentials
-    // is this case let's just pretend the url is fine and pass it to the server for the validation
-    return true;
-  }
-}
index 279fc9ba4e66a9ecfc2fd02173e124c92053688a..d5faaf6b2776acc8e20e9e10c1115f642a724b54 100644 (file)
     "@types/prop-types" "*"
     csstype "^2.2.0"
 
+"@types/valid-url@1.0.2":
+  version "1.0.2"
+  resolved "http://registry.npmjs.org/@types/valid-url/-/valid-url-1.0.2.tgz#60fa435ce24bfd5ba107b8d2a80796aeaf3a8f45"
+  integrity sha1-YPpDXOJL/VuhB7jSqAeWrq86j0U=
+
 "@webassemblyjs/ast@1.5.13":
   version "1.5.13"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25"
@@ -10185,6 +10190,11 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0:
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
   integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==
 
+valid-url@1.0.9:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
+  integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=
+
 validate-npm-package-license@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"