Migrate storage to DogeCloud and expand admin dashboard

This commit is contained in:
yoyuzh
2026-04-02 12:20:50 +08:00
parent 2424fbd2a7
commit 97edc4cc32
65 changed files with 2842 additions and 380 deletions

View File

@@ -3,12 +3,15 @@ import test from 'node:test';
import {
buildObjectKey,
createAuthorizationHeader,
createDogeCloudApiAuthorization,
createAwsV4Headers,
extractDogeCloudScopeBucketName,
getFrontendSpaAliasContentType,
getFrontendSpaAliasKeys,
getCacheControl,
getContentType,
normalizeEndpoint,
requestDogeCloudTemporaryS3Session,
} from './oss-deploy-lib.mjs';
test('normalizeEndpoint strips scheme and trailing slashes', () => {
@@ -43,16 +46,98 @@ test('frontend spa aliases are uploaded as html entry points', () => {
assert.equal(getFrontendSpaAliasContentType(), 'text/html; charset=utf-8');
});
test('createAuthorizationHeader is stable for a known request', () => {
const header = createAuthorizationHeader({
test('createAwsV4Headers signs uploads with S3-compatible SigV4 headers', () => {
const headers = createAwsV4Headers({
method: 'PUT',
endpoint: 'https://cos.ap-chengdu.myqcloud.com',
bucket: 'demo-bucket',
objectKey: 'assets/index.js',
contentType: 'text/javascript; charset=utf-8',
date: 'Tue, 17 Mar 2026 12:00:00 GMT',
amzDate: '20260317T120000Z',
accessKeyId: 'test-id',
accessKeySecret: 'test-secret',
secretAccessKey: 'test-secret',
region: 'automatic',
});
assert.equal(header, 'OSS test-id:JgyH7mTiSILGGWsnXJwg4KIBRO4=');
assert.equal(headers['x-amz-content-sha256'], 'UNSIGNED-PAYLOAD');
assert.equal(headers['x-amz-date'], '20260317T120000Z');
assert.ok(headers.Authorization.startsWith('AWS4-HMAC-SHA256 Credential=test-id/20260317/automatic/s3/aws4_request'));
});
test('extractDogeCloudScopeBucketName keeps only the logical bucket name', () => {
assert.equal(extractDogeCloudScopeBucketName('yoyuzh-files:users/*'), 'yoyuzh-files');
assert.equal(extractDogeCloudScopeBucketName('yoyuzh-front'), 'yoyuzh-front');
});
test('createDogeCloudApiAuthorization signs body with HMAC-SHA1 hex', () => {
const authorization = createDogeCloudApiAuthorization({
apiPath: '/auth/tmp_token.json',
body: '{"channel":"OSS_FULL","ttl":1800,"scopes":["yoyuzh-files"]}',
accessKey: 'doge-ak',
secretKey: 'doge-sk',
});
assert.equal(
authorization,
'TOKEN doge-ak:2cf0cf7cf6ddaf673cfe47e55646779d44470929'
);
});
test('requestDogeCloudTemporaryS3Session requests temp credentials and returns matching bucket', async () => {
const requests = [];
const session = await requestDogeCloudTemporaryS3Session({
apiBaseUrl: 'https://api.dogecloud.com',
accessKey: 'doge-ak',
secretKey: 'doge-sk',
scope: 'yoyuzh-front:assets/*',
ttlSeconds: 1200,
fetchImpl: async (url, options) => {
requests.push({url, options});
return {
ok: true,
status: 200,
async json() {
return {
code: 200,
msg: 'OK',
data: {
Credentials: {
accessKeyId: 'tmp-ak',
secretAccessKey: 'tmp-sk',
sessionToken: 'tmp-token',
},
ExpiredAt: 1777777777,
Buckets: [
{
name: 'yoyuzh-files',
s3Bucket: 's-cd-14873-yoyuzh-files-1258813047',
s3Endpoint: 'https://cos.ap-chengdu.myqcloud.com',
},
{
name: 'yoyuzh-front',
s3Bucket: 's-cd-14873-yoyuzh-front-1258813047',
s3Endpoint: 'https://cos.ap-chengdu.myqcloud.com',
},
],
},
};
},
};
},
});
assert.equal(requests[0].url, 'https://api.dogecloud.com/auth/tmp_token.json');
assert.equal(requests[0].options.method, 'POST');
assert.equal(requests[0].options.headers['Content-Type'], 'application/json');
assert.ok(requests[0].options.headers.Authorization.startsWith('TOKEN doge-ak:'));
assert.equal(requests[0].options.body, '{"channel":"OSS_FULL","ttl":1200,"scopes":["yoyuzh-front:assets/*"]}');
assert.deepEqual(session, {
accessKeyId: 'tmp-ak',
secretAccessKey: 'tmp-sk',
sessionToken: 'tmp-token',
bucket: 's-cd-14873-yoyuzh-front-1258813047',
endpoint: 'https://cos.ap-chengdu.myqcloud.com',
bucketName: 'yoyuzh-front',
expiresAt: 1777777777,
});
});