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

feat: be/new auth structure #1775

Closed
wants to merge 21 commits into from
Closed
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
3 changes: 2 additions & 1 deletion Client/src/Components/Inputs/TextInput/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const getSx = (theme, type, maxWidth) => {
const sx = {
maxWidth: maxWidth,
"& .MuiOutlinedInput-root ": {
backgroundColor: theme.palette.background.paper,
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: theme.palette.primary.contrastText, // Adjust hover border color
},
Expand Down Expand Up @@ -152,7 +153,7 @@ TextInput.displayName = "TextInput";

TextInput.propTypes = {
type: PropTypes.string,
id: PropTypes.string.isRequired,
id: PropTypes.string,
name: PropTypes.string,
value: PropTypes.string,
placeholder: PropTypes.string,
Expand Down
2 changes: 2 additions & 0 deletions Client/src/Features/Auth/authSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const initialState = {
isLoading: false,
authToken: "",
user: "",
teams: [],
success: null,
msg: null,
};
Expand Down Expand Up @@ -148,6 +149,7 @@ const handleAuthFulfilled = (state, action) => {
state.msg = action.payload.msg;
state.authToken = action.payload.data.token;
state.user = action.payload.data.user;
state.teams = action.payload.data.teams;
};
const handleAuthRejected = (state, action) => {
state.isLoading = false;
Expand Down
10 changes: 0 additions & 10 deletions Client/src/Pages/Auth/Login/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,6 @@ const Login = () => {
navigate("/uptime");
return;
}
networkService
.doesSuperAdminExist()
.then((response) => {
if (response.data.data === false) {
navigate("/register");
}
})
.catch((error) => {
logger.error(error);
});
}, [authToken, navigate]);

const handleChange = (event) => {
Expand Down
2 changes: 1 addition & 1 deletion Client/src/Pages/Auth/Register/StepThree/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function StepThree({ onSubmit, onBack }) {
}
}, []);

const { handleChange, feedbacks, form, errors } = useValidatePassword();
const [handleChange, feedbacks, form, errors] = useValidatePassword();
return (
<>
<Stack
Expand Down
220 changes: 220 additions & 0 deletions Client/src/Pages/Auth/Register/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
// Components
import { Stack, Typography, Box, Button } from "@mui/material";
import Background from "../../../assets/Images/background-grid.svg?react";
import TextInput from "../../../Components/Inputs/TextInput";
import Check from "../../../Components/Check/Check";

// Utils
import { createToast } from "../../../Utils/toastUtils";
import { useTheme } from "@emotion/react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useValidatePassword } from "../hooks/useValidatePassword";
import { credentials } from "../../../Validation/validation";
import { useDispatch } from "react-redux";
import { register } from "../../../Features/Auth/authSlice";
import { useNavigate } from "react-router-dom";
const Register = () => {
const theme = useTheme();
const navigate = useNavigate();
const { t } = useTranslation();
const dispatch = useDispatch();
const [handlePasswordChange, feedbacks, passwordForm, passwordErrors] =
useValidatePassword();

// Local state
const [form, setForm] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
confirm: "",
});

const [errors, setErrors] = useState({});
console.log(passwordErrors);
const handleFormChange = (e) => {
const { name, value } = e.target;
// Handle password
if (name === "password" || name === "confirm") {
handlePasswordChange(e);
}
setForm((prev) => ({ ...prev, [name]: value }));
const { error } = credentials.validate({ [name]: value }, { abortEarly: false });
setErrors((prev) => ({
...prev,
...(error ? { [name]: error.details[0].message } : { [name]: undefined }),
}));
};

const handleSubmit = async () => {
const { error } = credentials.validate(form, {
abortEarly: false,
context: { password: form.password }, // Why do we have to do this?
});
if (error) {
const newErrors = {};
error.details.forEach((err) => {
newErrors[err.path[0]] = err.message;
});
setErrors(newErrors);
return;
}

const registrationForm = {
firstName: form.firstName,
lastName: form.lastName,
email: form.email,
password: form.password,
plan: "free",
role: ["owner", "admin", "user"],
};
const action = await dispatch(register(registrationForm));
if (action.payload.success) {
navigate("/uptime");
createToast({
body: "Welcome! Your account was created successfully.",
});
} else {
if (action.payload) {
createToast({
body: action.payload.msg,
});
} else {
createToast({
body: "Unknown error.",
});
}
}
};

return (
<Stack
margin="auto"
maxWidth={400}
minHeight="100vh"
spacing={theme.spacing(10)}
justifyContent="center"
>
<Typography
variant="h1"
sx={{ alignSelf: "center" }}
>
Checkmate
</Typography>
<Typography>Create your account to get started</Typography>
<TextInput
label="Name"
name="firstName"
isRequired={true}
placeholder="Jordan"
autoComplete="given-name"
value={form.firstName}
onChange={handleFormChange}
error={errors.firstName ? true : false}
helperText={errors.firstName}
/>
<TextInput
label="Surname"
name="lastName"
isRequired={true}
placeholder="Ellis"
autoComplete="family-name"
value={form.lastName}
onChange={handleFormChange}
error={errors.lastName ? true : false}
helperText={errors.lastName}
/>
<TextInput
type="email"
name="email"
label={t("commonEmail")}
isRequired={true}
placeholder="[email protected]"
autoComplete="email"
value={form.email}
onChange={handleFormChange}
error={errors.email ? true : false}
helperText={errors.email}
/>
<TextInput
type="password"
name="password"
label={t("commonPassword")}
isRequired={true}
placeholder={t("createAPassword")}
autoComplete="current-password"
value={form.password}
onChange={handleFormChange}
error={errors.password ? true : false}
/>
<TextInput
type="password"
id="register-confirm-input"
name="confirm"
label={t("authSetNewPasswordConfirmPassword")}
isRequired={true}
placeholder={t("confirmPassword")}
onChange={handleFormChange}
error={errors.confirm ? true : false}
/>
<Stack
gap={theme.spacing(4)}
mb={{ xs: theme.spacing(6), sm: theme.spacing(8) }}
>
<Check
noHighlightText={t("authPasswordMustBeAtLeast")}
text={t("authPasswordCharactersLong")}
variant={feedbacks.length}
/>
<Check
noHighlightText={t("authPasswordMustContainAtLeast")}
text={t("authPasswordSpecialCharacter")}
variant={feedbacks.special}
/>
<Check
noHighlightText={t("authPasswordMustContainAtLeast")}
text={t("authPasswordOneNumber")}
variant={feedbacks.number}
/>
<Check
noHighlightText={t("authPasswordMustContainAtLeast")}
text={t("authPasswordUpperCharacter")}
variant={feedbacks.uppercase}
/>
<Check
noHighlightText={t("authPasswordMustContainAtLeast")}
text={t("authPasswordLowerCharacter")}
variant={feedbacks.lowercase}
/>
<Check
noHighlightText={t("authPasswordConfirmAndPassword")}
text={t("authPasswordMustMatch")}
variant={feedbacks.confirm}
/>
</Stack>
<Button
variant="contained"
color="accent"
sx={{ width: "100%" }}
onClick={handleSubmit}
>
Get Started
</Button>
<Box
position="absolute"
zIndex={-1}
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.primary.lowContrast,
},
}}
>
<Background style={{ width: "100%" }} />
</Box>
</Stack>
);
};

export default Register;
2 changes: 1 addition & 1 deletion Client/src/Pages/Auth/hooks/useValidatePassword.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ function useValidatePassword() {
[form, errors]
);

return { handleChange, feedbacks, form, errors };
return [handleChange, feedbacks, form, errors];
}
export { useValidatePassword };
7 changes: 6 additions & 1 deletion Client/src/Routes/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import NotFound from "../Pages/NotFound";

// Auth
import AuthLogin from "../Pages/Auth/Login/Login";
import AuthRegister from "../Pages/Auth/Register/Register";
import OldAuthRegister from "../Pages/Auth/Register/Register";
import AuthRegister from "../Pages/Auth/Register";
import AuthForgotPassword from "../Pages/Auth/ForgotPassword";
import AuthCheckEmail from "../Pages/Auth/CheckEmail";
import AuthSetNewPassword from "../Pages/Auth/SetNewPassword";
Expand Down Expand Up @@ -243,6 +244,10 @@ const Routes = () => {
path="/register"
element={<AdminCheckedRegister />}
/>
<Route
path="/old-register"
element={<OldAuthRegister />}
/>

<Route
exact
Expand Down
Loading