first commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/* eslint-disable react-refresh/only-export-components */
|
||||
import {
|
||||
FC,
|
||||
useState,
|
||||
useEffect,
|
||||
createContext,
|
||||
useContext,
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
} from "react";
|
||||
import { LayoutSplashScreen } from "../../../../_metronic/layout/core";
|
||||
import { AuthModel, UserModel } from "./_models";
|
||||
import * as authHelper from "./AuthHelpers";
|
||||
import { getUserByToken } from "./_requests";
|
||||
import { WithChildren } from "../../../../_metronic/helpers";
|
||||
|
||||
type AuthContextProps = {
|
||||
auth: AuthModel | undefined;
|
||||
saveAuth: (auth: AuthModel | undefined) => void;
|
||||
currentUser: UserModel | undefined;
|
||||
setCurrentUser: Dispatch<SetStateAction<UserModel | undefined>>;
|
||||
logout: () => void;
|
||||
};
|
||||
|
||||
const initAuthContextPropsState = {
|
||||
auth: authHelper.getAuth(),
|
||||
saveAuth: () => {},
|
||||
currentUser: undefined,
|
||||
setCurrentUser: () => {},
|
||||
logout: () => {},
|
||||
};
|
||||
|
||||
const AuthContext = createContext<AuthContextProps>(initAuthContextPropsState);
|
||||
|
||||
const useAuth = () => {
|
||||
return useContext(AuthContext);
|
||||
};
|
||||
|
||||
const AuthProvider: FC<WithChildren> = ({ children }) => {
|
||||
const [auth, setAuth] = useState<AuthModel | undefined>(authHelper.getAuth());
|
||||
const [currentUser, setCurrentUser] = useState<UserModel | undefined>();
|
||||
const saveAuth = (auth: AuthModel | undefined) => {
|
||||
setAuth(auth);
|
||||
if (auth) {
|
||||
authHelper.setAuth(auth);
|
||||
} else {
|
||||
authHelper.removeAuth();
|
||||
}
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
saveAuth(undefined);
|
||||
setCurrentUser(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{ auth, saveAuth, currentUser, setCurrentUser, logout }}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const AuthInit: FC<WithChildren> = ({ children }) => {
|
||||
const { auth, currentUser, logout, setCurrentUser } = useAuth();
|
||||
const [showSplashScreen, setShowSplashScreen] = useState(true);
|
||||
|
||||
// We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application
|
||||
useEffect(() => {
|
||||
const requestUser = async (apiToken: string) => {
|
||||
try {
|
||||
if (!currentUser) {
|
||||
const { data } = await getUserByToken(apiToken);
|
||||
if (data) {
|
||||
setCurrentUser(data);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (currentUser) {
|
||||
logout();
|
||||
}
|
||||
} finally {
|
||||
setShowSplashScreen(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (auth && auth.api_token) {
|
||||
requestUser(auth.api_token);
|
||||
} else {
|
||||
logout();
|
||||
setShowSplashScreen(false);
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
return showSplashScreen ? <LayoutSplashScreen /> : <>{children}</>;
|
||||
};
|
||||
|
||||
export { AuthProvider, AuthInit, useAuth };
|
||||
@@ -0,0 +1,66 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {AuthModel} from './_models'
|
||||
|
||||
const AUTH_LOCAL_STORAGE_KEY = 'kt-auth-react-v'
|
||||
const getAuth = (): AuthModel | undefined => {
|
||||
if (!localStorage) {
|
||||
return
|
||||
}
|
||||
|
||||
const lsValue: string | null = localStorage.getItem(AUTH_LOCAL_STORAGE_KEY)
|
||||
if (!lsValue) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const auth: AuthModel = JSON.parse(lsValue) as AuthModel
|
||||
if (auth) {
|
||||
// You can easily check auth_token expiration also
|
||||
return auth
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('AUTH LOCAL STORAGE PARSE ERROR', error)
|
||||
}
|
||||
}
|
||||
|
||||
const setAuth = (auth: AuthModel) => {
|
||||
if (!localStorage) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const lsValue = JSON.stringify(auth)
|
||||
localStorage.setItem(AUTH_LOCAL_STORAGE_KEY, lsValue)
|
||||
} catch (error) {
|
||||
console.error('AUTH LOCAL STORAGE SAVE ERROR', error)
|
||||
}
|
||||
}
|
||||
|
||||
const removeAuth = () => {
|
||||
if (!localStorage) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
localStorage.removeItem(AUTH_LOCAL_STORAGE_KEY)
|
||||
} catch (error) {
|
||||
console.error('AUTH LOCAL STORAGE REMOVE ERROR', error)
|
||||
}
|
||||
}
|
||||
|
||||
export function setupAxios(axios: any) {
|
||||
axios.defaults.headers.Accept = 'application/json'
|
||||
axios.interceptors.request.use(
|
||||
(config: {headers: {Authorization: string}}) => {
|
||||
const auth = getAuth()
|
||||
if (auth && auth.api_token) {
|
||||
config.headers.Authorization = `Bearer ${auth.api_token}`
|
||||
}
|
||||
|
||||
return config
|
||||
},
|
||||
(err: any) => Promise.reject(err)
|
||||
)
|
||||
}
|
||||
|
||||
export {getAuth, setAuth, removeAuth, AUTH_LOCAL_STORAGE_KEY}
|
||||
@@ -0,0 +1,67 @@
|
||||
export interface AuthModel {
|
||||
api_token: string
|
||||
refreshToken?: string
|
||||
}
|
||||
|
||||
export interface UserAddressModel {
|
||||
addressLine: string
|
||||
city: string
|
||||
state: string
|
||||
postCode: string
|
||||
}
|
||||
|
||||
export interface UserCommunicationModel {
|
||||
email: boolean
|
||||
sms: boolean
|
||||
phone: boolean
|
||||
}
|
||||
|
||||
export interface UserEmailSettingsModel {
|
||||
emailNotification?: boolean
|
||||
sendCopyToPersonalEmail?: boolean
|
||||
activityRelatesEmail?: {
|
||||
youHaveNewNotifications?: boolean
|
||||
youAreSentADirectMessage?: boolean
|
||||
someoneAddsYouAsAsAConnection?: boolean
|
||||
uponNewOrder?: boolean
|
||||
newMembershipApproval?: boolean
|
||||
memberRegistration?: boolean
|
||||
}
|
||||
updatesFromKeenthemes?: {
|
||||
newsAboutKeenthemesProductsAndFeatureUpdates?: boolean
|
||||
tipsOnGettingMoreOutOfKeen?: boolean
|
||||
thingsYouMissedSindeYouLastLoggedIntoKeen?: boolean
|
||||
newsAboutStartOnPartnerProductsAndOtherServices?: boolean
|
||||
tipsOnStartBusinessProducts?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface UserSocialNetworksModel {
|
||||
linkedIn: string
|
||||
facebook: string
|
||||
twitter: string
|
||||
instagram: string
|
||||
}
|
||||
|
||||
export interface UserModel {
|
||||
id: number
|
||||
username: string
|
||||
password: string | undefined
|
||||
email: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
fullname?: string
|
||||
occupation?: string
|
||||
companyName?: string
|
||||
phone?: string
|
||||
roles?: Array<number>
|
||||
pic?: string
|
||||
language?: 'en' | 'de' | 'es' | 'fr' | 'ja' | 'zh' | 'ru'
|
||||
timeZone?: string
|
||||
website?: 'https://keenthemes.com'
|
||||
emailSettings?: UserEmailSettingsModel
|
||||
auth?: AuthModel
|
||||
communication?: UserCommunicationModel
|
||||
address?: UserAddressModel
|
||||
socialNetworks?: UserSocialNetworksModel
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import axios from "axios";
|
||||
import { AuthModel, UserModel } from "./_models";
|
||||
|
||||
const API_URL = import.meta.env.VITE_APP_API_URL;
|
||||
|
||||
export const GET_USER_BY_ACCESSTOKEN_URL = `${API_URL}/verify_token`;
|
||||
export const LOGIN_URL = `${API_URL}/login`;
|
||||
export const REGISTER_URL = `${API_URL}/register`;
|
||||
export const REQUEST_PASSWORD_URL = `${API_URL}/forgot_password`;
|
||||
|
||||
// Server should return AuthModel
|
||||
export function login(email: string, password: string) {
|
||||
return axios.post<AuthModel>(LOGIN_URL, {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
// Server should return AuthModel
|
||||
export function register(
|
||||
email: string,
|
||||
firstname: string,
|
||||
lastname: string,
|
||||
password: string,
|
||||
password_confirmation: string
|
||||
) {
|
||||
return axios.post(REGISTER_URL, {
|
||||
email,
|
||||
first_name: firstname,
|
||||
last_name: lastname,
|
||||
password,
|
||||
password_confirmation,
|
||||
});
|
||||
}
|
||||
|
||||
// Server should return object => { result: boolean } (Is Email in DB)
|
||||
export function requestPassword(email: string) {
|
||||
return axios.post<{ result: boolean }>(REQUEST_PASSWORD_URL, {
|
||||
email,
|
||||
});
|
||||
}
|
||||
|
||||
export function getUserByToken(token: string) {
|
||||
return axios.post<UserModel>(GET_USER_BY_ACCESSTOKEN_URL, {
|
||||
api_token: token,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user