mirror of
https://github.com/penpot/penpot.git
synced 2025-05-19 23:36:11 +02:00
commit
068a099f37
17 changed files with 138 additions and 81 deletions
|
@ -31,8 +31,8 @@ in the changelog.**
|
||||||
## Pull requests ##
|
## Pull requests ##
|
||||||
|
|
||||||
If you want propose a change or bug fix with the Pull-Request system
|
If you want propose a change or bug fix with the Pull-Request system
|
||||||
firstly you should carefully read the **Contributor License Aggreement**
|
firstly you should carefully read the **DCO** section and format your
|
||||||
section and format your commits accordingly.
|
commits accordingly.
|
||||||
|
|
||||||
If you intend to fix a bug it's fine to submit a pull request right
|
If you intend to fix a bug it's fine to submit a pull request right
|
||||||
away but we still recommend to file an issue detailing what you're
|
away but we still recommend to file an issue detailing what you're
|
||||||
|
|
|
@ -57,7 +57,6 @@
|
||||||
:registration-domain-whitelist ""
|
:registration-domain-whitelist ""
|
||||||
|
|
||||||
:telemetry-enabled false
|
:telemetry-enabled false
|
||||||
:telemetry-with-taiga true
|
|
||||||
:telemetry-uri "https://telemetry.penpot.app/"
|
:telemetry-uri "https://telemetry.penpot.app/"
|
||||||
|
|
||||||
;; LDAP auth disabled by default. Set ldap-auth-host to enable
|
;; LDAP auth disabled by default. Set ldap-auth-host to enable
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def initsql
|
(def initsql
|
||||||
(str "SET statement_timeout = 10000;\n"
|
(str "SET statement_timeout = 60000;\n"
|
||||||
"SET idle_in_transaction_session_timeout = 120000;"))
|
"SET idle_in_transaction_session_timeout = 120000;"))
|
||||||
|
|
||||||
(defn- create-datasource-config
|
(defn- create-datasource-config
|
||||||
|
|
|
@ -35,51 +35,40 @@
|
||||||
|
|
||||||
(defn- get-access-token
|
(defn- get-access-token
|
||||||
[cfg code]
|
[cfg code]
|
||||||
(let [params {:code code
|
(try
|
||||||
:client_id (:client-id cfg)
|
(let [params {:code code
|
||||||
:client_secret (:client-secret cfg)
|
:client_id (:client-id cfg)
|
||||||
:redirect_uri (build-redirect-url cfg)
|
:client_secret (:client-secret cfg)
|
||||||
:grant_type "authorization_code"}
|
:redirect_uri (build-redirect-url cfg)
|
||||||
req {:method :post
|
:grant_type "authorization_code"}
|
||||||
:headers {"content-type" "application/x-www-form-urlencoded"}
|
req {:method :post
|
||||||
:uri "https://oauth2.googleapis.com/token"
|
:headers {"content-type" "application/x-www-form-urlencoded"}
|
||||||
:body (uri/map->query-string params)}
|
:uri "https://oauth2.googleapis.com/token"
|
||||||
res (http/send! req)]
|
:body (uri/map->query-string params)}
|
||||||
|
res (http/send! req)]
|
||||||
|
|
||||||
(when (not= 200 (:status res))
|
(when (= 200 (:status res))
|
||||||
(ex/raise :type :internal
|
(-> (json/read-str (:body res))
|
||||||
:code :invalid-response-from-google
|
(get "access_token"))))
|
||||||
:context {:status (:status res)
|
|
||||||
:body (:body res)}))
|
|
||||||
|
|
||||||
(try
|
(catch Exception e
|
||||||
(let [data (json/read-str (:body res))]
|
(log/error e "unexpected error on get-access-token")
|
||||||
(get data "access_token"))
|
nil)))
|
||||||
(catch Throwable e
|
|
||||||
(log/error "unexpected error on parsing response body from google access token request" e)
|
|
||||||
nil))))
|
|
||||||
|
|
||||||
(defn- get-user-info
|
(defn- get-user-info
|
||||||
[token]
|
[token]
|
||||||
(let [req {:uri "https://openidconnect.googleapis.com/v1/userinfo"
|
(try
|
||||||
:headers {"Authorization" (str "Bearer " token)}
|
(let [req {:uri "https://openidconnect.googleapis.com/v1/userinfo"
|
||||||
:method :get}
|
:headers {"Authorization" (str "Bearer " token)}
|
||||||
res (http/send! req)]
|
:method :get}
|
||||||
|
res (http/send! req)]
|
||||||
(when (not= 200 (:status res))
|
(when (= 200 (:status res))
|
||||||
(ex/raise :type :internal
|
(let [data (json/read-str (:body res))]
|
||||||
:code :invalid-response-from-google
|
{:email (get data "email")
|
||||||
:context {:status (:status res)
|
:fullname (get data "name")})))
|
||||||
:body (:body res)}))
|
(catch Exception e
|
||||||
|
(log/error e "unexpected exception on get-user-info")
|
||||||
(try
|
nil)))
|
||||||
(let [data (json/read-str (:body res))]
|
|
||||||
;; (clojure.pprint/pprint data)
|
|
||||||
{:email (get data "email")
|
|
||||||
:fullname (get data "name")})
|
|
||||||
(catch Throwable e
|
|
||||||
(log/error "unexpected error on parsing response body from google access token request" e)
|
|
||||||
nil))))
|
|
||||||
|
|
||||||
(defn- auth
|
(defn- auth
|
||||||
[{:keys [tokens] :as cfg} _req]
|
[{:keys [tokens] :as cfg} _req]
|
||||||
|
@ -99,33 +88,39 @@
|
||||||
|
|
||||||
(defn- callback
|
(defn- callback
|
||||||
[{:keys [tokens rpc session] :as cfg} request]
|
[{:keys [tokens rpc session] :as cfg} request]
|
||||||
(let [token (get-in request [:params :state])
|
(try
|
||||||
_ (tokens :verify {:token token :iss :google-oauth})
|
(let [token (get-in request [:params :state])
|
||||||
info (some->> (get-in request [:params :code])
|
_ (tokens :verify {:token token :iss :google-oauth})
|
||||||
(get-access-token cfg)
|
info (some->> (get-in request [:params :code])
|
||||||
(get-user-info))]
|
(get-access-token cfg)
|
||||||
|
(get-user-info))
|
||||||
(when-not info
|
_ (when-not info
|
||||||
(ex/raise :type :authentication
|
(ex/raise :type :internal
|
||||||
:code :unable-to-authenticate-with-google))
|
:code :unable-to-auth))
|
||||||
|
method-fn (get-in rpc [:methods :mutation :login-or-register])
|
||||||
(let [method-fn (get-in rpc [:methods :mutation :login-or-register])
|
|
||||||
profile (method-fn {:email (:email info)
|
profile (method-fn {:email (:email info)
|
||||||
:fullname (:fullname info)})
|
:fullname (:fullname info)})
|
||||||
uagent (get-in request [:headers "user-agent"])
|
uagent (get-in request [:headers "user-agent"])
|
||||||
token (tokens :generate {:iss :auth
|
token (tokens :generate {:iss :auth
|
||||||
:exp (dt/in-future "15m")
|
:exp (dt/in-future "15m")
|
||||||
:profile-id (:id profile)})
|
:profile-id (:id profile)})
|
||||||
|
|
||||||
uri (-> (uri/uri (:public-uri cfg))
|
uri (-> (uri/uri (:public-uri cfg))
|
||||||
(assoc :path "/#/auth/verify-token")
|
(assoc :path "/#/auth/verify-token")
|
||||||
(assoc :query (uri/map->query-string {:token token})))
|
(assoc :query (uri/map->query-string {:token token})))
|
||||||
|
|
||||||
sid (session/create! session {:profile-id (:id profile)
|
sid (session/create! session {:profile-id (:id profile)
|
||||||
:user-agent uagent})]
|
:user-agent uagent})]
|
||||||
{:status 302
|
{:status 302
|
||||||
:headers {"location" (str uri)}
|
:headers {"location" (str uri)}
|
||||||
:cookies (session/cookies session {:value sid})
|
:cookies (session/cookies session {:value sid})
|
||||||
:body ""})))
|
:body ""})
|
||||||
|
(catch Exception _e
|
||||||
|
(let [uri (-> (uri/uri (:public-uri cfg))
|
||||||
|
(assoc :path "/#/auth/login")
|
||||||
|
(assoc :query (uri/map->query-string {:error "unable-to-auth"})))]
|
||||||
|
{:status 302
|
||||||
|
:headers {"location" (str uri)}
|
||||||
|
:body ""}))))
|
||||||
|
|
||||||
(s/def ::client-id ::us/not-empty-string)
|
(s/def ::client-id ::us/not-empty-string)
|
||||||
(s/def ::client-secret ::us/not-empty-string)
|
(s/def ::client-secret ::us/not-empty-string)
|
||||||
|
|
|
@ -192,19 +192,19 @@
|
||||||
:fn (ig/ref :app.tasks.file-media-gc/handler)}
|
:fn (ig/ref :app.tasks.file-media-gc/handler)}
|
||||||
|
|
||||||
{:id "file-xlog-gc"
|
{:id "file-xlog-gc"
|
||||||
:cron #app/cron "0 0 */6 * * ?" ;; every 2 hours
|
:cron #app/cron "0 0 */1 * * ?" ;; hourly
|
||||||
:fn (ig/ref :app.tasks.file-xlog-gc/handler)}
|
:fn (ig/ref :app.tasks.file-xlog-gc/handler)}
|
||||||
|
|
||||||
{:id "storage-deleted-gc"
|
{:id "storage-deleted-gc"
|
||||||
:cron #app/cron "0 0 */6 * * ?" ;; every 6 hours
|
:cron #app/cron "0 0 1 */1 * ?" ;; daily (1 hour shift)
|
||||||
:fn (ig/ref :app.storage/gc-deleted-task)}
|
:fn (ig/ref :app.storage/gc-deleted-task)}
|
||||||
|
|
||||||
{:id "storage-touched-gc"
|
{:id "storage-touched-gc"
|
||||||
:cron #app/cron "0 30 */6 * * ?" ;; every 6 hours
|
:cron #app/cron "0 0 2 */1 * ?" ;; daily (2 hour shift)
|
||||||
:fn (ig/ref :app.storage/gc-touched-task)}
|
:fn (ig/ref :app.storage/gc-touched-task)}
|
||||||
|
|
||||||
{:id "storage-recheck"
|
{:id "storage-recheck"
|
||||||
:cron #app/cron "0 0 */6 * * ?" ;; every 6 hours
|
:cron #app/cron "0 0 */1 * * ?" ;; hourly
|
||||||
:fn (ig/ref :app.storage/recheck-task)}
|
:fn (ig/ref :app.storage/recheck-task)}
|
||||||
|
|
||||||
{:id "tasks-gc"
|
{:id "tasks-gc"
|
||||||
|
@ -260,7 +260,7 @@
|
||||||
:app.tasks.file-xlog-gc/handler
|
:app.tasks.file-xlog-gc/handler
|
||||||
{:pool (ig/ref :app.db/pool)
|
{:pool (ig/ref :app.db/pool)
|
||||||
:metrics (ig/ref :app.metrics/metrics)
|
:metrics (ig/ref :app.metrics/metrics)
|
||||||
:max-age (dt/duration {:hours 24})}
|
:max-age (dt/duration {:hours 48})}
|
||||||
|
|
||||||
:app.tasks.telemetry/handler
|
:app.tasks.telemetry/handler
|
||||||
{:pool (ig/ref :app.db/pool)
|
{:pool (ig/ref :app.db/pool)
|
||||||
|
|
|
@ -175,7 +175,12 @@
|
||||||
(ex/raise :type :internal
|
(ex/raise :type :internal
|
||||||
:code :rlimit-not-configured
|
:code :rlimit-not-configured
|
||||||
:hint ":image rlimit not configured"))
|
:hint ":image rlimit not configured"))
|
||||||
(rlm/execute rlimit (process params))))
|
(try
|
||||||
|
(rlm/execute rlimit (process params))
|
||||||
|
(catch org.im4java.core.InfoException e
|
||||||
|
(ex/raise :type :validation
|
||||||
|
:code :invalid-image
|
||||||
|
:cause e)))))
|
||||||
|
|
||||||
;; --- Utility functions
|
;; --- Utility functions
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,9 @@
|
||||||
|
|
||||||
{:name "0044-add-storage-refcount"
|
{:name "0044-add-storage-refcount"
|
||||||
:fn (mg/resource "app/migrations/sql/0044-add-storage-refcount.sql")}
|
:fn (mg/resource "app/migrations/sql/0044-add-storage-refcount.sql")}
|
||||||
|
|
||||||
|
{:name "0045-add-index-to-file-change-table"
|
||||||
|
:fn (mg/resource "app/migrations/sql/0045-add-index-to-file-change-table.sql")}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
CREATE INDEX file_change__created_at_idx
|
||||||
|
ON file_change (created_at);
|
|
@ -38,7 +38,7 @@
|
||||||
;; --- Create File Media object (upload)
|
;; --- Create File Media object (upload)
|
||||||
|
|
||||||
(declare create-file-media-object)
|
(declare create-file-media-object)
|
||||||
(declare select-file-for-update)
|
(declare select-file)
|
||||||
|
|
||||||
(s/def ::content ::media/upload)
|
(s/def ::content ::media/upload)
|
||||||
(s/def ::is-local ::us/boolean)
|
(s/def ::is-local ::us/boolean)
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
(sv/defmethod ::upload-file-media-object
|
(sv/defmethod ::upload-file-media-object
|
||||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(let [file (select-file-for-update conn file-id)]
|
(let [file (select-file conn file-id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
||||||
(-> (assoc cfg :conn conn)
|
(-> (assoc cfg :conn conn)
|
||||||
(create-file-media-object params)))))
|
(create-file-media-object params)))))
|
||||||
|
@ -66,9 +66,18 @@
|
||||||
[info]
|
[info]
|
||||||
(= (:mtype info) "image/svg+xml"))
|
(= (:mtype info) "image/svg+xml"))
|
||||||
|
|
||||||
|
(defn- fetch-url
|
||||||
|
[url]
|
||||||
|
(try
|
||||||
|
(http/get! url {:as :byte-array})
|
||||||
|
(catch Exception e
|
||||||
|
(ex/raise :type :validation
|
||||||
|
:code :unable-to-access-to-url
|
||||||
|
:cause e))))
|
||||||
|
|
||||||
(defn- download-media
|
(defn- download-media
|
||||||
[{:keys [storage] :as cfg} url]
|
[{:keys [storage] :as cfg} url]
|
||||||
(let [result (http/get! url {:as :byte-array})
|
(let [result (fetch-url url)
|
||||||
data (:body result)
|
data (:body result)
|
||||||
mtype (get (:headers result) "content-type")
|
mtype (get (:headers result) "content-type")
|
||||||
format (cm/mtype->format mtype)]
|
format (cm/mtype->format mtype)]
|
||||||
|
@ -129,7 +138,7 @@
|
||||||
(sv/defmethod ::create-file-media-object-from-url
|
(sv/defmethod ::create-file-media-object-from-url
|
||||||
[{:keys [pool storage] :as cfg} {:keys [profile-id file-id url name] :as params}]
|
[{:keys [pool storage] :as cfg} {:keys [profile-id file-id url name] :as params}]
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(let [file (select-file-for-update conn file-id)]
|
(let [file (select-file conn file-id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
||||||
(let [mobj (download-media cfg url)
|
(let [mobj (download-media cfg url)
|
||||||
content {:filename "tempfile"
|
content {:filename "tempfile"
|
||||||
|
@ -152,7 +161,7 @@
|
||||||
(sv/defmethod ::clone-file-media-object
|
(sv/defmethod ::clone-file-media-object
|
||||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(let [file (select-file-for-update conn file-id)]
|
(let [file (select-file conn file-id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
||||||
|
|
||||||
(-> (assoc cfg :conn conn)
|
(-> (assoc cfg :conn conn)
|
||||||
|
@ -175,17 +184,17 @@
|
||||||
|
|
||||||
;; --- HELPERS
|
;; --- HELPERS
|
||||||
|
|
||||||
(def ^:private sql:select-file-for-update
|
(def ^:private
|
||||||
|
sql:select-file
|
||||||
"select file.*,
|
"select file.*,
|
||||||
project.team_id as team_id
|
project.team_id as team_id
|
||||||
from file
|
from file
|
||||||
inner join project on (project.id = file.project_id)
|
inner join project on (project.id = file.project_id)
|
||||||
where file.id = ?
|
where file.id = ?")
|
||||||
for update of file")
|
|
||||||
|
|
||||||
(defn- select-file-for-update
|
(defn- select-file
|
||||||
[conn id]
|
[conn id]
|
||||||
(let [row (db/exec-one! conn [sql:select-file-for-update id])]
|
(let [row (db/exec-one! conn [sql:select-file id])]
|
||||||
(when-not row
|
(when-not row
|
||||||
(ex/raise :type :not-found))
|
(ex/raise :type :not-found))
|
||||||
row))
|
row))
|
||||||
|
|
|
@ -72,3 +72,17 @@
|
||||||
(let [profile (prof/retrieve-profile-data-by-email conn user-email)
|
(let [profile (prof/retrieve-profile-data-by-email conn user-email)
|
||||||
profile (merge profile (prof/retrieve-additional-data conn (:id profile)))]
|
profile (merge profile (prof/retrieve-additional-data conn (:id profile)))]
|
||||||
(pid/create-profile-initial-data conn file profile)))))
|
(pid/create-profile-initial-data conn file profile)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Migrate
|
||||||
|
|
||||||
|
(defn update-file-data-blob-format
|
||||||
|
[system]
|
||||||
|
(db/with-atomic [conn (:app.db/pool system)]
|
||||||
|
(doseq [id (->> (db/exec! conn ["select id from file;"]) (map :id))]
|
||||||
|
(let [{:keys [data]} (db/get-by-id conn :file id {:columns [:id :data]})]
|
||||||
|
(prn "Updating file:" id)
|
||||||
|
(db/update! conn :file
|
||||||
|
{:data (-> (blob/decode data)
|
||||||
|
(blob/encode {:version 2}))}
|
||||||
|
{:id id})))))
|
||||||
|
|
|
@ -121,11 +121,16 @@
|
||||||
|
|
||||||
(defn parse
|
(defn parse
|
||||||
[data]
|
[data]
|
||||||
(with-open [istream (IOUtils/toInputStream data "UTF-8")]
|
(try
|
||||||
(xml/parse istream)))
|
(with-open [istream (IOUtils/toInputStream data "UTF-8")]
|
||||||
|
(xml/parse istream))
|
||||||
|
(catch org.xml.sax.SAXParseException _e
|
||||||
|
(ex/raise :type :validation
|
||||||
|
:code :invalid-svg-file))))
|
||||||
|
|
||||||
(defn process-request
|
(defn process-request
|
||||||
[{:keys [svgc] :as cfg} body]
|
[{:keys [svgc] :as cfg} body]
|
||||||
(let [data (slurp body)
|
(let [data (slurp body)
|
||||||
data (svgc data)]
|
data (svgc data)]
|
||||||
(parse data)))
|
(parse data)))
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
:uri (:uri cfg)
|
:uri (:uri cfg)
|
||||||
:headers {"content-type" "application/json"}
|
:headers {"content-type" "application/json"}
|
||||||
:body (json/encode-str data)})]
|
:body (json/encode-str data)})]
|
||||||
|
|
||||||
(when (not= 200 (:status response))
|
(when (not= 200 (:status response))
|
||||||
(ex/raise :type :internal
|
(ex/raise :type :internal
|
||||||
:code :invalid-response-from-google
|
:code :invalid-response-from-google
|
||||||
|
@ -129,7 +130,7 @@
|
||||||
[{:keys [conn version]}]
|
[{:keys [conn version]}]
|
||||||
(merge
|
(merge
|
||||||
{:version version
|
{:version version
|
||||||
:with-taiga (:telemetry-with-taiga cfg/config)
|
:with-taiga (:telemetry-with-taiga cfg/config false)
|
||||||
:total-teams (retrieve-num-teams conn)
|
:total-teams (retrieve-num-teams conn)
|
||||||
:total-projects (retrieve-num-projects conn)
|
:total-projects (retrieve-num-projects conn)
|
||||||
:total-files (retrieve-num-files conn)}
|
:total-files (retrieve-num-files conn)}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
[app.http.middleware :refer [wrap-parse-request-body]]
|
[app.http.middleware :refer [wrap-parse-request-body]]
|
||||||
|
[clojure.pprint :refer [pprint]]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[clojure.tools.logging :as log]
|
[clojure.tools.logging :as log]
|
||||||
[integrant.core :as ig]
|
[integrant.core :as ig]
|
||||||
|
@ -87,7 +88,12 @@
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
;; We don't want notify user of a error, just log it for posible
|
;; We don't want notify user of a error, just log it for posible
|
||||||
;; future investigation.
|
;; future investigation.
|
||||||
(log/warnf e "Unexpected error on telemetry.")))
|
(log/warn e (str "Unexpected error on telemetry:\n"
|
||||||
|
(when-let [edata (ex-data e)]
|
||||||
|
(str "ex-data: \n"
|
||||||
|
(with-out-str (pprint edata))))
|
||||||
|
(str "params: \n"
|
||||||
|
(with-out-str (pprint params)))))))
|
||||||
{:status 200
|
{:status 200
|
||||||
:body "OK\n"})
|
:body "OK\n"})
|
||||||
|
|
||||||
|
|
|
@ -830,6 +830,12 @@
|
||||||
"es" : "Actualizado: %s"
|
"es" : "Actualizado: %s"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors.google-auth-not-enabled" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "Authentication with google disabled on backend",
|
||||||
|
"es" : "Autenticación con google esta dehabilitada en el servidor"
|
||||||
|
}
|
||||||
|
},
|
||||||
"errors.auth.unauthorized" : {
|
"errors.auth.unauthorized" : {
|
||||||
"used-in" : [ "src/app/main/ui/auth/login.cljs:89" ],
|
"used-in" : [ "src/app/main/ui/auth/login.cljs:89" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
|
|
|
@ -137,7 +137,8 @@
|
||||||
(d/index-by :id)
|
(d/index-by :id)
|
||||||
(assoc state :comment-threads)))
|
(assoc state :comment-threads)))
|
||||||
(on-error [{:keys [type] :as err}]
|
(on-error [{:keys [type] :as err}]
|
||||||
(if (= :authentication type)
|
(if (or (= :authentication type)
|
||||||
|
(= :not-found type))
|
||||||
(rx/empty)
|
(rx/empty)
|
||||||
(rx/throw err)))]
|
(rx/throw err)))]
|
||||||
|
|
||||||
|
|
|
@ -417,13 +417,22 @@
|
||||||
(defn- handle-upload-error [on-error stream]
|
(defn- handle-upload-error [on-error stream]
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/catch
|
(rx/catch
|
||||||
(fn on-error [error]
|
(fn on-error* [error]
|
||||||
(if (ex/ex-info? error)
|
(if (ex/ex-info? error)
|
||||||
(on-error (ex-data error))
|
(on-error* (ex-data error))
|
||||||
(cond
|
(cond
|
||||||
|
(= (:code error) :invalid-svg-file)
|
||||||
|
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||||
|
|
||||||
(= (:code error) :media-type-not-allowed)
|
(= (:code error) :media-type-not-allowed)
|
||||||
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||||
|
|
||||||
|
(= (:code error) :ubable-to-access-to-url)
|
||||||
|
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||||
|
|
||||||
|
(= (:code error) :invalid-image)
|
||||||
|
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||||
|
|
||||||
(= (:code error) :media-too-large)
|
(= (:code error) :media-too-large)
|
||||||
(rx/of (dm/error (tr "errors.media-too-large")))
|
(rx/of (dm/error (tr "errors.media-too-large")))
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(->> (rp/mutation! :login-with-google {})
|
(->> (rp/mutation! :login-with-google {})
|
||||||
(rx/subs (fn [{:keys [redirect-uri] :as rsp}]
|
(rx/subs (fn [{:keys [redirect-uri] :as rsp}]
|
||||||
(.replace js/location redirect-uri)))))
|
(.replace js/location redirect-uri))
|
||||||
|
(fn [{:keys [type] :as error}]
|
||||||
|
(st/emit! (dm/error (tr "errors.google-auth-not-enabled")))))))
|
||||||
|
|
||||||
(defn- login-with-gitlab
|
(defn- login-with-gitlab
|
||||||
[event]
|
[event]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue