update dependencies and devDependencies, address lint issues
[squeep-indie-auther] / src / template / authorization-request-html.js
index bb3d70118d1ebfbdef04814ad4328a60913c0e83..b23fb9207665077ce54743e39563ff3fe2b9e4a8 100644 (file)
@@ -4,13 +4,13 @@ const th = require('./template-helper');
 const { sessionNavLinks } = require('@squeep/authentication-module');
 
 /**
- * @param {Object} hApp
- * @param {Object} hApp.properties
- * @param {String[]=} hApp.properties.url
- * @param {String[]=} hApp.properties.summary
- * @param {String[]=} hApp.properties.logo
- * @param {String[]=} hApp.properties.name
- * @returns {String}
+ * @param {object} hApp client identifier h-app
+ * @param {object} hApp.properties properties
+ * @param {string[]=} hApp.properties.url url
+ * @param {string[]=} hApp.properties.summary summary
+ * @param {string[]=} hApp.properties.logo logo
+ * @param {string[]=} hApp.properties.name name
+ * @returns {string} span
  */
 function renderClientIdentifierProperties(hApp) {
   const properties = hApp.properties || {};
@@ -47,9 +47,9 @@ function renderClientIdentifierProperties(hApp) {
 
 
 /**
- * @param {Object} clientIdentifier 
- * @param {Object[]} clientIdentifier.items
- * @returns {String}
+ * @param {object} clientIdentifier client identifier
+ * @param {object[]} clientIdentifier.items items
+ * @returns {string} spans
  */
 function renderClientIdentifier(clientIdentifier) {
   const hAppEntries = clientIdentifier?.items || [];
@@ -58,9 +58,9 @@ function renderClientIdentifier(clientIdentifier) {
 
 
 /**
- * @param {String} profile
- * @param {Boolean} selected
- * @returns {String}
+ * @param {string} profile profile
+ * @param {boolean} selected is selected
+ * @returns {string} option
  */
 function renderProfileOption(profile, selected) {
   return `<option value="${profile}"${selected ? ' selected' : ''}>${profile}</option>`;
@@ -68,9 +68,9 @@ function renderProfileOption(profile, selected) {
 
 
 /**
- * @param {String[]} availableProfiles
- * @param {String} hintProfile
- * @returns {String}
+ * @param {string[]} availableProfiles profiles
+ * @param {string} hintProfile profile
+ * @returns {string} fieldset
  */
 function renderProfileFieldset(availableProfiles, hintProfile) {
   if (!availableProfiles || availableProfiles.length <= 1) {
@@ -93,12 +93,16 @@ ${availableProfiles.map((profile) => renderProfileOption(profile, profile === hi
 
 
 /**
- * @param {ScopeDetails} scope
- * @param {String} scope.scope
- * @param {String} scope.description
- * @param {String[]} scope.profiles
- * @param {Boolean} checked
- * @returns {String}
+ * @typedef {object} ScopeDetails
+ * @property {string} scope scope
+ * @property {string} description description
+ * @property {string[]} profiles profiles
+ */
+
+/**
+ * @param {ScopeDetails} scope scope details
+ * @param {boolean} checked is checked
+ * @returns {string} scope li
  */
 function renderScopeCheckboxLI(scope, checked) {
   let scopeDescription;
@@ -116,12 +120,17 @@ function renderScopeCheckboxLI(scope, checked) {
   }
   return `
         <li class="${profileClass}">
-          <input type="checkbox" id="scope_${scope.scope}" name="accepted_scopes" value="${scope.scope}"${checked ? ' checked' : ''}>
+          <input type="checkbox" id="scope_${scope.scope}" name="accepted_scopes[]" value="${scope.scope}"${checked ? ' checked' : ''}>
           <label for="scope_${scope.scope}">${scope.scope}</label>${scopeDescription}
         </li>`;
 }
 
 
+/**
+ *
+ * @param {ScopeDetails[]=} requestedScopes scope details
+ * @returns {string} fieldset
+ */
 function renderRequestedScopes(requestedScopes) {
   if (!requestedScopes?.length) {
     return '';
@@ -140,8 +149,8 @@ ${requestedScopes.map((scopeDetails) => renderScopeCheckboxLI(scopeDetails, true
 }
 
 /**
- * @param {ScopeDetails[]} additionalScopes
- * @returns {String}
+ * @param {ScopeDetails[]} additionalScopes scopes
+ * @returns {string} fieldset
  */
 function renderAdditionalScopes(additionalScopes) {
   const parts = [];
@@ -165,7 +174,7 @@ ${additionalScopes.map((scopeDetails) => renderScopeCheckboxLI(scopeDetails, fal
       You may also specify a space-separated list of any additional ad hoc scopes you would like to associate with this authorization request, which were not explicitly requested by the client application.
     </div>
     <label for="ad-hoc-scopes">Ad Hoc Scopes</label>
-    <input id="ad-hoc-scopes" name="ad_hoc_scopes" value="">
+    <input type="text" id="ad-hoc-scopes" name="ad_hoc_scopes" value="">
   </fieldset>`);
   return parts.join('');
 }
@@ -173,6 +182,8 @@ ${additionalScopes.map((scopeDetails) => renderScopeCheckboxLI(scopeDetails, fal
 
 /**
  * 
+ * @param {string[]} requestedScopes scopes
+ * @returns {string} fieldset
  */
 function renderExpiration(requestedScopes) {
   const tokenableScopes = requestedScopes.filter((s) => !['profile', 'email'].includes(s));
@@ -189,18 +200,10 @@ function renderExpiration(requestedScopes) {
 \t\t<br>
 \t\t<details>
 \t\t\t<summary>Set Expiration</summary>
-\t\t\t<div>
 \t\t\t\t${radioButton('expires', 'never', 'Never', true)}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('expires', '1d', '1 Day')}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('expires', '1w', '1 Week')}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('expires', '1m', '1 Month')}
-\t\t\t</div>
 \t\t\t<div>
 \t\t\t\t${radioButton('expires', 'custom', 'Other:')}
 \t\t\t\t<input type="number" id="expires-seconds" name="expires-seconds">
@@ -210,26 +213,28 @@ function renderExpiration(requestedScopes) {
 \t\t\t<div>
 \t\t\t\tTokens with expirations may be allowed to be renewed for a fresh token for an amount of time after they expire.
 \t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('refresh', 'none', 'Not Refreshable', true)}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('refresh', '1d', '1 Day')}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('refresh', '1w', '1 Week')}
-\t\t\t</div>
-\t\t\t<div>
 \t\t\t\t${radioButton('refresh', '1m', '1 Month')}
 \t\t\t<div>
 \t\t\t\t${radioButton('refresh', 'custom', 'Other:')}
 \t\t\t\t<input type="number" id="refresh-seconds" name="refresh-seconds">
 \t\t\t\t<label for="refresh-seconds">seconds</label>
-\t\t\t </div>
+\t\t\t</div>
 \t\t</details>
 \t</fieldset>`;
 }
 
+/**
+ *
+ * @param {string} name name
+ * @param {string} value value
+ * @param {string} label label
+ * @param {boolean} checked is checked
+ * @param {number} indent indent
+ * @returns {string} div
+ */
 function radioButton(name, value, label, checked = false, indent = 0) {
   const id = `${name}-${value}`;
   return th.indented(indent, [
@@ -240,27 +245,31 @@ function radioButton(name, value, label, checked = false, indent = 0) {
   ]).join('');
 }
 
+/**
+ * @alias {object} ScopeIndex
+ */
+
 /**
  * 
- * @param {Object} ctx
- * @param {Object[]} ctx.notifications
- * @param {Object} ctx.session
- * @param {String[]=} ctx.session.scope
- * @param {URL=} ctx.session.me
- * @param {String[]} ctx.session.profiles
- * @param {ScopeIndex} ctx.session.scopeIndex
- * @param {Object} ctx.session.clientIdentifier
- * @param {Object[]} ctx.session.clientIdentifier.items
- * @param {Object} ctx.session.clientIdentifier.items.properties
- * @param {String[]=} ctx.session.clientIdentifier.items.properties.url
- * @param {String[]=} ctx.session.clientIdentifier.items.properties.summary
- * @param {String[]=} ctx.session.clientIdentifier.items.properties.logo
- * @param {String[]=} ctx.session.clientIdentifier.items.properties.name
- * @param {String} ctx.session.clientId
- * @param {String} ctx.session.persist
- * @param {String} ctx.session.redirectUri
- * @param {Object} options
- * @returns {String}
+ * @param {object} ctx context
+ * @param {object[]} ctx.notifications notifications
+ * @param {object} ctx.session session
+ * @param {string[]=} ctx.session.scope scopes
+ * @param {URL=} ctx.session.me profile
+ * @param {string[]} ctx.session.profiles profiles
+ * @param {ScopeIndex} ctx.session.scopeIndex scopes structure
+ * @param {object} ctx.session.clientIdentifier client identifier
+ * @param {object[]} ctx.session.clientIdentifier.items items
+ * @param {object} ctx.session.clientIdentifier.items.properties properties
+ * @param {string[]=} ctx.session.clientIdentifier.items.properties.url url
+ * @param {string[]=} ctx.session.clientIdentifier.items.properties.summary sumamry
+ * @param {string[]=} ctx.session.clientIdentifier.items.properties.logo logo
+ * @param {string[]=} ctx.session.clientIdentifier.items.properties.name name
+ * @param {string} ctx.session.clientId client id
+ * @param {string} ctx.session.persist persist
+ * @param {string} ctx.session.redirectUri redirect
+ * @param {object} options options
+ * @returns {string} section
  */
 function mainContent(ctx, options) { // eslint-disable-line no-unused-vars
   const session = ctx.session || {};
@@ -298,9 +307,7 @@ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars
 
   return [
     `<section class="information">
-\tThe application client
-\t${renderClientIdentifier(session.clientIdentifier)}
-\tat <a class="uri" name="${session.clientId}">${session.clientId}</a> would like to identify you as <a class="uri" name="${hintedProfile}">${hintedProfile}</a>.
+\tThe application client ${renderClientIdentifier(session.clientIdentifier)} at <a class="uri" aria-label="client-identifier" id="${session.clientId}">${session.clientId}</a> would like to identify you as <a class="uri" aria-label="profile"${hintedProfile ? ' id="' + hintedProfile + '"' : ''}>${hintedProfile || '(unspecified)'}</a>.
 </section>
 <section class="choices">
 \t<form action="consent" method="POST" class="form-consent">`,
@@ -312,14 +319,14 @@ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars
 \t\t<br>
 \t\t<fieldset>
 \t\t\t<legend>Do you want to allow this?</legend>
-\t\t\t<button class="button-accept" name="accept" value="true">Accept</button>
-\t\t\t<button class="button-decline" name="accept" value="false">Decline</button>
+\t\t\t<button type="submit" class="button-accept" name="accept" value="true">Accept</button>
+\t\t\t<button type="submit" class="button-decline" name="accept" value="false">Decline</button>
 \t\t</fieldset>
 \t\t<input type="hidden" name="session" value="${session.persist}">
 \t</form>
 \t<br>
 \t<div>
-\t\tYou will be redirected to <a class="uri" name="${session.redirectUri}">${session.redirectUri}</a>.
+\t\tYou will be redirected to <a class="uri" id="${session.redirectUri ? session.redirectUri : 'unknown-redirect'}">${session.redirectUri}</a>.
 \t</div>
 </section>`,
   ];
@@ -327,21 +334,21 @@ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars
 
 /**
  * 
- * @param {Object} ctx
- * @param {Object} ctx.session
- * @param {String[]=} ctx.session.scope
- * @param {URL=} ctx.session.me
- * @param {String[]} ctx.session.profiles
- * @param {ScopeIndex} ctx.session.scopeIndex
- * @param {Object} ctx.session.clientIdentifier
- * @param {String} ctx.session.clientId
- * @param {String} ctx.session.persist
- * @param {String} ctx.session.redirectUri
- * @param {Object} options
- * @param {Object} options.manager
- * @param {String} options.manager.pageTitle
- * @param {String} options.manager.footerEntries
- * @returns {String}
+ * @param {object} ctx context
+ * @param {object} ctx.session session object
+ * @param {string[]=} ctx.session.scope scopes
+ * @param {URL=} ctx.session.me url
+ * @param {string[]} ctx.session.profiles profiles
+ * @param {ScopeIndex} ctx.session.scopeIndex scopes structure
+ * @param {object} ctx.session.clientIdentifier client identifier
+ * @param {string} ctx.session.clientId client id
+ * @param {string} ctx.session.persist persist
+ * @param {string} ctx.session.redirectUri redirect url
+ * @param {object} options options
+ * @param {object} options.manager manager options
+ * @param {string} options.manager.pageTitle page title
+ * @param {string} options.manager.footerEntries footer entries
+ * @returns {string} page
  */
 module.exports = (ctx, options) => {
   const pagePathLevel = 0;