mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-05 23:47:50 +08:00
feat: add NO_LIMIT_SEND_ROLE (#373)
This commit is contained in:
+2
-1
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
- Docs: Update new-address-api.md (#360)
|
- Docs: Update new-address-api.md (#360)
|
||||||
- feat: worker 增加 `ADMIN_USER_ROLE` 配置, 用于配置管理员用户角色,此角色的用户可访问 admin 管理页面 (#363)
|
- feat: worker 增加 `ADMIN_USER_ROLE` 配置, 用于配置管理员用户角色,此角色的用户可访问 admin 管理页面 (#363)
|
||||||
- feat: worker 增加 `SHOW_GITHUB` 配置, 用于配置是否显示 github 链接
|
- feat: worker 增加 `DISABLE_SHOW_GITHUB` 配置, 用于配置是否显示 github 链接
|
||||||
|
- feat: worker 增加 `NO_LIMIT_SEND_ROLE` 配置, 用于配置可以无限发送邮件的角色
|
||||||
|
|
||||||
## v0.6.1
|
## v0.6.1
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const useGlobalState = createGlobalState(
|
|||||||
cfTurnstileSiteKey: '',
|
cfTurnstileSiteKey: '',
|
||||||
enableWebhook: false,
|
enableWebhook: false,
|
||||||
isS3Enabled: false,
|
isS3Enabled: false,
|
||||||
showGithub: false,
|
showGithub: true,
|
||||||
})
|
})
|
||||||
const settings = ref({
|
const settings = ref({
|
||||||
fetched: false,
|
fetched: false,
|
||||||
|
|||||||
@@ -109,9 +109,10 @@ ENABLE_AUTO_REPLY = false
|
|||||||
# ENABLE_WEBHOOK = true
|
# ENABLE_WEBHOOK = true
|
||||||
# Footer text
|
# Footer text
|
||||||
# COPYRIGHT = "Dream Hunter"
|
# COPYRIGHT = "Dream Hunter"
|
||||||
# SHOW_GITHUB = true # Show GitHub link
|
# DISABLE_SHOW_GITHUB = true # Disable Show GitHub link
|
||||||
# default send balance, if not set, it will be 0
|
# default send balance, if not set, it will be 0
|
||||||
# DEFAULT_SEND_BALANCE = 1
|
# DEFAULT_SEND_BALANCE = 1
|
||||||
|
# NO_LIMIT_SEND_ROLE = "vip" # the role which can send emails without limit
|
||||||
# Turnstile verification configuration
|
# Turnstile verification configuration
|
||||||
# CF_TURNSTILE_SITE_KEY = ""
|
# CF_TURNSTILE_SITE_KEY = ""
|
||||||
# CF_TURNSTILE_SECRET_KEY = ""
|
# CF_TURNSTILE_SECRET_KEY = ""
|
||||||
|
|||||||
@@ -80,9 +80,10 @@ ENABLE_AUTO_REPLY = false
|
|||||||
# ENABLE_WEBHOOK = true
|
# ENABLE_WEBHOOK = true
|
||||||
# 前端界面页脚文本
|
# 前端界面页脚文本
|
||||||
# COPYRIGHT = "Dream Hunter"
|
# COPYRIGHT = "Dream Hunter"
|
||||||
# SHOW_GITHUB = true # 是否显示 GitHub 链接
|
# DISABLE_SHOW_GITHUB = true # 是否显示 GitHub 链接
|
||||||
# 默认发送邮件余额,如果不设置,将为 0
|
# 默认发送邮件余额,如果不设置,将为 0
|
||||||
# DEFAULT_SEND_BALANCE = 1
|
# DEFAULT_SEND_BALANCE = 1
|
||||||
|
# NO_LIMIT_SEND_ROLE = "vip" # 可以无限发送邮件的角色
|
||||||
# Turnstile 人机验证配置
|
# Turnstile 人机验证配置
|
||||||
# CF_TURNSTILE_SITE_KEY = ""
|
# CF_TURNSTILE_SITE_KEY = ""
|
||||||
# CF_TURNSTILE_SECRET_KEY = ""
|
# CF_TURNSTILE_SECRET_KEY = ""
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ api.get('/open_api/settings', async (c) => {
|
|||||||
"enableWebhook": getBooleanValue(c.env.ENABLE_WEBHOOK),
|
"enableWebhook": getBooleanValue(c.env.ENABLE_WEBHOOK),
|
||||||
"isS3Enabled": isS3Enabled(c),
|
"isS3Enabled": isS3Enabled(c),
|
||||||
"version": CONSTANTS.VERSION,
|
"version": CONSTANTS.VERSION,
|
||||||
"showGithub": getBooleanValue(c.env.SHOW_GITHUB),
|
"showGithub": !getBooleanValue(c.env.DISABLE_SHOW_GITHUB),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Hono } from 'hono'
|
import { Hono } from 'hono'
|
||||||
|
|
||||||
import { HonoCustomType } from "../types";
|
import { HonoCustomType } from "../types";
|
||||||
import { getBooleanValue, getJsonSetting, checkCfTurnstile } from '../utils';
|
import { getBooleanValue, getJsonSetting, checkCfTurnstile, getStringValue } from '../utils';
|
||||||
import { newAddress, handleListQuery, deleteAddressWithData, getAddressPrefix, getAllowDomains } from '../common'
|
import { newAddress, handleListQuery, deleteAddressWithData, getAddressPrefix, getAllowDomains } from '../common'
|
||||||
import { CONSTANTS } from '../constants'
|
import { CONSTANTS } from '../constants'
|
||||||
import auto_reply from './auto_reply'
|
import auto_reply from './auto_reply'
|
||||||
@@ -49,6 +49,7 @@ api.delete('/api/mails/:id', async (c) => {
|
|||||||
|
|
||||||
api.get('/api/settings', async (c) => {
|
api.get('/api/settings', async (c) => {
|
||||||
const { address, address_id } = c.get("jwtPayload")
|
const { address, address_id } = c.get("jwtPayload")
|
||||||
|
const user_role = c.get("userRolePayload")
|
||||||
if (address_id && address_id > 0) {
|
if (address_id && address_id > 0) {
|
||||||
try {
|
try {
|
||||||
const db_address_id = await c.env.DB.prepare(
|
const db_address_id = await c.env.DB.prepare(
|
||||||
@@ -82,7 +83,8 @@ api.get('/api/settings', async (c) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Failed to update address")
|
console.warn("Failed to update address")
|
||||||
}
|
}
|
||||||
const balance = await c.env.DB.prepare(
|
const is_no_limit_send_balance = user_role && user_role === getStringValue(c.env.NO_LIMIT_SEND_ROLE);
|
||||||
|
const balance = is_no_limit_send_balance ? 99999 : await c.env.DB.prepare(
|
||||||
`SELECT balance FROM address_sender where address = ? and enabled = 1`
|
`SELECT balance FROM address_sender where address = ? and enabled = 1`
|
||||||
).bind(address).first("balance");
|
).bind(address).first("balance");
|
||||||
return c.json({
|
return c.json({
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createMimeMessage } from 'mimetext';
|
|||||||
import { Resend } from 'resend';
|
import { Resend } from 'resend';
|
||||||
|
|
||||||
import { CONSTANTS } from '../constants'
|
import { CONSTANTS } from '../constants'
|
||||||
import { getJsonSetting, getDomains, getIntValue, getBooleanValue } from '../utils';
|
import { getJsonSetting, getDomains, getIntValue, getBooleanValue, getStringValue } from '../utils';
|
||||||
import { GeoData } from '../models'
|
import { GeoData } from '../models'
|
||||||
import { handleListQuery } from '../common'
|
import { handleListQuery } from '../common'
|
||||||
import { HonoCustomType } from '../types';
|
import { HonoCustomType } from '../types';
|
||||||
@@ -105,13 +105,17 @@ export const sendMail = async (
|
|||||||
if (!domains.includes(mailDomain)) {
|
if (!domains.includes(mailDomain)) {
|
||||||
throw new Error("Invalid domain")
|
throw new Error("Invalid domain")
|
||||||
}
|
}
|
||||||
// check permission
|
const user_role = c.get("userRolePayload");
|
||||||
const balance = await c.env.DB.prepare(
|
const is_no_limit_send_balance = user_role && user_role === getStringValue(c.env.NO_LIMIT_SEND_ROLE);
|
||||||
`SELECT balance FROM address_sender
|
if (!is_no_limit_send_balance) {
|
||||||
|
// check permission
|
||||||
|
const balance = await c.env.DB.prepare(
|
||||||
|
`SELECT balance FROM address_sender
|
||||||
where address = ? and enabled = 1`
|
where address = ? and enabled = 1`
|
||||||
).bind(address).first<number>("balance");
|
).bind(address).first<number>("balance");
|
||||||
if (!balance || balance <= 0) {
|
if (!balance || balance <= 0) {
|
||||||
throw new Error("No balance")
|
throw new Error("No balance")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
from_name, to_mail, to_name,
|
from_name, to_mail, to_name,
|
||||||
@@ -154,7 +158,7 @@ export const sendMail = async (
|
|||||||
throw new Error("Please enable resend or verified address list")
|
throw new Error("Please enable resend or verified address list")
|
||||||
}
|
}
|
||||||
// update balance
|
// update balance
|
||||||
if (!sendByVerifiedAddressList) {
|
if (!sendByVerifiedAddressList && !is_no_limit_send_balance) {
|
||||||
try {
|
try {
|
||||||
const { success } = await c.env.DB.prepare(
|
const { success } = await c.env.DB.prepare(
|
||||||
`UPDATE address_sender SET balance = balance - 1 where address = ?`
|
`UPDATE address_sender SET balance = balance - 1 where address = ?`
|
||||||
|
|||||||
Vendored
+4
-2
@@ -33,9 +33,10 @@ export type Bindings = {
|
|||||||
ENABLE_USER_DELETE_EMAIL: string | boolean | undefined
|
ENABLE_USER_DELETE_EMAIL: string | boolean | undefined
|
||||||
ENABLE_INDEX_ABOUT: string | boolean | undefined
|
ENABLE_INDEX_ABOUT: string | boolean | undefined
|
||||||
DEFAULT_SEND_BALANCE: number | string | undefined
|
DEFAULT_SEND_BALANCE: number | string | undefined
|
||||||
|
NO_LIMIT_SEND_ROLE: string | undefined | null
|
||||||
ADMIN_CONTACT: string | undefined
|
ADMIN_CONTACT: string | undefined
|
||||||
COPYRIGHT: string | undefined
|
COPYRIGHT: string | undefined
|
||||||
SHOW_GITHUB: string | boolean | undefined
|
DISABLE_SHOW_GITHUB: string | boolean | undefined
|
||||||
FORWARD_ADDRESS_LIST: string | string[] | undefined
|
FORWARD_ADDRESS_LIST: string | string[] | undefined
|
||||||
|
|
||||||
// s3 config
|
// s3 config
|
||||||
@@ -72,7 +73,8 @@ type UserPayload = {
|
|||||||
|
|
||||||
type Variables = {
|
type Variables = {
|
||||||
userPayload: UserPayload,
|
userPayload: UserPayload,
|
||||||
jwtPayload: JwtPayload
|
userRolePayload: string | undefined | null,
|
||||||
|
jwtPayload: JwtPayload,
|
||||||
}
|
}
|
||||||
|
|
||||||
type HonoCustomType = {
|
type HonoCustomType = {
|
||||||
|
|||||||
@@ -75,6 +75,26 @@ const checkUserPayload = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkoutUserRolePayload = async (
|
||||||
|
c: Context<HonoCustomType>
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const token = c.req.raw.headers.get("x-user-access-token");
|
||||||
|
if (!token) return;
|
||||||
|
const payload = await Jwt.verify(token, c.env.JWT_SECRET, "HS256");
|
||||||
|
// check expired
|
||||||
|
if (!payload.exp) return;
|
||||||
|
// exp is in seconds
|
||||||
|
if (payload.exp < Math.floor(Date.now() / 1000)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof payload?.user_role !== "string") return;
|
||||||
|
c.set("userRolePayload", payload.user_role);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// api auth
|
// api auth
|
||||||
app.use('/api/*', async (c, next) => {
|
app.use('/api/*', async (c, next) => {
|
||||||
// check header x-custom-auth
|
// check header x-custom-auth
|
||||||
@@ -90,6 +110,11 @@ app.use('/api/*', async (c, next) => {
|
|||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (c.req.path.startsWith("/api/settings")
|
||||||
|
|| c.req.path.startsWith("/api/send_mail")
|
||||||
|
) {
|
||||||
|
await checkoutUserRolePayload(c);
|
||||||
|
}
|
||||||
return jwt({ secret: c.env.JWT_SECRET, alg: "HS256" })(c, next);
|
return jwt({ secret: c.env.JWT_SECRET, alg: "HS256" })(c, next);
|
||||||
});
|
});
|
||||||
// user_api auth
|
// user_api auth
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ ENABLE_AUTO_REPLY = false
|
|||||||
# ENABLE_WEBHOOK = true
|
# ENABLE_WEBHOOK = true
|
||||||
# Footer text
|
# Footer text
|
||||||
# COPYRIGHT = "Dream Hunter"
|
# COPYRIGHT = "Dream Hunter"
|
||||||
# SHOW_GITHUB = true
|
# DISABLE_SHOW_GITHUB = true
|
||||||
# default send balance, if not set, it will be 0
|
# default send balance, if not set, it will be 0
|
||||||
# DEFAULT_SEND_BALANCE = 1
|
# DEFAULT_SEND_BALANCE = 1
|
||||||
# Turnstile verification
|
# Turnstile verification
|
||||||
|
|||||||
Reference in New Issue
Block a user