Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change API token index actions to use action listeners and limit to 100 tokens outstanding #5147

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.opensearch.client.node.NodeClient;
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.settings.Settings;
Expand All @@ -48,6 +47,7 @@
import org.opensearch.security.ssl.transport.PrincipalExtractor;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.threadpool.ThreadPool;
import org.opensearch.transport.client.node.NodeClient;

import static org.opensearch.rest.RestRequest.Method.DELETE;
import static org.opensearch.rest.RestRequest.Method.GET;
Expand Down Expand Up @@ -146,30 +146,32 @@

private RestChannelConsumer handleGet(RestRequest request, NodeClient client) {
return channel -> {
final XContentBuilder builder = channel.newBuilder();
BytesRestResponse response;
try {
Map<String, ApiToken> tokens = apiTokenRepository.getApiTokens();

builder.startArray();
for (ApiToken token : tokens.values()) {
builder.startObject();
builder.field(NAME_FIELD, token.getName());
builder.field(CREATION_TIME_FIELD, token.getCreationTime().toEpochMilli());
builder.field(EXPIRATION_FIELD, token.getExpiration());
builder.field(CLUSTER_PERMISSIONS_FIELD, token.getClusterPermissions());
builder.field(INDEX_PERMISSIONS_FIELD, token.getIndexPermissions());
builder.endObject();
apiTokenRepository.getApiTokens(ActionListener.wrap(tokens -> {

Check warning on line 149 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L149

Added line #L149 was not covered by tests
try {
XContentBuilder builder = channel.newBuilder();
builder.startArray();

Check warning on line 152 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L151-L152

Added lines #L151 - L152 were not covered by tests
for (ApiToken token : tokens.values()) {
builder.startObject();
builder.field(NAME_FIELD, token.getName());
builder.field(CREATION_TIME_FIELD, token.getCreationTime().toEpochMilli());
builder.field(EXPIRATION_FIELD, token.getExpiration());
builder.field(CLUSTER_PERMISSIONS_FIELD, token.getClusterPermissions());
builder.field(INDEX_PERMISSIONS_FIELD, token.getIndexPermissions());
builder.endObject();
}
builder.endArray();

Check warning on line 162 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L154-L162

Added lines #L154 - L162 were not covered by tests

BytesRestResponse response = new BytesRestResponse(RestStatus.OK, builder);
builder.close();
channel.sendResponse(response);
} catch (final Exception exception) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, exception.getMessage());

Check warning on line 168 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L164-L168

Added lines #L164 - L168 were not covered by tests
}
builder.endArray();
}, exception -> {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, exception.getMessage());

Check warning on line 171 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L170-L171

Added lines #L170 - L171 were not covered by tests

}));

Check warning on line 173 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L173

Added line #L173 was not covered by tests

response = new BytesRestResponse(RestStatus.OK, builder);
} catch (final Exception exception) {
builder.startObject().field("error", exception.getMessage()).endObject();
response = new BytesRestResponse(RestStatus.INTERNAL_SERVER_ERROR, builder);
}
builder.close();
channel.sendResponse(response);
};
}

Expand All @@ -181,39 +183,66 @@

List<String> clusterPermissions = extractClusterPermissions(requestBody);
List<ApiToken.IndexPermission> indexPermissions = extractIndexPermissions(requestBody);

