mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
docs: Make registration form self-explanatory.
This commit is contained in:
parent
e99f670252
commit
969bb0ee6c
@ -31,13 +31,16 @@ export function throwIdpInteractionError(error: unknown, prefilled: Record<strin
|
|||||||
* @param confirmPassword - Confirmation of password to match.
|
* @param confirmPassword - Confirmation of password to match.
|
||||||
*/
|
*/
|
||||||
export function assertPassword(password: any, confirmPassword: any): asserts password is string {
|
export function assertPassword(password: any, confirmPassword: any): asserts password is string {
|
||||||
assert(typeof password === 'string' && password.length > 0, 'Password required');
|
assert(
|
||||||
|
typeof password === 'string' && password.length > 0,
|
||||||
|
'Please enter a password.',
|
||||||
|
);
|
||||||
assert(
|
assert(
|
||||||
typeof confirmPassword === 'string' && confirmPassword.length > 0,
|
typeof confirmPassword === 'string' && confirmPassword.length > 0,
|
||||||
'Password confirmation required',
|
'Please confirm your password.',
|
||||||
);
|
);
|
||||||
assert(
|
assert(
|
||||||
password === confirmPassword,
|
password === confirmPassword,
|
||||||
'Password and confirmation do not match',
|
'Your password and confirmation did not match.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -193,14 +193,12 @@ export class RegistrationHandler extends HttpHandler {
|
|||||||
*/
|
*/
|
||||||
private async parseInput(request: HttpRequest): Promise<ParsedInput> {
|
private async parseInput(request: HttpRequest): Promise<ParsedInput> {
|
||||||
const parsed = await getFormDataRequestBody(request);
|
const parsed = await getFormDataRequestBody(request);
|
||||||
let prefilled: Record<string, string> = {};
|
const prefilled: Record<string, string> = {};
|
||||||
try {
|
try {
|
||||||
for (const key of Object.keys(parsed)) {
|
for (const [ key, value ] of Object.entries(parsed)) {
|
||||||
if (Array.isArray(parsed[key])) {
|
assert(!Array.isArray(value), `Unexpected multiple values for ${key}.`);
|
||||||
throw new Error(`Multiple values found for key ${key}`);
|
prefilled[key] = value ? value.trim() : '';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
prefilled = parsed as Record<string, string>;
|
|
||||||
return this.validateInput(prefilled);
|
return this.validateInput(prefilled);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
throwIdpInteractionError(err, prefilled);
|
throwIdpInteractionError(err, prefilled);
|
||||||
@ -212,54 +210,38 @@ export class RegistrationHandler extends HttpHandler {
|
|||||||
* Verifies that all the data combinations make sense.
|
* Verifies that all the data combinations make sense.
|
||||||
*/
|
*/
|
||||||
private validateInput(parsed: NodeJS.Dict<string>): ParsedInput {
|
private validateInput(parsed: NodeJS.Dict<string>): ParsedInput {
|
||||||
const { email, password, confirmPassword, podName, webId, template, createWebId, register, createPod } = parsed;
|
const { email, password, confirmPassword, webId, podName, register, createPod, createWebId, template } = parsed;
|
||||||
|
|
||||||
assert(typeof email === 'string' && email.length > 0 && emailRegex.test(email),
|
// Parse email
|
||||||
'A valid e-mail address is required');
|
assert(typeof email === 'string' && emailRegex.test(email), 'Please enter a valid e-mail address.');
|
||||||
|
|
||||||
const result: ParsedInput = {
|
const validated: ParsedInput = {
|
||||||
email,
|
email,
|
||||||
template,
|
template,
|
||||||
|
register: Boolean(register) || Boolean(createWebId),
|
||||||
|
createPod: Boolean(createPod) || Boolean(createWebId),
|
||||||
createWebId: Boolean(createWebId),
|
createWebId: Boolean(createWebId),
|
||||||
register: Boolean(register),
|
|
||||||
createPod: Boolean(createPod),
|
|
||||||
};
|
};
|
||||||
|
assert(validated.register || validated.createPod, 'Please register for a WebID or create a Pod.');
|
||||||
|
|
||||||
const validWebId = typeof webId === 'string' && webId.length > 0;
|
// Parse WebID
|
||||||
if (result.createWebId) {
|
if (!validated.createWebId) {
|
||||||
if (validWebId) {
|
assert(typeof webId === 'string' && /^https?:\/\/[^/]+/u.test(webId), 'Please enter a valid WebID.');
|
||||||
throw new Error('A WebID should only be provided when no new one is being created');
|
validated.webId = webId;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!validWebId) {
|
|
||||||
throw new Error('A WebID is required if no new one is being created');
|
|
||||||
}
|
|
||||||
result.webId = webId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.register) {
|
// Parse Pod name
|
||||||
|
if (validated.createWebId || validated.createPod) {
|
||||||
|
assert(typeof podName === 'string' && podName.length > 0, 'Please specify a Pod name.');
|
||||||
|
validated.podName = podName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse account
|
||||||
|
if (validated.register) {
|
||||||
assertPassword(password, confirmPassword);
|
assertPassword(password, confirmPassword);
|
||||||
result.password = password;
|
validated.password = password;
|
||||||
} else if (typeof password === 'string' && password.length > 0) {
|
|
||||||
throw new Error('A password should only be provided when registering');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.createWebId || result.createPod) {
|
return validated;
|
||||||
assert(typeof podName === 'string' && podName.length > 0,
|
|
||||||
'A pod name is required when creating a pod and/or WebID');
|
|
||||||
result.podName = podName;
|
|
||||||
} else if (typeof podName === 'string' && podName.length > 0) {
|
|
||||||
throw new Error('A pod name should only be provided when creating a pod and/or WebID');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.createWebId && !(result.register && result.createPod)) {
|
|
||||||
throw new Error('Creating a WebID is only possible when also registering and creating a pod');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result.createWebId && !result.register && !result.createPod) {
|
|
||||||
throw new Error('At least one option needs to be chosen');
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
<legend>Your account</legend>
|
||||||
<ol>
|
<ol>
|
||||||
<li>
|
<li>
|
||||||
<label for="email">Email</label>
|
<label for="email">Email</label>
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% if (createPod) { %>
|
<% if (createPod) { %>
|
||||||
<h2>Your new pod</h2>
|
<h2>Your new Pod</h2>
|
||||||
<p>
|
<p>
|
||||||
Your new pod is located at <a href="<%= podBaseUrl %>" class="link"><%= podBaseUrl %></a>.
|
Your new Pod is located at <a href="<%= podBaseUrl %>" class="link"><%= podBaseUrl %></a>.
|
||||||
<br>
|
<br>
|
||||||
You can store your documents and data there.
|
You can store your documents and data there.
|
||||||
</p>
|
</p>
|
||||||
@ -37,18 +37,18 @@
|
|||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (register) { %>
|
<% if (register) { %>
|
||||||
<h2>Your new login</h2>
|
<h2>Your new account</h2>
|
||||||
<p>
|
<p>
|
||||||
You can <a href="./login">log in</a>
|
Via your email address <em><%= email %></em>,
|
||||||
with your WebID <a href="<%= webId %>" class="link"><%= webId %></a>
|
this server lets you <a href="./login">log in</a> to Solid apps
|
||||||
on this server via your email address <em><%= email %></em>.
|
with your WebID <a href="<%= webId %>" class="link"><%= webId %></a>
|
||||||
</p>
|
</p>
|
||||||
<% if (!createWebId) { %>
|
<% if (!createWebId) { %>
|
||||||
<p>
|
<p>
|
||||||
You will need to add the triple
|
You will need to add the triple
|
||||||
<code><%= `<${webId}> <http://www.w3.org/ns/solid/terms#oidcIssuer> <${oidcIssuer}>.`%></code>
|
<code><%= `<${webId}> <http://www.w3.org/ns/solid/terms#oidcIssuer> <${oidcIssuer}>.`%></code>
|
||||||
to your existing WebID document <em><%= webId %></em>
|
to your existing WebID document <em><%= webId %></em>
|
||||||
to indicate that you trust this server as a login provider for your WebID.
|
to indicate that you trust this server as a login provider.
|
||||||
</p>
|
</p>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -12,58 +12,195 @@
|
|||||||
<h1>Community Solid Server</h1>
|
<h1>Community Solid Server</h1>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<h1>Sign up for an account</h1>
|
<h1>Sign up</h1>
|
||||||
<form action="/idp/register" method="post">
|
<form action="/idp/register" method="post" id="mainForm">
|
||||||
|
<% const isBlankForm = !('email' in prefilled); %>
|
||||||
|
|
||||||
<%if (errorMessage) { %>
|
<% if (errorMessage) { %>
|
||||||
<p class="error">Error: <%= errorMessage %></p>
|
<p class="error">Error: <%= errorMessage %></p>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
<legend>Your WebID</legend>
|
||||||
|
<p>
|
||||||
|
A <em>WebID</em> is a unique identifier for you
|
||||||
|
in the form of a URL.
|
||||||
|
<br>
|
||||||
|
You WebID lets you log in to Solid apps
|
||||||
|
and access non-public data in Pods.
|
||||||
|
</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>
|
<li class="radio">
|
||||||
<label for="email">Email</label>
|
<label>
|
||||||
<input id="email" type="text" name="email" autofocus <% if (prefilled.email) { %> value="<%= prefilled.email %>" <% } %> />
|
<input type="radio" id="createWebIdOn" name="createWebId" value="on"<%
|
||||||
|
if (isBlankForm || prefilled.createWebId) { %> checked<% } %>>
|
||||||
|
Create a new WebID for my Pod.
|
||||||
|
</label>
|
||||||
|
<p id="createWebIdForm">
|
||||||
|
Please also create a Pod below, since your WebID will be stored there.
|
||||||
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="radio">
|
||||||
<label for="password">Password</label>
|
<label>
|
||||||
<input id="password" type="password" name="password" />
|
<input type="radio" id="createWebIdOff" name="createWebId" value=""<%
|
||||||
</li>
|
if (!isBlankForm && !prefilled.createWebId) { %> checked<% } %>>
|
||||||
<li>
|
Use my existing WebID to access my Pod.
|
||||||
<label for="confirmPassword">Confirm password</label>
|
</label>
|
||||||
<input id="confirmPassword" type="password" name="confirmPassword" />
|
<ol id="existingWebIdForm">
|
||||||
|
<li>
|
||||||
|
<label for="webId">Existing WebID:</label>
|
||||||
|
<input id="webId" type="text" name="webId" value="<%= prefilled.webId || '' %>">
|
||||||
|
</li>
|
||||||
|
<li class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="register" name="register"<%
|
||||||
|
if (isBlankForm || prefilled.register) { %> checked<% } %>>
|
||||||
|
Use my new account to log in with this WebID.
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
<legend>Your Pod</legend>
|
||||||
|
<p>
|
||||||
|
A Pod is a place to store your data.
|
||||||
|
<br>
|
||||||
|
If you create a new WebID, you must also create a Pod to store that WebID.
|
||||||
|
</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li class="checkbox">
|
<li class="checkbox">
|
||||||
<label><input type="checkbox" name="createWebId" checked>Create a new WebID <em>(requires the other two options)</em></label>
|
<label>
|
||||||
</li>
|
<input type="checkbox" id="createPod" name="createPod"<%
|
||||||
<li class="checkbox">
|
if (isBlankForm || prefilled.createPod) { %> checked<% } %>>
|
||||||
<label><input type="checkbox" name="register" checked>Register your WebID with the IDP</label>
|
Create a new Pod with my WebID as owner.
|
||||||
<ol>
|
</label>
|
||||||
|
<ol id="createPodForm">
|
||||||
<li>
|
<li>
|
||||||
<label for="webId">Alternatively, existing WebID</label>
|
<label for="podName">Pod name:</label>
|
||||||
<input id="webId" type="text" name="webId" <% if (prefilled.webId) { %> value="<%= prefilled.webId %>" <% } %> />
|
<input id="podName" type="text" name="podName" <%
|
||||||
</li>
|
if (prefilled.podName) { %> value="<%= prefilled.podName %>" <% } %>>
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
<li class="checkbox">
|
|
||||||
<label><input type="checkbox" name="createPod" checked>Create a new pod</label>
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<label for="podName">Pod name</label>
|
|
||||||
<input id="podName" type="text" name="podName" <% if (prefilled.podName) { %> value="<%= prefilled.podName %>" <% } %> />
|
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Your account</legend>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Choose the credentials you want to use to log in to this server in the future.
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<label for="email">Email:</label>
|
||||||
|
<input id="email" type="text" name="email" <%
|
||||||
|
if (prefilled.email) { %> value="<%= prefilled.email %>" <% } %>>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<ol id="passwordForm">
|
||||||
|
<li>
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input id="password" type="password" name="password">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="confirmPassword">Confirm password:</label>
|
||||||
|
<input id="confirmPassword" type="password" name="confirmPassword">
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div id="noPasswordForm" class="hidden">
|
||||||
|
<p>
|
||||||
|
Since you will be using your existing WebID setup to access your pod,
|
||||||
|
<br>
|
||||||
|
you do <em>not</em> need to set a password.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<p class="actions"><button type="submit" name="submit">Sign up</button></p>
|
<p class="actions"><button type="submit" name="submit">Sign up</button></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Assist the user with filling out the form by hiding irrelevant fields
|
||||||
|
(() => {
|
||||||
|
// Wire up the UI elements
|
||||||
|
const elements = {};
|
||||||
|
[
|
||||||
|
'createWebIdOn', 'createWebIdOff', 'createWebIdForm', 'existingWebIdForm', 'webId',
|
||||||
|
'createPod', 'createPodForm', 'podName',
|
||||||
|
'register', 'passwordForm', 'noPasswordForm', 'mainForm',
|
||||||
|
].forEach(id => {
|
||||||
|
elements[id] = document.getElementById(id);
|
||||||
|
elements[id].addEventListener('change', updateUI);
|
||||||
|
});
|
||||||
|
updateUI();
|
||||||
|
mainForm.classList.add('loaded');
|
||||||
|
|
||||||
|
// Updates the UI when something has changed
|
||||||
|
function updateUI({ srcElement } = {}) {
|
||||||
|
// When Pod creation is required, automatically tick the corresponding checkbox
|
||||||
|
if (elements.createWebIdOn.checked)
|
||||||
|
elements.createPod.checked = true;
|
||||||
|
elements.createPod.disabled = elements.createWebIdOn.checked;
|
||||||
|
|
||||||
|
// Hide irrelevant fields
|
||||||
|
setVisibility('createWebIdForm', elements.createWebIdOn.checked);
|
||||||
|
setVisibility('existingWebIdForm', elements.createWebIdOff.checked);
|
||||||
|
setVisibility('createPodForm', elements.createPod.checked);
|
||||||
|
setVisibility('passwordForm', elements.createWebIdOn.checked || elements.register.checked);
|
||||||
|
setVisibility('noPasswordForm', !isVisible('passwordForm'));
|
||||||
|
|
||||||
|
// If child elements have just been activated, focus on them
|
||||||
|
if (srcElement?.checked) {
|
||||||
|
switch(document.activeElement) {
|
||||||
|
case elements.createWebIdOff:
|
||||||
|
const { webId } = elements;
|
||||||
|
webId.value = webId.value.startsWith('http') ? webId.value : 'https://';
|
||||||
|
webId.focus();
|
||||||
|
break;
|
||||||
|
case elements.createPod:
|
||||||
|
elements.podName.focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether the given element is visible
|
||||||
|
function isVisible(element) {
|
||||||
|
return !(elements[element] ?? element).classList.contains('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the visibility of the given element
|
||||||
|
function setVisibility(element, visible) {
|
||||||
|
// Show or hide the element
|
||||||
|
element = elements[element] ?? element;
|
||||||
|
element.classList[visible ? 'remove' : 'add']('hidden');
|
||||||
|
|
||||||
|
// Disable children of hidden elements,
|
||||||
|
// such that the browser does not expect input for them
|
||||||
|
for (const child of getDescendants(element)) {
|
||||||
|
if ('disabled' in child)
|
||||||
|
child.disabled = !visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtains all children, grandchildren, etc. of the given element
|
||||||
|
function getDescendants(element) {
|
||||||
|
return [...element.querySelectorAll("*")];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable all elements on form submission (otherwise their value is not submitted)
|
||||||
|
elements.mainForm.addEventListener('submit', () => {
|
||||||
|
for (const child of getDescendants(elements.mainForm))
|
||||||
|
child.disabled = false;
|
||||||
|
});
|
||||||
|
elements.mainForm.addEventListener('formdata', updateUI);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<p>
|
<p>
|
||||||
|
@ -72,10 +72,14 @@ header img {
|
|||||||
|
|
||||||
main h1 {
|
main h1 {
|
||||||
margin: 1em 0 0;
|
margin: 1em 0 0;
|
||||||
|
|
||||||
|
font-size: 2em;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
main h2 {
|
main h2 {
|
||||||
margin: 1em 0 0;
|
margin: 1em 0 0;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--solid-gray);
|
color: var(--solid-gray);
|
||||||
}
|
}
|
||||||
@ -134,35 +138,49 @@ pre {
|
|||||||
fieldset {
|
fieldset {
|
||||||
border: none;
|
border: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 0 0 1em;
|
padding: 0;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
}
|
}
|
||||||
|
fieldset > legend {
|
||||||
|
margin: .5em 0 0;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--solid-gray);
|
||||||
|
}
|
||||||
|
fieldset > legend + p {
|
||||||
|
margin: 0 0 .5em .25em;
|
||||||
|
}
|
||||||
fieldset ol {
|
fieldset ol {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin; 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0 0 0 2em;
|
||||||
}
|
}
|
||||||
fieldset ol ol {
|
fieldset ol ol {
|
||||||
margin: 0 0 1em 2em;
|
margin: 0 0 1em .5em;
|
||||||
}
|
}
|
||||||
fieldset ol li:not(.checkbox) {
|
fieldset ol li:not(.checkbox, .radio) {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 10em auto;
|
grid-template-columns: 10em auto;
|
||||||
grid-gap: 1em;
|
grid-gap: 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
fieldset ol ol li:not(.checkbox) {
|
fieldset ol ol li:not(.checkbox, .radio) {
|
||||||
grid-template-columns: 8em auto;
|
grid-template-columns: 7.5em auto;
|
||||||
}
|
}
|
||||||
fieldset li label {
|
fieldset li label {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
fieldset li:not(.checkbox) > label:after {
|
fieldset li li label {
|
||||||
content: ": ";
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
fieldset li.checkbox > label > input {
|
fieldset li.checkbox > label > input,
|
||||||
|
fieldset li.radio > label > input {
|
||||||
margin: 0 .5em 0 0;
|
margin: 0 .5em 0 0;
|
||||||
}
|
}
|
||||||
|
fieldset li p {
|
||||||
|
margin-top: .25em;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
border: 1px solid var(--solid-purple);
|
border: 1px solid var(--solid-purple);
|
||||||
@ -183,7 +201,7 @@ button:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form p.actions {
|
form p.actions {
|
||||||
margin: 0 0 1em 12em;
|
margin: .5em 0 1em 11em;
|
||||||
}
|
}
|
||||||
|
|
||||||
form p.error {
|
form p.error {
|
||||||
@ -193,7 +211,7 @@ form p.error {
|
|||||||
|
|
||||||
form ul.actions {
|
form ul.actions {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 0 1em 12em;
|
margin: 0 0 1em 11em;
|
||||||
}
|
}
|
||||||
form ul.actions > li {
|
form ul.actions > li {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -201,6 +219,15 @@ form ul.actions > li {
|
|||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.loaded * {
|
||||||
|
max-height: 500px;
|
||||||
|
transition: max-height .2s;
|
||||||
|
}
|
||||||
|
form .hidden {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
ul.container > li {
|
ul.container > li {
|
||||||
margin: 0.25em 0;
|
margin: 0.25em 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
@ -117,8 +117,8 @@ describe('A Solid server with IDP', (): void => {
|
|||||||
const res = await postForm(`${baseUrl}idp/register`, formBody);
|
const res = await postForm(`${baseUrl}idp/register`, formBody);
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
expect(text).toMatch(new RegExp(`your WebID.*${webId}`, 'u'));
|
expect(text).toMatch(new RegExp(`your.WebID.*${webId}`, 'u'));
|
||||||
expect(text).toMatch(new RegExp(`your email address.*${email}`, 'u'));
|
expect(text).toMatch(new RegExp(`your.email.address.*${email}`, 'u'));
|
||||||
expect(text).toMatch(new RegExp(`<code><${webId}> <http://www.w3.org/ns/solid/terms#oidcIssuer> <${baseUrl}>\\.</code>`, 'mu'));
|
expect(text).toMatch(new RegExp(`<code><${webId}> <http://www.w3.org/ns/solid/terms#oidcIssuer> <${baseUrl}>\\.</code>`, 'mu'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -280,7 +280,7 @@ describe('A Solid server with IDP', (): void => {
|
|||||||
const res = await postForm(`${baseUrl}idp/register`, formBody);
|
const res = await postForm(`${baseUrl}idp/register`, formBody);
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
expect(text).toMatch(new RegExp(`Your new pod.*${baseUrl}${podName}/`, 'u'));
|
expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ describe('A Solid server with IDP', (): void => {
|
|||||||
newWebId = matchWebId![1];
|
newWebId = matchWebId![1];
|
||||||
expect(text).toMatch(new RegExp(`new WebID is.*${newWebId}`, 'u'));
|
expect(text).toMatch(new RegExp(`new WebID is.*${newWebId}`, 'u'));
|
||||||
expect(text).toMatch(new RegExp(`your email address.*${newMail}`, 'u'));
|
expect(text).toMatch(new RegExp(`your email address.*${newMail}`, 'u'));
|
||||||
expect(text).toMatch(new RegExp(`Your new pod.*${baseUrl}${podName}/`, 'u'));
|
expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('initializes the session and logs in.', async(): Promise<void> => {
|
it('initializes the session and logs in.', async(): Promise<void> => {
|
||||||
|
@ -53,12 +53,11 @@ describe('EmailPasswordUtil', (): void => {
|
|||||||
|
|
||||||
describe('#assertPassword', (): void => {
|
describe('#assertPassword', (): void => {
|
||||||
it('validates the password against the confirmPassword.', async(): Promise<void> => {
|
it('validates the password against the confirmPassword.', async(): Promise<void> => {
|
||||||
expect((): void => assertPassword(undefined, undefined)).toThrow('Password required');
|
expect((): void => assertPassword(undefined, undefined)).toThrow('Please enter a password.');
|
||||||
expect((): void => assertPassword([], undefined)).toThrow('Password required');
|
expect((): void => assertPassword([], undefined)).toThrow('Please enter a password.');
|
||||||
expect((): void => assertPassword('password', undefined)).toThrow('Password confirmation required');
|
expect((): void => assertPassword('password', undefined)).toThrow('Please confirm your password.');
|
||||||
expect((): void => assertPassword('password', [])).toThrow('Password confirmation required');
|
expect((): void => assertPassword('password', [])).toThrow('Please confirm your password.');
|
||||||
expect((): void => assertPassword('password', 'confirmPassword'))
|
expect((): void => assertPassword('password', 'other')).toThrow('Your password and confirmation did not match');
|
||||||
.toThrow('Password and confirmation do not match');
|
|
||||||
expect(assertPassword('password', 'password')).toBeUndefined();
|
expect(assertPassword('password', 'password')).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -78,81 +78,73 @@ describe('A RegistrationHandler', (): void => {
|
|||||||
|
|
||||||
describe('validating data', (): void => {
|
describe('validating data', (): void => {
|
||||||
it('rejects array inputs.', async(): Promise<void> => {
|
it('rejects array inputs.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ data: [ 'a', 'b' ]});
|
request = createPostFormRequest({ mydata: [ 'a', 'b' ]});
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('Multiple values found for key data');
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Unexpected multiple values for mydata.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors on invalid emails.', async(): Promise<void> => {
|
it('errors on invalid emails.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email: undefined });
|
request = createPostFormRequest({ email: undefined });
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('A valid e-mail address is required');
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Please enter a valid e-mail address.');
|
||||||
|
|
||||||
request = createPostFormRequest({ email: '' });
|
request = createPostFormRequest({ email: '' });
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('A valid e-mail address is required');
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Please enter a valid e-mail address.');
|
||||||
|
|
||||||
request = createPostFormRequest({ email: 'invalidEmail' });
|
request = createPostFormRequest({ email: 'invalidEmail' });
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('A valid e-mail address is required');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('errors when an unnecessary WebID is provided.', async(): Promise<void> => {
|
|
||||||
request = createPostFormRequest({ email, webId, createWebId });
|
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A WebID should only be provided when no new one is being created');
|
.rejects.toThrow('Please enter a valid e-mail address.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors when a required WebID is not valid.', async(): Promise<void> => {
|
it('errors when a required WebID is not valid.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email, webId: undefined });
|
request = createPostFormRequest({ email, register, webId: undefined });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A WebID is required if no new one is being created');
|
.rejects.toThrow('Please enter a valid WebID.');
|
||||||
|
|
||||||
request = createPostFormRequest({ email, webId: '' });
|
request = createPostFormRequest({ email, register, webId: '' });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A WebID is required if no new one is being created');
|
.rejects.toThrow('Please enter a valid WebID.');
|
||||||
});
|
|
||||||
|
|
||||||
it('errors when an unnecessary password is provided.', async(): Promise<void> => {
|
|
||||||
request = createPostFormRequest({ email, webId, password });
|
|
||||||
await expect(handler.handle({ request, response }))
|
|
||||||
.rejects.toThrow('A password should only be provided when registering');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors on invalid passwords when registering.', async(): Promise<void> => {
|
it('errors on invalid passwords when registering.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email, webId, password, confirmPassword: 'bad', register });
|
request = createPostFormRequest({ email, webId, password, confirmPassword: 'bad', register });
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('Password and confirmation do not match');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('errors when an unnecessary pod name is provided.', async(): Promise<void> => {
|
|
||||||
request = createPostFormRequest({ email, webId, podName });
|
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A pod name should only be provided when creating a pod and/or WebID');
|
.rejects.toThrow('Your password and confirmation did not match.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors on invalid pod names when required.', async(): Promise<void> => {
|
it('errors on invalid pod names when required.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email, podName: undefined, createWebId });
|
request = createPostFormRequest({ email, webId, createPod, podName: undefined });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A pod name is required when creating a pod and/or WebID');
|
.rejects.toThrow('Please specify a Pod name.');
|
||||||
|
|
||||||
request = createPostFormRequest({ email, webId, podName: '', createPod });
|
request = createPostFormRequest({ email, webId, createPod, podName: ' ' });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('A pod name is required when creating a pod and/or WebID');
|
.rejects.toThrow('Please specify a Pod name.');
|
||||||
|
|
||||||
|
request = createPostFormRequest({ email, webId, createWebId });
|
||||||
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Please specify a Pod name.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors when trying to create a WebID without registering or creating a pod.', async(): Promise<void> => {
|
it('errors when trying to create a WebID without registering or creating a pod.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email, podName, createWebId });
|
request = createPostFormRequest({ email, podName, createWebId });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('Creating a WebID is only possible when also registering and creating a pod');
|
.rejects.toThrow('Please enter a password.');
|
||||||
|
|
||||||
request = createPostFormRequest({ email, podName, password, confirmPassword, createWebId, register });
|
|
||||||
await expect(handler.handle({ request, response }))
|
|
||||||
.rejects.toThrow('Creating a WebID is only possible when also registering and creating a pod');
|
|
||||||
|
|
||||||
request = createPostFormRequest({ email, podName, createWebId, createPod });
|
request = createPostFormRequest({ email, podName, createWebId, createPod });
|
||||||
await expect(handler.handle({ request, response }))
|
await expect(handler.handle({ request, response }))
|
||||||
.rejects.toThrow('Creating a WebID is only possible when also registering and creating a pod');
|
.rejects.toThrow('Please enter a password.');
|
||||||
|
|
||||||
|
request = createPostFormRequest({ email, podName, createWebId, createPod, register });
|
||||||
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Please enter a password.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors when no option is chosen.', async(): Promise<void> => {
|
it('errors when no option is chosen.', async(): Promise<void> => {
|
||||||
request = createPostFormRequest({ email, webId });
|
request = createPostFormRequest({ email, webId });
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow('At least one option needs to be chosen');
|
await expect(handler.handle({ request, response }))
|
||||||
|
.rejects.toThrow('Please register for a WebID or create a Pod.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ describe('A ResetPasswordHandler', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('errors for invalid passwords.', async(): Promise<void> => {
|
it('errors for invalid passwords.', async(): Promise<void> => {
|
||||||
const errorMessage = 'Password and confirmation do not match';
|
const errorMessage = 'Your password and confirmation did not match.';
|
||||||
request = createPostFormRequest({ password: 'password!', confirmPassword: 'otherPassword!' }, url);
|
request = createPostFormRequest({ password: 'password!', confirmPassword: 'otherPassword!' }, url);
|
||||||
await expect(handler.handle({ request, response })).rejects.toThrow(errorMessage);
|
await expect(handler.handle({ request, response })).rejects.toThrow(errorMessage);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user