{"action":"created","comment":{"url":"https://api.github.com/repos/sdelements/sdetools/pulls/comments/53174224","id":53174224,"diff_hunk":"@@ -110,127 +174,230 @@ def connect(self):\n         except ldap.LDAPError, e:\n             raise LDAPConnectorError(\"Unable to bind connection: %s\" % e.message[\"desc\"])\n \n-    # For AD ONLY. Returns dictionary of {group: member distinguished name list} pairs\n-    def query_groups_ad(self):\n-        logger.info(\"Querying Active Directory Server for groups\")\n-        dirtyList = self.connection.search_s(self.basedn, ldap.SCOPE_SUBTREE, \"(&(cn=*)(objectClass=group))\", [\"name\", \"member\"])\n-        groups = {}\n-        logger.info(\"Querying Active Directory Server for users\")\n-        for group in dirtyList:\n-            info = group[1]\n-            if \"member\" in info:\n-                groupName = info[\"name\"][0]\n-                # Not 100% sure this check is needed. Will review TODO: review\n-                if groupName not in groups.keys():\n-                    groups[groupName] = []\n-                for member in info[\"member\"]:\n-                    query = \"(distinguishedName=\"+member+\")\"\n-                    logger.debug(\"Querying Active Directory Server for user: '%s'\" % member)\n-                    user = self.connection.search_s(self.basedn, ldap.SCOPE_SUBTREE, query,  [\n-                                                        self.config['user_schema']['email'],\n-                                                        self.config['user_schema']['full_name'],\n-                                                        self.config['user_schema']['last_name'],\n-                                                        self.config['user_schema']['first_name'],\n-                                                        \"userAccountControl\",\n-                                                    ])\n-\n-                    if len(user):\n-                        groups[groupName].append(user[0][1])\n-        return groups\n+        return True\n+\n+    @property\n+    def user_schema(self):\n+        return self.config['user_schema']\n+\n+    @property\n+    def current_user(self):\n+        if self._current_user:\n+            return self._current_user\n+\n+        if self.sde_plugin:\n+            self._current_user = self.sde_plugin.get_users(myself_only=True)\n+\n+        return self._current_user\n+\n+    @property\n+    def groups(self):\n+        if self._groups:\n+            return self._groups\n+\n+        if self.sde_plugin:\n+            self._groups = dict(\n+                (group['name'], group)\n+                for group in self.sde_plugin.get_groups()\n+            )\n+\n+        return self._groups\n \n-    def query_groups_ldap(self):\n-        dirtyList = self.connection.search_s(self.basedn, ldap.SCOPE_SUBTREE, \"ou=*\", [\"uniqueMember\"])\n-        groups = {}\n-\n-        for listItem in dirtyList:\n-            items = re.split(\"(ou=\\w*)\", listItem[0])\n-            groupName = items[1][3:]\n-\n-            # Prevent key value overwrites\n-            if groupName not in groups.keys():\n-                groups[groupName] = []\n-            items = items[2:]\n-\n-            # Check if group is a subgroup of another group\n-            for item in items:\n-                if re.match(\"ou=\", item):\n-                    match = item[3:]\n-                    # Prevent key value overwrites. Initializes parent group keys if current group is a subgroup\n-                    if match not in groups.keys():\n-                        groups[match] = []\n-                    #groups[match].append(groupName) CAUSES errors, way to track subgroups though...\n-\n-            # Search for each user by uid\n-            for item in listItem[1][\"uniqueMember\"]:\n-                uid = re.split(\",\", item)[0]\n-\n-                # Last paramaters of search are keys to take from queried dictionary\n-                user = self.connection.search_s(self.basedn, ldap.SCOPE_SUBTREE, uid, [\n-                                                    self.config['user_schema']['email'],\n-                                                    self.config['user_schema']['full_name'],\n-                                                    self.config['user_schema']['last_name'],\n-                                                    self.config['user_schema']['first_name'],\n-                                                ])\n-                # Currently stores users as dictionary with mail and cn attribute\n-                if len(user):\n-                    groups[groupName].append(user[0][1])\n+    @property\n+    def server_type(self):\n+        return self.config['server_type'].lower()\n+\n+    @property\n+    def ldap_method(self):\n+        return self.config['ldap_method'].lower()\n+\n+    def get_ldap_user_params(self):\n+        params = [\n+            self.user_schema['email'],\n+            self.user_schema['full_name'],\n+            self.user_schema['last_name'],\n+            self.user_schema['first_name'],\n+        ]\n+\n+        if self.server_type == 'ad':\n+            params.append('userAccountControl')\n+\n+        return params\n+\n+    def get_groups_from_ldap(self):\n+        logger.info(\"Querying LDAP Server for groups\")\n+\n+        if self.server_type == \"ad\":\n+            return self.connection.search_s(self.basedn,\n+                                            ldap.SCOPE_SUBTREE,\n+                                            \"(&(cn=*)(objectClass=group))\",\n+                                            [\"name\", \"member\"])\n+        else:\n+            return self.connection.search_s(self.basedn,\n+                                            ldap.SCOPE_SUBTREE,\n+                                            \"(ou=*)\",\n+                                            [\"uniqueMember\"])\n+\n+    def get_ldap_user(self, member):\n+        \"\"\"\n+        Queries LDAP for a specific user given a member DN\n+        \"\"\"\n+        log_message = \"Querying LDAP Server for user: '%s'\"\n+        logger.debug(log_message % member)\n+\n+        if self.server_type == 'ad':\n+            query = \"(distinguishedName=%s)\" % member\n+        else:\n+            query = '(' + member.split(',')[0] + ')'\n+\n+        user = self.connection.search_s(self.basedn,\n+                                        ldap.SCOPE_SUBTREE,\n+                                        query,\n+                                        self.get_ldap_user_params())\n+\n+        if len(user):\n+            # user is of the form:\n+            # [(USER_BIND_DN, {STUFF_IN_SCHEMA}),  OTHER_JUNK]\n+            # we only want to return USER_BIND_DN\n+            return user[0][1]\n+\n+        return ''\n+\n+    def get_group_from_ldap_tuple(self, ldap_tuple):\n+        \"\"\"\n+        Accepts a group tuple from LDAP and returns the group name\n+        and its members. The format are as follow:\n+\n+        ActiveDirectory:\n+            (GROUP_BIND_DN,\n+             {'member': [MEMBER_DN's],\n+              'name': [GROUP_NAME]})\n+        LDAP:\n+            (GROUP_BIND_DN,\n+             {'uniqueMember': [MEMBER_DN's]})\n+\n+        Returns a tuple\n+            (GROUP_NAME, [MEMBERs])\n+        \"\"\"\n+        if self.server_type == 'ad':\n+            info = ldap_tuple[1]\n+\n+            # empty group\n+            if 'member' not in info:\n+                return ('', [])\n+\n+            group_name = info['name'][0]\n+            members = info.get('member', [])\n+\n+            return (info['name'][0], members)\n+        else:\n+            items = self.ou_regex.split(ldap_tuple[0])\n+\n+            group_name = items[1][3:]\n+            members = ldap_tuple[1][\"uniqueMember\"]\n+\n+            return (group_name, members)","path":"sdetools/modules/sync_ldap/ldap_module.py","position":399,"original_position":399,"commit_id":"605b1999790557e93c00d8f9631212c845b2c020","original_commit_id":"020068fbd30cbafda70f659a6df33737e96faf9f","user":{"login":"emintham","id":3454934,"avatar_url":"https://avatars.githubusercontent.com/u/3454934?v=3","gravatar_id":"","url":"https://api.github.com/users/emintham","html_url":"https://github.com/emintham","followers_url":"https://api.github.com/users/emintham/followers","following_url":"https://api.github.com/users/emintham/following{/other_user}","gists_url":"https://api.github.com/users/emintham/gists{/gist_id}","starred_url":"https://api.github.com/users/emintham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emintham/subscriptions","organizations_url":"https://api.github.com/users/emintham/orgs","repos_url":"https://api.github.com/users/emintham/repos","events_url":"https://api.github.com/users/emintham/events{/privacy}","received_events_url":"https://api.github.com/users/emintham/received_events","type":"User","site_admin":false},"body":"Done","created_at":"2016-02-17T14:54:25Z","updated_at":"2016-02-17T14:54:25Z","html_url":"https://github.com/sdelements/sdetools/pull/330#discussion_r53174224","pull_request_url":"https://api.github.com/repos/sdelements/sdetools/pulls/330","_links":{"self":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/comments/53174224"},"html":{"href":"https://github.com/sdelements/sdetools/pull/330#discussion_r53174224"},"pull_request":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/330"}}},"pull_request":{"url":"https://api.github.com/repos/sdelements/sdetools/pulls/330","id":57911378,"html_url":"https://github.com/sdelements/sdetools/pull/330","diff_url":"https://github.com/sdelements/sdetools/pull/330.diff","patch_url":"https://github.com/sdelements/sdetools/pull/330.patch","issue_url":"https://api.github.com/repos/sdelements/sdetools/issues/330","number":330,"state":"open","locked":false,"title":"Fix/sync ldap","user":{"login":"emintham","id":3454934,"avatar_url":"https://avatars.githubusercontent.com/u/3454934?v=3","gravatar_id":"","url":"https://api.github.com/users/emintham","html_url":"https://github.com/emintham","followers_url":"https://api.github.com/users/emintham/followers","following_url":"https://api.github.com/users/emintham/following{/other_user}","gists_url":"https://api.github.com/users/emintham/gists{/gist_id}","starred_url":"https://api.github.com/users/emintham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emintham/subscriptions","organizations_url":"https://api.github.com/users/emintham/orgs","repos_url":"https://api.github.com/users/emintham/repos","events_url":"https://api.github.com/users/emintham/events{/privacy}","received_events_url":"https://api.github.com/users/emintham/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-02-01T22:34:00Z","updated_at":"2016-02-17T14:54:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dd47edc52045876027a5cd57cb5e69d919188cad","assignee":{"login":"geoffwhittington","id":1770544,"avatar_url":"https://avatars.githubusercontent.com/u/1770544?v=3","gravatar_id":"","url":"https://api.github.com/users/geoffwhittington","html_url":"https://github.com/geoffwhittington","followers_url":"https://api.github.com/users/geoffwhittington/followers","following_url":"https://api.github.com/users/geoffwhittington/following{/other_user}","gists_url":"https://api.github.com/users/geoffwhittington/gists{/gist_id}","starred_url":"https://api.github.com/users/geoffwhittington/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geoffwhittington/subscriptions","organizations_url":"https://api.github.com/users/geoffwhittington/orgs","repos_url":"https://api.github.com/users/geoffwhittington/repos","events_url":"https://api.github.com/users/geoffwhittington/events{/privacy}","received_events_url":"https://api.github.com/users/geoffwhittington/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/sdelements/sdetools/pulls/330/commits","review_comments_url":"https://api.github.com/repos/sdelements/sdetools/pulls/330/comments","review_comment_url":"https://api.github.com/repos/sdelements/sdetools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/sdelements/sdetools/issues/330/comments","statuses_url":"https://api.github.com/repos/sdelements/sdetools/statuses/605b1999790557e93c00d8f9631212c845b2c020","head":{"label":"sdelements:fix/sync_ldap","ref":"fix/sync_ldap","sha":"605b1999790557e93c00d8f9631212c845b2c020","user":{"login":"sdelements","id":739346,"avatar_url":"https://avatars.githubusercontent.com/u/739346?v=3","gravatar_id":"","url":"https://api.github.com/users/sdelements","html_url":"https://github.com/sdelements","followers_url":"https://api.github.com/users/sdelements/followers","following_url":"https://api.github.com/users/sdelements/following{/other_user}","gists_url":"https://api.github.com/users/sdelements/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelements/subscriptions","organizations_url":"https://api.github.com/users/sdelements/orgs","repos_url":"https://api.github.com/users/sdelements/repos","events_url":"https://api.github.com/users/sdelements/events{/privacy}","received_events_url":"https://api.github.com/users/sdelements/received_events","type":"Organization","site_admin":false},"repo":{"id":4272561,"name":"sdetools","full_name":"sdelements/sdetools","owner":{"login":"sdelements","id":739346,"avatar_url":"https://avatars.githubusercontent.com/u/739346?v=3","gravatar_id":"","url":"https://api.github.com/users/sdelements","html_url":"https://github.com/sdelements","followers_url":"https://api.github.com/users/sdelements/followers","following_url":"https://api.github.com/users/sdelements/following{/other_user}","gists_url":"https://api.github.com/users/sdelements/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelements/subscriptions","organizations_url":"https://api.github.com/users/sdelements/orgs","repos_url":"https://api.github.com/users/sdelements/repos","events_url":"https://api.github.com/users/sdelements/events{/privacy}","received_events_url":"https://api.github.com/users/sdelements/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/sdelements/sdetools","description":"SD Element Tools: A collection of SD Elements integration tools built around SD Elements API.","fork":false,"url":"https://api.github.com/repos/sdelements/sdetools","forks_url":"https://api.github.com/repos/sdelements/sdetools/forks","keys_url":"https://api.github.com/repos/sdelements/sdetools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sdelements/sdetools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sdelements/sdetools/teams","hooks_url":"https://api.github.com/repos/sdelements/sdetools/hooks","issue_events_url":"https://api.github.com/repos/sdelements/sdetools/issues/events{/number}","events_url":"https://api.github.com/repos/sdelements/sdetools/events","assignees_url":"https://api.github.com/repos/sdelements/sdetools/assignees{/user}","branches_url":"https://api.github.com/repos/sdelements/sdetools/branches{/branch}","tags_url":"https://api.github.com/repos/sdelements/sdetools/tags","blobs_url":"https://api.github.com/repos/sdelements/sdetools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sdelements/sdetools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sdelements/sdetools/git/refs{/sha}","trees_url":"https://api.github.com/repos/sdelements/sdetools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sdelements/sdetools/statuses/{sha}","languages_url":"https://api.github.com/repos/sdelements/sdetools/languages","stargazers_url":"https://api.github.com/repos/sdelements/sdetools/stargazers","contributors_url":"https://api.github.com/repos/sdelements/sdetools/contributors","subscribers_url":"https://api.github.com/repos/sdelements/sdetools/subscribers","subscription_url":"https://api.github.com/repos/sdelements/sdetools/subscription","commits_url":"https://api.github.com/repos/sdelements/sdetools/commits{/sha}","git_commits_url":"https://api.github.com/repos/sdelements/sdetools/git/commits{/sha}","comments_url":"https://api.github.com/repos/sdelements/sdetools/comments{/number}","issue_comment_url":"https://api.github.com/repos/sdelements/sdetools/issues/comments{/number}","contents_url":"https://api.github.com/repos/sdelements/sdetools/contents/{+path}","compare_url":"https://api.github.com/repos/sdelements/sdetools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sdelements/sdetools/merges","archive_url":"https://api.github.com/repos/sdelements/sdetools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sdelements/sdetools/downloads","issues_url":"https://api.github.com/repos/sdelements/sdetools/issues{/number}","pulls_url":"https://api.github.com/repos/sdelements/sdetools/pulls{/number}","milestones_url":"https://api.github.com/repos/sdelements/sdetools/milestones{/number}","notifications_url":"https://api.github.com/repos/sdelements/sdetools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sdelements/sdetools/labels{/name}","releases_url":"https://api.github.com/repos/sdelements/sdetools/releases{/id}","deployments_url":"https://api.github.com/repos/sdelements/sdetools/deployments","created_at":"2012-05-09T14:33:34Z","updated_at":"2016-01-26T12:43:59Z","pushed_at":"2016-02-17T02:56:56Z","git_url":"git://github.com/sdelements/sdetools.git","ssh_url":"git@github.com:sdelements/sdetools.git","clone_url":"https://github.com/sdelements/sdetools.git","svn_url":"https://github.com/sdelements/sdetools","homepage":"https://travis-ci.org/sdelements/sdetools","size":10853,"stargazers_count":10,"watchers_count":10,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":19,"forks":3,"open_issues":19,"watchers":10,"default_branch":"master"}},"base":{"label":"sdelements:feature/sync_ldap","ref":"feature/sync_ldap","sha":"35213226ece24bfbb3287306ea50d3cc3ed4a554","user":{"login":"sdelements","id":739346,"avatar_url":"https://avatars.githubusercontent.com/u/739346?v=3","gravatar_id":"","url":"https://api.github.com/users/sdelements","html_url":"https://github.com/sdelements","followers_url":"https://api.github.com/users/sdelements/followers","following_url":"https://api.github.com/users/sdelements/following{/other_user}","gists_url":"https://api.github.com/users/sdelements/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelements/subscriptions","organizations_url":"https://api.github.com/users/sdelements/orgs","repos_url":"https://api.github.com/users/sdelements/repos","events_url":"https://api.github.com/users/sdelements/events{/privacy}","received_events_url":"https://api.github.com/users/sdelements/received_events","type":"Organization","site_admin":false},"repo":{"id":4272561,"name":"sdetools","full_name":"sdelements/sdetools","owner":{"login":"sdelements","id":739346,"avatar_url":"https://avatars.githubusercontent.com/u/739346?v=3","gravatar_id":"","url":"https://api.github.com/users/sdelements","html_url":"https://github.com/sdelements","followers_url":"https://api.github.com/users/sdelements/followers","following_url":"https://api.github.com/users/sdelements/following{/other_user}","gists_url":"https://api.github.com/users/sdelements/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelements/subscriptions","organizations_url":"https://api.github.com/users/sdelements/orgs","repos_url":"https://api.github.com/users/sdelements/repos","events_url":"https://api.github.com/users/sdelements/events{/privacy}","received_events_url":"https://api.github.com/users/sdelements/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/sdelements/sdetools","description":"SD Element Tools: A collection of SD Elements integration tools built around SD Elements API.","fork":false,"url":"https://api.github.com/repos/sdelements/sdetools","forks_url":"https://api.github.com/repos/sdelements/sdetools/forks","keys_url":"https://api.github.com/repos/sdelements/sdetools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sdelements/sdetools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sdelements/sdetools/teams","hooks_url":"https://api.github.com/repos/sdelements/sdetools/hooks","issue_events_url":"https://api.github.com/repos/sdelements/sdetools/issues/events{/number}","events_url":"https://api.github.com/repos/sdelements/sdetools/events","assignees_url":"https://api.github.com/repos/sdelements/sdetools/assignees{/user}","branches_url":"https://api.github.com/repos/sdelements/sdetools/branches{/branch}","tags_url":"https://api.github.com/repos/sdelements/sdetools/tags","blobs_url":"https://api.github.com/repos/sdelements/sdetools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sdelements/sdetools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sdelements/sdetools/git/refs{/sha}","trees_url":"https://api.github.com/repos/sdelements/sdetools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sdelements/sdetools/statuses/{sha}","languages_url":"https://api.github.com/repos/sdelements/sdetools/languages","stargazers_url":"https://api.github.com/repos/sdelements/sdetools/stargazers","contributors_url":"https://api.github.com/repos/sdelements/sdetools/contributors","subscribers_url":"https://api.github.com/repos/sdelements/sdetools/subscribers","subscription_url":"https://api.github.com/repos/sdelements/sdetools/subscription","commits_url":"https://api.github.com/repos/sdelements/sdetools/commits{/sha}","git_commits_url":"https://api.github.com/repos/sdelements/sdetools/git/commits{/sha}","comments_url":"https://api.github.com/repos/sdelements/sdetools/comments{/number}","issue_comment_url":"https://api.github.com/repos/sdelements/sdetools/issues/comments{/number}","contents_url":"https://api.github.com/repos/sdelements/sdetools/contents/{+path}","compare_url":"https://api.github.com/repos/sdelements/sdetools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sdelements/sdetools/merges","archive_url":"https://api.github.com/repos/sdelements/sdetools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sdelements/sdetools/downloads","issues_url":"https://api.github.com/repos/sdelements/sdetools/issues{/number}","pulls_url":"https://api.github.com/repos/sdelements/sdetools/pulls{/number}","milestones_url":"https://api.github.com/repos/sdelements/sdetools/milestones{/number}","notifications_url":"https://api.github.com/repos/sdelements/sdetools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sdelements/sdetools/labels{/name}","releases_url":"https://api.github.com/repos/sdelements/sdetools/releases{/id}","deployments_url":"https://api.github.com/repos/sdelements/sdetools/deployments","created_at":"2012-05-09T14:33:34Z","updated_at":"2016-01-26T12:43:59Z","pushed_at":"2016-02-17T02:56:56Z","git_url":"git://github.com/sdelements/sdetools.git","ssh_url":"git@github.com:sdelements/sdetools.git","clone_url":"https://github.com/sdelements/sdetools.git","svn_url":"https://github.com/sdelements/sdetools","homepage":"https://travis-ci.org/sdelements/sdetools","size":10853,"stargazers_count":10,"watchers_count":10,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":19,"forks":3,"open_issues":19,"watchers":10,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/330"},"html":{"href":"https://github.com/sdelements/sdetools/pull/330"},"issue":{"href":"https://api.github.com/repos/sdelements/sdetools/issues/330"},"comments":{"href":"https://api.github.com/repos/sdelements/sdetools/issues/330/comments"},"review_comments":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/330/comments"},"review_comment":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/sdelements/sdetools/pulls/330/commits"},"statuses":{"href":"https://api.github.com/repos/sdelements/sdetools/statuses/605b1999790557e93c00d8f9631212c845b2c020"}}}}