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): add multi-bucket feature support #5681

Merged
merged 25 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e847d8a
feat(core): add storage bucket type (#5478)
NikaHsn Sep 20, 2024
3fecfa4
updating storage_outputs class for multi-bucket support
Sep 17, 2024
10aee0b
seperated bucket out into its own class instead of using a map
Sep 17, 2024
95f3e55
made bucket_output class a proper output class like the others in amp…
Sep 18, 2024
06cad0a
added doc comments and changed name of bucket class
Sep 18, 2024
565c46d
Update auth.dart
ekjotmultani Sep 18, 2024
dc03882
added trailing commas to pass ci test
Sep 18, 2024
6a3ea1d
Delete devtools_options.yaml
ekjotmultani Sep 18, 2024
f6b8cb3
ran dart format on two failing files
Sep 18, 2024
9246fff
updated resource.ts and backend.ts for multiple buckets in our infra-…
Sep 24, 2024
600e725
updated resource.ts and backend.ts for multiple buckets in our infra-…
Sep 24, 2024
2753202
feat(storage): update s3 storage service to support multiple s3 clien…
NikaHsn Sep 25, 2024
0658d24
feat(storage): update uploadData API to accept optional storage bucke…
NikaHsn Oct 14, 2024
9d4f747
feat(storage): multi bucket get properties api (#5577)
ekjotmultani Oct 24, 2024
8b7e5b8
feat(storage): multi bucket remove (#5598)
Equartey Oct 28, 2024
670f8eb
feat(storage): multi bucket download data (#5599)
Equartey Oct 28, 2024
f9083d4
feat(storage): multi bucket upload file (#5600)
Equartey Oct 29, 2024
fc1293c
chore(storage): add e2e tests for upload data api (#5622)
NikaHsn Nov 1, 2024
59ebae6
feat(storage): multi bucket list api (#5576)
ekjotmultani Nov 4, 2024
ef95d1f
feat(storage): multi bucket remove many api (#5633)
NikaHsn Nov 6, 2024
fcc011d
feat(storage): multi bucket get url (#5659)
Equartey Nov 11, 2024
a487307
feat(storage): multi bucket download file api (#5656)
ekjotmultani Nov 12, 2024
7a46411
feat(storage): multi bucket copy (#5674)
tyllark Nov 19, 2024
0db2d4f
chore(storage): test data to use clear random names for bucket info (…
NikaHsn Nov 26, 2024
4622de3
chore(ci): rebase with main to fix the failing tests
Dec 3, 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
34 changes: 30 additions & 4 deletions infra-gen2/backends/storage/main/amplify/backend.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,52 @@
import { defineBackend } from "@aws-amplify/backend";
import * as s3 from "aws-cdk-lib/aws-s3";
import { auth } from "./auth/resource";
import { storage } from "./storage/resource";
import { firstBucket, secondBucket } from "./storage/resource";

/**
* @see https://docs.amplify.aws/react/build-a-backend/ to add storage, functions, and more
*/
const backend = defineBackend({
auth,
storage,
firstBucket,
secondBucket,
});

// custom storage configurations
const s3Bucket = backend.storage.resources.bucket;
const s3Bucket = backend.firstBucket.resources.bucket;
const cfnBucket = s3Bucket.node.defaultChild as s3.CfnBucket;
const s3SecondaryBucket = backend.secondBucket.resources.bucket;
const cfnSecondaryBucket = s3SecondaryBucket.node.defaultChild as s3.CfnBucket;

cfnBucket.accelerateConfiguration = {
accelerationStatus: "Enabled",
};

cfnSecondaryBucket.accelerateConfiguration = {
accelerationStatus: "Enabled",
};

// required to add the metadata header, which amplify-backend does not support
backend.firstBucket.resources.cfnResources.cfnBucket.corsConfiguration = {
corsRules: [
{
allowedHeaders: ["*"],
allowedMethods: ["GET", "HEAD", "PUT", "POST", "DELETE"],
allowedOrigins: ["*"],
exposedHeaders: [
"x-amz-server-side-encryption",
"x-amz-request-id",
"x-amz-id-2",
"ETag",
"x-amz-meta-description",
],
maxAge: 3000,
},
],
};

// required to add the metadata header, which amplify-backend does not support
backend.storage.resources.cfnResources.cfnBucket.corsConfiguration = {
backend.secondBucket.resources.cfnResources.cfnBucket.corsConfiguration = {
corsRules: [
{
allowedHeaders: ["*"],
Expand Down
22 changes: 20 additions & 2 deletions infra-gen2/backends/storage/main/amplify/storage/resource.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
import { defineStorage } from "@aws-amplify/backend";

export const storage = defineStorage({
name: "Storage Integ Test main",
export const firstBucket = defineStorage({
name: "Storage Integ Test main bucket",
isDefault: true,
access: (allow) => ({
"public/*": [
allow.guest.to(["read", "write", "delete"]),
allow.authenticated.to(["read", "delete", "write"]),
],
"protected/{entity_id}/*": [
allow.authenticated.to(["read"]),
allow.entity("identity").to(["read", "write", "delete"]),
],
"private/{entity_id}/*": [
allow.entity("identity").to(["read", "write", "delete"]),
],
}),
});

export const secondBucket = defineStorage({
name: "Storage Integ Test secondary bucket",
access: (allow) => ({
"public/*": [
allow.guest.to(["read", "write", "delete"]),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_core/amplify_core.dart';

part 'bucket_outputs.g.dart';

/// {@template amplify_core.amplify_outputs.bucket_outputs}
/// The Amplify Gen 2 outputs for Buckets in the Storage category.
/// {@endtemplate}
@zAmplifyOutputsSerializable
class BucketOutputs
with AWSEquatable<BucketOutputs>, AWSSerializable, AWSDebuggable {
/// {@macro amplify_core.amplify_outputs.bucket_outputs}
const BucketOutputs({
required this.name,
required this.bucketName,
required this.awsRegion,
});

factory BucketOutputs.fromJson(Map<String, Object?> json) =>
_$BucketOutputsFromJson(json);

/// The user friendly name of the bucket
final String name;

/// The Amazon S3 bucket name.
final String bucketName;

/// The AWS region of Amazon S3 resources.
final String awsRegion;

@override
List<Object?> get props => [
name,
bucketName,
awsRegion,
];

@override
String get runtimeTypeName => 'BucketOutputs';

@override
Object? toJson() {
return _$BucketOutputsToJson(this);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_core/src/config/amplify_outputs/storage/bucket_outputs.dart';

part 'storage_outputs.g.dart';

Expand All @@ -12,7 +13,11 @@ part 'storage_outputs.g.dart';
class StorageOutputs
with AWSEquatable<StorageOutputs>, AWSSerializable, AWSDebuggable {
/// {@macro amplify_core.amplify_outputs.storage_outputs}
const StorageOutputs({required this.awsRegion, required this.bucketName});
const StorageOutputs({
required this.awsRegion,
required this.bucketName,
this.buckets,
});

factory StorageOutputs.fromJson(Map<String, Object?> json) =>
_$StorageOutputsFromJson(json);
Expand All @@ -23,8 +28,11 @@ class StorageOutputs
/// The Amazon S3 bucket name.
final String bucketName;

/// The list of buckets if there are multiple buckets for the project
final List<BucketOutputs>? buckets;

@override
List<Object?> get props => [awsRegion, bucketName];
List<Object?> get props => [awsRegion, bucketName, buckets];

@override
String get runtimeTypeName => 'StorageOutputs';
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ part 'network_exception.dart';
part 'push/push_notification_exception.dart';
part 'storage/access_denied_exception.dart';
part 'storage/http_status_exception.dart';
part 'storage/invalid_storage_bucket_exception.dart';
part 'storage/local_file_not_found_exception.dart';
part 'storage/not_found_exception.dart';
part 'storage/operation_canceled_exception.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
part of '../amplify_exception.dart';

/// {@template amplify_core.storage.invalid_storage_bucket_exception}
/// Exception thrown when the [StorageBucket] is invalid.
/// {@endtemplate}
class InvalidStorageBucketException extends StorageException {
const InvalidStorageBucketException(
super.message, {
super.recoverySuggestion,
super.underlyingException,
});

@override
String get runtimeTypeName => 'InvalidStorageBucketException';
}
24 changes: 24 additions & 0 deletions packages/amplify_core/lib/src/types/storage/bucket_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:amplify_core/amplify_core.dart';

/// {@template amplify_core.storage.bucket_info}
/// Presents a storage bucket information.
/// {@endtemplate}
class BucketInfo
with AWSEquatable<BucketInfo>, AWSSerializable<Map<String, Object?>> {
/// {@macro amplify_core.storage.bucket_info}
const BucketInfo({required this.bucketName, required this.region});
final String bucketName;
final String region;

@override
List<Object?> get props => [
bucketName,
region,
];

@override
Map<String, Object?> toJson() => {
'bucketName': bucketName,
'region': region,
};
}
24 changes: 24 additions & 0 deletions packages/amplify_core/lib/src/types/storage/copy_buckets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:amplify_core/amplify_core.dart';

/// Presents storage buckets for a copy operation.
class CopyBuckets with AWSSerializable<Map<String, Object?>> {
/// Creates a [CopyBuckets] with [source] and [destination] buckets.
const CopyBuckets({
required this.source,
required this.destination,
});

/// Creates a [CopyBuckets] with the same [bucket] for the [source] and [destination].
CopyBuckets.sameBucket(StorageBucket bucket)
: source = bucket,
destination = bucket;

final StorageBucket source;
final StorageBucket destination;

@override
Map<String, Object?> toJson() => {
'source': source.toJson(),
'destination': destination.toJson(),
};
}
13 changes: 10 additions & 3 deletions packages/amplify_core/lib/src/types/storage/copy_options.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:aws_common/aws_common.dart';
import 'package:amplify_core/amplify_core.dart';

/// {@template amplify_core.storage.copy_options}
/// Configurable options for `Amplify.Storage.copy`.
Expand All @@ -12,20 +12,27 @@ class StorageCopyOptions
AWSSerializable<Map<String, Object?>>,
AWSDebuggable {
/// {@macro amplify_core.storage.copy_options}
const StorageCopyOptions({this.pluginOptions});
const StorageCopyOptions({
this.pluginOptions,
this.buckets,
});

/// plugin specific options for `Amplify.Storage.copy`.
final StorageCopyPluginOptions? pluginOptions;

/// Optionally specify which buckets to target
final CopyBuckets? buckets;

@override
List<Object?> get props => [pluginOptions];
List<Object?> get props => [pluginOptions, buckets];

@override
String get runtimeTypeName => 'StorageCopyOptions';

@override
Map<String, Object?> toJson() => {
'pluginOptions': pluginOptions?.toJson(),
'buckets': buckets?.toJson(),
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:aws_common/aws_common.dart';
import 'package:amplify_core/amplify_core.dart';

/// {@template amplify_core.storage.download_data_options}
/// Configurable options for `Amplify.Storage.downloadData`.
Expand All @@ -14,20 +14,25 @@ class StorageDownloadDataOptions
/// {@macro amplify_core.storage.download_data_options}
const StorageDownloadDataOptions({
this.pluginOptions,
this.bucket,
});

/// {@macro amplify_core.storage.download_data_plugin_options}
final StorageDownloadDataPluginOptions? pluginOptions;

/// Optionally specify which bucket to target
final StorageBucket? bucket;

@override
List<Object?> get props => [pluginOptions];
List<Object?> get props => [pluginOptions, bucket];

@override
String get runtimeTypeName => 'StorageDownloadDataOptions';

@override
Map<String, Object?> toJson() => {
'pluginOptions': pluginOptions?.toJson(),
'bucket': bucket?.toJson(),
};
}

Expand Down
Loading
Loading