'use strict';
const { TemplateHelper: th } = require('@squeep/html-template-helper');
+const { sessionNavLinks } = require('./helpers');
/**
* Login form.
const showIndieAuthForm = options.authnEnabled.includes('indieAuth');
return showIndieAuthForm ? `\t\t\t<section class="indieauth">
\t\t\t\t<h2>Login</h2>
-\t\t\t\t<form action="" method="POST">
+\t\t\t\t<form method="POST">
\t\t\t\t\t<fieldset>
\t\t\t\t\t\t<legend>IndieAuth</legend>
\t\t\t\t\t\t<label for="me">Profile URL:</label>
\t\t\t\t\t\t<input id="me" name="me" type="url" size="40" placeholder="https://example.com/my_profile_url" value="" autofocus>
-\t\t\t\t\t\t<button>Login</button>
+\t\t\t\t\t\t<input type="hidden" name="me_auto_scheme">
+\t\t\t\t\t\t<button type="submit">Login</button>
${indieAuthBlurb}
\t\t\t\t\t</fieldset>
\t\t\t\t</form>
}
-const userAuthn = ['argon2', 'pam', 'DEBUG_ANY'];
+/**
+ * Default all URL inputs to https if scheme not specified,
+ * and set a flag if that happened.
+ * From https://aaronparecki.com/2019/05/13/2/https
+ */
+function indieAuthURLTrySecureFirstScript(ctx, options) {
+ const showIndieAuthForm = options.authnEnabled.includes('indieAuth');
+ return showIndieAuthForm ? `
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+ function addDefaultScheme(target) {
+ if (target.value.match(/^(?!https?:).+\\..+/)) {
+ const autoSchemeField = document.querySelector('input[name=' + target.getAttribute('name') + '_auto_scheme]');
+ let scheme;
+ if (autoSchemeField) {
+ scheme = 'https://';
+ autoSchemeField.value = '1';
+ } else {
+ scheme = 'http://';
+ }
+ target.value = scheme + target.value;
+ }
+ }
+ const elements = document.querySelectorAll('input[type=url]');
+ Array.prototype.forEach.call(elements, function (el, i) {
+ el.addEventListener('blur', function(e) {
+ addDefaultScheme(e.target);
+ });
+ el.addEventListener('keydown', function(e) {
+ if (e.keyCode === 13) {
+ addDefaultScheme(e.target);
+ }
+ });
+ });
+});
+</script>` : '';
+}
+
+const userAuthn = ['argon2', 'pam'];
function userSection(ctx, options) {
const userBlurb = (options.userBlurb || []).map((x) => '\t'.repeat(6) + x).join('\n');
const secure = (ctx.clientProtocol || '').toLowerCase() === 'https';
const showUserForm = options.authnEnabled.filter((x) => userAuthn.includes(x)).length
&& (secure || !options.secureAuthOnly);
return showUserForm ? `\t\t\t<section class="user">
-\t\t\t\t<form action="" method="POST">
+\t\t\t\t<form method="POST">
\t\t\t\t\t<fieldset>
\t\t\t\t\t\t<legend>User Account</legend>
\t\t\t\t\t\t<label for="identifier">Username:</label>
-\t\t\t\t\t\t<input id="identifier" name="identifier" value="">
+\t\t\t\t\t\t<input id="identifier" name="identifier" type="text" value="">
\t\t\t\t\t\t<br>
\t\t\t\t\t\t<label for="credential">Password:</label>
\t\t\t\t\t\t<input id="credential" name="credential" type="password" value="">
\t\t\t\t\t\t<br>
-\t\t\t\t\t\t<button>Login</button>
+\t\t\t\t\t\t<button type="submit">Login</button>
${userBlurb}
\t\t\t\t\t</fieldset>
\t\t\t\t</form>
* @param {String=} options.manager.logoUrl
* @param {Object} options.dingus
* @param {String} options.dingus.selfBaseUrl
+ * @param {() => {}} appCb
* @returns {String}
*/
-module.exports = (ctx, options) => {
+module.exports = (ctx, options, appCb = () => {}) => {
+ const pagePathLevel = 1;
const htmlOptions = {
+ pageIdentifier: 'login',
pageTitle: options.manager.pageTitle,
logoUrl: options.manager.logoUrl,
footerEntries: options.manager.footerEntries,
indieAuthBlurb: options.authenticator.indieAuthBlurb,
userBlurb: options.authenticator.userBlurb,
};
+ appCb(pagePathLevel, ctx, htmlOptions);
+ sessionNavLinks(pagePathLevel, ctx, htmlOptions);
const mainContent = [
...(options.authenticator.loginBlurb || []),
+ indieAuthURLTrySecureFirstScript(ctx, htmlOptions),
indieAuthSection(ctx, htmlOptions),
userSection(ctx, htmlOptions),
];
- return th.htmlPage(2, ctx, htmlOptions, mainContent);
+ return th.htmlPage(pagePathLevel, ctx, htmlOptions, mainContent);
};
\ No newline at end of file