Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ interface ApiKeysTableState {
filters: QueryFilters;
}

type KueryNode = any;

const DEFAULT_TABLE_STATE = {
query: EuiSearchBar.Query.MATCH_ALL,
sort: {
Expand All @@ -54,6 +56,8 @@ const DEFAULT_TABLE_STATE = {
filters: {},
};

const PLUS_SIGN_REGEX = /[+]/g;

export const APIKeysGridPage: FunctionComponent = () => {
const { services } = useKibana<CoreStart>();
const history = useHistory();
Expand All @@ -68,6 +72,41 @@ export const APIKeysGridPage: FunctionComponent = () => {
const [state, queryApiKeysAndAggregations] = useAsyncFn((tableStateArgs: ApiKeysTableState) => {
const queryContainer = EuiSearchBar.Query.toESQuery(tableStateArgs.query);

// Enhance the query to support partial matches for name and owner field
if (queryContainer.bool?.must) {
queryContainer.bool.must = queryContainer.bool.must.map((clause: KueryNode) => {
if (clause.simple_query_string) {
// Add wildcard to support partial matches
const rawQuery = String(clause.simple_query_string.query ?? '');
const wildCardQuery = rawQuery.replace(PLUS_SIGN_REGEX, '');
return {
bool: {
should: [
clause,
{
wildcard: {
name: {
value: `*${wildCardQuery}*`,
case_insensitive: true,
},
},
},
{
wildcard: {
username: {
value: `*${wildCardQuery}*`,
case_insensitive: true,
},
},
},
],
},
};
}
return clause;
});
}

const requestBody = {
...tableStateArgs,
query: queryContainer,
Expand Down
11 changes: 8 additions & 3 deletions x-pack/platform/test/functional/apps/api_keys/home_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,15 +483,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
username: 'elastic',
password: 'changeme',
});

await pageObjects.common.navigateToApp('apiKeys');
});

after(async () => {
await security.testUser.restoreDefaults();
await clearAllApiKeys(es, log);
});

beforeEach(async () => {
await pageObjects.common.navigateToApp('apiKeys');
});

it('active/expired filter buttons work as expected', async () => {
await pageObjects.apiKeys.clickExpiryFilters('active');
await ensureApiKeysExist(['my api key', 'Alerting: Managed', 'test_cross_cluster']);
Expand Down Expand Up @@ -539,13 +541,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await ensureApiKeysExist(['my api key', 'Alerting: Managed', 'test_cross_cluster']);
});

it.skip('search bar works as expected', async () => {
it('search bar works as expected', async () => {
await pageObjects.apiKeys.setSearchBarValue('test_user_api_key');

await ensureApiKeysExist(['test_user_api_key']);

await pageObjects.apiKeys.setSearchBarValue('"my api key"');
await ensureApiKeysExist(['my api key']);

await pageObjects.apiKeys.setSearchBarValue('"api"');
await ensureApiKeysExist(['my api key']);
});
});
});
Expand Down