String token = apiTokenRepository.createApiToken(
(String) requestBody.get(NAME_FIELD),
clusterPermissions,
indexPermissions,
(Long) requestBody.getOrDefault(EXPIRATION_FIELD, Instant.now().toEpochMilli() + TimeUnit.DAYS.toMillis(30))
String name = (String) requestBody.get(NAME_FIELD);
long expiration = (Long) requestBody.getOrDefault(

Check warning on line 187 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L186-L187

Added lines #L186 - L187 were not covered by tests
EXPIRATION_FIELD,
Instant.now().toEpochMilli() + TimeUnit.DAYS.toMillis(30)

Check warning on line 189 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L189

Added line #L189 was not covered by tests
);

// Then trigger the update action
ApiTokenUpdateRequest updateRequest = new ApiTokenUpdateRequest();
client.execute(ApiTokenUpdateAction.INSTANCE, updateRequest, new ActionListener<ApiTokenUpdateResponse>() {
@Override
public void onResponse(ApiTokenUpdateResponse updateResponse) {
try {
XContentBuilder builder = channel.newBuilder();
builder.startObject();
builder.field("Api Token: ", token);
builder.endObject();

BytesRestResponse response = new BytesRestResponse(RestStatus.OK, builder);
channel.sendResponse(response);
} catch (IOException e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to send response after token creation");
}
// First check token count
apiTokenRepository.getTokenCount(ActionListener.wrap(tokenCount -> {

Check warning on line 193 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L193

Added line #L193 was not covered by tests
if (tokenCount >= 100) {
sendErrorResponse(

Check warning on line 195 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L195

Added line #L195 was not covered by tests
channel,
RestStatus.TOO_MANY_REQUESTS,
"Maximum limit of 100 API tokens reached. Please delete existing tokens before creating new ones."
);
return;

Check warning on line 200 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L200

Added line #L200 was not covered by tests
}

@Override
public void onFailure(Exception e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to propagate token creation");
}
});
} catch (final Exception exception) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, exception.getMessage());
// If count is ok, create the token
apiTokenRepository.createApiToken(name, clusterPermissions, indexPermissions, expiration, ActionListener.wrap(token -> {

Check warning on line 204 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L204

Added line #L204 was not covered by tests
// After successful creation, trigger the update action
ApiTokenUpdateRequest updateRequest = new ApiTokenUpdateRequest();
client.execute(ApiTokenUpdateAction.INSTANCE, updateRequest, ActionListener.wrap(updateResponse -> {

Check warning on line 207 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L206-L207

Added lines #L206 - L207 were not covered by tests
try {
XContentBuilder builder = channel.newBuilder();
builder.startObject();
builder.field("Api Token: ", token);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just have the field name be token. No need to include the colon here because this gets serialized to json and will get included.

builder.endObject();
channel.sendResponse(new BytesRestResponse(RestStatus.OK, builder));
builder.close();
} catch (IOException e) {
sendErrorResponse(

Check warning on line 216 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L209-L216

Added lines #L209 - L216 were not covered by tests
channel,
RestStatus.INTERNAL_SERVER_ERROR,
"Failed to send response after token creation"
);
}
},
updateException -> sendErrorResponse(

Check warning on line 223 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L221-L223

Added lines #L221 - L223 were not covered by tests
channel,
RestStatus.INTERNAL_SERVER_ERROR,
"Failed to propagate token creation: " + updateException.getMessage()

Check warning on line 226 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L226

Added line #L226 was not covered by tests
)
));
},
createException -> sendErrorResponse(

Check warning on line 230 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L229-L230

Added lines #L229 - L230 were not covered by tests
channel,
RestStatus.INTERNAL_SERVER_ERROR,
"Failed to create token: " + createException.getMessage()

Check warning on line 233 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L233

Added line #L233 was not covered by tests
)
));
},
countException -> sendErrorResponse(

Check warning on line 237 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L236-L237

Added lines #L236 - L237 were not covered by tests
channel,
RestStatus.INTERNAL_SERVER_ERROR,
"Failed to get token count: " + countException.getMessage()

Check warning on line 240 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L240

Added line #L240 was not covered by tests
)
));

} catch (Exception e) {
sendErrorResponse(channel, RestStatus.BAD_REQUEST, "Invalid request: " + e.getMessage());

Check warning on line 245 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L244-L245

Added lines #L244 - L245 were not covered by tests
}
};
}
Expand Down Expand Up @@ -303,32 +332,44 @@
final Map<String, Object> requestBody = request.contentOrSourceParamParser().map();

validateRequestParameters(requestBody);
apiTokenRepository.deleteApiToken((String) requestBody.get(NAME_FIELD));

