Skip to content

Commit 7e19abf

Browse files
committed
Merge branch 'main' into postdeploy
2 parents ceeb6a5 + 3e01199 commit 7e19abf

File tree

9 files changed

+503
-74
lines changed

9 files changed

+503
-74
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## [1.0.2](https://github.com/adobe/da-admin/compare/v1.0.1...v1.0.2) (2025-12-15)
2+
3+
4+
### Bug Fixes
5+
6+
* exception when no path ([#223](https://github.com/adobe/da-admin/issues/223)) ([cb97c95](https://github.com/adobe/da-admin/commit/cb97c95c87ef019448b18c56b358aa27e0d31f73))
7+
8+
## [1.0.1](https://github.com/adobe/da-admin/compare/v1.0.0...v1.0.1) (2025-12-10)
9+
10+
11+
### Bug Fixes
12+
13+
* capture failing version requests ([#220](https://github.com/adobe/da-admin/issues/220)) ([729c8f5](https://github.com/adobe/da-admin/commit/729c8f5cc85573cd0dd2f761eb6ab8d471a820cb))
14+
115
# 1.0.0 (2025-12-04)
216

317

package-lock.json

Lines changed: 24 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "da-admin",
3-
"version": "1.0.0",
3+
"version": "1.0.2",
44
"description": "",
55
"main": "index.js",
66
"type": "module",
@@ -51,6 +51,7 @@
5151
"*.cjs": "eslint"
5252
},
5353
"dependencies": {
54+
"@adobe/helix-shared-process-queue": "3.1.3",
5455
"@aws-sdk/client-s3": "3.726.1",
5556
"@aws-sdk/s3-request-presigner": "^3.468.0",
5657
"@cloudflare/workers-types": "4.20251205.0",

src/storage/version/list.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,36 @@
99
* OF ANY KIND, either express or implied. See the License for the specific language
1010
* governing permissions and limitations under the License.
1111
*/
12+
import processQueue from '@adobe/helix-shared-process-queue';
1213
import getObject from '../object/get.js';
1314
import listObjects from '../object/list.js';
1415

16+
const MAX_VERSIONS = 500;
17+
const CONCURRENCY = 50;
18+
1519
export async function listObjectVersions(env, { bucket, org, key }) {
1620
const current = await getObject(env, { bucket, org, key }, true);
1721
if (current.status === 404 || !current.metadata.id) {
1822
return 404;
1923
}
20-
const resp = await listObjects(env, { bucket, org, key: `.da-versions/${current.metadata.id}` }, 500);
21-
const promises = await Promise.all(JSON.parse(resp.body).map(async (entry) => {
24+
const resp = await listObjects(env, { bucket, org, key: `.da-versions/${current.metadata.id}` }, MAX_VERSIONS);
25+
if (resp.status !== 200) {
26+
return resp;
27+
}
28+
const list = JSON.parse(resp.body);
29+
30+
const versions = await processQueue(list, async (entry) => {
2231
const entryResp = await getObject(env, {
2332
bucket,
2433
org,
2534
key: `.da-versions/${current.metadata.id}/${entry.name}.${entry.ext}`,
2635
}, true);
36+
37+
if (entryResp.status !== 200 || !entryResp.metadata) {
38+
// Some requests might fail for unknown reasons (system busy, etc.)
39+
return undefined;
40+
}
41+
2742
const timestamp = parseInt(entryResp.metadata.timestamp || '0', 10);
2843
const users = JSON.parse(entryResp.metadata.users || '[{"email":"anonymous"}]');
2944
const { label, path } = entryResp.metadata;
@@ -38,11 +53,14 @@ export async function listObjectVersions(env, { bucket, org, key }) {
3853
};
3954
}
4055
return { users, timestamp, path };
41-
}));
56+
}, CONCURRENCY);
57+
58+
// Filter out undefined entries (failed requests)
59+
const filteredVersions = versions.filter((version) => version !== undefined);
4260

4361
return {
4462
status: resp.status,
4563
contentType: resp.contentType,
46-
body: JSON.stringify(promises),
64+
body: JSON.stringify(filteredVersions),
4765
};
4866
}

src/utils/auth.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ export function getChildRules(daCtx) {
372372
}
373373

374374
export function hasPermission(daCtx, path, action, keywordPath = false) {
375+
if (path === null || path === undefined) return false;
375376
if (daCtx.aclCtx.pathLookup.size === 0) {
376377
return true;
377378
}

test/integration/conditional-e2e.test.js

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -155,59 +155,4 @@ describe('Conditional Headers End-to-End', () => {
155155
// Should have CORS headers even for error responses
156156
assert.strictEqual(resp.headers.get('Access-Control-Allow-Origin'), '*');
157157
});
158-
159-
it('versionsource GET with conditionals works correctly', async () => {
160-
const etag = '"version-etag"';
161-
s3Mock
162-
.on(GetObjectCommand)
163-
.rejects({ $metadata: { httpStatusCode: 304 }, ETag: etag });
164-
165-
const versionHandler = await esmock(
166-
'../../src/index.js',
167-
{
168-
'../../src/utils/daCtx.js': {
169-
default: async (req) => ({
170-
path: '/versionsource/org/doc-id/version-id.html',
171-
api: 'versionsource',
172-
bucket: 'test-bucket',
173-
org: 'org',
174-
key: 'doc-id/version-id.html',
175-
ext: 'html',
176-
users: [{ email: '[email protected]' }],
177-
authorized: true,
178-
conditionalHeaders: {
179-
ifMatch: req.headers?.get('if-match') || null,
180-
ifNoneMatch: req.headers?.get('if-none-match') || null,
181-
},
182-
aclCtx: {
183-
actionSet: new Set(['read']),
184-
pathLookup: new Map(),
185-
},
186-
method: req.method,
187-
}),
188-
},
189-
'../../src/storage/utils/object.js': {
190-
invalidateCollab: async () => {},
191-
},
192-
},
193-
);
194-
195-
const req = {
196-
method: 'GET',
197-
url: 'http://localhost:8787/versionsource/org/doc-id/version-id.html',
198-
headers: {
199-
get: (name) => {
200-
if (name === 'if-none-match') return etag;
201-
return null;
202-
},
203-
},
204-
};
205-
206-
const env = { AEM_BUCKET_NAME: 'test-bucket' };
207-
const resp = await versionHandler.default.fetch(req, env);
208-
209-
// Versionsource should support conditionals
210-
assert.strictEqual(resp.status, 304);
211-
assert.strictEqual(resp.headers.get('ETag'), etag);
212-
});
213158
});

test/routes/source.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('Source Route', () => {
2626
DA_COLLAB: 'http://localhost:4444',
2727
};
2828

29-
const daCtx = { aclCtx: { pathLookup: new Map() } };
29+
const daCtx = { key: '/somedoc.html', aclCtx: { pathLookup: new Map() } };
3030
const putResp = async (e, c) => {
3131
if (e === env && c === daCtx) {
3232
return { status: 200 };
@@ -76,7 +76,7 @@ describe('Source Route', () => {
7676
};
7777

7878
const env = { DA_COLLAB: 'http://localhost:1234' };
79-
const daCtx = { aclCtx: { pathLookup: new Map() } };
79+
const daCtx = { key: '/a/b/mydoc.html', aclCtx: { pathLookup: new Map() } };
8080

8181
const resp = await postSource({ req, env, daCtx });
8282
assert.equal(201, resp.status);
@@ -109,7 +109,7 @@ describe('Source Route', () => {
109109
};
110110

111111
const env = { DA_COLLAB: 'http://localhost:1234' };
112-
const daCtx = { aclCtx: { pathLookup: new Map() } };
112+
const daCtx = { key: '/a/b/mydoc.html', aclCtx: { pathLookup: new Map() } };
113113

114114
const resp = await postSource({ req, env, daCtx });
115115
assert.equal(500, resp.status);
@@ -121,7 +121,7 @@ describe('Source Route', () => {
121121

122122
it('Test getSource', async () => {
123123
const env = {};
124-
const daCtx = { aclCtx: { pathLookup: new Map() } };
124+
const daCtx = { key: '/test.html', aclCtx: { pathLookup: new Map() } };
125125

126126
const called = [];
127127
const getResp = async (e, c) => {
@@ -143,7 +143,7 @@ describe('Source Route', () => {
143143

144144
it('Test getSource with 204', async () => {
145145
const env = {};
146-
const daCtx = { aclCtx: { pathLookup: new Map() } };
146+
const daCtx = { key: '/test.html', aclCtx: { pathLookup: new Map() } };
147147

148148
const deleteResp = async (e, c) => {
149149
if (e === env && c === daCtx) {

0 commit comments

Comments
 (0)