🎉 Add the ability to create demo user on demand.

This commit is contained in:
Andrey Antukh 2020-01-14 13:13:10 +01:00
parent b0ca6493e3
commit e42ccf932e
12 changed files with 285 additions and 199 deletions

View file

@ -3,7 +3,7 @@ CREATE TABLE users (
created_at timestamptz NOT NULL DEFAULT clock_timestamp(), created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
modified_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 '', fullname text NOT NULL DEFAULT '',
username text NOT NULL, username text NOT NULL,
@ -11,7 +11,8 @@ CREATE TABLE users (
photo text NOT NULL, photo text NOT NULL,
password 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 ( CREATE TABLE IF NOT EXISTS user_attrs (
@ -31,7 +32,7 @@ CREATE TABLE IF NOT EXISTS tokens (
token text NOT NULL, token text NOT NULL,
created_at timestamptz NOT NULL DEFAULT clock_timestamp(), created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
used_at timestamptz DEFAULT NULL, used_at timestamptz NULL,
PRIMARY KEY (token, user_id) PRIMARY KEY (token, user_id)
); );
@ -43,27 +44,31 @@ CREATE TABLE IF NOT EXISTS sessions (
modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),
user_id uuid REFERENCES users(id) ON DELETE CASCADE, user_id uuid REFERENCES users(id) ON DELETE CASCADE,
user_agent TEXT NULL user_agent text NULL
); );
-- Insert a placeholder system user. -- 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, VALUES ('00000000-0000-0000-0000-000000000000'::uuid,
'System User', 'System User',
'00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000000',
'system@uxbox.io', 'system@uxbox.io',
'', '',
'!', '!');
'{}');
CREATE UNIQUE INDEX users__username__idx CREATE UNIQUE INDEX users__username__idx
ON users (username) ON users (username)
WHERE deleted_at is null; WHERE deleted_at IS null;
CREATE UNIQUE INDEX users__email__idx CREATE UNIQUE INDEX users__email__idx
ON users (email) 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 CREATE TRIGGER users__modified_at__tgr
BEFORE UPDATE ON users BEFORE UPDATE ON users

View file

@ -8,8 +8,7 @@ CREATE TABLE IF NOT EXISTS projects (
modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),
deleted_at timestamptz DEFAULT NULL, deleted_at timestamptz DEFAULT NULL,
name text NOT NULL, name text NOT NULL
metadata bytea NULL DEFAULT NULL
); );
CREATE TABLE IF NOT EXISTS project_users ( 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(), created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
modified_at timestamptz NOT NULL DEFAULT clock_timestamp(), modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),
deleted_at timestamptz DEFAULT NULL, deleted_at timestamptz DEFAULT NULL
metadata bytea NULL DEFAULT NULL
); );
CREATE TABLE IF NOT EXISTS project_file_users ( CREATE TABLE IF NOT EXISTS project_file_users (

View file

@ -58,6 +58,7 @@
:smtp-ssl (lookup-env env :uxbox-smtp-ssl false) :smtp-ssl (lookup-env env :uxbox-smtp-ssl false)
:smtp-enabled (lookup-env env :uxbox-smtp-enabled 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)}) :registration-enabled (lookup-env env :uxbox-registration-enabled true)})
(defn read-test-config (defn read-test-config

View file

@ -77,7 +77,6 @@
(> user-index 0)) (> user-index 0))
(create-additional-project-user conn [project-index user-index]))))) (create-additional-project-user conn [project-index user-index])))))
;; --- Create Page Files ;; --- Create Page Files
(def create-file-sql (def create-file-sql

View file

@ -22,7 +22,8 @@
(derive :logout ::unauthenticated) (derive :logout ::unauthenticated)
(derive :register-profile ::unauthenticated) (derive :register-profile ::unauthenticated)
(derive :request-profile-recovery ::unauthenticated) (derive :request-profile-recovery ::unauthenticated)
(derive :recover-profile ::unauthenticated))) (derive :recover-profile ::unauthenticated)
(derive :create-demo-profile ::unauthenticated)))
(def query-types-hierarchy (def query-types-hierarchy
(make-hierarchy)) (make-hierarchy))

View file

