Compare commits

..

5 Commits

9 changed files with 70 additions and 78 deletions

View File

@@ -7,7 +7,7 @@ const aliases = (prefix = `src`) => ({
'app/shared-components': `${prefix}/app/shared-components`, 'app/shared-components': `${prefix}/app/shared-components`,
'app/configs': `${prefix}/app/configs`, 'app/configs': `${prefix}/app/configs`,
'app/theme-layouts': `${prefix}/app/theme-layouts`, 'app/theme-layouts': `${prefix}/app/theme-layouts`,
'app/AppContext': `${prefix}/app/AppContext`, 'app/contexts/AppContext': `${prefix}/app/contexts/AppContext`,
}); });
module.exports = aliases; module.exports = aliases;

View File

@@ -1,16 +1,34 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": "./", "baseUrl": "./",
"paths": { "paths": {
"@fuse/*": ["./src/@fuse/*"], "@fuse/*": [
"@history*": ["./src/@history"], "./src/@fuse/*"
"@lodash": ["./src/@lodash"], ],
"@mock-api": ["./src/@mock-api"], "@history*": [
"app/store/*": ["./src/app/store/*"], "./src/@history"
"app/shared-components/*": ["./src/app/shared-components/*"], ],
"app/configs/*": ["./src/app/configs/*"], "@lodash": [
"app/theme-layouts/*": ["./src/app/theme-layouts/*"], "./src/@lodash"
"app/AppContext": ["./src/app/AppContext"] ],
} "@mock-api": [
"./src/@mock-api"
],
"app/store/*": [
"./src/app/store/*"
],
"app/shared-components/*": [
"./src/app/shared-components/*"
],
"app/configs/*": [
"./src/app/configs/*"
],
"app/theme-layouts/*": [
"./src/app/theme-layouts/*"
],
"app/contexts/AppContext": [
"./src/app/contexts/AppContext"
]
}
} }
} }

View File

