Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 19 additions & 1 deletion infra/storage_client/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ services:
FILE_STORAGE_BACKEND_PATH: /tmp/storage
ENABLE_IMAGE_TRANSFORMATION: "true"
IMGPROXY_URL: http://imgproxy:8080
DEBUG: "knex:*"

volumes:
- assets-volume:/tmp/storage
healthcheck:
test: ['CMD-SHELL', 'curl -f -LI http://localhost:5000/status']
interval: 2s

db:
build:
context: ./postgres
Expand All @@ -62,6 +66,20 @@ services:
timeout: 5s
retries: 5

dummy_data:
build:
context: ./postgres
depends_on:
storage:
condition: service_healthy
volumes:
- ./postgres:/sql
command:
- psql
- "postgresql://postgres:postgres@db:5432/postgres"
- -f
- /sql/dummy-data.sql

imgproxy:
image: darthsim/imgproxy
ports:
Expand All @@ -73,4 +91,4 @@ services:
- IMGPROXY_USE_ETAG=true
- IMGPROXY_ENABLE_WEBP_DETECTION=true
volumes:
assets-volume:
assets-volume:
3 changes: 1 addition & 2 deletions infra/storage_client/postgres/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ FROM supabase/postgres:0.13.0
COPY 00-initial-schema.sql /docker-entrypoint-initdb.d/00-initial-schema.sql
COPY auth-schema.sql /docker-entrypoint-initdb.d/01-auth-schema.sql
COPY storage-schema.sql /docker-entrypoint-initdb.d/02-storage-schema.sql
COPY dummy-data.sql /docker-entrypoint-initdb.d/03-dummy-data.sql

# Build time defaults
ARG build_POSTGRES_DB=postgres
Expand All @@ -17,4 +16,4 @@ ENV POSTGRES_USER=$build_POSTGRES_USER
ENV POSTGRES_PASSWORD=$build_POSTGRES_PASSWORD
ENV POSTGRES_PORT=$build_POSTGRES_PORT

EXPOSE 5432
EXPOSE 5432
18 changes: 7 additions & 11 deletions infra/storage_client/postgres/storage-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ CREATE TABLE "storage"."objects" (
"last_accessed_at" timestamptz DEFAULT now(),
"metadata" jsonb,
CONSTRAINT "objects_bucketId_fkey" FOREIGN KEY ("bucket_id") REFERENCES "storage"."buckets"("id"),
CONSTRAINT "objects_owner_fkey" FOREIGN KEY ("owner") REFERENCES "auth"."users"("id"),
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "bucketid_objname" ON "storage"."objects" USING BTREE ("bucket_id","name");
Expand Down Expand Up @@ -85,27 +84,24 @@ CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits i
)
LANGUAGE plpgsql
AS $function$
DECLARE
_bucketId text;
BEGIN
select buckets."id" from buckets where buckets.name=bucketname limit 1 into _bucketId;
return query
return query
with files_folders as (
select ((string_to_array(objects.name, '/'))[levels]) as folder
from objects
where objects.name ilike prefix || '%'
and bucket_id = _bucketId
and bucket_id = bucketname
GROUP by folder
limit limits
offset offsets
)
select files_folders.folder as name, objects.id, objects.updated_at, objects.created_at, objects.last_accessed_at, objects.metadata from files_folders
)
select files_folders.folder as name, objects.id, objects.updated_at, objects.created_at, objects.last_accessed_at, objects.metadata from files_folders
left join objects
on prefix || files_folders.folder = objects.name
where objects.id is null or objects.bucket_id=_bucketId;
on prefix || files_folders.folder = objects.name and objects.bucket_id=bucketname;
END
$function$;

GRANT ALL PRIVILEGES ON SCHEMA storage TO postgres;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA storage TO postgres;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA storage TO postgres;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA storage TO postgres;

4 changes: 2 additions & 2 deletions infra/storage_client/storage/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
FROM supabase/storage-api:v0.35.1
FROM supabase/storage-api:v1.8.2

RUN apk add curl --no-cache
RUN apk add curl --no-cache
18 changes: 16 additions & 2 deletions packages/storage_client/lib/src/storage_file_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,21 @@ class StorageFileApi {
/// example `folder/image.png`.
/// [toPath] is the new file path, including the new file name. For example
/// `folder/image-new.png`.
Future<String> move(String fromPath, String toPath) async {
///
/// When copying to a different bucket, you have to specify the [destinationBucket].
Future<String> move(
String fromPath,
String toPath, {
String? destinationBucket,
}) async {
final options = FetchOptions(headers: headers);
final response = await _storageFetch.post(
'$url/object/move',
{
'bucketId': bucketId,
'sourceKey': fromPath,
'destinationKey': toPath,
if (destinationBucket != null) 'destinationBucket': destinationBucket,
},
options: options,
);
Expand All @@ -297,14 +304,21 @@ class StorageFileApi {
///
/// [toPath] is the new file path, including the new file name. For example
/// `folder/image-copy.png`.
Future<String> copy(String fromPath, String toPath) async {
///
/// When copying to a different bucket, you have to specify the [destinationBucket].
Future<String> copy(
String fromPath,
String toPath, {
String? destinationBucket,
}) async {
final options = FetchOptions(headers: headers);
final response = await _storageFetch.post(
'$url/object/copy',
{
'bucketId': bucketId,
'sourceKey': fromPath,
'destinationKey': toPath,
if (destinationBucket != null) 'destinationBucket': destinationBucket,
},
options: options,
);
Expand Down
46 changes: 46 additions & 0 deletions packages/storage_client/test/client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -388,5 +388,51 @@ void main() {

await storage.from(newBucketName).copy(uploadPath, "$uploadPath 2");
});

test('copy to different bucket', () async {
final storage = SupabaseStorageClient(
storageUrl, {'Authorization': 'Bearer $storageKey'});

try {
await storage.from('bucket2').download(uploadPath);
fail('File that does not exist was found');
} on StorageException catch (error) {
expect(error.error, 'not_found');
}
await storage
.from(newBucketName)
.copy(uploadPath, uploadPath, destinationBucket: 'bucket2');
try {
await storage.from('bucket2').download(uploadPath);
} catch (error) {
fail('File that was copied was not found');
}
});

test('move to different bucket', () async {
final storage = SupabaseStorageClient(
storageUrl, {'Authorization': 'Bearer $storageKey'});

try {
await storage.from('bucket2').download('$uploadPath 3');
fail('File that does not exist was found');
} on StorageException catch (error) {
expect(error.error, 'not_found');
}
await storage
.from(newBucketName)
.move(uploadPath, '$uploadPath 3', destinationBucket: 'bucket2');
try {
await storage.from('bucket2').download('$uploadPath 3');
} catch (error) {
fail('File that was moved was not found');
}
try {
await storage.from(newBucketName).download(uploadPath);
fail('File that was moved was found');
} on StorageException catch (error) {
expect(error.error, 'not_found');
}
});
});
}