From 526ad8f664ee9c44072cdfb70963149911a7e1dd Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:21:48 -0200
Subject: [PATCH 1/6] Implement assert-cors-header to test_helper

---
 test/clojars/test/test_helper.clj | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/test/clojars/test/test_helper.clj b/test/clojars/test/test_helper.clj
index 720ef1ed..369cdb9d 100644
--- a/test/clojars/test/test_helper.clj
+++ b/test/clojars/test/test_helper.clj
@@ -108,3 +108,8 @@
 
 (defn get-content-type [resp]
   (some-> resp :headers (get "content-type") (string/split #";") first))
+
+(defn assert-cors-header [resp]
+  (some-> resp :headers
+          (get "access-control-allow-origin")
+          (= "*")))

From d5d677e0ed9fda96ecf96a68b7234a5a273fae4b Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:22:58 -0200
Subject: [PATCH 2/6] Move http-related wrappers to http-utils

---
 src/clojars/http_utils.clj | 27 +++++++++++++++++++++++++++
 src/clojars/web.clj        | 19 ++-----------------
 2 files changed, 29 insertions(+), 17 deletions(-)
 create mode 100644 src/clojars/http_utils.clj

diff --git a/src/clojars/http_utils.clj b/src/clojars/http_utils.clj
new file mode 100644
index 00000000..a3b89617
--- /dev/null
+++ b/src/clojars/http_utils.clj
@@ -0,0 +1,27 @@
+(ns clojars.http-utils
+  (:require [ring.middleware
+             [session :refer [wrap-session]]]))
+
+(defn wrap-cors-headers [handler]
+  (fn [req]
+    (let [response (handler req)]
+      (if (= 200 (:status response))
+                     (update-in response [:headers] assoc "Access-Control-Allow-Origin" "*")
+                     response
+                     ))))
+
+(defn wrap-x-frame-options [f]
+  (fn [req] (update-in (f req) [:headers] assoc "X-Frame-Options" "DENY")))
+
+(defn https-request? [req]
+  (or (= (:scheme req) :https)
+      (= (get-in req [:headers "x-forwarded-proto"]) "https")))
+
+(defn wrap-secure-session [f]
+  (let [secure-session (wrap-session f {:cookie-attrs {:secure true
+                                                       :http-only true}})
+        regular-session (wrap-session f {:cookie-attrs {:http-only true}})]
+    (fn [req]
+      (if (https-request? req)
+        (secure-session req)
+        (regular-session req)))))
diff --git a/src/clojars/web.clj b/src/clojars/web.clj
index 5a537abf..01b9f339 100644
--- a/src/clojars/web.clj
+++ b/src/clojars/web.clj
@@ -7,7 +7,8 @@
              [auth :refer [try-account]]
              [config :refer [config]]
              [db :as db]
-             [errors :refer [wrap-exceptions]]]
+             [errors :refer [wrap-exceptions]]
+             [http-utils :refer [wrap-x-frame-options wrap-secure-session]]]
             [clojars.friend.registration :as registration]
             [clojars.routes
              [api :as api]
@@ -99,22 +100,6 @@
           (swap! attempts bad-attempt username)
           nil)))))
 