@@ -50,7 +50,6 @@ class FuseAuthorization extends Component {
const { location, userRole } = this.props; const { location, userRole } = this.props;
const { pathname } = location; const { pathname } = location;
const redirectUrl = loginRedirectUrl || this.defaultLoginRedirectUrl; const redirectUrl = loginRedirectUrl || this.defaultLoginRedirectUrl;
console.log(location, userRole, redirectUrl);
/* /*
User is guest User is guest

View File

@@ -19,7 +19,7 @@ const settingsConfig = {
To make whole app accessible without authorization by default set defaultAuth: null To make whole app accessible without authorization by default set defaultAuth: null
*** The individual route configs which has auth option won't be overridden. *** The individual route configs which has auth option won't be overridden.
*/ */
defaultAuth: ['admin'], defaultAuth: ['admin', 'staff', 'user'],
/* /*
Default redirect url for the logged-in user, Default redirect url for the logged-in user,
*/ */

View File

@@ -4,7 +4,7 @@ import { useDispatch } from 'react-redux';
import FuseSplashScreen from '@fuse/core/FuseSplashScreen'; import FuseSplashScreen from '@fuse/core/FuseSplashScreen';
import { showMessage } from 'app/store/fuse/messageSlice'; import { showMessage } from 'app/store/fuse/messageSlice';
import { logoutUser, setUser } from 'app/store/userSlice'; import { logoutUser, setUser } from 'app/store/userSlice';
import jwtService from './services/jwtService'; import { authService, firebase } from '../services';
const AuthContext = React.createContext(); const AuthContext = React.createContext();
@@ -14,44 +14,35 @@ function AuthProvider({ children }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
jwtService.on('onAutoLogin', () => { authService.on('onLogout', () => {
dispatch(showMessage({ message: 'Signing in with JWT' }));
/**
* Sign in and retrieve user data with stored token
*/
jwtService
.signInWithToken()
.then((user) => {
success(user, 'Signed in with JWT');
})
.catch((error) => {
pass(error.message);
});
});
jwtService.on('onLogin', (user) => {
success(user, 'Signed in');
});
jwtService.on('onLogout', () => {
pass('Signed out'); pass('Signed out');
dispatch(logoutUser()); dispatch(logoutUser());
}); });
jwtService.on('onAutoLogout', (message) => { authService.init(firebase.auth, firebase.db);
pass(message);
dispatch(logoutUser()); authService.onAuthStateChanged((authUser) => {
dispatch(showMessage({ message: 'Signing...' }));
if (authUser) {
authService
.getUserData(authUser.uid)
.then((user) => {
if (user) {
success(user, 'Signed in');
} else {
const { displayName, photoURL, email } = authUser;
success({ role: 'user', data: { displayName, photoURL, email } }, 'Signed in');
}
})
.catch((error) => {
pass(error.message);
});
} else {
pass('Signed out');
}
}); });
jwtService.on('onNoAccessToken', () => {
pass();
});
jwtService.init();
function success(user, message) { function success(user, message) {
if (message) { if (message) {
dispatch(showMessage({ message })); dispatch(showMessage({ message }));

View File

@@ -1,7 +1,7 @@
import i18next from 'i18next'; import i18next from 'i18next';
import ForgotPasswordPage from './ForgotPasswordPage'; import ForgotPasswordPage from './ForgotPasswordPage';
import authRoles from '../../../auth/authRoles'; import authRoles from '../../../configs/authRoles';
import en from './i18n/en'; import en from './i18n/en';
i18next.addResourceBundle('en', 'forgotPasswordPage', en); i18next.addResourceBundle('en', 'forgotPasswordPage', en);

View File

@@ -7,6 +7,7 @@ import Typography from '@mui/material/Typography';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { withTranslation } from 'react-i18next'; import { withTranslation } from 'react-i18next';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { authService } from 'src/app/services';
import * as yup from 'yup'; import * as yup from 'yup';
import LeftSideCanvas from '../shared-components/LeftSideCanvas'; import LeftSideCanvas from '../shared-components/LeftSideCanvas';
@@ -19,7 +20,7 @@ function ForgotPasswordPage({ t }) {
email: yup.string().email(t('email_error')).required(t('email_error')), email: yup.string().email(t('email_error')).required(t('email_error')),
}); });
const { control, formState, handleSubmit, reset } = useForm({ const { control, formState, handleSubmit, setError } = useForm({
mode: 'onChange', mode: 'onChange',
defaultValues, defaultValues,
resolver: yupResolver(schema), resolver: yupResolver(schema),
@@ -27,8 +28,13 @@ function ForgotPasswordPage({ t }) {
const { isValid, dirtyFields, errors } = formState; const { isValid, dirtyFields, errors } = formState;
function onSubmit() { function onSubmit({ email }) {
reset(defaultValues); authService.sendPasswordResetEmail(email).catch((error) => {
setError('root', {
type: 'manual',
message: error.message,
});
});
} }
return ( return (

View File

@@ -5,7 +5,7 @@ import _ from '@lodash';
import { setInitialSettings } from 'app/store/fuse/settingsSlice'; import { setInitialSettings } from 'app/store/fuse/settingsSlice';
import { showMessage } from 'app/store/fuse/messageSlice'; import { showMessage } from 'app/store/fuse/messageSlice';
import settingsConfig from 'app/configs/settingsConfig'; import settingsConfig from 'app/configs/settingsConfig';
import jwtService from '../auth/services/jwtService'; import { authService } from '../services';
export const setUser = createAsyncThunk('user/setUser', async (user, { dispatch, getState }) => { export const setUser = createAsyncThunk('user/setUser', async (user, { dispatch, getState }) => {
/* /*
@@ -30,24 +30,6 @@ export const updateUserSettings = createAsyncThunk(
} }
); );
export const updateUserShortcuts = createAsyncThunk(
'user/updateShortucts',
async (shortcuts, { dispatch, getState }) => {
const { user } = getState();
const newUser = {
...user,
data: {
...user.data,
shortcuts,
},
};
dispatch(updateUserData(newUser));
return newUser;
}
);
export const logoutUser = () => async (dispatch, getState) => { export const logoutUser = () => async (dispatch, getState) => {
const { user } = getState(); const { user } = getState();
@@ -71,10 +53,10 @@ export const updateUserData = (user) => async (dispatch, getState) => {
return; return;
} }
jwtService authService
.updateUserData(user) .updateUserData(user)
.then(() => { .then(() => {
dispatch(showMessage({ message: 'User data saved with api' })); dispatch(showMessage({ message: 'User data saved' }));
}) })
.catch((error) => { .catch((error) => {
dispatch(showMessage({ message: error.message })); dispatch(showMessage({ message: error.message }));
@@ -87,7 +69,6 @@ const initialState = {
displayName: 'John Doe', displayName: 'John Doe',
photoURL: 'assets/images/avatars/brian-hughes.jpg', photoURL: 'assets/images/avatars/brian-hughes.jpg',
email: 'johndoe@withinpixels.com', email: 'johndoe@withinpixels.com',
shortcuts: ['apps.calendar', 'apps.mailbox', 'apps.contacts', 'apps.tasks'],
}, },
}; };
@@ -99,7 +80,6 @@ const userSlice = createSlice({
}, },
extraReducers: { extraReducers: {
[updateUserSettings.fulfilled]: (state, action) => action.payload, [updateUserSettings.fulfilled]: (state, action) => action.payload,
[updateUserShortcuts.fulfilled]: (state, action) => action.payload,
[setUser.fulfilled]: (state, action) => action.payload, [setUser.fulfilled]: (state, action) => action.payload,
}, },
}); });
@@ -108,6 +88,4 @@ export const { userLoggedOut } = userSlice.actions;
export const selectUser = ({ user }) => user; export const selectUser = ({ user }) => user;
export const selectUserShortcuts = ({ user }) => user.data.shortcuts;
export default userSlice.reducer; export default userSlice.reducer;

View File

@@ -40,7 +40,7 @@ function UserNavbarHeader(props) {
src={user.data.photoURL} src={user.data.photoURL}
alt={user.data.displayName} alt={user.data.displayName}
> >
{user.data.displayName.charAt(0)} {user.data.displayName?.charAt(0)}
</Avatar> </Avatar>
</div> </div>
<Typography className="username text-14 whitespace-nowrap font-medium"> <Typography className="username text-14 whitespace-nowrap font-medium">