From fa625dd1ae850be3a81dcd856f4cbd23f1855d66 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 14 Aug 2024 22:33:19 +0200 Subject: [PATCH] fix: duplicate oauth namespaces, join server response check --- src/co/gaiwan/compass/http/oauth.clj | 73 ++++---------------------- src/co/gaiwan/compass/routes/oauth.clj | 44 ++++------------ src/co/gaiwan/compass/util.clj | 4 ++ 3 files changed, 24 insertions(+), 97 deletions(-) diff --git a/src/co/gaiwan/compass/http/oauth.clj b/src/co/gaiwan/compass/http/oauth.clj index a2efc39..768fd65 100644 --- a/src/co/gaiwan/compass/http/oauth.clj +++ b/src/co/gaiwan/compass/http/oauth.clj @@ -4,12 +4,9 @@ [co.gaiwan.compass.config :as config] [co.gaiwan.compass.db :as db] [co.gaiwan.compass.util :as util] - [datomic.api :as d] [hato.client :as hato] [lambdaisland.uri :as uri] - [ring.util.response :as response] - [io.pedestal.log :as log]) - (:import (java.time Instant))) + [io.pedestal.log :as log])) (def discord-oauth-endpoint "https://discord.com/oauth2/authorize") (def discord-api-endpoint "https://discord.com/api/v10") @@ -20,7 +17,6 @@ (defn bot-auth-headers [] {"Authorization" (str "Bot " (config/value :discord/bot-token))}) - (defn flow-init-url ([] (flow-init-url nil)) @@ -62,10 +58,6 @@ {:grant_type "refresh_token" :refresh_token refresh-token})) -(defn- expires-in->instant - [expires-in] - (.plusSeconds (Instant/now) (- expires-in 60))) - (defn current-access-token "Get a valid Discord bearer access token for a user. @@ -90,7 +82,7 @@ (db/transact [{:user/uuid user-id :discord/access-token (:access_token body) :discord/refresh-token (:refresh_token body) - :discord/expires-at (expires-in->instant (:discord/expires_in body))}]) + :discord/expires-at (util/expires-in->instant (:discord/expires_in body))}]) (:access_token body))) (:discord/access-token oauth-data)))) @@ -102,55 +94,12 @@ :oauth-token token}))) (defn join-server [token] - (let [{:keys [id username]} (fetch-user-info token)] - (log/trace :discord/adding-user username) - (hato/put - (str discord-api-endpoint "/guilds/" (config/value :discord/server-id) "/members/" id) - {:as :auto - :content-type :json - :form-params {:access_token token} - :headers (bot-auth-headers)}))) - -(defn GET-callback [{:keys [query-params]}] - (let [code (get query-params "code") - {:keys [status body]} (exchange-code code)] - (if (not= 200 status) - {:status 302 - :headers {"Location" "/"} - :flash [:p - "Discord OAuth2 exchange failed." - [:pre (util/pprint-str body)]] - :session {:identity nil}} - (let [{:keys [access_token refresh_token expires_in]} body - {:keys [id global_name email username]} (fetch-user-info access_token) - user-uuid (:user/uuid (d/entity (db/db) [:user/email email]) (random-uuid)) - tx-data - [{:user/uuid user-uuid - :user/email email - :user/name global_name - :user/handle username - :discord/id id - :discord/access-token access_token - :discord/refresh-token refresh_token - :discord/expires-at (expires-in->instant expires_in)}] - {:keys [status]} (join-server access_token)] - @(db/transact tx-data) - {:status 302 - :headers {"Location" "/"} - :flash [:p "You are signed in!" - (when-not (= status 200) - [:br "Unfortunately, adding you to our Discord server didn't work."])] - :session {:identity user-uuid}})))) - -(defn routes [] - ["" - ["/oauth2" - ["/discord" - ["/callback" - {:get {:handler #'GET-callback}}]]] - ["/logout" - {:get {:handler (fn [req] - (assoc - (response/redirect "/") - :flash "You were signed out" - :session {}))}}]]) + (let [{:keys [id username]} (fetch-user-info token) + response + (hato/put + (str discord-api-endpoint "/guilds/" (config/value :discord/server-id) "/members/" id) + {:as :auto + :content-type :json + :form-params {:access_token token} + :headers (bot-auth-headers)})] + (log/trace :discord/user-add username :discord/add-guild-member-response response))) diff --git a/src/co/gaiwan/compass/routes/oauth.clj b/src/co/gaiwan/compass/routes/oauth.clj index 5f9c1f2..cecd4c4 100644 --- a/src/co/gaiwan/compass/routes/oauth.clj +++ b/src/co/gaiwan/compass/routes/oauth.clj @@ -1,39 +1,15 @@ (ns co.gaiwan.compass.routes.oauth (:require - [clojure.string :as str] - [co.gaiwan.compass.config :as config] [co.gaiwan.compass.db :as db] [co.gaiwan.compass.html.auth :as auth-html] [co.gaiwan.compass.http.oauth :as oauth] [co.gaiwan.compass.util :as util] [datomic.api :as d] - [hato.client :as hato] - [lambdaisland.uri :as uri] [ring.util.response :as response])) -(defn exchange-code [code] - (hato/post - (str oauth/discord-api-endpoint "/oauth2/token") - {:as :auto - :form-params - {:grant_type "authorization_code" - :code code - :redirect_uri (str (config/value :compass/origin) "/oauth2/discord/callback")} - :basic-auth - {:user (config/value :discord/client-id) - :pass (config/value :discord/client-secret)}})) - -(defn fetch-user-info [token] - (:body - (hato/get (str oauth/discord-api-endpoint "/users/@me") - {:as :auto - :headers {"Authorization" (str "Bearer " token)}}))) - (defn GET-callback [{:keys [query-params]}] (let [code (get query-params "code") - state (get query-params "state") - {:keys [status body]} (exchange-code code) - redirect-url (:oauth/redirect-url (db/entity [:oauth/state-id (parse-uuid state)]))] + {:keys [status body]} (oauth/exchange-code code)] (if (not= 200 status) {:status 302 :headers {"Location" "/"} @@ -42,25 +18,24 @@ [:pre (util/pprint-str body)]] :session {:identity nil}} (let [{:keys [access_token refresh_token expires_in]} body - {:keys [id global_name email username] :as user-info} (fetch-user-info access_token) - avatar-url (str "https://cdn.discordapp.com/avatars/" id "/" (:avatar user-info) ".png") - ;;_ (prn :avatar-url avatar-url) + {:keys [id global_name email username]} (oauth/fetch-user-info access_token) user-uuid (:user/uuid (d/entity (db/db) [:user/email email]) (random-uuid)) tx-data [{:user/uuid user-uuid :user/email email :user/name global_name :user/handle username - :discord/avatar-url avatar-url :discord/id id :discord/access-token access_token :discord/refresh-token refresh_token - :discord/expires-at (.plusSeconds (java.time.Instant/now) (- expires_in 60))}]] - (def tx-data tx-data) + :discord/expires-at (util/expires-in->instant expires_in)}] + {:keys [status]} (oauth/join-server access_token)] @(db/transact tx-data) {:status 302 - :headers {"Location" (or redirect-url "/")} - #_#_:flash [:p "You are signed in!"] + :headers {"Location" "/"} + :flash [:p "You are signed in!" + (when-not (= 2 (quot status 100)) + [:br "Unfortunately, adding you to our Discord server didn't work."])] :session {:identity user-uuid}})))) (defn GET-login [req] @@ -72,8 +47,7 @@ ["/oauth2" ["/discord" ["/callback" - {:get {:handler GET-callback}}]]] - ["/login" {:get {:handler GET-login}}] + {:get {:handler #'GET-callback}}]]] ["/logout" {:get {:handler (fn [req] (assoc diff --git a/src/co/gaiwan/compass/util.clj b/src/co/gaiwan/compass/util.clj index 1414414..b145884 100644 --- a/src/co/gaiwan/compass/util.clj +++ b/src/co/gaiwan/compass/util.clj @@ -96,3 +96,7 @@ (vector? res) (mapv deep-underscorize-keys res) (map? res) (update-vals (underscorize-keys res) deep-underscorize-keys) :else res)) + +(defn expires-in->instant + [expires-in] + (.plusSeconds (Instant/now) (- expires-in 60)))