From 64045c5660a0bfab55e5f73543649ebe6f43f7cd Mon Sep 17 00:00:00 2001 From: Jack Andrews <45759583+potts99@users.noreply.github.com> Date: Mon, 27 Nov 2023 00:12:54 +0000 Subject: [PATCH 1/5] Next (#184) * basic onboard * remove ant design * checks * internal users + auth * admin check --- apps/api/src/controllers/auth.ts | 79 ++++-- apps/api/src/controllers/clients.ts | 103 ++++--- apps/api/src/controllers/data.ts | 50 +++- apps/api/src/controllers/notebook.ts | 70 +++-- apps/api/src/controllers/queue.ts | 81 +++--- apps/api/src/controllers/ticket.ts | 210 +++++++------- apps/api/src/controllers/todos.ts | 76 +++--- apps/api/src/controllers/webhooks.ts | 60 ++-- apps/api/src/lib/checks.ts | 20 +- apps/api/src/lib/jwt.ts | 4 +- apps/api/src/main.ts | 3 +- .../20231126212553_onboarding/migration.sql | 2 + apps/api/src/prisma/schema.prisma | 42 +-- apps/client/components/ListTodo/index.js | 20 +- apps/client/components/ResetPassword/index.js | 54 ++-- apps/client/components/UserProfile/index.js | 226 ++++++++------- apps/client/layouts/adminLayout.tsx | 11 +- apps/client/layouts/newLayout.tsx | 2 +- apps/client/package.json | 1 - apps/client/pages/_app.tsx | 9 + apps/client/pages/admin/clients/index.tsx | 9 +- apps/client/pages/admin/clients/new.tsx | 4 + apps/client/pages/admin/email-queues/index.js | 14 +- apps/client/pages/admin/email-queues/new.js | 6 +- apps/client/pages/admin/settings.js | 258 ------------------ apps/client/pages/admin/teams.js | 18 +- apps/client/pages/admin/users/internal/new.js | 10 +- apps/client/pages/admin/webhooks.js | 18 +- apps/client/pages/auth/login.tsx | 6 +- apps/client/pages/index.tsx | 30 -- apps/client/pages/onboarding.tsx | 113 ++++++++ apps/client/pages/settings/password.tsx | 63 +++-- apps/client/pages/settings/profile.tsx | 11 +- apps/client/public/discord.svg | 8 + apps/client/public/swagger.json | 21 -- apps/client/public/version.json | 4 - apps/client/store/session.js | 7 +- 37 files changed, 886 insertions(+), 837 deletions(-) create mode 100644 apps/api/src/prisma/migrations/20231126212553_onboarding/migration.sql delete mode 100644 apps/client/pages/admin/settings.js create mode 100644 apps/client/pages/onboarding.tsx create mode 100644 apps/client/public/discord.svg delete mode 100644 apps/client/public/swagger.json delete mode 100644 apps/client/public/version.json diff --git a/apps/api/src/controllers/auth.ts b/apps/api/src/controllers/auth.ts index 118169152..20e62c5af 100644 --- a/apps/api/src/controllers/auth.ts +++ b/apps/api/src/controllers/auth.ts @@ -98,15 +98,15 @@ export function authRoutes(fastify: FastifyInstance) { throw new Error("Password is not valid"); } - var b64string = "TOMATOSOUP"; - var buf = new Buffer(b64string, "base64"); // Ta-da + var b64string = process.env.SECRET; + var buf = new Buffer(b64string!, "base64"); // Ta-da let token = jwt.sign( { data: { id: user!.id }, }, buf, - { expiresIn: "1d" } + { expiresIn: "7d" } ); await prisma.session.create({ @@ -127,6 +127,7 @@ export function authRoutes(fastify: FastifyInstance) { ticket_status_changed: user!.notify_ticket_status_changed, ticket_comments: user!.notify_ticket_comments, ticket_assigned: user!.notify_ticket_assigned, + firstLogin: user!.firstLogin, }; reply.send({ @@ -140,13 +141,18 @@ export function authRoutes(fastify: FastifyInstance) { fastify.delete( "/api/v1/auth/user/:id", async (request: FastifyRequest, reply: FastifyReply) => { - const { id } = request.params as { id: string }; + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - await prisma.user.delete({ - where: { id }, - }); + if (token) { + const { id } = request.params as { id: string }; + + await prisma.user.delete({ + where: { id }, + }); - reply.send({ success: true }); + reply.send({ success: true }); + } } ); @@ -154,11 +160,6 @@ export function authRoutes(fastify: FastifyInstance) { fastify.get( "/api/v1/auth/profile", async (request: FastifyRequest, reply: FastifyReply) => { - // check token - // see if token exists on session table - // if not, return 401 - // if yes, return user data - const bearer = request.headers.authorization!.split(" ")[1]; const token = checkToken(bearer); @@ -210,8 +211,6 @@ export function authRoutes(fastify: FastifyInstance) { }; const bearer = request.headers.authorization!.split(" ")[1]; - - //checks if token is valid and returns valid token const token = checkToken(bearer); if (token) { @@ -245,7 +244,41 @@ export function authRoutes(fastify: FastifyInstance) { fastify.put( "/api/v1/auth/profile", async (request: FastifyRequest, reply: FastifyReply) => { - // + const bearer = request.headers.authorization!.split(" ")[1]; + + //checks if token is valid and returns valid token + const token = checkToken(bearer); + + if (token) { + let session = await prisma.session.findUnique({ + where: { + sessionToken: bearer, + }, + }); + + const { name, email, language } = request.body as { + name: string; + email: string; + language: string; + }; + + let user = await prisma.user.update({ + where: { id: session?.userId }, + data: { + name: name, + email: email, + language: language, + }, + }); + + reply.send({ + user, + }); + } else { + reply.send({ + sucess: false, + }); + } } ); @@ -253,13 +286,17 @@ export function authRoutes(fastify: FastifyInstance) { fastify.get( "/api/v1/auth/user/:id/logout", async (request: FastifyRequest, reply: FastifyReply) => { - const { id } = request.params as { id: string }; + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + if (token) { + const { id } = request.params as { id: string }; - await prisma.session.deleteMany({ - where: { userId: id }, - }); + await prisma.session.deleteMany({ + where: { userId: id }, + }); - reply.send({ success: true }); + reply.send({ success: true }); + } } ); } diff --git a/apps/api/src/controllers/clients.ts b/apps/api/src/controllers/clients.ts index fa1868491..c3a9b63a5 100644 --- a/apps/api/src/controllers/clients.ts +++ b/apps/api/src/controllers/clients.ts @@ -1,4 +1,5 @@ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; +import { checkToken } from "../lib/jwt"; import { prisma } from "../prisma"; export function clientRoutes(fastify: FastifyInstance) { @@ -7,20 +8,25 @@ export function clientRoutes(fastify: FastifyInstance) { "/api/v1/client/create", async (request: FastifyRequest, reply: FastifyReply) => { - const { name, email, number, contactName }: any = request.body; - - await prisma.client.create({ - data: { - name, - contactName, - email, - number: String(number), - }, - }); - - reply.send({ - success: true, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { name, email, number, contactName }: any = request.body; + + await prisma.client.create({ + data: { + name, + contactName, + email, + number: String(number), + }, + }); + + reply.send({ + success: true, + }); + } } ); @@ -29,21 +35,26 @@ export function clientRoutes(fastify: FastifyInstance) { "/api/v1/client/update", async (request: FastifyRequest, reply: FastifyReply) => { - const { name, email, number, contactName, id }: any = request.body; - - await prisma.client.update({ - where: { id: id }, - data: { - name, - contactName, - email, - number: String(number), - }, - }); - - reply.send({ - success: true, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { name, email, number, contactName, id }: any = request.body; + + await prisma.client.update({ + where: { id: id }, + data: { + name, + contactName, + email, + number: String(number), + }, + }); + + reply.send({ + success: true, + }); + } } ); @@ -52,12 +63,17 @@ export function clientRoutes(fastify: FastifyInstance) { "/api/v1/clients/all", async (request: FastifyRequest, reply: FastifyReply) => { - const clients = await prisma.client.findMany({}); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - reply.send({ - success: true, - clients: clients, - }); + if (token) { + const clients = await prisma.client.findMany({}); + + reply.send({ + success: true, + clients: clients, + }); + } } ); @@ -66,15 +82,20 @@ export function clientRoutes(fastify: FastifyInstance) { "/api/v1/clients/:id/delete-client", async (request: FastifyRequest, reply: FastifyReply) => { - const { id }: any = request.params; + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { id }: any = request.params; - await prisma.client.delete({ - where: { id: id }, - }); + await prisma.client.delete({ + where: { id: id }, + }); - reply.send({ - success: true, - }); + reply.send({ + success: true, + }); + } } ); } diff --git a/apps/api/src/controllers/data.ts b/apps/api/src/controllers/data.ts index a8d3ba361..e3c6e69b2 100644 --- a/apps/api/src/controllers/data.ts +++ b/apps/api/src/controllers/data.ts @@ -1,4 +1,5 @@ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; +import { checkToken } from "../lib/jwt"; import { prisma } from "../prisma"; export function dataRoutes(fastify: FastifyInstance) { @@ -7,8 +8,14 @@ export function dataRoutes(fastify: FastifyInstance) { "/api/v1/data/tickets/all", async (request: FastifyRequest, reply: FastifyReply) => { - // check jwt is valid - // check user is admin + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const result = await prisma.ticket.count(); + + reply.send({ count: result }); + } } ); @@ -17,11 +24,16 @@ export function dataRoutes(fastify: FastifyInstance) { "/api/v1/data/tickets/completed", async (request: FastifyRequest, reply: FastifyReply) => { - const result = await prisma.ticket.count({ - where: { isComplete: true }, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const result = await prisma.ticket.count({ + where: { isComplete: true }, + }); - reply.send({ count: result }); + reply.send({ count: result }); + } } ); @@ -30,11 +42,16 @@ export function dataRoutes(fastify: FastifyInstance) { "/api/v1/data/tickets/open", async (request: FastifyRequest, reply: FastifyReply) => { - const result = await prisma.ticket.count({ - where: { isComplete: false }, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - reply.send({ count: result }); + if (token) { + const result = await prisma.ticket.count({ + where: { isComplete: false }, + }); + + reply.send({ count: result }); + } } ); @@ -43,11 +60,16 @@ export function dataRoutes(fastify: FastifyInstance) { "/api/v1/data/tickets/unassigned", async (request: FastifyRequest, reply: FastifyReply) => { - const result = await prisma.ticket.count({ - where: { userId: null }, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const result = await prisma.ticket.count({ + where: { userId: null }, + }); - reply.send({ count: result }); + reply.send({ count: result }); + } } ); } diff --git a/apps/api/src/controllers/notebook.ts b/apps/api/src/controllers/notebook.ts index 13f601ab9..0452452a4 100644 --- a/apps/api/src/controllers/notebook.ts +++ b/apps/api/src/controllers/notebook.ts @@ -17,19 +17,21 @@ export function notebookRoutes(fastify: FastifyInstance) { if (!title) { return reply.status(422).send({ error: "Please add a title" }); } else { - const user = await checkSession(bearer); + if (token) { + const user = await checkSession(bearer); - const data = await prisma.notes.create({ - data: { - title, - note: content, - userId: user!.id, - }, - }); + const data = await prisma.notes.create({ + data: { + title, + note: content, + userId: user!.id, + }, + }); - const { id } = data; + const { id } = data; - reply.status(200).send({ success: true, id }); + reply.status(200).send({ success: true, id }); + } } } ); @@ -41,13 +43,16 @@ export function notebookRoutes(fastify: FastifyInstance) { async (request: FastifyRequest, reply: FastifyReply) => { const bearer = request.headers.authorization!.split(" ")[1]; const token = checkToken(bearer); - const user = await checkSession(bearer); - const notebooks = await prisma.notes.findMany({ - where: { userId: user!.id }, - }); + if (token) { + const user = await checkSession(bearer); + + const notebooks = await prisma.notes.findMany({ + where: { userId: user!.id }, + }); - reply.status(200).send({ success: true, notebooks: notebooks }); + reply.status(200).send({ success: true, notebooks: notebooks }); + } } ); @@ -58,19 +63,40 @@ export function notebookRoutes(fastify: FastifyInstance) { async (request: FastifyRequest, reply: FastifyReply) => { const bearer = request.headers.authorization!.split(" ")[1]; const token = checkToken(bearer); - const user = await checkSession(bearer); - const { id }: any = request.params; + if (token) { + const user = await checkSession(bearer); + + const { id }: any = request.params; - const note = await prisma.notes.findUnique({ - where: { userId: user!.id, id: id }, - }); + const note = await prisma.notes.findUnique({ + where: { userId: user!.id, id: id }, + }); - reply.status(200).send({ success: true, note }); + reply.status(200).send({ success: true, note }); + } } ); // Delete an entry + fastify.delete( + "/api/v1/notebooks/note/:id/delete", + + async (request: FastifyRequest, reply: FastifyReply) => { + const { id }: any = request.params; + + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + await prisma.notes.delete({ + where: { id: id }, + }); + + reply.status(200).send({ success: true }); + } + } + ); // Update an entry fastify.put( @@ -84,7 +110,7 @@ export function notebookRoutes(fastify: FastifyInstance) { const token = checkToken(bearer); if (token) { - const user = await checkSession(bearer); + await checkSession(bearer); await prisma.notes.update({ where: { id: id }, diff --git a/apps/api/src/controllers/queue.ts b/apps/api/src/controllers/queue.ts index 12171df17..ae7dcdaa7 100644 --- a/apps/api/src/controllers/queue.ts +++ b/apps/api/src/controllers/queue.ts @@ -1,4 +1,5 @@ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; +import { checkToken } from "../lib/jwt"; import { prisma } from "../prisma"; export function emailQueueRoutes(fastify: FastifyInstance) { @@ -7,21 +8,26 @@ export function emailQueueRoutes(fastify: FastifyInstance) { "/api/v1/email-queue/create", async (request: FastifyRequest, reply: FastifyReply) => { - const { name, username, password, hostname, tls }: any = request.body; - - await prisma.emailQueue.create({ - data: { - name, - username, - password, - hostname, - tls, - }, - }); - - reply.send({ - success: true, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { name, username, password, hostname, tls }: any = request.body; + + await prisma.emailQueue.create({ + data: { + name, + username, + password, + hostname, + tls, + }, + }); + + reply.send({ + success: true, + }); + } } ); @@ -31,14 +37,17 @@ export function emailQueueRoutes(fastify: FastifyInstance) { "/api/v1/email-queues/all", async (request: FastifyRequest, reply: FastifyReply) => { - // check jwt is valid - // check user is admin - const queues = await prisma.emailQueue.findMany({}); - - reply.send({ - success: true, - queues: queues, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const queues = await prisma.emailQueue.findMany({}); + + reply.send({ + success: true, + queues: queues, + }); + } } ); @@ -47,16 +56,22 @@ export function emailQueueRoutes(fastify: FastifyInstance) { "/api/v1/email-queue/delete", async (request: FastifyRequest, reply: FastifyReply) => { - const { id }: any = request.body; - const queues = await prisma.emailQueue.delete({ - where: { - id: id, - }, - }); - - reply.send({ - success: true, - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { id }: any = request.params; + + await prisma.emailQueue.delete({ + where: { + id: id, + }, + }); + + reply.send({ + success: true, + }); + } } ); } diff --git a/apps/api/src/controllers/ticket.ts b/apps/api/src/controllers/ticket.ts index f1aeff869..febb19d03 100644 --- a/apps/api/src/controllers/ticket.ts +++ b/apps/api/src/controllers/ticket.ts @@ -22,8 +22,6 @@ export function ticketRoutes(fastify: FastifyInstance) { type, }: any = request.body; - console.log(request.body); - const ticket: any = await prisma.ticket.create({ data: { name, @@ -146,7 +144,6 @@ export function ticketRoutes(fastify: FastifyInstance) { // Get all tickets fastify.get( "/api/v1/tickets/open", - async (request: FastifyRequest, reply: FastifyReply) => { const bearer = request.headers.authorization!.split(" ")[1]; const token = checkToken(bearer); @@ -300,68 +297,73 @@ export function ticketRoutes(fastify: FastifyInstance) { "/api/v1/ticket/transfer", async (request: FastifyRequest, reply: FastifyReply) => { + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + const { user, id }: any = request.body; - await prisma.user.update({ - where: { id: user }, - data: { - tickets: { - connect: { - id: id, + if (token) { + await prisma.user.update({ + where: { id: user }, + data: { + tickets: { + connect: { + id: id, + }, }, }, - }, - }); + }); - reply.send({ - success: true, - }); + reply.send({ + success: true, + }); + } } ); // Link a ticket to another ticket - fastify.post( - "/api/v1/ticket/link", - - async (request: FastifyRequest, reply: FastifyReply) => { - const { ticket, id }: any = request.body; - - const prev: any = await prisma.ticket.findUnique({ - where: { - id: id, - }, - }); - - const ids = []; - - if (prev.length !== undefined && prev.linked.length > 0) { - ids.push(...prev.linked); - } - - ids.push({ - id: ticket.id, - title: ticket.title, - }); - - const data = await prisma.ticket.update({ - where: { - id: id, - }, - data: { - linked: { - ...ids, - }, - }, - }); - } - ); + // fastify.post( + // "/api/v1/ticket/link", + + // async (request: FastifyRequest, reply: FastifyReply) => { + // const { ticket, id }: any = request.body; + + // const prev: any = await prisma.ticket.findUnique({ + // where: { + // id: id, + // }, + // }); + + // const ids = []; + + // if (prev.length !== undefined && prev.linked.length > 0) { + // ids.push(...prev.linked); + // } + + // ids.push({ + // id: ticket.id, + // title: ticket.title, + // }); + + // const data = await prisma.ticket.update({ + // where: { + // id: id, + // }, + // data: { + // linked: { + // ...ids, + // }, + // }, + // }); + // } + // ); // Unlink a ticket from another ticket - fastify.post( - "/api/v1/ticket/unlink", + // fastify.post( + // "/api/v1/ticket/unlink", - async (request: FastifyRequest, reply: FastifyReply) => {} - ); + // async (request: FastifyRequest, reply: FastifyReply) => {} + // ); // Comment on a ticket fastify.post( @@ -397,44 +399,49 @@ export function ticketRoutes(fastify: FastifyInstance) { "/api/v1/ticket/status/update", async (request: FastifyRequest, reply: FastifyReply) => { - const { status, id }: any = request.body; - - const ticket: any = await prisma.ticket - .update({ - where: { id: id }, - data: { - isComplete: status, - }, - }) - .then(async (ticket) => { - // await sendTicketStatus(ticket); - }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - const webhook = await prisma.webhooks.findMany({ - where: { - type: "ticket_status_changed", - }, - }); + if (token) { + const { status, id }: any = request.body; - for (let i = 0; i < webhook.length; i++) { - if (webhook[i].active === true) { - const s = status ? "Completed" : "Outstanding"; - await axios.post(`${webhook[i].url}`, { - method: "POST", - headers: { - "Content-Type": "application/json", + const ticket: any = await prisma.ticket + .update({ + where: { id: id }, + data: { + isComplete: status, }, - body: JSON.stringify({ - data: `Ticket ${ticket.id} created by ${ticket.email}, has had it's status changed to ${s}`, - }), - redirect: "follow", + }) + .then(async (ticket) => { + // await sendTicketStatus(ticket); }); + + const webhook = await prisma.webhooks.findMany({ + where: { + type: "ticket_status_changed", + }, + }); + + for (let i = 0; i < webhook.length; i++) { + if (webhook[i].active === true) { + const s = status ? "Completed" : "Outstanding"; + await axios.post(`${webhook[i].url}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + data: `Ticket ${ticket.id} created by ${ticket.email}, has had it's status changed to ${s}`, + }), + redirect: "follow", + }); + } } - } - reply.send({ - success: true, - }); + reply.send({ + success: true, + }); + } } ); @@ -443,22 +450,27 @@ export function ticketRoutes(fastify: FastifyInstance) { "/api/v1/ticket/status/hide", async (request: FastifyRequest, reply: FastifyReply) => { - const { hidden, id }: any = request.body; + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - await prisma.ticket - .update({ - where: { id: id }, - data: { - hidden: hidden, - }, - }) - .then(async (ticket) => { - // await sendTicketStatus(ticket); - }); + if (token) { + const { hidden, id }: any = request.body; - reply.send({ - success: true, - }); + await prisma.ticket + .update({ + where: { id: id }, + data: { + hidden: hidden, + }, + }) + .then(async (ticket) => { + // await sendTicketStatus(ticket); + }); + + reply.send({ + success: true, + }); + } } ); diff --git a/apps/api/src/controllers/todos.ts b/apps/api/src/controllers/todos.ts index 9083679d5..10f859a9c 100644 --- a/apps/api/src/controllers/todos.ts +++ b/apps/api/src/controllers/todos.ts @@ -30,20 +30,22 @@ export function todoRoutes(fastify: FastifyInstance) { console.log("No text found!"); reply.status(400).send({ success: false, message: "No text found!" }); } else { - const user = await checkSession(bearer); - - if (user) { - await prisma.todos.create({ - data: { - text: todo, - userId: user!.id, - }, - }); - reply.send({ success: true, message: "Todo created!" }); - } else { - reply - .status(400) - .send({ success: false, message: "User not found!" }); + if (token) { + const user = await checkSession(bearer); + + if (user) { + await prisma.todos.create({ + data: { + text: todo, + userId: user!.id, + }, + }); + reply.send({ success: true, message: "Todo created!" }); + } else { + reply + .status(400) + .send({ success: false, message: "User not found!" }); + } } } } @@ -55,11 +57,16 @@ export function todoRoutes(fastify: FastifyInstance) { "/api/v1/todos/all", async (request: FastifyRequest, reply: FastifyReply) => { - const todos = await prisma.todos.findMany({}); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const todos = await prisma.todos.findMany({}); - reply.send({ - todos: todos, - }); + reply.send({ + todos: todos, + }); + } } ); @@ -68,24 +75,29 @@ export function todoRoutes(fastify: FastifyInstance) { "/api/v1/todo/:id/delete", async (request: FastifyRequest, reply: FastifyReply) => { - const { id } = request.params as { id: string }; + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); - const todo = await doesTodoExist(id); + if (token) { + const { id } = request.params as { id: string }; - if (!todo) { - return reply.status(404).send({ - success: false, - error: "Todo not found.", - }); - } + const todo = await doesTodoExist(id); + + if (!todo) { + return reply.status(404).send({ + success: false, + error: "Todo not found.", + }); + } - await prisma.todos.delete({ - where: { - id: id, - }, - }); + await prisma.todos.delete({ + where: { + id: id, + }, + }); - reply.status(201).send({ success: true, message: "Todo deleted" }); + reply.status(201).send({ success: true, message: "Todo deleted" }); + } } ); } diff --git a/apps/api/src/controllers/webhooks.ts b/apps/api/src/controllers/webhooks.ts index 5cecfecb6..0da80efc0 100644 --- a/apps/api/src/controllers/webhooks.ts +++ b/apps/api/src/controllers/webhooks.ts @@ -1,4 +1,5 @@ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; +import { checkToken } from "../lib/jwt"; import { prisma } from "../prisma"; export function webhookRoutes(fastify: FastifyInstance) { @@ -7,18 +8,23 @@ export function webhookRoutes(fastify: FastifyInstance) { "/api/v1/webhook/create", async (request: FastifyRequest, reply: FastifyReply) => { - const { name, url, type, active, secret }: any = request.body; - await prisma.webhooks.create({ - data: { - name, - url, - type, - active, - secret, - createdBy: "375f7799-5485-40ff-ba8f-0a28e0855ecf", - }, - }); - reply.status(200).send({ message: "Hook created!", success: true }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { name, url, type, active, secret }: any = request.body; + await prisma.webhooks.create({ + data: { + name, + url, + type, + active, + secret, + createdBy: "375f7799-5485-40ff-ba8f-0a28e0855ecf", + }, + }); + reply.status(200).send({ message: "Hook created!", success: true }); + } } ); @@ -27,9 +33,14 @@ export function webhookRoutes(fastify: FastifyInstance) { "/api/v1/webhooks/all", async (request: FastifyRequest, reply: FastifyReply) => { - const webhooks = await prisma.webhooks.findMany({}); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const webhooks = await prisma.webhooks.findMany({}); - reply.status(200).send({ webhooks: webhooks, success: true }); + reply.status(200).send({ webhooks: webhooks, success: true }); + } } ); @@ -39,14 +50,19 @@ export function webhookRoutes(fastify: FastifyInstance) { "/api/v1/admin/webhook/:id/delete", async (request: FastifyRequest, reply: FastifyReply) => { - const { id }: any = request.params; - await prisma.webhooks.delete({ - where: { - id: id, - }, - }); - - reply.status(200).send({ success: true }); + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + const { id }: any = request.params; + await prisma.webhooks.delete({ + where: { + id: id, + }, + }); + + reply.status(200).send({ success: true }); + } } ); } diff --git a/apps/api/src/lib/checks.ts b/apps/api/src/lib/checks.ts index 36e2314c9..985e707da 100644 --- a/apps/api/src/lib/checks.ts +++ b/apps/api/src/lib/checks.ts @@ -1 +1,19 @@ -// is Admin +import { FastifyReply, FastifyRequest } from "fastify"; +import { checkToken } from "./jwt"; + +// Check valid token +export const authenticateUser = ( + request: FastifyRequest, + reply: FastifyReply, + done: any +) => { + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (!token) { + return reply.code(401).send({ error: "Unauthorized" }); + } + + // User is authenticated, continue to the route handler + done(); +}; diff --git a/apps/api/src/lib/jwt.ts b/apps/api/src/lib/jwt.ts index 1c2ac987e..2fa1779b2 100644 --- a/apps/api/src/lib/jwt.ts +++ b/apps/api/src/lib/jwt.ts @@ -3,8 +3,8 @@ import jwt from "jsonwebtoken"; export function checkToken(token: string) { const bearer = token; - var b64string = "TOMATOSOUP"; - var buf = new Buffer(b64string, "base64"); // Ta-da + var b64string = process.env.SECRET; + var buf = new Buffer(b64string!, "base64"); // Ta-da const verified = jwt.verify(bearer, buf); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index bc4861bc9..4405a4e45 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -70,8 +70,7 @@ server.register(import("@fastify/rate-limit"), { registerRoutes(server); server.get("/", async function (request, response) { - const session = await prisma.session.findMany(); - response.send({ session }); + response.send({ healthy: true }); }); const start = async () => { diff --git a/apps/api/src/prisma/migrations/20231126212553_onboarding/migration.sql b/apps/api/src/prisma/migrations/20231126212553_onboarding/migration.sql new file mode 100644 index 000000000..53c41c469 --- /dev/null +++ b/apps/api/src/prisma/migrations/20231126212553_onboarding/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "User" ADD COLUMN "firstLogin" BOOLEAN NOT NULL DEFAULT true; diff --git a/apps/api/src/prisma/schema.prisma b/apps/api/src/prisma/schema.prisma index fa54db79e..9e1226fc5 100644 --- a/apps/api/src/prisma/schema.prisma +++ b/apps/api/src/prisma/schema.prisma @@ -46,30 +46,32 @@ model Session { } model User { - id String @id @default(uuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) name String password String? - email String @unique + email String @unique image String? emailVerified Boolean? - isAdmin Boolean @default(false) - language String? @default("en") - notify_ticket_created Boolean @default(true) - notify_ticket_status_changed Boolean @default(true) - notify_ticket_comments Boolean @default(true) - notify_ticket_assigned Boolean @default(true) - todos Todos[] - tickets Ticket[] - file UserFile[] - notes Notes[] - Team Team? @relation(fields: [teamId], references: [id]) - teamId String? - Comment Comment[] - Account Account[] - Session Session[] - TimeTracking TimeTracking[] + isAdmin Boolean @default(false) + language String? @default("en") + notify_ticket_created Boolean @default(true) + notify_ticket_status_changed Boolean @default(true) + notify_ticket_comments Boolean @default(true) + notify_ticket_assigned Boolean @default(true) + firstLogin Boolean @default(true) + + todos Todos[] + tickets Ticket[] + file UserFile[] + notes Notes[] + Team Team? @relation(fields: [teamId], references: [id]) + teamId String? + Comment Comment[] + Account Account[] + Session Session[] + TimeTracking TimeTracking[] } model VerificationToken { diff --git a/apps/client/components/ListTodo/index.js b/apps/client/components/ListTodo/index.js index 7f26f8b39..c203f9b4b 100644 --- a/apps/client/components/ListTodo/index.js +++ b/apps/client/components/ListTodo/index.js @@ -1,16 +1,18 @@ import { TrashIcon } from "@heroicons/react/20/solid"; -import { Pagination } from "antd"; import { getCookie } from "cookies-next"; import { useState } from "react"; import { useQuery } from "react-query"; async function getTodos(token) { - const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/todos/all`, { - method: "GET", - headers: { - Authorization: `Bearer ${token}`, - }, - }); + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/api/v1/todos/all`, + { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); return res.json(); } @@ -125,13 +127,13 @@ export default function ListTodo() {
None Found
)} -- This information will be displayed publicly so be careful what you - share. -
-+ This information will be displayed publicly so be careful what you + share. +
++ Welcome to Peppermint! A fully open sourced ticket management + system. +
+