mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-25 10:09:48 +08:00
feat: improve address credential connections
This commit is contained in:
@@ -2,7 +2,7 @@ import { Context } from 'hono'
|
||||
import { Jwt } from 'hono/utils/jwt'
|
||||
|
||||
import i18n from '../i18n'
|
||||
import { getBooleanValue, hashPassword } from '../utils'
|
||||
import { getBooleanValue } from '../utils'
|
||||
import { newAddress, handleListQuery } from '../common'
|
||||
|
||||
const listAddresses = async (c: Context<HonoCustomType>) => {
|
||||
@@ -32,7 +32,7 @@ const listAddresses = async (c: Context<HonoCustomType>) => {
|
||||
+ ` FROM address a`
|
||||
+ ` where ${whereClause}`,
|
||||
`SELECT count(*) as count FROM address where ${whereClause}`,
|
||||
[param], limit, offset, orderBy
|
||||
[param], limit, offset, orderBy, ['password']
|
||||
);
|
||||
}
|
||||
return await handleListQuery(c,
|
||||
@@ -41,7 +41,7 @@ const listAddresses = async (c: Context<HonoCustomType>) => {
|
||||
+ ` (SELECT COUNT(*) FROM sendbox WHERE address = a.name) AS send_count`
|
||||
+ ` FROM address a`,
|
||||
`SELECT count(*) as count FROM address`,
|
||||
[], limit, offset, orderBy
|
||||
[], limit, offset, orderBy, ['password']
|
||||
);
|
||||
};
|
||||
|
||||
@@ -137,16 +137,16 @@ const resetPassword = async (c: Context<HonoCustomType>) => {
|
||||
const msgs = i18n.getMessagesbyContext(c);
|
||||
const { id } = c.req.param();
|
||||
const { password } = await c.req.json();
|
||||
// NOTE: Keep the admin API field as password, but the value is a frontend SHA-256 hash.
|
||||
if (!getBooleanValue(c.env.ENABLE_ADDRESS_PASSWORD)) {
|
||||
return c.text(msgs.PasswordChangeDisabledMsg, 403);
|
||||
}
|
||||
if (!password) {
|
||||
return c.text(msgs.NewPasswordRequiredMsg, 400);
|
||||
}
|
||||
const hashedPassword = await hashPassword(password);
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`UPDATE address SET password = ?, updated_at = datetime('now') WHERE id = ?`
|
||||
).bind(hashedPassword, id).run();
|
||||
).bind(password, id).run();
|
||||
if (!success) {
|
||||
return c.text(msgs.FailedUpdatePasswordMsg, 500);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ api.get('/open_api/settings', async (c) => {
|
||||
const auth = c.req.raw.headers.get("x-custom-auth");
|
||||
needAuth = !auth || !passwords.includes(auth);
|
||||
}
|
||||
const smtpImapProxyConfig = utils.getJsonObjectValue<SmtpImapProxyConfig>(
|
||||
c.env.SMTP_IMAP_PROXY_CONFIG
|
||||
) || {};
|
||||
const smtpProxyConfig = smtpImapProxyConfig.smtp || {};
|
||||
const imapProxyConfig = smtpImapProxyConfig.imap || {};
|
||||
|
||||
return c.json({
|
||||
"title": c.env.TITLE,
|
||||
@@ -45,6 +50,19 @@ api.get('/open_api/settings', async (c) => {
|
||||
"showGithub": !utils.getBooleanValue(c.env.DISABLE_SHOW_GITHUB),
|
||||
"disableAdminPasswordCheck": utils.getBooleanValue(c.env.DISABLE_ADMIN_PASSWORD_CHECK),
|
||||
"enableAddressPassword": utils.getBooleanValue(c.env.ENABLE_ADDRESS_PASSWORD),
|
||||
"enableAgentEmailInfo": utils.getBooleanValue(c.env.ENABLE_AGENT_EMAIL_INFO),
|
||||
"smtpImapProxyConfig": {
|
||||
"smtp": {
|
||||
"host": utils.getStringValue(smtpProxyConfig.host),
|
||||
"port": utils.getIntValue(smtpProxyConfig.port, 8025),
|
||||
"starttls": utils.getBooleanValue(smtpProxyConfig.starttls),
|
||||
},
|
||||
"imap": {
|
||||
"host": utils.getStringValue(imapProxyConfig.host),
|
||||
"port": utils.getIntValue(imapProxyConfig.port, 11143),
|
||||
"starttls": utils.getBooleanValue(imapProxyConfig.starttls),
|
||||
},
|
||||
},
|
||||
"statusUrl": utils.getStringValue(c.env.STATUS_URL),
|
||||
"enableGlobalTurnstileCheck": utils.isGlobalTurnstileEnabled(c)
|
||||
});
|
||||
|
||||
@@ -611,7 +611,8 @@ export const handleListQuery = async (
|
||||
limit: string | number | undefined | null,
|
||||
offset: string | number | undefined | null,
|
||||
/** Must be pre-validated (e.g. whitelist), NOT raw user input. Interpolated directly into SQL. */
|
||||
orderBy?: string
|
||||
orderBy?: string,
|
||||
hiddenFields: string[] = []
|
||||
): Promise<Response> => {
|
||||
const msgs = i18n.getMessagesbyContext(c);
|
||||
if (typeof limit === "string") {
|
||||
@@ -634,7 +635,23 @@ export const handleListQuery = async (
|
||||
const count = offset == 0 ? await c.env.DB.prepare(
|
||||
countQuery
|
||||
).bind(...params).first("count") : 0;
|
||||
return c.json({ results, count });
|
||||
if (hiddenFields.length === 0) {
|
||||
return c.json({ results, count });
|
||||
}
|
||||
|
||||
const filteredResults = results.map((row) => hideObjectFields(row, hiddenFields));
|
||||
return c.json({ results: filteredResults, count });
|
||||
}
|
||||
|
||||
export const hideObjectFields = <T extends Record<string, unknown>>(
|
||||
row: T,
|
||||
fields: string[]
|
||||
): T => {
|
||||
const filteredRow = { ...row };
|
||||
for (const field of fields) {
|
||||
delete filteredRow[field];
|
||||
}
|
||||
return filteredRow;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
return c.text(msgs.InvalidAddressTokenMsg, 400);
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
// NOTE: new_password is the frontend SHA-256 hash, stored directly in address.password.
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`UPDATE address SET password = ?, updated_at = datetime('now') WHERE id = ?`
|
||||
).bind(new_password, address_id).run();
|
||||
@@ -67,7 +67,7 @@ export default {
|
||||
return c.text(msgs.AddressNotFoundMsg, 404);
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
// NOTE: password is the frontend SHA-256 hash, compared directly with address.password.
|
||||
if (address.password !== password) {
|
||||
return c.text(msgs.InvalidEmailOrPasswordMsg, 401);
|
||||
}
|
||||
|
||||
15
worker/src/types.d.ts
vendored
15
worker/src/types.d.ts
vendored
@@ -4,6 +4,19 @@ type UserRole = {
|
||||
prefix: string | undefined | null
|
||||
}
|
||||
|
||||
type SmtpImapProxyConfig = {
|
||||
smtp?: {
|
||||
host?: string
|
||||
port?: number | string
|
||||
starttls?: boolean | string
|
||||
}
|
||||
imap?: {
|
||||
host?: string
|
||||
port?: number | string
|
||||
starttls?: boolean | string
|
||||
}
|
||||
}
|
||||
|
||||
type Bindings = {
|
||||
// bindings
|
||||
DB: D1Database
|
||||
@@ -45,6 +58,8 @@ type Bindings = {
|
||||
DISABLE_ANONYMOUS_USER_CREATE_EMAIL: string | boolean | undefined
|
||||
ENABLE_USER_DELETE_EMAIL: string | boolean | undefined
|
||||
ENABLE_ADDRESS_PASSWORD: string | boolean | undefined
|
||||
ENABLE_AGENT_EMAIL_INFO: string | boolean | undefined
|
||||
SMTP_IMAP_PROXY_CONFIG: string | SmtpImapProxyConfig | undefined
|
||||
ENABLE_INDEX_ABOUT: string | boolean | undefined
|
||||
DEFAULT_SEND_BALANCE: number | string | undefined
|
||||
NO_LIMIT_SEND_ROLE: string | undefined | null
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Jwt } from 'hono/utils/jwt'
|
||||
import { isAddressCountLimitReached } from "../utils"
|
||||
import { unbindTelegramByAddress } from '../telegram_api/common';
|
||||
import i18n from '../i18n';
|
||||
import { updateAddressUpdatedAt, commonGetUserRole } from '../common';
|
||||
import { updateAddressUpdatedAt, commonGetUserRole, hideObjectFields } from '../common';
|
||||
|
||||
const UserBindAddressModule = {
|
||||
bind: async (c: Context<HonoCustomType>) => {
|
||||
@@ -140,7 +140,7 @@ const UserBindAddressModule = {
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>();
|
||||
return results || [];
|
||||
return (results || []).map((row) => hideObjectFields(row, ['password']));
|
||||
},
|
||||
getBindedAddressJwt: async (c: Context<HonoCustomType>) => {
|
||||
const msgs = i18n.getMessagesbyContext(c);
|
||||
|
||||
@@ -81,6 +81,15 @@ ENABLE_AUTO_REPLY = false
|
||||
# ENABLE_WEBHOOK = true
|
||||
# Enable address password feature, if set true, will generate password for new address and support password login and change
|
||||
# ENABLE_ADDRESS_PASSWORD = false
|
||||
# Show AI Agent mailbox connection info in the address credential modal
|
||||
# ENABLE_AGENT_EMAIL_INFO = true
|
||||
# Show SMTP/IMAP client connection info in the address credential modal
|
||||
# SMTP_IMAP_PROXY_CONFIG = """
|
||||
# {
|
||||
# "smtp": { "host": "smtp.example.com", "port": 8025, "starttls": true },
|
||||
# "imap": { "host": "imap.example.com", "port": 11143, "starttls": true }
|
||||
# }
|
||||
# """
|
||||
# Footer text
|
||||
# COPYRIGHT = "Dream Hunter"
|
||||
# DISABLE_SHOW_GITHUB = true
|
||||
|
||||
Reference in New Issue
Block a user