Revert "Remove old search API which is no longer in use"
This commit is contained in:
parent
e441a58a8d
commit
fe2cd240bc
5 changed files with 160 additions and 5 deletions
|
@ -181,6 +181,12 @@ def get_matching_admined_teams(team_prefix, user_obj, limit=10):
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
def get_matching_teams(team_prefix, organization):
|
||||||
|
team_prefix_search = _basequery.prefix_search(Team.name, team_prefix)
|
||||||
|
query = Team.select().where(team_prefix_search, Team.organization == organization)
|
||||||
|
return query.limit(10)
|
||||||
|
|
||||||
|
|
||||||
def get_teams_within_org(organization):
|
def get_teams_within_org(organization):
|
||||||
return Team.select().where(Team.organization == organization)
|
return Team.select().where(Team.organization == organization)
|
||||||
|
|
||||||
|
|
|
@ -513,6 +513,41 @@ def get_matching_user_namespaces(namespace_prefix, username, limit=10):
|
||||||
|
|
||||||
return _basequery.filter_to_repos_for_user(base_query, username).limit(limit)
|
return _basequery.filter_to_repos_for_user(base_query, username).limit(limit)
|
||||||
|
|
||||||
|
def get_matching_users(username_prefix, robot_namespace=None,
|
||||||
|
organization=None):
|
||||||
|
user_search = _basequery.prefix_search(User.username, username_prefix)
|
||||||
|
direct_user_query = (user_search & (User.organization == False) & (User.robot == False))
|
||||||
|
|
||||||
|
if robot_namespace:
|
||||||
|
robot_prefix = format_robot_username(robot_namespace, username_prefix)
|
||||||
|
robot_search = _basequery.prefix_search(User.username, robot_prefix)
|
||||||
|
direct_user_query = (direct_user_query | (robot_search & (User.robot == True)))
|
||||||
|
|
||||||
|
query = (User
|
||||||
|
.select(User.username, User.email, User.robot)
|
||||||
|
.group_by(User.username, User.email, User.robot)
|
||||||
|
.where(direct_user_query))
|
||||||
|
|
||||||
|
if organization:
|
||||||
|
query = (query
|
||||||
|
.select(User.username, User.email, User.robot, fn.Sum(Team.id))
|
||||||
|
.join(TeamMember, JOIN_LEFT_OUTER)
|
||||||
|
.join(Team, JOIN_LEFT_OUTER, on=((Team.id == TeamMember.team) &
|
||||||
|
(Team.organization == organization))))
|
||||||
|
|
||||||
|
class MatchingUserResult(object):
|
||||||
|
def __init__(self, *args):
|
||||||
|
self.username = args[0]
|
||||||
|
self.email = args[1]
|
||||||
|
self.robot = args[2]
|
||||||
|
|
||||||
|
if organization:
|
||||||
|
self.is_org_member = (args[3] != None)
|
||||||
|
else:
|
||||||
|
self.is_org_member = None
|
||||||
|
|
||||||
|
return (MatchingUserResult(*args) for args in query.tuples().limit(10))
|
||||||
|
|
||||||
|
|
||||||
def verify_user(username_or_email, password):
|
def verify_user(username_or_email, password):
|
||||||
# Make sure we didn't get any unicode for the username.
|
# Make sure we didn't get any unicode for the username.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
""" Conduct searches against all registry context. """
|
""" Conduct searches against all registry context. """
|
||||||
|
|
||||||
from endpoints.api import (ApiResource, parse_args, query_param, nickname, resource,
|
from endpoints.api import (ApiResource, parse_args, query_param, truthy_bool, nickname, resource,
|
||||||
require_scope, path_param)
|
require_scope, path_param)
|
||||||
from data import model
|
from data import model
|
||||||
from auth.permissions import (OrganizationMemberPermission, ReadRepositoryPermission,
|
from auth.permissions import (OrganizationMemberPermission, ReadRepositoryPermission,
|
||||||
|
@ -15,6 +15,86 @@ from util.names import parse_robot_username
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
@resource('/v1/entities/<prefix>')
|
||||||
|
class EntitySearch(ApiResource):
|
||||||
|
""" Resource for searching entities. """
|
||||||
|
@path_param('prefix', 'The prefix of the entities being looked up')
|
||||||
|
@parse_args()
|
||||||
|
@query_param('namespace', 'Namespace to use when querying for org entities.', type=str,
|
||||||
|
default='')
|
||||||
|
@query_param('includeTeams', 'Whether to include team names.', type=truthy_bool, default=False)
|
||||||
|
@query_param('includeOrgs', 'Whether to include orgs names.', type=truthy_bool, default=False)
|
||||||
|
@nickname('getMatchingEntities')
|
||||||
|
def get(self, prefix, parsed_args):
|
||||||
|
""" Get a list of entities that match the specified prefix. """
|
||||||
|
teams = []
|
||||||
|
org_data = []
|
||||||
|
|
||||||
|
namespace_name = parsed_args['namespace']
|
||||||
|
robot_namespace = None
|
||||||
|
organization = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
organization = model.organization.get_organization(namespace_name)
|
||||||
|
|
||||||
|
# namespace name was an org
|
||||||
|
permission = OrganizationMemberPermission(namespace_name)
|
||||||
|
if permission.can():
|
||||||
|
robot_namespace = namespace_name
|
||||||
|
|
||||||
|
if parsed_args['includeTeams']:
|
||||||
|
teams = model.team.get_matching_teams(prefix, organization)
|
||||||
|
|
||||||
|
if (parsed_args['includeOrgs'] and AdministerOrganizationPermission(namespace_name) and
|
||||||
|
namespace_name.startswith(prefix)):
|
||||||
|
org_data = [{
|
||||||
|
'name': namespace_name,
|
||||||
|
'kind': 'org',
|
||||||
|
'is_org_member': True,
|
||||||
|
'avatar': avatar.get_data_for_org(organization),
|
||||||
|
}]
|
||||||
|
|
||||||
|
except model.organization.InvalidOrganizationException:
|
||||||
|
# namespace name was a user
|
||||||
|
user = get_authenticated_user()
|
||||||
|
if user and user.username == namespace_name:
|
||||||
|
# Check if there is admin user permissions (login only)
|
||||||
|
admin_permission = UserAdminPermission(user.username)
|
||||||
|
if admin_permission.can():
|
||||||
|
robot_namespace = namespace_name
|
||||||
|
|
||||||
|
users = model.user.get_matching_users(prefix, robot_namespace, organization)
|
||||||
|
|
||||||
|
def entity_team_view(team):
|
||||||
|
result = {
|
||||||
|
'name': team.name,
|
||||||
|
'kind': 'team',
|
||||||
|
'is_org_member': True,
|
||||||
|
'avatar': avatar.get_data_for_team(team)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
def user_view(user):
|
||||||
|
user_json = {
|
||||||
|
'name': user.username,
|
||||||
|
'kind': 'user',
|
||||||
|
'is_robot': user.robot,
|
||||||
|
'avatar': avatar.get_data_for_user(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization is not None:
|
||||||
|
user_json['is_org_member'] = user.robot or user.is_org_member
|
||||||
|
|
||||||
|
return user_json
|
||||||
|
|
||||||
|
team_data = [entity_team_view(team) for team in teams]
|
||||||
|
user_data = [user_view(user) for user in users]
|
||||||
|
|
||||||
|
return {
|
||||||
|
'results': team_data + user_data + org_data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def search_entity_view(username, entity, get_short_name=None):
|
def search_entity_view(username, entity, get_short_name=None):
|
||||||
kind = 'user'
|
kind = 'user'
|
||||||
avatar_data = avatar.get_data_for_user(entity)
|
avatar_data = avatar.get_data_for_user(entity)
|
||||||
|
|
|
@ -12,7 +12,7 @@ from endpoints.api import api_bp, api
|
||||||
|
|
||||||
from endpoints.api.team import TeamMember, TeamMemberList, OrganizationTeam, TeamMemberInvite
|
from endpoints.api.team import TeamMember, TeamMemberList, OrganizationTeam, TeamMemberInvite
|
||||||
from endpoints.api.tag import RepositoryTagImages, RepositoryTag, ListRepositoryTags, RevertTag
|
from endpoints.api.tag import RepositoryTagImages, RepositoryTag, ListRepositoryTags, RevertTag
|
||||||
from endpoints.api.search import ConductSearch
|
from endpoints.api.search import EntitySearch
|
||||||
from endpoints.api.image import RepositoryImage, RepositoryImageList
|
from endpoints.api.image import RepositoryImage, RepositoryImageList
|
||||||
from endpoints.api.build import (FileDropResource, RepositoryBuildStatus, RepositoryBuildLogs,
|
from endpoints.api.build import (FileDropResource, RepositoryBuildStatus, RepositoryBuildLogs,
|
||||||
RepositoryBuildList, RepositoryBuildResource)
|
RepositoryBuildList, RepositoryBuildResource)
|
||||||
|
@ -3672,10 +3672,10 @@ class TestRepositoryBuynlargeOrgrepo(ApiTestCase):
|
||||||
self._run_test('DELETE', 204, 'devtable', None)
|
self._run_test('DELETE', 204, 'devtable', None)
|
||||||
|
|
||||||
|
|
||||||
class TestConductSearchR9nz(ApiTestCase):
|
class TestEntitySearchR9nz(ApiTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
ApiTestCase.setUp(self)
|
ApiTestCase.setUp(self)
|
||||||
self._set_url(ConductSearch, prefix="R9NZ")
|
self._set_url(EntitySearch, prefix="R9NZ")
|
||||||
|
|
||||||
def test_get_anonymous(self):
|
def test_get_anonymous(self):
|
||||||
self._run_test('GET', 200, None, None)
|
self._run_test('GET', 200, None, None)
|
||||||
|
|
|
@ -24,7 +24,7 @@ from data.database import RepositoryActionCount
|
||||||
|
|
||||||
from endpoints.api.team import TeamMember, TeamMemberList, TeamMemberInvite, OrganizationTeam
|
from endpoints.api.team import TeamMember, TeamMemberList, TeamMemberInvite, OrganizationTeam
|
||||||
from endpoints.api.tag import RepositoryTagImages, RepositoryTag, RevertTag, ListRepositoryTags
|
from endpoints.api.tag import RepositoryTagImages, RepositoryTag, RevertTag, ListRepositoryTags
|
||||||
from endpoints.api.search import ConductSearch
|
from endpoints.api.search import EntitySearch, ConductSearch
|
||||||
from endpoints.api.image import RepositoryImage, RepositoryImageList
|
from endpoints.api.image import RepositoryImage, RepositoryImageList
|
||||||
from endpoints.api.build import RepositoryBuildStatus, RepositoryBuildList, RepositoryBuildResource
|
from endpoints.api.build import RepositoryBuildStatus, RepositoryBuildList, RepositoryBuildResource
|
||||||
from endpoints.api.robot import (UserRobotList, OrgRobot, OrgRobotList, UserRobot,
|
from endpoints.api.robot import (UserRobotList, OrgRobot, OrgRobotList, UserRobot,
|
||||||
|
@ -668,6 +668,40 @@ class TestConductSearch(ApiTestCase):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetMatchingEntities(ApiTestCase):
|
||||||
|
def test_notinorg(self):
|
||||||
|
self.login(NO_ACCESS_USER)
|
||||||
|
|
||||||
|
json = self.getJsonResponse(EntitySearch,
|
||||||
|
params=dict(prefix='o', namespace=ORGANIZATION,
|
||||||
|
includeTeams='true'))
|
||||||
|
|
||||||
|
names = set([r['name'] for r in json['results']])
|
||||||
|
assert 'outsideorg' in names
|
||||||
|
assert not 'owners' in names
|
||||||
|
|
||||||
|
def test_inorg(self):
|
||||||
|
self.login(ADMIN_ACCESS_USER)
|
||||||
|
|
||||||
|
json = self.getJsonResponse(EntitySearch,
|
||||||
|
params=dict(prefix='o', namespace=ORGANIZATION,
|
||||||
|
includeTeams='true'))
|
||||||
|
|
||||||
|
names = set([r['name'] for r in json['results']])
|
||||||
|
assert 'outsideorg' in names
|
||||||
|
assert 'owners' in names
|
||||||
|
|
||||||
|
def test_inorg_withorgs(self):
|
||||||
|
self.login(ADMIN_ACCESS_USER)
|
||||||
|
|
||||||
|
json = self.getJsonResponse(EntitySearch,
|
||||||
|
params=dict(prefix=ORGANIZATION[0], namespace=ORGANIZATION,
|
||||||
|
includeOrgs='true'))
|
||||||
|
|
||||||
|
names = set([r['name'] for r in json['results']])
|
||||||
|
assert ORGANIZATION in names
|
||||||
|
|
||||||
|
|
||||||
class TestCreateOrganization(ApiTestCase):
|
class TestCreateOrganization(ApiTestCase):
|
||||||
def test_existinguser(self):
|
def test_existinguser(self):
|
||||||
self.login(ADMIN_ACCESS_USER)
|
self.login(ADMIN_ACCESS_USER)
|
||||||
|
|
Reference in a new issue