From 969bb0ee6c1706b2541ae2dc520f8a2dff5e9ede Mon Sep 17 00:00:00 2001 From: Ruben Verborgh Date: Thu, 29 Jul 2021 16:49:52 +0200 Subject: [PATCH] docs: Make registration form self-explanatory. --- .../email-password/EmailPasswordUtil.ts | 9 +- .../handler/RegistrationHandler.ts | 68 +++--- .../identity/email-password/login.html.ejs | 1 + .../email-password/register-response.html.ejs | 14 +- .../identity/email-password/register.html.ejs | 195 +++++++++++++++--- templates/styles/main.css | 51 +++-- test/integration/Identity.test.ts | 8 +- .../email-password/EmailPasswordUtil.test.ts | 11 +- .../handler/RegistrationHandler.test.ts | 66 +++--- .../handler/ResetPasswordHandler.test.ts | 2 +- 10 files changed, 283 insertions(+), 142 deletions(-) diff --git a/src/identity/interaction/email-password/EmailPasswordUtil.ts b/src/identity/interaction/email-password/EmailPasswordUtil.ts index 467374794..7ace30de0 100644 --- a/src/identity/interaction/email-password/EmailPasswordUtil.ts +++ b/src/identity/interaction/email-password/EmailPasswordUtil.ts @@ -31,13 +31,16 @@ export function throwIdpInteractionError(error: unknown, prefilled: Record 0, 'Password required'); + assert( + typeof password === 'string' && password.length > 0, + 'Please enter a password.', + ); assert( typeof confirmPassword === 'string' && confirmPassword.length > 0, - 'Password confirmation required', + 'Please confirm your password.', ); assert( password === confirmPassword, - 'Password and confirmation do not match', + 'Your password and confirmation did not match.', ); } diff --git a/src/identity/interaction/email-password/handler/RegistrationHandler.ts b/src/identity/interaction/email-password/handler/RegistrationHandler.ts index 0b125752d..5199bf7aa 100644 --- a/src/identity/interaction/email-password/handler/RegistrationHandler.ts +++ b/src/identity/interaction/email-password/handler/RegistrationHandler.ts @@ -193,14 +193,12 @@ export class RegistrationHandler extends HttpHandler { */ private async parseInput(request: HttpRequest): Promise { const parsed = await getFormDataRequestBody(request); - let prefilled: Record = {}; + const prefilled: Record = {}; try { - for (const key of Object.keys(parsed)) { - if (Array.isArray(parsed[key])) { - throw new Error(`Multiple values found for key ${key}`); - } + for (const [ key, value ] of Object.entries(parsed)) { + assert(!Array.isArray(value), `Unexpected multiple values for ${key}.`); + prefilled[key] = value ? value.trim() : ''; } - prefilled = parsed as Record; return this.validateInput(prefilled); } catch (err: unknown) { throwIdpInteractionError(err, prefilled); @@ -212,54 +210,38 @@ export class RegistrationHandler extends HttpHandler { * Verifies that all the data combinations make sense. */ private validateInput(parsed: NodeJS.Dict): 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), - 'A valid e-mail address is required'); + // Parse email + assert(typeof email === 'string' && emailRegex.test(email), 'Please enter a valid e-mail address.'); - const result: ParsedInput = { + const validated: ParsedInput = { email, template, + register: Boolean(register) || Boolean(createWebId), + createPod: Boolean(createPod) || 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; - if (result.createWebId) { - if (validWebId) { - throw new Error('A WebID should only be provided when no new one is being created'); - } - } else { - if (!validWebId) { - throw new Error('A WebID is required if no new one is being created'); - } - result.webId = webId; + // Parse WebID + if (!validated.createWebId) { + assert(typeof webId === 'string' && /^https?:\/\/[^/]+/u.test(webId), 'Please enter a valid WebID.'); + validated.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); - result.password = password; - } else if (typeof password === 'string' && password.length > 0) { - throw new Error('A password should only be provided when registering'); + validated.password = password; } - if (result.createWebId || result.createPod) { - 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; + return validated; } } diff --git a/templates/identity/email-password/login.html.ejs b/templates/identity/email-password/login.html.ejs index 382f03fee..75b9b4a7b 100644 --- a/templates/identity/email-password/login.html.ejs +++ b/templates/identity/email-password/login.html.ejs @@ -19,6 +19,7 @@ <% } %>
+ Your account
  1. diff --git a/templates/identity/email-password/register-response.html.ejs b/templates/identity/email-password/register-response.html.ejs index 3bbe29e72..46dee30c7 100644 --- a/templates/identity/email-password/register-response.html.ejs +++ b/templates/identity/email-password/register-response.html.ejs @@ -19,9 +19,9 @@

    <% if (createPod) { %> -

    Your new pod

    +

    Your new Pod

    - Your new pod is located at <%= podBaseUrl %>. + Your new Pod is located at <%= podBaseUrl %>.
    You can store your documents and data there.

    @@ -37,18 +37,18 @@ <% } %> <% if (register) { %> -

    Your new login

    +

    Your new account

    - You can log in - with your WebID <%= webId %> - on this server via your email address <%= email %>. + Via your email address <%= email %>, + this server lets you log in to Solid apps + with your WebID <%= webId %>

    <% if (!createWebId) { %>

    You will need to add the triple <%= `<${webId}> <${oidcIssuer}>.`%> to your existing WebID document <%= webId %> - 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.

    <% } %> <% } %> diff --git a/templates/identity/email-password/register.html.ejs b/templates/identity/email-password/register.html.ejs index 448ac5bf6..9ffb990ce 100644 --- a/templates/identity/email-password/register.html.ejs +++ b/templates/identity/email-password/register.html.ejs @@ -12,58 +12,195 @@

    Community Solid Server

    -

    Sign up for an account

    -
    +

    Sign up

    + + <% const isBlankForm = !('email' in prefilled); %> - <%if (errorMessage) { %> + <% if (errorMessage) { %>

    Error: <%= errorMessage %>

    <% } %>
    + Your WebID +

    + A WebID is a unique identifier for you + in the form of a URL. +
    + You WebID lets you log in to Solid apps + and access non-public data in Pods. +

      -
    1. - - value="<%= prefilled.email %>" <% } %> /> +
    2. + +

      + Please also create a Pod below, since your WebID will be stored there. +

    3. -
    4. - - -
    5. -
    6. - - +
    7. + +
        +
      1. + + +
      2. +
      3. + +
      4. +
    + Your Pod +

    + A Pod is a place to store your data. +
    + If you create a new WebID, you must also create a Pod to store that WebID. +

    1. - -
    2. -
    3. - -
        + +
        1. - - value="<%= prefilled.webId %>" <% } %> /> -
        2. -
        - -
      1. - -
          -
        1. - - value="<%= prefilled.podName %>" <% } %> /> + + value="<%= prefilled.podName %>" <% } %>>
    +
    + Your account +
    +

    + Choose the credentials you want to use to log in to this server in the future. +

    +
      +
    1. + + value="<%= prefilled.email %>" <% } %>> +
    2. +
    +
      +
    1. + + +
    2. +
    3. + + +
    4. +
    +
    + +
    +

    + +