ApiTokenUpdateRequest updateRequest = new ApiTokenUpdateRequest();
client.execute(ApiTokenUpdateAction.INSTANCE, updateRequest, new ActionListener<ApiTokenUpdateResponse>() {
@Override
public void onResponse(ApiTokenUpdateResponse updateResponse) {
try {
XContentBuilder builder = channel.newBuilder();
builder.startObject();
builder.field("message", "token " + requestBody.get(NAME_FIELD) + " deleted successfully.");
builder.endObject();

BytesRestResponse response = new BytesRestResponse(RestStatus.OK, builder);
channel.sendResponse(response);
} catch (Exception e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to send response after token update");
}
apiTokenRepository.deleteApiToken((String) requestBody.get(NAME_FIELD), ActionListener.wrap(ignored -> {

Check warning on line 335 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L335

Added line #L335 was not covered by tests
try {
ApiTokenUpdateRequest updateRequest = new ApiTokenUpdateRequest();
client.execute(ApiTokenUpdateAction.INSTANCE, updateRequest, new ActionListener<ApiTokenUpdateResponse>() {

Check warning on line 338 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L337-L338

Added lines #L337 - L338 were not covered by tests
@Override
public void onResponse(ApiTokenUpdateResponse updateResponse) {
try {
XContentBuilder builder = channel.newBuilder();
builder.startObject();
builder.field("message", "Token " + requestBody.get(NAME_FIELD) + " deleted successfully.");
builder.endObject();

Check warning on line 345 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L342-L345

Added lines #L342 - L345 were not covered by tests

BytesRestResponse response = new BytesRestResponse(RestStatus.OK, builder);
channel.sendResponse(response);
} catch (Exception e) {
sendErrorResponse(

Check warning on line 350 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L347-L350

Added lines #L347 - L350 were not covered by tests
channel,
RestStatus.INTERNAL_SERVER_ERROR,
"Failed to send response after token update"
);
}
}

Check warning on line 356 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L355-L356

Added lines #L355 - L356 were not covered by tests

@Override
public void onFailure(Exception e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to propagate token deletion");
}

Check warning on line 361 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L360-L361

Added lines #L360 - L361 were not covered by tests
});
} catch (IOException e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to build success response: " + e.getMessage());

Check warning on line 364 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L363-L364

Added lines #L363 - L364 were not covered by tests
}

@Override
public void onFailure(Exception e) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, "Failed to propagate token deletion");
}, exception -> {
RestStatus status = RestStatus.INTERNAL_SERVER_ERROR;

Check warning on line 367 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L366-L367

Added lines #L366 - L367 were not covered by tests
if (exception instanceof ApiTokenException) {
status = RestStatus.NOT_FOUND;

Check warning on line 369 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L369

Added line #L369 was not covered by tests
}
});
} catch (final ApiTokenException exception) {
sendErrorResponse(channel, RestStatus.NOT_FOUND, exception.getMessage());
sendErrorResponse(channel, status, exception.getMessage());
}));

Check warning on line 372 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenAction.java#L371-L372

