diff --git a/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(placement-groups)/create-placement-group.tsx b/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(placement-groups)/create-placement-group.tsx index e0329f1b2..26fa5d97b 100644 --- a/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(placement-groups)/create-placement-group.tsx +++ b/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(placement-groups)/create-placement-group.tsx @@ -138,6 +138,10 @@ function CreatePlacementGroup() { ) } +function shellSingleQuote(value: string): string { + return `'${value.replaceAll("'", `'"'"'`)}'` +} + function buildCreatePlacementGroupCommands( watch: (name?: string) => unknown, ): CliCommand[] { @@ -145,6 +149,7 @@ function buildCreatePlacementGroupCommands( const name = typeof rawName === "string" ? rawName : "" const rawStrategy = watch("strategy") const strategy = typeof rawStrategy === "string" ? rawStrategy : "" + const nameValue = name ? shellSingleQuote(name) : "" return [ { @@ -155,7 +160,7 @@ function buildCreatePlacementGroupCommands( value: "AWS_PROFILE=spinifex aws ec2 create-placement-group", }, { type: "flag", value: " \\\n --group-name" }, - { type: "value", value: ` ${name || ""}` }, + { type: "value", value: ` ${nameValue}` }, { type: "flag", value: " \\\n --strategy" }, { type: "value", value: ` ${strategy || "spread"}` }, ], diff --git a/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(target-groups)/-components/create-target-group-page.tsx b/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(target-groups)/-components/create-target-group-page.tsx index cedafd6bf..068d5b237 100644 --- a/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(target-groups)/-components/create-target-group-page.tsx +++ b/spinifex/services/spinifexui/frontend/src/routes/_auth/ec2/(target-groups)/-components/create-target-group-page.tsx @@ -121,6 +121,7 @@ function buildCreateTargetGroupCommands( const protocol = asString("protocol") || "HTTP" const port = asNumber("port") const vpcId = asString("vpcId") + const hcProtocol = asString("healthCheck.protocol") || "HTTP" const hcPath = asString("healthCheck.path") || "/" const hcPort = asString("healthCheck.port") || "traffic-port" const hcInterval = asNumber("healthCheck.intervalSeconds") @@ -151,7 +152,7 @@ function buildCreateTargetGroupCommands( } parts.push( { type: "flag", value: " \\\n --health-check-protocol" }, - { type: "value", value: " HTTP" }, + { type: "value", value: ` ${hcProtocol}` }, { type: "flag", value: " \\\n --health-check-path" }, { type: "value", value: ` ${hcPath}` }, { type: "flag", value: " \\\n --health-check-port" }, diff --git a/spinifex/services/spinifexui/frontend/src/routes/_auth/s3/-components/object-list-item.tsx b/spinifex/services/spinifexui/frontend/src/routes/_auth/s3/-components/object-list-item.tsx index 2636997c3..c0d2330cf 100644 --- a/spinifex/services/spinifexui/frontend/src/routes/_auth/s3/-components/object-list-item.tsx +++ b/spinifex/services/spinifexui/frontend/src/routes/_auth/s3/-components/object-list-item.tsx @@ -23,9 +23,11 @@ export function ObjectListItem({ fullKey, }: ObjectListItemProps) { const [showDeleteDialog, setShowDeleteDialog] = useState(false) + const [downloadError, setDownloadError] = useState(null) const deleteMutation = useDeleteObject() async function downloadObject() { + setDownloadError(null) try { const command = new GetObjectCommand({ Bucket: bucketName, @@ -48,7 +50,7 @@ export function ObjectListItem({ URL.revokeObjectURL(url) } } catch (error) { - throw new Error("Failed to download object", { cause: error }) + setDownloadError(new Error("Failed to download object", { cause: error })) } } @@ -71,6 +73,9 @@ export function ObjectListItem({ msg="Failed to delete object" /> )} + {downloadError && ( + + )}
diff --git a/spinifex/services/spinifexui/frontend/src/types/ec2.ts b/spinifex/services/spinifexui/frontend/src/types/ec2.ts index 7e8eccf8e..8d14615bd 100644 --- a/spinifex/services/spinifexui/frontend/src/types/ec2.ts +++ b/spinifex/services/spinifexui/frontend/src/types/ec2.ts @@ -243,7 +243,11 @@ export const createPlacementGroupSchema = z.object({ groupName: z .string() .min(1, "Group name is required") - .max(255, "Group name must be 255 characters or less"), + .max(255, "Group name must be 255 characters or less") + .regex( + /^[\w\s._\-:/()#,@[\]+=&;{}!$*]+$/, + "Group name contains invalid characters", + ), strategy: z.string().min(1, "Strategy is required"), }) diff --git a/spinifex/services/spinifexui/frontend/src/types/iam.ts b/spinifex/services/spinifexui/frontend/src/types/iam.ts index a5297b029..bb3676994 100644 --- a/spinifex/services/spinifexui/frontend/src/types/iam.ts +++ b/spinifex/services/spinifexui/frontend/src/types/iam.ts @@ -15,7 +15,8 @@ export const createPolicySchema = z.object({ policyName: z .string() .min(1, "Policy name is required") - .max(128, "Policy name must be 128 characters or less"), + .max(128, "Policy name must be 128 characters or less") + .regex(/^[\w+=,.@-]+$/, "Policy name contains invalid characters"), description: z.string().optional(), policyDocument: z .string()