add notes routes
This commit is contained in:
79
src/note/note.controller.ts
Normal file
79
src/note/note.controller.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { FastifyReply, FastifyRequest } from "fastify";
|
||||
import { createNote, deleteNote, listNotes, updateNote } from "./note.service";
|
||||
import { CreateNoteInput } from "./note.schema";
|
||||
|
||||
export async function createNoteHandler(
|
||||
req: FastifyRequest,
|
||||
res: FastifyReply
|
||||
) {
|
||||
const { resourceId } = req.params as { resourceId: string };
|
||||
const input = req.body as CreateNoteInput;
|
||||
|
||||
try {
|
||||
const note = await createNote(input, resourceId, req.user);
|
||||
return res.code(201).send(note);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function listNotesHandler(req: FastifyRequest, res: FastifyReply) {
|
||||
const { resourceId } = req.params as { resourceId: string };
|
||||
|
||||
try {
|
||||
const notes = await listNotes(resourceId, req.user.tenantId);
|
||||
return res.code(200).send({ notes: notes });
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateNoteHandler(
|
||||
req: FastifyRequest,
|
||||
res: FastifyReply
|
||||
) {
|
||||
const { resourceId, noteId } = req.params as {
|
||||
resourceId: string;
|
||||
noteId: string;
|
||||
};
|
||||
|
||||
const input = req.body as CreateNoteInput;
|
||||
|
||||
try {
|
||||
const updatedNote = await updateNote(
|
||||
input,
|
||||
resourceId,
|
||||
noteId,
|
||||
req.user.tenantId
|
||||
);
|
||||
if (!updateNote) return res.code(404).send({ error: "resource not found" });
|
||||
|
||||
return res.code(200).send(updatedNote);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteNoteHandler(
|
||||
req: FastifyRequest,
|
||||
res: FastifyReply
|
||||
) {
|
||||
const { resourceId, noteId } = req.params as {
|
||||
resourceId: string;
|
||||
noteId: string;
|
||||
};
|
||||
|
||||
try {
|
||||
const deleteResult = await deleteNote(
|
||||
resourceId,
|
||||
noteId,
|
||||
req.user.tenantId
|
||||
);
|
||||
if (deleteResult.deletedCount == 0)
|
||||
return res.code(404).send({ error: "resource not found" });
|
||||
|
||||
return res.code(204).send();
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
79
src/note/note.route.ts
Normal file
79
src/note/note.route.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { FastifyInstance } from "fastify";
|
||||
import {
|
||||
createNoteHandler,
|
||||
listNotesHandler,
|
||||
deleteNoteHandler,
|
||||
updateNoteHandler,
|
||||
} from "./note.controller";
|
||||
import { Claim } from "../utils/claims";
|
||||
|
||||
export async function noteRoutes(
|
||||
fastify: FastifyInstance,
|
||||
claims: { read: Claim; write: Claim; delete: Claim }
|
||||
) {
|
||||
fastify.post(
|
||||
"/:resourceId/notes",
|
||||
{
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
properties: { resourceId: { type: "string" } },
|
||||
},
|
||||
},
|
||||
config: { requiredClaims: [claims.write] },
|
||||
preHandler: [fastify.authorize],
|
||||
},
|
||||
createNoteHandler
|
||||
);
|
||||
|
||||
fastify.get(
|
||||
"/:resourceId/notes",
|
||||
{
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
properties: { resourceId: { type: "string" } },
|
||||
},
|
||||
},
|
||||
config: { requiredClaims: [claims.read] },
|
||||
preHandler: [fastify.authorize],
|
||||
},
|
||||
listNotesHandler
|
||||
);
|
||||
|
||||
fastify.patch(
|
||||
"/:resourceId/notes/:noteId",
|
||||
{
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
properties: {
|
||||
resourceId: { type: "string" },
|
||||
noteId: { type: "string" },
|
||||
},
|
||||
},
|
||||
},
|
||||
config: { requiredClaims: [claims.write] },
|
||||
preHandler: [fastify.authorize],
|
||||
},
|
||||
updateNoteHandler
|
||||
);
|
||||
|
||||
fastify.delete(
|
||||
"/:resourceId/notes/:noteId",
|
||||
{
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
properties: {
|
||||
resourceId: { type: "string" },
|
||||
noteId: { type: "string" },
|
||||
},
|
||||
},
|
||||
},
|
||||
config: { requiredClaims: [claims.write] },
|
||||
preHandler: [fastify.authorize],
|
||||
},
|
||||
deleteNoteHandler
|
||||
);
|
||||
}
|
||||
43
src/note/note.schema.ts
Normal file
43
src/note/note.schema.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { buildJsonSchemas } from "fastify-zod";
|
||||
import mongoose from "mongoose";
|
||||
import { z } from "zod";
|
||||
|
||||
const noteSchema = new mongoose.Schema({
|
||||
tenantId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
pid: {
|
||||
type: String,
|
||||
unique: true,
|
||||
required: true,
|
||||
},
|
||||
resourceId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
createdAt: Date,
|
||||
createdBy: {
|
||||
type: mongoose.Types.ObjectId,
|
||||
ref: "user",
|
||||
},
|
||||
});
|
||||
|
||||
export const noteModel = mongoose.model("note", noteSchema);
|
||||
|
||||
const createNoteInput = z.object({
|
||||
content: z.string(),
|
||||
});
|
||||
|
||||
export type CreateNoteInput = z.infer<typeof createNoteInput>;
|
||||
|
||||
export const { schemas: noteSchemas, $ref: $note } = buildJsonSchemas(
|
||||
{
|
||||
createNoteInput,
|
||||
},
|
||||
{ $id: "note" }
|
||||
);
|
||||
83
src/note/note.service.ts
Normal file
83
src/note/note.service.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { AuthenticatedUser } from "../auth";
|
||||
import { generateId } from "../utils/id";
|
||||
import { CreateNoteInput, noteModel } from "./note.schema";
|
||||
|
||||
export async function createNote(
|
||||
input: CreateNoteInput,
|
||||
resourceId: string,
|
||||
user: AuthenticatedUser
|
||||
) {
|
||||
return await noteModel.create({
|
||||
tenantId: user.tenantId,
|
||||
pid: generateId(),
|
||||
resourceId: resourceId,
|
||||
content: input.content,
|
||||
createdAt: new Date(),
|
||||
createdBy: user.userId,
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateNote(
|
||||
input: CreateNoteInput,
|
||||
resourceId: string,
|
||||
noteId: string,
|
||||
tenantId: string
|
||||
) {
|
||||
return await noteModel.findOneAndUpdate(
|
||||
{
|
||||
$and: [
|
||||
{ pid: noteId },
|
||||
{ tenantId: tenantId },
|
||||
{ resourceId: resourceId },
|
||||
],
|
||||
},
|
||||
{ ...input },
|
||||
{ new: true }
|
||||
);
|
||||
}
|
||||
|
||||
export async function listNotes(resourceId: string, tenantId: string) {
|
||||
return await noteModel.aggregate([
|
||||
{
|
||||
$match: { $and: [{ resourceId: resourceId }, { tenantId: tenantId }] },
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "users",
|
||||
localField: "createdBy",
|
||||
foreignField: "_id",
|
||||
as: "user",
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 1,
|
||||
pid: 1,
|
||||
resourceId: 1,
|
||||
content: 1,
|
||||
createdAt: 1,
|
||||
createdBy: {
|
||||
$let: {
|
||||
vars: { user: { $arrayElemAt: ["$user", 0] } },
|
||||
in: {
|
||||
_id: "$$user._id",
|
||||
pid: "$$user.pid",
|
||||
name: "$$user.name",
|
||||
avatar: "$$user.avatar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
export async function deleteNote(
|
||||
resourceId: string,
|
||||
noteId: string,
|
||||
tenantId: string
|
||||
) {
|
||||
return await noteModel.deleteOne({
|
||||
$and: [{ pid: noteId }, { tenantId: tenantId }, { resourceId: resourceId }],
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,12 @@ import {
|
||||
} from "./permit.controller";
|
||||
import { $permit } from "./permit.schema";
|
||||
import { hideFields } from "../auth";
|
||||
import {
|
||||
createNoteHandler,
|
||||
deleteNoteHandler,
|
||||
listNotesHandler,
|
||||
} from "../note/note.controller";
|
||||
import { noteRoutes } from "../note/note.route";
|
||||
|
||||
export async function permitRoutes(fastify: FastifyInstance) {
|
||||
fastify.post(
|
||||
@@ -111,5 +117,11 @@ export async function permitRoutes(fastify: FastifyInstance) {
|
||||
getUniqueFieldValuesPermit
|
||||
);
|
||||
|
||||
await noteRoutes(fastify, {
|
||||
read: "permit:read",
|
||||
write: "permit:write",
|
||||
delete: "permit:delete",
|
||||
});
|
||||
|
||||
fastify.addHook("onSend", hideFields("permits"));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
updateRtsHandler,
|
||||
} from "./rts.controller";
|
||||
import { hideFields } from "../auth";
|
||||
import { noteRoutes } from "../note/note.route";
|
||||
|
||||
export async function rtsRoutes(fastify: FastifyInstance) {
|
||||
fastify.post(
|
||||
@@ -94,5 +95,11 @@ export async function rtsRoutes(fastify: FastifyInstance) {
|
||||
newFilesHandler
|
||||
);
|
||||
|
||||
await noteRoutes(fastify, {
|
||||
read: "rts:read",
|
||||
write: "rts:write",
|
||||
delete: "rts:delete",
|
||||
});
|
||||
|
||||
fastify.addHook("onSend", hideFields("rts"));
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { authRoutes } from "./auth/auth.route";
|
||||
import { rtsSchemas } from "./rts/rts.schema";
|
||||
import { taskSchemas } from "./task/task.schema";
|
||||
import { notificationSchemas } from "./notification/notification.schema";
|
||||
import { noteSchemas } from "./note/note.schema";
|
||||
|
||||
const app = fastify({ logger: true });
|
||||
|
||||
@@ -43,6 +44,7 @@ for (const schema of [
|
||||
...rtsSchemas,
|
||||
...taskSchemas,
|
||||
...notificationSchemas,
|
||||
...noteSchemas,
|
||||
]) {
|
||||
app.addSchema(schema);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
listTaskHandler,
|
||||
updateTaskHandler,
|
||||
} from "./task.controller";
|
||||
import { noteRoutes } from "../note/note.route";
|
||||
|
||||
export async function taskRoutes(fastify: FastifyInstance) {
|
||||
fastify.post(
|
||||
@@ -79,4 +80,10 @@ export async function taskRoutes(fastify: FastifyInstance) {
|
||||
},
|
||||
deleteTaskHandler
|
||||
);
|
||||
|
||||
await noteRoutes(fastify, {
|
||||
read: "task:read",
|
||||
write: "task:write",
|
||||
delete: "task:delete",
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user