Files
cloudflare_temp_email/worker/src/worker.ts
2024-05-26 12:37:11 +08:00

138 lines
3.8 KiB
TypeScript

import { Hono } from 'hono'
import { cors } from 'hono/cors';
import { jwt } from 'hono/jwt'
import { Jwt } from 'hono/utils/jwt'
// @ts-ignore
import { api as apiV1 } from './deprecated';
import { api as commonApi } from './commom_api';
import { api as mailsApi } from './mails_api'
import { api as userApi } from './user_api';
import { api as adminApi } from './admin_api';
import { api as apiSendMail } from './mails_api/send_mail_api'
import { api as telegramApi } from './telegram_api'
import { email } from './email';
import { scheduled } from './scheduled';
import { getAdminPasswords, getPasswords, getBooleanValue } from './utils';
import { HonoCustomType } from './types';
const app = new Hono<HonoCustomType>()
//cors
app.use('/*', cors());
// rate limit
app.use('/*', async (c, next) => {
if (
c.req.path.startsWith("/api/new_address")
|| c.req.path.startsWith("/api/send_mail")
|| c.req.path.startsWith("/external/api/send_mail")
|| c.req.path.startsWith("/user_api/register")
|| c.req.path.startsWith("/user_api/verify_code")
) {
const reqIp = c.req.raw.headers.get("cf-connecting-ip")
if (reqIp && c.env.RATE_LIMITER) {
const { success } = await c.env.RATE_LIMITER.limit(
{ key: `${c.req.path}|${reqIp}` }
)
if (!success) {
return c.text(`IP=${reqIp} Rate limit exceeded for ${c.req.path}`, 429)
}
}
}
if (
c.req.path.startsWith("/api/webhook")
|| c.req.path.startsWith("/admin/webhook")
) {
if (!c.env.KV) {
return c.text("KV is not available", 400);
}
if (!getBooleanValue(c.env.ENABLE_WEBHOOK)) {
return c.text("Webhook is disabled", 403);
}
}
await next()
});
// api auth
app.use('/api/*', async (c, next) => {
// check header x-custom-auth
const passwords = getPasswords(c);
if (passwords && passwords.length > 0) {
const auth = c.req.raw.headers.get("x-custom-auth");
if (!auth || !passwords.includes(auth)) {
return c.text("Need Password", 401)
}
}
if (c.req.path.startsWith("/api/new_address")) {
await next();
return;
}
return jwt({ secret: c.env.JWT_SECRET, alg: "HS256" })(c, next);
});
// user_api auth
app.use('/user_api/*', async (c, next) => {
if (
c.req.path.startsWith("/user_api/open_settings")
|| c.req.path.startsWith("/user_api/register")
|| c.req.path.startsWith("/user_api/login")
|| c.req.path.startsWith("/user_api/verify_code")
) {
await next();
return;
}
try {
const token = c.req.raw.headers.get("x-user-token");
if (!token) return c.text("Need User Token", 401)
const payload = await Jwt.verify(token, c.env.JWT_SECRET, "HS256");
// check expired
if (!payload.exp) return c.text("Invalid Token", 401);
// exp is in seconds
if (payload.exp < Math.floor(Date.now() / 1000)) {
return c.text("Token Expired", 401)
}
c.set("userPayload", payload);
} catch (e) {
console.error(e);
return c.text("Need User Token", 401)
}
if (c.req.path.startsWith('/user_api/bind_address')
&& c.req.method === 'POST'
) {
return jwt({ secret: c.env.JWT_SECRET, alg: "HS256" })(c, next);
}
await next();
});
// admin auth
app.use('/admin/*', async (c, next) => {
// check header x-admin-auth
const adminPasswords = getAdminPasswords(c);
if (adminPasswords && adminPasswords.length > 0) {
const adminAuth = c.req.raw.headers.get("x-admin-auth");
if (adminAuth && adminPasswords.includes(adminAuth)) {
await next();
return;
}
}
return c.text("Need Admin Password", 401)
});
app.route('/', commonApi)
app.route('/', mailsApi)
app.route('/', userApi)
app.route('/', adminApi)
app.route('/', apiV1)
app.route('/', apiSendMail)
app.route('/', telegramApi)
app.get('/', async c => c.text("OK"))
app.get('/health_check', async c => c.text("OK"))
app.all('/*', async c => c.text("Not Found", 404))
export default {
fetch: app.fetch,
email: email,
scheduled: scheduled,
}