From 2612bcaefb35c9f99cd1e0962fba88455167df54 Mon Sep 17 00:00:00 2001 From: Leon Barrett Date: Sat, 27 Jan 2018 20:02:20 -0800 Subject: [PATCH 1/4] Ensure base-url ends in `/` --- src/jiggler/main.clj | 9 ++++++++- test/jiggler/main_test.clj | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/jiggler/main.clj b/src/jiggler/main.clj index 4b75729..9dad02f 100644 --- a/src/jiggler/main.clj +++ b/src/jiggler/main.clj @@ -1,12 +1,18 @@ ;; Copyright (c) 2017 Yieldbot (ns jiggler.main (:require + [clojure.string :as str] [clojure.tools.cli :refer [parse-opts]] [com.stuartsierra.component :as component] [jiggler.db :as db] [jiggler.routes :as routes]) (:gen-class)) +(defn ensure-ends-in-slash [s] + (-> s + (str "/") + (str/replace #"/+$" "/"))) + (def cli-options [["-P" "--port PORT" "Port to serve HTTP" :default 8666 @@ -28,7 +34,8 @@ :id :password :default (System/getenv "PGPASSWORD")] [nil "--base-url PATH" "The canonical URL to find this on the web" - :default "/"] + :default "/" + :parse-fn ensure-ends-in-slash] [nil "--sqlite FILE" "Run with a SQLite database"] [nil "--help"]]) diff --git a/test/jiggler/main_test.clj b/test/jiggler/main_test.clj index 89a3d0d..53cbc14 100644 --- a/test/jiggler/main_test.clj +++ b/test/jiggler/main_test.clj @@ -8,6 +8,11 @@ [jiggler.main :as main] [jiggler.routes :as routes])) +(deftest test-ensure-ends-in-slash + (is (= "http://jiggler/a/" (main/ensure-ends-in-slash "http://jiggler/a"))) + (is (= "http://jiggler/a/" (main/ensure-ends-in-slash "http://jiggler/a/"))) + (is (= "http://jiggler/a/" (main/ensure-ends-in-slash "http://jiggler/a//")))) + (deftest test-errors (binding [*out* (jio/writer "/dev/null")] (with-redefs [main/exit! identity] From dd68655041c944739ae6462deb3cb14ce1e05315 Mon Sep 17 00:00:00 2001 From: Leon Barrett Date: Sat, 27 Jan 2018 20:10:42 -0800 Subject: [PATCH 2/4] Simplify Firefox setup esp w/o search bar --- resources/public/setup.html | 28 --------------------------- resources/templates/help.html | 2 +- resources/templates/search.xml | 2 +- resources/templates/setup.html | 17 +++++++++++++++++ src/jiggler/routes.clj | 35 +++++++++++++++++++++++++--------- test/jiggler/routes_test.clj | 23 +++++++++++++++++++--- 6 files changed, 65 insertions(+), 42 deletions(-) delete mode 100644 resources/public/setup.html create mode 100644 resources/templates/setup.html diff --git a/resources/public/setup.html b/resources/public/setup.html deleted file mode 100644 index af40c40..0000000 --- a/resources/public/setup.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - Jiggler Short Links Setup - - -

Jiggler Short Links Setup

-

Jiggler lets you share short links with other people in the company.

-

Setup for: Chrome Firefox

-

Chrome

- Install the Jiggler extension. -

Firefox

-
    -
  1. - Click on the plus in the search box and choose "Add Jiggler".
    - -
  2. -
  3. Click on the plus in the search box and choose "Change Search Settings".
  4. -
  5. - Double-click to the right of Jiggler under the "Keyword" column. Put a "j" there.
    - -
  6. -
  7. Now you can type (for example) "j link" in the address bar to go to that link.
  8. -
- - diff --git a/resources/templates/help.html b/resources/templates/help.html index 50f879e..41c1070 100644 --- a/resources/templates/help.html +++ b/resources/templates/help.html @@ -11,7 +11,7 @@

Usage

For instance, you can use the link "jake" by going to https://JIGGLER-URL/jake, and it'll take you to the jake target.

If you go to a link that's not yet set, you'll be prompted to set it. You can also make or change a link at https://JIGGLER-URL/.

Plugin

-

For great convenience, install the Chrome extension (or see these simple instructions). Then, you can use short links just by typing "j [link]" in your address bar.

+

For great convenience, see these simple instructions to add a browser extension. Then, you can use short links just by typing "l [link]" in your address bar.

Search

You can search existing shortlinks here. diff --git a/resources/templates/search.xml b/resources/templates/search.xml index 43614f6..fe40a37 100644 --- a/resources/templates/search.xml +++ b/resources/templates/search.xml @@ -5,7 +5,7 @@ UTF-8 jiggler-16x16.ico jiggler-64x64.png - + https://URL/ diff --git a/resources/templates/setup.html b/resources/templates/setup.html new file mode 100644 index 0000000..9970ae0 --- /dev/null +++ b/resources/templates/setup.html @@ -0,0 +1,17 @@ + + + + +

+

Jiggler Short Links Setup

+

Jiggler lets you share short links with other people in the company.

+

Setup for: Chrome Firefox

+

Chrome

+

Install the Chrome extension.

+

Firefox

+

Right-click in this text-box and choose "Add a keyword for this search." Recommended keyword: "j".

+ + + diff --git a/src/jiggler/routes.clj b/src/jiggler/routes.clj index ebe9e82..4e5e834 100644 --- a/src/jiggler/routes.clj +++ b/src/jiggler/routes.clj @@ -128,6 +128,11 @@ [:span.selflink] (html/substitute base-url) [:a.selflink] (update-attr :href #(str base-url %))) +(html/deftemplate setup-template "templates/setup.html" [base-url] + [:head] (html/substitute (head-snippet base-url "Jiggler Short Links Help")) + [:#navbar] (html/substitute (navbar-snippet base-url :help)) + [:form.selflink] (update-attr :action #(str base-url %))) + (html/defsnippet search-result-snippet "templates/search-results.html" [:.search-result] [base-url {:keys [shortlink target usage]}] [:.search-shortlink :a] (html/do-> (html/set-attr :href (link-edit-url base-url shortlink)) @@ -168,6 +173,17 @@ {:status 307 :headers {"Location" target}}) +(defn redir + "Look up the shortlink in the database and make a redirection response." + [database base-url shortlink more query-string] + (let [{:keys [target] :as link} (db/get-link database shortlink)] + (if target + (do + (db/increment-usage! database shortlink) + (redir-resp (str target more + (if query-string (str "?" query-string) "")))) + (redir-resp (link-edit-url base-url shortlink))))) + (defn healthz [] {:status 200 :headers {"Content-Type" "text/plain"} @@ -192,7 +208,12 @@ :else (->> (db/update-link database shortlink target x-oauth-user-email) (link-template base-url) (html-resp 201)))) + (cc/GET "/go" {{:keys [link]} :params} + (let [[_ shortlink more query-string] + (re-matches #"([^/?]*)(/[^?]*)?(?:\?(.*))?" link)] + (redir database base-url shortlink more query-string))) (cc/GET "/help" [] (html-resp 200 (help-template base-url))) + (cc/GET "/setup.html" [] (html-resp 200 (setup-template base-url))) (cc/GET "/search" [query] (html-resp 200 (search-template base-url query (db/search database query 30)))) (cc/GET "/healthz" [] @@ -205,14 +226,8 @@ (defn redir-route [database base-url] (cc/GET "/:shortlink{[^/?]*}:more{.*}" req (let [{:keys [query-string params]} req - {:keys [shortlink more]} params - {:keys [target] :as link} (db/get-link database shortlink)] - (if target - (do - (db/increment-usage! database shortlink) - (redir-resp (str target more - (if query-string (str "?" query-string) "")))) - (redir-resp (link-edit-url base-url shortlink)))))) + {:keys [shortlink more]} params] + (redir database base-url shortlink more query-string)))) (defn jiggler-routes [database base-url] (cc/routes @@ -221,7 +236,9 @@ ;; NOTE(lbarrett, 2016-11-09): Set proxy to false to avoid an ;; assertion in ring-ssl/wrap-forwarded-scheme. I don't believe the ;; proxy wrappers are really doing anything for us anyway. - (assoc ring-defaults/api-defaults :proxy false))) + (-> ring-defaults/api-defaults + (assoc :proxy false) + (assoc-in [:responses :absolute-redirects] false)))) ;; Hardcode the "link" link. (cc/GET "/link" [] (redir-resp base-url)) diff --git a/test/jiggler/routes_test.clj b/test/jiggler/routes_test.clj index 6753cb2..4629c5d 100644 --- a/test/jiggler/routes_test.clj +++ b/test/jiggler/routes_test.clj @@ -129,15 +129,32 @@ (is (= {:status 307 :headers {"Location" "http://CANONICAL/_/link?shortlink=a"} :body ""} ((mk-routes) (mock/request :get "/a")))))) +(deftest test-go-redir-not-found + (with-redefs [db/get-link #(hash-map :shortlink %2)] + (is (= {:status 307 :headers {"Location" "http://CANONICAL/_/link?shortlink=a"} :body ""} + (-> ((mk-routes) (mock/request :get "/_/go?link=a")) + (update :headers dissoc "Content-Type")))))) + (deftest test-redir-found (let [link-count (atom {})] (with-redefs [db/get-link #(hash-map :shortlink %2 :target "b") db/increment-usage! (fn [_ sl] (swap! link-count update sl #(inc (or % 0))))] - (is (= {:status 307 :headers {"Location" "b"} :body ""} - ((mk-routes) (mock/request :get "/a")))) - (is (= {"a" 1} @link-count))))) + (is (= {:status 307 :headers {"Location" "b"} :body ""} + ((mk-routes) (mock/request :get "/a")))) + (is (= {"a" 1} @link-count))))) + +(deftest test-go-redir-found + (let [link-count (atom {})] + (with-redefs [db/get-link #(hash-map :shortlink %2 :target "b") + db/increment-usage! (fn [_ sl] + (swap! link-count update sl + #(inc (or % 0))))] + (is (= {:status 307 :headers {"Location" "b"} :body ""} + (-> ((mk-routes) (mock/request :get "/_/go?link=a")) + (update :headers dissoc "Content-Type")))) + (is (= {"a" 1} @link-count))))) (deftest test-healthz (is (= {:status 200 From 96feeca857d227e519c8e027053cae91a10d7719 Mon Sep 17 00:00:00 2001 From: Leon Barrett Date: Sat, 27 Jan 2018 20:13:26 -0800 Subject: [PATCH 3/4] Use x-forwarded-email to work behind oauth2_proxy https://github.com/bitly/oauth2_proxy --- src/jiggler/routes.clj | 4 ++-- test/jiggler/routes_test.clj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jiggler/routes.clj b/src/jiggler/routes.clj index 4e5e834..1d2cf16 100644 --- a/src/jiggler/routes.clj +++ b/src/jiggler/routes.clj @@ -200,12 +200,12 @@ (link-template base-url) (html-resp 200))) (cc/POST "/link" {{:keys [shortlink target]} :params - {:strs [x-oauth-user-email]} :headers} + {:strs [x-forwarded-email]} :headers} (cond (not (and shortlink target)) {:status 400 :body "Missing parameters"} (disallowed? shortlink) {:status 401 :body "Forbidden"} - :else (->> (db/update-link database shortlink target x-oauth-user-email) + :else (->> (db/update-link database shortlink target x-forwarded-email) (link-template base-url) (html-resp 201)))) (cc/GET "/go" {{:keys [link]} :params} diff --git a/test/jiggler/routes_test.clj b/test/jiggler/routes_test.clj index 4629c5d..5670825 100644 --- a/test/jiggler/routes_test.clj +++ b/test/jiggler/routes_test.clj @@ -94,7 +94,7 @@ {:shortlink shortlink :target target :modified? true})] (let [resp ((mk-routes) (-> (mock/request :post "/_/link") (mock/body {:shortlink "a" :target "b"}) - (mock/header :x-oauth-user-email "dummy@yieldbot.com")))] + (mock/header :x-forwarded-email "dummy@yieldbot.com")))] (is (= {"a" ["b" "dummy@yieldbot.com"]} @setval)) (is (= 201 (:status resp))) (is (html? resp)) From 69bb4cecf3f00385f1d938cf090c4288b2add14b Mon Sep 17 00:00:00 2001 From: Leon Barrett Date: Sat, 27 Jan 2018 20:14:21 -0800 Subject: [PATCH 4/4] Fix indentation --- src/jiggler/routes.clj | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/jiggler/routes.clj b/src/jiggler/routes.clj index 1d2cf16..a30e1f7 100644 --- a/src/jiggler/routes.clj +++ b/src/jiggler/routes.clj @@ -231,19 +231,19 @@ (defn jiggler-routes [database base-url] (cc/routes - (-> (ui-routes database base-url) - (ring-defaults/wrap-defaults - ;; NOTE(lbarrett, 2016-11-09): Set proxy to false to avoid an - ;; assertion in ring-ssl/wrap-forwarded-scheme. I don't believe the - ;; proxy wrappers are really doing anything for us anyway. + (-> (ui-routes database base-url) + (ring-defaults/wrap-defaults + ;; NOTE(lbarrett, 2016-11-09): Set proxy to false to avoid an + ;; assertion in ring-ssl/wrap-forwarded-scheme. I don't believe the + ;; proxy wrappers are really doing anything for us anyway. (-> ring-defaults/api-defaults (assoc :proxy false) (assoc-in [:responses :absolute-redirects] false)))) - ;; Hardcode the "link" link. - (cc/GET "/link" [] - (redir-resp base-url)) - (redir-route database base-url) - (route/not-found "Not found"))) + ;; Hardcode the "link" link. + (cc/GET "/link" [] + (redir-resp base-url)) + (redir-route database base-url) + (route/not-found "Not found"))) (defrecord Routes [base-url database routes] component/Lifecycle