Fetching contributors…
Cannot retrieve contributors at this time
136 lines (127 sloc) 5.99 KB
(ns foreclojure.settings
(:require [noir.session :as session]
[ring.util.response :as response])
(:import [org.jasypt.util.password StrongPasswordEncryptor])
(:use [hiccup.form :only [form-to label text-field password-field check-box drop-down text-area]]
[foreclojure.utils :only [from-mongo flash-error flash-msg with-user form-row assuming send-email login-url plausible-email?
codemirror-themes default-theme get-theme]]
[foreclojure.template :only [def-page content-page]]
[foreclojure.users :only [disable-codebox? hide-solutions? gravatar-img]]
[foreclojure.messages :only [err-msg]]
[compojure.core :only [defroutes GET POST]]
[ :only [keyed]]
[clojail.core :only [thunk-timeout]]
[clojure.stacktrace :only [print-cause-trace]]
[somnium.congomongo :only [update! fetch-one]]))
(defn account-settings-box [user email]
[:p "Leave new and reset password fields blank if you do not wish to change your password."]
(map form-row
[[text-field :new-username "Username" user]
[password-field :old-pwd "Current password"]
[password-field :pwd "New password"]
[password-field :repeat-pwd "Repeat password"]
[text-field :email "Email" email]])]))
(defn js-settings-box [user-obj]
[:p "Selecting this will disable the JavaScript code entry box and just give you plain text entry."]
(check-box :disable-codebox
(disable-codebox? user-obj))
[:label {:for "disable-codebox"}
"Disable JavaScript in code entry box"]
(defn hide-settings-box [user-obj]
[:p "When you solve a problem, we allow any user who has solved a problem to view your solutions to that problem. Check this box to keep your solutions private."]
(check-box :hide-solutions
(hide-solutions? user-obj))
[:label {:for "hide-solutions"}
"Hide my solutions"]
(def code-example
"(defn balanced? [s]
\"Determine whether input string
is balanced bracket sequence\"
(loop [[first & coll] (seq s)
stack '()]
(if first
(if (= first \\[)
(recur coll (conj stack \\[))
(when (= (peek stack) \\[)
(recur coll (pop stack))))
(zero? (count stack)))))")
(defn theme-settings-box [user-obj]
[:p "Editor theme that will be used for higlighting editor and all code snippets."]
(drop-down :theme codemirror-themes "eclipse")
(text-area {:id "code-box"
:name "code"
:spellcheck "false"}
:code code-example)))
(def-page settings-page []
(with-user [{:keys [user email] :as user-obj}]
{:title "Account settings"
(form-to {:id "settings"} [:post "/settings"]
[:h2 "Change settings for " user]
[:div#account-settings (account-settings-box user email)]
[:h3 "Disable JavaScript Code Box"]
[:div#settings-codebox (js-settings-box user-obj)]
[:h3 "Hide My Solutions"]
[:div#settings-follow (hide-settings-box user-obj)]
[:h3 "Editor theme"]
[:div#editor-theme (theme-settings-box user-obj)]
[:h3 "Profile Image"]
[:div (gravatar-img {:email email :size 64})]
[:p "To change your profile image, visit <a href='' target='_blank'>Gravatar</a> and edit the image for '" email "'."]
[:button {:type "submit"} "Submit"]]))})}))
(defn do-update-settings! [new-username old-pwd new-pwd repeat-pwd email disable-codebox hide-solutions theme]
(with-user [{:keys [user pwd]}]
(let [encryptor (StrongPasswordEncryptor.)
new-pwd-hash (.encryptPassword encryptor new-pwd)
new-lower-user (.toLowerCase new-username)
theme (or ((set codemirror-themes) theme) default-theme)]
(assuming [(or (= new-lower-user user) (nil? (fetch-one :users :where {:user new-lower-user})))
(err-msg "settings.user-exists"),
(< 3 (.length new-lower-user) 14)
(err-msg "settings.uname-size"),
(= new-lower-user
(first (re-seq #"[A-Za-z0-9_]+" new-lower-user)))
(err-msg "settings.uname-alphanum")
(or (empty? new-pwd) (< 6 (.length new-pwd)))
(err-msg "settings.npwd-size"),
(= new-pwd repeat-pwd)
(err-msg "settings.npwd-match")
(or (empty? new-pwd)
(.checkPassword encryptor old-pwd pwd))
(err-msg "settings.pwd-incorrect")
(plausible-email? email)
(err-msg "")
(nil? (fetch-one :users :where {:email email :user {:$ne user}}))
(err-msg "")]
(update! :users {:user user}
{:$set {:pwd (if (seq new-pwd) new-pwd-hash pwd)
:user new-lower-user
:email email
:disable-code-box (boolean disable-codebox)
:hide-solutions (boolean hide-solutions)
:theme theme}}
:upsert false)
(session/put! :user new-lower-user)
(flash-msg "/problems"
(str "Account for " new-lower-user " updated successfully")))
(flash-error "/settings" why)))))
(defroutes settings-routes
(GET "/settings" [] (settings-page))
(POST "/settings" {{:strs [new-username old-pwd pwd repeat-pwd email disable-codebox hide-solutions theme]} :form-params}
(do-update-settings! new-username old-pwd pwd repeat-pwd email disable-codebox hide-solutions theme)))