From e42ccf932e92ad1d1f6c77fecae30abfb28740f0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 14 Jan 2020 13:13:10 +0100 Subject: [PATCH] :tada: Add the ability to create demo user on demand. --- backend/resources/migrations/0002.users.sql | 23 +- .../resources/migrations/0003.projects.sql | 7 +- backend/src/uxbox/config.clj | 1 + backend/src/uxbox/fixtures.clj | 1 - backend/src/uxbox/http/handlers.clj | 3 +- backend/src/uxbox/services/init.clj | 2 +- backend/src/uxbox/services/mutations/demo.clj | 52 +++ .../src/uxbox/services/mutations/profile.clj | 34 +- .../queries/{users.clj => profile.clj} | 16 +- frontend/resources/locales.json | 321 ++++++++++-------- frontend/src/uxbox/main/data/auth.cljs | 9 + frontend/src/uxbox/main/ui/login.cljs | 15 +- 12 files changed, 285 insertions(+), 199 deletions(-) create mode 100644 backend/src/uxbox/services/mutations/demo.clj rename backend/src/uxbox/services/queries/{users.clj => profile.clj} (82%) diff --git a/backend/resources/migrations/0002.users.sql b/backend/resources/migrations/0002.users.sql index cbf4c7d11..0d92b8e55 100644 --- a/backend/resources/migrations/0002.users.sql +++ b/backend/resources/migrations/0002.users.sql @@ -3,7 +3,7 @@ CREATE TABLE users ( created_at timestamptz NOT NULL DEFAULT clock_timestamp(), modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), - deleted_at timestamptz DEFAULT NULL, + deleted_at timestamptz NULL, fullname text NOT NULL DEFAULT '', username text NOT NULL, @@ -11,7 +11,8 @@ CREATE TABLE users ( photo text NOT NULL, password text NOT NULL, - metadata bytea NULL DEFAULT NULL + lang text NULL, + is_demo boolean NOT NULL DEFAULT false ); CREATE TABLE IF NOT EXISTS user_attrs ( @@ -31,7 +32,7 @@ CREATE TABLE IF NOT EXISTS tokens ( token text NOT NULL, created_at timestamptz NOT NULL DEFAULT clock_timestamp(), - used_at timestamptz DEFAULT NULL, + used_at timestamptz NULL, PRIMARY KEY (token, user_id) ); @@ -43,27 +44,31 @@ CREATE TABLE IF NOT EXISTS sessions ( modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), user_id uuid REFERENCES users(id) ON DELETE CASCADE, - user_agent TEXT NULL + user_agent text NULL ); -- Insert a placeholder system user. -INSERT INTO users (id, fullname, username, email, photo, password, metadata) +INSERT INTO users (id, fullname, username, email, photo, password) VALUES ('00000000-0000-0000-0000-000000000000'::uuid, 'System User', '00000000-0000-0000-0000-000000000000', 'system@uxbox.io', '', - '!', - '{}'); + '!'); CREATE UNIQUE INDEX users__username__idx ON users (username) - WHERE deleted_at is null; + WHERE deleted_at IS null; CREATE UNIQUE INDEX users__email__idx ON users (email) - WHERE deleted_at is null; + WHERE deleted_at IS null; + +CREATE INDEX users__is_demo + ON users(is_demo) + WHERE deleted_at IS null + AND is_demo IS true; CREATE TRIGGER users__modified_at__tgr BEFORE UPDATE ON users diff --git a/backend/resources/migrations/0003.projects.sql b/backend/resources/migrations/0003.projects.sql index 5826f1345..b96a53f18 100644 --- a/backend/resources/migrations/0003.projects.sql +++ b/backend/resources/migrations/0003.projects.sql @@ -8,8 +8,7 @@ CREATE TABLE IF NOT EXISTS projects ( modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), deleted_at timestamptz DEFAULT NULL, - name text NOT NULL, - metadata bytea NULL DEFAULT NULL + name text NOT NULL ); CREATE TABLE IF NOT EXISTS project_users ( @@ -33,9 +32,7 @@ CREATE TABLE IF NOT EXISTS project_files ( created_at timestamptz NOT NULL DEFAULT clock_timestamp(), modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), - deleted_at timestamptz DEFAULT NULL, - - metadata bytea NULL DEFAULT NULL + deleted_at timestamptz DEFAULT NULL ); CREATE TABLE IF NOT EXISTS project_file_users ( diff --git a/backend/src/uxbox/config.clj b/backend/src/uxbox/config.clj index 889744ac7..173af0f95 100644 --- a/backend/src/uxbox/config.clj +++ b/backend/src/uxbox/config.clj @@ -58,6 +58,7 @@ :smtp-ssl (lookup-env env :uxbox-smtp-ssl false) :smtp-enabled (lookup-env env :uxbox-smtp-enabled false) + :allow-demo-users (lookup-env env :uxbox-allow-demo-users true) :registration-enabled (lookup-env env :uxbox-registration-enabled true)}) (defn read-test-config diff --git a/backend/src/uxbox/fixtures.clj b/backend/src/uxbox/fixtures.clj index 86a8e6fb6..72ac7bcae 100644 --- a/backend/src/uxbox/fixtures.clj +++ b/backend/src/uxbox/fixtures.clj @@ -77,7 +77,6 @@ (> user-index 0)) (create-additional-project-user conn [project-index user-index]))))) - ;; --- Create Page Files (def create-file-sql diff --git a/backend/src/uxbox/http/handlers.clj b/backend/src/uxbox/http/handlers.clj index 734bf73fd..e4efe4b7f 100644 --- a/backend/src/uxbox/http/handlers.clj +++ b/backend/src/uxbox/http/handlers.clj @@ -22,7 +22,8 @@ (derive :logout ::unauthenticated) (derive :register-profile ::unauthenticated) (derive :request-profile-recovery ::unauthenticated) - (derive :recover-profile ::unauthenticated))) + (derive :recover-profile ::unauthenticated) + (derive :create-demo-profile ::unauthenticated))) (def query-types-hierarchy (make-hierarchy)) diff --git a/backend/src/uxbox/services/init.clj b/backend/src/uxbox/services/init.clj index 6bc9e8963..348cd2f1a 100644 --- a/backend/src/uxbox/services/init.clj +++ b/backend/src/uxbox/services/init.clj @@ -19,7 +19,7 @@ (require 'uxbox.services.queries.projects) (require 'uxbox.services.queries.project-files) (require 'uxbox.services.queries.project-pages) - (require 'uxbox.services.queries.users) + (require 'uxbox.services.queries.profile) (require 'uxbox.services.queries.user-attrs)) (defn- load-mutation-services diff --git a/backend/src/uxbox/services/mutations/demo.clj b/backend/src/uxbox/services/mutations/demo.clj new file mode 100644 index 000000000..79e54db04 --- /dev/null +++ b/backend/src/uxbox/services/mutations/demo.clj @@ -0,0 +1,52 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2016-2020 Andrey Antukh + +(ns uxbox.services.mutations.demo + "A demo specific mutations." + (:require + [clojure.spec.alpha :as s] + [datoteka.core :as fs] + [datoteka.storages :as ds] + [promesa.core :as p] + [promesa.exec :as px] + [sodi.prng] + [sodi.pwhash] + [sodi.util] + [uxbox.common.exceptions :as ex] + [uxbox.common.spec :as us] + [uxbox.config :as cfg] + [uxbox.db :as db] + [uxbox.emails :as emails] + [uxbox.images :as images] + [uxbox.media :as media] + [uxbox.services.mutations :as sm] + [uxbox.services.util :as su] + [uxbox.services.mutations.profile :as profile] + [uxbox.util.blob :as blob] + [uxbox.util.uuid :as uuid] + [vertx.core :as vc])) + +(su/defstr sql:create-demo-user + "insert into users (id, fullname, username, email, password, photo, is_demo) + values ($1, $2, $3, $4, $5, '', true) returning *") + +(sm/defmutation ::create-demo-profile + [params] + (let [id (uuid/next) + sem (System/currentTimeMillis) + username (str "demo-" sem) + email (str username ".demo@uxbox.io") + fullname (str "Demo User " sem) + password (-> (sodi.prng/random-bytes 12) + (sodi.util/bytes->b64s)) + password' (sodi.pwhash/derive password)] + (db/with-atomic [conn db/pool] + (db/query-one conn [sql:create-demo-user id fullname username email password']) + {:username username + :password password}))) diff --git a/backend/src/uxbox/services/mutations/profile.clj b/backend/src/uxbox/services/mutations/profile.clj index 7aa2b7ddf..55517ba1e 100644 --- a/backend/src/uxbox/services/mutations/profile.clj +++ b/backend/src/uxbox/services/mutations/profile.clj @@ -26,10 +26,7 @@ [uxbox.media :as media] [uxbox.services.mutations :as sm] [uxbox.services.util :as su] - [uxbox.services.queries.users :refer [get-profile - decode-profile-row - strip-private-attrs - resolve-thumbnail]] + [uxbox.services.queries.profile :as profile] [uxbox.util.blob :as blob] [uxbox.util.uuid :as uuid] [vertx.core :as vc])) @@ -125,8 +122,7 @@ email fullname (blob/encode metadata)]] (-> (db/query-one conn sqlv) (p/then' su/raise-not-found-if-nil) - (p/then' decode-profile-row) - (p/then' strip-private-attrs)))) + (p/then' profile/strip-private-attrs)))) (s/def ::update-profile (s/keys :req-un [::id ::username ::email ::fullname ::metadata])) @@ -142,7 +138,7 @@ (defn- validate-password [conn {:keys [user old-password] :as params}] - (p/let [profile (get-profile conn user) + (p/let [profile (profile/retrieve-profile conn user) result (sodi.pwhash/verify old-password (:password profile))] (when-not (:valid result) (ex/raise :type :validation @@ -205,8 +201,7 @@ returning id, photo"] (-> (db/query-one db/pool [sql (str path) user]) (p/then' su/raise-not-found-if-nil) - ;; (p/then' strip-private-attrs) - (p/then resolve-thumbnail))))] + (p/then profile/resolve-thumbnail))))] (when-not (valid-image-types? (:mtype file)) (ex/raise :type :validation @@ -218,9 +213,9 @@ ;; --- Mutation: Register Profile -(def ^:private create-user-sql - "insert into users (id, fullname, username, email, password, metadata, photo) - values ($1, $2, $3, $4, $5, $6, '') returning *") +(su/defstr sql:create-user + "insert into users (id, fullname, username, email, password, photo) + values ($1, $2, $3, $4, $5, '') returning *") (defn- check-profile-existence! [conn {:keys [username email] :as params}] @@ -239,24 +234,21 @@ (defn create-profile "Create the user entry on the database with limited input filling all the other fields with defaults." - [conn {:keys [id username fullname email password metadata] :as params}] + [conn {:keys [id username fullname email password] :as params}] (let [id (or id (uuid/next)) - metadata (blob/encode metadata) password (sodi.pwhash/derive password) - sqlv [create-user-sql + sqlv [sql:create-user id fullname username email - password - metadata]] - (-> (db/query-one conn sqlv) - (p/then' decode-profile-row)))) + password]] + (db/query-one conn sqlv))) (defn register-profile [conn params] (-> (create-profile conn params) - (p/then' strip-private-attrs) + (p/then' profile/strip-private-attrs) (p/then (fn [profile] (-> (emails/send! emails/register {:to (:email params) :name (:fullname params)}) @@ -328,3 +320,5 @@ (db/with-atomic [conn db/pool] (-> (validate-token conn token) (p/then (fn [user-id] (update-password conn user-id))))))) + + diff --git a/backend/src/uxbox/services/queries/users.clj b/backend/src/uxbox/services/queries/profile.clj similarity index 82% rename from backend/src/uxbox/services/queries/users.clj rename to backend/src/uxbox/services/queries/profile.clj index e6f228340..c8dbdf7e5 100644 --- a/backend/src/uxbox/services/queries/users.clj +++ b/backend/src/uxbox/services/queries/profile.clj @@ -4,7 +4,7 @@ ;; ;; Copyright (c) 2016 Andrey Antukh -(ns uxbox.services.queries.users +(ns uxbox.services.queries.profile (:require [clojure.spec.alpha :as s] [promesa.core :as p] @@ -18,7 +18,6 @@ ;; --- Helpers & Specs -(declare decode-profile-row) (declare strip-private-attrs) (s/def ::email ::us/email) @@ -42,28 +41,21 @@ (-> (px/submit! #(images/populate-thumbnails user opts)) (su/handle-on-context)))) -(defn get-profile +(defn retrieve-profile [conn id] (let [sql "select * from users where id=$1 and deleted_at is null"] - (-> (db/query-one db/pool [sql id]) - (p/then' decode-profile-row)))) + (db/query-one db/pool [sql id]))) (s/def ::profile (s/keys :req-un [::user])) (sq/defquery ::profile [{:keys [user] :as params}] - (-> (get-profile db/pool user) + (-> (retrieve-profile db/pool user) (p/then' strip-private-attrs))) ;; --- Attrs Helpers -(defn decode-profile-row - [{:keys [metadata] :as row}] - (when row - (cond-> row - metadata (assoc :metadata (blob/decode metadata))))) - (defn strip-private-attrs "Only selects a publicy visible user attrs." [profile] diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 0335ecf19..8f134c1ff 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -1,97 +1,4 @@ { - "auth.email-or-username" : { - "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:61" ], - "translations" : { - "en" : "Email or Username", - "fr" : "adresse email ou nom d'utilisateur" - } - }, - "auth.forgot-password" : { - "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:83" ], - "translations" : { - "en" : "Forgot your password?", - "fr" : "Mot de passe oublié ?" - } - }, - - "profile.recovery.password-changed" : { - "used-in" : [ "src/uxbox/main/data/auth.cljs:178" ], - "translations" : { - "en" : "Password successfully changed", - "fr" : "TODO" - } - }, - - "profile.recovery.username-or-email": { - "translations" : { - "en" : "Username or Email Address", - "fr" : "adresse email ou nom d'utilisateur" - } - }, - - "profile.recovery.token": { - "translations" : { - "en" : "Recovery token (sent by email)", - "fr" : null - } - }, - - "profile.recovery.password": { - "translations" : { - "en" : "Type a new password", - "fr" : null - } - }, - - "profile.recovery.submit-request": { - "translations" : { - "en" : "Recover Password", - "fr" : null - } - }, - - "profile.recovery.submit-recover": { - "translations" : { - "en" : "Change your password", - "fr" : null - } - }, - - "profile.recovery.go-to-login": { - "translations" : { - "en" : "Go back!", - "fr" : "Retour!" - } - }, - - "profile.recovery.recovery-token-sent" : { - "used-in" : [ "src/uxbox/main/data/auth.cljs:141" ], - "translations" : { - "en" : "Password recovery link sent to your inbox.", - "fr" : "Lien de récupération de mot de passe envoyé." - } - }, - "auth.no-account" : { - "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:86" ], - "translations" : { - "en" : "Don't have an account?", - "fr" : "Vous n'avez pas de compte ?" - } - }, - "auth.password" : { - "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:70" ], - "translations" : { - "en" : "Password", - "fr" : "Mot de passe" - } - }, - "auth.signin" : { - "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:77" ], - "translations" : { - "en" : "Sign in", - "fr" : "Se connecter" - } - }, "ds.accept" : { "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:113" ], "translations" : { @@ -107,14 +14,21 @@ } }, "ds.color-lightbox.add" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:52" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:49", "src/uxbox/main/ui/dashboard/colors.cljs:52" ], "translations" : { "en" : "+ Add color", "fr" : "+ Ajouter couleur" } }, + "ds.color-lightbox.title" : { + "translations" : { + "en" : null, + "fr" : null + }, + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:43" ] + }, "ds.color-new" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:149" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:146", "src/uxbox/main/ui/dashboard/colors.cljs:149" ], "translations" : { "en" : "+ New color", "fr" : "+ Nouvelle couleur" @@ -128,7 +42,7 @@ } }, "ds.colors-collection.new" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:134" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:131", "src/uxbox/main/ui/dashboard/colors.cljs:134" ], "translations" : { "en" : "+ New library", "fr" : "+ Nouvelle librairie" @@ -233,35 +147,35 @@ } }, "ds.multiselect-bar.copy" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:196", "src/uxbox/main/ui/dashboard/images.cljs:171", "src/uxbox/main/ui/dashboard/colors.cljs:224", "src/uxbox/main/ui/dashboard/colors.cljs:201" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:221", "src/uxbox/main/ui/dashboard/colors.cljs:198", "src/uxbox/main/ui/dashboard/images.cljs:196", "src/uxbox/main/ui/dashboard/images.cljs:171", "src/uxbox/main/ui/dashboard/colors.cljs:224", "src/uxbox/main/ui/dashboard/colors.cljs:201" ], "translations" : { "en" : "Copy", "fr" : "Copier" } }, "ds.multiselect-bar.copy-to-library" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:200", "src/uxbox/main/ui/dashboard/images.cljs:175", "src/uxbox/main/ui/dashboard/colors.cljs:228", "src/uxbox/main/ui/dashboard/colors.cljs:205" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:225", "src/uxbox/main/ui/dashboard/colors.cljs:202", "src/uxbox/main/ui/dashboard/images.cljs:200", "src/uxbox/main/ui/dashboard/images.cljs:175", "src/uxbox/main/ui/dashboard/colors.cljs:228", "src/uxbox/main/ui/dashboard/colors.cljs:205" ], "translations" : { "en" : "Copy to library", "fr" : "Copier vers la librairie" } }, "ds.multiselect-bar.delete" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:190", "src/uxbox/main/ui/dashboard/colors.cljs:217" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:214", "src/uxbox/main/ui/dashboard/images.cljs:190", "src/uxbox/main/ui/dashboard/colors.cljs:217" ], "translations" : { "en" : "Delete", "fr" : "Supprimer" } }, "ds.multiselect-bar.move" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:179", "src/uxbox/main/ui/dashboard/colors.cljs:209" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:206", "src/uxbox/main/ui/dashboard/images.cljs:179", "src/uxbox/main/ui/dashboard/colors.cljs:209" ], "translations" : { "en" : "Move", "fr" : "Déplacer" } }, "ds.multiselect-bar.move-to-library" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:183", "src/uxbox/main/ui/dashboard/colors.cljs:213" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:210", "src/uxbox/main/ui/dashboard/images.cljs:183", "src/uxbox/main/ui/dashboard/colors.cljs:213" ], "translations" : { "en" : "Move to library", "fr" : "Déplacer vers la librairie" @@ -275,7 +189,7 @@ } }, "ds.new-file" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:143" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:142", "src/uxbox/main/ui/dashboard/projects.cljs:143" ], "translations" : { "en" : "+ New File", "fr" : null @@ -303,7 +217,7 @@ } }, "ds.search.placeholder" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:192" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:191", "src/uxbox/main/ui/dashboard/projects.cljs:192" ], "translations" : { "en" : "Search...", "fr" : "Rechercher..." @@ -316,13 +230,6 @@ "fr" : null } }, - "workspace.sidebar.layers" : { - "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/layers.cljs:260" ], - "translations" : { - "en" : "Layers", - "fr" : "Couches" - } - }, "ds.size" : { "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:33" ], "translations" : { @@ -331,7 +238,7 @@ } }, "ds.store-colors-title" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:129" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:126", "src/uxbox/main/ui/dashboard/colors.cljs:129" ], "translations" : { "en" : "COLORS STORE", "fr" : "BOUTIQUE" @@ -352,14 +259,14 @@ } }, "ds.updated-at" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:110" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:109", "src/uxbox/main/ui/dashboard/projects.cljs:110" ], "translations" : { "en" : "Updated %s", "fr" : "Mis à jour %s" } }, "ds.uploaded-at" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:237", "src/uxbox/main/ui/dashboard/icons.cljs:303" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:303", "src/uxbox/main/ui/dashboard/images.cljs:237" ], "translations" : { "en" : "Uploaded at %s", "fr" : "Mise en ligne : %s" @@ -401,7 +308,7 @@ } }, "ds.your-colors-title" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:126" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:123", "src/uxbox/main/ui/dashboard/colors.cljs:126" ], "translations" : { "en" : "YOUR COLORS", "fr" : "VOS COULEURS" @@ -429,42 +336,35 @@ } }, "errors.api.form.registration-disabled" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:39" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:39", "src/uxbox/main/ui/auth/register.cljs:39" ], "translations" : { "en" : "The registration is currently disabled.", "fr" : "L'enregistrement est actuellement désactivé." } }, "errors.api.form.unexpected-error" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:51" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:51", "src/uxbox/main/ui/auth/register.cljs:51" ], "translations" : { "en" : "An unexpected error occurred.", "fr" : "Une erreur inattendue c'est produite" } }, - "profile.recovery.invalid-token" : { - "used-in" : [ "src/uxbox/main/data/auth.cljs:174", "src/uxbox/main/data/auth.cljs:151" ], - "translations" : { - "en" : "The recovery token is invalid.", - "fr" : "Le jeton de récupération n'est pas valide." - } - }, "errors.auth.unauthorized" : { - "used-in" : [ "src/uxbox/main/data/auth.cljs:59" ], + "used-in" : [ "src/uxbox/main/data/auth.cljs:62", "src/uxbox/main/data/auth.cljs:59" ], "translations" : { "en" : "Username or password seems to be wrong.", "fr" : "Le nom d'utilisateur ou le mot de passe semble être faux." } }, "errors.generic" : { - "used-in" : [ "src/uxbox/main/ui.cljs:86" ], + "used-in" : [ "src/uxbox/main/ui.cljs:127", "src/uxbox/main/ui.cljs:86" ], "translations" : { "en" : "Something wrong has happened.", "fr" : "Quelque chose c'est mal passé." } }, "errors.network" : { - "used-in" : [ "src/uxbox/main/ui.cljs:80" ], + "used-in" : [ "src/uxbox/main/ui.cljs:121", "src/uxbox/main/ui.cljs:80" ], "translations" : { "en" : "Unable to connect to backend server.", "fr" : "Impossible de se connecter au serveur principal." @@ -512,34 +412,160 @@ "fr" : "Envoyer un fichier" } }, + "login.create-demo-profile" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:92" ], + "translations" : { + "en" : "Create demo account", + "fr" : null + } + }, + "login.create-demo-profile-description" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:91" ], + "translations" : { + "en" : "Will be deleted in 24 hours since creation", + "fr" : null + } + }, + "login.email-or-username" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:63", "src/uxbox/main/ui/auth/login.cljs:61" ], + "translations" : { + "en" : "Email or Username", + "fr" : "adresse email ou nom d'utilisateur" + } + }, + "login.forgot-password" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:85", "src/uxbox/main/ui/auth/login.cljs:83" ], + "translations" : { + "en" : "Forgot your password?", + "fr" : "Mot de passe oublié ?" + } + }, + "login.password" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:72", "src/uxbox/main/ui/auth/login.cljs:70" ], + "translations" : { + "en" : "Password", + "fr" : "Mot de passe" + } + }, + "login.register" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:88", "src/uxbox/main/ui/auth/login.cljs:86" ], + "translations" : { + "en" : "Don't have an account?", + "fr" : "Vous n'avez pas de compte ?" + } + }, + "login.submit" : { + "used-in" : [ "src/uxbox/main/ui/login.cljs:79", "src/uxbox/main/ui/auth/login.cljs:77" ], + "translations" : { + "en" : "Sign in", + "fr" : "Se connecter" + } + }, + "profile.recovery.go-to-login" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:81", "src/uxbox/main/ui/profile/recovery_request.cljs:64" ], + "translations" : { + "en" : "Go back!", + "fr" : "Retour!" + } + }, + "profile.recovery.invalid-token" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:45", "src/uxbox/main/data/auth.cljs:174", "src/uxbox/main/data/auth.cljs:151" ], + "translations" : { + "en" : "The recovery token is invalid.", + "fr" : "Le jeton de récupération n'est pas valide." + } + }, + "profile.recovery.password" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:70" ], + "translations" : { + "en" : "Type a new password", + "fr" : null + } + }, + "profile.recovery.password-changed" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:40", "src/uxbox/main/data/auth.cljs:178" ], + "translations" : { + "en" : "Password successfully changed", + "fr" : "TODO" + } + }, + "profile.recovery.recovery-token-sent" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery_request.cljs:38", "src/uxbox/main/data/auth.cljs:141" ], + "translations" : { + "en" : "Password recovery link sent to your inbox.", + "fr" : "Lien de récupération de mot de passe envoyé." + } + }, + "profile.recovery.submit-recover" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:76" ], + "translations" : { + "en" : "Change your password", + "fr" : null + } + }, + "profile.recovery.submit-request" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery_request.cljs:59" ], + "translations" : { + "en" : "Recover Password", + "fr" : null + } + }, + "profile.recovery.token" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:61" ], + "translations" : { + "en" : "Recovery token (sent by email)", + "fr" : null + } + }, + "profile.recovery.username-or-email" : { + "used-in" : [ "src/uxbox/main/ui/profile/recovery_request.cljs:53" ], + "translations" : { + "en" : "Username or Email Address", + "fr" : "adresse email ou nom d'utilisateur" + } + }, "profile.register.already-have-account" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:131" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:131", "src/uxbox/main/ui/auth/register.cljs:131" ], "translations" : { "en" : "Already have an account?", "fr" : "Vous avez déjà un compte ?" } }, + "profile.register.email" : { + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:101", "src/uxbox/main/ui/settings/profile.cljs:111", "src/uxbox/main/ui/auth/register.cljs:101" ], + "translations" : { + "en" : "Your email", + "fr" : "Votre adresse email" + } + }, "profile.register.fullname" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:72" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:72", "src/uxbox/main/ui/auth/register.cljs:72" ], "translations" : { "en" : "Full Name", "fr" : "Nom complet" } }, "profile.register.get-started" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:127" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:127", "src/uxbox/main/ui/auth/register.cljs:127" ], "translations" : { "en" : "Get started", "fr" : "Commencer" } }, "profile.register.password" : { - "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:115" ], + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:115", "src/uxbox/main/ui/auth/register.cljs:115" ], "translations" : { "en" : "Password", "fr" : "Mot de passe" } }, + "profile.register.username" : { + "used-in" : [ "src/uxbox/main/ui/profile/register.cljs:87", "src/uxbox/main/ui/settings/profile.cljs:98", "src/uxbox/main/ui/auth/register.cljs:87" ], + "translations" : { + "en" : "Your username", + "fr" : "Votre nom d'utilisateur" + } + }, "settings.notifications" : { "used-in" : [ "src/uxbox/main/ui/settings/header.cljs:43" ], "translations" : { @@ -659,12 +685,12 @@ "fr" : "Votre avatar" } }, - "profile.register.email" : { - "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:111", "src/uxbox/main/ui/auth/register.cljs:101" ], + "settings.profile.your-email" : { "translations" : { - "en" : "Your email", - "fr" : "Votre adresse email" - } + "en" : null, + "fr" : null + }, + "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:111" ] }, "settings.profile.your-name" : { "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:86" ], @@ -673,12 +699,12 @@ "fr" : "Votre nom complet" } }, - "profile.register.username" : { - "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98", "src/uxbox/main/ui/auth/register.cljs:87" ], + "settings.profile.your-username" : { "translations" : { - "en" : "Your username", - "fr" : "Votre nom d'utilisateur" - } + "en" : null, + "fr" : null + }, + "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98" ] }, "settings.update-settings" : { "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:130", "src/uxbox/main/ui/settings/password.cljs:86", "src/uxbox/main/ui/settings/notifications.cljs:42" ], @@ -793,7 +819,7 @@ } }, "workspace.options.color" : { - "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:125", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47" ], + "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:125" ], "translations" : { "en" : "Color", "fr" : "Couleur" @@ -821,7 +847,7 @@ } }, "workspace.options.grid-options" : { - "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:113" ], + "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:113" ], "translations" : { "en" : "Grid settings", "fr" : "Paramètres de la grille" @@ -863,7 +889,7 @@ } }, "workspace.options.size" : { - "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:72", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:115", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:69", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:38" ], + "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:72", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:69", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:38", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:115" ], "translations" : { "en" : "Size", "fr" : "Taille" @@ -925,8 +951,15 @@ "fr" : "Alignement de texte" } }, + "workspace.sidebar.layers" : { + "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/layers.cljs:261", "src/uxbox/main/ui/workspace/sidebar/layers.cljs:260" ], + "translations" : { + "en" : "Layers", + "fr" : "Couches" + } + }, "workspace.sidebar.sitemap" : { - "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:134" ], + "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:135", "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:134" ], "translations" : { "en" : "Sitemap", "fr" : "Plan du site" diff --git a/frontend/src/uxbox/main/data/auth.cljs b/frontend/src/uxbox/main/data/auth.cljs index d72369579..b7b667ae9 100644 --- a/frontend/src/uxbox/main/data/auth.cljs +++ b/frontend/src/uxbox/main/data/auth.cljs @@ -150,3 +150,12 @@ (rx/catch (fn [err] (on-error) (rx/empty))))))) + +;; --- Create Demo Profile + +(def create-demo-profile + (ptk/reify ::create-demo-profile + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :create-demo-profile {}) + (rx/map login))))) diff --git a/frontend/src/uxbox/main/ui/login.cljs b/frontend/src/uxbox/main/ui/login.cljs index 7fcbfacac..6aa5b87e2 100644 --- a/frontend/src/uxbox/main/ui/login.cljs +++ b/frontend/src/uxbox/main/ui/login.cljs @@ -45,7 +45,6 @@ [:strong "DO NOT USE"] " for real work, " " the projects will be periodicaly wiped."]]) - (mf/defc login-form [] (let [{:keys [data] :as form} (fm/use-form ::login-form {})] @@ -61,7 +60,7 @@ :class (fm/error-class form :username) :on-blur (fm/on-input-blur form :username) :on-change (fm/on-input-change form :username) - :placeholder (tr "auth.email-or-username") + :placeholder (tr "login.email-or-username") :type "text"}] [:input.input-text {:name "password" @@ -70,23 +69,27 @@ :class (fm/error-class form :password) :on-blur (fm/on-input-blur form :password) :on-change (fm/on-input-change form :password) - :placeholder (tr "auth.password") + :placeholder (tr "login.password") :type "password"}] [:input.btn-primary {:name "login" :tab-index "4" :class (when-not (:valid form) "btn-disabled") :disabled (not (:valid form)) - :value (tr "auth.signin") + :value (tr "login.submit") :type "submit"}] [:div.login-links [:a {:on-click #(st/emit! (rt/nav :profile-recovery-request)) :tab-index "5"} - (tr "auth.forgot-password")] + (tr "login.forgot-password")] [:a {:on-click #(st/emit! (rt/nav :profile-register)) :tab-index "6"} - (tr "auth.no-account")]]]])) + (tr "login.register")] + [:a {:on-click #(st/emit! da/create-demo-profile) + :tab-index "7" + :title (tr "login.create-demo-profile-description")} + (tr "login.create-demo-profile")]]]])) (mf/defc login-page []