Added lines #L371 - L372 were not covered by tests
} catch (final Exception exception) {
sendErrorResponse(channel, RestStatus.INTERNAL_SERVER_ERROR, exception.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@

import org.opensearch.action.admin.indices.create.CreateIndexRequest;
import org.opensearch.action.index.IndexRequest;
import org.opensearch.action.index.IndexResponse;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.client.Client;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.xcontent.XContentFactory;
import org.opensearch.common.xcontent.XContentType;
Expand All @@ -35,12 +32,12 @@
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.index.query.QueryBuilders;
import org.opensearch.index.reindex.BulkByScrollResponse;
import org.opensearch.index.reindex.DeleteByQueryAction;
import org.opensearch.index.reindex.DeleteByQueryRequest;
import org.opensearch.search.SearchHit;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.transport.client.Client;

import static org.opensearch.security.action.apitokens.ApiToken.NAME_FIELD;

Expand All @@ -55,66 +52,69 @@
this.clusterService = clusterService;
}

public void indexTokenMetadata(ApiToken token) {
public void indexTokenMetadata(ApiToken token, ActionListener<Void> listener) {
try {

XContentBuilder builder = XContentFactory.jsonBuilder();
String jsonString = token.toXContent(builder, ToXContent.EMPTY_PARAMS).toString();

IndexRequest request = new IndexRequest(ConfigConstants.OPENSEARCH_API_TOKENS_INDEX).source(jsonString, XContentType.JSON);

ActionListener<IndexResponse> irListener = ActionListener.wrap(idxResponse -> {
client.index(request, ActionListener.wrap(indexResponse -> {
LOGGER.info("Created {} entry.", ConfigConstants.OPENSEARCH_API_TOKENS_INDEX);
}, (failResponse) -> {
LOGGER.error(failResponse.getMessage());
listener.onResponse(null);
}, exception -> {
LOGGER.error(exception.getMessage());

Check warning on line 66 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java#L66

Added line #L66 was not covered by tests
LOGGER.info("Failed to create {} entry.", ConfigConstants.OPENSEARCH_API_TOKENS_INDEX);
});
client.index(request, irListener);
listener.onFailure(exception);
}));

Check warning on line 69 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java#L68-L69

Added lines #L68 - L69 were not covered by tests
} catch (IOException e) {
throw new RuntimeException(e);
}

}

public void deleteToken(String name) throws ApiTokenException {
public void deleteToken(String name, ActionListener<Void> listener) {
DeleteByQueryRequest request = new DeleteByQueryRequest(ConfigConstants.OPENSEARCH_API_TOKENS_INDEX).setQuery(
QueryBuilders.matchQuery(NAME_FIELD, name)
).setRefresh(true);

BulkByScrollResponse response = client.execute(DeleteByQueryAction.INSTANCE, request).actionGet();

long deletedDocs = response.getDeleted();

if (deletedDocs == 0) {
throw new ApiTokenException("No token found with name " + name);
}
client.execute(DeleteByQueryAction.INSTANCE, request, ActionListener.wrap(response -> {
long deletedDocs = response.getDeleted();
if (deletedDocs == 0) {
listener.onFailure(new ApiTokenException("No token found with name " + name));
} else {
listener.onResponse(null);
}
}, exception -> listener.onFailure(exception)));
}

public Map<String, ApiToken> getTokenMetadatas() {
public void getTokenMetadatas(ActionListener<Map<String, ApiToken>> listener) {
try {
SearchRequest searchRequest = new SearchRequest(ConfigConstants.OPENSEARCH_API_TOKENS_INDEX);
searchRequest.source(new SearchSourceBuilder());

SearchResponse response = client.search(searchRequest).actionGet();

Map<String, ApiToken> tokens = new HashMap<>();
for (SearchHit hit : response.getHits().getHits()) {
try (
XContentParser parser = XContentType.JSON.xContent()
.createParser(
NamedXContentRegistry.EMPTY,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
hit.getSourceRef().streamInput()
)
) {

ApiToken token = ApiToken.fromXContent(parser);
tokens.put(token.getName(), token);
client.search(searchRequest, ActionListener.wrap(response -> {
try {
Map<String, ApiToken> tokens = new HashMap<>();
for (SearchHit hit : response.getHits().getHits()) {
try (
XContentParser parser = XContentType.JSON.xContent()
.createParser(
NamedXContentRegistry.EMPTY,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
hit.getSourceRef().streamInput()
)
) {
ApiToken token = ApiToken.fromXContent(parser);
tokens.put(token.getName(), token);
}
}
listener.onResponse(tokens);
} catch (IOException e) {
listener.onFailure(e);

Check warning on line 113 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java#L112-L113

Added lines #L112 - L113 were not covered by tests
}
}
return tokens;
} catch (IOException e) {
throw new RuntimeException(e);
}, listener::onFailure));
} catch (Exception e) {
listener.onFailure(e);

Check warning on line 117 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexHandler.java#L116-L117

Added lines #L116 - L117 were not covered by tests
}
}

Expand Down
Loading
Loading