Merge branch 'develop'

This commit is contained in:
Teemu Patja 2017-01-21 12:21:36 +02:00
commit bc14283cc0
No known key found for this signature in database
GPG Key ID: F5B7035E6580FD4C
9 changed files with 188 additions and 146 deletions

View File

@ -1,68 +1,66 @@
(defproject commiteth "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:description "Ethereum bounty bot for Github"
:url "https://commiteth.com"
:dependencies [[metosin/compojure-api "1.1.6"]
[re-frame "0.8.0"]
:dependencies [[metosin/compojure-api "1.1.10"]
[re-frame "0.9.1"]
[cljs-ajax "0.5.8"]
[secretary "1.2.3"]
[reagent-utils "0.2.0"]
[reagent "0.6.0"]
[org.clojure/clojurescript "1.9.229" :scope "provided"]
[org.clojure/clojurescript "1.9.293" :scope "provided"]
[org.clojure/clojure "1.8.0"]
[selmer "1.0.7"]
[markdown-clj "0.9.89"]
[selmer "1.10.5"]
[markdown-clj "0.9.91"]
[ring-middleware-format "0.7.0"]
[metosin/ring-http-response "0.8.0"]
[metosin/ring-http-response "0.8.1"]
[bouncer "1.0.0"]
[org.webjars/bootstrap "4.0.0-alpha.3"]
[org.webjars/font-awesome "4.6.3"]
[org.webjars/bootstrap "4.0.0-alpha.6"]
[org.webjars/font-awesome "4.7.0"]
[org.webjars/bootstrap-social "5.0.0"]
[org.webjars.bower/tether "1.3.3"]
[org.webjars.bower/tether "1.4.0"]
[org.clojure/tools.logging "0.3.1"]
[compojure "1.5.1"]
[http-kit "2.1.18"]
[compojure "1.5.2"]
[http-kit "2.2.0"]
[ring/ring-json "0.4.0"]
[ring-webjars "0.1.1"]
[ring/ring-defaults "0.2.1"]
[mount "0.1.10"]
[cprop "0.1.9"]
[ring/ring-defaults "0.2.2"]
[ring/ring-codec "1.0.1"]
[mount "0.1.11"]
[cprop "0.1.10"]
[org.clojure/tools.cli "0.3.5"]
[luminus-nrepl "0.1.4"]
[buddy "1.0.0"]
[buddy/buddy-auth "1.1.0"]
[luminus-migrations "0.2.6"]
[conman "0.6.0"]
[org.postgresql/postgresql "9.4.1209"]
[buddy "1.2.0"]
[buddy/buddy-auth "1.3.0"]
[luminus-migrations "0.2.9"]
[conman "0.6.3"]
[org.postgresql/postgresql "9.4.1212"]
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
[luminus-immutant "0.2.2"]
[luminus-immutant "0.2.3"]
[clj.qrgen "0.4.0"]
[digest "1.4.4"]
[digest "1.4.5"]
[tentacles "0.5.1"]]
:min-lein-version "2.0.0"
:jvm-opts ["-server" "-Dconf=.lein-env"]
:source-paths ["src/clj" "src/cljc"]
:resource-paths ["resources" "target/cljsbuild"]
:target-path "target/%s/"
:main commiteth.core
:migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
:migratus {:store :database
:migration-dir "resources/migrations"
:db ~(get (System/getenv) "DATABASE_URL")}
:plugins [[lein-cprop "1.0.1"]
[migratus-lein "0.4.1"]
[lein-cljsbuild "1.1.3"]
[lein-immutant "2.1.0"]
[lein-sassc "0.10.4"]
[lein-npm "0.6.2"]
[lein-auto "0.1.2"]]
:immutant {:war {:name "ROOT"
:destination "/opt/wildfly/standalone/deployments"
:context-path "/"}}
:ring {:destroy commiteth.scheduler/stop-scheduler}
;:npm {:dependencies ["primer-css" "latest"]}
:user {:plugins [[cider/cider-nrepl "0.15.0-SNAPSHOT"]]}
:ring {:destroy commiteth.scheduler/stop-scheduler}
:sassc
[{:src "resources/scss/main.scss"
@ -74,7 +72,7 @@
{"sassc" {:file-pattern #"\.(scss|sass)$" :paths ["resources/scss"]}}
:clean-targets ^{:protect false}
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
[:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
:figwheel
{:http-server-root "public"
:nrepl-port 7002
@ -86,16 +84,16 @@
{:uberjar {:omit-source true
:prep-tasks ["compile" ["cljsbuild" "once" "min"]]
:cljsbuild
{:builds
{:min
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
:compiler
{:output-to "target/cljsbuild/public/js/app.js"
:externs ["react/externs/react.js"]
:optimizations :advanced
:pretty-print false
:closure-warnings
{:externs-validation :off :non-standard-jsdoc :off}}}}}
{:builds
{:min
{:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
:compiler
{:output-to "target/cljsbuild/public/js/app.js"
:externs ["react/externs/react.js"]
:optimizations :advanced
:pretty-print false
:closure-warnings
{:externs-validation :off :non-standard-jsdoc :off}}}}}
:aot :all
@ -106,30 +104,30 @@
:dev [:project/dev :profiles/dev]
:test [:project/test :profiles/test]
:project/dev {:dependencies [[prone "1.1.1"]
:project/dev {:dependencies [[prone "1.1.4"]
[ring/ring-mock "0.3.0"]
[ring/ring-devel "1.5.0"]
[ring/ring-devel "1.5.1"]
[pjstadig/humane-test-output "0.8.1"]
[doo "0.1.7"]
[binaryage/devtools "0.8.1"]
[figwheel-sidecar "0.5.7"]
[binaryage/devtools "0.8.3"]
[figwheel-sidecar "0.5.8"]
[org.clojure/tools.nrepl "0.2.12"]
[com.cemerick/piggieback "0.2.2-SNAPSHOT"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.14.0"]
[lein-doo "0.1.7"]
[lein-figwheel "0.5.7"]
[org.clojure/clojurescript "1.9.225"]]
[lein-figwheel "0.5.7"]]
:cljsbuild
{:builds
{:app
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
:compiler
{:main "commiteth.app"
:asset-path "/js/out"
:output-to "target/cljsbuild/public/js/app.js"
:output-dir "target/cljsbuild/public/js/out"
:source-map true
:optimizations :none
:pretty-print true}}}}
{:builds
{:app
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
:compiler
{:main "commiteth.app"
:asset-path "/js/out"
:output-to "target/cljsbuild/public/js/app.js"
:output-dir "target/cljsbuild/public/js/out"
:source-map true
:optimizations :none
:pretty-print true}}}}
@ -141,14 +139,14 @@
(pjstadig.humane-test-output/activate!)]}
:project/test {:resource-paths ["env/dev/resources" "env/test/resources"]
:cljsbuild
{:builds
{:test
{:source-paths ["src/cljc" "src/cljs" "test/cljs"]
:compiler
{:output-to "target/test.js"
:main "commiteth.doo-runner"
:optimizations :whitespace
:pretty-print true}}}}
{:builds
{:test
{:source-paths ["src/cljc" "src/cljs" "test/cljs"]
:compiler
{:output-to "target/test.js"
:main "commiteth.doo-runner"
:optimizations :whitespace
:pretty-print true}}}}
}
:profiles/dev {}

View File

@ -4,7 +4,8 @@
[clojure.java.io :as io]
[commiteth.config :refer [env]]
[clojure.string :refer [join]]
[clojure.tools.logging :as log]))
[clojure.tools.logging :as log]
[clojure.string :as str]))
(def eth-rpc-url "http://localhost:8545")
(defn eth-account [] (:eth-account env))
@ -57,12 +58,16 @@
(defn send-transaction
[from to value & [params]]
;; todo: estimate gas instead of hardcoding
(let [gas 2100000]
(eth-rpc "personal_signAndSendTransaction" [(merge params {:from from
:to to
:value value
:gas gas})
(eth-password)])))
(let [gas (format "0x%x" 2600000)
args (merge params {:from from
:value value
:gas gas})]
(eth-rpc
"personal_sendTransaction"
[(if (not (nil? to))
(merge args {:to to})
args)
(eth-password)])))
(defn get-transaction-receipt
[hash]
@ -74,14 +79,16 @@
(format "%064x" param)
(clojure.string/replace (format "%64s" (subs param 2)) " " "0")))
(defn deploy-contract
[owner]
(let [contract-code (-> "contracts/wallet.data" io/resource slurp)
owner1 (format-param (eth-account))
owner2 (format-param owner)
data (str contract-code owner1 owner2)]
data (str contract-code owner1 owner2)
value (format "0x%x" 1)]
(println data)
(send-transaction (eth-account) nil 1 {:data data})))
(send-transaction (eth-account) nil value {:data data})))
(defn- format-call-params
[method-id & params]
@ -95,5 +102,6 @@
(defn execute
[from contract method-id & params]
(let [data (apply format-call-params method-id params)]
(send-transaction from contract 1 {:data data})))
(let [data (apply format-call-params method-id params)
value (format "0x%x" 1)]
(send-transaction from contract value {:data data})))

