Repository: chaoss/grimoirelab-sortinghat (language: python)

Issue:
Affiliate job doesn't support top domains
The `affiliate` job matches the organizations subdomains regardless of whether they are marked as "top" domains or not. Eg., it affiliates the individuals with `@users.noreply.github.com` emails to GitHub when it should only match `@github.com`.


Discussion / hints:

Fix patch:
diff --git a/releases/unreleased/subdomain-affiliation-error.yml b/releases/unreleased/subdomain-affiliation-error.yml
new file mode 100644
index 00000000..9280b4b7
--- /dev/null
+++ b/releases/unreleased/subdomain-affiliation-error.yml
@@ -0,0 +1,8 @@
+---
+title: Sub-domain affiliation error
+category: fixed
+author: Eva Millán <evamillan@bitergia.com>
+issue: 805
+notes: |
+  The `affiliate` and `recommend affiliations` jobs no longer recommend
+  matches based on a domain's sub-domains if it is not marked as `top_domain`.
diff --git a/sortinghat/core/recommendations/affiliation.py b/sortinghat/core/recommendations/affiliation.py
index 0662137e..d01b7ab7 100644
--- a/sortinghat/core/recommendations/affiliation.py
+++ b/sortinghat/core/recommendations/affiliation.py
@@ -133,17 +133,21 @@ def _find_matching_domain(domain):
     """Look for domains and sub-domains that match with the given one."""
 
     keep_looking = True
+    is_subdomain = False
 
     # Splits the domain into root domains until
     # is found in the database.
     while keep_looking:
         try:
             result = find_domain(domain)
+            if is_subdomain and not result.is_top_domain:
+                result = None
             keep_looking = False
         except NotFoundError:
             index = domain.find('.')
             if index > -1:
                 domain = domain[index + 1:]
+                is_subdomain = True
             else:
                 result = None
                 keep_looking = False


Test patch:
diff --git a/tests/rec/test_affiliations.py b/tests/rec/test_affiliations.py
index 42fe36fa..8606aade 100644
--- a/tests/rec/test_affiliations.py
+++ b/tests/rec/test_affiliations.py
@@ -48,7 +48,7 @@ def setUp(self):
 
         api.add_organization(ctx, 'Bitergia')
         api.add_domain(ctx, 'Bitergia', 'bitergia.com')
-        api.add_domain(ctx, 'Bitergia', 'bitergia.org')
+        api.add_domain(ctx, 'Bitergia', 'bitergia.org', is_top_domain=False)
 
         api.add_organization(ctx, 'LibreSoft')
 
@@ -237,3 +237,43 @@ def test_not_found_individual(self):
         recs = list(recommend_affiliations('FFFFFFFFFFFFFFFFFF'))
 
         self.assertListEqual(recs, [])
+
+    def test_top_domain(self):
+        """Check if recommendations are generated for subdomains only
+        when the domain is marked as top"""
+
+        ctx = SortingHatContext(self.user)
+
+        jsmith = api.add_identity(ctx,
+                                  source='scm',
+                                  email='jsmith@bitergia.org',
+                                  name='John Smith',
+                                  username='jsmith')
+        api.add_identity(ctx,
+                         source='scm',
+                         email='jsmith@subdomain.example.com',
+                         uuid=jsmith.uuid)
+
+        jroe = api.add_identity(ctx,
+                                source='scm',
+                                email='jroe@example.com',
+                                name='Jane Roe',
+                                username='jroe')
+        api.add_identity(ctx,
+                         source='scm',
+                         email='jroe@subdomain.bitergia.org',
+                         uuid=jroe.uuid)
+
+        # Test
+        uuids = [jsmith.uuid, jroe.uuid]
+        recs = list(recommend_affiliations(uuids))
+
+        self.assertEqual(len(recs), 2)
+
+        rec = recs[0]
+        self.assertEqual(rec[0], jsmith.uuid)
+        self.assertListEqual(rec[1], ['Bitergia', 'Example'])
+
+        rec = recs[1]
+        self.assertEqual(rec[0], jroe.uuid)
+        self.assertListEqual(rec[1], ['Example'])