เรากำลังเลิกใช้งาน API ภายในองค์กร และหากต้องการรายละเอียดเพิ่มเติมและเรียนรู้วิธีย้ายไปใช้ API ระบบคลาวด์รุ่นใหม่ของเรา โปรดดูเอกสารการเลิกใช้งาน API ภายในองค์กรของเรา
Learn how to delete a user's data from your database when you're running the On-Premises API.
Running these commands may result in database problems that can cause the loss of data or the coreapp not function properly. Only use this guide if you really need to delete the data.
For MySQL, we rely on stored procedure for handling the deletion of user data. Therefore, we will create a stored procedure that we store in one of the data stores, preferable contactStore. To do this, follow these steps:
docker ps -a // to get the full list of containers running docker exec -it <database-container> mysql -h <hostname> -u <username for db> -p <port number> //for mysql
contactStore
is selected by doing:
use contactStore;
DELIMITER // CREATE PROCEDURE `deleteUserDataByPhoneNumber`(IN wa_id BIGINT) BEGIN DECLARE user_jid VARCHAR(50); DECLARE phone_number_ VARCHAR(50); SET phone_number_ = concat('+', wa_id); SET user_jid = concat(wa_id, '@s.whatsapp.net'); DELETE FROM callbackStore.queue WHERE key_remote_jid = user_jid; DELETE FROM messageStore.chats WHERE key_remote_jid = user_jid OR group_creator = user_jid; DELETE FROM messageStore.group_participants_history WHERE jid = user_jid; DELETE FROM messageStore.messages WHERE key_remote_jid = user_jid OR remote_resource = user_jid; DELETE FROM messageStore.messages_pending_actions WHERE key_remote_jid = user_jid OR remote_resource = user_jid; DELETE FROM messageStore.messages_receipt_log WHERE key_remote_jid = user_jid; DELETE FROM messageStore.sender_key_distribution_status WHERE jid = user_jid; DELETE FROM axolotlStore.identities WHERE recipient_id = wa_id; DELETE FROM axolotlStore.message_base_key WHERE msg_key_remote_jid = user_jid; DELETE FROM axolotlStore.sender_keys WHERE sender_id = wa_id; DELETE FROM axolotlStore.sessions WHERE recipient_id = wa_id; DELETE FROM contactStore.wa_contacts WHERE jid = user_jid; DELETE FROM contactStore.wa_phones WHERE jid = user_jid; END//
SHOW PROCEDURE STATUS WHERE Db = 'contactStore';
Now you have your procedure set up. In case you need to delete a user's data, you can just run the following command:
call contactStore.deleteUserDataByPhoneNumber('wa_id');
A successful response looks like this:
mysql> call contactStore.deleteUserDataByPhoneNumber(XXXXXXXXXXXX); Query OK, 0 rows affected (0.01 sec)
Since the version of Postgres we are using (10.x
) does not support stored procedures, we rely on functions yo implement this logic:
docker ps -a // this will list all the current running containers docker exec -it <database-container> psql -h <hostname> -U <username for db> -p <port-numer> //for postgres
contactStore
database by doing:
connect contactStore;Postgres doesn't allow us to easily run queries that operate on different databases. So, we have to rely on foreign data wrappers to accomplish this. More information on this can be found in the following:
postgres_fdw
: Details on how to create the the foreign data wrappers needed to access data stored in other databases.
postgres_fdw
doc. The steps are:
postgres_fdw
extensionCREATE EXTENSION IF NOT EXISTS postgres_fdw; -- Create connection to the callback Store CREATE SERVER callbackStore FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'db-hostname', port 'db-port number', dbname 'callbackStore'); CREATE USER MAPPING FOR root SERVER callbackStore OPTIONS (user 'root', password 'testpass'); CREATE FOREIGN TABLE queue ( key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL ) SERVER callbackStore OPTIONS (schema_name 'public', table_name 'queue'); -- Create connection to the messages store CREATE SERVER messageStore FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'db-hostname', port 'db-port number', dbname 'messageStore'); CREATE USER MAPPING FOR root SERVER messageStore OPTIONS (user 'root', password 'testpass'); -- message store tables CREATE FOREIGN TABLE chats ( key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL, group_creator text COLLATE pg_catalog."default" ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'chats'); CREATE FOREIGN TABLE group_participants_history ( jid character varying(256) COLLATE pg_catalog."default" NOT NULL ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'group_participants_history'); CREATE FOREIGN TABLE messages ( key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL, remote_resource text COLLATE pg_catalog."default" ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'messages'); CREATE FOREIGN TABLE messages_receipt_log ( key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'messages_receipt_log'); CREATE FOREIGN TABLE messages_pending_actions ( key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL, remote_resource text COLLATE pg_catalog."default" ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'messages_pending_actions'); CREATE FOREIGN TABLE sender_key_distribution_status ( jid character varying(256) COLLATE pg_catalog."default" NOT NULL ) SERVER messageStore OPTIONS (schema_name 'public', table_name 'sender_key_distribution_status'); -- Create connection to the axolotlStore CREATE SERVER axolotlStore FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'db-hostname', port 'db-port number', dbname 'axolotlStore'); CREATE USER MAPPING FOR root SERVER axolotlStore OPTIONS (user 'root', password 'testpass'); CREATE FOREIGN TABLE identities ( recipient_id bigint ) SERVER axolotlStore OPTIONS (schema_name 'public', table_name 'identities'); CREATE FOREIGN TABLE message_base_key ( msg_key_remote_jid character varying(256) COLLATE pg_catalog."default" NOT NULL ) SERVER axolotlStore OPTIONS (schema_name 'public', table_name 'message_base_key'); CREATE FOREIGN TABLE sessions ( recipient_id bigint ) SERVER axolotlStore OPTIONS (schema_name 'public', table_name 'sessions');
CREATE OR REPLACE FUNCTION public."deleteUserDataByPhoneNumber"( wa_id bigint) RETURNS void LANGUAGE 'plpgsql' COST 100 VOLATILE PARALLEL UNSAFE AS $BODY$ DECLARE user_jid VARCHAR(56); phone_number_ VARCHAR(56); BEGIN SELECT INTO phone_number_ concat('+', wa_id); SELECT jid into user_jid FROM wa_phones where phone_number=phone_number_; IF NOT FOUND THEN SELECT INTO user_jid concat(wa_id, '@s.whatsapp.net'); END IF; DELETE FROM queue WHERE key_remote_jid = user_jid; DELETE FROM chats WHERE key_remote_jid = user_jid OR group_creator = user_jid; DELETE FROM group_participants_history WHERE jid = user_jid; DELETE FROM messages WHERE key_remote_jid = user_jid OR remote_resource = user_jid; DELETE FROM messages_pending_actions WHERE key_remote_jid = user_jid OR remote_resource = user_jid; DELETE FROM messages_receipt_log WHERE key_remote_jid = user_jid; DELETE FROM sender_key_distribution_status WHERE jid = user_jid; DELETE FROM identities WHERE recipient_id = wa_id; DELETE FROM message_base_key WHERE msg_key_remote_jid = user_jid; DELETE FROM sessions WHERE recipient_id = wa_id; DELETE FROM wa_contacts WHERE jid = user_jid; DELETE FROM wa_phones WHERE jid = user_jid; END $BODY$;
ALTER FUNCTION public."deleteUserDataByPhoneNumber"(bigint) OWNER TO root; -- fill free to replace this with the correct user
Now you can run the function if you need to delete a user's data:
SELECT public."deleteUserDataByPhoneNumber"(wa-id); //wa-id is the phone number with the conditions stated above
If you also want to delete the foreign data handlers at the end you can run:
DROP USER MAPPING IF EXISTS FOR root SERVER local_server; DROP SERVER IF EXISTS local_server CASCADE; DROP EXTENSION IF EXISTS postgres_fdw CASCADE;