diff --git a/data/model/legacy.py b/data/model/legacy.py index 1997ec512..5cebbaac6 100644 --- a/data/model/legacy.py +++ b/data/model/legacy.py @@ -679,14 +679,19 @@ def get_user_or_org_by_customer_id(customer_id): except User.DoesNotExist: return None -def get_matching_entities(entity_prefix): - matching_user_orgs = ((User.username ** (entity_prefix + '%')) & (User.robot == False)) - matching_robots = ((User.username ** ('%+%' + entity_prefix + '%')) & (User.robot == True)) +def get_matching_user_namespaces(namespace_prefix, username, limit=10): + query = (Repository + .select() + .join(Namespace, on=(Repository.namespace_user == Namespace.id)) + .switch(Repository) + .join(Visibility) + .switch(Repository) + .join(RepositoryPermission, JOIN_LEFT_OUTER) + .where(Namespace.username ** (namespace_prefix + '%')) + .group_by(Repository.namespace_user, Repository) + .limit(limit)) - query = (User.select() - .where(matching_user_orgs | matching_robots)) - - return query + return [r.namespace_user for r in _filter_to_repos_for_user(query, username)] def get_matching_user_teams(team_prefix, user, limit=10): query = (Team.select() @@ -699,6 +704,23 @@ def get_matching_user_teams(team_prefix, user, limit=10): return query + +def get_matching_robots(name_prefix, username, limit=10): + admined_orgs = (get_user_organizations(username) + .switch(Team) + .join(TeamRole) + .where(TeamRole.name == 'admin')) + + prefix_checks = False + + for org in admined_orgs: + prefix_checks = prefix_checks | (User.username ** (org.username + '+' + name_prefix + '%')) + + prefix_checks = prefix_checks | (User.username ** (username + '+' + name_prefix + '%')) + + return User.select().where(prefix_checks).limit(limit) + + def get_matching_admined_teams(team_prefix, user, limit=10): admined_orgs = (get_user_organizations(user.username) .switch(Team) diff --git a/endpoints/api/search.py b/endpoints/api/search.py index 94472b775..5262fdad5 100644 --- a/endpoints/api/search.py +++ b/endpoints/api/search.py @@ -227,22 +227,18 @@ def conduct_repo_search(username, query, results): }) -def conduct_entity_search(username, query, results): - """ Finds matching users, robots and organizations. """ - matching_entities = model.get_matching_entities(query) - entity_count = 0 +def conduct_namespace_search(username, query, results): + """ Finds matching users and organizations. """ + matching_entities = model.get_matching_user_namespaces(query, username, limit=5) for entity in matching_entities: - # If the entity is a robot, filter it to only match those that are under the current - # user or can be administered by the organization. - if entity.robot: - orgname = parse_robot_username(entity.username)[0] - if not AdministerOrganizationPermission(orgname).can() and not orgname == username: - continue - results.append(search_entity_view(username, entity)) - entity_count = entity_count + 1 - if entity_count >= 5: - break + + +def conduct_robot_search(username, query, results): + """ Finds matching robot accounts. """ + matching_robots = model.get_matching_robots(query, username, limit=5) + for robot in matching_robots: + results.append(search_entity_view(username, robot)) @resource('/v1/find/all') @@ -269,11 +265,14 @@ class ConductSearch(ApiResource): conduct_team_search(username, query, encountered_teams, results) conduct_admined_team_search(username, query, encountered_teams, results) + # Search for robot accounts. + conduct_robot_search(username, query, results) + # Search for repos. conduct_repo_search(username, query, results) - # Search for users, orgs and robots. - conduct_entity_search(username, query, results) + # Search for users and orgs. + conduct_namespace_search(username, query, results) # Modify the results' scores via how close the query term is to each result's name. for result in results: diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 7e0b2e904..e994fe205 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -479,9 +479,7 @@ class TestConductSearch(ApiTestCase): json = self.getJsonResponse(ConductSearch, params=dict(query='read')) - self.assertEquals(1, len(json['results'])) - self.assertEquals(json['results'][0]['kind'], 'user') - self.assertEquals(json['results'][0]['name'], 'reader') + self.assertEquals(0, len(json['results'])) json = self.getJsonResponse(ConductSearch, params=dict(query='owners')) @@ -493,9 +491,7 @@ class TestConductSearch(ApiTestCase): json = self.getJsonResponse(ConductSearch, params=dict(query='read')) - self.assertEquals(1, len(json['results'])) - self.assertEquals(json['results'][0]['kind'], 'user') - self.assertEquals(json['results'][0]['name'], 'reader') + self.assertEquals(0, len(json['results'])) json = self.getJsonResponse(ConductSearch, params=dict(query='public'))