Skip to content

Commit

Permalink
Merge pull request #249 from ai-cfia/226-as-a-user-i-want-to-be-direc…
Browse files Browse the repository at this point in the history
…ted-to-the-main-page-after-logging-in

Add redirection and logout button to the login functionality
  • Loading branch information
k-allagbe authored Oct 4, 2024
2 parents be49e19 + a1359ef commit 46e7253
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 166 deletions.
217 changes: 146 additions & 71 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@dts-stn/service-canada-design-system": "^1.67.3",
"axios": "^1.7.7",
"deepmerge": "^4.3.1",
"dotenv": "^16.4.5",
"i18next": "^23.11.5",
Expand Down
6 changes: 5 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AlertProvider } from "./Utils/AlertContext";
import { SessionProvider } from "./Utils/SessionContext";
import LabelPage from "./Pages/LabelPage/LabelPage";
import AlertBanner from "./Components/AlertBanner/AlertBanner";
import { isAuthenticated } from "./Utils/Auth/AuthUtil";

function App() {
useEffect(() => {
Expand All @@ -30,7 +31,10 @@ function App() {
</StrictMode>
<Routes>
<Route path="/">
<Route index element={<HomePage />} />
<Route
index
element={isAuthenticated() ? <HomePage /> : <SettingPage />}
/>
<Route path="Settings" element={<SettingPage />} />
<Route path="Saved" element={<SavedListPage />} />
<Route path="Label/:labelId" element={<LabelPage />} />
Expand Down
7 changes: 6 additions & 1 deletion src/Components/SideMenu/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import list from "../../assets/list.svg";
import { SessionContext, SetSessionContext } from "../../Utils/SessionContext";
import Data from "../../Model/Data-Model";
import Inspection from "../../interfaces/Inspection.ts";
import { isAuthenticated } from "../../Utils/Auth/AuthUtil";

function SideMenu() {
const { t } = useTranslation();
Expand Down Expand Up @@ -54,7 +55,11 @@ function SideMenu() {

const goToHome = () => {
retrieveState();
navigate("/");
if (isAuthenticated()) {
navigate("/");
} else {
navigate("/Settings");
}
};

const goToSettings = () => {
Expand Down
21 changes: 18 additions & 3 deletions src/Pages/SettingPage/SettingPage.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@
border-radius: 5px;
}

.settings hr {
width: 100%;
}

/* LoginPage.css */
.login-page {
margin: 20px;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
display: flex;
flex-direction: column;
}

#login,
#uname,
#password {
Expand All @@ -36,6 +50,7 @@
#password label {
width: fit-content;
}

#uname input,
#password input {
width: 20%;
Expand All @@ -49,17 +64,16 @@
#validate-uname {
display: flex;
}

#validate-uname input {
margin: auto 20px auto 0;
width: fit-content;
}

#validate-uname p {
width: 35%;
text-align: left;
}
.settings hr {
width: 100%;
}

.send-uname {
width: fit-content;
Expand All @@ -69,6 +83,7 @@
background-color: #666666 !important;
cursor: not-allowed;
}

.send-uname:disabled:hover {
transform: none !important;
}
222 changes: 134 additions & 88 deletions src/Pages/SettingPage/SettingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,121 +1,167 @@
import { useState } from "react";
import axios from "axios";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import LanguageButton from "../../Components/LanguageButton/LanguageButton";
import { useAlert } from "../../Utils/AlertContext.tsx";
import { useAlert } from "../../Utils/AlertContext";
import {
login as authLogin,
isAuthenticated,
logout,
} from "../../Utils/Auth/AuthUtil";
import "./SettingPage.css";

function SettingPage() {
const SettingsPage = () => {
const navigate = useNavigate();
const { t } = useTranslation();
const { showAlert } = useAlert();
const [uname_validated, setUnameValidated] = useState(false);
const [uname, setUname] = useState("");
const [password, setPassword] = useState("");
const login = () => {
const form = new FormData();
form.append("username", uname);
form.append("password", password);
if (process.env.VITE_APP_ACTIVATE_USING_JSON == "true") {
document.cookie = `auth=${btoa(uname + ":" + password)}`;
showAlert(t("loggedIn"), "confirm");
const [auth, setAuth] = useState(false);
const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
setAuth(isAuthenticated());
}, []);

const finalizeAuth = (messageKey: string) => {
authLogin(uname, password);
showAlert(t(messageKey), "confirm");
setAuth(true);
navigate("/");
};

const login = async () => {
setIsLoading(true);

if (process.env.VITE_APP_ACTIVATE_USING_JSON === "true") {
finalizeAuth("loggedIn");
setIsLoading(false);
return;
}
fetch(process.env.VITE_API_URL + "/login", {
method: "POST",
body: form,
headers: {
Authorization: "Basic " + btoa(uname + ":" + password),
},
})
.then((r) => {
if (r.status !== 200) {
fetch(process.env.VITE_API_URL + "/signup", {
method: "POST",
body: form,
headers: {
Authorization: "Basic " + btoa(uname + ":" + password),
},
})
.then((r) => {
if (r.status !== 201) {
r.json().then((data) => {
showAlert(data.error, "error");
});
} else {
document.cookie = `auth=${btoa(uname + ":" + password)}`;
showAlert(t("loggedIn"), "confirm");
}

console.info("logging in");
axios
.post(
process.env.VITE_API_URL + "/login",
new URLSearchParams({ uname, password }),
{
headers: {
Authorization: "Basic " + btoa(uname + ":" + password),
},
timeout: 5000,
},
)
.then((response) => {
console.log(response);
finalizeAuth("loggedIn");
})
.catch((error) => {
if (error.response) {
console.error("login failed:", error.response);
console.info("signing up");
axios
.post(
`${process.env.VITE_API_URL}/signup`,
new URLSearchParams({
username: uname,
password: password,
}),
{
headers: {
Authorization: "Basic " + btoa(uname + ":" + password),
},
timeout: 5000,
},
)
.then((response) => {
console.log(response);
finalizeAuth("registered");
})
.catch((e) => {
showAlert(e, "error");
.catch((error) => {
console.error("unexpected error during signup", error.message);
showAlert(String(error), "error");
});
} else {
document.cookie = `auth=${btoa(uname + ":" + password)}`;
showAlert(t("registered"), "confirm");
}
console.error("unexpected error during login:", error.message);
showAlert(String(error), "error");
})
.catch((e) => {
showAlert(e, "error");
.finally(() => {
setIsLoading(false);
});
};

const handleLogout = () => {
logout();
setAuth(false);
};

return (
<div className="${theme}">
<div>
<h1>{t("settingH1")}</h1>

<div className="settings">
<div id="language">
<label>{t("languageLabel")} : </label>
<LanguageButton />
</div>
<hr />
<div id={"login"}>
<div id={"inputs"}>
<div id={"uname"}>
<label>{t("askForUName")} : </label>
<input
type={"text"}
value={uname}
onChange={(e) => setUname(e.target.value)}
></input>
</div>
<div id={"password"}>
<label>{t("askForPassword")} : </label>
<input
type={"password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
></input>
<div id="login">
{auth ? (
<div>
<button onClick={handleLogout}>{t("logout")}</button>
</div>
</div>
<div id={"validate-uname"}>
<div
className={"checkbox-container"}
onClick={() => setUnameValidated(!uname_validated)}
>
<input
type="checkbox"
value={"accepted-uname"}
checked={uname_validated}
onChange={() => setUnameValidated(!uname_validated)}
/>
) : (
<div>
<div id="inputs">
<div id="uname">
<label>{t("askForUName")} : </label>
<input
type="text"
value={uname}
onChange={(e) => setUname(e.target.value)}
/>
</div>
<div id="password">
<label>{t("askForPassword")} : </label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
</div>
<div id="validate-uname">
<div
className="checkbox-container"
onClick={() => setUnameValidated(!uname_validated)}
>
<input
type="checkbox"
value="accepted-uname"
checked={uname_validated}
onChange={() => setUnameValidated(!uname_validated)}
/>
</div>
<p id="accept-uname">
{t("acceptUName")}
<br />
{t("reminderSensitive")}
</p>
</div>
<button
className="language-button en send-uname"
onClick={login}
disabled={!uname_validated || uname === "" || isLoading}
>
{isLoading ? t("loading...") : t("login")}
</button>
</div>
<p id={"accept-uname"}>
{t("acceptUName")}
<br />
{t("reminderSensitive")}
</p>
</div>
<button
className={"language-button en send-uname"}
onClick={login}
disabled={!uname_validated || uname === ""}
>
{t("login")}
</button>
)}
</div>
</div>
</div>
);
}
};

export default SettingPage;
export default SettingsPage;
25 changes: 25 additions & 0 deletions src/Utils/Auth/AuthUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const isAuthenticated = () => {
// Look for the `auth` cookie
const authCookie = document.cookie
.split("; ")
.find((row) => row.startsWith("auth="));

// Check that the cookie is present and not empty
if (authCookie) {
const authValue = authCookie.split("=")[1];
return authValue !== undefined && authValue !== "";
}

return false;
};

const login = (username: string, password: string) => {
document.cookie = `auth=${btoa(username + ":" + password)}`;
};

const logout = () => {
// Set the cookie's expiry date to a past date to effectively remove it
document.cookie = "auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
};

export { isAuthenticated, login, logout };
4 changes: 2 additions & 2 deletions src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import i18n from "i18next";
import { initReactI18next } from "react-i18next";

// Import your translations (replace with your actual files)
import en from "../public/locales/en.json";
import fr from "../public/locales/fr.json";
import en from "./locales/en.json";
import fr from "./locales/fr.json";

i18n
.use(initReactI18next) // Initializes i18n with React
Expand Down
Loading

0 comments on commit 46e7253

Please sign in to comment.