forked from Esri/ago-tools
-
Notifications
You must be signed in to change notification settings - Fork 1
/
admin.py
251 lines (210 loc) · 11.6 KB
/
admin.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#!/usr/bin/env python
import urllib
import json
import csv
from datetime import date, timedelta
class Admin:
'''A class of tools for administering AGO Orgs or Portals'''
def __init__(self, username, portal=None, password=None):
from . import User
self.user = User(username, portal, password)
def __users__(self, start=0):
'''Retrieve a single page of users.'''
parameters = urllib.urlencode({'token' : self.user.token,
'f' : 'json',
'start' : start,
'num' : 100})
portalId = self.user.__portalId__()
response = urllib.urlopen(self.user.portalUrl + '/sharing/rest/portals/' + portalId + '/users?' + parameters).read()
users = json.loads(response)
return users
def getUsers(self):
''' Returns a list of all users in the organization (requires admin access).'''
allUsers = []
users = self.__users__()
for user in users['users']:
allUsers.append(user)
while users['nextStart'] > 0:
users = self.__users__(users['nextStart'])
for user in users['users']:
allUsers.append(user)
return allUsers
def getNewUsers(self, daysToCheck):
'''
REQUIRES ADMIN ACCESS
Add new organization users to multiple groups and return a list of the status.
'''
# daysToCheck is the time interval to check for new users.
# e.g. 1 will check past day, 7 will check past week, etc.
users = self.getUsers()
# Create a list of all new users (joined in the last 'daysToCheck' days).
newUsers = []
for user in users:
if date.fromtimestamp(float(user['created'])/1000) > date.today()-timedelta(days=daysToCheck):
newUsers.append(user)
return newUsers
def addUsersToGroups(self, users, groups):
'''
REQUIRES ADMIN ACCESS
Add organization users to multiple groups and return a list of the status
'''
# Provide one or more usernames in a list.
# e.g. ['user_1', 'user_2']
# Provide one or more group IDs as strings in a list.
# e.g. ['d93aabd856f8459a8905a5bd434d4d4a', 'f84c841a3dfc4591b1ff83281ea5025f']
toolSummary = []
# Assign users to the specified group(s).
parameters = urllib.urlencode({'token': self.user.token, 'f': 'json'})
for groupID in groups:
userSummary = []
for user in users:
print 'Attempting to add ' + user + ' to groupID ' + groupID
# Add Users - REQUIRES POST method (undocumented operation as of 2013-07-10).
response = urllib.urlopen(self.user.portalUrl + '/sharing/rest/community/groups/' + groupID + '/addUsers?', 'users=' + user + "&" + parameters).read()
responseKeys = json.loads(response).keys() # Returns a list of the keys from the response JSON.
# Will likely report a false-negative.
userSummary.append({user: responseKeys[0]})
toolSummary.append({groupID: userSummary})
return toolSummary
def reassignAllUser1ItemsToUser2(self, userFrom, userTo):
'''
REQUIRES ADMIN ACCESS
Transfers ownership of all items in userFrom/User1's account to userTo/User2's account, keeping same folder names.
- Does not check for existing folders in userTo's account.
- Does not delete content from userFrom's account.
'''
# request user content for userFrom
# response contains list of items in root folder and list of all folders
parameters = urllib.urlencode({'token': self.user.token, 'f': 'json'})
request = self.user.portalUrl + '/sharing/rest/content/users/' + userFrom + '?' + parameters
userContent = json.loads(urllib.urlopen(request).read())
# create same folders in userTo's account like those in userFrom's account
for folder in userContent['folders']:
parameters2 = urllib.urlencode({'title' : folder['title'], 'token': self.user.token, 'f': 'json'})
request2 = self.user.portalUrl + '/sharing/rest/content/users/' + userTo + '/createFolder?'
response2 = urllib.urlopen(request2, parameters2).read() # requires POST
# keep track of items and folders
numberOfItems = 0
numberOfFolders = 1
# change ownership of items in ROOT folder
for item in userContent['items']:
parameters3 = urllib.urlencode({'targetUsername' : userTo, 'targetFoldername' : '/', 'token': self.user.token, 'f': 'json'})
request3 = self.user.portalUrl + '/sharing/rest/content/users/' + userFrom + '/items/' + item['id'] + '/reassign?'
response3 = urllib.urlopen(request3, parameters3).read() # requires POST
if 'success' in response3:
numberOfItems += 1
### change ownership of items in SUBFOLDERS (nested loop)
# request content in current folder
for folder in userContent['folders']:
parameters4 = urllib.urlencode({'token': self.user.token, 'f': 'json'})
request4 = self.user.portalUrl + '/sharing/rest/content/users/' + userFrom + '/' + folder['id'] + '?' + parameters4
folderContent = json.loads(urllib.urlopen(request4).read())
numberOfFolders += 1
# change ownership of items in CURRENT folder to userTo and put in correct folder
for item in folderContent['items']:
parameters5 = urllib.urlencode({'targetUsername' : userTo, 'targetFoldername' : folder['title'], 'token': self.user.token, 'f': 'pjson'})
request5 = self.user.portalUrl + '/sharing/rest/content/users/' + userFrom + '/' + folder['id'] + '/items/' + item['id'] + '/reassign?'
response5 = urllib.urlopen(request5, parameters5).read() # requires POST
numberOfItems += 1
# summarize results
print ' ' + str(numberOfItems) + ' ITEMS in ' + str(numberOfFolders) + ' FOLDERS (incl. Home folder) copied'
print ' from USER ' + userFrom + ' to USER ' + userTo
return
def reassignAllGroupOwnership(self, userFrom, userTo):
'''
REQUIRES ADMIN ACCESS
Reassigns ownership of all groups between a pair of accounts.
'''
groups = 0
groupsReassigned = 0
# Get list of userFrom's groups
print 'Requesting ' + userFrom + "'s group info from ArcGIS Online...",
parameters = urllib.urlencode({'token': self.user.token, 'f': 'pjson'})
request = self.user.portalUrl + '/sharing/rest/community/users/' + userFrom + '?' + parameters
response = urllib.urlopen(request).read()
userFromContent = json.loads(response)
print 'RECEIVED!'
# Determine if userFrom is group owner and, if so, transfer ownership to userTo
print 'Checking groups...',
for group in userFromContent['groups']:
print '.',
groups += 1
if group['owner'] == userFrom:
parameters = urllib.urlencode({'targetUsername' : userTo, 'token': self.user.token, 'f': 'pjson'})
request = self.user.portalUrl + '/sharing/rest/community/groups/' + group['id'] + '/reassign?'
response = urllib.urlopen(request, parameters).read() # requires POST
if 'success' in response:
groupsReassigned += 1
# Report results
print
print ' CHECKED ' + str(groups) + ' groups ASSOCIATED with ' + userFrom + '.'
print ' REASSIGNED ' + str(groupsReassigned) + ' groups OWNED by ' + userFrom + ' to ' + userTo + '.'
return
def addUser2ToAllUser1Groups(self, userFrom, userTo):
'''
REQUIRES ADMIN ACCESS
Adds userTo/User2 to all groups that userFrom/User1 is a member
'''
groups = 0
groupsOwned = 0
groupsAdded = 0
# Get list of userFrom's groups
parameters = urllib.urlencode({'token': self.user.token, 'f': 'pjson'})
request = self.user.portalUrl + '/sharing/rest/community/users/' + userFrom + '?' + parameters
response = urllib.urlopen(request).read()
userFromContent = json.loads(response)
# Add userTo to each group that userFrom's is a member, but not an owner
for group in userFromContent['groups']:
groups += 1
if group['owner'] == userFrom:
groupsOwned += 1
else:
parameters = urllib.urlencode({'users' : userTo, 'token': self.user.token, 'f': 'pjson'})
request = self.user.portalUrl + '/sharing/rest/community/groups/' + group['id'] + '/addUsers?'
response = urllib.urlopen(request, parameters).read() # requires POST
if '[]' in response: # This currently undocumented operation does not correctly return "success"
groupsAdded += 1
print ' CHECKED ' + str(groups) + ' groups associated with ' + userFrom + ':'
print ' ' + userFrom + ' OWNS ' + str(groupsOwned) + ' groups (' + userTo + ' NOT added).'
print ' ' + userTo + ' is already a MEMBER of ' + str(groups-groupsOwned-groupsAdded) + ' groups.'
print ' ' + userTo + ' was ADDED to ' + str(groupsAdded) + ' groups.'
return
def migrateAccount(self, userFrom, userTo):
'''
REQUIRES ADMIN ACCESS
Reassigns ownership of all content items and groups from userFrom to userTo.
Also adds userTo to all groups which userFrom is a member.
'''
print 'Copying all items from ' + userFrom + ' to ' + userTo + '...'
self.reassignAllUser1ItemsToUser2(self, userFrom, userTo)
print
print 'Reassigning groups owned by ' + userFrom + ' to ' + userTo + '...'
self.reassignAllGroupOwnership(self, userFrom, userTo)
print
print 'Adding ' + userTo + ' as a member of ' + userFrom + "'s groups..."
self.addUser2ToAllUser1Groups(self, userFrom, userTo)
return
def migrateAccounts(self, pathUserMappingCSV):
'''
REQUIRES ADMIN ACCESS
Reassigns ownership of all content items and groups between pairs of accounts specified in a CSV file.
Also adds userTo to all groups which userFrom is a member.
This function batches migrateAccount using a CSV to feed in the accounts to migrate from/to,
the CSV should have two columns (no column headers/labels): col1=userFrom, col2=userTo)
'''
with open(pathUserMappingCSV, 'rb') as userMappingCSV:
userMapping = csv.reader(userMappingCSV)
for user in userMapping:
userFrom = user[0]
userTo = user[1]
print '=========='
print 'Copying all items from ' + userFrom + ' to ' + userTo + '...'
self.reassignAllUser1ItemsToUser2(self, userFrom, userTo)
print
print 'Reassigning groups owned by ' + userFrom + ' to ' + userTo + '...'
self.reassignAllGroupOwnership(self, userFrom, userTo)
print
print 'Adding ' + userTo + ' as a member of ' + userFrom + "'s groups..."
self.addUser2ToAllUser1Groups(self, userFrom, userTo)
print '=========='
return