-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathso4t_scim_user_deletion.py
156 lines (119 loc) · 4.99 KB
/
so4t_scim_user_deletion.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
156
'''
This Python script is a labor of love and has no formal support from Stack Overflow.
If you run into difficulties, reach out to the person who provided you with this script.
Or, open an issue here: https://github.com/jklick-so/so4t_scim_user_deletion/issues
'''
# Standard Python libraries
import argparse
import csv
import datetime
import logging
import json
# Local libraries
from so4t_scim import ScimClient
def main():
args = get_args()
client = ScimClient(args.token, args.url)
# Get all users via SCIM API and write to a JSON file
all_users = client.get_all_users()
write_json(all_users, 'all_users')
failed_deletions = []
if args.deactivated and args.csv: # if both --deactivated and --csv flags are provided, print help message
logging.info("Please provide only one argument for which users to delete.")
logging.info("Use --deactivated to delete deactivated users.")
logging.info("Use --csv to delete users from a CSV file.")
logging.info("See README for more information.")
return
elif args.deactivated: # if --deactivated flag is provided, delete deactivated users
users_to_delete = [user for user in all_users if not user["active"]]
for user in users_to_delete:
deletion_result = client.delete_user(user["id"])
if deletion_result['status'] != 'success':
failed_deletions.append(deletion_result)
elif args.csv: # if a CSV file is provided, delete users from the CSV file
csv_users_to_delete = get_users_from_csv(args.csv)
for user in csv_users_to_delete:
scim_user = scim_user_lookup(all_users, email=user)
if scim_user is None: # if user_lookup returns None, skip this user
deletion_result = {
'email': user,
'status': 'failed',
'message': 'User email address not found via SCIM API'
}
failed_deletions.append(deletion_result)
else: # if user_lookup returns a user, attempt to delete the user
deletion_result = client.delete_user(scim_user["id"])
deletion_result['email'] = user
if deletion_result['status'] != 'success':
failed_deletions.append(deletion_result)
else: # if no arguments are provided, print help message
logging.info("Please provide an argument for which users to delete.")
logging.info("Use --deactivated to delete deactivated users.")
logging.info("Use --csv to delete users from a CSV file.")
logging.info("See README for more information.")
return
# get date and time of report generation to add to the filename
# this ensures that previous reports are not overwritten when script is run multiple times
report_date = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
if len(failed_deletions) == 0:
logging.info("All users deleted successfully.")
failed_deletions = {
'status': 'success',
'message': 'All selected users were deleted successfully.'
}
else:
logging.warning("Some users were not deleted successfully.")
logging.warning("Please review 'failed_deletions.json' for any users that were not deleted successfully.")
write_json(failed_deletions, f"failed_deletions_{report_date}") # write failed deletions to a JSON file
def get_args():
parser = argparse.ArgumentParser(
description="Delete users from Stack Overflow for Teams."
)
parser.add_argument(
"--token",
type=str,
required=True,
help="The SCIM token for your Stack Overflow for Teams site."
)
parser.add_argument(
"--url",
type=str,
required=True,
help="The base URL for your Stack Overflow for Teams site."
)
parser.add_argument(
"--csv",
type=str,
help="A CSV file with a list of users to delete."
)
parser.add_argument(
"--deactivated",
action="store_true",
help="Delete deactivated users."
)
args = parser.parse_args()
return args
def get_users_from_csv(csv_file):
users_to_delete = []
with open(csv_file, 'r') as f:
csv_reader = csv.reader(f)
for line in csv_reader:
users_to_delete.append(line[0])
return users_to_delete
def scim_user_lookup(users, email):
logging.debug("**********")
logging.debug(f"Finding account ID for user with email {email}...")
for user in users:
try:
if user["emails"][0]["value"].lower() == email.lower():
logging.debug(f"Account ID is {user['id']}")
return user
except KeyError: # if SCIM user does not have an email address, skip this user
continue
return None
def write_json(data, file_name):
file_path = file_name+'.json'
with open(file_path, 'w') as f:
f.write(json.dumps(data, indent=4))
if __name__ == "__main__":
main()