hi guys
how to fix refresh page problem, when i refresh the page i get login page again after successful login https://github.com/aibrahim/user_management
@abdullahibra a common approach is to create a user variable on the page served from the server when there’s a user in the session
you can see an example here https://github.com/yogthos/memory-hole
the layout
namespace has an *identity*
variable and injects in the template whenever render
is called:
(defn render
"renders the HTML template located relative to resources/templates"
[template & [params]]
(content-type
(ok
(parser/render-file
template
(assoc params
...
:user *identity*)))
"text/html; charset=utf-8"))
the *identity*
variable is populated by a middleware function using the :identity
key from the session:
(defn wrap-identity [handler]
(fn [request]
(binding [*identity* (get-in request [:session :identity])]
(handler request))))
the home.html
template will have a corresponding variable:
var user = {{user|json|safe}};
then in cljs you check the user
variable on load :
(def default-db
{:user (js->clj js/user :keywordize-keys true)
...})
@yogthos after i did this, successfully login, then view page source i got:
which refer user didn't changed
@yogthos my code at https://github.com/aibrahim/user_management
if you can please check and try to figure it out
@yogthos what do you think i did wrong in the code?
it looks correct, have you tried restarting the app after making the change?
yeah i restarted the server
but the same always user = null
I’d double check you’re seeing the user in the session in wrap-identity
what do you mean?
try logging what your session looks like:
(defn wrap-identity [handler]
(fn [request]
(println "session:" (:session request))
(binding [*identity* (get-in request [:session :identity])]
(handler request))))
after login
there is no :identity in the session of request
https://github.com/aibrahim/user_management/blob/master/src/clj/user_management/users.clj
(assoc :session (assoc session :identity email))
yeah that seems ok
so this add [:session :identity] to response map right?
but not to request
note that you’re also doing
(defn wrap-auth [handler]
(let [backend (session-backend)]
(-> handler
(wrap-authentication backend)
(wrap-authorization backend))))
wrap-identity should be wrapped before that
and you may not wish to use wrap-auth
at all if you’re explicitly managing the user key on the session
https://github.com/aibrahim/user_management/blob/master/src/clj/user_management/middleware.clj
so i should only use wrap-identity and remove wrap-auth ?
it's the same here https://github.com/yogthos/memory-hole/blob/master/src/clj/memory_hole/middleware.clj
you can use wrap-identity in combination with wrap-auth as memory hole is doing, or you could just use wrap-identity directly
if you just need to track that a user key is present in the session, using wrap-identity directly is probably the way to go
but i can't see what is the problem with the current code ?
i have used only wrap-identity and removed wrap-auth
but still get
it's very strange
not sure why you’re not seeing the use in the session unfortunately, from a cursory look it seems correct
I do notice you’re wrapping the session middleware twice though:
(wrap-defaults
(-> site-defaults
(assoc-in [:security :anti-forgery] false)
(assoc-in [:session :store] (cookie-store {:key "0b0f3256ec202a30"}))))
(wrap-session {:cookie-attrs {:http-only true}})
ring-defaults will call wrap-session
when the :session
key is present in the config https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj#L101
double wrapping the session middleware is likely what’s causing the problem
@yogthos should be like this?
i tried with commented both and comment only ;(wrap-session {:cookie-attrs {:http-only true}}) both not working
that does look correct
I think I see the problem here:
(POST "/user/login" request (json/write-str
(try
(let [headers (:headers request)
auth (get headers "authorization")]
(login! request auth))
(catch Exception e {"msg" "something wrong."}))))
you're returning a json string instead of a ring response there
the route should be returning a map and the json should be attached to the :body
key in that map
so you should be doing
(POST "/user/login" request
(try
(let [headers (:headers request)
auth (get headers "authorization")]
(login! request auth))
(catch Exception e
(r/internal-server-error {"msg" "something wrong."}))))
and similarly, logout should look like:
(POST "/user/logout" []
(-> {"msg" "logout successfully."}
(response/ok)
(assoc :session nil))))