Search in sources :

Example 1 with AppSyncGraphQLRequest

use of com.amplifyframework.api.aws.AppSyncGraphQLRequest in project amplify-android by aws-amplify.

the class AppSyncRequestFactory method buildSyncRequest.

/**
 * Builds the query document for base and delta sync.
 * If you provide lastSyncTime, it builds a delta sync, where the delta is computed
 * against the provided time. Otherwise, if you provide a null lastSyncTime, a
 * request doc is generated for a base sync.
 * @param modelSchema Schema Class for which we want to sync.
 * @param lastSync The last time synced. If not provided, do a base query.
 *                 If provided, do a delta query.
 * @param <T> The type of objects we are syncing
 * @return A string which contains a GraphQL query doc for an base/delta sync
 * @throws DataStoreException On Failure to inspect
 */
@NonNull
static <T> AppSyncGraphQLRequest<T> buildSyncRequest(@NonNull final ModelSchema modelSchema, @Nullable final Long lastSync, @Nullable final Integer limit, @NonNull final QueryPredicate predicate, @NonNull final AuthModeStrategyType strategyType) throws DataStoreException {
    try {
        AppSyncGraphQLRequest.Builder builder = AppSyncGraphQLRequest.builder().modelClass(modelSchema.getModelClass()).modelSchema(modelSchema).operation(QueryType.SYNC).requestAuthorizationStrategyType(strategyType).requestOptions(new DataStoreGraphQLRequestOptions()).responseType(TypeMaker.getParameterizedType(PaginatedResult.class, ModelWithMetadata.class, modelSchema.getModelClass()));
        if (lastSync != null) {
            builder.variable("lastSync", "AWSTimestamp", lastSync);
        }
        if (limit != null) {
            builder.variable("limit", "Int", limit);
        }
        if (!QueryPredicates.all().equals(predicate)) {
            String filterType = "Model" + Casing.capitalizeFirst(modelSchema.getName()) + "FilterInput";
            QueryPredicate syncPredicate = predicate;
            if (!(syncPredicate instanceof QueryPredicateGroup)) {
                // When a filter is provided, wrap it with a predicate group of type AND.  By doing this, it enables
                // AppSync to optimize the request by performing a DynamoDB query instead of a scan.  If the
                // provided syncPredicate is already a QueryPredicateGroup, this is not needed.  If the provided
                // group is of type AND, the optimization will occur.  If the top level group is OR or NOT, the
                // optimization is not possible anyway.
                syncPredicate = QueryPredicateGroup.andOf(syncPredicate);
            }
            builder.variable("filter", filterType, parsePredicate(syncPredicate));
        }
        return builder.build();
    } catch (AmplifyException amplifyException) {
        throw new DataStoreException("Failed to get fields for model.", amplifyException, "Validate your model file.");
    }
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) AmplifyException(com.amplifyframework.AmplifyException) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) AppSyncGraphQLRequest(com.amplifyframework.api.aws.AppSyncGraphQLRequest) PaginatedResult(com.amplifyframework.api.graphql.PaginatedResult) QueryPredicateGroup(com.amplifyframework.core.model.query.predicate.QueryPredicateGroup) NonNull(androidx.annotation.NonNull)

Example 2 with AppSyncGraphQLRequest

use of com.amplifyframework.api.aws.AppSyncGraphQLRequest in project amplify-android by aws-amplify.

the class AppSyncRequestFactory method buildMutation.

/**
 * Builds a mutation.
 * @param schema the model schema for the mutation
 * @param mutationType Type of mutation, e.g. {@link MutationType#CREATE}
 * @param <M> Type of model being mutated
 * @return Mutation doc
 */
private static <M extends Model> AppSyncGraphQLRequest<ModelWithMetadata<M>> buildMutation(ModelSchema schema, Map<String, Object> inputMap, QueryPredicate predicate, MutationType mutationType, AuthModeStrategyType strategyType) throws DataStoreException {
    try {
        String graphQlTypeName = schema.getName();
        AppSyncGraphQLRequest.Builder builder = AppSyncGraphQLRequest.builder().modelClass(schema.getModelClass()).modelSchema(schema).operation(mutationType).requestAuthorizationStrategyType(strategyType).requestOptions(new DataStoreGraphQLRequestOptions()).responseType(TypeMaker.getParameterizedType(ModelWithMetadata.class, schema.getModelClass()));
        String inputType = Casing.capitalize(mutationType.toString()) + Casing.capitalizeFirst(graphQlTypeName) + // CreateTodoInput
        "Input!";
        builder.variable("input", inputType, inputMap);
        if (!QueryPredicates.all().equals(predicate)) {
            String conditionType = "Model" + Casing.capitalizeFirst(graphQlTypeName) + "ConditionInput";
            builder.variable("condition", conditionType, parsePredicate(predicate));
        }
        return builder.build();
    } catch (AmplifyException amplifyException) {
        throw new DataStoreException("Failed to get fields for model.", amplifyException, "Validate your model file.");
    }
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) AmplifyException(com.amplifyframework.AmplifyException) AppSyncGraphQLRequest(com.amplifyframework.api.aws.AppSyncGraphQLRequest)

