mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-07-10 23:13:12 +08:00
feat: add JWT
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
DROP TABLE IF EXISTS mails;
|
DROP TABLE IF EXISTS mails;
|
||||||
DROP TABLE IF EXISTS address;
|
DROP TABLE IF EXISTS address;
|
||||||
CREATE TABLE IF NOT EXISTS mails (id INTEGER PRIMARY KEY, address TEXT, message TEXT);
|
CREATE TABLE IF NOT EXISTS mails (id INTEGER PRIMARY KEY, source TEXT, address TEXT, message TEXT);
|
||||||
CREATE TABLE IF NOT EXISTS address (id INTEGER PRIMARY KEY, name TEXT UNIQUE);
|
CREATE TABLE IF NOT EXISTS address (id INTEGER PRIMARY KEY, name TEXT UNIQUE);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { NGrid, NGi, NSpace, NAlert, NMessageProvider } from 'naive-ui'
|
import { NGrid, NGi, NSpace, NAlert, NMessageProvider } from 'naive-ui'
|
||||||
import { NSpin, NButton, NCard, NLayout, NPopconfirm } from 'naive-ui'
|
import { NSpin, NButton, NCard, NLayout, NPopconfirm } from 'naive-ui'
|
||||||
import { onMounted, ref } from "vue";
|
import { watch, onMounted, ref } from "vue";
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
|
|
||||||
const address = useStorage('address')
|
const jwt = useStorage('jwt')
|
||||||
|
const address = ref("")
|
||||||
const result = ref("")
|
const result = ref("")
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
@@ -19,6 +20,7 @@ const refresh = async () => {
|
|||||||
const response = await fetch(`${API_BASE}/api/mails?address=${address.value}`, {
|
const response = await fetch(`${API_BASE}/api/mails?address=${address.value}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
"Authorization": `Bearer ${jwt.value}`,
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -51,9 +53,9 @@ const newEmail = async () => {
|
|||||||
throw new Error(`${response.status} ${await response.text()}` || "error");
|
throw new Error(`${response.status} ${await response.text()}` || "error");
|
||||||
}
|
}
|
||||||
let res = await response.json();
|
let res = await response.json();
|
||||||
address.value = res["address"];
|
jwt.value = res["jwt"];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
address.value = "";
|
jwt.value = "";
|
||||||
console.error(error);
|
console.error(error);
|
||||||
result.value = error.message || "error";
|
result.value = error.message || "error";
|
||||||
} finally {
|
} finally {
|
||||||
@@ -62,7 +64,28 @@ const newEmail = async () => {
|
|||||||
await refresh();
|
await refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSettings = async (jwt) => {
|
||||||
|
const response = await fetch(`${API_BASE}/api/settings`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${jwt}`,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error(response);
|
||||||
|
address.value = "";
|
||||||
|
}
|
||||||
|
let res = await response.json();
|
||||||
|
address.value = res["address"];
|
||||||
|
await refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(jwt, async (jwt, old) => getSettings(jwt))
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
getSettings(jwt.value)
|
||||||
await refresh();
|
await refresh();
|
||||||
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;
|
const token = import.meta.env.VITE_CF_WEB_ANALY_TOKEN;
|
||||||
|
|
||||||
@@ -115,7 +138,8 @@ onMounted(async () => {
|
|||||||
<pre>{{ result }}</pre>
|
<pre>{{ result }}</pre>
|
||||||
</span>
|
</span>
|
||||||
</n-alert>
|
</n-alert>
|
||||||
<n-alert v-for="row in data" v-bind:key="row.id" :title="`EMAIL ID: ${row.id}`" type="default">
|
<n-alert v-for="row in data" v-bind:key="row.id" :title="`FROM: ${row.source} ID: ${row.id}`"
|
||||||
|
type="default">
|
||||||
<div v-html="row.message"></div>
|
<div v-html="row.message"></div>
|
||||||
</n-alert>
|
</n-alert>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ async function email(message, env, ctx) {
|
|||||||
const parsedEmail = await parser.parse(rawEmail);
|
const parsedEmail = await parser.parse(rawEmail);
|
||||||
|
|
||||||
const { success } = await env.DB.prepare(
|
const { success } = await env.DB.prepare(
|
||||||
`INSERT INTO mails (address, message) VALUES (?, ?)`
|
`INSERT INTO mails (source, address, message) VALUES (?, ?, ?)`
|
||||||
).bind(message.to, parsedEmail.html).run();
|
).bind(message.from, message.to, parsedEmail.html).run();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
message.setReject(`Failed save message to ${message.to}`);
|
message.setReject(`Failed save message to ${message.to}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Hono } from 'hono'
|
import { Hono } from 'hono'
|
||||||
|
import { Jwt } from 'hono/utils/jwt'
|
||||||
|
|
||||||
const api = new Hono()
|
const api = new Hono()
|
||||||
|
|
||||||
@@ -8,11 +9,15 @@ api.get('/api/mails', async (c) => {
|
|||||||
return c.json({ "error": "No address" }, 400)
|
return c.json({ "error": "No address" }, 400)
|
||||||
}
|
}
|
||||||
const { results } = await c.env.DB.prepare(
|
const { results } = await c.env.DB.prepare(
|
||||||
`SELECT id, message FROM mails where address = ? order by id desc limit 10`
|
`SELECT id, source, message FROM mails where address = ? order by id desc limit 10`
|
||||||
).bind(address).all();
|
).bind(address).all();
|
||||||
return c.json(results);
|
return c.json(results);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
api.get('/api/settings', async (c) => {
|
||||||
|
return c.json(c.get("jwtPayload"));
|
||||||
|
})
|
||||||
|
|
||||||
api.get('/api/new_address', async (c) => {
|
api.get('/api/new_address', async (c) => {
|
||||||
// insert new address
|
// insert new address
|
||||||
const name = Math.random().toString(36).substring(2, 15)
|
const name = Math.random().toString(36).substring(2, 15)
|
||||||
@@ -22,8 +27,12 @@ api.get('/api/new_address', async (c) => {
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
return c.json({ "error": "Failed to create address" }, 500)
|
return c.json({ "error": "Failed to create address" }, 500)
|
||||||
}
|
}
|
||||||
return c.json({
|
// create jwt
|
||||||
|
const jwt = await Jwt.sign({
|
||||||
address: c.env.PREFIX + name + "@" + c.env.DOMAIN
|
address: c.env.PREFIX + name + "@" + c.env.DOMAIN
|
||||||
|
}, c.env.JWT_SECRET)
|
||||||
|
return c.json({
|
||||||
|
jwt: jwt
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
import { Hono } from 'hono'
|
import { Hono } from 'hono'
|
||||||
import { cors } from 'hono/cors';
|
import { cors } from 'hono/cors';
|
||||||
|
import { jwt } from 'hono/jwt'
|
||||||
|
|
||||||
import { api } from './router';
|
import { api } from './router';
|
||||||
import { email } from './email';
|
import { email } from './email';
|
||||||
|
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
app.use('/*', cors());
|
app.use('/*', cors());
|
||||||
|
app.use('/api/*', async (c, next) => {
|
||||||
|
if (c.req.path.startsWith("/api/new_address")) {
|
||||||
|
await next();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
return jwt({ secret: c.env.JWT_SECRET })(c, next);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
app.route('/', api)
|
app.route('/', api)
|
||||||
|
|
||||||
app.all('/*', async c => c.html(`<h1>Hello World</h1>`))
|
app.all('/*', async c => c.html(`<h1>Hello World</h1>`))
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ compatibility_date = "2023-08-14"
|
|||||||
[vars]
|
[vars]
|
||||||
PREFIX = "tmp"
|
PREFIX = "tmp"
|
||||||
DOMAIN = "xxx.xxx"
|
DOMAIN = "xxx.xxx"
|
||||||
|
JWT_SECRET = "xxx"
|
||||||
|
|
||||||
[[d1_databases]]
|
[[d1_databases]]
|
||||||
binding = "DB"
|
binding = "DB"
|
||||||
|
|||||||
Reference in New Issue
Block a user