5
votes

I have written a simple contrived auth function in Clojure and it doesn't feel very idiomatic to me at all. Is there a better way of writing this:

(defn auth [username password] 
  (let [user-record (credential-fn username)]
    (if (and user-record (verify-pw password))
      (let [user-record (dissoc user-record :password)]
        {:status 200 :body user-record})
      {:status 401})))

I thought it might be possible to get rid of the if by using if-let, but the if is doing a boolean check and I need to bind the user-record? Stuck!

NOTE: the dissoc is removing the password from user-record so it's not returned in the body.

1

1 Answers

9
votes

I think the biggest problem with your function is that it tries to handle three things at once:

  1. Checking if username and password are valid for a user (credential-fn and verify-pw)
  2. Cleaning up the record data (dissoc user-record password)
  3. Building a Ring response map ({:status 401} vs. {:status 200 :body user-record})

I would consider splitting your code into two separate functions:

(defn authenticate
  [username password]
  (and (verify-pw password) 
       (dissoc (credential-fn username) :password)))

(defn login
  [username password]
  (if-let [user-record (authenticate username password)]
    {:status 200 :body user-record}
    {:status 401}))