Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
kayra1 committed Oct 16, 2024
1 parent 3a61285 commit 4ccc7b2
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 11 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ $(BUILD_FOLDER)/fetch-repo:

$(BUILD_FOLDER)/$(NMS_ARTIFACT_NAME): $(NMS_FILES)
@npm install && npm run build
rm -rf $@
mv out $@

$(ARTIFACT_FOLDER)/$(WEBCONSOLE_ARTIFACT_NAME): build/fetch-repo $(WEBCONSOLE_FILES) build/$(NMS_ARTIFACT_NAME)
Expand Down
4 changes: 4 additions & 0 deletions app/(nms)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import Navigation from "@/components/Navigation";
import PageContent from "@/components/PageContent";
import Loader from "@/components/Loader";
import { useAuth } from "@/utils/auth";
import { useRouter } from "next/navigation";

const inter = Inter({ subsets: ["latin"] });
const queryClient = new QueryClient();
Expand All @@ -21,6 +23,8 @@ export default function RootLayout({
const [backendAvailable, setBackendAvailable] = useState<null | boolean>(
null,
);
const router = useRouter()
const auth = useAuth()

useEffect(() => {
const fetchData = async () => {
Expand Down
93 changes: 93 additions & 0 deletions app/(nms)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client"

import { getStatus, login } from "@/utils/queries"
import { useMutation, useQuery } from "@tanstack/react-query"
import { useState, ChangeEvent } from "react"
import { useCookies } from "react-cookie"
import { useRouter } from "next/navigation"
import { useAuth } from "@/utils/auth"
import { statusResponse } from "@/components/types"
import { Input, PasswordToggle, Button, Form, Notification, LoginPageLayout } from "@canonical/react-components";


export default function LoginPage() {
const router = useRouter()
const auth = useAuth()
const [cookies, setCookie, removeCookie] = useCookies(['user_token']);
const statusQuery = useQuery<statusResponse, Error>({
queryKey: ['status'],
queryFn: getStatus,
})
if (statusQuery.data && !statusQuery.data.initialized) {
router.push("/initialize")
}
const mutation = useMutation({
mutationFn: login,
onSuccess: (result) => {
setErrorText("")
setCookie('user_token', result?.token, {
sameSite: true,
secure: true,
expires: new Date(new Date().getTime() + 60 * 60 * 1000),
})
router.push('/certificate_requests')
},
onError: (e: Error) => {
setErrorText(e.message)
}
})

const [username, setUsername] = useState<string>("")
const [password, setPassword] = useState<string>("")
const [errorText, setErrorText] = useState<string>("")
const handleUsernameChange = (event: ChangeEvent<HTMLInputElement>) => { setUsername(event.target.value) }
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => { setPassword(event.target.value) }
return (
<>
<LoginPageLayout
logo={{
src: 'https://assets.ubuntu.com/v1/82818827-CoF_white.svg',
title: 'Notary',
url: '#'
}}
title="Log in"
>
<Form>
<Input
id="InputUsername"
label="Username"
type="text"
required={true}
onChange={handleUsernameChange}
/>
<PasswordToggle
id="InputPassword"
label="Password"
required={true}
onChange={handlePasswordChange}
/>
{errorText &&
<Notification
severity="negative"
title="Error"
>
{errorText.split("error: ")}
</Notification>
}
<Button
appearance="positive"
disabled={password.length == 0 || username.length == 0}
onClick={
(event) => {
event.preventDefault();
mutation.mutate({ username: username, password: password })
}
}
>
Log In
</Button>
</Form>
</LoginPageLayout>
</>
)
}
2 changes: 1 addition & 1 deletion app/(nms)/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default function Users() {
defaultSort='"abcd"'
defaultSortDirection="ascending"
headers={[
{ content: "IMSI" },
{ content: "Username" },
{ content: "Actions", className: "u-align--right" },
]}
rows={tableContent}
Expand Down
1 change: 1 addition & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const metadata: Metadata = {
description: "Aether SD-Core NMS",
};


export default function RootLayout({
children,
}: {
Expand Down
6 changes: 1 addition & 5 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function Home() {
const router = useRouter();

useEffect(() => {
router.replace('/network-configuration');
}, [router]);
router.push('/network-configuration')

return null;
}
21 changes: 18 additions & 3 deletions components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ const Navigation: FC = () => {
Subscribers
</a>
</li>
<li className="p-side-navigation__item">
<a
className="p-side-navigation__link"
href={`/users`}
title={`Users`}
aria-current={
pathname === "/users" ? "page" : undefined
}
>
<Icon
className="is-light p-side-navigation__icon"
name="profile"
/>{" "}
Subscribers
</a>
</li>
</ul>
<ul className="p-side-navigation__list sidenav-bottom-ul">
<li className="p-side-navigation__item">
Expand Down Expand Up @@ -151,9 +167,8 @@ const Navigation: FC = () => {
<div className="sidenav-toggle-wrapper">
<Button
appearance="base"
aria-label={`${
isCollapsed ? "expand" : "collapse"
} main navigation`}
aria-label={`${isCollapsed ? "expand" : "collapse"
} main navigation`}
hasIcon
dense
className="sidenav-toggle is-dark u-no-margin l-navigation-collapse-toggle u-hide--small"
Expand Down
4 changes: 4 additions & 0 deletions components/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ export type User = {
export type UserEntry = {
id: number
username: string
}

export type statusResponse = {
initialized: boolean
}
2 changes: 0 additions & 2 deletions utils/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const AuthContext = createContext<AuthContextType>({ user: null, logout: () => {
export const AuthProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
const [cookies, setCookie, removeCookie] = useCookies(['user_token']);
const [user, setUser] = useState<User | null>(null);
const [firstUserCreated, setFirstUserCreated] = useState<boolean>(false)
const router = useRouter();

useEffect(() => {
Expand All @@ -25,7 +24,6 @@ export const AuthProvider = ({ children }: Readonly<{ children: React.ReactNode
let userObject = jwtDecode(cookies.user_token) as User
userObject.authToken = cookies.user_token
setUser(userObject);
setFirstUserCreated(true)
} else {
setUser(null)
router.push('/login');
Expand Down
22 changes: 22 additions & 0 deletions utils/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ export async function changePassword(changePasswordForm: { authToken: string, id
return respData.result
}

export async function getStatus() {
const response = await fetch("/status")
const respData = await response.json();
if (!response.ok) {
throw new Error(`${response.status}: ${HTTPStatus(response.status)}. ${respData.error}`)
}
return respData.result
}

export async function login(userForm: { username: string, password: string }) {
const response = await fetch("/login", {
method: "POST",

body: JSON.stringify({ "username": userForm.username, "password": userForm.password })
})
const respData = await response.json();
if (!response.ok) {
throw new Error(`${response.status}: ${HTTPStatus(response.status)}. ${respData.error}`)
}
return respData.result
}

export const HTTPStatus = (code: number): string => {
const map: { [key: number]: string } = {
400: "Bad Request",
Expand Down

0 comments on commit 4ccc7b2

Please sign in to comment.