update devDependencies, eslint config, address lint issues
[squeep-indieauth-helper] / lib / communication.js
index 2bda4ce2307dc0b026ba3975e65d0f56a936b940..9446b0013483cfbfc701746345038a83e6f85930 100644 (file)
@@ -11,6 +11,7 @@ const { Address4, Address6 } = require('ip-address');
 const dns = require('dns');
 const common = require('./common');
 const Enum = require('./enum');
+const { Microformat2: { Relation: MF2Rel } } = Enum;
 const { ValidationError } = require('./errors');
 const { fileScope } = require('@squeep/log-helper');
 
@@ -412,15 +413,15 @@ class Communication {
        * call would already have failed.
        */
       address = new Address6(urlObj.hostname.slice(1, urlObj.hostname.length - 1));
-      /* succeeded parsing as ipv6, reject unless loopback */
+      /* Succeeded parsing as ipv6, reject unless loopback */
       urlObj.isLoopback = address.isLoopback();
     } else {
       try {
         address = new Address4(urlObj.hostname);
-        /* succeeded parsing as ipv4, reject unless loopback */
+        /* Succeeded parsing as ipv4, reject unless loopback */
         urlObj.isLoopback = address.isInSubnet(loopback4);
       } catch (e) {
-        /* did not parse as ip, carry on */
+        /* Did not parse as ip, carry on */
       }
     }
 
@@ -447,12 +448,12 @@ class Communication {
         throw new ValidationError('could not resolve hostname');
       }
 
-      // extract each resolution value, array of {address,family}
+      // Extract each resolution value, array of {address,family}
       const resolutions = settledResolutions.map((resolution) => resolution.value);
 
       // If there were two resolutions, ensure they returned identical results.
       if (resolutions.length > 1) {
-        // create set of addresses for each resolution
+        // Create set of addresses for each resolution
         const addressSets = resolutions.map((addrs) => {
           return new Set((addrs || []).map((a) => a.address));
         });
@@ -498,10 +499,11 @@ class Communication {
     const _scope = _fileScope('validateProfile');
     const errorScope = 'invalid profile url';
 
-    const options = Object.assign({
+    const options = {
       allowLoopback: false,
       resolveHostname: false,
-    }, validationOptions);
+      ...validationOptions,
+    };
 
     let profile;
     try {
@@ -539,10 +541,11 @@ class Communication {
     const _scope = _fileScope('validateClientIdentifier');
     const errorScope = 'invalid client identifier url';
 
-    const options = Object.assign({
+    const options = {
       allowLoopback: true,
       resolveHostname: true,
-    }, validationOptions);
+      ...validationOptions,
+    };
 
     let clientId;
     try {
@@ -579,17 +582,13 @@ class Communication {
    * @returns {Promise<ClientIdentifierData|undefined>} mf2 data filtered for h-app items, or undefined if url could not be fetched
    */
   async fetchClientIdentifier(urlObj) {
-    const _scope = _fileScope('fetchClientIdentifier');
-
-    // Loopback address will eschew client fetch, return empty data.
-    const isLoopbackResult = {
-      rels: {},
-      items: [],
-    };
-
     // Set by validation method in case of loopback ip hostname
     if (urlObj.isLoopback) {
-      return isLoopbackResult;
+      // Loopback address will eschew client fetch, return empty data.
+      return {
+        rels: {},
+        items: [],
+      };
     }
 
     const mfData = await this.fetchMicroformat(urlObj);
@@ -668,12 +667,14 @@ class Communication {
       metadata: {},
     };
 
-    // Locate h-card mf2 items with url field matching profile url,
-    // and populate profile fields with first-encountered card values.
+    /**
+     * Locate h-card mf2 items with url field matching profile url,
+     * and populate profile fields with first-encountered card values.
+     */
     if (mfData && 'items' in mfData) {
       const hCards = mfData.items.filter((item) =>
         item?.type?.includes('h-card') &&
-        item.properties && item.properties.url && item.properties.url.includes(urlObj.href));
+        item?.properties?.url?.includes(urlObj.href));
       hCards.forEach((hCard) => {
         Object.keys(profile).forEach((key) => {
           if (!profile[key] && key in hCard.properties) { // eslint-disable-line security/detect-object-injection
@@ -686,9 +687,9 @@ class Communication {
     // Populate legacy mf2 fields from relation links.
     // These will be overwritten if they also exist in server metadata.
     Object.entries({
-      authorizationEndpoint: 'authorization_endpoint', // backwards compatibility
-      tokenEndpoint: 'token_endpoint', // backwards compatibility
-      ticketEndpoint: 'ticket_endpoint', // backwards compatibility
+      authorizationEndpoint: MF2Rel.AuthorizationEndpoint, // Backwards compatibility
+      tokenEndpoint: MF2Rel.TokenEndpoint, // Backwards compatibility
+      ticketEndpoint: MF2Rel.TicketEndpoint, // Backwards compatibility
     }).forEach(([p, r]) => {
       if (mfData && r in mfData.rels) {
         profile.metadata[p] = profile[p] = mfData.rels[r][0]; // eslint-disable-line security/detect-object-injection
@@ -696,8 +697,8 @@ class Communication {
     });
 
     // Set metadata field.
-    if (mfData && 'indieauth-metadata' in mfData.rels) {
-      profile.indieauthMetadata = mfData.rels['indieauth-metadata'][0];
+    if (mfData && MF2Rel.IndieauthMetadata in mfData.rels) {
+      profile.indieauthMetadata = mfData.rels[MF2Rel.IndieauthMetadata][0];
     }
 
     // Attempt to populate metadata from authorization server.
@@ -841,7 +842,7 @@ class Communication {
 
     try {
       const response = await this.got(postIntrospectConfig);
-      // check status
+      // Check status
       try {
         const {
           active,
@@ -920,7 +921,7 @@ class Communication {
     let metadataUrl, tokenUrl;
     if (urlObj) {
       const mfData = await this.fetchMicroformat(urlObj);
-      const metadataRel = mfData?.rels?.['indieauth-metadata']?.[0];
+      const metadataRel = mfData?.rels?.[MF2Rel.IndieauthMetadata]?.[0];
       if (metadataRel) {
         try {
           metadataUrl = new URL(metadataRel);
@@ -929,8 +930,8 @@ class Communication {
         }
       }
       if (!metadataUrl) {
-        // no metadata rel, try old-style token endpoint
-        const tokenRel = mfData?.rels?.['token_endpoint']?.[0];
+        // No metadata rel, try old-style token endpoint
+        const tokenRel = mfData?.rels?.[MF2Rel.TokenEndpoint]?.[0];
         if (tokenRel) {
           try {
             tokenUrl = new URL(tokenRel);