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

feat(storage): Gen2 Implementation for getUrl, remove, list #2755

Merged
merged 64 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2817b4e
Add deprecation to StorageOptions
tylerjroach Feb 20, 2024
127198d
Add new StoragePath methods and deprecate old
tylerjroach Feb 20, 2024
e1346e5
Deprecate StorageAccessLevel
tylerjroach Feb 20, 2024
b5c8246
Deprecate S3 Prefix Resolver
tylerjroach Feb 20, 2024
819c1b8
Update Upload Result Types
tylerjroach Feb 20, 2024
bbfcf5c
Rename .java to .kt
tylerjroach Feb 21, 2024
77b69a5
Update storage item with path
tylerjroach Feb 21, 2024
ac52808
Update results
tylerjroach Feb 21, 2024
ee805e7
download implementation
tylerjroach Feb 21, 2024
6c556f6
lint cleanup
tylerjroach Feb 21, 2024
99cbd5b
lint cleanup
tylerjroach Feb 21, 2024
16d5380
lint cleanup
tylerjroach Feb 21, 2024
54550df
update storage path
tylerjroach Mar 1, 2024
6e03c2e
StoragePath Kotlin Facade APIs
tylerjroach Mar 11, 2024
337bf4f
StoragePath Rx Facade APIs
tylerjroach Mar 11, 2024
9c38f16
StoragePath Rx Facade APIs
tylerjroach Mar 11, 2024
babbf5a
lint
tylerjroach Mar 11, 2024
1ee4029
Storage path updates
tylerjroach Mar 13, 2024
1dfde82
updates after api review
tylerjroach Mar 15, 2024
f8ba29f
add contract tests
tylerjroach Mar 15, 2024
fb1336c
rx contract tests
tylerjroach Mar 18, 2024
2e911bc
Merge branch 'main' into tjroach/gen2-storage-contract
tylerjroach Mar 18, 2024
ac387c8
lint
tylerjroach Mar 18, 2024
b48dbb3
cleanup and remove download implementation for follow up PR
tylerjroach Mar 18, 2024
3ca63f7
deprecation on entire object is enough
tylerjroach Mar 18, 2024
886ec72
fix issues causing building failures
tylerjroach Mar 18, 2024
3b122ec
Add StoragePathValidationException
tylerjroach Mar 18, 2024
86cc7fe
cleanup
tylerjroach Mar 18, 2024
10f6c97
binary dump
tylerjroach Mar 18, 2024
b07a4a9
lint
tylerjroach Mar 18, 2024
6757e71
lint
tylerjroach Mar 18, 2024
acd582e
lint
tylerjroach Mar 18, 2024
733c9ae
lint
tylerjroach Mar 19, 2024
7f39908
adding download and upload functionality to gen2
tylerjroach Mar 21, 2024
eef1b4e
storage path changes
tylerjroach Mar 22, 2024
7d17677
storage path changes
tylerjroach Mar 22, 2024
a2887b5
lint
tylerjroach Mar 22, 2024
344299d
accidental change
tylerjroach Mar 22, 2024
4a0c92c
fix test
tylerjroach Mar 22, 2024
46089d4
input stream support
tylerjroach Mar 25, 2024
bfbd92f
code cleanup
tylerjroach Mar 26, 2024
dd6d309
geturl, remove, list gen2 experience
tylerjroach Mar 27, 2024
76b7a1f
PR comments
tylerjroach Mar 27, 2024
6ee7199
PR comments
tylerjroach Mar 27, 2024
9a3d0e2
Merge branch 'feat/gen2-storage' into tjroach/gen2-storage-download-u…
tylerjroach Mar 27, 2024
21ad0de
merge cleanup
tylerjroach Mar 27, 2024
373d7b5
remove unnecessary change
tylerjroach Mar 27, 2024
1823175
Merge branch 'tjroach/gen2-storage-download-upload' into tjroach/gen2…
tylerjroach Mar 27, 2024
4b0acb0
StoragePath list unit test
tylerjroach Mar 27, 2024
29be849
add unit tests
tylerjroach Mar 29, 2024
278d587
Merge branch 'main' into tjroach/gen2-geturl-remove-list
tylerjroach Apr 2, 2024
e32f0ee
upload integration tests
tylerjroach Apr 2, 2024
1f92921
additional download storage integration tests
tylerjroach Apr 2, 2024
1544f95
getUrl and remove tests
tylerjroach Apr 2, 2024
d0bbcbc
More tests and PR comments
tylerjroach Apr 4, 2024
4577c25
pr comments
tylerjroach Apr 4, 2024
770a6ae
Merge remote-tracking branch 'origin/main' into tjroach/gen2-geturl-r…
tylerjroach Apr 4, 2024
985a8d5
Merge remote-tracking branch 'origin/feat/gen2-storage' into tjroach/…
tylerjroach Apr 4, 2024
daaa811
lint
tylerjroach Apr 4, 2024
3d0113e
fix licenses
tylerjroach Apr 4, 2024
31fb94a
additional tests and bux fixes
tylerjroach Apr 4, 2024
1baa01c
fix accidental change
tylerjroach Apr 5, 2024
0e131a6
test optimizations
tylerjroach Apr 5, 2024
f71c946
test optimizations
tylerjroach Apr 5, 2024
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 @@ -55,7 +55,6 @@ class AuthStressTests {
} catch (error: AmplifyException) {
Log.e("MyAmplifyApp", "Could not initialize Amplify", error)
}
Thread.sleep(5000)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ public void setUp() throws Exception {
}
}

