diff --git a/worker/src/telegram_api/common.ts b/worker/src/telegram_api/common.ts index 1bc1c52e..e18bd822 100644 --- a/worker/src/telegram_api/common.ts +++ b/worker/src/telegram_api/common.ts @@ -3,7 +3,7 @@ import { Jwt } from "hono/utils/jwt"; import { CONSTANTS } from "../constants"; import { HonoCustomType } from "../types"; import { getIntValue, getJsonSetting } from "../utils"; -import { newAddress } from "../common"; +import { deleteAddressWithData, newAddress } from "../common"; export const tgUserNewAddress = async ( c: Context, userId: string, address: string @@ -18,7 +18,6 @@ export const tgUserNewAddress = async ( } // @ts-ignore address = address || Math.random().toString(36).substring(2, 15); - console.log(`new address: ${address}`); const [name, domain] = address.includes("@") ? address.split("@") : [address, null]; const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; if (jwtList.length >= getIntValue(c.env.TG_MAX_ADDRESS, 5)) { @@ -40,6 +39,24 @@ export const tgUserNewAddress = async ( return res; } +export const jwtListToAddressData = async ( + c: Context, jwtList: string[] +): Promise<{ addressList: string[], addressIdMap: Record }> => { + const addressList = []; + const addressIdMap = {} as Record; + for (const jwt of jwtList) { + try { + const { address, address_id } = await Jwt.verify(jwt, c.env.JWT_SECRET, "HS256"); + addressList.push(address); + addressIdMap[address] = address_id; + } catch (e) { + addressList.push("无效凭证"); + console.log(`获取地址列表失败: ${(e as Error).message}`); + } + } + return { addressList, addressIdMap }; +} + export const bindTelegramAddress = async ( c: Context, userId: string, jwt: string ): Promise => { @@ -48,6 +65,10 @@ export const bindTelegramAddress = async ( throw Error("无效凭证"); } const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; + const { addressIdMap } = await jwtListToAddressData(c, jwtList); + if (address in addressIdMap) { + return address; + } if (jwtList.length >= getIntValue(c.env.TG_MAX_ADDRESS, 5)) { throw Error("绑定地址数量已达上限"); } @@ -87,3 +108,16 @@ export const unbindTelegramByAddress = async ( } return true; } + + +export const deleteTelegramAddress = async ( + c: Context, userId: string, address: string +): Promise => { + const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; + const { addressIdMap } = await jwtListToAddressData(c, jwtList); + if (!(address in addressIdMap)) { + throw Error("此地址不属于您"); + } + await deleteAddressWithData(c, null, addressIdMap[address]) + return true; +} diff --git a/worker/src/telegram_api/miniapp.ts b/worker/src/telegram_api/miniapp.ts index 53ea77d7..776a6f33 100644 --- a/worker/src/telegram_api/miniapp.ts +++ b/worker/src/telegram_api/miniapp.ts @@ -2,7 +2,7 @@ import { Context } from "hono"; import { Jwt } from 'hono/utils/jwt' import { HonoCustomType } from "../types"; import { CONSTANTS } from "../constants"; -import { bindTelegramAddress, tgUserNewAddress, unbindTelegramAddress } from "./common"; +import { bindTelegramAddress, jwtListToAddressData, tgUserNewAddress, unbindTelegramAddress } from "./common"; import { checkCfTurnstile } from "../utils"; const encoder = new TextEncoder(); @@ -126,20 +126,18 @@ async function getMail(c: Context): Promise { try { const userId = await checkTelegramAuth(c, initData); const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; - const addressList = []; - for (const jwt of jwtList) { - try { - const { address } = await Jwt.verify(jwt, c.env.JWT_SECRET, "HS256"); - addressList.push(address); - } catch (e) { - addressList.push("此凭证无效"); - continue; - } - } + const { addressList, addressIdMap } = await jwtListToAddressData(c, jwtList); const result = await c.env.DB.prepare( `SELECT * FROM raw_mails where id = ?` ).bind(mailId).first(); - if (result?.address && !addressList.includes(result.address)) { + if (result?.address && !(result.address as string in addressIdMap)) { + return c.text("无权查看此邮件", 403); + } + const address_id = addressIdMap[result?.address as string]; + const db_address_id = await c.env.DB.prepare( + `SELECT id FROM address where id = ? ` + ).bind(address_id).first("id"); + if (!db_address_id) { return c.text("无权查看此邮件", 403); } return c.json(result); diff --git a/worker/src/telegram_api/telegram.ts b/worker/src/telegram_api/telegram.ts index 6b64779b..3bf374fd 100644 --- a/worker/src/telegram_api/telegram.ts +++ b/worker/src/telegram_api/telegram.ts @@ -6,11 +6,10 @@ import { callbackQuery } from "telegraf/filters"; import PostalMime from 'postal-mime'; import { CONSTANTS } from "../constants"; -import { getIntValue, getDomains, getStringValue } from '../utils'; -import { deleteAddressWithData } from '../common' +import { getDomains, getStringValue } from '../utils'; import { HonoCustomType } from "../types"; import { TelegramSettings } from "./settings"; -import { bindTelegramAddress, tgUserNewAddress, unbindTelegramAddress } from "./common"; +import { bindTelegramAddress, deleteTelegramAddress, jwtListToAddressData, tgUserNewAddress, unbindTelegramAddress, unbindTelegramByAddress } from "./common"; const COMMANDS = [ { @@ -145,13 +144,17 @@ export function newTelegramBot(c: Context, token: string): Teleg }) bot.command("delete", async (ctx: TgContext) => { + const userId = ctx?.message?.from?.id; + if (!userId) { + return await ctx.reply("无法获取用户信息"); + } try { // @ts-ignore const address = ctx?.message?.text.slice("/unbind".length).trim(); if (!address) { return await ctx.reply("请输入地址"); } - await deleteAddressWithData(c, address, null) + await deleteTelegramAddress(c, userId.toString(), address); return await ctx.reply(`删除成功: ${address}`); } catch (e) { return await ctx.reply(`删除失败: ${(e as Error).message}`); @@ -165,16 +168,7 @@ export function newTelegramBot(c: Context, token: string): Teleg } try { const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; - const addressList = []; - for (const jwt of jwtList) { - try { - const { address } = await Jwt.verify(jwt, c.env.JWT_SECRET, "HS256"); - addressList.push(address); - } catch (e) { - addressList.push("此凭证无效"); - continue; - } - } + const { addressList } = await jwtListToAddressData(c, jwtList); return await ctx.reply(`地址列表:\n\n` + addressList.map(a => `地址: ${a}`).join("\n") ); @@ -189,21 +183,20 @@ export function newTelegramBot(c: Context, token: string): Teleg return await ctx.reply("无法获取用户信息"); } const jwtList = await c.env.KV.get(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || []; - const addressList = []; - for (const jwt of jwtList) { - try { - const { address } = await Jwt.verify(jwt, c.env.JWT_SECRET, "HS256"); - addressList.push(address); - } catch (e) { - continue; - } - } + const { addressList, addressIdMap } = await jwtListToAddressData(c, jwtList); if (!queryAddress && addressList.length > 0) { queryAddress = addressList[0]; } - if (!addressList.includes(queryAddress)) { + if (!(queryAddress in addressIdMap)) { return await ctx.reply(`未绑定此地址 ${queryAddress}`); } + const address_id = addressIdMap[queryAddress]; + const db_address_id = await c.env.DB.prepare( + `SELECT id FROM address where id = ? ` + ).bind(address_id).first("id"); + if (!db_address_id) { + return await ctx.reply("无效地址"); + } const { raw, id: mailId } = await c.env.DB.prepare( `SELECT * FROM raw_mails where address = ? ` + ` order by id desc limit 1 offset ?` @@ -217,7 +210,7 @@ export function newTelegramBot(c: Context, token: string): Teleg const url = new URL(settings.miniAppUrl); url.pathname = "/telegram_mail" url.searchParams.set("mail_id", mailId); - miniAppButtons.push(Markup.button.webApp("OpenApp", url.toString())); + miniAppButtons.push(Markup.button.webApp("查看邮件", url.toString())); } if (edit) { return await ctx.editMessageText(mail || "无邮件",