diff --git a/CHANGELOG.md b/CHANGELOG.md index a3b81911e..7643c5ad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ ### Changed - The sign-in/sign-up functions are now on a separate page +- The email sign-in/registration does not require an email address anymore but uses a username - The history shows both the entries saved in LocalStorage and the entries saved on the server together - The gist and pdf embeddings now use a one-click aproach similar to vimeo and youtube - Use [Twemoji](https://twemoji.twitter.com/) as icon font diff --git a/public/api/v2/config b/public/api/v2/config index dcc4a4568..6a3dd78be 100644 --- a/public/api/v2/config +++ b/public/api/v2/config @@ -10,9 +10,10 @@ "google": true, "saml": true, "oauth2": true, - "email": true, + "internal": true, "openid": true }, + "allowRegister": true, "branding": { "name": "ACME Corp", "logo": "http://localhost:3001/acme.png" diff --git a/public/api/v2/me b/public/api/v2/me index 68a396bf5..fcf166f76 100644 --- a/public/api/v2/me +++ b/public/api/v2/me @@ -3,5 +3,5 @@ "photo": "https://1.gravatar.com/avatar/767fc9c115a1b989744c755db47feb60?s=200&r=pg&d=mp", "name": "Test", "status": "ok", - "provider": "email" + "provider": "internal" } diff --git a/public/locales/ar.json b/public/locales/ar.json index e41711755..8ba4b9d56 100644 --- a/public/locales/ar.json +++ b/public/locales/ar.json @@ -181,7 +181,9 @@ "signInVia": "لِج عبر {{service}}", "signIn": "لِج", "signOut": "خروج", - "register": "انشئ حسابا", + "register": { + "title": "انشئ حسابا" + }, "auth": { "error": {} } diff --git a/public/locales/ca.json b/public/locales/ca.json index 13d82b901..26a1f7c26 100644 --- a/public/locales/ca.json +++ b/public/locales/ca.json @@ -181,7 +181,9 @@ "signInVia": "Entrar a través de {{service}}", "signIn": "Entrar", "signOut": "Sortir", - "register": "Registrar-se", + "register": { + "title": "Registrar-se" + }, "auth": { "error": {} } diff --git a/public/locales/cs.json b/public/locales/cs.json index ee17680ad..1ade5352c 100644 --- a/public/locales/cs.json +++ b/public/locales/cs.json @@ -181,7 +181,9 @@ "signInVia": "Přihlásit se přes {{service}}", "signIn": "Přihlásit", "signOut": "Odhlásit", - "register": "Registrovat", + "register": { + "title": "Registrovat" + }, "auth": { "error": {} } diff --git a/public/locales/de.json b/public/locales/de.json index cf8d6e25e..24f4ab941 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -181,15 +181,16 @@ "signInVia": "Einloggen über {{service}}", "signIn": "Einloggen", "signOut": "Ausloggen", - "register": "Registrieren", + "register": { + "title": "Registrieren" + }, "auth": { "email": "E-Mail", "password": "Passwort", "username": "Benutzername", "error": { "openIdLogin": "OpenID nicht korrekt", - "emailLogin": "E-Mail oder Passwort nicht korrekt", - "ldapLogin": "Benutzername oder Passwort nicht korrekt" + "usernamePassword": "Benutzername oder Passwort nicht korrekt" } } } diff --git a/public/locales/en.json b/public/locales/en.json index 6c36a3940..c651a7282 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -284,16 +284,25 @@ "signInVia": "Sign in via {{service}}", "signIn": "Sign In", "signOut": "Sign Out", - "register": "Register", "auth": { "email": "Email", "password": "Password", "username": "Username", "error": { "openIdLogin": "Invalid OpenID provided", - "emailLogin": "Invalid email or password", - "ldapLogin": "Invalid username or password" + "usernamePassword": "Invalid username or password" } + }, + "register": { + "title": "Register", + "passwordAgain": "Password (again)", + "usernameInfo": "The username is your unique identifier for login.", + "passwordInfo": "Choose a unique and secure password. It must contain at least 8 characters.", + "infoTermsPrivacy": "With the registration of my user account I agree to the following terms:", + "error": { + "usernameExisting": "There is already an account with this username.", + "other": "There was an error while registering your account. Just try it again." + } } } } diff --git a/public/locales/es.json b/public/locales/es.json index 0a2d0b28f..f8471d994 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -181,7 +181,9 @@ "signInVia": "Ingresar via {{service}}", "signIn": "Ingresar", "signOut": "Salir", - "register": "Registrar", + "register": { + "title": "Registrar" + }, "auth": { "error": {} } diff --git a/public/locales/fr.json b/public/locales/fr.json index 108cef49b..65e9946b5 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -181,7 +181,9 @@ "signInVia": "Se connecter depuis {{service}}", "signIn": "Se connecter", "signOut": "Se déconnecter", - "register": "S'enregistrer", + "register": { + "title": "S'enregistrer" + }, "auth": { "error": {} } diff --git a/public/locales/id.json b/public/locales/id.json index 9d5798edf..2b7216e8f 100644 --- a/public/locales/id.json +++ b/public/locales/id.json @@ -181,7 +181,9 @@ "signInVia": "Masuk menggunakan {{service}}", "signIn": "Masuk", "signOut": "Keluar", - "register": "Daftar", + "register": { + "title": "Daftar" + }, "auth": { "error": {} } diff --git a/public/locales/it.json b/public/locales/it.json index fa0d39673..d100e2260 100644 --- a/public/locales/it.json +++ b/public/locales/it.json @@ -181,7 +181,9 @@ "signInVia": "Entra con {{service}}", "signIn": "Entra", "signOut": "Disconettiti", - "register": "Registrati", + "register": { + "title": "Registrati" + }, "auth": { "error": {} } diff --git a/public/locales/ja.json b/public/locales/ja.json index 8f61f65db..17c366e19 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -181,7 +181,9 @@ "signInVia": "{{service}}でサインイン", "signIn": "サインイン", "signOut": "サインアウト", - "register": "登録", + "register": { + "title": "登録" + }, "auth": { "error": {} } diff --git a/public/locales/nl.json b/public/locales/nl.json index 81df5bde7..9bb75da98 100644 --- a/public/locales/nl.json +++ b/public/locales/nl.json @@ -181,7 +181,9 @@ "signInVia": "Log in via {{service}}", "signIn": "Inloggen", "signOut": "Uitloggen", - "register": "Registreren", + "register": { + "title": "Registreren" + }, "auth": { "error": {} } diff --git a/public/locales/pl.json b/public/locales/pl.json index c0a71b085..c4457b991 100644 --- a/public/locales/pl.json +++ b/public/locales/pl.json @@ -181,7 +181,9 @@ "signInVia": "Zaloguj się poprzez {{service}}", "signIn": "Zaloguj się", "signOut": "Wyloguj się", - "register": "Zarejestruj", + "register": { + "title": "Zarejestruj" + }, "auth": { "error": {} } diff --git a/public/locales/pt.json b/public/locales/pt.json index 83fbfc002..f6592fa73 100644 --- a/public/locales/pt.json +++ b/public/locales/pt.json @@ -181,7 +181,9 @@ "signInVia": "Entrar via {{service}}", "signIn": "Entrar", "signOut": "Sair", - "register": "Register", + "register": { + "title": "Register" + }, "auth": { "error": {} } diff --git a/public/locales/ru.json b/public/locales/ru.json index 6556ba6c9..4e6bd86ed 100644 --- a/public/locales/ru.json +++ b/public/locales/ru.json @@ -181,7 +181,9 @@ "signInVia": "Войти с помощью {{service}}", "signIn": "Войти", "signOut": "Выйти", - "register": "Регистрация", + "register": { + "title": "Регистрация" + }, "auth": { "error": {} } diff --git a/public/locales/sk.json b/public/locales/sk.json index f2f257f26..12b7a43a1 100644 --- a/public/locales/sk.json +++ b/public/locales/sk.json @@ -181,7 +181,9 @@ "signInVia": "Prihlásiť sa cez {{service}}", "signIn": "Prihlásiť sa", "signOut": "Odhlásiť sa", - "register": "Registrovať", + "register": { + "title": "Registrovať" + }, "auth": { "error": {} } diff --git a/public/locales/sr.json b/public/locales/sr.json index 50db9a862..814b8e98c 100644 --- a/public/locales/sr.json +++ b/public/locales/sr.json @@ -180,7 +180,9 @@ "signInVia": "Пријави се уз {{service}}", "signIn": "Пријави се", "signOut": "Одјави се", - "register": "Региструј се", + "register": { + "title": "Региструј се" + }, "auth": { "error": {} } diff --git a/public/locales/sv.json b/public/locales/sv.json index e839033e8..64e4db2f8 100644 --- a/public/locales/sv.json +++ b/public/locales/sv.json @@ -181,7 +181,9 @@ "signInVia": "Logga in via {{service}}", "signIn": "Logga in", "signOut": "Logga ut", - "register": "Registrera", + "register": { + "title": "Registrera" + }, "auth": { "error": {} } diff --git a/public/locales/vi.json b/public/locales/vi.json index ae5632c2d..91dba4ea0 100644 --- a/public/locales/vi.json +++ b/public/locales/vi.json @@ -180,7 +180,9 @@ "signInVia": "Đăng nhấp với {{service}}", "signIn": "Đăng nhập", "signOut": "Đăng xuất", - "register": "Đăng ký", + "register": { + "title": "Đăng ký" + }, "auth": { "error": {} } diff --git a/public/locales/zh-CN.json b/public/locales/zh-CN.json index e1f60ff80..142f24b25 100644 --- a/public/locales/zh-CN.json +++ b/public/locales/zh-CN.json @@ -181,7 +181,9 @@ "signInVia": "通过 {{service}} 登录", "signIn": "登录", "signOut": "登出", - "register": "注册", + "register": { + "title": "注册" + }, "auth": { "error": {} } diff --git a/public/locales/zh-TW.json b/public/locales/zh-TW.json index c7b2fb2f1..f28dbc33f 100644 --- a/public/locales/zh-TW.json +++ b/public/locales/zh-TW.json @@ -181,7 +181,9 @@ "signInVia": "透過 {{service}} 登入", "signIn": "登入", "signOut": "登出", - "register": "註冊", + "register": { + "title": "註冊" + }, "auth": { "error": {} } diff --git a/src/api/auth.ts b/src/api/auth.ts index 538ab8c9c..f57547533 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,12 +1,13 @@ +import { RegisterError } from '../components/landing/pages/register/register' import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' -export const doEmailLogin = async (email: string, password: string): Promise => { - const response = await fetch(getApiUrl() + '/auth/email', { +export const doInternalLogin = async (username: string, password: string): Promise => { + const response = await fetch(getApiUrl() + '/auth/internal', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ - email: email, + username: username, password: password }) }) @@ -14,6 +15,23 @@ export const doEmailLogin = async (email: string, password: string): Promise => { + const response = await fetch(getApiUrl() + '/auth/register', { + ...defaultFetchConfig, + method: 'POST', + body: JSON.stringify({ + username: username, + password: password + }) + }) + + if (response.status === 409) { + throw new Error(RegisterError.USERNAME_EXISTING) + } + + expectResponseCode(response) +} + export const doLdapLogin = async (username: string, password: string): Promise => { const response = await fetch(getApiUrl() + '/auth/ldap', { ...defaultFetchConfig, diff --git a/src/api/config/types.ts b/src/api/config/types.ts index 75a088b5a..4728a0e6d 100644 --- a/src/api/config/types.ts +++ b/src/api/config/types.ts @@ -1,5 +1,6 @@ export interface Config { allowAnonymous: boolean, + allowRegister: boolean, authProviders: AuthProvidersState, branding: BrandingConfig, banner: BannerConfig, @@ -36,7 +37,7 @@ export interface AuthProvidersState { google: boolean, saml: boolean, oauth2: boolean, - email: boolean, + internal: boolean, openid: boolean, } diff --git a/src/components/landing/pages/login/auth/via-email.tsx b/src/components/landing/pages/login/auth/via-email.tsx deleted file mode 100644 index bd13449ec..000000000 --- a/src/components/landing/pages/login/auth/via-email.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React, { FormEvent, useState } from 'react' -import { Alert, Button, Card, Form } from 'react-bootstrap' -import { Trans, useTranslation } from 'react-i18next' -import { doEmailLogin } from '../../../../../api/auth' -import { getAndSetUser } from '../../../../../utils/apiUtils' - -export const ViaEMail: React.FC = () => { - const { t } = useTranslation() - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [error, setError] = useState(false) - - const doAsyncLogin = async () => { - await doEmailLogin(email, password) - await getAndSetUser() - } - - const onFormSubmit = (event: FormEvent) => { - doAsyncLogin().catch(() => setError(true)) - event.preventDefault() - } - - return ( - - - - - -
- - setEmail(event.currentTarget.value)} className="bg-dark text-white" - /> - - - - setPassword(event.currentTarget.value)} - className="bg-dark text-white"/> - - - - - - - -
-
-
- ) -} diff --git a/src/components/landing/pages/login/auth/via-internal.tsx b/src/components/landing/pages/login/auth/via-internal.tsx new file mode 100644 index 000000000..04b6b82c5 --- /dev/null +++ b/src/components/landing/pages/login/auth/via-internal.tsx @@ -0,0 +1,81 @@ +import React, { FormEvent, useCallback, useState } from 'react' +import { Alert, Button, Card, Form } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { useSelector } from 'react-redux' +import { Link } from 'react-router-dom' +import { doInternalLogin } from '../../../../../api/auth' +import { ApplicationState } from '../../../../../redux' +import { getAndSetUser } from '../../../../../utils/apiUtils' +import { ShowIf } from '../../../../common/show-if/show-if' + +export const ViaInternal: React.FC = () => { + const { t } = useTranslation() + const [username, setUsername] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState(false) + const allowRegister = useSelector((state: ApplicationState) => state.config.allowRegister) + + const onLoginSubmit = useCallback((event: FormEvent) => { + doInternalLogin(username, password) + .then(() => getAndSetUser()) + .catch(() => setError(true)) + event.preventDefault() + }, [username, password]) + + return ( + + + + + +
+ + setUsername(event.currentTarget.value)} className="bg-dark text-white" + autoComplete='username' + /> + + + + setPassword(event.currentTarget.value)} + className="bg-dark text-white" + autoComplete='current-password' + /> + + + + + + +
+ + + + + + +
+
+
+
+ ) +} diff --git a/src/components/landing/pages/login/auth/via-ldap.tsx b/src/components/landing/pages/login/auth/via-ldap.tsx index 1ea19f4c4..f69677933 100644 --- a/src/components/landing/pages/login/auth/via-ldap.tsx +++ b/src/components/landing/pages/login/auth/via-ldap.tsx @@ -1,4 +1,4 @@ -import React, { FormEvent, useState } from 'react' +import React, { FormEvent, useCallback, useState } from 'react' import { Alert, Button, Card, Form } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' @@ -17,19 +17,12 @@ export const ViaLdap: React.FC = () => { const name = ldapCustomName ? `${ldapCustomName} (LDAP)` : 'LDAP' - const doAsyncLogin = async () => { - try { - await doLdapLogin(username, password) - await getAndSetUser() - } catch { - setError(true) - } - } - - const onFormSubmit = (event: FormEvent) => { - doAsyncLogin().catch(() => setError(true)) + const onLoginSubmit = useCallback((event: FormEvent) => { + doLdapLogin(username, password) + .then(() => getAndSetUser()) + .catch(() => setError(true)) event.preventDefault() - } + }, [username, password]) return ( @@ -37,29 +30,32 @@ export const ViaLdap: React.FC = () => { -
- + + setUsername(event.currentTarget.value)} className="bg-dark text-white" + autoComplete='username' /> - + setPassword(event.currentTarget.value)} - className="bg-dark text-white"/> + className="bg-dark text-white" + autoComplete='current-password' + /> - + + +
+ + + + +
+ + + + ) +} diff --git a/src/index.tsx b/src/index.tsx index dc0901e9c..557257100 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,10 +10,11 @@ import { History } from './components/landing/pages/history/history' import { Intro } from './components/landing/pages/intro/intro' import { Login } from './components/landing/pages/login/login' import { Profile } from './components/landing/pages/profile/profile' +import { Register } from './components/landing/pages/register/register' +import { Redirector } from './components/redirector/redirector' import './global-style/index.scss' import * as serviceWorker from './service-worker' import { store } from './utils/store' -import { Redirector } from './components/redirector/redirector' ReactDOM.render( @@ -35,6 +36,11 @@ ReactDOM.render( + + + + + diff --git a/src/redux/config/reducers.ts b/src/redux/config/reducers.ts index d99d5210d..c70238986 100644 --- a/src/redux/config/reducers.ts +++ b/src/redux/config/reducers.ts @@ -4,6 +4,7 @@ import { ConfigActions, ConfigActionType, SetConfigAction } from './types' export const initialState: Config = { allowAnonymous: true, + allowRegister: true, authProviders: { facebook: false, github: false, @@ -14,7 +15,7 @@ export const initialState: Config = { google: false, saml: false, oauth2: false, - email: false, + internal: false, openid: false }, branding: { diff --git a/src/redux/user/types.ts b/src/redux/user/types.ts index db338b52f..3a2a5111d 100644 --- a/src/redux/user/types.ts +++ b/src/redux/user/types.ts @@ -31,7 +31,7 @@ export enum LoginProvider { GOOGLE = 'google', SAML = 'saml', OAUTH2 = 'oauth2', - EMAIL = 'email', + INTERNAL = 'internal', LDAP = 'ldap', OPENID = 'openid' }