Skip to content

Commit e6c04d6

Browse files
committed
Add util for self-verification of VCS-based groups
1 parent 53e45af commit e6c04d6

File tree

2 files changed

+102
-5
lines changed

2 files changed

+102
-5
lines changed

src/clojars/verification.clj

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
(ns clojars.verification
22
(:require
3+
[clj-http.client :as http]
34
[clojars.db :as db]
45
[clojars.web.common :as common]
56
[clojure.java.shell :as shell]
7+
[clojure.set :as set]
68
[clojure.string :as str]))
79

810
(defn- get-txt-records
@@ -51,11 +53,15 @@
5153
[request msg]
5254
(assoc request :error msg))
5355

54-
(defn- verify-group
55-
[db request username group]
56+
(defn- verify-group*
57+
[db username group]
5658
;; will only create the group if it doesn't already exist
5759
(db/add-group db username group)
58-
(db/verify-group! db username group)
60+
(db/verify-group! db username group))
61+
62+
(defn- verify-group
63+
[db request username group]
64+
(verify-group* db username group)
5965
(assoc request :message (format "The group '%s' has been verified." group)))
6066

6167
(defn verify-group-by-TXT
@@ -95,7 +101,7 @@
95101
(err request "No valid verification TXT record found.")
96102

97103
(not (= username username-from-txt))
98-
(err request (format "Validation TXT record is for user '%s', not '%s' (you)."
104+
(err request (format "The verification TXT record is for user '%s', not '%s' (you)."
99105
username-from-txt username))
100106

101107
group-verification
@@ -136,3 +142,56 @@
136142
(db/find-group-verifications-for-users-groups db username))]
137143
(verify-group db (assoc request :parent-group parent-group-name) username group)
138144
(err request "The group is not a subgroup of a verified group.")))))
145+
146+
(defn- parse-url
147+
[url]
148+
(when (string? url)
149+
(rest (re-find #"^https://(github|gitlab)\.com/([^/]+)/clojars-([^/]+)/?$" url))))
150+
151+
(defn- repo-exists?
152+
[url]
153+
(try
154+
(= 200 (:status (http/head url {:throw-exceptions false})))
155+
(catch Exception _
156+
false)))
157+
158+
(defn- verify-groups
159+
[db request username groups]
160+
(if (= 1 (count groups))
161+
(verify-group db request username (first groups))
162+
(do
163+
(doseq [group groups]
164+
(verify-group* db username group))
165+
;; We will only have two groups here, so this format string should be fine
166+
(assoc request :message (apply format "The groups '%s' & '%s' have been verified." groups)))))
167+
168+
(defn verify-vcs-groups
169+
"Verifies the net. and com. groups for a github/gitlab organization based on url."
170+
[db {:as request :keys [username url]}]
171+
(let [[provider org username-from-url] (parse-url url)
172+
candidate-groups (set (for [tld ["com" "net"]] (format "%s.%s.%s" tld provider org)))
173+
group-verifications (set (map
174+
(fn [group-name]
175+
(db/find-group-verification db group-name))
176+
candidate-groups))
177+
group-verification-names (set (map :group_name group-verifications))
178+
groups-to-verify (set/difference candidate-groups group-verifications)]
179+
(cond
180+
(not provider)
181+
(err request "The format of the URL is invalid.")
182+
183+
(= candidate-groups group-verification-names)
184+
(let [{:keys [created verified_by]} (first group-verifications)]
185+
(err request (format "Groups already verified by user '%s' on %s."
186+
verified_by
187+
(common/format-date created))))
188+
189+
(not (= username username-from-url))
190+
(err request (format "The verification repo is for user '%s', not '%s' (you)."
191+
username-from-url username))
192+
193+
(not (repo-exists? url))
194+
(err request "The verification repo does not exist.")
195+
196+
:else
197+
(verify-groups db request username groups-to-verify))))

test/clojars/unit/verification_test.clj

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(ns clojars.unit.verification-test
22
(:require
3+
[clj-http.client :as http]
34
[clojars.db :as db]
45
[clojars.test-helper :as help]
56
[clojars.verification :as nut]
@@ -70,7 +71,7 @@
7071
(help/with-TXT records
7172
(is (match?
7273
{:txt-records records
73-
:error "Validation TXT record is for user 'abc', not 'dantheman' (you)."}
74+
:error "The verification TXT record is for user 'abc', not 'dantheman' (you)."}
7475
(nut/verify-group-by-TXT help/*db* {:username "dantheman"
7576
:group "com.foo"
7677
:domain "foo.com"}))))))
@@ -170,3 +171,40 @@
170171
:parent-group "com.foo"}
171172
(nut/verify-group-by-parent-group help/*db* {:group "com.foo.bar"
172173
:username "dantheman"}))))
174+
175+
(deftest verify-vcs-groups-with-invalid-url
176+
(is (match?
177+
{:error "The format of the URL is invalid."}
178+
(nut/verify-vcs-groups help/*db* {:url "huh?"}))))
179+
180+
(deftest verify-vcs-groups-with-url-not-matching-user
181+
(is (match?
182+
{:error "The verification repo is for user 'manthedan', not 'dantheman' (you)."}
183+
(nut/verify-vcs-groups help/*db* {:url "https://github.com/foo/clojars-manthedan"
184+
:username "dantheman"}))))
185+
186+
(deftest verify-vcs-groups-with-already-verified-groups
187+
(db/verify-group! help/*db* "dantheman" "com.github.foo")
188+
(db/verify-group! help/*db* "dantheman" "net.github.foo")
189+
(is (match?
190+
{:error (format "Groups already verified by user 'dantheman' on %s."
191+
(common/format-date (Date.)))}
192+
(nut/verify-vcs-groups help/*db* {:url "https://github.com/foo/clojars-dantheman"
193+
:username "dantheman"}))))
194+
195+
(deftest verify-vcs-groups-with-non-existent-repo
196+
(doseq [responders [(constantly {:status 404})
197+
(constantly {:status 302})
198+
(fn [& _] (throw (ex-info "BOOM" {})))]]
199+
(with-redefs [http/head responders]
200+
(is (match?
201+
{:error "The verification repo does not exist."}
202+
(nut/verify-vcs-groups help/*db* {:url "https://github.com/foo/clojars-dantheman"
203+
:username "dantheman"}))))))
204+
205+
(deftest verify-vcs-groups-when-the-repo-exists
206+
(with-redefs [http/head (constantly {:status 200})]
207+
(is (match?
208+
{:message "The groups 'com.github.foo' & 'net.github.foo' have been verified."}
209+
(nut/verify-vcs-groups help/*db* {:url "https://github.com/foo/clojars-dantheman"
210+
:username "dantheman"})))))

0 commit comments

Comments
 (0)