Example 3 with AppSyncGraphQLRequest

use of com.amplifyframework.api.aws.AppSyncGraphQLRequest in project amplify-android by aws-amplify.

the class AuthRuleRequestDecorator method decorate.

/**
 * Decorate given GraphQL request instance with additional variables for owner-based or
 * group-based authorization.
 *
 * This will only work if the request is compliant with the AppSync specifications.
 * @param request an instance of {@link GraphQLRequest}.
 * @param authType the mode of authorization being used to authorize the request
 * @param <R> The type of data contained in the GraphQLResponse expected from this request.
 * @return the input request with additional variables that specify model's owner and/or
 *          groups
 * @throws ApiException If an error is encountered while processing the auth rules associated
 *          with the request or if the authorization fails
 */
public <R> GraphQLRequest<R> decorate(@NonNull GraphQLRequest<R> request, @NonNull AuthorizationType authType) throws ApiException {
    if (!(request instanceof AppSyncGraphQLRequest)) {
        return request;
    }
    AppSyncGraphQLRequest<R> appSyncRequest = (AppSyncGraphQLRequest<R>) request;
    AuthRule ownerRuleWithReadRestriction = null;
    Map<String, Set<String>> readAuthorizedGroupsMap = new HashMap<>();
    // and it's not clear what a good solution would be until AppSync supports real time filters.
    for (AuthRule authRule : appSyncRequest.getModelSchema().getAuthRules()) {
        if (isReadRestrictingOwner(authRule)) {
            if (ownerRuleWithReadRestriction == null) {
                ownerRuleWithReadRestriction = authRule;
            } else {
                throw new ApiAuthException("Detected multiple owner type auth rules with a READ operation", "We currently do not support this use case. Please limit your type to just one owner " + "auth rule with a READ operation restriction.");
            }
        } else if (isReadRestrictingStaticGroup(authRule)) {
            // Group read-restricting groups by the claim name
            String groupClaim = authRule.getGroupClaimOrDefault();
            List<String> groups = authRule.getGroups();
            Set<String> readAuthorizedGroups = readAuthorizedGroupsMap.get(groupClaim);
            if (readAuthorizedGroups != null) {
                readAuthorizedGroups.addAll(groups);
            } else {
                readAuthorizedGroupsMap.put(groupClaim, new HashSet<>(groups));
            }
        }
    }
    // them.
    if (ownerRuleWithReadRestriction != null && userNotInReadRestrictingGroups(readAuthorizedGroupsMap, authType)) {
        String idClaim = ownerRuleWithReadRestriction.getIdentityClaimOrDefault();
        String key = ownerRuleWithReadRestriction.getOwnerFieldOrDefault();
        String value = getIdentityValue(idClaim, authType);
        try {
            return appSyncRequest.newBuilder().variable(key, "String!", value).build();
        } catch (AmplifyException error) {
            // This should not happen normally
            throw new ApiAuthException("Failed to set owner field on AppSyncGraphQLRequest.", error, AmplifyException.REPORT_BUG_TO_AWS_SUGGESTION);
        }
    }
    return request;
}
Also used : ApiAuthException(com.amplifyframework.api.ApiException.ApiAuthException) HashSet(java.util.HashSet) Set(java.util.Set) AmplifyException(com.amplifyframework.AmplifyException) HashMap(java.util.HashMap) AppSyncGraphQLRequest(com.amplifyframework.api.aws.AppSyncGraphQLRequest) ArrayList(java.util.ArrayList) List(java.util.List) AuthRule(com.amplifyframework.core.model.AuthRule) HashSet(java.util.HashSet)

Aggregations

AmplifyException (com.amplifyframework.AmplifyException)3 AppSyncGraphQLRequest (com.amplifyframework.api.aws.AppSyncGraphQLRequest)3 DataStoreException (com.amplifyframework.datastore.DataStoreException)2 NonNull (androidx.annotation.NonNull)1 ApiAuthException (com.amplifyframework.api.ApiException.ApiAuthException)1 PaginatedResult (com.amplifyframework.api.graphql.PaginatedResult)1 AuthRule (com.amplifyframework.core.model.AuthRule)1 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)1 QueryPredicateGroup (com.amplifyframework.core.model.query.predicate.QueryPredicateGroup)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Set (java.util.Set)1