private void assertListContainsUploadedFile(StorageListResult result) {
private void assertListContainsUploadedFile(
StorageListResult result,
String pathPrefix
) {
List<StorageItem> items = result.getItems();
assertNotNull(items);
assertEquals(1, items.size());
Expand All @@ -113,6 +116,8 @@ private void assertListContainsUploadedFile(StorageListResult result) {
StorageItem storedItem = items.get(0);
assertEquals(UPLOAD_SIZE, storedItem.getSize());
assertEquals(uploadKey, storedItem.getKey());
assertEquals(pathPrefix + uploadKey, storedItem.getPath());

}

/**
Expand All @@ -126,7 +131,7 @@ public void testListUnauthenticatedPublicAccess() throws Exception {
.accessLevel(StorageAccessLevel.PUBLIC)
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "public/");
}

/**
Expand All @@ -144,7 +149,7 @@ public void testListUnauthenticatedProtectedAccess() throws Exception {
.targetIdentityId(userOne.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "protected/" + userOne.getIdentityId() + "/");
}

/**
Expand All @@ -163,7 +168,7 @@ public void testListUnauthenticatedPrivateAccess() throws Exception {
.targetIdentityId(userOne.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "private/" + userOne.getIdentityId() + "/");
}

/**
Expand All @@ -179,7 +184,7 @@ public void testListAuthenticatedProtectedAccess() throws Exception {
.targetIdentityId(userOne.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "protected/" + userOne.getIdentityId() + "/");
}

/**
Expand Down Expand Up @@ -220,7 +225,7 @@ public void testListAuthenticatedPrivateAccess() throws Exception {
.targetIdentityId(userOne.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "private/" + userOne.getIdentityId() + "/");
}

/**
Expand All @@ -240,7 +245,7 @@ public void testListDifferentUsersProtectedAccess() throws Exception {
.targetIdentityId(userTwo.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "protected/" + userTwo.getIdentityId() + "/");
}

/**
Expand All @@ -260,14 +265,13 @@ public void testListDifferentUsersPrivateAccess() throws Exception {
.targetIdentityId(userTwo.getIdentityId())
.build();
StorageListResult result = storage.list(TEST_DIR_NAME, listOptions);
assertListContainsUploadedFile(result);
assertListContainsUploadedFile(result, "private/" + userTwo.getIdentityId() + "/");
}

private static void uploadTestFiles() throws Exception {
// Create a temporary file to upload
File uploadFile = new RandomTempFile(UPLOAD_SIZE);
String uploadName = uploadFile.getName();
String uploadPath = uploadFile.getAbsolutePath();
uploadKey = TEST_DIR_NAME + "/" + uploadName;
StorageUploadFileOptions options;

Expand Down Expand Up @@ -307,7 +311,6 @@ private static void uploadMultipleTestFiles() throws Exception {
// Create a temporary file to upload
File uploadFile = new RandomTempFile(UPLOAD_SIZE);
String uploadName = uploadFile.getName();
String uploadPath = uploadFile.getAbsolutePath();
pagedUploadKeyPrefix = "PAGED" + TEST_DIR_NAME + "/" + uploadName;
StorageUploadFileOptions options;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@ package com.amplifyframework.storage.s3

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.amplifyframework.auth.AuthPlugin
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
import com.amplifyframework.core.Amplify
import com.amplifyframework.core.async.Cancelable
Expand All @@ -26,6 +25,7 @@ import com.amplifyframework.hub.HubEvent
import com.amplifyframework.hub.SubscriptionToken
import com.amplifyframework.storage.StorageCategory
import com.amplifyframework.storage.StorageChannelEventName
import com.amplifyframework.storage.StorageException
import com.amplifyframework.storage.StoragePath
import com.amplifyframework.storage.TransferState
import com.amplifyframework.storage.TransferState.Companion.getState
Expand Down Expand Up @@ -67,11 +67,20 @@ class AWSS3StoragePathDownloadTest {
private val LARGE_FILE_PATH = StoragePath.fromString("public/$LARGE_FILE_NAME")
private val SMALL_FILE_NAME = "small-${System.currentTimeMillis()}"
private val SMALL_FILE_PATH = StoragePath.fromString("public/$SMALL_FILE_NAME")
private val USER_ONE_PROTECTED_FILE_NAME = "user1Protected-${System.currentTimeMillis()}"
private val USER_ONE_PRIVATE_FILE_NAME = "user1Private-${System.currentTimeMillis()}"

lateinit var storageCategory: StorageCategory
lateinit var synchronousStorage: SynchronousStorage
lateinit var synchronousAuth: SynchronousAuth
lateinit var largeFile: File
lateinit var smallFile: File
lateinit var userOneProtectedFile: File
lateinit var userOneProtectedStoragePath: StoragePath
lateinit var userOnePrivateFile: File
lateinit var userOnePrivateStoragePath: StoragePath
internal lateinit var userOne: UserCredentials.Credential
internal lateinit var userTwo: UserCredentials.Credential

/**
* Initialize mobile client and configure the storage.
Expand All @@ -82,21 +91,50 @@ class AWSS3StoragePathDownloadTest {
fun setUpOnce() {
val context = ApplicationProvider.getApplicationContext<Context>()
initializeWorkmanagerTestUtil(context)
SynchronousAuth.delegatingToCognito(context, AWSCognitoAuthPlugin() as AuthPlugin<*>)
synchronousAuth = SynchronousAuth.delegatingToCognito(context, AWSCognitoAuthPlugin())
val identityIdSource = MobileClientIdentityIdSource.create(synchronousAuth)
val userCredentials = UserCredentials.create(context, identityIdSource)
val iterator = userCredentials.iterator()
userOne = iterator.next()
userTwo = iterator.next()

// Get a handle to storage
storageCategory = TestStorageCategory.create(context, R.raw.amplifyconfiguration)
synchronousStorage = SynchronousStorage.delegatingTo(storageCategory)

val uploadOptions = StorageUploadFileOptions.defaultInstance()

synchronousAuth.signOut()

// Upload large test file
largeFile = RandomTempFile(LARGE_FILE_NAME, LARGE_FILE_SIZE)
synchronousStorage.uploadFile(LARGE_FILE_PATH, largeFile, uploadOptions, EXTENDED_TIMEOUT_MS)

// Upload small test file
smallFile = RandomTempFile(SMALL_FILE_NAME, SMALL_FILE_SIZE)
synchronousStorage.uploadFile(SMALL_FILE_PATH, smallFile, uploadOptions)

synchronousAuth.signIn(userOne.username, userOne.password)

userOneProtectedFile = RandomTempFile(USER_ONE_PROTECTED_FILE_NAME, SMALL_FILE_SIZE)
userOneProtectedStoragePath =
StoragePath.fromString("protected/${userOne.identityId}/$USER_ONE_PROTECTED_FILE_NAME")
synchronousStorage.uploadFile(
StoragePath.fromString("protected/${userOne.identityId}/$USER_ONE_PROTECTED_FILE_NAME"),
userOneProtectedFile,
uploadOptions
)

userOnePrivateFile = RandomTempFile(USER_ONE_PRIVATE_FILE_NAME, SMALL_FILE_SIZE)
userOnePrivateStoragePath =
StoragePath.fromString("private/${userOne.identityId}/$USER_ONE_PRIVATE_FILE_NAME")
synchronousStorage.uploadFile(
userOnePrivateStoragePath,
userOnePrivateFile,
uploadOptions
)

synchronousAuth.signOut()
}
}

Expand All @@ -109,6 +147,8 @@ class AWSS3StoragePathDownloadTest {
for (token in subscriptions) {
Amplify.Hub.unsubscribe(token)
}

synchronousAuth.signOut()
}

@Test
Expand Down Expand Up @@ -268,4 +308,50 @@ class AWSS3StoragePathDownloadTest {
EXTENDED_TIMEOUT_MS
)
}

@Test
fun testDownloadUnauthenticatedProtectedAccess() {
val result = synchronousStorage.downloadFile(
userOneProtectedStoragePath,
downloadFile,
options
)

FileAssert.assertEquals(userOneProtectedFile, result.file)
}

@Test
fun testDownloadAuthenticatedProtectedAccess() {
synchronousAuth.signIn(userOne.username, userOne.password)

val result = synchronousStorage.downloadFile(
userOneProtectedStoragePath,
downloadFile,
options
)

FileAssert.assertEquals(userOneProtectedFile, result.file)
}

@Test(expected = StorageException::class)
fun testDownloadUnauthenticatedPrivateAccess() {
synchronousStorage.downloadFile(
userOnePrivateStoragePath,
downloadFile,
options
)
}

@Test
fun testAuthenticatedPrivateAccess() {
synchronousAuth.signIn(userOne.username, userOne.password)

val result = synchronousStorage.downloadFile(
userOnePrivateStoragePath,
downloadFile,
options
)

FileAssert.assertEquals(userOnePrivateFile, result.file)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amplifyframework.storage.s3

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
import com.amplifyframework.storage.StorageCategory
import com.amplifyframework.storage.StoragePath
import com.amplifyframework.storage.options.StorageGetUrlOptions
import com.amplifyframework.storage.options.StorageUploadFileOptions
import com.amplifyframework.storage.s3.test.R
import com.amplifyframework.storage.s3.util.WorkmanagerTestUtils.initializeWorkmanagerTestUtil
import com.amplifyframework.testutils.random.RandomTempFile
import com.amplifyframework.testutils.sync.SynchronousAuth
import com.amplifyframework.testutils.sync.SynchronousStorage
import java.io.File
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.BeforeClass
import org.junit.Test

/**
* Instrumentation test for operational work on download.
*/
class AWSS3StoragePathGetUrlTest {
// Create a file to download to
private val downloadFile: File = RandomTempFile()

private companion object {
const val SMALL_FILE_SIZE = 100L
val SMALL_FILE_NAME = "small-${System.currentTimeMillis()}"
val SMALL_FILE_PATH = StoragePath.fromString("public/$SMALL_FILE_NAME")

lateinit var storageCategory: StorageCategory
lateinit var synchronousStorage: SynchronousStorage
lateinit var smallFile: File

/**
* Initialize mobile client and configure the storage.
* Upload the test files ahead of time.
*/
@JvmStatic
@BeforeClass
fun setUpOnce() {
val context = ApplicationProvider.getApplicationContext<Context>()
initializeWorkmanagerTestUtil(context)

SynchronousAuth.delegatingToCognito(context, AWSCognitoAuthPlugin())

storageCategory = TestStorageCategory.create(context, R.raw.amplifyconfiguration)
synchronousStorage = SynchronousStorage.delegatingTo(storageCategory)

// Upload small test file
smallFile = RandomTempFile(SMALL_FILE_NAME, SMALL_FILE_SIZE)
synchronousStorage.uploadFile(SMALL_FILE_PATH, smallFile, StorageUploadFileOptions.defaultInstance())
}
}

@Test
fun testGetUrl() {
val result = synchronousStorage.getUrl(
SMALL_FILE_PATH,
StorageGetUrlOptions.builder().expires(30).build()
)

assertEquals("/public/$SMALL_FILE_NAME", result.url.path)
assertTrue(result.url.query.contains("X-Amz-Expires=30"))
}
}
Loading