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

Private Files and Asset Delivery #3799

Merged
merged 101 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
4728d1d
wip: setup cookies and add response headers class
Pavel910 Dec 2, 2023
3fcc68b
wip: implement asset delivery
Pavel910 Dec 11, 2023
171359d
wip: implement asset transformation
Pavel910 Dec 19, 2023
d358a94
feat(plugins): add AsyncPluginsContainer
Pavel910 Dec 19, 2023
f74ff2a
fix(handler): remove fastify instance from context
Pavel910 Dec 19, 2023
12bf966
feat(handler-aws): use AsyncPluginsContainer
Pavel910 Dec 19, 2023
940b437
feat(handler): add Context support for PluginsContainer
Pavel910 Dec 19, 2023
bced093
Merge branch 'pavel/feat/async-plugins-container' into pavel/feat/pri…
Pavel910 Dec 19, 2023
7b0633c
fix(project-utils): enable code splitting of Lambda bundles
Pavel910 Dec 20, 2023
cdc87a7
wip: enable cookie config when private files are used
Pavel910 Dec 20, 2023
a4320b4
Merge branch 'next' into pavel/feat/private-files
Pavel910 Dec 20, 2023
76765b0
wip: add accessControl field
Pavel910 Dec 21, 2023
e331986
wip: add private files checks
Pavel910 Dec 21, 2023
cf3ab0e
merge: pull in changes from next
Pavel910 Dec 21, 2023
52c0f9c
wip: enable cookies and secure headers by default
Pavel910 Dec 22, 2023
d13b721
wip: implement cache control and service discovery
Pavel910 Dec 26, 2023
f82eea7
wip: service discovery
Pavel910 Dec 27, 2023
4790100
wip(tasks): start with tasks
brunozoric Nov 29, 2023
526625c
wip(tasks): split plugin and definition
brunozoric Nov 30, 2023
c893c45
wip(tasks): task runs
brunozoric Dec 4, 2023
baa2829
feat(api-headless-cms): add json type field
brunozoric Dec 4, 2023
cdaec0a
feat(tasks): graphql and crud
brunozoric Dec 5, 2023
13f2297
refactor(tasks): database response manager
brunozoric Dec 5, 2023
b1a7083
chore: update ts configs
brunozoric Dec 5, 2023
f37579f
refactor(tasks): rename tests
brunozoric Dec 6, 2023
7c9c1ea
feat(tasks): add step fn token to input and output
brunozoric Dec 6, 2023
900cb92
refactor(tasks): add state machine id to event
brunozoric Dec 8, 2023
43bbadb
feat(tasks): task crud
brunozoric Dec 8, 2023
f1cbee2
refactor(pulumi-aws): background tasks
brunozoric Dec 8, 2023
0712207
refactor(pulumi-aws): background tasks logging policy
brunozoric Dec 11, 2023
4bbb104
refactor(tasks): simplify response types
brunozoric Dec 12, 2023
5cb1a27
refactor(tasks): move classes and abstractions
brunozoric Dec 12, 2023
97dba6c
refactor(pulumi-aws): update step function definition
brunozoric Dec 12, 2023
c7294a5
feat(pulumi-aws): add waiting possibility in background task
brunozoric Dec 13, 2023
1373616
test(tasks): add crud tests
brunozoric Dec 13, 2023
e7825d2
test(tasks): definitions crud
brunozoric Dec 13, 2023
8f8bdac
fix(tasks): expose graphql
brunozoric Dec 13, 2023
37b0232
test(tasks): task manager and event validation
brunozoric Dec 14, 2023
e4fed20
feat(pulumi-aws): deploy event bridge to step fn connection
brunozoric Dec 14, 2023
68fe0e7
feat(tasks): implement graphql
brunozoric Dec 14, 2023
3d38d48
feat(tasks): ability to stop a task
brunozoric Dec 15, 2023
1f35cd1
test(tasks): graphql to list tasks from database
brunozoric Dec 15, 2023
7a110d4
test(tasks): trigger crud
brunozoric Dec 15, 2023
1bf99e2
fix(tests): validate task definition id
brunozoric Dec 15, 2023
0be1a4e
test(tasks): modify tasks to camel cased id
brunozoric Dec 15, 2023
45e7a17
feat(tasks): add task values store method
brunozoric Dec 18, 2023
3cda7ca
feat(api-elasticsearch-tasks): indexing
brunozoric Dec 18, 2023
d3bb26b
feat(api-elasticsearch-task): code split task runner
brunozoric Dec 19, 2023
aa2520a
feat(api-background-tasks): wrapper for tasks and definitions
brunozoric Dec 19, 2023
034ad7f
fix(api-background-tasks): readme
brunozoric Dec 19, 2023
ee4b630
fix(tasks): store task management
brunozoric Dec 19, 2023
b061762
test(api-elasticsearch-tasks): wip reindexing
brunozoric Dec 19, 2023
6dbd877
feat(api-background-tasks-dynamodb): ddb tasks
brunozoric Dec 20, 2023
a13cc0d
feat(api-background-tasks-es): elasticsearch tasks
brunozoric Dec 20, 2023
2f3830f
feat(api-background-tasks-os): opensearch tasks
brunozoric Dec 20, 2023
c59aa4a
refactor: rename dynamodb tasks package
brunozoric Dec 20, 2023
112c55d
fix(cwp-template-aws): dynamodb setup
brunozoric Dec 20, 2023
0bf0c6a
fix(cwp-template-aws): os setup
brunozoric Dec 20, 2023
9a33a8d
fix(tasks): event input
brunozoric Dec 20, 2023
c920e8e
refactor(tasks): graphql type names
brunozoric Dec 21, 2023
15b129d
feat(pulumi-aws): step to transform event input into lambda input
brunozoric Dec 21, 2023
bd480da
feat: add count dynamodb items task to dev deployment
brunozoric Dec 21, 2023
3b7cec6
fix: deployment is missing some packages because they are private
brunozoric Dec 22, 2023
7af4aca
feat(tasks): enable users to wait certain amount of time to continue …
brunozoric Dec 22, 2023
a8abed7
refactor(pulumi-aws): wait task use new response var
brunozoric Dec 22, 2023
901ef88
refactor: continuing task
brunozoric Dec 22, 2023
720aceb
fix: task status after next merge
brunozoric Dec 26, 2023
21fbcd5
fix(project-utils): add sharp to webpack externals for all Lambda fun…
Pavel910 Dec 29, 2023
b478199
feat(pulumi-aws): add sharp layer to background task function
Pavel910 Dec 29, 2023
f0dc6cc
feat(handler): process response headers in onSend hook
Pavel910 Dec 29, 2023
1f7c11e
fix(project-utils): improve handling of browser dependencies (CSS and…
Pavel910 Dec 29, 2023
886701f
feat(aws-layers): add ts definition
brunozoric Dec 30, 2023
4084848
fix(pulumi-aws): remove unnecessary expect error
brunozoric Dec 30, 2023
80caed7
merge: background tasks branch
Pavel910 Jan 1, 2024
7ad2edf
fix(cwp-template-aws): position of background tasks init
brunozoric Jan 2, 2024
1caf5ad
fix(tasks): updating task
brunozoric Jan 2, 2024
17b4f1d
fix(db-dynamodb): retry batch write on unprocessed items
brunozoric Jan 2, 2024
125ead4
fix(pulumi-aws): aborted status
brunozoric Jan 2, 2024
031632f
fix(api-elasticsearch-tasks): method to add logs is now user friendly
brunozoric Jan 2, 2024
b0fa4c1
refactor(tasks): export all types from root
brunozoric Jan 2, 2024
fa873b7
feat(api): add ServiceDiscovery class
Pavel910 Jan 3, 2024
51711fa
fix(pulumi-aws): add permission to create cache invalidation
Pavel910 Jan 3, 2024
33ad86b
chore: remove console logs
Pavel910 Jan 3, 2024
5a132ca
feat(app-headless-cms-common): make prepareFormData generic
Pavel910 Jan 3, 2024
e80f538
feat(aws-sdk): add sfn package
brunozoric Jan 4, 2024
0f9c340
feat(pulumi-aws): pass execution name into lambda
brunozoric Jan 4, 2024
7148aab
refactor(tasks): add additional fields into the task model
brunozoric Jan 4, 2024
8250161
refactor(api-elasticsearch-tasks): implement changes from tasks package
brunozoric Jan 4, 2024
4b957fa
fix(tasks): convert Error into plain object for output
brunozoric Jan 4, 2024
b233c96
feat: add built-in fields to bulk edit dialog
Pavel910 Jan 5, 2024
454a5d8
chore: use params object in decorators
Pavel910 Jan 5, 2024
a453f5c
feat(app-page-builder): export composable components
Pavel910 Jan 5, 2024
42de519
Merge branch 'bruno/feat/webiny-tasks' into pavel/feat/private-files
Pavel910 Jan 5, 2024
26da803
refactor(tasks): rename task property values to input
brunozoric Jan 6, 2024
cb07e3d
chore: add asset delivery to ddb-os template
Pavel910 Jan 6, 2024
7056015
Merge branch 'bruno/feat/webiny-tasks' into pavel/feat/private-files
Pavel910 Jan 8, 2024
345dcc6
Merge remote-tracking branch 'origin/next' into pavel/feat/private-files
Pavel910 Jan 8, 2024
179c03f
Merge branch 'next' into pavel/feat/private-files
Pavel910 Jan 8, 2024
21072a1
fix: resolve conflicts and type issues
Pavel910 Jan 8, 2024
cdf683d
merge: pull changes from next
Pavel910 Jan 9, 2024
372da80
fix: remove unused vars and disable download test
Pavel910 Jan 9, 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
15 changes: 0 additions & 15 deletions apps/api/fileManager/download/package.json

This file was deleted.

15 changes: 0 additions & 15 deletions apps/api/fileManager/download/src/index.ts

This file was deleted.

21 changes: 0 additions & 21 deletions apps/api/fileManager/download/tsconfig.json

This file was deleted.

8 changes: 0 additions & 8 deletions apps/api/fileManager/download/webiny.config.ts

This file was deleted.

14 changes: 0 additions & 14 deletions apps/api/fileManager/transform/package.json

This file was deleted.

6 changes: 0 additions & 6 deletions apps/api/fileManager/transform/src/index.ts

This file was deleted.

18 changes: 0 additions & 18 deletions apps/api/fileManager/transform/tsconfig.json

This file was deleted.

13 changes: 0 additions & 13 deletions apps/api/fileManager/transform/webiny.config.ts

This file was deleted.

5 changes: 2 additions & 3 deletions apps/api/graphql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from "@webiny/api-file-manager";
import { createFileManagerStorageOperations } from "@webiny/api-file-manager-ddb";
import logsPlugins from "@webiny/handler-logs";
import fileManagerS3 from "@webiny/api-file-manager-s3";
import fileManagerS3, { createAssetDelivery } from "@webiny/api-file-manager-s3";
import { createFormBuilder } from "@webiny/api-form-builder";
import { createFormBuilderStorageOperations } from "@webiny/api-form-builder-so-ddb";
import { createHeadlessCmsContext, createHeadlessCmsGraphQL } from "@webiny/api-headless-cms";
Expand All @@ -36,8 +36,6 @@ import { createAco } from "@webiny/api-aco";
import { createAcoPageBuilderContext } from "@webiny/api-page-builder-aco";
import { createAuditLogs } from "@webiny/api-audit-logs";
import { createBackgroundTasks } from "@webiny/api-background-tasks-ddb";

// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";
import { createBenchmarkEnablePlugin } from "~/plugins/benchmarkEnable";
import { createCountDynamoDbTask } from "~/plugins/countDynamoDbTask";
Expand Down Expand Up @@ -75,6 +73,7 @@ export const handler = createHandler({
})
}),
createFileManagerGraphQL(),
createAssetDelivery({ documentClient }),
fileManagerS3(),
prerenderingServicePlugins({
eventBus: String(process.env.EVENT_BUS)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"rimraf": "^3.0.2",
"rxjs": "^6.5.5",
"semver": "^7.5.4",
"ts-expect": "^1.3.0",
"ts-jest": "^29.1.0",
"typescript": "4.7.4",
"typescript-transform-paths": "^2.2.3",
Expand Down
6 changes: 5 additions & 1 deletion packages/api-file-manager-s3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
"@webiny/api-security": "0.0.0",
"@webiny/aws-sdk": "0.0.0",
"@webiny/error": "0.0.0",
"@webiny/handler": "0.0.0",
"@webiny/handler-graphql": "0.0.0",
"@webiny/plugins": "0.0.0",
"@webiny/tasks": "0.0.0",
"@webiny/utils": "0.0.0",
"@webiny/validation": "0.0.0",
"form-data": "^4.0.0",
"mime": "^3.0.0",
"node-fetch": "^2.6.1",
"object-hash": "^3.0.0",
"p-map": "4.0.0",
"p-reduce": "2.1.0",
"sanitize-filename": "^1.6.3"
"sanitize-filename": "^1.6.3",
"sharp": "0.32.6"
},
"devDependencies": {
"@babel/cli": "^7.22.6",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
createAssetDelivery as createBaseAssetDelivery,
createAssetDeliveryConfig
} from "@webiny/api-file-manager";
import { S3 } from "@webiny/aws-sdk/client-s3";
import { S3AssetResolver } from "~/assetDelivery/s3/S3AssetResolver";
import { S3OutputStrategy } from "~/assetDelivery/s3/S3OutputStrategy";
import { SharpTransform } from "~/assetDelivery/s3/SharpTransform";

export type AssetDeliveryParams = Parameters<typeof createBaseAssetDelivery>[0] & {
imageResizeWidths?: number[];
presignedUrlTtl?: number;
};

export const assetDeliveryConfig = (params: AssetDeliveryParams) => {
const bucket = process.env.S3_BUCKET as string;
const region = process.env.AWS_REGION as string;

const {
presignedUrlTtl = 900,
imageResizeWidths = [100, 300, 500, 750, 1000, 1500, 2500],
...baseParams
} = params;

return [
// Base asset delivery
createBaseAssetDelivery(baseParams),
// S3 plugins
createAssetDeliveryConfig(config => {
const s3 = new S3({ region });

config.decorateAssetResolver(() => {
// This resolver loads file information from the `.metadata` file.
return new S3AssetResolver(s3, bucket);
});

config.decorateAssetOutputStrategy(() => {
return new S3OutputStrategy(s3, bucket, presignedUrlTtl);
});

config.decorateAssetTransformationStrategy(() => {
return new SharpTransform({ s3, bucket, imageResizeWidths });
});
})
];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createAssetDeliveryPluginLoader } from "@webiny/api-file-manager";
import { PluginFactory } from "@webiny/plugins/types";
import type { AssetDeliveryParams } from "./assetDeliveryConfig";

export const createAssetDelivery = (params: AssetDeliveryParams): PluginFactory => {
/**
* We only want to load this plugin in the context of the Asset Delivery Lambda function.
*/
return createAssetDeliveryPluginLoader(() => {
return import(/* webpackChunkName: "s3AssetDelivery" */ "./assetDeliveryConfig").then(
({ assetDeliveryConfig }) => assetDeliveryConfig(params)
);
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { S3 } from "@webiny/aws-sdk/client-s3";

interface AssetMetadata {
id: string;
tenant: string;
locale: string;
size: number;
contentType: string;
}

export class S3AssetMetadataReader {
private readonly s3: S3;
private readonly bucket: string;

constructor(s3: S3, bucket: string) {
this.bucket = bucket;
this.s3 = s3;
}

async getMetadata(key: string): Promise<AssetMetadata> {
const metadataKey = `${key}.metadata`;

console.log("Reading metadata", metadataKey);

const { Body } = await this.s3.getObject({
Bucket: this.bucket,
Key: metadataKey
});

if (!Body) {
throw Error(`Missing or corrupted ${metadataKey} file!`);
}

const metadata = JSON.parse(await Body.transformToString());

return {
id: metadata.id,
tenant: metadata.tenant,
locale: metadata.locale,
size: metadata.size,
contentType: metadata.contentType
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { S3 } from "@webiny/aws-sdk/client-s3";
import { Asset, AssetRequest, AssetResolver } from "@webiny/api-file-manager";
import { S3AssetMetadataReader } from "./S3AssetMetadataReader";
import { S3ContentsReader } from "./S3ContentsReader";

export class S3AssetResolver implements AssetResolver {
private readonly s3: S3;
private readonly bucket: string;

constructor(s3: S3, bucket: string) {
this.s3 = s3;
this.bucket = bucket;
}

async resolve(request: AssetRequest): Promise<Asset | undefined> {
try {
const metadataReader = new S3AssetMetadataReader(this.s3, this.bucket);
const metadata = await metadataReader.getMetadata(request.getKey());

const asset = new Asset({
id: metadata.id,
tenant: metadata.tenant,
locale: metadata.locale,
size: metadata.size,
contentType: metadata.contentType,
key: request.getKey()
});

asset.setContentsReader(new S3ContentsReader(this.s3, this.bucket));

return asset;
} catch (error) {
console.error(error);
return undefined;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { S3 } from "@webiny/aws-sdk/client-s3";
import { Asset, AssetContentsReader } from "@webiny/api-file-manager";

export class S3ContentsReader implements AssetContentsReader {
private s3: S3;
private readonly bucket: string;

constructor(s3: S3, bucket: string) {
this.s3 = s3;
this.bucket = bucket;
}

async read(asset: Asset): Promise<Buffer> {
const { Body } = await this.s3.getObject({
Bucket: this.bucket,
Key: asset.getKey()
});

if (!Body) {
throw Error(`Unable to read ${asset.getKey()}!`);
}

return Buffer.from(await Body.transformToByteArray());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { AssetReply } from "@webiny/api-file-manager";

export class S3ErrorAssetReply extends AssetReply {
constructor(message: string) {
super({
code: 400,
body: () => ({ error: message })
});
}
}
Loading
Loading