do_update_account_lifetime.sql (2959B)
1 -- 2 -- This file is part of Anastasis 3 -- Copyright (C) 2026 Anastasis SARL 4 -- 5 -- ANASTASIS is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- ANASTASIS is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- ANASTASIS; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 -- 16 17 DROP FUNCTION IF EXISTS anastasis_do_update_account_lifetime; 18 CREATE FUNCTION anastasis_do_update_account_lifetime ( 19 IN in_user_id BYTEA, 20 IN in_payment_identifier BYTEA, 21 IN in_absolute_lifetime INT8, -- lower bound for the new expiration 22 IN in_relative_lifetime INT8, -- added on top of that lower bound 23 OUT out_payment_credited BOOLEAN, -- FALSE if the payment was not new 24 OUT out_paid_until INT8) 25 LANGUAGE plpgsql 26 AS $$ 27 BEGIN 28 29 -- Credit the payment. This is the gate: a payment that is unknown or was 30 -- already credited must not extend the lifetime a second time. 31 UPDATE anastasis_recdoc_payment 32 SET paid=TRUE 33 WHERE payment_identifier=in_payment_identifier 34 AND user_id=in_user_id 35 AND paid=FALSE; 36 37 IF NOT FOUND 38 THEN 39 -- Payment unknown or credited before: report the lifetime the account has 40 -- right now and leave it alone. 41 out_payment_credited=FALSE; 42 SELECT expiration_date 43 INTO out_paid_until 44 FROM anastasis_user 45 WHERE user_id=in_user_id; 46 IF NOT FOUND 47 THEN 48 out_paid_until=0; 49 END IF; 50 RETURN; 51 END IF; 52 53 out_payment_credited=TRUE; 54 55 -- New expiration is MAX(what the account has, the caller's lower bound) 56 -- plus the caller's increment. A caller that paid for a duration passes 57 -- the current time as the lower bound and the duration as the increment; a 58 -- caller that paid up to a date passes that date and a zero increment. The 59 -- LEAST() saturates at "forever" instead of overflowing INT8. 60 INSERT INTO anastasis_user 61 (user_id 62 ,expiration_date) 63 VALUES 64 (in_user_id 65 ,LEAST(in_absolute_lifetime, 66 9223372036854775807 - in_relative_lifetime) 67 + in_relative_lifetime) 68 ON CONFLICT (user_id) DO UPDATE 69 SET expiration_date= 70 LEAST(GREATEST(anastasis_user.expiration_date, 71 in_absolute_lifetime), 72 9223372036854775807 - in_relative_lifetime) 73 + in_relative_lifetime 74 RETURNING expiration_date INTO out_paid_until; 75 76 END $$; 77 78 COMMENT ON FUNCTION anastasis_do_update_account_lifetime 79 IS 'Credits a recovery-document payment and extends the account lifetime to MAX(current,in_absolute_lifetime)+in_relative_lifetime, creating the account if needed. Does nothing but report the current lifetime if the payment is not new.';