-(defn wrap-x-frame-options [f]
-  (fn [req] (update-in (f req) [:headers] assoc "X-Frame-Options" "DENY")))
-
-(defn https-request? [req]
-  (or (= (:scheme req) :https)
-      (= (get-in req [:headers "x-forwarded-proto"]) "https")))
-
-(defn wrap-secure-session [f]
-  (let [secure-session (wrap-session f {:cookie-attrs {:secure true
-                                                      :http-only true}})
-        regular-session (wrap-session f {:cookie-attrs {:http-only true}})]
-    (fn [req]
-      (if (https-request? req)
-        (secure-session req)
-        (regular-session req)))))
-
 (defn clojars-app [db reporter stats search mailer]
   (routes
    (context "/repo" _

From cbd1ad2efeb8bdfc42e600e6c47a5ce5783e6844 Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:24:12 -0200
Subject: [PATCH 3/6] Add test cases to check CORS conformity

---
 test/clojars/test/integration/api.clj      |  7 +++++--
 test/clojars/test/integration/artifact.clj | 23 ++++++++++++++++++++++
 test/clojars/test/integration/search.clj   |  3 +++
 3 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 test/clojars/test/integration/artifact.clj

diff --git a/test/clojars/test/integration/api.clj b/test/clojars/test/integration/api.clj
index a281a44d..9c954d0a 100644
--- a/test/clojars/test/integration/api.clj
+++ b/test/clojars/test/integration/api.clj
@@ -10,8 +10,8 @@
             [cheshire.core :as json]))
 
 (use-fixtures :each
-  help/default-fixture
-  help/run-test-app)
+              help/default-fixture
+              help/run-test-app)
 
 (defn get-api [parts & [opts]]
   (-> (str "http://localhost:" help/test-port "/api/"
@@ -46,6 +46,9 @@
   (testing "default format is json"
     (is (= "application/json" (help/get-content-type (get-api [:groups "fake"])))))
 
+  (testing "api endpoints uses permissive cors settings"
+    (is (help/assert-cors-header (get-api [:groups "fake"]))))
+
   (testing "list group artifacts"
     (let [resp (get-api [:groups "fake"] {:accept :json})
           body (json/parse-string (:body resp) true)]
diff --git a/test/clojars/test/integration/artifact.clj b/test/clojars/test/integration/artifact.clj
new file mode 100644
index 00000000..4539b19c
--- /dev/null
+++ b/test/clojars/test/integration/artifact.clj
@@ -0,0 +1,23 @@
+(ns clojars.test.integration.artifact
+  (:require [clojure.test :refer :all]
+            [clojars.test.test-helper :as help]
+            [clojure.string :as str]
+            [clj-http.lite.client :as client]
+            [kerodon.core :refer [session]]
+            [clojars.test.integration.steps :refer [register-as inject-artifacts-into-repo!]]
+            [cheshire.core :as json]))
+
+(use-fixtures :each
+              help/using-test-config
+              help/default-fixture
+              help/with-clean-database
+              help/run-test-app)
+
+(defn get-artifact [parts & [opts]]
+  (-> (str "http://localhost:" help/test-port "/"
+           (str/join "/" (map name parts)))
+      (client/get opts)))
+
+(deftest artifacts-test
+  (testing "latest-version.json should have permissive cors headers"
+    (is (help/assert-cors-header (get-artifact ["test" "latest-version.json"])))))
diff --git a/test/clojars/test/integration/search.clj b/test/clojars/test/integration/search.clj
index 1464ad66..203a4062 100644
--- a/test/clojars/test/integration/search.clj
+++ b/test/clojars/test/integration/search.clj
@@ -32,6 +32,9 @@
         (is (= 200 (:status resp)))
         (is (= "application/json" (help/get-content-type resp)))))
 
+    (testing "json request uses permissive cors headers"
+      (is (help/assert-cors-header (do-search :json "test"))))
+
     (testing "default request returns html"
       (let [resp (do-search "" "test")]
         (is (= 200 (:status resp)))

From 1f14cd74baea286d0ddcacc0be28dff3607de580 Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:24:37 -0200
Subject: [PATCH 4/6] Ensure CORS conformity on /api

---
 src/clojars/routes/api.clj | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/clojars/routes/api.clj b/src/clojars/routes/api.clj
index 32016b63..32d29285 100644
--- a/src/clojars/routes/api.clj
+++ b/src/clojars/routes/api.clj
@@ -1,7 +1,8 @@
 (ns clojars.routes.api
   (:require [clojars
              [db :as db]
-             [stats :as stats]]
+             [stats :as stats]
+             [http-utils :refer [wrap-cors-headers]]]
             [compojure
              [core :as compojure :refer [ANY context GET]]
              [route :refer [not-found]]]
@@ -47,4 +48,5 @@
 
 (defn routes [db stats]
   (-> (handler db stats)
+      (wrap-cors-headers)
       (wrap-restful-response :formats [:json :edn :yaml :transit-json])))

From 78a8b95a63e080de0cdac1daf875b3874dfda992 Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:25:03 -0200
Subject: [PATCH 5/6] Ensure CORS conformity on artifact endpoints

---
 src/clojars/routes/artifact.clj | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/clojars/routes/artifact.clj b/src/clojars/routes/artifact.clj
index c64756b6..00b4fcbb 100644
--- a/src/clojars/routes/artifact.clj
+++ b/src/clojars/routes/artifact.clj
@@ -45,10 +45,12 @@
   (cond
     (= file-format "json") (-> (response/response (view/make-latest-version-json db group-id artifact-id))
                                (response/header "Cache-Control" "no-cache")
-                               (response/content-type "application/json; charset=UTF-8"))
+                               (response/content-type "application/json; charset=UTF-8")
+                               (response/header "Access-Control-Allow-Origin" "*"))
     (= file-format "svg") (-> (response/response (view/make-latest-version-svg db group-id artifact-id))
                               (response/header "Cache-Control" "no-cache")
-                              (response/content-type "image/svg+xml")))))
+                              (response/content-type "image/svg+xml")
+                              (response/header "Access-Control-Allow-Origin" "*")))))
 
 (defn routes [db reporter stats]
   (compojure/routes

From 1fcc7001a079535bbe42bdd697605ae90db1c8f9 Mon Sep 17 00:00:00 2001
From: Victor Gama <hey@vito.io>
Date: Mon, 4 Jan 2016 15:25:20 -0200
Subject: [PATCH 6/6] Ensure CORS conformity on /search endpoints

---
 src/clojars/web/search.clj | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/clojars/web/search.clj b/src/clojars/web/search.clj
index e2f23699..d7930ef7 100644
--- a/src/clojars/web/search.clj
+++ b/src/clojars/web/search.clj
@@ -17,7 +17,8 @@
 
 (defn json-search [search query]
   (let [response {:status 200
-                  :headers {"Content-Type" "application/json; charset=UTF-8"}}]
+                  :headers {"Content-Type" "application/json; charset=UTF-8"
+                            "Access-Control-Allow-Origin" "*"}}]
     (try
       (assoc response
         :body (let [results (search/search search query 1)]