From e3891df243a85dc894fb3e7958051a92718e2f79 Mon Sep 17 00:00:00 2001 From: Andrey Antukh <niwi@niwi.nz> Date: Fri, 29 Jan 2021 17:18:53 +0100 Subject: [PATCH] :sparkles: Minor improvements on profile initial data. --- backend/src/app/config.clj | 8 +-- backend/src/app/db/profile_initial_data.clj | 80 +++++++++------------ backend/src/app/rpc/mutations/demo.clj | 10 ++- backend/src/app/rpc/mutations/profile.clj | 23 +++--- backend/src/app/srepl/main.clj | 18 ++--- 5 files changed, 67 insertions(+), 72 deletions(-) diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index 87357a8bc..1f0f7912b 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -70,8 +70,8 @@ :ldap-auth-fullname-attribute "displayName" :ldap-auth-avatar-attribute "jpegPhoto" - ;; :initial-data-project-name "Penpot Onboarding" - ;; :initial-data-file "/internal/initial-data.json" + ;; :initial-data-file "resources/initial-data.json" + ;; :initial-data-project-name "Penpot Oboarding" }) (s/def ::http-server-port ::us/integer) @@ -140,7 +140,7 @@ (s/def ::telemetry-server-enabled ::us/boolean) (s/def ::telemetry-server-port ::us/integer) -(s/def ::initial-data-project-id ::us/uuid) +(s/def ::initial-data-file ::us/string) (s/def ::initial-data-project-name ::us/string) (s/def ::config @@ -197,7 +197,7 @@ ::telemetry-server-enabled ::telemetry-server-port ::telemetry-uri - ::initial-data-project-id + ::initial-data-file ::initial-data-project-name])) (defn- env->config diff --git a/backend/src/app/db/profile_initial_data.clj b/backend/src/app/db/profile_initial_data.clj index 9366b9dd5..c10778077 100644 --- a/backend/src/app/db/profile_initial_data.clj +++ b/backend/src/app/db/profile_initial_data.clj @@ -13,12 +13,10 @@ [app.config :as cfg] [app.db :as db] [app.rpc.mutations.projects :as projects] - [app.storage :as storage] [app.util.transit :as tr] - [clojure.tools.logging :as log] - [cuerdas.core :as str]) - (:import java.io.FileOutputStream - java.io.FileInputStream)) + [clojure.java.io :as io] + [cuerdas.core :as str] + [datoteka.core :as fs])) (def sql:file "select * from file where project_id = ?") @@ -35,18 +33,10 @@ from file_media_object where file_id in (select id from file_ids)") -(def sql:file-media-thumbnail - "with file_ids as (select id from file where project_id = ?), - media_ids as (select id from file_media_object where file_id in (select id from file_ids)) - select * - from file_media_thumbnail - where media_object_id in (select id from media_ids)") - (defn change-ids "Given a collection and a map from ID to ID. Changes all the `keys` properties so they point to the new ID existing in `map-ids`" [map-ids coll keys] - (let [generate-id (fn [map-ids {:keys [id]}] (assoc map-ids id (uuid/next))) @@ -66,61 +56,57 @@ [new-map-ids (map (partial change-id new-map-ids) coll)])) (defn create-initial-data-dump - [conn project-id output-file] + [conn project-id output-path] (let [ ;; Retrieve data from templates + opath (fs/path output-path) file (db/exec! conn [sql:file, project-id]) file-library-rel (db/exec! conn [sql:file-library-rel, project-id]) file-media-object (db/exec! conn [sql:file-media-object, project-id]) - file-media-thumbnail (db/exec! conn [sql:file-media-thumbnail, project-id]) data {:file file :file-library-rel file-library-rel - :file-media-object file-media-object - :file-media-thumbnail file-media-thumbnail}] + :file-media-object file-media-object}] + (with-open [output (io/output-stream opath)] + (tr/encode-stream data output) + nil))) - (with-open [output (FileOutputStream. output-file)] - (tr/encode-stream data output)))) +(defn read-initial-data + [path] + (when (fs/exists? path) + (with-open [input (io/input-stream (fs/path path))] + (tr/decode-stream input)))) (defn create-profile-initial-data - [conn storage profile] - - (let [initial-data-file (get cfg/config :initial-data-file) - initial-data (when initial-data-file - (with-open [input (FileInputStream. initial-data-file)] - (tr/decode-stream input)))] - (when initial-data - (let [{:keys [file file-library-rel file-media-object file-media-thumbnail]} initial-data - - sample-project-name (get cfg/config :initial-data-project-name "Penpot Onboarding") - - + [conn profile] + (when-let [initial-data-path (:initial-data-file cfg/config)] + (when-let [{:keys [file file-library-rel file-media-object file-media-thumbnail]} (read-initial-data initial-data-path)] + (let [sample-project-name (:initial-data-project-name cfg/config "Penpot Onboarding") proj (projects/create-project conn {:profile-id (:id profile) :team-id (:default-team-id profile) :name sample-project-name}) - _ (projects/create-project-profile conn {:project-id (:id proj) - :profile-id (:id profile)}) - - _ (projects/create-team-project-profile conn {:team-id (:default-team-id profile) - :project-id (:id proj) - :profile-id (:id profile)}) - map-ids {} ;; Create new ID's and change the references - [map-ids file] (change-ids map-ids file #{:id}) - + [map-ids file] (change-ids map-ids file #{:id}) [map-ids file-library-rel] (change-ids map-ids file-library-rel #{:file-id :library-file-id}) [map-ids file-media-object] (change-ids map-ids file-media-object #{:id :file-id :media-id :thumbnail-id}) [map-ids file-media-thumbnail] (change-ids map-ids file-media-thumbnail #{:id :media-object-id}) - file (->> file (map (fn [data] (assoc data :project-id (:id proj))))) - file-profile-rel (->> file (map (fn [data] - (hash-map :file-id (:id data) - :profile-id (:id profile) - :is-owner true - :is-admin true - :can-edit true))))] + file (map #(assoc % :project-id (:id proj)) file) + file-profile-rel (map #(array-map :file-id (:id %) + :profile-id (:id profile) + :is-owner true + :is-admin true + :can-edit true) + file)] + + (projects/create-project-profile conn {:project-id (:id proj) + :profile-id (:id profile)}) + + (projects/create-team-project-profile conn {:team-id (:default-team-id profile) + :project-id (:id proj) + :profile-id (:id profile)}) ;; Re-insert into the database (db/insert-multi! conn :file file) diff --git a/backend/src/app/rpc/mutations/demo.clj b/backend/src/app/rpc/mutations/demo.clj index 5ebe0b5cf..b7a5759f5 100644 --- a/backend/src/app/rpc/mutations/demo.clj +++ b/backend/src/app/rpc/mutations/demo.clj @@ -14,6 +14,7 @@ [app.common.exceptions :as ex] [app.config :as cfg] [app.db :as db] + [app.db.profile-initial-data :refer [create-profile-initial-data]] [app.rpc.mutations.profile :as profile] [app.tasks :as tasks] [app.util.services :as sv] @@ -27,7 +28,7 @@ [{:keys [pool] :as cfg} _] (let [id (uuid/next) sem (System/currentTimeMillis) - email (str "demo-" sem ".demo@nodomain.com") + email (str "demo-" sem ".demo@example.com") fullname (str "Demo User " sem) password (-> (bn/random-bytes 16) (bc/bytes->b64u) @@ -36,7 +37,8 @@ :email email :fullname fullname :demo? true - :password password}] + :password password + :props {:onboarding-viewed true}}] (when-not (:allow-demo-users cfg/config) (ex/raise :type :validation @@ -45,11 +47,13 @@ (db/with-atomic [conn pool] (->> (#'profile/create-profile conn params) - (#'profile/create-profile-relations conn)) + (#'profile/create-profile-relations conn) + (create-profile-initial-data conn)) ;; Schedule deletion of the demo profile (tasks/submit! conn {:name "delete-profile" :delay cfg/default-deletion-delay :props {:profile-id id}}) + {:email email :password password}))) diff --git a/backend/src/app/rpc/mutations/profile.clj b/backend/src/app/rpc/mutations/profile.clj index 3576a89c9..2ffad5f30 100644 --- a/backend/src/app/rpc/mutations/profile.clj +++ b/backend/src/app/rpc/mutations/profile.clj @@ -55,7 +55,7 @@ :opt-un [::token])) (sv/defmethod ::register-profile {:auth false :rlimit :password} - [{:keys [pool tokens session storage] :as cfg} {:keys [token] :as params}] + [{:keys [pool tokens session] :as cfg} {:keys [token] :as params}] (when-not (:registration-enabled cfg/config) (ex/raise :type :restriction :code :registration-disabled)) @@ -69,7 +69,7 @@ (check-profile-existence! conn params) (let [profile (->> (create-profile conn params) (create-profile-relations conn))] - (create-profile-initial-data conn storage profile) + (create-profile-initial-data conn profile) (if token ;; If token comes in params, this is because the user comes @@ -160,18 +160,21 @@ (defn- create-profile "Create the profile entry on the database with limited input filling all the other fields with defaults." - [conn {:keys [id fullname email password demo?] :as params}] + [conn {:keys [id fullname email password demo? props] :as params}] (let [id (or id (uuid/next)) demo? (if (boolean? demo?) demo? false) active? (if demo? true false) + props (db/tjson (or props {})) password (derive-password password)] - (db/insert! conn :profile - {:id id - :fullname fullname - :email (str/lower email) - :password password - :is-active active? - :is-demo demo?}))) + (-> (db/insert! conn :profile + {:id id + :fullname fullname + :email (str/lower email) + :password password + :props props + :is-active active? + :is-demo demo?}) + (update :props db/decode-transit-pgobject)))) (defn- create-profile-relations [conn profile] diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj index f62dfa91f..99a69b586 100644 --- a/backend/src/app/srepl/main.clj +++ b/backend/src/app/srepl/main.clj @@ -44,15 +44,17 @@ (update :data pmg/migrate-data))))) -;; Examples +;; Examples: ;; (def backup (update-file #uuid "1586e1f0-3e02-11eb-b1d2-556a2f641513" identity)) -;; (def x (update-file #uuid "1586e1f0-3e02-11eb-b1d2-556a2f641513" (fn [{:keys [data] :as file}] (update-in data [:pages-index #uuid "878278c0-3ef0-11eb-9d67-8551e7624f43" :objects] dissoc nil)))) +;; (def x (update-file +;; #uuid "1586e1f0-3e02-11eb-b1d2-556a2f641513" +;; (fn [{:keys [data] :as file}] +;; (update-in data [:pages-index #uuid "878278c0-3ef0-11eb-9d67-8551e7624f43" :objects] dissoc nil)))) + +(def default-project-id #uuid "5761a890-3b81-11eb-9e7d-556a2f641513") (defn initial-data-dump - ([system file] - (let [default-project-id #uuid "5761a890-3b81-11eb-9e7d-556a2f641513"] - (initial-data-dump system default-project-id file))) - - ([system project-id file] + ([system file] (initial-data-dump system default-project-id file)) + ([system project-id path] (db/with-atomic [conn (:app.db/pool system)] - (pid/create-initial-data-dump conn file)))) + (pid/create-initial-data-dump conn project-id path))))