@ -19,7 +19,7 @@
(require 'uxbox.services.queries.projects) (require 'uxbox.services.queries.projects)
(require 'uxbox.services.queries.project-files) (require 'uxbox.services.queries.project-files)
(require 'uxbox.services.queries.project-pages) (require 'uxbox.services.queries.project-pages)
(require 'uxbox.services.queries.users) (require 'uxbox.services.queries.profile)
(require 'uxbox.services.queries.user-attrs)) (require 'uxbox.services.queries.user-attrs))
(defn- load-mutation-services (defn- load-mutation-services

View file

@ -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 <niwi@niwi.nz>
(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})))

View file

@ -26,10 +26,7 @@
[uxbox.media :as media] [uxbox.media :as media]
[uxbox.services.mutations :as sm] [uxbox.services.mutations :as sm]
[uxbox.services.util :as su] [uxbox.services.util :as su]
[uxbox.services.queries.users :refer [get-profile [uxbox.services.queries.profile :as profile]
decode-profile-row
strip-private-attrs
resolve-thumbnail]]
[uxbox.util.blob :as blob] [uxbox.util.blob :as blob]
[uxbox.util.uuid :as uuid] [uxbox.util.uuid :as uuid]
[vertx.core :as vc])) [vertx.core :as vc]))
@ -125,8 +122,7 @@
email fullname (blob/encode metadata)]] email fullname (blob/encode metadata)]]
(-> (db/query-one conn sqlv) (-> (db/query-one conn sqlv)
(p/then' su/raise-not-found-if-nil) (p/then' su/raise-not-found-if-nil)
(p/then' decode-profile-row) (p/then' profile/strip-private-attrs))))
(p/then' strip-private-attrs))))
(s/def ::update-profile (s/def ::update-profile
(s/keys :req-un [::id ::username ::email ::fullname ::metadata])) (s/keys :req-un [::id ::username ::email ::fullname ::metadata]))
@ -142,7 +138,7 @@
(defn- validate-password (defn- validate-password
[conn {:keys [user old-password] :as params}] [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))] result (sodi.pwhash/verify old-password (:password profile))]
(when-not (:valid result) (when-not (:valid result)
(ex/raise :type :validation (ex/raise :type :validation
@ -205,8 +201,7 @@
returning id, photo"] returning id, photo"]
(-> (db/query-one db/pool [sql (str path) user]) (-> (db/query-one db/pool [sql (str path) user])
(p/then' su/raise-not-found-if-nil) (p/then' su/raise-not-found-if-nil)
;; (p/then' strip-private-attrs) (p/then profile/resolve-thumbnail))))]
(p/then resolve-thumbnail))))]
(when-not (valid-image-types? (:mtype file)) (when-not (valid-image-types? (:mtype file))
(ex/raise :type :validation (ex/raise :type :validation
@ -218,9 +213,9 @@
;; --- Mutation: Register Profile ;; --- Mutation: Register Profile
(def ^:private create-user-sql (su/defstr sql:create-user
"insert into users (id, fullname, username, email, password, metadata, photo) "insert into users (id, fullname, username, email, password, photo)
values ($1, $2, $3, $4, $5, $6, '') returning *") values ($1, $2, $3, $4, $5, '') returning *")
(defn- check-profile-existence! (defn- check-profile-existence!
[conn {:keys [username email] :as params}] [conn {:keys [username email] :as params}]
@ -239,24 +234,21 @@
(defn create-profile (defn create-profile
"Create the user entry on the database with limited input "Create the user entry on the database with limited input
filling all the other fields with defaults." 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)) (let [id (or id (uuid/next))
metadata (blob/encode metadata)
password (sodi.pwhash/derive password) password (sodi.pwhash/derive password)
sqlv [create-user-sql sqlv [sql:create-user
id id
fullname fullname
username username
email email
password password]]
metadata]] (db/query-one conn sqlv)))
(-> (db/query-one conn sqlv)
(p/then' decode-profile-row))))
(defn register-profile (defn register-profile
[conn params] [conn params]
(-> (create-profile conn params) (-> (create-profile conn params)
(p/then' strip-private-attrs) (p/then' profile/strip-private-attrs)
(p/then (fn [profile] (p/then (fn [profile]
(-> (emails/send! emails/register {:to (:email params) (-> (emails/send! emails/register {:to (:email params)
:name (:fullname params)}) :name (:fullname params)})
@ -328,3 +320,5 @@
(db/with-atomic [conn db/pool] (db/with-atomic [conn db/pool]
(-> (validate-token conn token) (-> (validate-token conn token)
(p/then (fn [user-id] (update-password conn user-id))))))) (p/then (fn [user-id] (update-password conn user-id)))))))

View file

@ -4,7 +4,7 @@
;; ;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.services.queries.users (ns uxbox.services.queries.profile
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[promesa.core :as p] [promesa.core :as p]
@ -18,7 +18,6 @@
;; --- Helpers & Specs ;; --- Helpers & Specs
(declare decode-profile-row)
(declare strip-private-attrs) (declare strip-private-attrs)
(s/def ::email ::us/email) (s/def ::email ::us/email)
@ -42,28 +41,21 @@
(-> (px/submit! #(images/populate-thumbnails user opts)) (-> (px/submit! #(images/populate-thumbnails user opts))
(su/handle-on-context)))) (su/handle-on-context))))
(defn get-profile (defn retrieve-profile
[conn id] [conn id]
(let [sql "select * from users where id=$1 and deleted_at is null"] (let [sql "select * from users where id=$1 and deleted_at is null"]
(-> (db/query-one db/pool [sql id]) (db/query-one db/pool [sql id])))
(p/then' decode-profile-row))))
(s/def ::profile (s/def ::profile
(s/keys :req-un [::user])) (s/keys :req-un [::user]))
(sq/defquery ::profile (sq/defquery ::profile
[{:keys [user] :as params}] [{:keys [user] :as params}]
(-> (get-profile db/pool user) (-> (retrieve-profile db/pool user)
(p/then' strip-private-attrs))) (p/then' strip-private-attrs)))
;; --- Attrs Helpers ;; --- Attrs Helpers
(defn decode-profile-row
[{:keys [metadata] :as row}]
(when row
(cond-> row
metadata (assoc :metadata (blob/decode metadata)))))
(defn strip-private-attrs (defn strip-private-attrs
"Only selects a publicy visible user attrs." "Only selects a publicy visible user attrs."
[profile] [profile]

View file

@ -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" : { "ds.accept" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:113" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:113" ],
"translations" : { "translations" : {
@ -107,14 +14,21 @@
} }
}, },
"ds.color-lightbox.add" : { "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" : { "translations" : {
"en" : "+ Add color", "en" : "+ Add color",
"fr" : "+ Ajouter couleur" "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" : { "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" : { "translations" : {
"en" : "+ New color", "en" : "+ New color",
"fr" : "+ Nouvelle couleur" "fr" : "+ Nouvelle couleur"
@ -128,7 +42,7 @@
} }
}, },
"ds.colors-collection.new" : { "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" : { "translations" : {
"en" : "+ New library", "en" : "+ New library",
"fr" : "+ Nouvelle librairie" "fr" : "+ Nouvelle librairie"
@ -233,35 +147,35 @@
} }
}, },
"ds.multiselect-bar.copy" : { "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" : { "translations" : {
"en" : "Copy", "en" : "Copy",
"fr" : "Copier" "fr" : "Copier"
} }
}, },
"ds.multiselect-bar.copy-to-library" : { "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" : { "translations" : {
"en" : "Copy to library", "en" : "Copy to library",
"fr" : "Copier vers la librairie" "fr" : "Copier vers la librairie"
} }
}, },
"ds.multiselect-bar.delete" : { "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" : { "translations" : {
"en" : "Delete", "en" : "Delete",
"fr" : "Supprimer" "fr" : "Supprimer"
} }
}, },
"ds.multiselect-bar.move" : { "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" : { "translations" : {
"en" : "Move", "en" : "Move",
"fr" : "Déplacer" "fr" : "Déplacer"
} }
}, },
"ds.multiselect-bar.move-to-library" : { "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" : { "translations" : {
"en" : "Move to library", "en" : "Move to library",
"fr" : "Déplacer vers la librairie" "fr" : "Déplacer vers la librairie"
@ -275,7 +189,7 @@
} }
}, },
"ds.new-file" : { "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" : { "translations" : {
"en" : "+ New File", "en" : "+ New File",
"fr" : null "fr" : null
@ -303,7 +217,7 @@
} }
}, },
"ds.search.placeholder" : { "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" : { "translations" : {
"en" : "Search...", "en" : "Search...",
"fr" : "Rechercher..." "fr" : "Rechercher..."
@ -316,13 +230,6 @@
"fr" : null "fr" : null
} }
}, },
"workspace.sidebar.layers" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/layers.cljs:260" ],
"translations" : {
"en" : "Layers",
"fr" : "Couches"
}
},
"ds.size" : { "ds.size" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:33" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:33" ],
"translations" : { "translations" : {
@ -331,7 +238,7 @@
} }
}, },
"ds.store-colors-title" : { "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" : { "translations" : {
"en" : "COLORS STORE", "en" : "COLORS STORE",
"fr" : "BOUTIQUE" "fr" : "BOUTIQUE"
@ -352,14 +259,14 @@
} }
}, },
"ds.updated-at" : { "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" : { "translations" : {
"en" : "Updated %s", "en" : "Updated %s",
"fr" : "Mis à jour %s" "fr" : "Mis à jour %s"
} }
}, },
"ds.uploaded-at" : { "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" : { "translations" : {
"en" : "Uploaded at %s", "en" : "Uploaded at %s",
"fr" : "Mise en ligne : %s" "fr" : "Mise en ligne : %s"
@ -401,7 +308,7 @@
} }
}, },
"ds.your-colors-title" : { "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" : { "translations" : {
"en" : "YOUR COLORS", "en" : "YOUR COLORS",
"fr" : "VOS COULEURS" "fr" : "VOS COULEURS"
@ -429,42 +336,35 @@
} }
}, },
"errors.api.form.registration-disabled" : { "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" : { "translations" : {
"en" : "The registration is currently disabled.", "en" : "The registration is currently disabled.",
"fr" : "L'enregistrement est actuellement désactivé." "fr" : "L'enregistrement est actuellement désactivé."
} }
}, },
"errors.api.form.unexpected-error" : { "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" : { "translations" : {
"en" : "An unexpected error occurred.", "en" : "An unexpected error occurred.",
"fr" : "Une erreur inattendue c'est produite" "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" : { "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" : { "translations" : {
"en" : "Username or password seems to be wrong.", "en" : "Username or password seems to be wrong.",
"fr" : "Le nom d'utilisateur ou le mot de passe semble être faux." "fr" : "Le nom d'utilisateur ou le mot de passe semble être faux."
} }
}, },
"errors.generic" : { "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" : { "translations" : {
"en" : "Something wrong has happened.", "en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé." "fr" : "Quelque chose c'est mal passé."
} }
}, },
"errors.network" : { "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" : { "translations" : {
"en" : "Unable to connect to backend server.", "en" : "Unable to connect to backend server.",
"fr" : "Impossible de se connecter au serveur principal." "fr" : "Impossible de se connecter au serveur principal."
@ -512,34 +412,160 @@
"fr" : "Envoyer un fichier" "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" : { "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" : { "translations" : {
"en" : "Already have an account?", "en" : "Already have an account?",
"fr" : "Vous avez déjà un compte ?" "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" : { "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" : { "translations" : {
"en" : "Full Name", "en" : "Full Name",
"fr" : "Nom complet" "fr" : "Nom complet"
} }
}, },
"profile.register.get-started" : { "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" : { "translations" : {
"en" : "Get started", "en" : "Get started",
"fr" : "Commencer" "fr" : "Commencer"
} }
}, },
"profile.register.password" : { "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" : { "translations" : {
"en" : "Password", "en" : "Password",
"fr" : "Mot de passe" "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" : { "settings.notifications" : {
"used-in" : [ "src/uxbox/main/ui/settings/header.cljs:43" ], "used-in" : [ "src/uxbox/main/ui/settings/header.cljs:43" ],
"translations" : { "translations" : {
@ -659,12 +685,12 @@
"fr" : "Votre avatar" "fr" : "Votre avatar"
} }
}, },
"profile.register.email" : { "settings.profile.your-email" : {
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:111", "src/uxbox/main/ui/auth/register.cljs:101" ],
"translations" : { "translations" : {
"en" : "Your email", "en" : null,
"fr" : "Votre adresse email" "fr" : null
} },
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:111" ]
}, },
"settings.profile.your-name" : { "settings.profile.your-name" : {
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:86" ], "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:86" ],
@ -673,12 +699,12 @@
"fr" : "Votre nom complet" "fr" : "Votre nom complet"
} }
}, },
"profile.register.username" : { "settings.profile.your-username" : {
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98", "src/uxbox/main/ui/auth/register.cljs:87" ],
"translations" : { "translations" : {
"en" : "Your username", "en" : null,
"fr" : "Votre nom d'utilisateur" "fr" : null
} },
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98" ]
}, },
"settings.update-settings" : { "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" ], "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" : { "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" : { "translations" : {
"en" : "Color", "en" : "Color",
"fr" : "Couleur" "fr" : "Couleur"
@ -821,7 +847,7 @@
} }
}, },
"workspace.options.grid-options" : { "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" : { "translations" : {
"en" : "Grid settings", "en" : "Grid settings",
"fr" : "Paramètres de la grille" "fr" : "Paramètres de la grille"
@ -863,7 +889,7 @@
} }
}, },
"workspace.options.size" : { "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" : { "translations" : {
"en" : "Size", "en" : "Size",
"fr" : "Taille" "fr" : "Taille"
@ -925,8 +951,15 @@
"fr" : "Alignement de texte" "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" : { "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" : { "translations" : {
"en" : "Sitemap", "en" : "Sitemap",
"fr" : "Plan du site" "fr" : "Plan du site"

View file

@ -150,3 +150,12 @@
(rx/catch (fn [err] (rx/catch (fn [err]
(on-error) (on-error)
(rx/empty))))))) (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)))))

View file

@ -45,7 +45,6 @@
[:strong "DO NOT USE"] " for real work, " [:strong "DO NOT USE"] " for real work, "
" the projects will be periodicaly wiped."]]) " the projects will be periodicaly wiped."]])
(mf/defc login-form (mf/defc login-form
[] []
(let [{:keys [data] :as form} (fm/use-form ::login-form {})] (let [{:keys [data] :as form} (fm/use-form ::login-form {})]
@ -61,7 +60,7 @@
:class (fm/error-class form :username) :class (fm/error-class form :username)
:on-blur (fm/on-input-blur form :username) :on-blur (fm/on-input-blur form :username)
:on-change (fm/on-input-change form :username) :on-change (fm/on-input-change form :username)
:placeholder (tr "auth.email-or-username") :placeholder (tr "login.email-or-username")
:type "text"}] :type "text"}]
[:input.input-text [:input.input-text
{:name "password" {:name "password"
@ -70,23 +69,27 @@
:class (fm/error-class form :password) :class (fm/error-class form :password)
:on-blur (fm/on-input-blur form :password) :on-blur (fm/on-input-blur form :password)
:on-change (fm/on-input-change form :password) :on-change (fm/on-input-change form :password)
:placeholder (tr "auth.password") :placeholder (tr "login.password")
:type "password"}] :type "password"}]
[:input.btn-primary [:input.btn-primary
{:name "login" {:name "login"
:tab-index "4" :tab-index "4"
:class (when-not (:valid form) "btn-disabled") :class (when-not (:valid form) "btn-disabled")
:disabled (not (:valid form)) :disabled (not (:valid form))
:value (tr "auth.signin") :value (tr "login.submit")
:type "submit"}] :type "submit"}]
[:div.login-links [:div.login-links
[:a {:on-click #(st/emit! (rt/nav :profile-recovery-request)) [:a {:on-click #(st/emit! (rt/nav :profile-recovery-request))
:tab-index "5"} :tab-index "5"}
(tr "auth.forgot-password")] (tr "login.forgot-password")]
[:a {:on-click #(st/emit! (rt/nav :profile-register)) [:a {:on-click #(st/emit! (rt/nav :profile-register))
:tab-index "6"} :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 (mf/defc login-page
[] []