From 9e9921e50e856fa419cd269191a549cc3580d127 Mon Sep 17 00:00:00 2001 From: Eduardo Diaz Date: Tue, 27 Aug 2013 23:41:08 -0500 Subject: [PATCH] Simple su implementation This is a very simple su implementation, adds a switch-user that expects a handler and a function that returns the new user based on the request --- src/cemerick/friend.clj | 14 ++++++++++++++ test/test_friend/functional.clj | 13 ++++++++++++- test/test_friend/mock_app.clj | 9 +++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/cemerick/friend.clj b/src/cemerick/friend.clj index b3a8b99..be65ee0 100644 --- a/src/cemerick/friend.clj +++ b/src/cemerick/friend.clj @@ -2,6 +2,7 @@ (:require [cemerick.friend.util :as util] [clojure.set :as set]) (:use (ring.util [response :as response :only (redirect)]) + (ring.middleware [session :as session :only (wrap-session)]) [slingshot.slingshot :only (throw+ try+)] [clojure.core.incubator :only (-?>)]) (:refer-clojure :exclude (identity))) @@ -122,6 +123,19 @@ any funny-business related to the dynamic binding of `*identity*`." identity-or-ring-map)] (-> identity :authentications (get (:current identity)))))) +(defn switch-user + "Simply updates current authentication. Receives a ring + handler and a function that returns a user when it receives the + request. + + This function assumes that you somehow already have several + authentications." + [handler current-auth-fn] + (fn [request] + (if-let [response ((wrap-session handler) request)] + (assoc-in response [:session ::identity :current] + (current-auth-fn request))))) + (def ^{:doc "Returns true only if the provided request/response has no identity. Equivalent to (complement current-authentication)."} anonymous? (complement current-authentication)) diff --git a/test/test_friend/functional.clj b/test/test_friend/functional.clj index 2c5d694..43fe1e3 100644 --- a/test/test_friend/functional.clj +++ b/test/test_friend/functional.clj @@ -161,6 +161,17 @@ (is (= (page-bodies "/")) (http/get (url "/logout"))) (is (= (page-bodies "/login") (:body (http/get (url "/admin"))))))) +; su +(deftest alternate-users + (binding [clj-http.core/*cookie-store* (clj-http.cookies/cookie-store)] + (http/post (url "/login") {:form-params {:username "root" :password "admin_password"}}) + (is (= "root" (:body (http/get (url "/echo-identity"))))) + (http/post (url "/login") {:form-params {:username "jane" :password "user_password"}}) + (is (= "jane" (:body (http/get (url "/echo-identity"))))) + (http/post (url "/switch-user") {:form-params {:user "root"}}) + (is (= "root" (:body (http/get (url "/echo-identity"))))) + (http/post (url "/switch-user") {:form-params {:user "jane"}}) + (is (= "jane" (:body (http/get (url "/echo-identity"))))))) + ;;;; TODO ; requires-scheme -; su diff --git a/test/test_friend/mock_app.clj b/test/test_friend/mock_app.clj index d5292f5..fba9582 100644 --- a/test/test_friend/mock_app.clj +++ b/test/test_friend/mock_app.clj @@ -57,11 +57,20 @@ (GET "/login" request (page-bodies (:uri request))) (GET "/free-api" request (api-call 99)) (friend/logout (ANY "/logout" request (resp/redirect "/"))) + (friend/switch-user + (POST "/switch-user" request (resp/response "User switched")) + #(-> % :params :user)) (GET "/echo-roles" request (friend/authenticated (-> (friend/current-authentication request) (select-keys [:roles]) json-response))) + + (GET "/echo-identity" request (-> request + :session + :cemerick.friend/identity + :current + resp/response)) ;;;;; session integrity (GET "/session-value" request