(:~
: 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})
}
};