Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete member using Rest Api #335

Merged
merged 3 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion docs/docs/Rest Api/_source/networkMember.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ paths:
properties:
message:
type: string

/network/{networkId}/member/{memberId}:
post:
summary: Modify a network member
Expand Down Expand Up @@ -133,6 +132,59 @@ paths:
properties:
error:
type: string
500:
description: Internal server error
content:
application/json:
schema:
type: object
properties:
message:
type: string
delete:
summary: Delete a network member
# description: Delete a network member
operationId: deleteNetworkMember
parameters:
- in: path
name: networkId
required: true
schema:
type: string
description: ID of the network
- in: path
name: memberId
required: true
schema:
type: string
description: ID of the member
responses:
200:
description: Network Response
content:
application/json:
schema:
$ref: '../_schema/NetworkResponse.yml#/NetworkResponse'
example:
$ref: '../_example/NetworkExample.yml#/NetworkArrayExample'
401:
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
error:
type: string
429:
description: Rate limit exceeded
content:
application/json:
schema:
type: object
properties:
error:
type: string
500:
description: Internal server error
content:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ describe("Update Network Members", () => {
);
});

it("should allow only POST method", async () => {
const methods = ["GET", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
it("should allow only POST and DELETE method", async () => {
const methods = ["GET", "PUT", "PATCH", "OPTIONS", "HEAD"];
const req = {} as NextApiRequest;
const res = createMockRes();

Expand Down
93 changes: 91 additions & 2 deletions src/pages/api/v1/network/[id]/member/[memberId]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ export default async function apiNetworkUpdateMembersHandler(
// create a switch based on the HTTP method
switch (req.method) {
case "POST":
await POST_networkUpdateMembers(req, res);
await POST_updateNetworkMember(req, res);
break;
case "DELETE":
await POST_deleteNetworkMember(req, res);
break;
default:
// Method Not Allowed
Expand All @@ -52,7 +55,14 @@ export default async function apiNetworkUpdateMembersHandler(
}
}

const POST_networkUpdateMembers = async (req: NextApiRequest, res: NextApiResponse) => {
/**
* Handles the POST request to update network members.
*
* @param req - The NextApiRequest object.
* @param res - The NextApiResponse object.
* @returns A JSON response indicating the success or failure of the update operation.
*/
const POST_updateNetworkMember = async (req: NextApiRequest, res: NextApiResponse) => {
const apiKey = req.headers["x-ztnet-auth"] as string;
const networkId = req.query?.id as string;
const memberId = req.query?.memberId as string;
Expand Down Expand Up @@ -199,3 +209,82 @@ const POST_networkUpdateMembers = async (req: NextApiRequest, res: NextApiRespon
return res.status(500).json({ message: "Internal server error" });
}
};

/**
* Handles the HTTP DELETE request to delete a member from a network.
*
* @param req - The NextApiRequest object representing the incoming request.
* @param res - The NextApiResponse object representing the outgoing response.
* @returns A JSON response indicating the success or failure of the operation.
*/
const POST_deleteNetworkMember = async (req: NextApiRequest, res: NextApiResponse) => {
const apiKey = req.headers["x-ztnet-auth"] as string;
const networkId = req.query?.id as string;
const memberId = req.query?.memberId as string;

let decryptedData: { userId: string; name?: string };
try {
decryptedData = await decryptAndVerifyToken({ apiKey });
} catch (error) {
return res.status(401).json({ error: error.message });
}

// Check if the networkId exists
if (!networkId) {
return res.status(400).json({ error: "Network ID is required" });
}

// Check if the networkId exists
if (!memberId) {
return res.status(400).json({ error: "Member ID is required" });
}

// assemble the context object
const ctx = {
session: {
user: {
id: decryptedData.userId as string,
},
},
prisma,
wss: null,
};

try {
// make sure the member is valid
const network = await prisma.network.findUnique({
where: { nwid: networkId, authorId: decryptedData.userId },
include: {
networkMembers: {
where: { id: memberId },
},
},
});

if (!network?.networkMembers || network.networkMembers.length === 0) {
return res
.status(401)
.json({ error: "Member or Network not found or access denied." });
}

// @ts-expect-error
const caller = appRouter.createCaller(ctx);
const networkAndMembers = await caller.networkMember.stash({
nwid: networkId,
id: memberId,
});

return res.status(200).json(networkAndMembers);
} catch (cause) {
if (cause instanceof TRPCError) {
const httpCode = getHTTPStatusCodeFromError(cause);
try {
const parsedErrors = JSON.parse(cause.message);
return res.status(httpCode).json({ cause: parsedErrors });
} catch (_error) {
return res.status(httpCode).json({ error: cause.message });
}
}
return res.status(500).json({ message: "Internal server error" });
}
};
24 changes: 11 additions & 13 deletions src/server/api/routers/memberRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export const networkMemberRouter = createTRPCRouter({
throwError(error.message);
}

if (input.central) return updatedMember;
return updatedMember;
}),
Tags: protectedProcedure
.input(
Expand Down Expand Up @@ -466,18 +466,24 @@ export const networkMemberRouter = createTRPCRouter({
const caller = networkMemberRouter.createCaller(ctx);
//user needs to be de-authorized before deleted.
// adding try catch to prevent error if user is not part of the network but still in the database.
let response;
try {
await caller.Update({
response = await caller.Update({
memberId: input.id,
nwid: input.nwid,
updateParams: { authorized: false, ipAssignments: [] },
updateParams: {
authorized: false,
ipAssignments: [],
tags: [],
capabilities: [],
},
});
} catch (error) {
console.error(error);
}

// Set member with deleted status in database.
const memberUpdate = await ctx.prisma.network
await ctx.prisma.network
.update({
where: {
nwid: input.nwid,
Expand All @@ -492,14 +498,6 @@ export const networkMemberRouter = createTRPCRouter({
},
},
},
include: {
networkMembers: {
where: {
id: input.id,
deleted: false,
},
},
},
})
// biome-ignore lint/suspicious/noConsoleLog: <explanation>
.catch((err: string) => console.log(err));
Expand All @@ -520,7 +518,7 @@ export const networkMemberRouter = createTRPCRouter({
throwError(error.message);
}

return memberUpdate;
return response;
}),
delete: protectedProcedure
.input(
Expand Down
Loading