mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-10 18:07:00 +08:00
Compare commits
2
Commits
v1.0.5
..
8e5293f010
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e5293f010 | ||
|
|
711378cb11 |
@@ -6,7 +6,6 @@
|
|||||||
- feat: 新增 `DISABLE_CUSTOM_ADDRESS_NAME` 配置: 禁用自定义邮箱地址名称功能
|
- feat: 新增 `DISABLE_CUSTOM_ADDRESS_NAME` 配置: 禁用自定义邮箱地址名称功能
|
||||||
- feat: 新增 `CREATE_ADDRESS_DEFAULT_DOMAIN_FIRST` 配置: 创建地址时优先使用第一个域名
|
- feat: 新增 `CREATE_ADDRESS_DEFAULT_DOMAIN_FIRST` 配置: 创建地址时优先使用第一个域名
|
||||||
- feat: |UI| 主页增加进入极简模式按钮
|
- feat: |UI| 主页增加进入极简模式按钮
|
||||||
- feat: |Webhook| 增加白名单开关功能,支持灵活控制访问权限
|
|
||||||
|
|
||||||
## v1.0.4
|
## v1.0.4
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
"naive-ui": "^2.42.0",
|
"naive-ui": "^2.42.0",
|
||||||
"postal-mime": "^2.4.4",
|
"postal-mime": "^2.4.4",
|
||||||
"vooks": "^0.2.12",
|
"vooks": "^0.2.12",
|
||||||
"vue": "^3.5.21",
|
"vue": "^3.5.20",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-i18n": "^11.1.11",
|
"vue-i18n": "^11.1.11",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1"
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"vite-plugin-wasm": "^3.5.0",
|
"vite-plugin-wasm": "^3.5.0",
|
||||||
"workbox-build": "^7.3.0",
|
"workbox-build": "^7.3.0",
|
||||||
"workbox-window": "^7.3.0",
|
"workbox-window": "^7.3.0",
|
||||||
"wrangler": "^4.34.0"
|
"wrangler": "^4.33.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+273
-282
File diff suppressed because it is too large
Load Diff
@@ -33,12 +33,7 @@ const { t } = useI18n({
|
|||||||
itemCount: 'itemCount',
|
itemCount: 'itemCount',
|
||||||
query: 'Query',
|
query: 'Query',
|
||||||
addressQueryTip: 'Leave blank to query all addresses',
|
addressQueryTip: 'Leave blank to query all addresses',
|
||||||
clearInbox: 'Clear Inbox',
|
actions: 'Actions'
|
||||||
clearSentItems: 'Clear Sent Items',
|
|
||||||
clearInboxTip: 'Are you sure to clear inbox for this email?',
|
|
||||||
clearSentItemsTip: 'Are you sure to clear sent items for this email?',
|
|
||||||
actions: 'Actions',
|
|
||||||
success: 'Success',
|
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
name: '名称',
|
name: '名称',
|
||||||
@@ -57,12 +52,7 @@ const { t } = useI18n({
|
|||||||
itemCount: '总数',
|
itemCount: '总数',
|
||||||
query: '查询',
|
query: '查询',
|
||||||
addressQueryTip: '留空查询所有地址',
|
addressQueryTip: '留空查询所有地址',
|
||||||
clearInbox: '清空收件箱',
|
|
||||||
clearSentItems: '清空发件箱',
|
|
||||||
clearInboxTip: '确定要清空这个邮箱的收件箱吗?',
|
|
||||||
clearSentItemsTip: '确定要清空这个邮箱的发件箱吗?',
|
|
||||||
actions: '操作',
|
actions: '操作',
|
||||||
success: '成功',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -70,8 +60,6 @@ const { t } = useI18n({
|
|||||||
const showEmailCredential = ref(false)
|
const showEmailCredential = ref(false)
|
||||||
const curEmailCredential = ref("")
|
const curEmailCredential = ref("")
|
||||||
const curDeleteAddressId = ref(0);
|
const curDeleteAddressId = ref(0);
|
||||||
const curClearInboxAddressId = ref(0);
|
|
||||||
const curClearSentItemsAddressId = ref(0);
|
|
||||||
|
|
||||||
const addressQuery = ref("")
|
const addressQuery = ref("")
|
||||||
|
|
||||||
@@ -80,8 +68,6 @@ const count = ref(0)
|
|||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const showDeleteAccount = ref(false)
|
const showDeleteAccount = ref(false)
|
||||||
const showClearInbox = ref(false)
|
|
||||||
const showClearSentItems = ref(false)
|
|
||||||
|
|
||||||
const showCredential = async (id) => {
|
const showCredential = async (id) => {
|
||||||
try {
|
try {
|
||||||
@@ -97,7 +83,7 @@ const showCredential = async (id) => {
|
|||||||
const deleteEmail = async () => {
|
const deleteEmail = async () => {
|
||||||
try {
|
try {
|
||||||
await api.adminDeleteAddress(curDeleteAddressId.value)
|
await api.adminDeleteAddress(curDeleteAddressId.value)
|
||||||
message.success(t("success"));
|
message.success("success");
|
||||||
await fetchData()
|
await fetchData()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error(error.message || "error");
|
message.error(error.message || "error");
|
||||||
@@ -106,34 +92,6 @@ const deleteEmail = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearInbox = async () => {
|
|
||||||
try {
|
|
||||||
await api.fetch(`/admin/clear_inbox/${curClearInboxAddressId.value}`, {
|
|
||||||
method: 'DELETE'
|
|
||||||
});
|
|
||||||
message.success(t("success"));
|
|
||||||
await fetchData()
|
|
||||||
} catch (error) {
|
|
||||||
message.error(error.message || "error");
|
|
||||||
} finally {
|
|
||||||
showClearInbox.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearSentItems = async () => {
|
|
||||||
try {
|
|
||||||
await api.fetch(`/admin/clear_sent_items/${curClearSentItemsAddressId.value}`, {
|
|
||||||
method: 'DELETE'
|
|
||||||
});
|
|
||||||
message.success(t("success"));
|
|
||||||
await fetchData()
|
|
||||||
} catch (error) {
|
|
||||||
message.error(error.message || "error");
|
|
||||||
} finally {
|
|
||||||
showClearSentItems.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
addressQuery.value = addressQuery.value.trim()
|
addressQuery.value = addressQuery.value.trim()
|
||||||
@@ -270,32 +228,6 @@ const columns = [
|
|||||||
),
|
),
|
||||||
show: row.send_count > 0
|
show: row.send_count > 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: () => h(NButton,
|
|
||||||
{
|
|
||||||
text: true,
|
|
||||||
onClick: () => {
|
|
||||||
curClearInboxAddressId.value = row.id;
|
|
||||||
showClearInbox.value = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ default: () => t('clearInbox') }
|
|
||||||
),
|
|
||||||
show: row.mail_count > 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: () => h(NButton,
|
|
||||||
{
|
|
||||||
text: true,
|
|
||||||
onClick: () => {
|
|
||||||
curClearSentItemsAddressId.value = row.id;
|
|
||||||
showClearSentItems.value = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ default: () => t('clearSentItems') }
|
|
||||||
),
|
|
||||||
show: row.send_count > 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: () => h(NButton,
|
label: () => h(NButton,
|
||||||
{
|
{
|
||||||
@@ -349,22 +281,6 @@ onMounted(async () => {
|
|||||||
</n-button>
|
</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-modal v-model:show="showClearInbox" preset="dialog" :title="t('clearInbox')">
|
|
||||||
<p>{{ t('clearInboxTip') }}</p>
|
|
||||||
<template #action>
|
|
||||||
<n-button :loading="loading" @click="clearInbox" size="small" tertiary type="error">
|
|
||||||
{{ t('clearInbox') }}
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
</n-modal>
|
|
||||||
<n-modal v-model:show="showClearSentItems" preset="dialog" :title="t('clearSentItems')">
|
|
||||||
<p>{{ t('clearSentItemsTip') }}</p>
|
|
||||||
<template #action>
|
|
||||||
<n-button :loading="loading" @click="clearSentItems" size="small" tertiary type="error">
|
|
||||||
{{ t('clearSentItems') }}
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
</n-modal>
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input v-model:value="addressQuery" clearable :placeholder="t('addressQueryTip')"
|
<n-input v-model:value="addressQuery" clearable :placeholder="t('addressQueryTip')"
|
||||||
@keydown.enter="fetchData" />
|
@keydown.enter="fetchData" />
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const { t } = useI18n({
|
|||||||
messages: {
|
messages: {
|
||||||
en: {
|
en: {
|
||||||
tip: 'You can manually input the following multiple select input and enter',
|
tip: 'You can manually input the following multiple select input and enter',
|
||||||
manualInputPrompt: 'Type and press Enter to add',
|
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
successTip: 'Save Success',
|
successTip: 'Save Success',
|
||||||
address_block_list: 'Address Block Keywords for Users(Admin can skip)',
|
address_block_list: 'Address Block Keywords for Users(Admin can skip)',
|
||||||
@@ -39,7 +38,6 @@ const { t } = useI18n({
|
|||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
tip: '您可以手动输入以下多选输入框, 回车增加',
|
tip: '您可以手动输入以下多选输入框, 回车增加',
|
||||||
manualInputPrompt: '输入后按回车键添加',
|
|
||||||
save: '保存',
|
save: '保存',
|
||||||
successTip: '保存成功',
|
successTip: '保存成功',
|
||||||
address_block_list: '邮件地址屏蔽关键词(管理员可跳过检查)',
|
address_block_list: '邮件地址屏蔽关键词(管理员可跳过检查)',
|
||||||
@@ -211,55 +209,25 @@ onMounted(async () => {
|
|||||||
</n-flex>
|
</n-flex>
|
||||||
<n-form-item-row :label="t('address_block_list')">
|
<n-form-item-row :label="t('address_block_list')">
|
||||||
<n-select v-model:value="addressBlockList" filterable multiple tag
|
<n-select v-model:value="addressBlockList" filterable multiple tag
|
||||||
:placeholder="t('address_block_list_placeholder')">
|
:placeholder="t('address_block_list_placeholder')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('send_address_block_list')">
|
<n-form-item-row :label="t('send_address_block_list')">
|
||||||
<n-select v-model:value="sendAddressBlockList" filterable multiple tag
|
<n-select v-model:value="sendAddressBlockList" filterable multiple tag
|
||||||
:placeholder="t('address_block_list_placeholder')">
|
:placeholder="t('address_block_list_placeholder')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('noLimitSendAddressList')">
|
<n-form-item-row :label="t('noLimitSendAddressList')">
|
||||||
<n-select v-model:value="noLimitSendAddressList" filterable multiple tag
|
<n-select v-model:value="noLimitSendAddressList" filterable multiple tag
|
||||||
:placeholder="t('noLimitSendAddressList')">
|
:placeholder="t('noLimitSendAddressList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('verified_address_list')">
|
<n-form-item-row :label="t('verified_address_list')">
|
||||||
<n-select v-model:value="verifiedAddressList" filterable multiple tag
|
<n-select v-model:value="verifiedAddressList" filterable multiple tag
|
||||||
:placeholder="t('verified_address_list')">
|
:placeholder="t('verified_address_list')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('fromBlockList')">
|
<n-form-item-row :label="t('fromBlockList')">
|
||||||
<n-select v-model:value="fromBlockList" filterable multiple tag :placeholder="t('fromBlockList')">
|
<n-select v-model:value="fromBlockList" filterable multiple tag :placeholder="t('fromBlockList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('block_receive_unknow_address_email')">
|
<n-form-item-row :label="t('block_receive_unknow_address_email')">
|
||||||
<n-switch v-model:value="emailRuleSettings.blockReceiveUnknowAddressEmail" :round="false" />
|
<n-checkbox v-model:checked="emailRuleSettings.blockReceiveUnknowAddressEmail" />
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('email_forwarding_config')">
|
<n-form-item-row :label="t('email_forwarding_config')">
|
||||||
<n-button @click="openEmailForwardingModal">{{ t('config') }}</n-button>
|
<n-button @click="openEmailForwardingModal">{{ t('config') }}</n-button>
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ onMounted(async () => {
|
|||||||
</n-modal>
|
</n-modal>
|
||||||
<n-card :bordered="false" embedded style="max-width: 600px;">
|
<n-card :bordered="false" embedded style="max-width: 600px;">
|
||||||
<n-form-item-row v-if="openSettings.prefix" :label="t('enablePrefix')">
|
<n-form-item-row v-if="openSettings.prefix" :label="t('enablePrefix')">
|
||||||
<n-switch v-model:value="enablePrefix" :round="false" />
|
<n-checkbox v-model:checked="enablePrefix" />
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('address')">
|
<n-form-item-row :label="t('address')">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
|
|||||||
@@ -15,29 +15,25 @@ const { t } = useI18n({
|
|||||||
init: 'Init',
|
init: 'Init',
|
||||||
successTip: 'Success',
|
successTip: 'Success',
|
||||||
status: 'Check Status',
|
status: 'Check Status',
|
||||||
enableTelegramAllowList: 'Enable Telegram Allow List(Manually input Chat ID)',
|
enableTelegramAllowList: 'Enable Telegram Allow List(Manually input user ID)',
|
||||||
enable: 'Enable',
|
enable: 'Enable',
|
||||||
telegramAllowList: 'Telegram Allow List(Manually input telegram Chat ID)',
|
telegramAllowList: 'Telegram Allow List(Manually input telegram user ID)',
|
||||||
manualInputPrompt: 'Type and press Enter to add',
|
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
miniAppUrl: 'Telegram Mini App URL',
|
miniAppUrl: 'Telegram Mini App URL',
|
||||||
enableGlobalMailPush: 'Enable Global Mail Push(Manually input telegram Chat ID)',
|
enableGlobalMailPush: 'Enable Global Mail Push(Manually input telegram user ID)',
|
||||||
globalMailPushList: 'Global Mail Push Chat ID List',
|
globalMailPushList: 'Global Mail Push List',
|
||||||
globalMailPushListTip: 'Support chat_id of private chat/group/channel. You can send a message to your bot, then visit this link to see chat_id, https://api.telegram.org/bot<Replace with your BOT TOKEN>/getUpdates',
|
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
init: '初始化',
|
init: '初始化',
|
||||||
successTip: '成功',
|
successTip: '成功',
|
||||||
status: '查看状态',
|
status: '查看状态',
|
||||||
enableTelegramAllowList: '启用 Telegram 白名单(手动输入 Chat ID, 回车增加)',
|
enableTelegramAllowList: '启用 Telegram 白名单(手动输入用户 ID, 回车增加)',
|
||||||
enable: '启用',
|
enable: '启用',
|
||||||
telegramAllowList: 'Telegram 白名单(手动输入 Chat ID, 回车增加)',
|
telegramAllowList: 'Telegram 白名单(手动输入用户 ID, 回车增加)',
|
||||||
manualInputPrompt: '输入后按回车键添加',
|
|
||||||
save: '保存',
|
save: '保存',
|
||||||
miniAppUrl: '电报小程序 URL(请输入你部署的电报小程序网页地址)',
|
miniAppUrl: '电报小程序 URL(请输入你部署的电报小程序网页地址)',
|
||||||
enableGlobalMailPush: '启用全局邮件推送(手动输入邮箱管理员的 telegram Chat ID, 回车增加)',
|
enableGlobalMailPush: '启用全局邮件推送(手动输入邮箱管理员的 telegram 用户 ID, 回车增加)',
|
||||||
globalMailPushList: '全局邮件推送 Chat ID 列表',
|
globalMailPushList: '全局邮件推送用户列表',
|
||||||
globalMailPushListTip: '支持对话/群组/频道的 Chat ID, 您可以发送一条消息给您的机器人,然后访问此链接来查看 chat_id, https://api.telegram.org/bot<这里替换成您的 BOT TOKEN>/getUpdates',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -117,17 +113,6 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<n-card :bordered="false" embedded style="max-width: 800px; overflow: auto;">
|
<n-card :bordered="false" embedded style="max-width: 800px; overflow: auto;">
|
||||||
<n-flex justify="end">
|
|
||||||
<n-button @click="fetchStatus" secondary>
|
|
||||||
{{ t('status') }}
|
|
||||||
</n-button>
|
|
||||||
<n-button @click="init" type="primary">
|
|
||||||
{{ t('init') }}
|
|
||||||
</n-button>
|
|
||||||
<n-button @click="saveSettings" type="primary">
|
|
||||||
{{ t('save') }}
|
|
||||||
</n-button>
|
|
||||||
</n-flex>
|
|
||||||
<n-card :bordered="false" embedded>
|
<n-card :bordered="false" embedded>
|
||||||
<n-form-item-row :label="t('enableTelegramAllowList')">
|
<n-form-item-row :label="t('enableTelegramAllowList')">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
@@ -135,41 +120,31 @@ onMounted(async () => {
|
|||||||
{{ t('enable') }}
|
{{ t('enable') }}
|
||||||
</n-checkbox>
|
</n-checkbox>
|
||||||
<n-select v-model:value="settings.allowList" filterable multiple tag style="width: 80%;"
|
<n-select v-model:value="settings.allowList" filterable multiple tag style="width: 80%;"
|
||||||
:placeholder="t('telegramAllowList')">
|
:placeholder="t('telegramAllowList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<br />
|
|
||||||
<n-form-item-row :label="t('enableGlobalMailPush')">
|
<n-form-item-row :label="t('enableGlobalMailPush')">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-checkbox v-model:checked="settings.enableGlobalMailPush" style="width: 20%;">
|
<n-checkbox v-model:checked="settings.enableGlobalMailPush" style="width: 20%;">
|
||||||
{{ t('enable') }}
|
{{ t('enable') }}
|
||||||
</n-checkbox>
|
</n-checkbox>
|
||||||
<n-select v-model:value="settings.globalMailPushList" filterable multiple tag
|
<n-select v-model:value="settings.globalMailPushList" filterable multiple tag
|
||||||
style="width: 80%;" :placeholder="t('globalMailPushList')">
|
style="width: 80%;" :placeholder="t('globalMailPushList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
<template #feedback>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('globalMailPushListTip') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<br />
|
|
||||||
<n-form-item-row :label="t('miniAppUrl')">
|
<n-form-item-row :label="t('miniAppUrl')">
|
||||||
<n-input v-model:value="settings.miniAppUrl"></n-input>
|
<n-input v-model:value="settings.miniAppUrl"></n-input>
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
|
<n-button @click="saveSettings" type="primary" block>
|
||||||
|
{{ t('save') }}
|
||||||
|
</n-button>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
<n-button @click="init" type="primary" block>
|
||||||
|
{{ t('init') }}
|
||||||
|
</n-button>
|
||||||
|
<n-button @click="fetchStatus" secondary block>
|
||||||
|
{{ t('status') }}
|
||||||
|
</n-button>
|
||||||
<pre v-if="status.fetched">{{ JSON.stringify(status, null, 2) }}</pre>
|
<pre v-if="status.fetched">{{ JSON.stringify(status, null, 2) }}</pre>
|
||||||
</n-card>
|
</n-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -182,4 +157,8 @@ onMounted(async () => {
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.n-button {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ const { t } = useI18n({
|
|||||||
successTip: 'Save Success',
|
successTip: 'Save Success',
|
||||||
enable: 'Enable',
|
enable: 'Enable',
|
||||||
enableMailAllowList: 'Enable Mail Address Allow List(Manually enterable)',
|
enableMailAllowList: 'Enable Mail Address Allow List(Manually enterable)',
|
||||||
manualInputPrompt: 'Type and press Enter to add',
|
|
||||||
mailAllowList: 'Mail Address Allow List',
|
mailAllowList: 'Mail Address Allow List',
|
||||||
addOauth2: 'Add Oauth2',
|
addOauth2: 'Add Oauth2',
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
@@ -34,7 +33,6 @@ const { t } = useI18n({
|
|||||||
successTip: '保存成功',
|
successTip: '保存成功',
|
||||||
enable: '启用',
|
enable: '启用',
|
||||||
enableMailAllowList: '启用邮件地址白名单(可手动输入, 回车增加)',
|
enableMailAllowList: '启用邮件地址白名单(可手动输入, 回车增加)',
|
||||||
manualInputPrompt: '输入后按回车键添加',
|
|
||||||
mailAllowList: '邮件地址白名单',
|
mailAllowList: '邮件地址白名单',
|
||||||
addOauth2: '添加 Oauth2',
|
addOauth2: '添加 Oauth2',
|
||||||
name: '名称',
|
name: '名称',
|
||||||
@@ -186,7 +184,7 @@ onMounted(async () => {
|
|||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-card :bordered="false" embedded style="max-width: 600px;">
|
<n-card :bordered="false" embedded style="max-width: 600px;">
|
||||||
<n-alert :show-icon="false" :bordered="false" type="warning" closable style="margin-bottom: 10px;">
|
<n-alert :show-icon="false" type="warning" closable style="margin-bottom: 10px;">
|
||||||
{{ t("tip") }}
|
{{ t("tip") }}
|
||||||
</n-alert>
|
</n-alert>
|
||||||
<n-flex justify="end">
|
<n-flex justify="end">
|
||||||
@@ -248,13 +246,7 @@ onMounted(async () => {
|
|||||||
</n-checkbox>
|
</n-checkbox>
|
||||||
<n-select v-model:value="item.mailAllowList" v-if="item.enableMailAllowList" filterable
|
<n-select v-model:value="item.mailAllowList" v-if="item.enableMailAllowList" filterable
|
||||||
multiple tag style="width: 80%;" :options="mailAllowOptions"
|
multiple tag style="width: 80%;" :options="mailAllowOptions"
|
||||||
:placeholder="t('mailAllowList')">
|
:placeholder="t('mailAllowList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
</n-form>
|
</n-form>
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const { t } = useI18n({
|
|||||||
enableMailVerify: 'Enable Mail Verify (Send address must be an address in the system with a balance and can send mail normally)',
|
enableMailVerify: 'Enable Mail Verify (Send address must be an address in the system with a balance and can send mail normally)',
|
||||||
verifyMailSender: 'Verify Mail Sender',
|
verifyMailSender: 'Verify Mail Sender',
|
||||||
enableMailAllowList: 'Enable Mail Address Allow List(Manually enterable)',
|
enableMailAllowList: 'Enable Mail Address Allow List(Manually enterable)',
|
||||||
manualInputPrompt: 'Type and press Enter to add',
|
|
||||||
mailAllowList: 'Mail Address Allow List',
|
mailAllowList: 'Mail Address Allow List',
|
||||||
maxAddressCount: 'Maximum number of email addresses that can be binded',
|
maxAddressCount: 'Maximum number of email addresses that can be binded',
|
||||||
},
|
},
|
||||||
@@ -30,7 +29,6 @@ const { t } = useI18n({
|
|||||||
enableMailVerify: '启用邮件验证(发送地址必须是系统中能有余额且能正常发送邮件的地址)',
|
enableMailVerify: '启用邮件验证(发送地址必须是系统中能有余额且能正常发送邮件的地址)',
|
||||||
verifyMailSender: '验证邮件发送地址',
|
verifyMailSender: '验证邮件发送地址',
|
||||||
enableMailAllowList: '启用邮件地址白名单(可手动输入, 回车增加)',
|
enableMailAllowList: '启用邮件地址白名单(可手动输入, 回车增加)',
|
||||||
manualInputPrompt: '输入后按回车键添加',
|
|
||||||
mailAllowList: '邮件地址白名单',
|
mailAllowList: '邮件地址白名单',
|
||||||
maxAddressCount: '可绑定最大邮箱地址数量',
|
maxAddressCount: '可绑定最大邮箱地址数量',
|
||||||
}
|
}
|
||||||
@@ -85,14 +83,9 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<n-card :bordered="false" embedded style="max-width: 600px;">
|
<n-card :bordered="false" embedded style="max-width: 600px;">
|
||||||
<n-flex justify="end">
|
|
||||||
<n-button @click="save" type="primary" :loading="loading">
|
|
||||||
{{ t('save') }}
|
|
||||||
</n-button>
|
|
||||||
</n-flex>
|
|
||||||
<n-form :model="userSettings">
|
<n-form :model="userSettings">
|
||||||
<n-form-item-row :label="t('enableUserRegister')">
|
<n-form-item-row :label="t('enableUserRegister')">
|
||||||
<n-switch v-model:value="userSettings.enable" :round="false" />
|
<n-checkbox v-model:checked="userSettings.enable" />
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('enableMailVerify')">
|
<n-form-item-row :label="t('enableMailVerify')">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
@@ -110,13 +103,7 @@ onMounted(async () => {
|
|||||||
</n-checkbox>
|
</n-checkbox>
|
||||||
<n-select v-model:value="userSettings.mailAllowList" v-if="userSettings.enableMailAllowList"
|
<n-select v-model:value="userSettings.mailAllowList" v-if="userSettings.enableMailAllowList"
|
||||||
filterable multiple tag style="width: 80%;" :options="mailAllowOptions"
|
filterable multiple tag style="width: 80%;" :options="mailAllowOptions"
|
||||||
:placeholder="t('mailAllowList')">
|
:placeholder="t('mailAllowList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
<n-form-item-row :label="t('maxAddressCount')">
|
<n-form-item-row :label="t('maxAddressCount')">
|
||||||
@@ -125,6 +112,9 @@ onMounted(async () => {
|
|||||||
:placeholder="t('maxAddressCount')" />
|
:placeholder="t('maxAddressCount')" />
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
|
<n-button @click="save" type="primary" block :loading="loading">
|
||||||
|
{{ t('save') }}
|
||||||
|
</n-button>
|
||||||
</n-form>
|
</n-form>
|
||||||
</n-card>
|
</n-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,17 +13,13 @@ const { t } = useI18n({
|
|||||||
messages: {
|
messages: {
|
||||||
en: {
|
en: {
|
||||||
successTip: 'Success',
|
successTip: 'Success',
|
||||||
enableAllowList: 'Enable Allow List (Restrict webhook access to specific users)',
|
webhookAllowList: 'Webhook Allow List(Enter the address that is allowed to use webhook and enter)',
|
||||||
webhookAllowList: 'Webhook Allow List(Enter the mail address that is allowed to use webhook and enter)',
|
|
||||||
manualInputPrompt: 'Type and press Enter to add',
|
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
notEnabled: 'Webhook is not enabled',
|
notEnabled: 'Webhook is not enabled',
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
successTip: '成功',
|
successTip: '成功',
|
||||||
enableAllowList: '启用白名单 (限制 webhook 访问权限,只有白名单中的用户可以使用)',
|
webhookAllowList: 'Webhook 白名单(请输入允许使用webhook 的地址, 回车增加)',
|
||||||
webhookAllowList: 'Webhook 白名单(请输入允许使用webhook 的邮箱地址, 回车增加)',
|
|
||||||
manualInputPrompt: '输入后按回车键添加',
|
|
||||||
save: '保存',
|
save: '保存',
|
||||||
notEnabled: 'Webhook 未开启',
|
notEnabled: 'Webhook 未开启',
|
||||||
}
|
}
|
||||||
@@ -31,16 +27,14 @@ const { t } = useI18n({
|
|||||||
});
|
});
|
||||||
|
|
||||||
class WebhookSettings {
|
class WebhookSettings {
|
||||||
enableAllowList: boolean;
|
|
||||||
allowList: string[];
|
allowList: string[];
|
||||||
|
|
||||||
constructor(enableAllowList: boolean, allowList: string[]) {
|
constructor(allowList: string[]) {
|
||||||
this.enableAllowList = enableAllowList;
|
|
||||||
this.allowList = allowList;
|
this.allowList = allowList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const webhookSettings = ref(new WebhookSettings(false, []))
|
const webhookSettings = ref(new WebhookSettings([]))
|
||||||
const webhookEnabled = ref(false)
|
const webhookEnabled = ref(false)
|
||||||
const errorInfo = ref('')
|
const errorInfo = ref('')
|
||||||
|
|
||||||
@@ -74,24 +68,13 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<n-card v-if="webhookEnabled" :bordered="false" embedded style="max-width: 800px; overflow: auto;">
|
<n-card v-if="webhookEnabled" :bordered="false" embedded style="max-width: 800px; overflow: auto;">
|
||||||
<n-flex justify="end">
|
|
||||||
<n-button @click="saveSettings" type="primary">
|
|
||||||
{{ t('save') }}
|
|
||||||
</n-button>
|
|
||||||
</n-flex>
|
|
||||||
<n-form-item-row :label="t('enableAllowList')">
|
|
||||||
<n-switch v-model:value="webhookSettings.enableAllowList" :round="false" />
|
|
||||||
</n-form-item-row>
|
|
||||||
<n-form-item-row :label="t('webhookAllowList')">
|
<n-form-item-row :label="t('webhookAllowList')">
|
||||||
<n-select v-model:value="webhookSettings.allowList" filterable multiple tag
|
<n-select v-model:value="webhookSettings.allowList" filterable multiple tag
|
||||||
:placeholder="t('webhookAllowList')">
|
:placeholder="t('webhookAllowList')" />
|
||||||
<template #empty>
|
|
||||||
<n-text depth="3">
|
|
||||||
{{ t('manualInputPrompt') }}
|
|
||||||
</n-text>
|
|
||||||
</template>
|
|
||||||
</n-select>
|
|
||||||
</n-form-item-row>
|
</n-form-item-row>
|
||||||
|
<n-button @click="saveSettings" type="primary" block>
|
||||||
|
{{ t('save') }}
|
||||||
|
</n-button>
|
||||||
</n-card>
|
</n-card>
|
||||||
<n-result v-else status="404" :title="t('notEnabled')" :description="errorInfo" />
|
<n-result v-else status="404" :title="t('notEnabled')" :description="errorInfo" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<n-card :bordered="false" embedded style="max-width: 800px; overflow: auto;">
|
<n-card :bordered="false" embedded style="max-width: 600px; overflow: auto;">
|
||||||
<pre>{{ JSON.stringify(settings, null, 2) }}</pre>
|
<pre>{{ JSON.stringify(settings, null, 2) }}</pre>
|
||||||
</n-card>
|
</n-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ import { api } from '../../api'
|
|||||||
import { getRouterPathWithLang } from '../../utils'
|
import { getRouterPathWithLang } from '../../utils'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
jwt, settings, showAddressCredential, loading, openSettings
|
jwt, settings, showAddressCredential, loading
|
||||||
} = useGlobalState()
|
} = useGlobalState()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
const showLogout = ref(false)
|
const showLogout = ref(false)
|
||||||
const showDeleteAccount = ref(false)
|
const showDeleteAccount = ref(false)
|
||||||
const showClearInbox = ref(false)
|
|
||||||
const showClearSentItems = ref(false)
|
|
||||||
const { locale, t } = useI18n({
|
const { locale, t } = useI18n({
|
||||||
messages: {
|
messages: {
|
||||||
en: {
|
en: {
|
||||||
@@ -26,11 +24,6 @@ const { locale, t } = useI18n({
|
|||||||
logoutConfirm: 'Are you sure to logout?',
|
logoutConfirm: 'Are you sure to logout?',
|
||||||
deleteAccount: "Delete Account",
|
deleteAccount: "Delete Account",
|
||||||
deleteAccountConfirm: "Are you sure to delete your account and all emails for this account?",
|
deleteAccountConfirm: "Are you sure to delete your account and all emails for this account?",
|
||||||
clearInbox: "Clear Inbox",
|
|
||||||
clearSentItems: "Clear Sent Items",
|
|
||||||
clearInboxConfirm: "Are you sure to clear all emails in your inbox?",
|
|
||||||
clearSentItemsConfirm: "Are you sure to clear all emails in your sent items?",
|
|
||||||
success: "Success",
|
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
logout: '退出登录',
|
logout: '退出登录',
|
||||||
@@ -39,11 +32,6 @@ const { locale, t } = useI18n({
|
|||||||
logoutConfirm: '确定要退出登录吗?',
|
logoutConfirm: '确定要退出登录吗?',
|
||||||
deleteAccount: "删除账户",
|
deleteAccount: "删除账户",
|
||||||
deleteAccountConfirm: "确定要删除你的账户和其中的所有邮件吗?",
|
deleteAccountConfirm: "确定要删除你的账户和其中的所有邮件吗?",
|
||||||
clearInbox: "清空收件箱",
|
|
||||||
clearSentItems: "清空发件箱",
|
|
||||||
clearInboxConfirm: "确定要清空你收件箱中的所有邮件吗?",
|
|
||||||
clearSentItemsConfirm: "确定要清空你发件箱中的所有邮件吗?",
|
|
||||||
success: "成功",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -66,32 +54,6 @@ const deleteAccount = async () => {
|
|||||||
message.error(error.message || "error");
|
message.error(error.message || "error");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearInbox = async () => {
|
|
||||||
try {
|
|
||||||
await api.fetch(`/api/clear_inbox`, {
|
|
||||||
method: 'DELETE'
|
|
||||||
});
|
|
||||||
message.success(t("success"));
|
|
||||||
} catch (error) {
|
|
||||||
message.error(error.message || "error");
|
|
||||||
} finally {
|
|
||||||
showClearInbox.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearSentItems = async () => {
|
|
||||||
try {
|
|
||||||
await api.fetch(`/api/clear_sent_items`, {
|
|
||||||
method: 'DELETE'
|
|
||||||
});
|
|
||||||
message.success(t("success"));
|
|
||||||
} catch (error) {
|
|
||||||
message.error(error.message || "error");
|
|
||||||
} finally {
|
|
||||||
showClearSentItems.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -100,19 +62,10 @@ const clearSentItems = async () => {
|
|||||||
<n-button @click="showAddressCredential = true" type="primary" secondary block strong>
|
<n-button @click="showAddressCredential = true" type="primary" secondary block strong>
|
||||||
{{ t('showAddressCredential') }}
|
{{ t('showAddressCredential') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button v-if="openSettings.enableUserDeleteEmail" @click="showClearInbox = true" type="warning" secondary
|
|
||||||
block strong>
|
|
||||||
{{ t('clearInbox') }}
|
|
||||||
</n-button>
|
|
||||||
<n-button v-if="openSettings.enableUserDeleteEmail" @click="showClearSentItems = true" type="warning"
|
|
||||||
secondary block strong>
|
|
||||||
{{ t('clearSentItems') }}
|
|
||||||
</n-button>
|
|
||||||
<n-button @click="showLogout = true" secondary block strong>
|
<n-button @click="showLogout = true" secondary block strong>
|
||||||
{{ t('logout') }}
|
{{ t('logout') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button v-if="openSettings.enableUserDeleteEmail" @click="showDeleteAccount = true" type="error" secondary
|
<n-button @click="showDeleteAccount = true" type="error" secondary block strong>
|
||||||
block strong>
|
|
||||||
{{ t('deleteAccount') }}
|
{{ t('deleteAccount') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-card>
|
</n-card>
|
||||||
@@ -132,22 +85,6 @@ const clearSentItems = async () => {
|
|||||||
</n-button>
|
</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
<n-modal v-model:show="showClearInbox" preset="dialog" :title="t('clearInbox')">
|
|
||||||
<p>{{ t('clearInboxConfirm') }}</p>
|
|
||||||
<template #action>
|
|
||||||
<n-button :loading="loading" @click="clearInbox" size="small" tertiary type="warning">
|
|
||||||
{{ t('clearInbox') }}
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
</n-modal>
|
|
||||||
<n-modal v-model:show="showClearSentItems" preset="dialog" :title="t('clearSentItems')">
|
|
||||||
<p>{{ t('clearSentItemsConfirm') }}</p>
|
|
||||||
<template #action>
|
|
||||||
<n-button :loading="loading" @click="clearSentItems" size="small" tertiary type="warning">
|
|
||||||
{{ t('clearSentItems') }}
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
</n-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"wrangler": "^4.34.0"
|
"wrangler": "^4.33.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.3.1",
|
"@types/node": "^24.3.0",
|
||||||
"vitepress": "^1.6.4",
|
"vitepress": "^1.6.4",
|
||||||
"wrangler": "^4.34.0"
|
"wrangler": "^4.33.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vitepress dev docs",
|
"dev": "vitepress dev docs",
|
||||||
|
|||||||
Generated
+333
-342
File diff suppressed because it is too large
Load Diff
+7
-7
@@ -11,20 +11,20 @@
|
|||||||
"build": "wrangler deploy --dry-run --outdir dist --minify"
|
"build": "wrangler deploy --dry-run --outdir dist --minify"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20250904.0",
|
"@cloudflare/workers-types": "^4.20250826.0",
|
||||||
"@eslint/js": "9.18.0",
|
"@eslint/js": "9.18.0",
|
||||||
"@simplewebauthn/types": "10.0.0",
|
"@simplewebauthn/types": "10.0.0",
|
||||||
"@types/node": "^22.18.1",
|
"@types/node": "^22.18.0",
|
||||||
"eslint": "9.18.0",
|
"eslint": "9.18.0",
|
||||||
"globals": "^15.15.0",
|
"globals": "^15.15.0",
|
||||||
"typescript-eslint": "^8.42.0",
|
"typescript-eslint": "^8.41.0",
|
||||||
"wrangler": "^4.34.0"
|
"wrangler": "^4.33.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.879.0",
|
"@aws-sdk/client-s3": "^3.876.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.879.0",
|
"@aws-sdk/s3-request-presigner": "^3.876.0",
|
||||||
"@simplewebauthn/server": "10.0.1",
|
"@simplewebauthn/server": "10.0.1",
|
||||||
"hono": "^4.9.6",
|
"hono": "^4.9.4",
|
||||||
"jsonpath-plus": "^10.3.0",
|
"jsonpath-plus": "^10.3.0",
|
||||||
"mimetext": "^3.0.27",
|
"mimetext": "^3.0.27",
|
||||||
"postal-mime": "^2.4.4",
|
"postal-mime": "^2.4.4",
|
||||||
|
|||||||
Generated
+697
-691
File diff suppressed because it is too large
Load Diff
@@ -89,34 +89,6 @@ api.delete('/admin/delete_address/:id', async (c) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
api.delete('/admin/clear_inbox/:id', async (c) => {
|
|
||||||
const { id } = c.req.param();
|
|
||||||
const { success: mailSuccess } = await c.env.DB.prepare(
|
|
||||||
`DELETE FROM raw_mails WHERE address IN`
|
|
||||||
+ ` (select name from address where id = ?) `
|
|
||||||
).bind(id).run();
|
|
||||||
if (!mailSuccess) {
|
|
||||||
return c.text("Failed to clear inbox", 500)
|
|
||||||
}
|
|
||||||
return c.json({
|
|
||||||
success: mailSuccess
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
api.delete('/admin/clear_sent_items/:id', async (c) => {
|
|
||||||
const { id } = c.req.param();
|
|
||||||
const { success: sendboxSuccess } = await c.env.DB.prepare(
|
|
||||||
`DELETE FROM sendbox WHERE address IN`
|
|
||||||
+ ` (select name from address where id = ?) `
|
|
||||||
).bind(id).run();
|
|
||||||
if (!sendboxSuccess) {
|
|
||||||
return c.text("Failed to clear sent items", 500)
|
|
||||||
}
|
|
||||||
return c.json({
|
|
||||||
success: sendboxSuccess
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
api.get('/admin/show_password/:id', async (c) => {
|
api.get('/admin/show_password/:id', async (c) => {
|
||||||
const { id } = c.req.param();
|
const { id } = c.req.param();
|
||||||
const name = await c.env.DB.prepare(
|
const name = await c.env.DB.prepare(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { AdminWebhookSettings } from "../models";
|
|||||||
|
|
||||||
async function getWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
async function getWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
||||||
const settings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
const settings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
||||||
return c.json(settings || new AdminWebhookSettings(false, []));
|
return c.json(settings || new AdminWebhookSettings([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
async function saveWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
||||||
|
|||||||
@@ -268,7 +268,9 @@ const batchDeleteAddressWithData = async (
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: need senbox delete?
|
||||||
|
*/
|
||||||
export const deleteAddressWithData = async (
|
export const deleteAddressWithData = async (
|
||||||
c: Context<HonoCustomType>,
|
c: Context<HonoCustomType>,
|
||||||
address: string | undefined | null,
|
address: string | undefined | null,
|
||||||
@@ -478,7 +480,7 @@ export async function triggerWebhook(
|
|||||||
|
|
||||||
// user mail webhook
|
// user mail webhook
|
||||||
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
||||||
if (!adminSettings?.enableAllowList || adminSettings?.allowList.includes(address)) {
|
if (adminSettings?.allowList.includes(address)) {
|
||||||
const settings = await c.env.KV.get<WebhookSettings>(
|
const settings = await c.env.KV.get<WebhookSettings>(
|
||||||
`${CONSTANTS.WEBHOOK_KV_USER_SETTINGS_KEY}:${address}`, "json"
|
`${CONSTANTS.WEBHOOK_KV_USER_SETTINGS_KEY}:${address}`, "json"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -162,39 +162,3 @@ api.delete('/api/delete_address', async (c) => {
|
|||||||
success: success
|
success: success
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
api.delete('/api/clear_inbox', async (c) => {
|
|
||||||
const lang = c.get("lang") || c.env.DEFAULT_LANG;
|
|
||||||
const msgs = i18n.getMessages(lang);
|
|
||||||
if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
|
|
||||||
return c.text(msgs.UserDeleteEmailDisabledMsg, 403)
|
|
||||||
}
|
|
||||||
const { address } = c.get("jwtPayload")
|
|
||||||
const { success } = await c.env.DB.prepare(
|
|
||||||
`DELETE FROM raw_mails WHERE address = ?`
|
|
||||||
).bind(address).run();
|
|
||||||
if (!success) {
|
|
||||||
return c.text("Failed to clear inbox", 500)
|
|
||||||
}
|
|
||||||
return c.json({
|
|
||||||
success: success
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
api.delete('/api/clear_sent_items', async (c) => {
|
|
||||||
const lang = c.get("lang") || c.env.DEFAULT_LANG;
|
|
||||||
const msgs = i18n.getMessages(lang);
|
|
||||||
if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
|
|
||||||
return c.text(msgs.UserDeleteEmailDisabledMsg, 403)
|
|
||||||
}
|
|
||||||
const { address } = c.get("jwtPayload")
|
|
||||||
const { success } = await c.env.DB.prepare(
|
|
||||||
`DELETE FROM sendbox WHERE address = ?`
|
|
||||||
).bind(address).run();
|
|
||||||
if (!success) {
|
|
||||||
return c.text("Failed to clear sent items", 500)
|
|
||||||
}
|
|
||||||
return c.json({
|
|
||||||
success: success
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { commonParseMail, sendWebhook } from "../common";
|
|||||||
async function getWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
async function getWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
||||||
const { address } = c.get("jwtPayload")
|
const { address } = c.get("jwtPayload")
|
||||||
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
||||||
if (adminSettings?.enableAllowList && !adminSettings?.allowList.includes(address)) {
|
if (!adminSettings?.allowList.includes(address)) {
|
||||||
return c.text("Webhook settings is not allowed for this user", 403);
|
return c.text("Webhook settings is not allowed for this user", 403);
|
||||||
}
|
}
|
||||||
const settings = await c.env.KV.get<WebhookSettings>(
|
const settings = await c.env.KV.get<WebhookSettings>(
|
||||||
@@ -20,7 +20,7 @@ async function getWebhookSettings(c: Context<HonoCustomType>): Promise<Response>
|
|||||||
async function saveWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
async function saveWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
|
||||||
const { address } = c.get("jwtPayload")
|
const { address } = c.get("jwtPayload")
|
||||||
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
const adminSettings = await c.env.KV.get<AdminWebhookSettings>(CONSTANTS.WEBHOOK_KV_SETTINGS_KEY, "json");
|
||||||
if (adminSettings?.enableAllowList && !adminSettings?.allowList.includes(address)) {
|
if (!adminSettings?.allowList.includes(address)) {
|
||||||
return c.text("Webhook settings is not allowed for this user", 403);
|
return c.text("Webhook settings is not allowed for this user", 403);
|
||||||
}
|
}
|
||||||
const settings = await c.req.json<WebhookSettings>();
|
const settings = await c.req.json<WebhookSettings>();
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ export type Passkey = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class AdminWebhookSettings {
|
export class AdminWebhookSettings {
|
||||||
enableAllowList: boolean;
|
|
||||||
allowList: string[];
|
allowList: string[];
|
||||||
|
|
||||||
constructor(enableAllowList: boolean, allowList: string[]) {
|
constructor(allowList: string[]) {
|
||||||
this.enableAllowList = enableAllowList;
|
|
||||||
this.allowList = allowList;
|
this.allowList = allowList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user