View File

@ -9,7 +9,8 @@
[commiteth.config :refer [env]]
[digest :refer [sha-256]]
[clojure.tools.logging :as log]
[cheshire.core :as json])
[cheshire.core :as json]
[clojure.string :as str])
(:import [java.util UUID]))
(def ^:dynamic url "https://api.github.com/")
@ -25,7 +26,7 @@
(defn authorize-url []
(let [params (codec/form-encode {:client_id (client-id)
:redirect_uri (redirect-uri)
:scope "admin:repo_hook repo"
:scope "admin:repo_hook user:email repo admin:org_hook"
:allow_signup true
:state (str (UUID/randomUUID))})]
(str "https://github.com/login/oauth/authorize" "?" params)))
@ -33,12 +34,12 @@
(defn post-for-token
[code state]
(http/post "https://github.com/login/oauth/access_token"
{:content-type :json
:form-params {:client_id (client-id)
:client_secret (client-secret)
:code code
:redirect_uri (redirect-uri)
:state state}}))
{:content-type :json
:form-params {:client_id (client-id)
:client_secret (client-secret)
:code code
:redirect_uri (redirect-uri)
:state state}}))
(defn- auth-params
[token]
@ -69,40 +70,50 @@
"List all repos managed by the given user."
[token]
(->>
(map #(merge
{:login (get-in % login-field)}
(select-keys % repo-fields))
(repos/repos (merge (auth-params token) {:type "all"
:all-pages true})))
(filter #(not (:fork %)))
(filter #(-> % :permissions :admin))))
(map #(merge
{:login (get-in % login-field)}
(select-keys % repo-fields))
(repos/repos (merge (auth-params token) {:type "all"
:all-pages true})))
(filter #(not (:fork %)))
(filter #(-> % :permissions :admin))))
(defn get-user
[token]
(users/me (auth-params token)))
(defn get-user-email
[token]
(let [emails (users/emails (auth-params token))]
(->
(filter :primary emails)
first
:email)))
(defn add-webhook
[user repo token]
(log/debug "adding webhook" (str user "/" repo) token)
(repos/create-hook user repo "web"
{:url (str (server-address) "/webhook")
:content_type "json"}
(merge (auth-params token)
{:events ["issues", "issue_comment", "pull_request"]
:active true})))
[full-repo token]
(log/debug "adding webhook" full-repo token)
(let [[user repo] (str/split full-repo #"/")]
(repos/create-hook user repo "web"
{:url (str (server-address) "/webhook")
:content_type "json"}
(merge (auth-params token)
{:events ["issues", "issue_comment", "pull_request"]
:active true}))))
(defn remove-webhook
[user repo hook-id token]
(log/debug "removing webhook" (str user "/" repo) hook-id token)
(repos/delete-hook user repo hook-id (auth-params token)))
[full-repo hook-id token]
(let [[user repo] (str/split full-repo #"/")]
(log/debug "removing webhook" (str user "/" repo) hook-id token)
(repos/delete-hook user repo hook-id (auth-params token))))
(defn github-comment-hash
[user repo issue-number]
(digest/sha-256 (str "SALT_Yoh2looghie9jishah7aiphahphoo6udiju" user repo issue-number)))
[user repo issue-number balance]
(digest/sha-256 (str "SALT_Yoh2looghie9jishah7aiphahphoo6udiju" user repo issue-number balance)))
(defn- get-qr-url
[user repo issue-number]
(let [hash (github-comment-hash user repo issue-number)]
[user repo issue-number balance]
(let [hash (github-comment-hash user repo issue-number balance)]
(str (server-address) (format "/qr/%s/%s/bounty/%s/%s/qr.png" user repo issue-number hash))))
(defn- md-url
@ -117,7 +128,7 @@
(defn generate-comment
[user repo issue-number balance]
(let [image-url (md-image "QR Code" (get-qr-url user repo issue-number))
(let [image-url (md-image "QR Code" (get-qr-url user repo issue-number balance))
balance (str balance " ETH")
site-url (md-url (server-address) (server-address))]
(format "Current balance: %s\n%s\n%s" balance image-url site-url)))
@ -132,13 +143,18 @@
(let [{:keys [auth oauth-token]
:as query} query
req (merge-with merge
{:url (tentacles/format-url end-point positional)
:basic-auth auth
:method :patch}
(when oauth-token
{:headers {"Authorization" (str "token " oauth-token)}}))
{:url (tentacles/format-url end-point positional)
:basic-auth auth
:method :patch}
(when oauth-token
{:headers {"Authorization" (str "token " oauth-token)}}))
raw-query (:raw query)
proper-query (tentacles/query-map (dissoc query :auth :oauth-token :all-pages :accept :user-agent :otp))]
proper-query (tentacles/query-map (dissoc query :auth
:oauth-token
:all-pages
:accept
:user-agent
:otp))]
(assoc req :body (json/generate-string (or raw-query proper-query)))))
(defn update-comment
@ -146,7 +162,8 @@
(let [comment (generate-comment user repo issue-number balance)]
(log/debug (str "Updating " user "/" repo "/" issue-number " comment #" comment-id " with contents: " comment))
(let [req (make-patch-request "repos/%s/%s/issues/comments/%s"
[user repo comment-id] (assoc (self-auth-params) :body comment))]
[user repo comment-id]
(assoc (self-auth-params) :body comment))]
(tentacles/safe-parse (http/request req)))))
(defn get-issue
@ -158,6 +175,7 @@
(issues/issue-events user repo issue-id (self-auth-params)))
(defn create-label
[user repo token]
(log/debug "creating bounty label" (str user "/" repo) token)
(issues/create-label user repo "bounty" "00ff00" (auth-params token)))
[full-repo token]
(let [[user repo] (str/split full-repo #"/")]
(log/debug "creating bounty label" (str user "/" repo) token)
(issues/create-label user repo "bounty" "00ff00" (auth-params token))))

View File

@ -6,14 +6,15 @@
[commiteth.util.images :refer :all]
[clj.qrgen :as qr]
[commiteth.eth.core :as eth]
[commiteth.github.core :as github])
[commiteth.github.core :as github]
[clojure.tools.logging :as log])
(:import [javax.imageio ImageIO]
[java.io InputStream]))
(defn ^InputStream generate-qr-code
[address]
(qr/as-input-stream
(qr/from (str "ethereum:" address) :size [256 256])))
(qr/from (str "ethereum:" address) :size [256 256])))
(defn generate-html
[address balance issue-url]
@ -24,20 +25,28 @@
(defn generate-image
[address balance issue-url width height]
(let [qr-code-image (ImageIO/read (generate-qr-code address))
comment-image (html->image (generate-html address balance issue-url) width height)]
comment-image (html->image
(generate-html address balance issue-url) width height)]
(combine-images qr-code-image comment-image)))
(defapi qr-routes
(context "/qr" []
(GET "/:user/:repo/bounty/:issue{[0-9]{1,9}}/:hash/qr.png" [user repo issue hash]
(if (= hash (github/github-comment-hash user repo issue))
(let [{address :contract_address
login :login
repo :repo
issue-number :issue_number} (bounties/get-bounty-address user repo (Integer/parseInt issue))]
(if address
(let [balance (eth/get-balance-eth address 8)
issue-url (str login "/" repo "/issues/" issue-number)]
(ok (generate-image address balance issue-url 768 256)))
(bad-request)))
(bad-request)))))
;; user may be an organization here
(GET "/:user/:repo/bounty/:issue{[0-9]{1,9}}/:hash/qr.png" [user repo issue hash]
(log/debug "qr PNG GET")
(let [{address :contract_address
login :login
repo :repo
issue-number :issue_number}
(bounties/get-bounty-address user
repo
(Integer/parseInt issue))
balance (eth/get-balance-eth address 8)]
(log/debug "address:" address "balance:" balance)
(if (and address
(= hash (github/github-comment-hash user repo issue balance)))
(let [issue-url (str login "/" repo "/issues/" issue-number)]
(log/debug "balance:" address)
(ok (generate-image address balance issue-url 768 256)))
(bad-request))))))

