Pregunta

I have created a function that should in theory return true on successful password change and false on opposite.

The function is defined as:

CREATE OR REPLACE FUNCTION database."changePassword"(username character varying, newpassword character varying, oldpassword character varying) RETURNS boolean AS
$BODY$
UPDATE database.users SET hash = MD5($2) WHERE (username = $1 AND hash = MD5($3));
SELECT EXISTS(SELECT 1 FROM datsabase.users WHERE username = $1 AND hash = MD5($2))
$BODY$
LANGUAGE sql VOLATILE NOT LEAKPROOF
COST 100;

The problem is that when I call the function like SELECT database."changePassword"('usrNm', 'newPassword', 'oldOne');, at first I get the true as expected, and the value in the database is changed.

When I call the function again (and again and again) with the same parameters, it also returns true, but that should not be the case since the password is changed now and the old password sent via the function call is incorrect.

Am I doing something wrong?

PostgreSQL version is 9.3.1.
I have called the function from the pgAdmin interface and from a PHP script, same problem.

¿Fue útil?

Solución

If you want to return whether any password has been changed, you can just return the special variable FOUND in a plpgsql function like this (simplified with input from @Pavel):

CREATE OR REPLACE FUNCTION database."changePassword"(
    username character varying
   ,newpassword character varying
   ,oldpassword character varying
) RETURNS boolean AS
$func$
BEGIN

UPDATE database.users
SET    hash = MD5($2)
WHERE  username = $1
AND    hash = MD5($3);

RETURN FOUND;

END 
$func$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;

Or simpler, use the RETURNING clause. That would work in a plain sql function as well:

CREATE OR REPLACE FUNCTION database."changePassword"(
    username character varying
   ,newpassword character varying
   ,oldpassword character varying
) RETURNS boolean AS
$func$

UPDATE database.users
SET    hash = MD5($2)
WHERE  username = $1
AND    hash = MD5($3)
RETURNING TRUE;

$func$
LANGUAGE sql VOLATILE NOT LEAKPROOF;

If no row is updated, nothing is returned. Else, you get TRUE.

Otros consejos

The return value of the function is the result of the SELECT statement. The result is true when the stored hash of the user matches with the hash of the second parameter (newpassword). When the password is changed to the new password, this check always succeeds and the function returns true for the same parameter, despite the fact that the update statement does not update any row after the second call. You should change your logic and instead of querying for a matching user and password, check weather any row is updated or not.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top