Skip to content

Commit

Permalink
Merge pull request #335 from sinamics/delete_member_api
Browse files Browse the repository at this point in the history
Delete member using Rest Api
  • Loading branch information
sinamics authored Mar 11, 2024
2 parents a9cf08a + f898d2a commit aa80725
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 18 deletions.
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

0 comments on commit aa80725

Please sign in to comment.