Make admin quotas editable and simplify uploader storage

This commit is contained in:
2026-10-15 12:51:42 +09:00
parent 4d527f74e6
commit 328fad2e36
26 changed files with 1101 additions and 205 deletions

View File

@@ -485,3 +485,83 @@ test(
}
},
);
test('IPv4 trailing wildcards normalize to CIDR for both lists, preserve range boundaries and reject invalid patterns or operator lockout', async () => {
const f = await fixture();
try {
const admin = await login(f),
guest = await f.create();
f.cfg.clientIpSource = 'cloudflare';
for (const [value, expected] of [
['203.0.113.*', '203.0.113.0/24'],
['203.0.*.*', '203.0.0.0/16'],
['203.*.*.*', '203.0.0.0/8'],
['*.*.*.*', '0.0.0.0/0'],
]) {
const response = await f.call(
admin,
'/admin/network-rules/validate',
'POST',
{ kind: 'ip', value },
undefined,
actorHeaders,
);
assert.equal(response.statusCode, 200, response.body);
assert.equal(response.json().value, expected);
}
for (const value of [
'203.*.113.*',
'203.0.113.1*',
'203.0.113.* /24',
'256.0.113.*',
'203.0.*',
'203.00.113.*',
'2001:db8::*',
])
assert.equal(
(
await f.call(
admin,
'/admin/network-rules/validate',
'POST',
{ kind: 'ip', value },
undefined,
actorHeaders,
)
).statusCode,
400,
value,
);
await patch(f, admin, {
blockedIps: ['1.1.1.*', '1.1.1.0/24'],
allowedIps: ['8.8.4.*', '1.1.*.*'],
});
assert.deepEqual(f.service.admin.state.blockedIps, ['1.1.1.0/24']);
assert.deepEqual(new Administration(f.service).state.allowedIps, ['1.1.0.0/16', '8.8.4.0/24']);
for (const [ip, status] of [
['1.1.1.0', 403],
['1.1.1.255', 403],
['1.1.2.0', 200],
['1.2.0.0', 403],
['8.8.4.255', 200],
['8.8.5.0', 403],
])
assert.equal(
(await f.call(guest, '/device/me', 'GET', undefined, undefined, headers(ip))).statusCode,
status,
ip,
);
const lockout = await f.call(
admin,
'/admin/settings',
'PATCH',
{ revision: f.service.admin.state.revision, blockedIps: ['8.8.4.*'] },
undefined,
actorHeaders,
);
assert.equal(lockout.json().code, 'ADMIN_SELF_BLOCK');
assert.deepEqual(f.service.admin.state.blockedIps, ['1.1.1.0/24']);
} finally {
await f.close();
}
});