-
Notifications
You must be signed in to change notification settings - Fork 0
/
box_export.py
155 lines (118 loc) · 6.21 KB
/
box_export.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from boxsdk import JWTAuth, Client # Box API
import requests # test environments require VPN to access
from datetime import date # For comparing the "cutoff" date to affiliation_removed_date
from time import sleep # For regenerating the access token
from threading import Thread # For regenerating the access token
import csv # For writing a CSV file containing separated / terminated users
import secret_credentials # For generating the iamtesttoken
url_base = 'https://eis.identity.ucsb.edu/.'
iam_headers = { "Authorization" : 'Bearer {}'.format(secret_credentials.generate_iamtesttoken()) }
box_config = JWTAuth.from_settings_file('PROD_config.json')
client = Client(box_config)
service_account = client.user().get()
print(f'Service Account user ID is {service_account.id}')
def replace_iam_access_token():
# generate a new access token
global iam_headers
# run forever
while True:
iamtesttoken = secret_credentials.generate_iamtesttoken()
iam_headers = { "Authorization" : 'Bearer {}'.format(iamtesttoken) }
print("new access token created (inside replace_iam_access_token)", iamtesttoken)
# Block for 29 min (60 seconds * 29 min)
sleep(60 * 29)
def get_affiliations_removed_users(dateFilter, cutoff_date):
# dateFilter: 0000-00-00 | year, month, date
cutoff_year = int(cutoff_date[:4])
cutoff_month = int(cutoff_date[5:7])
cutoff_day = int(cutoff_date[8:])
datetime_cutoff_date = date(cutoff_year, cutoff_month, cutoff_day)
# Concatenate base URL and request URL
request_url = "{}/affiliate/readonly/affiliations/removed?dateFilter={}".format(url_base, dateFilter)
response = requests.get(request_url, headers=iam_headers)
# Speed up affiliations request with json + dictionary instead of parsing through strings
content_list = response.json()
data_dict = {}
for dic in content_list:
net_id = dic['netId']
affiliations_removed_date = dic['lastAffiliationRemovedDate']
aff_rem_year = int(affiliations_removed_date[:4])
aff_rem_month = int(affiliations_removed_date[5:7])
aff_rem_day = int(affiliations_removed_date[8:])
datetime_affiliations_removed_date = date(aff_rem_year, aff_rem_month, aff_rem_day)
# Comparing the dates, proceed if affiliation removed date is EARLIER OR EQUAL to the cutoff date
if datetime_affiliations_removed_date <= datetime_cutoff_date:
print("Proceeded with affiliation removed date:", datetime_affiliations_removed_date)
request_url = url_base + "/people/readonly/" + net_id + "/status"
req = requests.get(request_url, headers=iam_headers)
tempList=req.text.split(":")
try:
# Sometimes you get a Forbidden HTML string as tempList, skip the user if we get "forbidden"
tempItem=tempList[2]
statusStr=tempItem.rstrip(tempItem[-1])
if statusStr == '"activated"' or statusStr == '"renew"' or statusStr == '"created"' or statusStr == "null":
data_dict[net_id] = {
'terminated': False
}
elif statusStr == '"separated"' or statusStr == '"terminated"':
data_dict[net_id] = {
'terminated': True
}
print("terminated account", net_id)
except:
print("AN ERROR AS OCCURED:", net_id, "\n", req, "\n", tempList)
else:
print("Did not proceed with affiliation removed date:", datetime_affiliations_removed_date)
return data_dict
if __name__ == '__main__':
print('Starting background access token generation...')
daemon = Thread(target = replace_iam_access_token, daemon=True, name="Access Token Generator:")
daemon.start()
print('Main thread has begun.')
# Export all box users
with open("/var/tmp/box_export.csv", mode='w') as write_file:
csv_writer = csv.writer(write_file, delimiter=",")
csv_writer.writerow(["Full Name", "Email", "UCSB Net Id", "Box Id", "Data Used", "Department", "Status"])
# To analyze a subsection of users, use the get_affiliations_removed_users function all instead of
# looping through all useres in Box
'''
example:
data_dict = get_affiliations_removed(start_date, end_date)
if netId in data_dict:
if data_dict[netId]["terminated"]:
handle unaffiliated users
'''
users = client.users(user_type='all')
for user in users:
email=f'{user.login}'
netIdTemp=email.split("@")
netId=str(netIdTemp[0])
box_id = user.id
name = user.name
data_used = user.space_used
# Get the user's status from the UCSB Identity API
request_url = "{}/people/readonly/{}/status".format(url_base, netId)
response = requests.get(request_url, headers=iam_headers)
status = ""
try:
status = response.json()["status"]
except:
status = "Unknown Status"
# Get the user's UCSB Campus ID and Department (only readonly calls are in scope
# other calls lead to insufficient scope)
request_url = "{}/people/readonly/{}".format(url_base, netId)
response = requests.get(request_url, headers=iam_headers)
campus_id = ""
try:
campus_id = response.json()[("ucsbCampusId")]
except:
campus_id = "Unknown Campus ID"
department = ""
try:
department = response.json()["ucsbHomeDepartment"]
except:
department = "Unknown Department"
if status == "terminated" or status == "separated":
print(f"{name}, {email}, {netId}, {box_id}, {data_used}, {department}, {campus_id}, {status}")
csv_writer.writerow([name, email, netId, box_id, data_used, department, campus_id, status])
print('Main thread done.')