Instantly share code, notes, and snippets.

Embed
What would you like to do?
(ns creator.handler
(:require [compojure.core :refer :all]
[compojure.handler :as handler]
[compojure.route :as route]
[ring.middleware.params :refer [wrap-params]]
[hiccup.page :refer [html5 include-css include-js]]
[clojure.data.json :as json]
[ring.util.codec :refer [base64-encode]])
(:import (javax.crypto Mac)
(javax.crypto.spec SecretKeySpec)
(java.text SimpleDateFormat)
(java.util Date TimeZone)))
(def s3-bucket "your-bucket")
(def aws-access-key "key")
(def aws-secret-key "secret")
(defn now-plus [n]
"Returns current time plus `n` minutes as string"
(let [f (SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
_ (.setTimeZone f (TimeZone/getTimeZone "UTC" ))]
(.format f (Date. (+ (System/currentTimeMillis) (* n 60 1000))))))
(defn policy
"Generate policy for upload of `key` with `mime-type` to be uploaded
within optional `expiration-window` (defaults to 60)."
([key mime-type]
(policy key mime-type 60))
([key mime-type expiration-window]
(ring.util.codec/base64-encode
(.getBytes (json/write-str { "expiration" (now-plus expiration-window)
"conditions" [{"bucket" s3-bucket}
{"acl" "public-read"}
["starts-with" "$Content-Type" mime-type]
["starts-with" "$key" key]
{"success_action_status" "201"}]})
"UTF-8"))))
(defn hmac-sha1 [key string]
"Returns signature of `string` with a given `key` using SHA-1 HMAC."
(ring.util.codec/base64-encode
(.doFinal (doto (javax.crypto.Mac/getInstance "HmacSHA1")
(.init (javax.crypto.spec.SecretKeySpec. (.getBytes key) "HmacSHA1")))
(.getBytes string "UTF-8"))))
(defn sign-upload [{:keys [file-name mime-type]}]
(let [p (policy file-name mime-type)]
{:action (str "https://" s3-bucket ".s3-eu-west-1.amazonaws.com/")
:key file-name
:Content-Type mime-type
:policy p
:acl "public-read"
:success_action_status "201"
:AWSAccessKeyId aws-access-key
:signature (hmac-sha1 aws-secret-key p)}))
(defroutes app-routes
(GET "/" [] app-template)
(GET "/sign" {params :params} {:status 200 :body (pr-str (sign-upload params))})
(route/resources "/")
(route/not-found "Not Found"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment