Add resumable uploads, proxy discovery, PWA install and 2 GiB personal vaults

This commit is contained in:
2026-10-12 15:54:26 +09:00
parent 439c2ae61b
commit 464715aa69
43 changed files with 1647 additions and 137 deletions

View File

@@ -45,6 +45,96 @@ function limits(f) {
f.cfg.ipRate = 60;
}
test('개인 보관함은 임시 저장·받은 파일을 합산하고 초과 수신은 다운로드만 유지한다', async () => {
const f = await fixture();
try {
limits(f);
f.cfg.userQuota = 7;
const sender = await f.create(),
receiver = await f.create(),
outsider = await f.create();
await f.space(sender, receiver);
await signed(f, receiver, 'quota@hop.test');
await signed(f, outsider, 'other-quota@hop.test');
const saved = (
await f.call(
receiver,
'/vault',
'POST',
{
kind: 'file',
files: [{ name: 'saved.txt', size: 4, type: 'text/plain' }],
},
randomUUID(),
)
).json();
assert.equal((await upload(f, receiver, saved.requestId, Buffer.from('save'))).statusCode, 200);
async function received(bytes) {
const r = await f.call(
sender,
'/transfer-requests',
'POST',
{
targetDeviceId: receiver.deviceId,
kind: 'file',
byteSize: bytes.length,
count: 1,
files: [{ name: 'saved.txt', size: bytes.length, type: 'text/plain' }],
},
randomUUID(),
);
const id = r.json().requestId;
assert.equal(
(await f.call(receiver, `/transfer-requests/${id}/accept`, 'POST', {}, randomUUID()))
.statusCode,
200,
);
assert.equal((await upload(f, sender, id, bytes)).statusCode, 200);
return id;
}
const skipped = await received(Buffer.from('full'));
assert.equal((await f.call(receiver, '/inbox')).json().items.length, 0);
const guestItem = (await f.call(receiver, '/device/items'))
.json()
.items.find((item) => item.file?.size === 4 && item.role === 'recipient');
assert.deepEqual(
(await f.call(receiver, `/access/${guestItem.accessId}/download`)).rawPayload,
Buffer.from('full'),
);
await received(Buffer.from('fit'));
assert.equal((await f.call(receiver, '/account/storage')).json().usedBytes, 7);
assert.equal((await f.call(outsider, '/account/storage')).json().usedBytes, 0);
const own = (await f.call(receiver, '/vault')).json().items[0];
const deleted = (
await f.call(receiver, '/access/delete-batch', 'POST', { ids: [own.accessId] })
).json();
assert.equal((await f.call(receiver, '/account/storage')).json().usedBytes, 3);
const replacement = (
await f.call(
receiver,
'/vault',
'POST',
{
kind: 'file',
files: [{ name: 'saved.txt', size: 4, type: 'text/plain' }],
},
randomUUID(),
)
).json();
assert.equal(
(await upload(f, receiver, replacement.requestId, Buffer.from('more'))).statusCode,
200,
);
assert.equal(
(await f.call(receiver, `/deletion-operations/${deleted.operationId}/undo`, 'POST', {}))
.statusCode,
413,
);
} finally {
await f.close();
}
});
test('기기 수신은 로그인 계정의 날짜 기록에만 자동 저장, 익명 과거 자료와 로그아웃 후 도착은 가져오지 않음', async () => {
const f = await fixture();
try {