@ampless/backend 1.0.0-beta.78 → 1.0.0-beta.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events/processor-trusted.js +11 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -11
- package/package.json +3 -3
|
@@ -64,14 +64,6 @@ function decryptSecret(rawKey, b64) {
|
|
|
64
64
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
65
65
|
return plaintext.toString("utf8");
|
|
66
66
|
}
|
|
67
|
-
function safeParse(s) {
|
|
68
|
-
try {
|
|
69
|
-
return JSON.parse(s);
|
|
70
|
-
} catch (err) {
|
|
71
|
-
console.warn("[trusted-processor] post.body is not valid JSON; passing through as string", err);
|
|
72
|
-
return s;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
67
|
function createProcessorTrustedHandler(opts) {
|
|
76
68
|
const privilegedHookedPlugins = (opts.plugins ?? []).filter(
|
|
77
69
|
(p) => typeof p === "object" && p.trust_level === "privileged" && !!p.hooks && Object.keys(p.hooks).length > 0
|
|
@@ -145,7 +137,15 @@ function createProcessorTrustedHandler(opts) {
|
|
|
145
137
|
title: row.title,
|
|
146
138
|
excerpt: row.excerpt ?? void 0,
|
|
147
139
|
format: row.format ?? "markdown",
|
|
148
|
-
|
|
140
|
+
// DynamoDBDocumentClient unmarshals AWSJSON-backed attributes
|
|
141
|
+
// into native JS types (S→string, N→number, BOOL→boolean,
|
|
142
|
+
// M→object), so `row.body` is already correctly typed here and
|
|
143
|
+
// must NOT be re-parsed. Re-running JSON.parse on a pure-numeric
|
|
144
|
+
// or JSON-looking string body (e.g. a markdown/html body of
|
|
145
|
+
// "1470" or "123") double-decodes it into a number and corrupts
|
|
146
|
+
// the post. Only the Amplify GraphQL-client read path returns an
|
|
147
|
+
// AWSJSON wire string and needs decodeAwsJson.
|
|
148
|
+
body: row.body,
|
|
149
149
|
status: row.status ?? "published",
|
|
150
150
|
publishedAt: row.publishedAt ?? void 0,
|
|
151
151
|
tags: Array.isArray(row.tags) ? row.tags : []
|
|
@@ -281,7 +281,7 @@ function createProcessorTrustedHandler(opts) {
|
|
|
281
281
|
const sk = row.sk;
|
|
282
282
|
if (!sk) continue;
|
|
283
283
|
const raw = row.value;
|
|
284
|
-
settings[sk] =
|
|
284
|
+
settings[sk] = raw;
|
|
285
285
|
}
|
|
286
286
|
exclusiveStartKey = res.LastEvaluatedKey;
|
|
287
287
|
} while (exclusiveStartKey);
|
|
@@ -314,7 +314,7 @@ function createProcessorTrustedHandler(opts) {
|
|
|
314
314
|
try {
|
|
315
315
|
await rebuildSiteSettingsCache();
|
|
316
316
|
} catch (err) {
|
|
317
|
-
console.error("[trusted-processor] site-settings-cache rebuild failed", err);
|
|
317
|
+
console.error("[trusted-processor][ALERT] site-settings-cache rebuild failed", err);
|
|
318
318
|
throw err;
|
|
319
319
|
}
|
|
320
320
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -170,6 +170,7 @@ declare function amplessAuthConfig(opts?: AmplessAuthConfigOpts): Parameters<typ
|
|
|
170
170
|
* Build the ampless S3 bucket configuration as a plain options object
|
|
171
171
|
* suitable for `defineStorage(...)`. Access map:
|
|
172
172
|
* - `public/media/*` — guest read, admin/editor full
|
|
173
|
+
* - `public/static/*` — guest read, admin/editor full (static-bundle posts)
|
|
173
174
|
* - `public/plugins/*` — guest read, admin full
|
|
174
175
|
*
|
|
175
176
|
* Bucket-level overrides (PublicAccessBlock, CORS, IAM policies for
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,9 @@ import { FunctionUrlAuthType, HttpMethod, StartingPosition } from "aws-cdk-lib/a
|
|
|
7
7
|
import { DynamoEventSource, SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
8
8
|
import { Rule, Schedule } from "aws-cdk-lib/aws-events";
|
|
9
9
|
import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
|
|
10
|
+
function siteSettingsCacheS3Resources(bucketArn) {
|
|
11
|
+
return [`${bucketArn}/public/plugins/*`, `${bucketArn}/public/site-settings.json`];
|
|
12
|
+
}
|
|
10
13
|
function defineAmplessBackend(opts) {
|
|
11
14
|
const backend = defineBackend({
|
|
12
15
|
auth: opts.auth,
|
|
@@ -152,17 +155,15 @@ function defineAmplessBackend(opts) {
|
|
|
152
155
|
new PolicyStatement({
|
|
153
156
|
effect: Effect.ALLOW,
|
|
154
157
|
actions: ["s3:PutObject", "s3:DeleteObject"],
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
`${backend.storage.resources.bucket.bucketArn}/public/site-settings.json`
|
|
165
|
-
]
|
|
158
|
+
// Built-in cache: rebuildSiteSettingsCache writes the single JSON
|
|
159
|
+
// file the public site reads. The resource list MUST contain the
|
|
160
|
+
// exact-match key `public/site-settings.json` — a wildcard like
|
|
161
|
+
// `public/site-settings/*` would NOT match the single-file key and
|
|
162
|
+
// the PutObject would fail silently with AccessDenied, so the public
|
|
163
|
+
// site would never see admin-side theme / settings changes. Extracted
|
|
164
|
+
// into siteSettingsCacheS3Resources() so backend.test.ts can guard
|
|
165
|
+
// the exact ARN against this regression.
|
|
166
|
+
resources: siteSettingsCacheS3Resources(backend.storage.resources.bucket.bucketArn)
|
|
166
167
|
})
|
|
167
168
|
);
|
|
168
169
|
const pluginSecretTable = backend.data.resources.tables["PluginSecret"];
|
|
@@ -303,6 +304,16 @@ function amplessStorageConfig() {
|
|
|
303
304
|
allow.guest.to(["read"]),
|
|
304
305
|
allow.groups(["ampless-admin", "ampless-editor"]).to(["read", "write", "delete"])
|
|
305
306
|
],
|
|
307
|
+
// Static-bundle posts (`format: 'static'`) upload their files to
|
|
308
|
+
// `public/static/<slug>/...` from the browser admin via Cognito
|
|
309
|
+
// identity-pool credentials. Without this rule the admin group's
|
|
310
|
+
// role is denied `s3:PutObject` and saving the post fails. Mirrors
|
|
311
|
+
// the media grant; the MCP/Lambda upload path is granted separately
|
|
312
|
+
// on the function role in `defineAmplessBackend`.
|
|
313
|
+
"public/static/*": [
|
|
314
|
+
allow.guest.to(["read"]),
|
|
315
|
+
allow.groups(["ampless-admin", "ampless-editor"]).to(["read", "write", "delete"])
|
|
316
|
+
],
|
|
306
317
|
"public/plugins/*": [
|
|
307
318
|
allow.guest.to(["read"]),
|
|
308
319
|
allow.groups(["ampless-admin"]).to(["read", "write", "delete"])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ampless/backend",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.80",
|
|
4
4
|
"description": "Amplify Gen 2 backend factories for ampless: auth, data, storage, event processors, API key renewer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"@smithy/protocol-http": "^5.4.4",
|
|
70
70
|
"@smithy/signature-v4": "^5.4.4",
|
|
71
71
|
"fflate": "^0.8.3",
|
|
72
|
-
"@ampless/mcp-server": "1.0.0-beta.
|
|
73
|
-
"ampless": "1.0.0-beta.
|
|
72
|
+
"@ampless/mcp-server": "1.0.0-beta.59",
|
|
73
|
+
"ampless": "1.0.0-beta.53"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@aws-amplify/backend": "^1.19.0",
|