blob: 015fad49dbee290080c36aa2137e6d70dce90ebd [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2019 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file.
4
5"""Cron and task handlers for syncing with wipeoute-lite and deleting users."""
6
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import json
12import logging
13import httplib2
14
15from google.appengine.api import app_identity
16
17from businesslogic import work_env
18from framework import cloud_tasks_helpers
19from framework import framework_constants
20from framework import jsonfeed
21from framework import urls
22from oauth2client.client import GoogleCredentials
23
24WIPEOUT_ENDPOINT = 'https://emporia-pa.googleapis.com/v1/apps/%s'
25MAX_BATCH_SIZE = 10000
26MAX_DELETE_USERS_SIZE = 1000
27
28
29def authorize():
30 credentials = GoogleCredentials.get_application_default()
31 credentials = credentials.create_scoped(framework_constants.OAUTH_SCOPE)
32 return credentials.authorize(httplib2.Http(timeout=60))
33
34
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020035class WipeoutSyncCron(jsonfeed.FlaskInternalTask):
Copybara854996b2021-09-07 19:36:02 +000036 """Enqueue tasks for sending user lists to wipeout-lite and deleting deleted
37 users fetched from wipeout-lite."""
38
39 def HandleRequest(self, mr):
40 batch_param = mr.GetIntParam('batchsize', default_value=MAX_BATCH_SIZE)
41 # Use batch_param as batch_size unless it is None or 0.
42 batch_size = min(batch_param, MAX_BATCH_SIZE)
43 total_users = self.services.user.TotalUsersCount(mr.cnxn)
44 total_batches = int(total_users / batch_size)
45 # Add an extra batch to process remainder user emails.
46 if total_users % batch_size:
47 total_batches += 1
48 if not total_batches:
49 logging.info('No users to report.')
50 return
51
52 for i in range(total_batches):
53 params = dict(limit=batch_size, offset=i * batch_size)
54 task = cloud_tasks_helpers.generate_simple_task(
55 urls.SEND_WIPEOUT_USER_LISTS_TASK + '.do', params)
56 cloud_tasks_helpers.create_task(
57 task, queue=framework_constants.QUEUE_SEND_WIPEOUT_USER_LISTS)
58
59 task = cloud_tasks_helpers.generate_simple_task(
60 urls.DELETE_WIPEOUT_USERS_TASK + '.do', {})
61 cloud_tasks_helpers.create_task(
62 task, queue=framework_constants.QUEUE_FETCH_WIPEOUT_DELETED_USERS)
63
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020064 def GetWipeoutSyncCron(self, **kwargs):
65 return self.handler(**kwargs)
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020066
67
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020068class SendWipeoutUserListsTask(jsonfeed.FlaskInternalTask):
Copybara854996b2021-09-07 19:36:02 +000069 """Sends a batch of monorail users to wipeout-lite."""
70
71 def HandleRequest(self, mr):
72 limit = mr.GetIntParam('limit')
73 assert limit != None, 'Missing param limit'
74 offset = mr.GetIntParam('offset')
75 assert offset != None, 'Missing param offset'
76 emails = self.services.user.GetAllUserEmailsBatch(
77 mr.cnxn, limit=limit, offset=offset)
78 accounts = [{'id': email} for email in emails]
79 service = authorize()
80 self.sendUserLists(service, accounts)
81
82 def sendUserLists(self, service, accounts):
83 app_id = app_identity.get_application_id()
84 endpoint = WIPEOUT_ENDPOINT % app_id
85 resp, data = service.request(
86 '%s/verifiedaccounts' % endpoint,
87 method='POST',
88 headers={'Content-Type': 'application/json; charset=UTF-8'},
89 body=json.dumps(accounts))
90 logging.info(
91 'Received response, %s with contents, %s', resp, data)
92
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020093 def PostSendWipeoutUserListsTask(self, **kwargs):
94 return self.handler(**kwargs)
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020095
96
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020097class DeleteWipeoutUsersTask(jsonfeed.FlaskInternalTask):
Copybara854996b2021-09-07 19:36:02 +000098 """Fetches deleted users from wipeout-lite and enqueues tasks to delete
99 those users from Monorail's DB."""
100
101 def HandleRequest(self, mr):
102 limit = mr.GetIntParam('limit', MAX_DELETE_USERS_SIZE)
103 limit = min(limit, MAX_DELETE_USERS_SIZE)
104 service = authorize()
105 deleted_user_data = self.fetchDeletedUsers(service)
106 deleted_emails = [user_object['id'] for user_object in deleted_user_data]
107 total_batches = int(len(deleted_emails) / limit)
108 if len(deleted_emails) % limit:
109 total_batches += 1
110
111 for i in range(total_batches):
112 start = i * limit
113 end = start + limit
114 params = dict(emails=','.join(deleted_emails[start:end]))
115 task = cloud_tasks_helpers.generate_simple_task(
116 urls.DELETE_USERS_TASK + '.do', params)
117 cloud_tasks_helpers.create_task(
118 task, queue=framework_constants.QUEUE_DELETE_USERS)
119
120 def fetchDeletedUsers(self, service):
121 app_id = app_identity.get_application_id()
122 endpoint = WIPEOUT_ENDPOINT % app_id
123 resp, data = service.request(
124 '%s/deletedaccounts' % endpoint,
125 method='GET',
126 headers={'Content-Type': 'application/json; charset=UTF-8'})
127 logging.info(
128 'Received response, %s with contents, %s', resp, data)
129 return json.loads(data)
130
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +0200131 def PostDeleteWipeoutUsersTask(self, **kwargs):
132 return self.handler(**kwargs)
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +0200133
134
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +0200135class DeleteUsersTask(jsonfeed.FlaskInternalTask):
Copybara854996b2021-09-07 19:36:02 +0000136 """Deletes users from Monorail's DB."""
137
138 def HandleRequest(self, mr):
139 """Delete users with the emails given in the 'emails' param."""
140 emails = mr.GetListParam('emails', default_value=[])
141 assert len(emails) <= MAX_DELETE_USERS_SIZE, (
142 'We cannot delete more than %d users at once, current users: %d' %
143 (MAX_DELETE_USERS_SIZE, len(emails)))
144 if len(emails) == 0:
145 logging.info("No user emails found in deletion request")
146 return
147 with work_env.WorkEnv(mr, self.services) as we:
148 we.ExpungeUsers(emails, check_perms=False)
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +0200149
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +0200150 def PostDeleteUsersTask(self, **kwargs):
151 return self.handler(**kwargs)