Skip to content

Commit

Permalink
Less error prone username and password creation.
Browse files Browse the repository at this point in the history
  • Loading branch information
amyjko committed Oct 27, 2023
1 parent 2f0748b commit 5738c44
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 79 deletions.
34 changes: 18 additions & 16 deletions src/components/concepts/MarkupHTMLView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,27 @@
{#each parsed.asLine().paragraphs[0].segments as segment}
<SegmentHTMLView {segment} {spaces} alone={false} />
{/each}
{:else}{#each paragraphsAndLists as paragraphOrList, index}<p
class="paragraph"
class:animated={$animationFactor > 0}
style="--delay:{$animationDuration * index * 0.1}ms"
>{#if paragraphOrList instanceof Paragraph}
{#each paragraphOrList.segments as segment}<SegmentHTMLView
{:else}{#each paragraphsAndLists as paragraphOrList, index}{#if paragraphOrList instanceof Paragraph}
<p
class="paragraph"
class:animated={$animationFactor > 0}
style="--delay:{$animationDuration * index * 0.1}ms"
>{#each paragraphOrList.segments as segment}<SegmentHTMLView
{segment}
{spaces}
alone={paragraphOrList.segments.length === 1}
/>{/each}{:else}<ul
>{#each paragraphOrList.items as paragraph}<li
>{#each paragraph.segments as segment}<SegmentHTMLView
{segment}
{spaces}
alone={paragraph.segments.length === 1}
/>{/each}</li
>{/each}</ul
>{/if}</p
>{/each}
/>{/each}</p
>{:else}<ul
class:animated={$animationFactor > 0}
style="--delay:{$animationDuration * index * 0.1}ms"
>{#each paragraphOrList.items as paragraph}<li
>{#each paragraph.segments as segment}<SegmentHTMLView
{segment}
{spaces}
alone={paragraph.segments.length === 1}
/>{/each}</li
>{/each}</ul
>{/if}{/each}
{/if}
{:else}no spaces{/if}

Expand Down
6 changes: 4 additions & 2 deletions src/locale/UITexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -667,9 +667,11 @@ type UITexts = {
/** Encouragement to go create after logging in. */
play: string;
/** Gives rules for emails above the login form */
emailrules: string;
emailrules: string[];
/** Gives rules for usernames and passwords above the login form */
usernamerules: string;
usernamerules: string[];
/** Reminder to write down password */
passwordreminder: string;
/** Offers to log out the creator. */
logout: string;
/** Shown briefly before page redirects to projects */
Expand Down
14 changes: 11 additions & 3 deletions src/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4196,8 +4196,16 @@
},
"enter": "It looks like your login link came from a different browser or device. Can you enter your email again, just so we're sure it's you?",
"play": "You're logged in, we can save your projects online now! Want to create something?",
"emailrules": "Don't provide your email if you are 12 or younger.",
"usernamerules": "If you're creating an account, *usernames* should not contain identiable information (e.g., names), cannot be an email addresses, and should be at least 5 characters long. *Passwords* must be at least 10 characters long; if you're not using a password manager, choose three long words you'll remember.",
"emailrules": [
"• Don't provide your email if you are *12 or younger*.",
"• If you *lose access* to your email account, you won't be able to update your email address."
],
"usernamerules": [
"• *Usernames* should not contain identiable information (e.g., names), cannot be an email addresses, and should be at least 5 characters long",
"• *Passwords* must be at least 10 characters long; if you're not using a password manager, choose three long words you'll remember.",
"• *If you forget your password*, you can't recover your account, since we have no other way to know it's you. Store your password somewhere safe, like a password manager"
],
"passwordreminder": "It looks like you're creating an account. Reveal it above, and make sure you wrote it down correctly, then submit again to create your account.",
"change": "Want to change your email? Submit a new one and we'll send a confirmation to the old one.",
"sent": "Check your email for a login link. Patience, email can be slow!",
"logout": "Leaving a shared device and want to keep your projects private? Logout and we'll remove your projects from this device. They will still be stored online.",
Expand All @@ -4215,7 +4223,7 @@
"offline": "You appear to be offline.",
"unchanged": "We couldn't change your email address, but we don't know why.",
"delete": "We couldn't delete your account, but we don't know why.",
"wrongPassword": "Not a valid username and password"
"wrongPassword": "Not a valid username and password. Either your password is wrong, or someone else has this username."
},
"feedback": {
"changing": "Submitting new email...",
Expand Down
122 changes: 72 additions & 50 deletions src/routes/login/Login.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import Mode from '../../components/widgets/Mode.svelte';
import Subheader from '../../components/app/Subheader.svelte';
import MarkupHtmlView from '../../components/concepts/MarkupHTMLView.svelte';
import Note from '../../components/widgets/Note.svelte';
import { CreatorUsernameEmailDomain } from '../../db/CreatorDatabase';
let user = getUser();
Expand All @@ -36,11 +35,17 @@
let younger = true;
let username = '';
let password = '';
let reveal = false;
$: emailUsername = `${username}${CreatorUsernameEmailDomain}`;
/** True if we tried to log in and there's no account. */
let noAccount = false;
$: emailSubmittable = !sent && validEmail(email);
$: usernameSubmittable =
!sent && isValidUsername(username) && isValidPassword(password);
$: userNameValid = isValidUsername(username) && isValidPassword(password);
$: usernameIsCheckable = !noAccount && userNameValid;
function isValidUsername(username: string) {
return !validEmail(username) && username.length >= 5;
Expand Down Expand Up @@ -114,33 +119,33 @@
return undefined;
}
async function startUsernameLogin() {
const emailUsername = `${username}${CreatorUsernameEmailDomain}`;
if (auth && usernameSubmittable) {
async function tryUsernameLogin() {
if (auth && usernameIsCheckable) {
try {
await signInWithEmailAndPassword(
auth,
`${username}${CreatorUsernameEmailDomain}`,
password
);
await signInWithEmailAndPassword(auth, emailUsername, password);
} catch (error) {
// If not found, then we create the user.
if (
error instanceof FirebaseError &&
error.code === 'auth/user-not-found'
) {
try {
await createUserWithEmailAndPassword(
auth,
emailUsername,
password
);
} catch (error) {
usernameLoginFeedback = communicateError(error);
}
noAccount = true;
} else {
usernameLoginFeedback = communicateError(error);
}
// Otherwise, communicate the error.
else usernameLoginFeedback = communicateError(error);
}
}
}
async function createUsernameLogin() {
if (auth && reveal) {
try {
await createUserWithEmailAndPassword(
auth,
emailUsername,
password
);
} catch (error) {
usernameLoginFeedback = communicateError(error);
}
}
}
Expand Down Expand Up @@ -187,12 +192,6 @@
<Subheader>{$locales.get((l) => l.ui.page.login.subheader.email)}</Subheader
>
<form class="login-form" on:submit={startEmailLogin}>
<Note
><MarkupHtmlView
inline
markup={$locales.get((l) => l.ui.page.login.prompt.emailrules)}
/></Note
>
<div>
<TextField
kind="email"
Expand All @@ -213,6 +212,9 @@
action={() => undefined}>&gt;</Button
>
</div>
<MarkupHtmlView
markup={$locales.get((l) => l.ui.page.login.prompt.emailrules)}
/>
</form>
{/if}

Expand All @@ -225,39 +227,59 @@
{/if}

<Subheader>{$locales.get((l) => l.ui.page.login.subheader.username)}</Subheader>
<form class="login-form" on:submit={startUsernameLogin}>
<TextField
description={$locales.get(
(l) => l.ui.page.login.field.username.description
)}
placeholder={$locales.get(
(l) => l.ui.page.login.field.username.placeholder
)}
bind:text={username}
editable={!sent}
validator={(name) => isValidUsername(name)}
/>
<form
class="login-form"
on:submit={noAccount ? createUsernameLogin : tryUsernameLogin}
>
<div>
<TextField
kind="password"
description={$locales.get(
(l) => l.ui.page.login.field.password.description
(l) => l.ui.page.login.field.username.description
)}
placeholder={$locales.get(
(l) => l.ui.page.login.field.password.placeholder
(l) => l.ui.page.login.field.username.placeholder
)}
bind:text={password}
bind:text={username}
editable={!sent}
validator={(pass) => isValidPassword(pass)}
validator={(name) => isValidUsername(name)}
/>
{#if noAccount}
{#if reveal}{password}{:else}<Button
tip={$locales.get(
(l) => l.ui.page.login.prompt.passwordreminder
)}
action={() => (reveal = true)}
>🔍{''.repeat(password.length)}</Button
>{/if}
{:else}
<TextField
kind={noAccount ? undefined : 'password'}
description={$locales.get(
(l) => l.ui.page.login.field.password.description
)}
placeholder={$locales.get(
(l) => l.ui.page.login.field.password.placeholder
)}
bind:text={password}
validator={(pass) => isValidPassword(pass)}
/>
{/if}
<Button
submit
background
tip={$locales.get((l) => l.ui.page.login.button.login)}
active={usernameSubmittable}
action={() => undefined}>&gt;</Button
></div
>
active={usernameIsCheckable || reveal}
action={() => undefined}
>{#if noAccount}&gt;&gt;{:else}&gt;{/if}</Button
>
</div>
{#if noAccount}
<Feedback
>{$locales.get(
(l) => l.ui.page.login.prompt.passwordreminder
)}</Feedback
>
{/if}
<MarkupHtmlView
markup={$locales.get((l) => l.ui.page.login.prompt.usernamerules)}
/>
Expand Down
5 changes: 3 additions & 2 deletions static/locales/es-MX/es-MX.json
Original file line number Diff line number Diff line change
Expand Up @@ -2570,8 +2570,9 @@
},
"enter": "Parece que tu enlace de inicio de sesión vino de un navegador o dispositivo diferente. ¿Puedes ingresar tu correo electrónico nuevamente, solo para estar seguros de que eres tú?",
"play": "Estás conectado, ¡podemos guardar tus proyectos en línea ahora! ¿Quieres crear algo?",
"emailrules": "$?",
"usernamerules": "$?",
"emailrules": ["$?"],
"usernamerules": ["$?"],
"passwordreminder": "$?",
"change": "¿Quieres cambiar tu correo electrónico? Envía uno nuevo y te enviaremos una confirmación al antiguo.",
"sent": "Revisa tu correo electrónico para encontrar un enlace de inicio de sesión.",
"logout": "¿Estás saliendo de un dispositivo compartido y quieres mantener tus proyectos privados? Cierra la sesión y borraremos tus proyectos de este dispositivo. Todavía se almacenarán en línea.",
Expand Down
5 changes: 3 additions & 2 deletions static/locales/example/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2511,8 +2511,9 @@
"modes": ["$?", "$?"]
},
"enter": "$?",
"emailrules": "$?",
"usernamerules": "$?",
"emailrules": ["$?"],
"usernamerules": ["$?"],
"passwordreminder": "$?",
"play": "$?",
"change": "$?",
"logout": "$?",
Expand Down
5 changes: 3 additions & 2 deletions static/locales/zh-CN/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2511,8 +2511,9 @@
"modes": ["$?", "$?"]
},
"enter": "$?",
"emailrules": "$?",
"usernamerules": "$?",
"emailrules": ["$?"],
"usernamerules": ["$?"],
"passwordreminder": "$?",
"play": "$?",
"change": "$?",
"logout": "$?",
Expand Down
15 changes: 13 additions & 2 deletions static/schemas/Locale.json
Original file line number Diff line number Diff line change
Expand Up @@ -8898,7 +8898,10 @@
},
"emailrules": {
"description": "Gives rules for emails above the login form",
"type": "string"
"items": {
"type": "string"
},
"type": "array"
},
"enter": {
"description": "Asks the creator to enter their email if they opened the email link in a different browser.",
Expand All @@ -8916,6 +8919,10 @@
"description": "Pick an emoji as a name",
"type": "string"
},
"passwordreminder": {
"description": "Reminder to write down password",
"type": "string"
},
"play": {
"description": "Encouragement to go create after logging in.",
"type": "string"
Expand All @@ -8934,7 +8941,10 @@
},
"usernamerules": {
"description": "Gives rules for usernames and passwords above the login form",
"type": "string"
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
Expand All @@ -8945,6 +8955,7 @@
"play",
"emailrules",
"usernamerules",
"passwordreminder",
"logout",
"success",
"confirm",
Expand Down

0 comments on commit 5738c44

Please sign in to comment.