/** * Takes a list of results (in json value wrapped form) and calls the handleResource for each on * the handler. * * @param resultList the list of results, possibly with id and rev entries * @param handler the handle to set the results on */ private void handleQueryResultList(JsonValue resultList, QueryResourceHandler handler) { for (JsonValue entry : resultList) { // These can end up null String id = null; String rev = null; if (entry.isMap()) { id = entry.get(ResourceResponse.FIELD_ID).asString(); rev = entry.get(ResourceResponse.FIELD_REVISION).asString(); } handler.handleResource(newResourceResponse(id, rev, entry)); } }
/** * Allows users to query OAuth2 applications that they have given their consent access to and that * have active access and/or refresh tokens. * * <p>Applications consist of an id, a name (the client id), a set of scopes and an expiry time. * The scopes field is the union of the scopes of the individual access/refresh tokens. The expiry * time is the time when the last access/refresh token will expire, or null if the server is * configured to allow tokens to be refreshed indefinitely. * * @param context The request context. * @param queryHandler The query handler. * @param request Unused but necessary for used of the {@link @Query} annotation. * @return A promise of a query response. */ @Query public Promise<QueryResponse, ResourceException> query( Context context, QueryResourceHandler queryHandler, QueryRequest request) { String userId = contextHelper.getUserId(context); String realm = contextHelper.getRealm(context); try { QueryFilter<CoreTokenField> queryFilter = getQueryFilter(userId, realm); JsonValue tokens = tokenStore.query(queryFilter); Map<String, Set<JsonValue>> applicationTokensMap = new HashMap<>(); for (JsonValue token : tokens) { String clientId = getAttributeValue(token, CLIENT_ID.getOAuthField()); Set<JsonValue> applicationTokens = applicationTokensMap.get(clientId); if (applicationTokens == null) { applicationTokens = new HashSet<>(); applicationTokensMap.put(clientId, applicationTokens); } applicationTokens.add(token); } for (Map.Entry<String, Set<JsonValue>> applicationTokens : applicationTokensMap.entrySet()) { ResourceResponse resource = getResourceResponse(context, applicationTokens.getKey(), applicationTokens.getValue()); queryHandler.handleResource(resource); } return Promises.newResultPromise(Responses.newQueryResponse()); } catch (CoreTokenException | ServerException | InvalidClientException | NotFoundException e) { debug.message("Failed to query OAuth2 clients for user {}", userId, e); return new InternalServerErrorException(e).asPromise(); } catch (InternalServerErrorException e) { debug.message("Failed to query OAuth2 clients for user {}", userId, e); return e.asPromise(); } }
@Override public Promise<QueryResponse, ResourceException> queryCollection( final Context serverContext, final QueryRequest queryRequest, final QueryResourceHandler queryResultHandler) { QueryFilter<JsonPointer> queryFilter = queryRequest.getQueryFilter(); if (queryFilter == null) { return new BadRequestException(getUsageString()).asPromise(); } try { final QueryFilter<CoreTokenField> coreTokenFieldQueryFilter = convertToCoreTokenFieldQueryFilter(queryFilter); final List<STSIssuedTokenState> issuedTokens = ctsTokenPersistence.listTokens(coreTokenFieldQueryFilter); for (STSIssuedTokenState tokenState : issuedTokens) { queryResultHandler.handleResource( newResourceResponse(tokenState.getTokenId(), EMPTY_STRING, tokenState.toJson())); } return newResultPromise(newQueryResponse()); } catch (CTSTokenPersistenceException e) { logger.error("Exception caught obtaining list of sts-issued tokens: " + e, e); return e.asPromise(); } }
/** * Performs the query on the specified object and returns the associated results. * * <p>Queries are parametric; a set of named parameters is provided as the query criteria. The * query result is a JSON object structure composed of basic Java types. * * <p>The returned map is structured as follow: - The top level map contains meta-data about the * query, plus an entry with the actual result records. - The <code>QueryConstants</code> defines * the map keys, including the result records (QUERY_RESULT) * * @param context identifies the object to query. * @param request the parameters of the query to perform. * @return the query results, which includes meta-data and the result records in JSON object * structure format. * @throws NotFoundException if the specified object could not be found. * @throws BadRequestException if the specified params contain invalid arguments, e.g. a query id * that is not configured, a query expression that is invalid, or missing query substitution * tokens. * @throws ForbiddenException if access to the object or specified query is forbidden. */ @Override public Promise<QueryResponse, ResourceException> handleQuery( final Context context, final QueryRequest request, final QueryResourceHandler handler) { // If paged results are requested then decode the cookie in order to determine // the index of the first result to be returned. final int requestPageSize = request.getPageSize(); // Cookie containing offset of last request final String pagedResultsCookie = request.getPagedResultsCookie(); final boolean pagedResultsRequested = requestPageSize > 0; // index of first record (used for SKIP/OFFSET) final int firstResultIndex; if (pagedResultsRequested) { if (StringUtils.isNotEmpty(pagedResultsCookie)) { try { firstResultIndex = Integer.parseInt(pagedResultsCookie); } catch (final NumberFormatException e) { return new BadRequestException("Invalid paged results cookie").asPromise(); } } else { firstResultIndex = Math.max(0, request.getPagedResultsOffset()); } } else { firstResultIndex = 0; } // Once cookie is processed Queries.query() can rely on the offset. request.setPagedResultsOffset(firstResultIndex); try { List<ResourceResponse> results = query(request); for (ResourceResponse result : results) { handler.handleResource(result); } /* * Execute additional -count query if we are paging */ final String nextCookie; // The number of results (if known) final int resultCount; if (pagedResultsRequested) { // count if requested switch (request.getTotalPagedResultsPolicy()) { case ESTIMATE: case EXACT: // Get total if -count query is available final String countQueryId = request.getQueryId() + "-count"; if (queries.queryIdExists(countQueryId)) { QueryRequest countRequest = Requests.copyOfQueryRequest(request); countRequest.setQueryId(countQueryId); // Strip pagination parameters countRequest.setPageSize(0); countRequest.setPagedResultsOffset(0); countRequest.setPagedResultsCookie(null); List<ResourceResponse> countResult = query(countRequest); if (countResult != null && !countResult.isEmpty()) { resultCount = countResult.get(0).getContent().get("total").asInteger(); } else { logger.debug("Count query {} failed.", countQueryId); resultCount = NO_COUNT; } } else { logger.debug("No count query found with id {}", countQueryId); resultCount = NO_COUNT; } break; case NONE: default: resultCount = NO_COUNT; break; } if (results.size() < requestPageSize) { nextCookie = null; } else { final int remainingResults = resultCount - (firstResultIndex + results.size()); if (remainingResults == 0) { nextCookie = null; } else { nextCookie = String.valueOf(firstResultIndex + requestPageSize); } } } else { resultCount = NO_COUNT; nextCookie = null; } if (resultCount == NO_COUNT) { return newQueryResponse(nextCookie).asPromise(); } else { return newQueryResponse(nextCookie, EXACT, resultCount).asPromise(); } } catch (ResourceException e) { return e.asPromise(); } }