diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index fe87fe3cf5..d723b28c6b 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -16,6 +16,12 @@ (fn [err & rest] (:type (ex-data err)))) + +(defmethod handle-exception :authorization + [err req] + {:status 403 + :body (ex-data err)}) + (defmethod handle-exception :validation [err req] (let [header (get-in req [:headers "accept"]) diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index bfd5b9aaee..172654e8b6 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -35,40 +35,39 @@ (s/def ::id ::us/uuid) (s/def ::file-id ::us/uuid) (s/def ::page-id ::us/uuid) -(s/def ::share-token ::us/string) +(s/def ::token ::us/string) (s/def ::viewer-bundle (s/keys :req-un [::file-id ::page-id] - :opt-un [::profile-id ::share-token])) + :opt-un [::profile-id ::token])) (sq/defquery ::viewer-bundle - [{:keys [profile-id file-id page-id share-token] :as params}] + [{:keys [profile-id file-id page-id token] :as params}] (db/with-atomic [conn db/pool] (let [file (files/retrieve-file conn file-id) - project (retrieve-project conn (:project-id file)) page (get-in file [:data :pages-index page-id]) - - file-library (select-keys (:data file) [:colors :media :typographies]) - bundle {:file (-> (dissoc file :data) - (merge file-library)) - :page (get-in file [:data :pages-index page-id]) - :project project} - ] - (if (string? share-token) + file (merge (dissoc file :data) + (select-keys (:data file) [:colors :media :typographies])) + libs (files/retrieve-file-libraries conn false file-id) + bundle {:file file + :page page + :project project + :libraries libs}] + (if (string? token) (do - (check-shared-token! conn file-id page-id share-token) - (assoc bundle :share-token share-token)) - (let [token (retrieve-shared-token conn file-id page-id)] - (files/check-edition-permissions! conn profile-id file-id) - (assoc bundle :share-token token)))))) + (check-shared-token! conn file-id page-id token) + (assoc bundle :token token)) + (let [stoken (retrieve-shared-token conn file-id page-id)] + (files/check-read-permissions! conn profile-id file-id) + (assoc bundle :share-token (:token stoken))))))) (defn check-shared-token! [conn file-id page-id token] (let [sql "select exists(select 1 from file_share_token where file_id=? and page_id=? and token=?) as exists"] (when-not (:exists (db/exec-one! conn [sql file-id page-id token])) - (ex/raise :type :validation - :code :not-authorized)))) + (ex/raise :type :authorization + :code :unauthorized-token)))) (defn retrieve-shared-token [conn file-id page-id] diff --git a/frontend/src/app/main/data/auth.cljs b/frontend/src/app/main/data/auth.cljs index 2209cdd995..ad0b31e1b9 100644 --- a/frontend/src/app/main/data/auth.cljs +++ b/frontend/src/app/main/data/auth.cljs @@ -120,7 +120,8 @@ (reset! storage {}) (i18n/set-default-locale!)))) -(def logout +(defn logout + [] (ptk/reify ::logout ptk/WatchEvent (watch [_ state stream] diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 67c1310abf..b40917be69 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -71,13 +71,10 @@ (watch [_ state stream] (let [params (cond-> {:page-id page-id :file-id file-id} - (string? token) (assoc :share-token token))] - (->> (rx/zip (rp/query :viewer-bundle params) - (rp/query :file-libraries {:file-id file-id})) + (string? token) (assoc :token token))] + (->> (rp/query :viewer-bundle params) (rx/first) - (rx/map #(apply bundle-fetched %)) - #_(rx/catch (fn [error-data] - (rx/of (rt/nav :not-found))))))))) + (rx/map bundle-fetched)))))) (defn- extract-frames [objects] @@ -89,7 +86,7 @@ (vec)))) (defn bundle-fetched - [{:keys [project file page share-token] :as bundle} libraries] + [{:keys [project file page share-token token libraries] :as bundle}] (us/verify ::bundle bundle) (ptk/reify ::file-fetched ptk/UpdateEvent @@ -103,6 +100,7 @@ :file file :page page :frames frames + :token token :share-token share-token})))))) (def create-share-link @@ -244,12 +242,12 @@ (let [page-id (get-in state [:viewer-local :page-id]) file-id (get-in state [:viewer-local :file-id]) frames (get-in state [:viewer-data :frames]) - share-token (get-in state [:viewer-data :share-token]) + token (get-in state [:viewer-data :token]) index (d/index-of-pred frames #(= (:id %) frame-id))] (rx/of (rt/nav :viewer {:page-id page-id :file-id file-id} - {:token share-token + {:token token :index index})))))) (defn set-current-frame [frame-id] diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 611ba44f1f..e81e7801ca 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -178,7 +178,7 @@ (defmethod ptk/handle-error :validation [error] (ts/schedule - (st/emitf (dm/show {:content "Unexpected validation error." + (st/emitf (dm/show {:content "Unexpected validation error (server side)." :type :error :timeout 5000}))) (when-let [explain (:explain error)] @@ -190,11 +190,13 @@ (defmethod ptk/handle-error :authentication [error] - (ts/schedule 0 #(st/emit! logout))) + (ts/schedule 0 #(st/emit! (logout)))) (defmethod ptk/handle-error :authorization [error] - (ts/schedule 0 #(st/emit! logout))) + (ts/schedule + (st/emitf (dm/show {:content "Not authorized to see this content." + :type :error})))) (defmethod ptk/handle-error :assertion [{:keys [data stack message context] :as error}]