Skip to content

Commit

Permalink
Enable & Disable 2FA
Browse files Browse the repository at this point in the history
  • Loading branch information
ProgrammerDATCH committed Aug 5, 2024
1 parent d4e54ea commit ac6c525
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 10 deletions.
14 changes: 13 additions & 1 deletion src/assets/styles/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ a {
border-radius: 0.6rem;
position: absolute;
left: -10%;
padding-right: 0;
padding-right: 10px;
top: 150%;
width: 140%;
z-index: 500;
Expand All @@ -406,6 +406,18 @@ a {
flex-direction: column;
gap: 1.2rem;
}
&__2fa_btn{
color: $white;
background-color: $primary-color-dark ;
margin-top: 5px;
border-radius: 4px;
padding: 2px 4px;
cursor: pointer;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}

&__icon {
width: 1.8rem;
Expand Down
49 changes: 41 additions & 8 deletions src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import Notifications from './notification';
import SearchInput from '../inputs/SearchInput';
import { useAppDispatch, useAppSelector } from '../../store/store';
import { fetchNotifications } from '../../store/features/notifications/notificationSlice';
import { getUserDetails } from '../../store/features/auth/authSlice';
import { change2FAStatus, getUserDetails } from '../../store/features/auth/authSlice';
import { useLocation, Link } from 'react-router-dom';
import logo from "../../../public/assets/images/logo.png";
import useSocket from '../../hooks/useSocket';
import { toast } from 'react-toastify';
import { PulseLoader } from 'react-spinners';
const Header: React.FC = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
Expand All @@ -37,6 +39,8 @@ const Header: React.FC = () => {
} = useAppSelector((state) => state.auth);
const { notifications } = useAppSelector((state) => state.notification);
const [token, setToken] = useState('');
const [is2FAEnabled, setIs2FAEnabled] = useState(false);
const [is2FALoading, setIs2FALoading] = useState(false);
const navEl = useRef<HTMLDivElement | null>(null);

const User: any = { ...user };
Expand Down Expand Up @@ -92,12 +96,28 @@ const Header: React.FC = () => {
const unreadCount = notifications
? notifications.filter((notification) => !notification.isRead).length
: 0;

function formatName(name: string) {
const trimmedName = name.trim();
const formattedName = trimmedName.replace(/\s+/g, '.');
return formattedName.length > 5 ? formattedName.substring(0, 5) + '...' : formattedName;

function formatName(name: string) {
const trimmedName = name.trim();
const formattedName = trimmedName.replace(/\s+/g, '.');
return formattedName.length > 5 ? formattedName.substring(0, 5) + '...' : formattedName;
}

const switch2FA = async () => {
const successMessage = `2FA ${is2FAEnabled ? "Disabled" : "Enabled"}`;
setIs2FALoading(true);
const res = await dispatch(change2FAStatus({ newStatus: !is2FAEnabled }))
setIs2FALoading(false);
if (res.type === "auth/change-2fa-status/fulfilled") {
toast.success(res.payload.message || successMessage)
setIs2FAEnabled(res.payload.data.user.is2FAEnabled || !is2FAEnabled)
}
else {
toast.error(res.payload)
}
}

useEffect(() => { if (user) setIs2FAEnabled(user.is2FAEnabled) }, [user])

return (
<header className="header">
Expand Down Expand Up @@ -228,7 +248,7 @@ const Header: React.FC = () => {

<span className="cart__text">{user ? 'Hi, ' : 'User'}</span>
<span className="cart__description">
{user
{user
? formatName(User?.firstName || User?.email?.split('@')[0])
: "Account"}
</span>
Expand Down Expand Up @@ -259,7 +279,20 @@ const Header: React.FC = () => {
<span className="order__text">Logout</span>
</NavLink>
</li>

</ul>
<button
type="button"
className="order__2fa_btn"
onClick={switch2FA}
disabled={is2FALoading}
>
{is2FALoading
? (is2FAEnabled
? <>Disabling 2FA <PulseLoader size={3} color="#ffe2d1" loading={is2FAEnabled} /></>
: <>Enabling 2FA <PulseLoader size={3} color="#ffe2d1" loading={is2FAEnabled} /></>)
: (is2FAEnabled ? "Disable 2FA" : "Enable 2FA")}
</button>
</div>
)}
</div>
Expand All @@ -276,7 +309,7 @@ const Header: React.FC = () => {
<div className="header__nav" ref={navEl}>
<nav>
<ul className="header__list">
{isAuthenticated && (
{isAuthenticated && (
<li className="nav__item" onClick={handleSetIsMenuOpen}>
<NavLink
to="/home"
Expand Down
8 changes: 7 additions & 1 deletion src/store/features/auth/authService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const login = async (userData: IUser) => {
return response.data;
};

const logout = async() => {
const logout = async () => {
const response = await axiosInstance.post("/api/auth/logout");
return response.data;
}
Expand Down Expand Up @@ -77,6 +77,11 @@ const verifyOTP = async (userId: string, otp: string) => {
return response.data;
};

const change2FAStatus = async (newStatus: boolean) => {
const response = await axiosInstance.put("/api/auth/enable-2f", { is2FAEnabled: newStatus });
return response.data;
}

const authService = {
register,
login,
Expand All @@ -89,6 +94,7 @@ const authService = {
sendResetLink,
resetPassword,
verifyOTP,
change2FAStatus,
};

export default authService;
15 changes: 15 additions & 0 deletions src/store/features/auth/authSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,21 @@ export const verifyOTP = createAsyncThunk(
}
);

export const change2FAStatus = createAsyncThunk(
"auth/change-2fa-status",
async (
{ newStatus }: { newStatus: boolean },
thunkApi
) => {
try {
const response = await authService.change2FAStatus(newStatus);
return response;
} catch (error) {
return thunkApi.rejectWithValue(getErrorMessage(error));
}
}
);

const userSlice = createSlice({
name: "auth",
initialState,
Expand Down

0 comments on commit ac6c525

Please sign in to comment.