update login dan password
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Models\User;
|
|||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
|
|
||||||
@@ -16,7 +17,8 @@ class AuthController extends Controller
|
|||||||
public function login(Request $request)
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'phoneOrEmail' => 'required'
|
'phoneOrEmail' => 'required',
|
||||||
|
'password' => 'required'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = User::query()
|
$user = User::query()
|
||||||
@@ -32,45 +34,61 @@ class AuthController extends Controller
|
|||||||
|
|
||||||
return Helper::responseJson(statusCode: Response::HTTP_NOT_FOUND, message: $message);
|
return Helper::responseJson(statusCode: Response::HTTP_NOT_FOUND, message: $message);
|
||||||
}
|
}
|
||||||
$token = rand(1000, 9999); // Menghasilkan angka acak antara 100000 dan 999999
|
|
||||||
if($request->phoneOrEmail == 'manager+one@gmail.com' || $request->phoneOrEmail == 'manager+two@gmail.com')
|
|
||||||
{
|
// $token = rand(1000, 9999); // Menghasilkan angka acak antara 100000 dan 999999
|
||||||
$token = 4444;
|
// if($request->phoneOrEmail == 'manager+one@gmail.com' || $request->phoneOrEmail == 'manager+two@gmail.com')
|
||||||
}
|
// {
|
||||||
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
// $token = 4444;
|
||||||
User::query()->find($user->id)->update([
|
// }
|
||||||
'email' => $request->phoneOrEmail,
|
// if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||||
'otp' => $token,
|
// User::query()->find($user->id)->update([
|
||||||
'otp_created_at' => now()
|
// 'email' => $request->phoneOrEmail,
|
||||||
]);
|
// 'otp' => $token,
|
||||||
} else {
|
// 'otp_created_at' => now()
|
||||||
User::query()->find($user->id)->update([
|
// ]);
|
||||||
'phone' => $request->phoneOrEmail,
|
// } else {
|
||||||
'otp' => $token,
|
// User::query()->find($user->id)->update([
|
||||||
'otp_created_at' => now()
|
// 'phone' => $request->phoneOrEmail,
|
||||||
]);
|
// 'otp' => $token,
|
||||||
|
// 'otp_created_at' => now()
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // TODO Send the OTP
|
||||||
|
// if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
// // Send Email
|
||||||
|
// //send to alarm
|
||||||
|
// if($request->phoneOrEmail != 'manager+one@gmail.com' && $request->phoneOrEmail != 'manager+two@gmail.com')
|
||||||
|
// {
|
||||||
|
// $nameTo = 'User';
|
||||||
|
// $dataEmail = [
|
||||||
|
// 'email' => $request->phoneOrEmail,
|
||||||
|
// 'name' => $nameTo,
|
||||||
|
// 'subject' => 'OTP Login Client Portal Tanggal '. date('Y-m-d H:i:s'),
|
||||||
|
// 'body' => View::make('email/forgot_password', ['token' => $token])->render(),
|
||||||
|
// ];
|
||||||
|
// Helper::sendEmail($dataEmail);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // Send Whatsapp
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return Helper::responseJson(message: 'OTP Terkirim');
|
||||||
|
|
||||||
|
|
||||||
|
if (!Hash::check($request->password, $user->password)) {
|
||||||
|
return response(['message' => 'Password Salah'], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Send the OTP
|
return Helper::responseJson(
|
||||||
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
data: [
|
||||||
// Send Email
|
'token' => $user->createToken('app')->plainTextToken,
|
||||||
//send to alarm
|
'user' => $user,
|
||||||
if($request->phoneOrEmail != 'manager+one@gmail.com' && $request->phoneOrEmail != 'manager+two@gmail.com')
|
],
|
||||||
{
|
message: 'Selamat Datang'
|
||||||
$nameTo = 'User';
|
);
|
||||||
$dataEmail = [
|
|
||||||
'email' => $request->phoneOrEmail,
|
|
||||||
'name' => $nameTo,
|
|
||||||
'subject' => 'OTP Login Client Portal Tanggal '. date('Y-m-d H:i:s'),
|
|
||||||
'body' => View::make('email/forgot_password', ['token' => $token])->render(),
|
|
||||||
];
|
|
||||||
Helper::sendEmail($dataEmail);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Send Whatsapp
|
|
||||||
}
|
|
||||||
|
|
||||||
return Helper::responseJson(message: 'OTP Terkirim');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validateOtp(Request $request)
|
public function validateOtp(Request $request)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export type JWTContextType = {
|
|||||||
isInitialized: boolean;
|
isInitialized: boolean;
|
||||||
user: AuthUser;
|
user: AuthUser;
|
||||||
method: 'jwt';
|
method: 'jwt';
|
||||||
login: (phoneOrEmail: string) => Promise<void>;
|
login: (phoneOrEmail: string, password: string, rememberMe: boolean) => Promise<void>;
|
||||||
validateOtp: (phoneOrEmail: string, otp: string) => Promise<void>
|
validateOtp: (phoneOrEmail: string, otp: string) => Promise<void>
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { createContext, ReactNode, useEffect, useReducer } from 'react';
|
import { createContext, ReactNode, useEffect, useReducer } from 'react';
|
||||||
// utils
|
// utils
|
||||||
import axios from '../utils/axios';
|
import axios from '../utils/axios';
|
||||||
import { setSession, getSession } from '../utils/token';
|
import { setSession, getSession, setUser, getUser, getCookie } from '../utils/token';
|
||||||
// @types
|
// @types
|
||||||
import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth';
|
import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
import { Navigate, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
enum Types {
|
enum Types {
|
||||||
Initial = 'INITIALIZE',
|
Initial = 'INITIALIZE',
|
||||||
@@ -19,7 +20,9 @@ type JWTAuthPayload = {
|
|||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
user: AuthUser;
|
user: AuthUser;
|
||||||
};
|
};
|
||||||
[Types.Login]: undefined;
|
[Types.Login]: {
|
||||||
|
user: AuthUser;
|
||||||
|
};
|
||||||
[Types.ValidateOtp]: {
|
[Types.ValidateOtp]: {
|
||||||
user: AuthUser;
|
user: AuthUser;
|
||||||
};
|
};
|
||||||
@@ -45,8 +48,8 @@ const JWTReducer = (state: AuthState, action: JWTActions) => {
|
|||||||
case 'LOGIN':
|
case 'LOGIN':
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isAuthenticated: false,
|
isAuthenticated: true,
|
||||||
user: null,
|
user: action.payload.user,
|
||||||
};
|
};
|
||||||
case 'VALIDATE-OTP':
|
case 'VALIDATE-OTP':
|
||||||
return {
|
return {
|
||||||
@@ -75,7 +78,46 @@ type AuthProviderProps = {
|
|||||||
|
|
||||||
function AuthProvider({ children }: AuthProviderProps) {
|
function AuthProvider({ children }: AuthProviderProps) {
|
||||||
const [state, dispatch] = useReducer(JWTReducer, initialState);
|
const [state, dispatch] = useReducer(JWTReducer, initialState);
|
||||||
|
let location = useLocation();
|
||||||
const accessToken = getSession();
|
const accessToken = getSession();
|
||||||
|
// useEffect(() => {
|
||||||
|
// (async () => {
|
||||||
|
// try {
|
||||||
|
// // const accessToken = getSession();
|
||||||
|
|
||||||
|
// if (accessToken) {
|
||||||
|
// setSession(accessToken);
|
||||||
|
|
||||||
|
// const response = await axios.get('/user');
|
||||||
|
// const user = response.data;
|
||||||
|
|
||||||
|
// dispatch({
|
||||||
|
// type: Types.Initial,
|
||||||
|
// payload: {
|
||||||
|
// isAuthenticated: true,
|
||||||
|
// user,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// dispatch({
|
||||||
|
// type: Types.Initial,
|
||||||
|
// payload: {
|
||||||
|
// isAuthenticated: false,
|
||||||
|
// user: null,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// } catch (err) {
|
||||||
|
// dispatch({
|
||||||
|
// type: Types.Initial,
|
||||||
|
// payload: {
|
||||||
|
// isAuthenticated: false,
|
||||||
|
// user: null,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// })();
|
||||||
|
// }, [accessToken]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -116,12 +158,28 @@ function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
})();
|
})();
|
||||||
}, [accessToken]);
|
}, [accessToken]);
|
||||||
|
|
||||||
const login = async (phoneOrEmail: string) =>
|
|
||||||
|
const headers = {
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type' : 'application/json',
|
||||||
|
'Accept-Language': localStorage.getItem('currentLocale') ?? 'id-ID',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const login = async (phoneOrEmail: string, password: string, remember:boolean) =>
|
||||||
axios
|
axios
|
||||||
.post('/login', { phoneOrEmail })
|
.post('/login', { phoneOrEmail, password }, headers)
|
||||||
.then(() => {
|
.then((response) => {
|
||||||
|
const { user, token } = response.data.data;
|
||||||
|
setSession(token);
|
||||||
|
setUser(user);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Types.Login,
|
type: Types.Login,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default function Login() {
|
|||||||
</video>
|
</video>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6} sx={{ padding: 3 }}>
|
<Grid item xs={6} sx={{ padding: 3 }}>
|
||||||
{loginOrVerifyCode && emailOrPhone ? (
|
{/* {loginOrVerifyCode && emailOrPhone ? (
|
||||||
<>
|
<>
|
||||||
<Stack direction="column" sx={{ mb: 5 }}>
|
<Stack direction="column" sx={{ mb: 5 }}>
|
||||||
<Stack direction="row" alignItems="center">
|
<Stack direction="row" alignItems="center">
|
||||||
@@ -138,7 +138,7 @@ export default function Login() {
|
|||||||
>Kirim Ulang Kode OTP</Link>
|
>Kirim Ulang Kode OTP</Link>
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : ( */}
|
||||||
<>
|
<>
|
||||||
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
|
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
|
||||||
<Logo sx={{ width: 90, height: 90 }} />
|
<Logo sx={{ width: 90, height: 90 }} />
|
||||||
@@ -152,19 +152,16 @@ export default function Login() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
{emailOrPhoneForm ? (
|
{/* {emailOrPhoneForm ? (
|
||||||
<LoginPhoneForm
|
<LoginPhoneForm
|
||||||
setEmailOrPhone={setEmailOrPhone}
|
setEmailOrPhone={setEmailOrPhone}
|
||||||
setLoginOrVerifyCode={setLoginOrVerifyCode}
|
setLoginOrVerifyCode={setLoginOrVerifyCode}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : ( */}
|
||||||
<LoginEmailForm
|
<LoginEmailForm/>
|
||||||
setEmailOrPhone={setEmailOrPhone}
|
{/* )} */}
|
||||||
setLoginOrVerifyCode={setLoginOrVerifyCode}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
{/* )} */}
|
||||||
|
|
||||||
{/* <Divider sx={{ marginTop: 5 }}>Atau</Divider>
|
{/* <Divider sx={{ marginTop: 5 }}>Atau</Divider>
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,52 @@
|
|||||||
/* ----------------------------------- yup ---------------------------------- */
|
/* ----------------------------------- yup ---------------------------------- */
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
|
import React, { useContext, useRef, useState, useEffect } from 'react';
|
||||||
/* ---------------------------------- form ---------------------------------- */
|
/* ---------------------------------- form ---------------------------------- */
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
/* ---------------------------------- @mui ---------------------------------- */
|
/* ---------------------------------- @mui ---------------------------------- */
|
||||||
import { Stack, Alert } from '@mui/material';
|
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { Link, Stack, Alert, IconButton, InputAdornment } from '@mui/material';
|
||||||
/* ---------------------------------- hooks --------------------------------- */
|
/* ---------------------------------- hooks --------------------------------- */
|
||||||
import useAuth from '../../../hooks/useAuth';
|
import useAuth from '../../../hooks/useAuth';
|
||||||
import useIsMountedRef from '../../../hooks/useIsMountedRef';
|
import useIsMountedRef from '../../../hooks/useIsMountedRef';
|
||||||
/* ------------------------------- components ------------------------------- */
|
/* ------------------------------- components ------------------------------- */
|
||||||
import { FormProvider, RHFTextField } from '../../../components/hook-form';
|
import Iconify from '../../../components/Iconify';
|
||||||
|
import { FormProvider, RHFTextField, RHFCheckbox } from '../../../components/hook-form';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
/* ---------------------------------- types --------------------------------- */
|
||||||
|
|
||||||
type LoginFormProps = {
|
// type LoginFormProps = {
|
||||||
setEmailOrPhone: Function;
|
// setEmailOrPhone: Function;
|
||||||
setLoginOrVerifyCode: Function;
|
// setLoginOrVerifyCode: Function;
|
||||||
};
|
// };
|
||||||
|
|
||||||
type FormValuesProps = {
|
type FormValuesProps = {
|
||||||
email: string;
|
email: string;
|
||||||
|
password: string;
|
||||||
|
remember: boolean;
|
||||||
afterSubmit?: string;
|
afterSubmit?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export default function LoginForm({ setEmailOrPhone, setLoginOrVerifyCode }: LoginFormProps) {
|
export default function LoginForm() {
|
||||||
const { login } = useAuth();
|
const { login } = useAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
const isMountedRef = useIsMountedRef();
|
const isMountedRef = useIsMountedRef();
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const LoginSchema = Yup.object().shape({
|
const LoginSchema = Yup.object().shape({
|
||||||
email: Yup.string().email('Email must be a valid email address').required('Email is required'),
|
email: Yup.string().email('Format email tidak valid').required('Email harus diisi'),
|
||||||
|
password: Yup.string().required('Password harus diisi'),
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
email: '',
|
email: '',
|
||||||
|
password: '',
|
||||||
|
remember: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const methods = useForm<FormValuesProps>({
|
const methods = useForm<FormValuesProps>({
|
||||||
@@ -51,17 +61,34 @@ export default function LoginForm({ setEmailOrPhone, setLoginOrVerifyCode }: Log
|
|||||||
formState: { errors, isSubmitting },
|
formState: { errors, isSubmitting },
|
||||||
} = methods;
|
} = methods;
|
||||||
|
|
||||||
|
// const onSubmit = async (data: FormValuesProps) => {
|
||||||
|
// try {
|
||||||
|
// const loginResult = await login(data.email, data.password, data.remember);
|
||||||
|
// // setEmailOrPhone(data.email);
|
||||||
|
// // setLoginOrVerifyCode(true);
|
||||||
|
// // reset();
|
||||||
|
// console.log('test');
|
||||||
|
// navigate('/dashboard');
|
||||||
|
// // enqueueSnackbar('Kode OTP telah dikirim, silahkan cek email dan spam folder', {
|
||||||
|
// // variant: 'success',
|
||||||
|
// // autoHideDuration: 5000,
|
||||||
|
// // });
|
||||||
|
// } catch (error: any) {
|
||||||
|
// reset();
|
||||||
|
// console.log(error, 'test');
|
||||||
|
|
||||||
|
// if (isMountedRef.current) {
|
||||||
|
// setError('afterSubmit', { ...error, message: error.data.message });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
const onSubmit = async (data: FormValuesProps) => {
|
const onSubmit = async (data: FormValuesProps) => {
|
||||||
try {
|
try {
|
||||||
await login(data.email);
|
const loginResult = await login(data.email, data.password, data.remember);
|
||||||
setEmailOrPhone(data.email);
|
navigate('/dashboard');
|
||||||
setLoginOrVerifyCode(true);
|
} catch (error) {
|
||||||
reset();
|
|
||||||
enqueueSnackbar('Kode OTP telah dikirim, silahkan cek email dan spam folder', {
|
|
||||||
variant: 'success',
|
|
||||||
autoHideDuration: 5000,
|
|
||||||
});
|
|
||||||
} catch (error: any) {
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
@@ -73,10 +100,25 @@ export default function LoginForm({ setEmailOrPhone, setLoginOrVerifyCode }: Log
|
|||||||
return (
|
return (
|
||||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
<Alert severity="info">Masukkan akun yang telah terdaftar</Alert>
|
<Alert severity="info">Masukan Email atau Username dan Password</Alert>
|
||||||
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
||||||
|
|
||||||
<RHFTextField name="email" label="Email address" />
|
<RHFTextField name="email" label="Email address" />
|
||||||
|
<RHFTextField
|
||||||
|
name="password"
|
||||||
|
label="Password"
|
||||||
|
type={showPassword ? 'text' : 'password'}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton onClick={() => setShowPassword(!showPassword)} edge="end">
|
||||||
|
<Iconify icon={showPassword ? 'eva:eye-fill' : 'eva:eye-off-fill'} />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
|
|||||||
Reference in New Issue
Block a user