Skip to content

Commit 04dab83

Browse files
committed
Merge spurious changes in master and ignore them.
2 parents 10c33ac + aa060a8 commit 04dab83

File tree

6 files changed

+45
-104
lines changed

6 files changed

+45
-104
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ Requirements:
4040

4141
To build, run `make pex` from the command line in the main repo directory.
4242

43+
## Build Instructions for local execution and debugging on Windows
44+
45+
First, there are several projects that do not have good 64 bit builds for Windows platforms. These are enum34, python_ldap, and pyYaml. Acceptable builds are in the misc/build/Win64 folder and these can be used directly. You can also check http://www.lfd.uci.edu/~gohlke/pythonlibs/
46+
47+
Load dependencies into interpreter directory:
48+
49+
pip install -r misc\build\Win64\python-ldap-requirements.txt
50+
pip install -r misc\build\requirements.txt
51+
52+
The requirements will usually be loaded into C:\Python27\lib\site-packages if C:\Python27 is your install directory and you aren't specifying any options that send things elsewhere.
53+
54+
To set up PyCharm for debugging,
55+
1. Make sure you are using 64 bit python interpreter. File Settings Project Interpreter
56+
2. Make sure interprter isn't overridden in run configuration
57+
3. Set up a run configuration based on Python that references the user_sync\app.py file as the script, and has the command line parameters you want to test with (e.g. --users file test.csv). Working directory works best as the folder with your config files.
58+
4359
# Basic Usage
4460

