Merge pull request #46 from status-im/develop
Progressive Github permissioning & client-side oauth tokens
This commit is contained in:
commit
9f0cc6497b
|
@ -46,7 +46,8 @@
|
||||||
[org.clojure/tools.nrepl "0.2.12"]
|
[org.clojure/tools.nrepl "0.2.12"]
|
||||||
[com.cemerick/piggieback "0.2.1"]
|
[com.cemerick/piggieback "0.2.1"]
|
||||||
[jarohen/chime "0.2.0"]
|
[jarohen/chime "0.2.0"]
|
||||||
[com.andrewmcveigh/cljs-time "0.4.0"]]
|
[com.andrewmcveigh/cljs-time "0.4.0"]
|
||||||
|
[akiroz.re-frame/storage "0.1.1"]]
|
||||||
|
|
||||||
:min-lein-version "2.0.0"
|
:min-lein-version "2.0.0"
|
||||||
:source-paths ["src/clj" "src/cljc"]
|
:source-paths ["src/clj" "src/cljc"]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE "public"."users" DROP COLUMN "token";
|
|
@ -3,14 +3,13 @@
|
||||||
-- :name create-user! :<! :1
|
-- :name create-user! :<! :1
|
||||||
-- :doc creates a new user record
|
-- :doc creates a new user record
|
||||||
INSERT INTO users
|
INSERT INTO users
|
||||||
(id, login, name, email, avatar_url, token, address, created)
|
(id, login, name, email, avatar_url, address, created)
|
||||||
SELECT
|
SELECT
|
||||||
:id,
|
:id,
|
||||||
:login,
|
:login,
|
||||||
:name,
|
:name,
|
||||||
:email,
|
:email,
|
||||||
:avatar_url,
|
:avatar_url,
|
||||||
:token,
|
|
||||||
:address,
|
:address,
|
||||||
:created
|
:created
|
||||||
WHERE NOT exists(SELECT 1
|
WHERE NOT exists(SELECT 1
|
||||||
|
@ -24,17 +23,9 @@ UPDATE users
|
||||||
SET login = :login,
|
SET login = :login,
|
||||||
name = :name,
|
name = :name,
|
||||||
email = :email,
|
email = :email,
|
||||||
token = :token,
|
|
||||||
address = :address
|
address = :address
|
||||||
WHERE id = :id;
|
WHERE id = :id;
|
||||||
|
|
||||||
-- :name update-user-token! :<! :1
|
|
||||||
-- :doc updates user token and returns updated user
|
|
||||||
UPDATE users
|
|
||||||
SET token = :token
|
|
||||||
WHERE id = :id
|
|
||||||
RETURNING id, login, name, email, token, address, created;
|
|
||||||
|
|
||||||
-- :name update-user-address! :! :n
|
-- :name update-user-address! :! :n
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET address = :address
|
SET address = :address
|
||||||
|
|
|
@ -25,13 +25,15 @@
|
||||||
var context = "{{servlet-context}}";
|
var context = "{{servlet-context}}";
|
||||||
var csrfToken = "{{csrf-token}}";
|
var csrfToken = "{{csrf-token}}";
|
||||||
var authorizeUrl = "{{authorize-url}}";
|
var authorizeUrl = "{{authorize-url}}";
|
||||||
|
var authorizeUrlAdmin = "{{authorize-url-admin}}";
|
||||||
var token = "{{token}}";
|
var token = "{{token}}";
|
||||||
var userId = "{{userId}}";
|
var adminToken = "{{admin-token}}";
|
||||||
|
var userId = "{{user-id}}";
|
||||||
var user = "{{login}}";
|
var user = "{{login}}";
|
||||||
if (user === "") {
|
if (user === "") {
|
||||||
user = null;
|
user = null;
|
||||||
}
|
}
|
||||||
var commitethVersion = "{{commitethVersion}}";
|
var commitethVersion = "{{commiteth-version}}";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% style "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css" %}
|
{% style "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css" %}
|
||||||
|
|
|
@ -5,14 +5,13 @@
|
||||||
(:import [java.util Date]))
|
(:import [java.util Date]))
|
||||||
|
|
||||||
(defn create-user
|
(defn create-user
|
||||||
[user-id login name email avatar-url token]
|
[user-id login name email avatar-url]
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
(db/create-user! con-db
|
(db/create-user! con-db
|
||||||
{:id user-id
|
{:id user-id
|
||||||
:login login
|
:login login
|
||||||
:name name
|
:name name
|
||||||
:email email
|
:email email
|
||||||
:token token
|
|
||||||
:avatar_url avatar-url
|
:avatar_url avatar-url
|
||||||
:address nil
|
:address nil
|
||||||
:created (new Date)})))
|
:created (new Date)})))
|
||||||
|
@ -33,12 +32,6 @@
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
(jdbc/with-db-connection [con-db *db*]
|
||||||
(db/update-user-address! con-db {:id user-id :address address})))
|
(db/update-user-address! con-db {:id user-id :address address})))
|
||||||
|
|
||||||
(defn update-user-token
|
|
||||||
"Updates user token and returns updated user"
|
|
||||||
[user-id token]
|
|
||||||
(jdbc/with-db-connection [con-db *db*]
|
|
||||||
(db/update-user-token! con-db {:id user-id :token token})))
|
|
||||||
|
|
||||||
(defn get-repo-owner
|
(defn get-repo-owner
|
||||||
"Gets repository owner by given repository id"
|
"Gets repository owner by given repository id"
|
||||||
[repo-id]
|
[repo-id]
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
(ns commiteth.github.core
|
(ns commiteth.github.core
|
||||||
(:require [tentacles.repos :as repos]
|
(:require [tentacles
|
||||||
[tentacles.users :as users]
|
[core :as tentacles]
|
||||||
[tentacles.repos :as repos]
|
[repos :as repos]
|
||||||
[tentacles.issues :as issues]
|
[oauth :as oauth]
|
||||||
[tentacles.core :as tentacles]
|
[users :as users]
|
||||||
|
[repos :as repos]
|
||||||
|
[issues :as issues]]
|
||||||
[ring.util.codec :as codec]
|
[ring.util.codec :as codec]
|
||||||
[commiteth.config :refer [env]]
|
[commiteth.config :refer [env]]
|
||||||
[clj-http.client :as http]
|
[clj-http.client :as http]
|
||||||
|
@ -24,14 +26,23 @@
|
||||||
(defn self [] (:github-user env))
|
(defn self [] (:github-user env))
|
||||||
(defn self-password [] (:github-password env))
|
(defn self-password [] (:github-password env))
|
||||||
|
|
||||||
(defn authorize-url []
|
(defn authorize-url [scope]
|
||||||
(let [params (codec/form-encode {:client_id (client-id)
|
(let [params (codec/form-encode {:client_id (client-id)
|
||||||
:redirect_uri (redirect-uri)
|
:redirect_uri (redirect-uri)
|
||||||
:scope "admin:repo_hook repo user:email admin:org_hook"
|
:scope scope
|
||||||
:allow_signup true
|
:allow_signup true
|
||||||
:state (str (UUID/randomUUID))})]
|
:state (str (UUID/randomUUID))})]
|
||||||
(str "https://github.com/login/oauth/authorize" "?" params)))
|
(str "https://github.com/login/oauth/authorize" "?" params)))
|
||||||
|
|
||||||
|
(defn signup-authorize-url []
|
||||||
|
(authorize-url "user:email"))
|
||||||
|
|
||||||
|
(defn admin-authorize-url []
|
||||||
|
(authorize-url "admin:repo_hook repo user:email admin:org_hook"))
|
||||||
|
|
||||||
|
(defn access-settings-url []
|
||||||
|
(str "https://github.com/settings/connections/applications/" (client-id)))
|
||||||
|
|
||||||
(defn post-for-token
|
(defn post-for-token
|
||||||
[code state]
|
[code state]
|
||||||
(http/post "https://github.com/login/oauth/access_token"
|
(http/post "https://github.com/login/oauth/access_token"
|
||||||
|
@ -75,10 +86,10 @@
|
||||||
(map #(merge
|
(map #(merge
|
||||||
{:owner-login (get-in % [:owner :login])}
|
{:owner-login (get-in % [:owner :login])}
|
||||||
{:owner-type (get-in % [:owner :type])}
|
{:owner-type (get-in % [:owner :type])}
|
||||||
|
{:owner-avatar-url (get-in % [:owner :avatar_url])}
|
||||||
(select-keys % repo-fields))
|
(select-keys % repo-fields))
|
||||||
(repos/repos (merge (auth-params token) {:type "all"
|
(repos/repos (merge (auth-params token) {:type "all"
|
||||||
:all-pages true})))
|
:all-pages true})))
|
||||||
(filter #(not (:fork %)))
|
|
||||||
(filter #(-> % :permissions :admin)))]
|
(filter #(-> % :permissions :admin)))]
|
||||||
(group-by :owner-login all-repos-with-admin-access)))
|
(group-by :owner-login all-repos-with-admin-access)))
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
[markdown.core :refer [md-to-html-string]]
|
[markdown.core :refer [md-to-html-string]]
|
||||||
[ring.util.http-response :refer [content-type ok]]
|
[ring.util.http-response :refer [content-type ok]]
|
||||||
[ring.util.anti-forgery :refer [anti-forgery-field]]
|
[ring.util.anti-forgery :refer [anti-forgery-field]]
|
||||||
[ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
|
[ring.middleware.anti-forgery :refer [*anti-forgery-token*]]))
|
||||||
[commiteth.github.core :as github]))
|
|
||||||
|
|
||||||
(parser/set-resource-path! (clojure.java.io/resource "templates"))
|
(parser/set-resource-path! (clojure.java.io/resource "templates"))
|
||||||
(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
|
(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
|
||||||
|
@ -19,7 +18,6 @@
|
||||||
(parser/render-file
|
(parser/render-file
|
||||||
template
|
template
|
||||||
(assoc params
|
(assoc params
|
||||||
:authorize-url (github/authorize-url)
|
|
||||||
:page template
|
:page template
|
||||||
:csrf-token *anti-forgery-token*)))
|
:csrf-token *anti-forgery-token*)))
|
||||||
"text/html; charset=utf-8"))
|
"text/html; charset=utf-8"))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns commiteth.routes.home
|
(ns commiteth.routes.home
|
||||||
(:require [commiteth.layout :as layout]
|
(:require [commiteth.layout :as layout]
|
||||||
|
[commiteth.github.core :as github]
|
||||||
[compojure.core :refer [defroutes GET]]
|
[compojure.core :refer [defroutes GET]]
|
||||||
[ring.util.response :refer [redirect]]
|
[ring.util.response :refer [redirect]]
|
||||||
[ring.util.http-response :refer [ok header]]
|
[ring.util.http-response :refer [ok header]]
|
||||||
|
@ -8,15 +9,21 @@
|
||||||
|
|
||||||
(defonce ^:const version (System/getProperty "commiteth.version"))
|
(defonce ^:const version (System/getProperty "commiteth.version"))
|
||||||
|
|
||||||
(defn home-page [{user-id :id login :login token :token}]
|
(defn home-page [{user-id :id
|
||||||
(layout/render "home.html" {:userId user-id
|
login :login
|
||||||
|
token :token
|
||||||
|
admin-token :admin-token}]
|
||||||
|
(layout/render "home.html" {:user-id user-id
|
||||||
:login login
|
:login login
|
||||||
:token token
|
:token token
|
||||||
:commitethVersion version}))
|
:admin-token admin-token
|
||||||
|
:authorize-url (github/signup-authorize-url)
|
||||||
|
:authorize-url-admin (github/admin-authorize-url)
|
||||||
|
:commiteth-version version}))
|
||||||
|
|
||||||
(defroutes home-routes
|
(defroutes home-routes
|
||||||
(GET "/" {{identity :identity} :session}
|
(GET "/" {{user :identity} :session}
|
||||||
(home-page identity))
|
(home-page user))
|
||||||
(GET "/logout" {session :session}
|
(GET "/logout" {session :session}
|
||||||
(-> (redirect "/")
|
(-> (redirect "/")
|
||||||
(assoc :session (dissoc session :identity)))))
|
(assoc :session (dissoc session :identity)))))
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
[ring.util.response :as response]
|
[ring.util.response :as response]
|
||||||
[commiteth.layout :refer [render]]
|
[commiteth.layout :refer [render]]
|
||||||
[cheshire.core :refer [generate-string]]
|
[cheshire.core :refer [generate-string]]
|
||||||
[clojure.tools.logging :as log]))
|
[clojure.tools.logging :as log]
|
||||||
|
[clojure.string :as str]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
user-id :id
|
user-id :id
|
||||||
avatar-url :avatar_url} user
|
avatar-url :avatar_url} user
|
||||||
email (github/get-user-email token)]
|
email (github/get-user-email token)]
|
||||||
(users/create-user user-id login name email avatar-url token)))
|
(users/create-user user-id login name email avatar-url)))
|
||||||
|
|
||||||
(defn- get-or-create-user
|
(defn- get-or-create-user
|
||||||
[token]
|
[token]
|
||||||
|
@ -28,17 +29,22 @@
|
||||||
user-id :id} user]
|
user-id :id} user]
|
||||||
(log/debug "get-or-create-user" user)
|
(log/debug "get-or-create-user" user)
|
||||||
(or
|
(or
|
||||||
(users/update-user-token user-id token)
|
(users/get-user user-id)
|
||||||
(create-user token user))))
|
(create-user token user))))
|
||||||
|
|
||||||
(defroutes redirect-routes
|
(defroutes redirect-routes
|
||||||
(GET "/callback" [code state]
|
(GET "/callback" [code state]
|
||||||
(let [resp (github/post-for-token code state)
|
(let [resp (github/post-for-token code state)
|
||||||
body (keywordize-keys (codec/form-decode (:body resp)))
|
body (keywordize-keys (codec/form-decode (:body resp)))
|
||||||
|
scope (:scope body)
|
||||||
access-token (:access_token body)]
|
access-token (:access_token body)]
|
||||||
|
(log/debug "github sign-in callback, response body:" body)
|
||||||
(if (:error body)
|
(if (:error body)
|
||||||
;; Why does Mist browser sends two redirects at the same time? The latter results in 401 error.
|
;; Why does Mist browser sends two redirects at the same time? The latter results in 401 error.
|
||||||
(response/redirect "/")
|
(response/redirect "/")
|
||||||
(let [user (get-or-create-user access-token)]
|
(let [admin-token? (str/includes? scope "repo")
|
||||||
|
token-key (if admin-token? :admin-token :token)
|
||||||
|
user (-> (get-or-create-user access-token)
|
||||||
|
(assoc token-key access-token))]
|
||||||
(-> (response/redirect "/")
|
(-> (response/redirect "/")
|
||||||
(assoc :session {:identity user})))))))
|
(assoc :session {:identity user})))))))
|
||||||
|
|
|
@ -61,11 +61,11 @@
|
||||||
|
|
||||||
(defn handle-toggle-repo [user params]
|
(defn handle-toggle-repo [user params]
|
||||||
(log/debug "handle-toggle-repo" user params)
|
(log/debug "handle-toggle-repo" user params)
|
||||||
(let [{token :token
|
(let [{user-id :id} user
|
||||||
user-id :id} user
|
|
||||||
{repo-id :id
|
{repo-id :id
|
||||||
full-repo :full_name
|
full-repo :full_name
|
||||||
owner-avatar-url :owner-avatar-url
|
owner-avatar-url :owner-avatar-url
|
||||||
|
token :token
|
||||||
repo :name} params
|
repo :name} params
|
||||||
[owner _] (str/split full-repo #"/")
|
[owner _] (str/split full-repo #"/")
|
||||||
db-user (users/get-user (:id user))]
|
db-user (users/get-user (:id user))]
|
||||||
|
@ -90,9 +90,9 @@
|
||||||
(defn in? [coll elem]
|
(defn in? [coll elem]
|
||||||
(some #(= elem %) coll))
|
(some #(= elem %) coll))
|
||||||
|
|
||||||
(defn handle-get-user-repos [user]
|
(defn handle-get-user-repos [user token]
|
||||||
(log/debug "handle-get-user-repos")
|
(log/debug "handle-get-user-repos")
|
||||||
(let [github-repos (github/get-user-repos (:token user))
|
(let [github-repos (github/get-user-repos token)
|
||||||
enabled-repos (vec (repositories/get-enabled (:id user)))
|
enabled-repos (vec (repositories/get-enabled (:id user)))
|
||||||
repo-enabled? (fn [repo] (in? enabled-repos (:id repo)))
|
repo-enabled? (fn [repo] (in? enabled-repos (:id repo)))
|
||||||
update-enabled (fn [repo] (assoc repo :enabled (repo-enabled? repo)))]
|
update-enabled (fn [repo] (assoc repo :enabled (repo-enabled? repo)))]
|
||||||
|
@ -164,7 +164,6 @@
|
||||||
:current-user user
|
:current-user user
|
||||||
(ok {:user (dissoc
|
(ok {:user (dissoc
|
||||||
(users/get-user (:id user))
|
(users/get-user (:id user))
|
||||||
:token
|
|
||||||
:email)}))
|
:email)}))
|
||||||
(POST "/address" []
|
(POST "/address" []
|
||||||
:auth-rules authenticated?
|
:auth-rules authenticated?
|
||||||
|
@ -179,10 +178,12 @@
|
||||||
(if (= 1 result)
|
(if (= 1 result)
|
||||||
(ok)
|
(ok)
|
||||||
(internal-server-error)))))
|
(internal-server-error)))))
|
||||||
(GET "/repositories" []
|
(GET "/repositories" {:keys [params]}
|
||||||
:auth-rules authenticated?
|
:auth-rules authenticated?
|
||||||
:current-user user
|
:current-user user
|
||||||
(ok {:repositories (handle-get-user-repos user)}))
|
(ok {:repositories (handle-get-user-repos
|
||||||
|
user
|
||||||
|
(:token params))}))
|
||||||
(GET "/enabled-repositories" []
|
(GET "/enabled-repositories" []
|
||||||
:auth-rules authenticated?
|
:auth-rules authenticated?
|
||||||
:current-user user
|
:current-user user
|
||||||
|
|
|
@ -173,18 +173,22 @@
|
||||||
|
|
||||||
(defn load-user []
|
(defn load-user []
|
||||||
(if-let [login js/user]
|
(if-let [login js/user]
|
||||||
(when-not (= login @active-user)
|
(if (= login @active-user)
|
||||||
|
(do
|
||||||
|
(println "refresh with active user, updating tokens")
|
||||||
|
(rf/dispatch [:update-tokens js/token js/adminToken]))
|
||||||
|
(do
|
||||||
(println "active user changed, loading user data")
|
(println "active user changed, loading user data")
|
||||||
(reset! active-user login)
|
(reset! active-user login)
|
||||||
(rf/dispatch [:set-active-user
|
(rf/dispatch [:set-active-user
|
||||||
{:login login
|
{:login login
|
||||||
:id (js/parseInt js/userId)
|
:id (js/parseInt js/userId)}
|
||||||
:token js/token}]))
|
js/token
|
||||||
|
js/adminToken])))
|
||||||
(reset! active-user nil)))
|
(reset! active-user nil)))
|
||||||
|
|
||||||
(defn load-data []
|
(defn load-data []
|
||||||
(doall
|
(doall (map rf/dispatch
|
||||||
(map rf/dispatch
|
|
||||||
[[:load-open-bounties]
|
[[:load-open-bounties]
|
||||||
[:load-activity-feed]
|
[:load-activity-feed]
|
||||||
[:load-top-hunters]]))
|
[:load-top-hunters]]))
|
||||||
|
|
|
@ -8,4 +8,6 @@
|
||||||
:open-bounties []
|
:open-bounties []
|
||||||
:owner-bounties {}
|
:owner-bounties {}
|
||||||
:top-hunters []
|
:top-hunters []
|
||||||
:activity-feed []})
|
:activity-feed []
|
||||||
|
:gh-token nil
|
||||||
|
:gh-admin-token nil})
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
(ns commiteth.handlers
|
(ns commiteth.handlers
|
||||||
(:require [commiteth.db :as db]
|
(:require [commiteth.db :as db]
|
||||||
[re-frame.core :refer [dispatch reg-event-db reg-event-fx reg-fx]]
|
[re-frame.core :refer [dispatch
|
||||||
|
reg-event-db
|
||||||
|
reg-event-fx
|
||||||
|
reg-fx
|
||||||
|
inject-cofx]]
|
||||||
[ajax.core :refer [GET POST]]
|
[ajax.core :refer [GET POST]]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]
|
||||||
|
[akiroz.re-frame.storage
|
||||||
|
:as rf-storage
|
||||||
|
:refer [reg-co-fx!]]))
|
||||||
|
|
||||||
|
|
||||||
|
(rf-storage/reg-co-fx! :commiteth {:fx :store
|
||||||
|
:cofx :store})
|
||||||
|
|
||||||
(reg-fx
|
(reg-fx
|
||||||
:http
|
:http
|
||||||
|
@ -23,13 +34,14 @@
|
||||||
:redirect
|
:redirect
|
||||||
(fn [{:keys [path]}]
|
(fn [{:keys [path]}]
|
||||||
(println "redirecting to" path)
|
(println "redirecting to" path)
|
||||||
(set! (.-pathname js/location) path))
|
(set! (.-pathname js/location) path)))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-fx
|
||||||
:initialize-db
|
:initialize-db
|
||||||
(fn [_ _]
|
[(inject-cofx :store)]
|
||||||
db/default-db)))
|
(fn [{:keys [db store]} [_]]
|
||||||
|
{:db (merge db/default-db store)}))
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
:assoc-in
|
:assoc-in
|
||||||
|
@ -55,11 +67,42 @@
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(dissoc db :flash-message)))
|
(dissoc db :flash-message)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn update-if-not-empty [m k val]
|
||||||
|
(conj m (when (not (empty? val)) [k val])))
|
||||||
|
|
||||||
|
(defn update-local-storage-tokens [ls token admin-token]
|
||||||
|
(into {}
|
||||||
|
(-> ls
|
||||||
|
(update-if-not-empty :gh-token token)
|
||||||
|
(update-if-not-empty :gh-admin-token admin-token))))
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:set-active-user
|
:set-active-user
|
||||||
(fn [{:keys [db]} [_ user]]
|
(fn [{:keys [db store]} [_ user token admin-token]]
|
||||||
{:db (assoc db :user user)
|
{:db (assoc db :user user)
|
||||||
:dispatch [:load-user-profile]}))
|
:dispatch-n [[:update-tokens token admin-token]
|
||||||
|
[:load-user-profile]]}))
|
||||||
|
|
||||||
|
(reg-event-fx
|
||||||
|
:update-tokens
|
||||||
|
[(inject-cofx :store)]
|
||||||
|
(fn [{:keys [db store]} [_ token admin-token]]
|
||||||
|
(let [ls-data (update-local-storage-tokens store token admin-token)]
|
||||||
|
(println "update-tokens, ls-data:" ls-data)
|
||||||
|
{:db (merge db ls-data)
|
||||||
|
:store ls-data
|
||||||
|
:dispatch [:load-user-repos]})))
|
||||||
|
|
||||||
|
;; copied from plumbing.core to avoid cljsbuild warnings
|
||||||
|
(defn dissoc-in
|
||||||
|
[m [k & ks]]
|
||||||
|
(when m
|
||||||
|
(if-let [res (and ks (dissoc-in (get m k) ks))]
|
||||||
|
(assoc m k res)
|
||||||
|
(let [res (dissoc m k)]
|
||||||
|
(when-not (empty? res)
|
||||||
|
res)))))
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:sign-out
|
:sign-out
|
||||||
|
@ -156,6 +199,7 @@
|
||||||
{:db (assoc db :repos-loading? true)
|
{:db (assoc db :repos-loading? true)
|
||||||
:http {:method GET
|
:http {:method GET
|
||||||
:url "/api/user/repositories"
|
:url "/api/user/repositories"
|
||||||
|
:params {:token (:gh-admin-token db)}
|
||||||
:on-success #(dispatch [:set-user-repos (:repositories %)])
|
:on-success #(dispatch [:set-user-repos (:repositories %)])
|
||||||
:on-error #(dispatch [:set-flash-message
|
:on-error #(dispatch [:set-flash-message
|
||||||
:error "Failed to load repositories"])
|
:error "Failed to load repositories"])
|
||||||
|
@ -175,7 +219,8 @@
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:toggle-repo
|
:toggle-repo
|
||||||
(fn [{:keys [db]} [_ repo]]
|
[(inject-cofx :store)]
|
||||||
|
(fn [{:keys [db store]} [_ repo]]
|
||||||
{:db (assoc db :repos (update-repo-state
|
{:db (assoc db :repos (update-repo-state
|
||||||
(:repos db)
|
(:repos db)
|
||||||
(:full_name repo)
|
(:full_name repo)
|
||||||
|
@ -186,7 +231,12 @@
|
||||||
:on-success #(dispatch [:repo-toggle-success %])
|
:on-success #(dispatch [:repo-toggle-success %])
|
||||||
:on-error #(dispatch [:repo-toggle-error repo %])
|
:on-error #(dispatch [:repo-toggle-error repo %])
|
||||||
:finally #(println "finally" %)
|
:finally #(println "finally" %)
|
||||||
:params (select-keys repo [:id :owner :owner-avatar-url :full_name :name])}}))
|
:params (merge {:token (:gh-admin-token store)}
|
||||||
|
(select-keys repo [:id
|
||||||
|
:owner
|
||||||
|
:owner-avatar-url
|
||||||
|
:full_name
|
||||||
|
:name]))}}))
|
||||||
|
|
||||||
|
|
||||||
(reg-event-db
|
(reg-event-db
|
||||||
|
@ -288,16 +338,6 @@
|
||||||
:error
|
:error
|
||||||
(str "Failed to send transaction" e)]]})))))
|
(str "Failed to send transaction" e)]]})))))
|
||||||
|
|
||||||
;; copied from plumbing.core to avoid cljsbuild warnings
|
|
||||||
(defn dissoc-in
|
|
||||||
[m [k & ks]]
|
|
||||||
(when m
|
|
||||||
(if-let [res (and ks (dissoc-in (get m k) ks))]
|
|
||||||
(assoc m k res)
|
|
||||||
(let [res (dissoc m k)]
|
|
||||||
(when-not (empty? res)
|
|
||||||
res)))))
|
|
||||||
|
|
||||||
(reg-event-fx
|
(reg-event-fx
|
||||||
:payout-confirmed
|
:payout-confirmed
|
||||||
(fn [{:keys [db]} [_ issue-id]]
|
(fn [{:keys [db]} [_ issue-id]]
|
||||||
|
|
|
@ -54,8 +54,8 @@
|
||||||
(into [:div.ui.cards]
|
(into [:div.ui.cards]
|
||||||
(map repo-card group-repos))]))))))
|
(map repo-card group-repos))]))))))
|
||||||
|
|
||||||
|
(defn repos-page-token-ok []
|
||||||
(defn repos-page []
|
(println "repos-token-ok")
|
||||||
(let [repos-loading? (rf/subscribe [:repos-loading?])]
|
(let [repos-loading? (rf/subscribe [:repos-loading?])]
|
||||||
(fn []
|
(fn []
|
||||||
(if @repos-loading?
|
(if @repos-loading?
|
||||||
|
@ -63,3 +63,15 @@
|
||||||
[:div.ui.active.inverted.dimmer
|
[:div.ui.active.inverted.dimmer
|
||||||
[:div.ui.text.loader "Loading"]]]
|
[:div.ui.text.loader "Loading"]]]
|
||||||
[repos-list]))))
|
[repos-list]))))
|
||||||
|
|
||||||
|
(defn repos-page []
|
||||||
|
(let [gh-admin-token (rf/subscribe [:gh-admin-token])]
|
||||||
|
(fn []
|
||||||
|
(println "gh-admin-token" @gh-admin-token)
|
||||||
|
(if (empty? @gh-admin-token)
|
||||||
|
[:div.ui.container
|
||||||
|
[:div.ui.warning.message
|
||||||
|
[:i.warning.icon]
|
||||||
|
"To set bounties for your repositories or for organizations' repositories where you have access, you need to grant Commit ETH the required permissions"]
|
||||||
|
[:a.ui.button.small {:href js/authorizeUrlAdmin} "Enable"]]
|
||||||
|
[repos-page-token-ok]))))
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:activity-feed db)))
|
(:activity-feed db)))
|
||||||
|
|
||||||
|
(reg-sub
|
||||||
|
:gh-admin-token
|
||||||
|
(fn [db _]
|
||||||
|
(:gh-admin-token db)))
|
||||||
|
|
||||||
(reg-sub
|
(reg-sub
|
||||||
:get-in
|
:get-in
|
||||||
(fn [db [_ path]]
|
(fn [db [_ path]]
|
||||||
|
|
Loading…
Reference in New Issue