luminus

abdullahibra 2018-07-31T11:11:01.000173Z

hi guys

abdullahibra 2018-07-31T11:11:54.000015Z

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

yogthos 2018-07-31T13:26:36.000419Z

@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

yogthos 2018-07-31T13:26:49.000104Z

you can see an example here https://github.com/yogthos/memory-hole

yogthos 2018-07-31T13:29:21.000053Z

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

yogthos 2018-07-31T13:31:08.000111Z

then in cljs you check the user variable on load :

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

abdullahibra 2018-07-31T13:46:26.000161Z

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

abdullahibra 2018-07-31T13:46:56.000005Z

abdullahibra 2018-07-31T13:47:06.000313Z

which refer user didn't changed

abdullahibra 2018-07-31T13:49:14.000085Z

@yogthos my code at https://github.com/aibrahim/user_management

abdullahibra 2018-07-31T13:49:34.000240Z

if you can please check and try to figure it out

abdullahibra 2018-07-31T14:14:33.000314Z

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

yogthos 2018-07-31T14:15:35.000144Z

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

abdullahibra 2018-07-31T14:16:04.000237Z

yeah i restarted the server

abdullahibra 2018-07-31T14:16:21.000574Z

but the same always user = null

yogthos 2018-07-31T14:18:02.000532Z

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

abdullahibra 2018-07-31T14:18:20.000435Z

what do you mean?

yogthos 2018-07-31T14:18:58.000183Z

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

abdullahibra 2018-07-31T14:20:43.000274Z

abdullahibra 2018-07-31T14:20:51.000218Z

after login

abdullahibra 2018-07-31T14:21:11.000120Z

there is no :identity in the session of request

abdullahibra 2018-07-31T14:23:21.000302Z

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

yogthos 2018-07-31T14:23:27.000344Z

yeah that seems ok

abdullahibra 2018-07-31T14:23:49.000315Z

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

abdullahibra 2018-07-31T14:23:55.000118Z

but not to request

yogthos 2018-07-31T14:24:35.000547Z

note that you’re also doing

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

yogthos 2018-07-31T14:24:57.000204Z

wrap-identity should be wrapped before that

yogthos 2018-07-31T14:25:47.000611Z

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

abdullahibra 2018-07-31T14:27:03.000379Z

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

abdullahibra 2018-07-31T14:27:54.000498Z

it's the same here https://github.com/yogthos/memory-hole/blob/master/src/clj/memory_hole/middleware.clj

yogthos 2018-07-31T14:29:46.000373Z

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

yogthos 2018-07-31T14:30:17.000333Z

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

abdullahibra 2018-07-31T14:33:24.000601Z

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

abdullahibra 2018-07-31T14:36:25.000063Z

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

abdullahibra 2018-07-31T14:36:28.000253Z

but still get

abdullahibra 2018-07-31T14:36:35.000202Z

abdullahibra 2018-07-31T14:36:42.000288Z

it's very strange

yogthos 2018-07-31T14:37:34.000483Z

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

yogthos 2018-07-31T14:38:40.000169Z

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

yogthos 2018-07-31T14:40:42.000609Z

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

yogthos 2018-07-31T14:41:20.000260Z

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

abdullahibra 2018-07-31T14:59:37.000188Z

abdullahibra 2018-07-31T14:59:45.000174Z

@yogthos should be like this?

abdullahibra 2018-07-31T15:04:13.000515Z

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

yogthos 2018-07-31T15:15:58.000579Z

that does look correct

yogthos 2018-07-31T15:16:07.000378Z

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

yogthos 2018-07-31T15:16:21.000607Z

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

yogthos 2018-07-31T15:17:00.000275Z

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

yogthos 2018-07-31T15:19:08.000147Z

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

yogthos 2018-07-31T15:19:51.000472Z

and similarly, logout should look like:

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