4561
```

user_sync/config.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,15 @@ def get_directory_groups(self):
205205

206206
dashboard_groups_config = item.get_list_config('dashboard_groups')
207207
for dashboard_group in dashboard_groups_config.iter_values(types.StringTypes):
208-
group = self.create_dashboard_group(dashboard_group)
209-
if (group is None):
208+
parts = dashboard_group.split(GROUP_NAME_DELIMITER)
209+
group_name = parts.pop()
210+
organization_name = GROUP_NAME_DELIMITER.join(parts)
211+
if (len(organization_name) == 0):
212+
organization_name = user_sync.rules.OWNING_ORGANIZATION_NAME
213+
if (len(group_name) == 0):
210214
validation_message = 'Bad dashboard group: "%s" in directory group: "%s"' % (dashboard_group, directory_group)
211-
raise user_sync.error.AssertionException(validation_message)
215+
raise user_sync.error.AssertionException(validation_message)
216+
group = user_sync.rules.Group(group_name, organization_name)
212217
groups.append(group)
213218

214219
return adobe_groups_by_directory_group

user_sync/connector/directory.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@ def initialize(self, options = {}):
4040
'''
4141
self.state = self.implementation.connector_initialize(options)
4242

43-
def load_users_and_groups(self, groups, extended_attributes=None):
43+
def load_users_and_groups(self, groups):
4444
'''
4545
:type groups: list(str)
46-
:type extended_attributes: list(str)
4746
:rtype (bool, iterable(dict))
4847
'''
49-
return self.implementation.connector_load_users_and_groups(self.state, groups, extended_attributes)
48+
return self.implementation.connector_load_users_and_groups(self.state, groups)
5049

user_sync/connector/directory_csv.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,12 @@ def connector_initialize(options):
3737
state = CSVDirectoryConnector(options)
3838
return state
3939

40-
def connector_load_users_and_groups(state, groups, extended_attributes):
40+
def connector_load_users_and_groups(state, groups):
4141
'''
4242
:type state: CSVDirectoryConnector
4343
:type groups: list(str)
44-
:type extended_attributes: list(str)
4544
:rtype (bool, iterable(dict))
4645
'''
47-
48-
# CSV supports arbitrary aka "extended" attrs by default, so the value of extended_attributes has no impact on this particular connector
49-
5046
return state.load_users_and_groups(groups)
5147

5248
class CSVDirectoryConnector(object):

user_sync/connector/directory_ldap.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@ def connector_initialize(options):
3939
connector = LDAPDirectoryConnector(options)
4040
return connector
4141

42-
def connector_load_users_and_groups(state, groups, extended_attributes):
42+
def connector_load_users_and_groups(state, groups):
4343
'''
4444
:type state: LDAPDirectoryConnector
4545
:type groups: list(str)
46-
:type extended_attributes: list(str)
4746
:rtype (bool, iterable(dict))
4847
'''
49-
return state.load_users_and_groups(groups, extended_attributes)
48+
return state.load_users_and_groups(groups)
5049

5150
class LDAPDirectoryConnector(object):
5251
name = 'ldap'
@@ -104,10 +103,9 @@ def __init__(self, caller_options):
104103
self.connection = connection
105104
logger.info('Connected')
106105

107-
def load_users_and_groups(self, groups, extended_attributes):
106+
def load_users_and_groups(self, groups):
108107
'''
109108
:type groups: list(str)
110-
:type extended_attributes: list(str)
111109
:rtype (bool, iterable(dict))
112110
'''
113111
options = self.options
@@ -127,12 +125,12 @@ def load_users_and_groups(self, groups, extended_attributes):
127125

128126
self.user_by_dn = user_by_dn = {}
129127
self.user_by_uid = user_by_uid = {}
130-
for user_dn, user in self.iter_users(users_filter, extended_attributes):
128+
for user_dn, user in self.iter_users(users_filter):
131129
uid = user.get('uid')
132130
if (uid != None):
133131
user_by_uid[uid] = user
134132
user_by_dn[user_dn] = user
135-
133+
136134
self.logger.info('Total users loaded: %d', len(user_by_dn))
137135

138136
for group in groups:
@@ -252,11 +250,11 @@ def iter_ldap_group_members(self, group):
252250
for attribute_value in attribute_values:
253251
yield (attribute, attribute_value)
254252

255-
def iter_users(self, users_filter, extended_attributes):
253+
def iter_users(self, users_filter):
256254
options = self.options
257255
base_dn = options['base_dn']
258-
259-
user_attribute_names = ["givenName", "sn", "c", "uid"]
256+
257+
user_attribute_names = ["givenName", "sn", "c", "uid"]
260258
user_attribute_names.extend(self.user_email_formatter.get_attribute_names())
261259
user_attribute_names.extend(self.user_username_formatter.get_attribute_names())
262260
user_attribute_names.extend(self.user_domain_formatter.get_attribute_names())
@@ -274,53 +272,35 @@ def iter_users(self, users_filter, extended_attributes):
274272
if (last_attribute_name != None):
275273
self.logger.warn('No email attribute: %s for dn: %s', last_attribute_name, dn)
276274
continue
277-
278-
source_attributes = {}
279275

280276
user = user_sync.connector.helper.create_blank_user()
281-
source_attributes['email'] = email
282277
user['email'] = email
283-
278+
284279
username, last_attribute_name = self.user_username_formatter.generate_value(record)
285-
source_attributes['username'] = username
286280
if (username == None and last_attribute_name != None):
287281
self.logger.info('No username attribute: %s for dn: %s', last_attribute_name, dn)
288282
user['username'] = username if username != None else email
289-
283+
290284
domain, last_attribute_name = self.user_domain_formatter.generate_value(record)
291-
source_attributes['domain'] = domain
292285
if (domain != None):
293286
user['domain'] = domain
294287
elif (last_attribute_name != None):
295288
self.logger.info('No domain attribute: %s for dn: %s', last_attribute_name, dn)
296289

297290
given_name_value = LDAPValueFormatter.get_attribute_value(record, 'givenName')
298-
source_attributes['givenName'] = given_name_value
299-
if (given_name_value != None):
291+
if (given_name_value != None):
300292
user['firstname'] = given_name_value
301293
sn_value = LDAPValueFormatter.get_attribute_value(record, 'sn')
302-
source_attributes['sn'] = sn_value
303294
if sn_value != None:
304295
user['lastname'] = sn_value
305296
c_value = LDAPValueFormatter.get_attribute_value(record, 'c')
306-
source_attributes['c'] = c_value
307297
if c_value != None:
308298
user['country'] = c_value
309-
299+
310300
uid = LDAPValueFormatter.get_attribute_value(record, 'uid')
311-
source_attributes['uid'] = uid
312301
if (uid != None):
313302
user['uid'] = uid
314-
315-
if extended_attributes is not None:
316-
for extended_attribute in extended_attributes:
317-
extended_attribute_value = LDAPValueFormatter.get_attribute_value(record, extended_attribute)
318-
source_attributes[extended_attribute] = extended_attribute_value
319-
320-
# [TODO morr 2017-02-26]: Could be omitted if no hook; worth considering?
321-
# [TODO morr 2017-02-28]: Is the copy necessary? Could just assign I think
322-
user['source_attributes'] = source_attributes.copy()
323-
303+
324304
yield (dn, user)
325305

326306
def iter_search_result(self, base_dn, scope, filter_string, attributes):

user_sync/rules.py

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,6 @@ def __init__(self, caller_options):
5757
self.filtered_directory_user_by_user_key = {}
5858
self.organization_info_by_organization = {}
5959
self.adding_dashboard_user_key = set()
60-
61-
# in/out variables for per-user after-mapping-hook code
62-
self.after_mapping_hook_scope = {
63-
'hook_storage': None, # for exclusive use by hook code; persists across calls
64-
'source_attributes': None, # in: attributes retrieved from customer directory system (eg 'c', 'givenName')
65-
# out: N/A
66-
'source_groups': None, # in: customer-side directory groups found for user
67-
# out: N/A
68-
'target_attributes': None, # in: user's attributes for UMAPI calls as defined by usual rules (eg 'country', 'firstname')
69-
# out: user's attributes for UMAPI calls as potentially changed by hook code
70-
'target_groups': None, # in: Adobe-side dashboard groups mapped for user by usual rules
71-
# out: Adobe-side dashboard groups as potentially changed by hook code
72-
}
7360

7461
remove_user_key_list = options['remove_user_key_list']
7562
remove_user_key_list = set(remove_user_key_list) if (remove_user_key_list != None) else set()
@@ -144,7 +131,6 @@ def read_desired_user_groups(self, mappings, directory_connector):
144131
directory_group_filter = options['directory_group_filter']
145132
if (directory_group_filter != None):
146133
directory_group_filter = set(directory_group_filter)
147-
extended_attributes = options.get('extended_attributes')
148134

149135
directory_user_by_user_key = self.directory_user_by_user_key
150136
filtered_directory_user_by_user_key = self.filtered_directory_user_by_user_key
@@ -153,7 +139,7 @@ def read_desired_user_groups(self, mappings, directory_connector):
153139
directory_groups = set(mappings.iterkeys())
154140
if (directory_group_filter != None):
155141
directory_groups.update(directory_group_filter)
156-
all_loaded, directory_users = directory_connector.load_users_and_groups(directory_groups, extended_attributes)
142+
all_loaded, directory_users = directory_connector.load_users_and_groups(directory_groups)
157143
if (not all_loaded and self.need_to_process_orphaned_dashboard_users):
158144
self.logger.warn('Not all users loaded. Cannot check orphaned users...')
159145
self.need_to_process_orphaned_dashboard_users = False
@@ -171,12 +157,7 @@ def read_desired_user_groups(self, mappings, directory_connector):
171157

172158
filtered_directory_user_by_user_key[user_key] = directory_user
173159
self.get_organization_info(OWNING_ORGANIZATION_NAME).add_desired_group_for(user_key, None)
174-
175-
# set up groups in hook scope; the target groups will be used whether or not there's customer hook code
176-
self.after_mapping_hook_scope['source_groups'] = set()
177-
self.after_mapping_hook_scope['target_groups'] = set()
178160
for group in directory_user['groups']:
179-
self.after_mapping_hook_scope['source_groups'].add(group) # this is a directory group name
180161
dashboard_groups = mappings.get(group)
181162
if (dashboard_groups != None):
182163
for dashboard_group in dashboard_groups:
@@ -708,21 +689,7 @@ def read_remove_list(file_path, delimiter = None, logger = None):
708689
if (user_key != None):
709690
result.append(user_key)
710691
return result
711-
712-
def make_dashboard_group_qualified_name(self, group_name, organization_name):
713-
prefix = ""
714-
if (organization_name is not None and organization_name != OWNING_ORGANIZATION_NAME):
715-
prefix = organization_name + user_sync.config.GROUP_NAME_DELIMITER
716-
return prefix + group_name
717-
718-
def parse_dashboard_group_qualified_name(self, qualified_name):
719-
parts = qualified_name.split(user_sync.config.GROUP_NAME_DELIMITER)
720-
group_name = parts.pop()
721-
organization_name = user_sync.config.GROUP_NAME_DELIMITER.join(parts)
722-
if (len(organization_name) == 0):
723-
organization_name = user_sync.rules.OWNING_ORGANIZATION_NAME
724-
return group_name, organization_name
725-
692+
726693
def write_remove_list(self, file_path, dashboard_users):
727694
total_users = 0
728695
with open(file_path, 'wb') as output_file:
@@ -735,18 +702,8 @@ def write_remove_list(self, file_path, dashboard_users):
735702
writer.writerow({'user': username, 'domain': domain})
736703
total_users += 1
737704
self.logger.info('Total users in remove list: %d', total_users)
738-
739-
def log_after_mapping_hook_scope(self, before_call=None, after_call=None):
740-
if ((before_call is None and after_call is None) or (before_call is not None and after_call is not None)):
741-
raise ValueError("Exactly one of 'before_call', 'after_call' must be passed (and not None)")
742-
when = 'before' if before_call is not None else 'after'
743-
if (before_call is not None):
744-
self.logger.debug('.')
745-
self.logger.debug('Source attrs, %s: %s', when, self.after_mapping_hook_scope['source_attributes'])
746-
self.logger.debug('Source groups, %s: %s', when, self.after_mapping_hook_scope['source_groups'])
747-
self.logger.debug('Target attrs, %s: %s', when, self.after_mapping_hook_scope['target_attributes'])
748-
self.logger.debug('Target groups, %s: %s', when, self.after_mapping_hook_scope['target_groups'])
749-
705+
706+
750707
class DashboardConnectors(object):
751708
def __init__(self, owning_connector, accessor_connectors):
752709
'''
@@ -778,17 +735,13 @@ def execute_actions(self):
778735
break
779736

780737
class Group(object):
781-
782-
dashboard_groups = {}
783-
784738
def __init__(self, group_name, organization_name):
785739
'''
786740
:type group_name: str
787741
:type organization_name: str
788742
'''
789743
self.group_name = group_name
790744
self.organization_name = organization_name
791-
Group.dashboard_groups[(group_name, organization_name)] = self
792745

793746
def __eq__(self, other):
794747
return self.__dict__ == other.__dict__
@@ -801,15 +754,7 @@ def __hash__(self):
801754

802755
def __str__(self):
803756
return str(self.__dict__)
804-
805-
@classmethod
806-
def get_dashboard_group(cls, group_name, organization_name):
807-
'''
808-
:type group_name: str
809-
:type organization_name: str
810-
'''
811-
return Group.dashboard_groups.get((group_name, organization_name))
812-
757+
813758
class OrganizationInfo(object):
814759
def __init__(self, name):
815760
'''

0 commit comments

Comments
 (0)