diff --git a/bruno/Newt/Create Newt.bru b/bruno/Newt/Create Newt.bru new file mode 100644 index 00000000..56baf89b --- /dev/null +++ b/bruno/Newt/Create Newt.bru @@ -0,0 +1,11 @@ +meta { + name: Create Newt + type: http + seq: 2 +} + +get { + url: http://localhost:3000/api/v1/newt + body: none + auth: none +} diff --git a/bruno/Newt/Get Token.bru b/bruno/Newt/Get Token.bru new file mode 100644 index 00000000..93d91cc5 --- /dev/null +++ b/bruno/Newt/Get Token.bru @@ -0,0 +1,18 @@ +meta { + name: Get Token + type: http + seq: 1 +} + +get { + url: http://localhost:3000/api/v1/auth/newt/get-token + body: json + auth: none +} + +body:json { + { + "newtId": "o0d4rdxq3stnz7b", + "secret": "sy7l09fnaesd03iwrfp9m3qf0ryn19g0zf3dqieaazb4k7vk" + } +} diff --git a/server/routers/external.ts b/server/routers/external.ts index 74e099bf..ac7d62a2 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -24,6 +24,7 @@ import { import { verifyUserHasAction } from "./auth/verifyUserHasAction"; import { ActionsEnum } from "@server/auth/actions"; import { verifyUserIsOrgOwner } from "./auth/verifyUserIsOrgOwner"; +import { createNewt, getToken } from "./newt"; // Root routes export const unauthenticated = Router(); @@ -353,6 +354,8 @@ authenticated.delete( // role.removeRoleAction // ); +authenticated.put("/newt", createNewt); + // Auth routes export const authRouter = Router(); unauthenticated.use("/auth", authRouter); @@ -367,6 +370,8 @@ authRouter.use( authRouter.put("/signup", auth.signup); authRouter.post("/login", auth.login); authRouter.post("/logout", auth.logout); +authRouter.post('/newt/get-token', getToken); + authRouter.post("/2fa/enable", verifySessionUserMiddleware, auth.verifyTotp); authRouter.post( "/2fa/request", diff --git a/server/routers/newt/createNewt.ts b/server/routers/newt/createNewt.ts new file mode 100644 index 00000000..4a177e01 --- /dev/null +++ b/server/routers/newt/createNewt.ts @@ -0,0 +1,91 @@ +import { NextFunction, Request, Response } from "express"; +import db from "@server/db"; +import { hash } from "@node-rs/argon2"; +import HttpCode from "@server/types/HttpCode"; +import { z } from "zod"; +import { newts } from "@server/db/schema"; +import createHttpError from "http-errors"; +import response from "@server/utils/response"; +import { SqliteError } from "better-sqlite3"; +import moment from "moment"; +import { + generateId, + generateSessionToken, +} from "@server/auth"; +import { createNewtSession } from "@server/auth/newt"; + +export const createNewtBodySchema = z.object({}); + +export type CreateNewtBody = z.infer; + +export type CreateNewtResponse = { + token: string; + newtId: string; + secret: string; +}; + +export async function createNewt( + req: Request, + res: Response, + next: NextFunction +): Promise { + try { + + // generate a newtId and secret + const secret = generateId(48); + const secretHash = await hash(secret, { + memoryCost: 19456, + timeCost: 2, + outputLen: 32, + parallelism: 1, + }); + + const newtId = generateId(15); + + await db.insert(newts).values({ + newtId: newtId, + secretHash, + dateCreated: moment().toISOString(), + }); + + // give the newt their default permissions: + // await db.insert(newtActions).values({ + // newtId: newtId, + // actionId: ActionsEnum.createOrg, + // orgId: null, + // }); + + const token = generateSessionToken(); + await createNewtSession(token, newtId); + + return response(res, { + data: { + newtId, + secret, + token, + }, + success: true, + error: false, + message: "Newt created successfully", + status: HttpCode.OK, + }); + } catch (e) { + if (e instanceof SqliteError && e.code === "SQLITE_CONSTRAINT_UNIQUE") { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + "A newt with that email address already exists" + ) + ); + } else { + console.error(e); + + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "Failed to create newt" + ) + ); + } + } +} diff --git a/server/routers/auth/newtGetToken.ts b/server/routers/newt/getToken.ts similarity index 92% rename from server/routers/auth/newtGetToken.ts rename to server/routers/newt/getToken.ts index 5a959edb..259409c0 100644 --- a/server/routers/auth/newtGetToken.ts +++ b/server/routers/newt/getToken.ts @@ -13,18 +13,17 @@ import { NextFunction, Request, Response } from "express"; import createHttpError from "http-errors"; import { z } from "zod"; import { fromError } from "zod-validation-error"; -import config from "@server/config"; -import { validateNewtSessionToken } from "@server/auth/newt"; +import { createNewtSession, validateNewtSessionToken } from "@server/auth/newt"; export const newtGetTokenBodySchema = z.object({ - newtId: z.string().email(), + newtId: z.string(), secret: z.string(), token: z.string().optional(), }); export type NewtGetTokenBody = z.infer; -export async function newtGetToken( +export async function getToken( req: Request, res: Response, next: NextFunction @@ -93,7 +92,7 @@ export async function newtGetToken( } const resToken = generateSessionToken(); - await createSession(resToken, existingNewt.newtId); + await createNewtSession(resToken, existingNewt.newtId); return response<{ token: string }>(res, { data: { @@ -105,6 +104,7 @@ export async function newtGetToken( status: HttpCode.OK, }); } catch (e) { + console.error(e); return next( createHttpError( HttpCode.INTERNAL_SERVER_ERROR, diff --git a/server/routers/newt/index.ts b/server/routers/newt/index.ts new file mode 100644 index 00000000..19a0d9f0 --- /dev/null +++ b/server/routers/newt/index.ts @@ -0,0 +1,2 @@ +export * from "./createNewt"; +export * from "./getToken"; \ No newline at end of file diff --git a/server/routers/ws.ts b/server/routers/ws.ts index beb2a7a7..ac73ccf4 100644 --- a/server/routers/ws.ts +++ b/server/routers/ws.ts @@ -6,7 +6,6 @@ import { Socket } from 'net'; import { Newt, newts, NewtSession } from '@server/db/schema'; import { eq } from 'drizzle-orm'; import db from '@server/db'; -import { newtGetToken } from './auth'; import { validateNewtSessionToken } from '@server/auth/newt'; // Custom interfaces @@ -61,8 +60,6 @@ router.get('/ws', (req: Request, res: Response) => { res.status(200).send('WebSocket endpoint'); }); -router.get('/ws/auth/newtGetToken', newtGetToken); - // Set up WebSocket server handling const handleWSUpgrade = (server: HttpServer): void => { server.on('upgrade', async (request: WebSocketRequest, socket: Socket, head: Buffer) => { diff --git a/src/app/[orgId]/settings/sites/components/SitesTable.tsx b/src/app/[orgId]/settings/sites/components/SitesTable.tsx index 655d90cc..6634b41f 100644 --- a/src/app/[orgId]/settings/sites/components/SitesTable.tsx +++ b/src/app/[orgId]/settings/sites/components/SitesTable.tsx @@ -13,6 +13,8 @@ import { ArrowUpDown, MoreHorizontal } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import api from "@app/api"; +import { authCookieHeader } from "@app/api/cookies"; +import { AxiosResponse } from "axios"; export type SiteRow = { id: number; @@ -120,7 +122,17 @@ type SitesTableProps = { export default function SitesTable({ sites, orgId }: SitesTableProps) { const router = useRouter(); + const callApi = async () => { + + const res = await api.put>( + `/newt` + ); + console.log(res); + + }; + return ( + <> + + + ); }