## 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("")
}
}
```