mirror of
https://github.com/streetwriters/notesnook-sync-server.git
synced 2026-10-11 06:38:45 +02:00
inbox: add health endpoint & docs (#64)
* inbox: add health endpoint && docs * inbox: update post endpoint uri * inbox: update docs & dockerfile --------- Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
This commit is contained in:
1 parent
3a2a04317f
commit
1c5bcd6eff
3 files changed
+85
-8
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
FROM oven/bun:1.2.21-slim
|
FROM oven/bun:1.3.5-slim
|
||||||
|
|
||||||
RUN mkdir -p /home/bun/app && chown -R bun:bun /home/bun/app
|
RUN mkdir -p /home/bun/app && chown -R bun:bun /home/bun/app
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Notesnook Inbox API
|
||||||
|
|
||||||
|
## Running locally
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- Bun (v1.3.0 or higher)
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
- `bun install` - Install dependencies
|
||||||
|
- `bun run dev` - Start the development server
|
||||||
|
- `bun run build` - Build the project for production
|
||||||
|
- `bun run start` - Start the production server
|
||||||
|
|
||||||
|
## Self-hosting
|
||||||
|
|
||||||
|
The easiest way to self-host is with Docker or Docker Compose.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- `docker` (Engine) installed
|
||||||
|
- `docker-compose` (optional, for multi-service setups)
|
||||||
|
|
||||||
|
Build and run with Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# build the image from the current folder
|
||||||
|
docker build -t notesnook-inbox-api .
|
||||||
|
|
||||||
|
# run the container (example)
|
||||||
|
docker run --rm -p 3000:3000 \
|
||||||
|
-e PORT=3000 \
|
||||||
|
-e NOTESNOOK_API_SERVER_URL="https://api.notesnook.com" \
|
||||||
|
notesnook-inbox-api
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker Compose (example):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
inbox-api:
|
||||||
|
image: notesnook-inbox-api
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
PORT: 3000
|
||||||
|
NOTESNOOK_API_SERVER_URL: "https://api.notesnook.com"
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
|
||||||
|
- `PORT` — port the service listens on (default: `5181`)
|
||||||
|
- `NOTESNOOK_API_SERVER_URL` — base URL of the Notesnook API used to fetch public inbox keys
|
||||||
|
|
||||||
|
_If you prefer running without Docker, use `bun install` and `bun run start` with the environment variables set._
|
||||||
|
|
||||||
|
## Writing from scratch
|
||||||
|
|
||||||
|
The inbox API server is pretty simple to write from scratch in any programming language and/or framework. There's only one endpoint that needs to be implemented, which does these three steps:
|
||||||
|
|
||||||
|
1. Fetch the user's public inbox API key from the Notesnook API.
|
||||||
|
2. Encrypt the payload using `openpgp` or any other `openpgp` compatible library.
|
||||||
|
3. Post the encrypted payload to the Notesnook API.
|
||||||
|
|
||||||
|
You can refer to the [source code](./src/index.ts) for implementation details.
|
||||||
@@ -33,9 +33,15 @@ interface EncryptedInboxItem {
|
|||||||
alg: string;
|
alg: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts raw data using OpenPGP with the recipient's public key
|
||||||
|
*
|
||||||
|
* @param {string} rawData - The plaintext data to encrypt
|
||||||
|
* @param {string} rawPublicKey - The recipient's OpenPGP public key
|
||||||
|
*/
|
||||||
async function encrypt(
|
async function encrypt(
|
||||||
rawData: string,
|
rawData: string,
|
||||||
rawPublicKey: string
|
rawPublicKey: string,
|
||||||
): Promise<EncryptedInboxItem> {
|
): Promise<EncryptedInboxItem> {
|
||||||
const publicKey = await openpgp.readKey({ armoredKey: rawPublicKey });
|
const publicKey = await openpgp.readKey({ armoredKey: rawPublicKey });
|
||||||
const message = await openpgp.createMessage({ text: rawData });
|
const message = await openpgp.createMessage({ text: rawData });
|
||||||
@@ -57,11 +63,11 @@ async function getInboxPublicEncryptionKey(apiKey: string) {
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: apiKey,
|
Authorization: apiKey,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`failed to fetch inbox public encryption key: ${await response.text()}`
|
`failed to fetch inbox public encryption key: ${await response.text()}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +77,7 @@ async function getInboxPublicEncryptionKey(apiKey: string) {
|
|||||||
|
|
||||||
async function postEncryptedInboxItem(
|
async function postEncryptedInboxItem(
|
||||||
apiKey: string,
|
apiKey: string,
|
||||||
item: EncryptedInboxItem
|
item: EncryptedInboxItem,
|
||||||
) {
|
) {
|
||||||
const response = await fetch(`${NOTESNOOK_API_SERVER_URL}/inbox/items`, {
|
const response = await fetch(`${NOTESNOOK_API_SERVER_URL}/inbox/items`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -92,9 +98,12 @@ app.use(
|
|||||||
rateLimit({
|
rateLimit({
|
||||||
windowMs: 1 * 60 * 1000, // 1 minute
|
windowMs: 1 * 60 * 1000, // 1 minute
|
||||||
limit: 60,
|
limit: 60,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
app.post("/inbox", async (req, res) => {
|
app.get("/health", (_, res) => {
|
||||||
|
return res.status(200).json({ status: "ok" });
|
||||||
|
});
|
||||||
|
app.post("/", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const apiKey = req.headers["authorization"];
|
const apiKey = req.headers["authorization"];
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
@@ -117,7 +126,7 @@ app.post("/inbox", async (req, res) => {
|
|||||||
|
|
||||||
const encryptedItem = await encrypt(
|
const encryptedItem = await encrypt(
|
||||||
JSON.stringify(validationResult.data),
|
JSON.stringify(validationResult.data),
|
||||||
inboxPublicKey
|
inboxPublicKey,
|
||||||
);
|
);
|
||||||
console.log("[info] encrypted item");
|
console.log("[info] encrypted item");
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user