## Customization ### Customize Object Key Path You can customize your key path by defining a prefix resolver: ```java // Define your own prefix resolver, that conforms to `AWSS3StoragePluginPrefixResolver` public class MyDeveloperPrefixResolver implements AWSS3PluginPrefixResolver { @Override public void resolvePrefix(@NonNull StorageAccessLevel accessLevel, @Nullable String targetIdentity, @NonNull Consumer onSuccess, @NonNull Consumer onError) { switch (accessLevel) { case PUBLIC: { onSuccess.accept("myPublicPrefix/"); } case PROTECTED: { onSuccess.accept("myProtectedPrefix/" + targetIdentity + "/"); } case PRIVATE: { onSuccess.accept("myPrivatePrefix/" + targetIdentity + "/"); } } } } ``` ```kotlin // Define your own prefix resolver, that conforms to `AWSS3StoragePluginPrefixResolver` class MyDeveloperPrefixResolver: AWSS3PluginPrefixResolver { override fun resolvePrefix( accessLevel: StorageAccessLevel, targetIdentity: String?, onSuccess: Consumer, onError: Consumer ) { when(accessLevel) { StorageAccessLevel.PUBLIC -> { onSuccess.accept("myPublicPrefix/") } StorageAccessLevel.PROTECTED -> { onSuccess.accept("myProtectedPrefix/$targetIdentity/") } StorageAccessLevel.PRIVATE -> { onSuccess.accept("myPrivatePrefix/$targetIdentity/") } } } } ``` Then configure the storage plugin with the resolver. ```java AWSS3StoragePluginConfiguration.Builder builder = new AWSS3StoragePluginConfiguration.Builder(); builder.setAwsS3PluginPrefixResolver(new MyDeveloperPrefixResolver()); Amplify.addPlugin(new AWSS3StoragePlugin(builder.build())); ``` ```kotlin Amplify.addPlugin>( AWSS3StoragePlugin( AWSS3StoragePluginConfiguration { awsS3PluginPrefixResolver = MyDeveloperPrefixResolver() } ) ) ``` Add the IAM policy that corresponds with the prefixes defined above to enable read, write and delete operation for all the objects under path *myPublicPrefix/*: ```xml "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::your-s3-bucket/myPublicPrefix/*", ] } ] ``` If you want to have custom *private* path prefix like *myPrivatePrefix/*, you need to add it into your IAM policy: ```xml "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::your-s3-bucket/myPrivatePrefix/${cognito-identity.amazonaws.com:sub}/*" ] } ] ``` #### Passthrough PrefixResolver If you would like no prefix resolution logic, such as performing S3 requests at the root of the bucket, create a prefix resolver that returns an empty string: ```java public class PassThroughPrefixResolver implements AWSS3PluginPrefixResolver { @Override public void resolvePrefix(@NonNull StorageAccessLevel accessLevel, @Nullable String targetIdentity, @NonNull Consumer onSuccess, @NonNull Consumer onError) { onSuccess.accept("") } } ``` ```kotlin class PassThroughPrefixResolver: AWSS3PluginPrefixResolver { override fun resolvePrefix( accessLevel: StorageAccessLevel, targetIdentity: String?, onSuccess: Consumer, onError: Consumer ) { onSuccess.accept("") } } ```