(:~ : User's Password RESTXQ functions. : : @author Rave Technologies, https://www.rave-tech.com/, 2017 :) module namespace blpass = 'http://www.rave-tech.com/bloomsbury/password'; import module namespace config = 'http://www.rave-tech.com/bloomsbury/config' at './module/config.xqm'; import module namespace audit = 'http://www.rave-tech.com/bloomsbury/audit' at './module/manage-audit.xqm'; import module namespace Request = 'http://exquery.org/ns/request'; (:~ : Create a token to set user password. : @param $body as document node user1500547727558 : @return element(result) :) declare %updating %rest:path("/reset-password") %rest:POST("{$body}") %rest:consumes("application/xml", "text/xml") function blpass:set( $body as document-node() ) { let $email := $body/email/text() let $userXml := db:open($config:CoreDatabase,$config:UserDir)/user[email=$email] [fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))] let $userID := $userXml/id/text() let $userName := $userXml/name/text() return if($userXml) then (:if($userXml/user[password[xs:dateTime(@expire-on/data()) > fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))]]) then ( config:non-update-message("[Set Password][Password token already exist for the user : " || $userID || "]"), update:output(FailurePassword token already exist for this user) ) else:) if($userXml[active='No']) then ( config:update-message("[Set Password][This user is not active : " || $userID || "]"), update:output(FailureThis user is not active. Please contact administrator) ) else if($userXml[locked='Yes']) then ( config:update-message("[Set Password][This user is locked : " || $userID || "]"), update:output(FailureThis user is locked. Please contact administrator) ) else try { let $passwordToken := fn:concat($config:PasswordTokenPrefix,fn:string(convert:dateTime-to-integer(fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))))) let $tokenExpireTime := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms())) + xs:dayTimeDuration('P2D') return if($userXml/password) then ( replace node $userXml/password with , config:update-message("[Set Password][Password token as been set for the user : " || $userID || "]"), update:output(Success{$userName}{$passwordToken}) ) else ( insert node as last into $userXml, config:update-message("[Set Password][Password token as been set for the user : " || $userID || "]"), update:output(Success{$userName}{$passwordToken}) ) } catch * { admin:write-log("[Set Password][Error: " || $err:description || "]"), admin:write-log("[Set Password][Error: " || $err:additional || "]"), update:output(Error{$err:description}) } else ( config:update-message("[Set Password][User is unavailable]"), update:output(FailureUser is unavailable) ) }; (:~ : Check Password token validity. : @param $token Password token to check validity : @return element(result) :) declare %rest:path("/reset-password/{$token=.+}") %rest:GET function blpass:check( $token as xs:string ) { try { if(db:open($config:CoreDatabase,$config:UserDir)/user/password[@tokenid=$token] [xs:dateTime(@expire-on/data()) > fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))] [fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))] ) then ( SuccessThe link is valid, config:non-update-message("[Check Password][Password token is valid : " || $token || "]") ) else if(db:open($config:CoreDatabase,$config:UserDir)/user/password[@tokenid=$token] [xs:dateTime(@expire-on/data()) le fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))] [fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))] ) then ( FailureThe password token has expired, config:non-update-message("[Check Password][The password token has expired : " || $token || "]") ) else FailureInvalid password token } catch * { admin:write-log("[Check Password][Error: " || $err:description || "]"), admin:write-log("[Check Password][Error: " || $err:additional || "]"), Error{$err:description} } }; (:~ : Delete Password token. : @param $token Password token to check validity : @return element(result) :) declare %updating %rest:path("/reset-password/{$token=.+}") %rest:DELETE %rest:consumes("application/xml", "text/xml") function blpass:delete( $token as xs:string ) { try { if(db:open($config:CoreDatabase,$config:UserDir)/user/password[@tokenid=$token] [fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))]) then ( delete node db:open($config:CoreDatabase,$config:UserDir)/user/password[@tokenid=$token][not(matches(base-uri(.),'(/version/|/audit/)'))], config:update-message("[Delete Password][Password token deleted : " || $token || "]"), update:output(SuccessPassword token deleted) ) else ( config:update-message("[Delete Password][Invalid password token : " || $token || "]"), update:output(FailureInvalid password token for the user) ) } catch * { admin:write-log("[Delete Password][Error: " || $err:description || "]"), admin:write-log("[Delete Password][Error: " || $err:additional || "]"), update:output(Error{$err:description}) } }; (:~ : Reset user password. : @param $body as document node #@%@#@# : @return element(result) :) declare %updating %rest:path("/reset-password/{$token=.+}") %rest:PUT("{$body}") %rest:consumes("application/xml", "text/xml") function blpass:reset( $body as document-node(), $token as xs:string ) { try { let $userXml := db:open($config:CoreDatabase,$config:UserDir)/user[password/@tokenid=$token] [fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))] let $email := $userXml/email/text() let $userID := $userXml/id/text() let $username := $userXml/name/text() return if($userXml/password[xs:dateTime(@expire-on/data()) > fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))]) then ( user:password($email, $body/password/text()), delete node $userXml/password, replace node $userXml/password-updated with {fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}, replace node $userXml/updated with {fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}, audit:user($userID, 'Reset Password'), config:update-message("[Set Password][Password has been set for user : " || $email || "]"), update:output(Success{$username}Password has been reset) ) else ( update:output(FailureThe password token has expired), config:update-message("[Check Password][The password token has expired : " || $token || "]") ) } catch * { admin:write-log("[Set Password][Error: " || $err:description || "]"), admin:write-log("[Set Password][Error: " || $err:additional || "]"), update:output(Error{$err:description}) } };