diff --git a/priv/dispatch.conf b/priv/dispatch.conf index db86337..33314e3 100644 --- a/priv/dispatch.conf +++ b/priv/dispatch.conf @@ -2,5 +2,6 @@ {["static", '*'], 'elmdap-static', []}. {["users", uid], 'elmdap-user', []}. +{["users", uid, "password"], 'elmdap-password', []}. {["users"], 'elmdap-users', []}. {["groups"], 'elmdap-groups', []}. diff --git a/src/elmdap-entry.lfe b/src/elmdap-entry.lfe index 1213499..f54d11f 100644 --- a/src/elmdap-entry.lfe +++ b/src/elmdap-entry.lfe @@ -9,6 +9,9 @@ ((`#(eldap_entry ,_ ,attributes)) attributes)) +(defun attribute (entry name) + (proplists:get_value name (attributes entry))) + (defun to_json (entry) `#(struct [#(dn ,(dn entry)) #(attributes diff --git a/src/elmdap-password.lfe b/src/elmdap-password.lfe new file mode 100644 index 0000000..3b39623 --- /dev/null +++ b/src/elmdap-password.lfe @@ -0,0 +1,80 @@ +(defmodule elmdap-password + (export (init 1) + (service_available 2) + (is_authorized 2) + (resource_exists 2) + (allowed_methods 2) + (content_types_provided 2) + (to_json 2) + (process_post 2))) + +(include-lib "webmachine/include/webmachine.hrl") +(include-lib "calrissian/include/monads.lfe") + +(defrecord state + connection + entry) + +(defun init (args) + `#(ok ,(make-state))) + +(defun service_available (req-data state) + (case (elmdap:open) + ((tuple 'ok connection) + `#(true ,req-data ,(set-state state connection connection))) + (_ + `#(false ,req-data ,state)))) + +(defun is_authorized (req-data state) + (elmdap:is_authorized (state-connection state) + req-data state)) + +(defun resource_exists (req-data state) + (let ((`[#(uid ,uid)] (wrq:path_info req-data))) + (case (get-entry (state-connection state) uid) + (`#(ok ,entry) + (if (!= 'undefined (elmdap-entry:attribute entry "userPassword")) + `#(true ,req-data ,(set-state state entry entry)) + `#(false ,req-data ,state))) + (_ `#(false ,req-data ,state))))) + +(defun allowed_methods (req-data state) + `#([GET HEAD POST] ,req-data ,state)) + +(defun content_types_provided (req-data state) + `#([#("application/json" to_json)] ,req-data ,state)) + +(defun to_json (req-data state) + (tuple (mochijson:encode + (password (state-entry state))) + req-data + state)) + +(defun process_post (req-data state) + (let* ((newpassword (mochijson:decode (wrq:req_body req-data))) + (dn (elmdap-entry:dn (state-entry state))) + (result (eldap:modify_password + (state-connection state) + dn + newpassword))) + (error_logger:info_report `#(newpass ,dn ,result)) + (case result + ('ok `#(true ,req-data ,state)) + (_ `#(false ,req-data ,state))))) + +(defun get-entry (connection uid) + (let* ((base "ou=people,dc=coredial,dc=com") + (filter (eldap:equalityMatch "uid" uid)) + (`#(ok #(eldap_search_result ,results ,_)) + (eldap:search connection + `[#(base ,base) + #(filter ,filter) + #(attributes ["userPassword"])])) + ((cons entry _) results)) + (case results + (`[,entry] `#(ok ,entry)) + (_ #(error not_found))))) + +(defun password (entry) + (let (((cons password _) (elmdap-entry:attribute entry "userPassword"))) + password))