| 685 | |
| 686 | @staticmethod |
| 687 | def sync_membership(scim_url, # type: str |
| 688 | token, # type: str |
| 689 | keeper_groups, # type: Dict[str, ScimGroup] |
| 690 | keeper_users, # type: Dict[str, ScimUser] |
| 691 | external_users, # type: Dict[str, ScimUser] |
| 692 | dry_run=False, # type: bool |
| 693 | **kwargs # type: Any |
| 694 | ): # type: (...) -> None |
| 695 | destructive = kwargs.get('destructive') |
| 696 | if not isinstance(destructive, int): |
| 697 | destructive = 0 |
| 698 | |
| 699 | keeper_user_lookup = {x.email: x for x in keeper_users.values()} # type: Dict[str, ScimUser] |
| 700 | keeper_group_map = {x.external_id: x.id for x in keeper_groups.values() if x.external_id} |
| 701 | for user in external_users.values(): |
| 702 | if user.email not in keeper_user_lookup: |
| 703 | continue |
| 704 | keeper_user = keeper_user_lookup[user.email] |
| 705 | keeper_user_groups = set(keeper_user.groups or []) |
| 706 | add_groups = [] |
| 707 | remove_groups = [] |
| 708 | for external_group_id in user.groups: |
| 709 | if external_group_id in keeper_group_map: |
| 710 | keeper_group_id = keeper_group_map[external_group_id] |
| 711 | if keeper_group_id in keeper_user_groups: |
| 712 | keeper_user_groups.remove(keeper_group_id) |
| 713 | else: |
| 714 | add_groups.append(keeper_group_id) |
| 715 | if len(keeper_user_groups) > 0: |
| 716 | if destructive > 0: |
| 717 | remove_groups.extend(keeper_user_groups) |
| 718 | else: |
| 719 | for keeper_group_id in keeper_user_groups: |
| 720 | if keeper_group_id in keeper_groups: |
| 721 | keeper_group = keeper_groups[keeper_group_id] |
| 722 | if keeper_group.external_id: |
| 723 | remove_groups.append(keeper_group_id) |
| 724 | else: |
| 725 | logging.info('Remove team \"%s\" user "%s" membership skipped. Team is not controlled by SCIM', |
| 726 | keeper_group.name, user.email) |
| 727 | else: |
| 728 | logging.info('Remove team Id "%s" from user "%s" skipped. Team is outside of SCIM node', keeper_group_id, user.email) |
| 729 | |
| 730 | if len(add_groups) > 0 or len(remove_groups) > 0: |
| 731 | payload = { |
| 732 | 'schemas': ['urn:ietf:params:scim:api:messages:2.0:PatchOp'], |
| 733 | 'Operations': [] |
| 734 | } |
| 735 | if len(add_groups) > 0: |
| 736 | payload['Operations'].append({ |
| 737 | 'op': 'add', |
| 738 | 'path': 'groups', |
| 739 | 'value': [{'value': x} for x in add_groups] |
| 740 | }) |
| 741 | if len(remove_groups) > 0: |
| 742 | payload['Operations'].append({ |
| 743 | 'op': 'remove', |
| 744 | 'path': 'groups', |