Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
5 changes: 5 additions & 0 deletions .changeset/whole-feet-win.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-app-products-feed": minor
---

change the s3 configuration form of app/product-feed to be more generic, to allow custom endpoints, regions and allow to toggle path style endpoints.
14 changes: 8 additions & 6 deletions apps/products-feed/generated/graphql.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ fragment GoogleFeedProductVariant on ProductVariant {
url
}
category {
slug
id
name
googleCategoryId: metafield(key: "google_category_id")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
fragment RelatedProducts on Product {
id
name
slug
description
seoDescription
productType {
isShippingRequired
}
media {
id
alt
url(size: $imageSize)
type
}
variants {
id
name
slug
description
seoDescription
productType {
isShippingRequired
}
media {
id
alt
url(size: $imageSize)
type
}
variants {
id
media{
id
alt
url(size: $imageSize)
type
}
id
alt
url(size: $imageSize)
type
}
attributes{
attribute{
id
}
values{
value
name
}
}
attributes {
attribute {
id
}
thumbnail(size: $imageSize) {
url
values {
value
name
}
category {
id
name
googleCategoryId: metafield(key: "google_category_id")
}

}
thumbnail(size: $imageSize) {
url
}
category {
id
slug
name
googleCategoryId: metafield(key: "google_category_id")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const s3ConfigSchema = z.object({
secretAccessKey: z.string().min(1),
accessKeyId: z.string().min(1),
region: z.string().min(1),
endpoint: z.string().optional(),
forcePathStyle: z.boolean().default(false),
});

const urlConfigurationSchema = z.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const appConfigurationRouter = router({
try {
await checkBucketAccess({
bucketName: input.bucketName,
endpoint: input?.endpoint,
s3Client,
});
logger.info("Verification succeeded");
Expand All @@ -59,8 +60,9 @@ export const appConfigurationRouter = router({
});
throw new TRPCError({
code: "BAD_REQUEST",
message:
"Could not access the S3 bucket using the provided credentials. Check permissions",
message: `Could not access the S3 bucket using the provided credentials. ${(
e as Error
).toString()}`,
});
}
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useDashboardNotification } from "@saleor/apps-shared/use-dashboard-notification";
import { Box, Button, Text } from "@saleor/macaw-ui";
import { Input, Select } from "@saleor/react-hook-form-macaw";
import { Input, Toggle } from "@saleor/react-hook-form-macaw";
import { useCallback, useMemo } from "react";
import { useForm } from "react-hook-form";

import { awsRegionList } from "../file-storage/s3/aws-region-list";
import { trpcClient } from "../trpc/trpc-client";
import { AppConfigSchema, RootConfig } from "./app-config";

Expand Down Expand Up @@ -33,25 +32,41 @@ export const S3ConfigurationForm = (props: Props) => {
props.onSubmit(data);
})}
>
<Input size={"small"} name={"accessKeyId"} control={control} label="Amazon access key ID" />
<Input size={"small"} name={"accessKeyId"} control={control} label="Access key ID" />

<Input
type={"password"}
size={"small"}
name={"secretAccessKey"}
control={control}
label="Amazon secret access key"
label="Secret access key"
/>

<Input size={"small"} name={"bucketName"} control={control} label="Bucket name" />

<Select
{/* <Select */}
{/* control={control} */}
{/* label="Region" */}
{/* name={"region"} */}
{/* required={false} */}
{/* options={awsRegionList.map((region) => ({ label: region, value: region }))} */}
{/* /> */}

<Input required={true} size={"small"} name={"region"} control={control} label="Region" />
Comment thread
lkostrowski marked this conversation as resolved.
Outdated

<Input
required={false}
size={"small"}
name={"endpoint"}
control={control}
label="Region"
name={"region"}
options={awsRegionList.map((region) => ({ label: region, value: region }))}
label="Custom S3 compatible endpoint (leave empty for AWS)"
/>

<Box as="label" display="flex" gap={2} cursor="pointer">
<Toggle name={"forcePathStyle"} control={control} type="button" />
<Text marginLeft={2}>Force path style (leave off for AWS)</Text>
Comment thread
djkato marked this conversation as resolved.
Outdated
</Box>

<Box display={"flex"} flexDirection={"row"} gap={4} justifyContent={"flex-end"}>
<Button variant="secondary" onClick={() => props.onValidate(getValues())}>
Test credentials
Expand Down Expand Up @@ -117,6 +132,7 @@ export const ConnectedS3ConfigurationForm = () => {
bucketName: "",
region: "",
secretAccessKey: "",
forcePathStyle: false,
};
}, [data]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,28 @@ import {
interface checkBucketAccessArgs {
s3Client: S3Client;
bucketName: string;
endpoint?: string;
}

// Check if client can access the bucket. Throws an error otherwise
export const checkBucketAccess = async ({ s3Client, bucketName }: checkBucketAccessArgs) => {
export const checkBucketAccess = async ({
s3Client,
bucketName,
endpoint,
}: checkBucketAccessArgs) => {
const file = "saleor_product_feed_temp/verification_file";

if (endpoint) {
try {
new URL(endpoint);
} catch (e) {
throw new Error(
"Failed to check access, verify endpoint URL is a valid URL (Has to start with 'http(s)://')",
{ cause: e },
);
}
}

const putCommand = new PutObjectCommand({
Bucket: bucketName,
Key: file,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ export const createS3ClientFromConfiguration = ({
accessKeyId,
secretAccessKey,
region,
endpoint,
forcePathStyle,
}: Exclude<RootConfig["s3"], null>) => {
return new S3Client({
endpoint,
forcePathStyle,
credentials: {
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
Expand Down
3 changes: 2 additions & 1 deletion apps/products-feed/turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"DYNAMODB_REQUEST_TIMEOUT_MS",
"DYNAMODB_CONNECTION_TIMEOUT_MS",
"MANIFEST_APP_ID",
"FILE_APL_PATH"
"FILE_APL_PATH",
"APP_API_BASE_URL"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@djkato duplicated line with L9

]
}
}
Expand Down
Loading