add proxy routes, webauthn bug fix

This commit is contained in:
2025-02-21 11:37:23 +05:30
parent 5d5cee2d7e
commit a41127b2fd
9 changed files with 198 additions and 2 deletions

View File

@@ -0,0 +1,39 @@
import { FastifyInstance } from "fastify";
import { $mail, ProxyRequest } from "./mailProxy.schema";
import { getOutlookTokens } from "./mailProxy.service";
import axios from "axios";
export async function mailProxyRoutes(fastify: FastifyInstance) {
fastify.post(
"/",
{
schema: {
body: $mail("proxyRequest"),
},
config: { requiredClaims: ["mail:all"] },
preHandler: [fastify.authorize],
},
async (req, res) => {
const input = req.body as ProxyRequest;
try {
const tokens = await getOutlookTokens(input.email);
if (!tokens) return res.code(404).send({ error: "resource not found" });
const result = await axios({
url: input.url,
method: input.method,
headers: {
Authorization: "Bearer " + tokens.access_token,
},
data: input.body,
validateStatus: () => true,
});
return res.code(result.status).send(result.data);
} catch (err) {
return err;
}
}
);
}

View File

@@ -0,0 +1,34 @@
import { buildJsonSchemas } from "fastify-zod";
import mongoose from "mongoose";
import { z } from "zod";
export const mailModel = mongoose.model(
"oauth",
new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
access_token: String,
expiry: Date,
refresh_token: String,
}),
"oauth"
);
const proxyRequest = z.object({
email: z.string().email(),
url: z.string(),
method: z.enum(["GET", "POST", "PATCH", "DELETE"]),
body: z.any(),
});
export type ProxyRequest = z.infer<typeof proxyRequest>;
export const { schemas: mailSchemas, $ref: $mail } = buildJsonSchemas(
{
proxyRequest,
},
{ $id: "mail" }
);

View File

@@ -0,0 +1,48 @@
import qs from "qs";
import axios from "axios";
import { mailModel } from "./mailProxy.schema";
export async function getOutlookTokens(email: string) {
let tokens = await mailModel.findOne({ email: email });
if (!tokens) {
return null;
} else {
const date = new Date();
const expiry = new Date(tokens.expiry);
if (expiry > date) {
return tokens.access_token;
} else {
try {
let res = await axios({
url: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify({
client_id: process.env.MAIL_CLIENT_ID,
scope: process.env.MAIL_SCOPE,
refresh_token: tokens.refresh_token,
redirect_uri: process.env.MAIL_REDIRECT_URI,
grant_type: "refresh_token",
client_secret: process.env.MAIL_CLIENT_SECRET,
}),
});
let expiresAt = new Date(Date.now() + res.data.expires_in * 1000);
await mailModel.findByIdAndUpdate(tokens._id, {
expiry: expiresAt,
refresh_token: res.data.refresh_token,
access_token: res.data.access_token,
});
return res.data.access_token;
} catch (err) {
throw new Error("error fetching tokens");
}
}
}
}

View File

@@ -18,6 +18,7 @@ import { notificationSchemas } from "./notification/notification.schema";
import { noteSchemas } from "./note/note.schema";
import { webAuthnRoutes } from "./webauthn/webauthn.route";
import { configSchemas } from "./config/config.schema";
import { mailSchemas } from "./mailProxy/mailProxy.schema";
const app = fastify({ logger: true, trustProxy: true });
@@ -49,6 +50,7 @@ for (const schema of [
...notificationSchemas,
...noteSchemas,
...configSchemas,
...mailSchemas,
]) {
app.addSchema(schema);
}

View File

@@ -23,4 +23,5 @@ export type Claim =
| "notification:read"
| "notification:write"
| "config:read"
| "config:write";
| "config:write"
| "mail:all";

View File

@@ -28,6 +28,7 @@ export const rules: Record<
"notification:write",
"config:read",
"config:write",
"mail:all",
],
hiddenFields: {
orgs: ["__v"],

View File

@@ -154,7 +154,7 @@ export async function webAuthnRoutes(fastify: FastifyInstance) {
{
schema: {
body: {
type: "string",
type: "object",
properties: {
email: { type: "string" },
},