View File

@ -8,18 +8,27 @@
[ring.util.http-response :refer [content-type ok]]
[ring.util.response :as response]
[commiteth.layout :refer [render]]
[cheshire.core :refer [generate-string]]))
[cheshire.core :refer [generate-string]]
[clojure.tools.logging :as log]))
(defn- create-user [token user]
(let [{name :name
login :login
user-id :id} user
email (github/get-user-email token)]
(users/create-user user-id login name email token)))
(defn- get-or-create-user
[token]
(let [user (github/get-user token)
{email :email
name :name
login :login
user-id :id} user]
(log/debug "get-or-create-user" user)
(or
(users/update-user-token user-id token)
(users/create-user user-id login name email token))))
(create-user token user))))
(defroutes redirect-routes
(GET "/callback" [code state]

View File

@ -77,7 +77,7 @@
:auth-rules authenticated?
:current-user user
(ok (let [{repo-id :id
repo :name} params
repo :full_name} params
{token :token
login :login
user-id :id} user
@ -86,9 +86,9 @@
(repositories/toggle repo-id))]
(if (:enabled result)
;; @todo: do we really want to make this call at this moment?
(let [created-hook (github/add-webhook login repo token)]
(let [created-hook (github/add-webhook repo token)]
(log/debug "Created webhook:" created-hook)
(github/create-label login repo token)
(github/create-label repo token)
(repositories/update-hook-id repo-id (:id created-hook)))
(github/remove-webhook login repo (:hook_id result) token))
(github/remove-webhook repo (:hook_id result) token))
result)))))

View File

@ -137,11 +137,12 @@
(reg-event-fx
:toggle-repo
(fn [{:keys [db]} [_ repo]]
(println "toggle-repo" repo)
{:db db
:http {:method POST
:url "/api/repository/toggle"
:on-success #(println %)
:params (select-keys repo [:id :login :name])}}))
:params (select-keys repo [:id :login :full_name :name])}}))
(reg-event-fx
:save-user-address

View File

@ -8,7 +8,7 @@
(defn repository-row [repo]
(let [{repo-id :id
url :html_url
name :name
name :full_name
description :description} repo]
^{:key repo-id}
[:div.d-table.width-full

View File

@ -12,7 +12,6 @@
(mount/start
#'commiteth.config/env
#'commiteth.db.core/*db*)
(println (env :jdbc-database-url))
(migrations/migrate ["migrate"]
{:database-url (env :jdbc-database-url)})
(f)))