Skip to content

Commit

Permalink
Prevent duplicated subscribers creation
Browse files Browse the repository at this point in the history
Signed-off-by: Patricia Reinoso <patricia.reinoso@canonical.com>
  • Loading branch information
patriciareinoso committed Dec 12, 2023
1 parent 01c4b4a commit 0b2e7ec
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 19 deletions.
38 changes: 26 additions & 12 deletions components/CreateSubscriberModal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";
import React, { useCallback, useEffect } from "react";
import React, { useCallback, useEffect, useState } from "react";
import {
Modal,
ActionButton,
Form,
Input,
Modal,
Notification,
Select,
ActionButton,
} from "@canonical/react-components";
import { createSubscriber } from "@/utils/createSubscriber";
import { getNetworkSlices } from "@/utils/getNetworkSlices";
Expand All @@ -29,6 +30,7 @@ type Props = {

const CreateSubscriberModal = ({ toggleModal }: Props) => {
const queryClient = useQueryClient();
const [apiError, setApiError] = useState<string | null>(null);

const SubscriberSchema = Yup.object().shape({
imsi: Yup.string()
Expand Down Expand Up @@ -63,15 +65,22 @@ const CreateSubscriberModal = ({ toggleModal }: Props) => {
},
validationSchema: SubscriberSchema,
onSubmit: async (values) => {
await createSubscriber({
imsi: values.imsi,
opc: values.opc,
key: values.key,
sequenceNumber: values.sequenceNumber,
deviceGroupName: values.deviceGroup,
});
void queryClient.invalidateQueries({ queryKey: [queryKeys.subscribers] });
toggleModal();
try{
await createSubscriber({
imsi: values.imsi,
opc: values.opc,
key: values.key,
sequenceNumber: values.sequenceNumber,
deviceGroupName: values.deviceGroup,
});
void queryClient.invalidateQueries({ queryKey: [queryKeys.subscribers] });
toggleModal();
} catch (error) {
console.error(error);
setApiError(
(error as Error).message || "An unexpected error occurred.",
);
}
},
});

Expand Down Expand Up @@ -141,6 +150,11 @@ const CreateSubscriberModal = ({ toggleModal }: Props) => {
</>
}
>
{apiError && (
<Notification severity="negative" title="Error">
{apiError}
</Notification>
)}
<Form stacked>
<Input
type="text"
Expand Down
50 changes: 44 additions & 6 deletions pages/api/subscriber/[name].ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,58 @@ const WEBUI_ENDPOINT = process.env.WEBUI_ENDPOINT;

export default async function handleSubscriber(req: NextApiRequest, res: NextApiResponse) {
switch (req.method) {
case "GET":
return handleGET(req, res);
case "POST":
return handlePOST(req, res);
case "DELETE":
return handleDELETE(req, res);
default:
res.setHeader("Allow", ["POST", "DELETE"]);
res.setHeader("Allow", ["GET", "POST", "DELETE"]);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}

function isValidName(name: string): boolean {
return /^[a-zA-Z0-9-_]+$/.test(name);
return /^[a-zA-Z0-9-_]+$/.test(name);
}

async function handleGET(req: NextApiRequest, res: NextApiResponse) {
const { name } = req.query

if (typeof name !== 'string') {
res.status(400).json({ error: "Invalid name provided." });
return;
}

if (!isValidName(name)) {
res.status(400).json({ error: "Invalid name provided." });
return;
}

const url = `${WEBUI_ENDPOINT}/api/subscriber/${name}`;

try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

if (!response.ok) {
throw new Error(`Error getting subscriber. Error code: ${response.status}`);
}

const data = await response.json();
res.status(200).json(data);
} catch (error) {
console.error("Error details:", error);
res.status(500).json({
error: "An error occurred while retrieving the subscriber.",
});
}
}

async function handlePOST(req: NextApiRequest, res: NextApiResponse) {
const { name } = req.query
Expand Down Expand Up @@ -52,7 +90,7 @@ async function handlePOST(req: NextApiRequest, res: NextApiResponse) {
} catch (error) {
console.error("Error details:", error);
res.status(500).json({
error: "An error occurred while creating the subscriber",
error: "An error occurred while creating the subscriber.",
});
}
}
Expand Down Expand Up @@ -84,11 +122,11 @@ async function handleDELETE(req: NextApiRequest, res: NextApiResponse) {
throw new Error(`Error deleting subscriber. Error code: ${response.status}`);
}

res.status(200).json({ message: "Subscriber deleted successfully" });
res.status(200).json({ message: "Subscriber deleted successfully." });
} catch (error) {
console.error("Error details:", error);
res.status(500).json({
error: "An error occurred while deleting the subscriber",
error: "An error occurred while deleting the subscriber.",
});
}
}
21 changes: 20 additions & 1 deletion utils/createSubscriber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ export const createSubscriber = async ({
};

try {
const checkResponse = await fetch(`/api/subscriber/imsi-${imsi}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

const existingSubscriberData = await checkResponse.json();
if (checkResponse.ok && existingSubscriberData["AuthenticationSubscription"]["authenticationMethod"]) {
throw new Error("Subscriber already exists.");
}
else{
console.error(checkResponse);
}

const response = await fetch(`/api/subscriber/imsi-${imsi}`, {
method: "POST",
headers: {
Expand Down Expand Up @@ -73,6 +88,10 @@ export const createSubscriber = async ({
return response.json();
} catch (error) {
console.error(error);
throw new Error("Failed to create the subscriber.");
const details =
error instanceof Error
? error.message
: "Failed to configure the network.";
throw new Error(details);
}
};

0 comments on commit 0b2e7ec

Please sign in to comment.