@@ -179,6 +179,87 @@ class OrganizationRepository {
179179 { organizationId, limit, offset } ,
180180 )
181181 }
182+
183+ public async pruneOrganization ( organizationId : string ) : Promise < void > {
184+ const tablesToDelete = [
185+ { name : 'organizationNoMerge' , conditions : [ 'organizationId' , 'noMergeId' ] } ,
186+ { name : 'organizationToMerge' , conditions : [ 'organizationId' , 'toMergeId' ] } ,
187+ { name : 'organizationToMergeRaw' , conditions : [ 'organizationId' , 'toMergeId' ] } ,
188+ { name : 'organizationEnrichmentCache' , conditions : [ 'organizationId' ] } ,
189+ { name : 'organizationEnrichments' , conditions : [ 'organizationId' ] } ,
190+ { name : 'memberSegmentAffiliations' , conditions : [ 'organizationId' ] } ,
191+ { name : 'organizationSegmentsAgg' , conditions : [ 'organizationId' ] } ,
192+ { name : 'organizationSegments' , conditions : [ 'organizationId' ] } ,
193+ { name : 'orgAttributes' , conditions : [ 'organizationId' ] } ,
194+ { name : 'organizationIdentities' , conditions : [ 'organizationId' ] } ,
195+ { name : 'memberOrganizations' , conditions : [ 'organizationId' ] } ,
196+ { name : 'organizations' , conditions : [ 'id' ] } ,
197+ ]
198+
199+ await this . connection . tx ( async ( tx ) => {
200+ for ( const table of tablesToDelete ) {
201+ const whereClause = table . conditions
202+ . map ( ( field ) => `"${ field } " = $(organizationId)` )
203+ . join ( ' OR ' )
204+ await tx . none ( `DELETE FROM "${ table . name } " WHERE ${ whereClause } ` , { organizationId } )
205+ }
206+ } )
207+ }
208+
209+ public async getOrganizationsToPrune (
210+ batchSize : number ,
211+ ) : Promise < { id : string ; displayName : string } [ ] > {
212+ return this . connection . query (
213+ `
214+ WITH email_providers AS (
215+ SELECT unnest(ARRAY[
216+ 'gmail.com', 'gmail.co.uk', 'gmail.com.au', 'gmail.com.tr',
217+ 'yahoo.com', 'yahoo.co.uk', 'yahoo.com.br', 'yahoo.co.in', 'yahoo.fr', 'yahoo.es', 'yahoo.it', 'yahoo.de', 'yahoo.ca', 'yahoo.com.au', 'yahoo.in', 'yahoo.co.jp', 'yahoo.com.ar', 'yahoo.com.mx', 'yahoo.co.id', 'yahoo.com.sg', 'yahoo.co.za', 'yahoo.com.ph', 'yahoo.com.tw', 'yahoo.com.hk', 'yahoo.com.vn',
218+ 'hotmail.com', 'hotmail.co.uk', 'hotmail.fr', 'hotmail.ca', 'hotmail.it', 'hotmail.es', 'hotmail.de', 'hotmail.com.au', 'hotmail.com.mx',
219+ 'icloud.com', 'icloud.com.cn',
220+ 'fastmail.com', 'tutanota.com', 'tuta.io',
221+ 'gmx.com', 'gmx.de', 'gmx.net', 'gmx.at', 'gmx.ch', 'gmx.fr', 'gmx.co.uk',
222+ 'aol.com', 'aol.co.uk', 'aol.fr', 'aol.de',
223+ 'msn.com', 'wanadoo.fr', 'orange.fr', 'comcast.net',
224+ 'live.com', 'live.co.uk', 'live.fr', 'live.nl', 'live.it', 'live.com.au', 'live.ca', 'live.cn',
225+ 'rediffmail.com', 'sify.com', 'indiatimes.com', 'free.fr', 'web.de',
226+ 'yandex.ru', 'yandex.com', 'yandex.com.tr', 'ya.ru',
227+ 'ymail.com', 'libero.it',
228+ 'outlook.com', 'outlook.fr', 'outlook.co.uk', 'outlook.de', 'outlook.es', 'outlook.it', 'outlook.com.au', 'outlook.com.br', 'outlook.com.mx', 'outlook.co.jp', 'outlook.in', 'outlook.com.sg', 'outlook.co.za', 'outlook.co.in',
229+ 'uol.com.br', 'bol.com.br',
230+ 'mail.ru', 'inbox.ru', 'list.ru', 'bk.ru',
231+ 'mail.com', 'mail.de', 'mail.co.uk',
232+ 'cox.net', 'sbcglobal.net', 'sfr.fr', 'verizon.net', 'googlemail.com', 'ig.com.br', 'bigpond.com', 'bigpond.net.au', 'terra.com.br', 'neuf.fr', 'alice.it', 'rocketmail.com', 'att.net', 'laposte.net', 'bellsouth.net', 'charter.net', 'rambler.ru', 'tiscali.it', 'tiscali.co.uk', 'shaw.ca', 'sky.com', 'earthlink.net', 'optonline.net', 'freenet.de', 't-online.de', 'aliceadsl.fr', 'virgilio.it', 'home.nl', 'qq.com', 'vip.qq.com', 'telenet.be', 'pandora.be', 'me.com', 'voila.fr', 'planet.nl', 'tin.it', 'ntlworld.com', 'arcor.de', 'frontiernet.net', 'hetnet.nl', 'zonnet.nl', 'club-internet.fr', 'juno.com', 'optusnet.com.au', 'blueyonder.co.uk', 'bluewin.ch', 'skynet.be', 'sympatico.ca', 'windstream.net', 'mac.com', 'centurytel.net', 'chello.nl', 'aim.com',
233+ 'protonmail.com', 'protonmail.ch', 'proton.me', 'pm.me', 'duck.com',
234+ 'zoho.com', 'zohomail.com',
235+ 'users.noreply.github.com',
236+ '126.com', '139.com', '163.com', '188.com', 'foxmail.com', 'tom.com', '21cn.com', 'yeah.net',
237+ 'naver.com', 'daum.net', 'hanmail.net',
238+ 'hey.com', 'inbox.com', 'lycos.com', 'excite.com', 'hushmail.com', 'mailfence.com', 'mailbox.org', 'posteo.de', 'startmail.com', 'runbox.com', 'countermail.com', 'mynet.com',
239+ 'wp.pl', 'onet.pl', 'interia.pl', 'o2.pl',
240+ 'seznam.cz', 'centrum.cz',
241+ 'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'tempmail.com'
242+ ]) AS provider
243+ )
244+ SELECT DISTINCT o.id, o."displayName"
245+ FROM organizations o
246+ INNER JOIN "organizationIdentities" oi
247+ ON o.id = oi."organizationId"
248+ INNER JOIN email_providers ep
249+ ON LOWER(oi.value) = ep.provider
250+ WHERE o."deletedAt" IS NULL
251+ AND oi.type = 'primary-domain'
252+ AND NOT EXISTS (
253+ SELECT 1
254+ FROM "memberOrganizations" mo
255+ WHERE mo."organizationId" = o.id
256+ AND (mo.title IS NOT NULL AND mo.title != '')
257+ AND (mo.source IS NOT NULL AND mo.source NOT IN ('email-domain'))
258+ )
259+ ` ,
260+ { batchSize } ,
261+ )
262+ }
182263}
183264
184265export default OrganizationRepository
0 commit comments