feat: add s3 attachment (#291)

This commit is contained in:
Dream Hunter
2024-06-01 20:08:42 +08:00
committed by GitHub
parent e91bbe273a
commit 9725407c77
18 changed files with 1584 additions and 42 deletions

View File

@@ -19,6 +19,8 @@
"wrangler": "^3.57.1"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.588.0",
"@aws-sdk/s3-request-presigner": "^3.588.0",
"hono": "^4.3.9",
"mimetext": "^3.0.24",
"postal-mime": "^2.2.5",

1240
worker/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ import { Hono } from 'hono'
import { getDomains, getPasswords, getBooleanValue } from './utils';
import { CONSTANTS } from './constants';
import { HonoCustomType } from './types';
import { isS3Enabled } from './mails_api/s3_attachment';
const api = new Hono<HonoCustomType>
@@ -27,6 +28,7 @@ api.get('/open_api/settings', async (c) => {
"copyright": c.env.COPYRIGHT,
"cfTurnstileSiteKey": c.env.CF_TURNSTILE_SITE_KEY,
"enableWebhook": getBooleanValue(c.env.ENABLE_WEBHOOK),
"isS3Enabled": isS3Enabled(c),
"version": CONSTANTS.VERSION,
});
})

View File

@@ -6,6 +6,7 @@ import { newAddress, handleListQuery, deleteAddressWithData } from '../common'
import { CONSTANTS } from '../constants'
import auto_reply from './auto_reply'
import webhook_settings from './webhook_settings';
import s3_attachment from './s3_attachment';
export const api = new Hono<HonoCustomType>()
@@ -14,6 +15,9 @@ api.post('/api/auto_reply', auto_reply.saveAutoReply)
api.get('/api/webhook/settings', webhook_settings.getWebhookSettings)
api.post('/api/webhook/settings', webhook_settings.saveWebhookSettings)
api.post('/api/webhook/test', webhook_settings.testWebhookSettings)
api.get('/api/attachment/list', s3_attachment.list)
api.post('/api/attachment/put_url', s3_attachment.getSignedPutUrl)
api.post('/api/attachment/get_url', s3_attachment.getSignedGetUrl)
api.get('/api/mails', async (c) => {
const { address } = c.get("jwtPayload")

View File

@@ -0,0 +1,84 @@
import { HonoCustomType } from "../types";
import { Context } from "hono";
import {
S3Client,
ListObjectsV2Command,
GetObjectCommand,
PutObjectCommand
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
export const isS3Enabled = (c: Context<HonoCustomType>) => {
return !(!c.env.S3_ENDPOINT ||
!c.env.S3_ACCESS_KEY_ID ||
!c.env.S3_SECRET_ACCESS_KEY ||
!c.env.S3_BUCKET);
}
const getS3Client = (c: Context<HonoCustomType>) => {
if (
!c.env.S3_ENDPOINT ||
!c.env.S3_ACCESS_KEY_ID ||
!c.env.S3_SECRET_ACCESS_KEY ||
!c.env.S3_BUCKET
) {
throw new Error("S3 config is not set");
}
return new S3Client({
region: "auto",
endpoint: c.env.S3_ENDPOINT,
credentials: {
accessKeyId: c.env.S3_ACCESS_KEY_ID,
secretAccessKey: c.env.S3_SECRET_ACCESS_KEY,
},
});
}
export default {
getSignedGetUrl: async (c: Context<HonoCustomType>) => {
const { address } = c.get("jwtPayload")
const { key } = await c.req.json()
const client = getS3Client(c);
const url = await getSignedUrl(
client,
new GetObjectCommand({
Bucket: c.env.S3_BUCKET,
Key: `${address}/${key}`
}),
{ expiresIn: c.env.S3_URL_EXPIRES || 360 }
);
return c.json({ url });
},
getSignedPutUrl: async (c: Context<HonoCustomType>) => {
const { address } = c.get("jwtPayload")
const { key } = await c.req.json()
const client = getS3Client(c);
const url = await getSignedUrl(
client,
new PutObjectCommand({
Bucket: c.env.S3_BUCKET,
Key: `${address}/${key}`
}),
{ expiresIn: c.env.S3_URL_EXPIRES || 360 }
);
return c.json({ url });
},
list: async (c: Context<HonoCustomType>) => {
const { address } = c.get("jwtPayload")
const client = getS3Client(c);
const data = await client.send(
new ListObjectsV2Command({
Bucket: c.env.S3_BUCKET,
Prefix: `${address}/`
})
);
return c.json(
{
results: data?.Contents
?.map((v) => v.Key?.replace(`${address}/`, ""))
?.filter(k => k)
?.map((k) => ({ key: k }))
}
);
},
}

View File

@@ -23,6 +23,13 @@ export type Bindings = {
COPYRIGHT: string | undefined
FORWARD_ADDRESS_LIST: string | string[] | undefined
// s3 config
S3_ENDPOINT: string | undefined
S3_ACCESS_KEY_ID: string | undefined
S3_SECRET_ACCESS_KEY: string | undefined
S3_BUCKET: string | undefined
S3_URL_EXPIRES: number | undefined
// dkim
DKIM_SELECTOR: string | undefined
DKIM_PRIVATE_KEY: string | undefined