Fork me on GitHub
#luminus
<
2018-07-31
>
abdullahibra11:07:54

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

yogthos13:07:36

@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

yogthos13:07:21

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}};

yogthos13:07:08

then in cljs you check the user variable on load :

(def default-db
  {:user (js->clj js/user :keywordize-keys true)
   ...})

abdullahibra13:07:26

@yogthos after i did this, successfully login, then view page source i got:

abdullahibra13:07:06

which refer user didn't changed

abdullahibra13:07:34

if you can please check and try to figure it out

abdullahibra14:07:33

@yogthos what do you think i did wrong in the code?

yogthos14:07:35

it looks correct, have you tried restarting the app after making the change?

abdullahibra14:07:04

yeah i restarted the server

abdullahibra14:07:21

but the same always user = null

yogthos14:07:02

I’d double check you’re seeing the user in the session in wrap-identity

abdullahibra14:07:20

what do you mean?

yogthos14:07:58

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))))

abdullahibra14:07:11

there is no :identity in the session of request

abdullahibra14:07:21

(assoc :session (assoc session :identity email))

yogthos14:07:27

yeah that seems ok

abdullahibra14:07:49

so this add [:session :identity] to response map right?

abdullahibra14:07:55

but not to request

yogthos14:07:35

note that you’re also doing

(defn wrap-auth [handler]
  (let [backend (session-backend)]
    (-> handler
        (wrap-authentication backend)
        (wrap-authorization backend))))

yogthos14:07:57

wrap-identity should be wrapped before that

yogthos14:07:47

and you may not wish to use wrap-auth at all if you’re explicitly managing the user key on the session

abdullahibra14:07:03

so i should only use wrap-identity and remove wrap-auth ?

yogthos14:07:46

you can use wrap-identity in combination with wrap-auth as memory hole is doing, or you could just use wrap-identity directly

yogthos14:07:17

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

abdullahibra14:07:24

but i can't see what is the problem with the current code ?

abdullahibra14:07:25

i have used only wrap-identity and removed wrap-auth

abdullahibra14:07:42

it's very strange

yogthos14:07:34

not sure why you’re not seeing the use in the session unfortunately, from a cursory look it seems correct

yogthos14:07:40

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}})

yogthos14:07:42

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

yogthos14:07:20

double wrapping the session middleware is likely what’s causing the problem

abdullahibra14:07:45

@yogthos should be like this?

abdullahibra15:07:13

i tried with commented both and comment only ;(wrap-session {:cookie-attrs {:http-only true}}) both not working

yogthos15:07:58

that does look correct

yogthos15:07:07

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."}))))

yogthos15:07:21

you're returning a json string instead of a ring response there

yogthos15:07:00

the route should be returning a map and the json should be attached to the :body key in that map

yogthos15:07:08

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."}))))

yogthos15:07:51

and similarly, logout should look like:

(POST "/user/logout" []
                           (-> {"msg" "logout successfully."}
                               (response/ok)
                               (assoc :session nil))))