Browse Source

authorization and token with redax

serg1557733 1 year ago
parent
commit
5ea1f6482b

+ 6 - 4
backend/app.js

@@ -26,10 +26,10 @@ const PORT = process.env.PORT || 5000;
 const TOKEN_KEY = process.env.TOKEN_KEY || 'rGH4r@3DKOg06hgj'; 
 const HASH_KEY = 7;
 
-//main test page
-app.get('/', (req, res) => {
-    res.send('here will be login page')
-})
+// //main test page
+// app.get('/', (req, res) => {
+//     res.send('here will be login page')
+// })
 
 const generateToken = (id, userName, isAdmin) => {
     const payload = {
@@ -56,8 +56,10 @@ const getOneUser = async (userName) => {
 }
 
 app.post('/login', async (req, res) => {
+    
     try {
         const {userName,password} = req.body;
+        console.log(userName,password)
         if (!isValidUserName(userName)){
             return res.status(400).json({message: 'Invalid username'})
         }

+ 26 - 0
backend/node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html

@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Node-webkit-based module test</title>
+<script>
+function nwModuleTest(){
+   var util = require('util');
+   var moduleFolder = require('nw.gui').App.argv[0];
+   try {
+      require(moduleFolder);
+   } catch(e) {
+      if( process.platform !== 'win32' ){
+         util.log('nw-pre-gyp error:');
+         util.log(e.stack);
+      }
+      process.exit(1);
+   }
+   process.exit(0);
+}
+</script>
+</head>
+<body onload="nwModuleTest()">
+<h1>Node-webkit-based module test</h1>
+</body>
+</html>

+ 17 - 0
frontend/public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="theme-color" content="#000000" />
+    <meta name="description" content="Web site created using create-react-app" />
+    <title>Chat client</title>
+</head>
+
+<body>
+    <noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+</body>
+
+</html>

+ 3 - 7
frontend/src/App.js

@@ -1,17 +1,13 @@
 import { LoginForm } from './components/loginForm/LoginForm';
 import { ChatPage } from './components/chatPage/ChatPage';
 import { useState } from 'react';
+import { useSelector } from 'react-redux';
 import { store } from './store';
 
 export default function App() {
 
-    const [token, setToken] = useState(localStorage.getItem('token'))
- 
-    store.subscribe(() =>  {
-        setToken(store.getState().token)
-        localStorage.setItem('token', store.getState().token)
-    });
-    
+    const token = useSelector(state => state.userDataReducer.token) 
+
     return token ? <ChatPage /> : <LoginForm/>
 };
 

+ 0 - 2
frontend/src/actions/actions.js

@@ -1,2 +0,0 @@
-export const storeToken = (token) => ({type: 'SET_TOKEN', token});
-export const removeToken = () => ({type: 'REMOVE_TOKEN'});

+ 8 - 5
frontend/src/components/chatPage/ChatPage.js

@@ -10,7 +10,7 @@ import { banUser } from './service/banUser';
 import { muteUser } from './service/muteUser';
 import {sendMessage} from './service/sendMessage';
 import { store } from '../../store';
-import { removeToken } from '../../actions/actions';
+import { removeToken} from '../../reducers/userDataReducer'
 
 
 import { useDispatch } from 'react-redux';
@@ -103,6 +103,7 @@ export const ChatPage = () => {
                 sx={{
                     display: 'flex',
                     flexGrow:'2',
+                    maxWidth: '75%',
                     flexDirection: 'column',                    
                 }}>
                     <Box className='messageBox'>                     
@@ -123,7 +124,7 @@ export const ChatPage = () => {
                                     }
                                     :
                                     {
-                                        backgroundColor:  (usersOnline.map(current =>{
+                                        backgroundColor:  (usersOnline.map(current => {
                                             if(item.userName == current.userName ) {
                                                 return current.color
                                             }
@@ -143,6 +144,7 @@ export const ChatPage = () => {
                                     if(e.target.className.includes('myMessage')){
                                         e.currentTarget.className += ' editMessage' 
                                     }
+                                    //add function to edit message
                                 }}
 
                                 className={ 
@@ -187,9 +189,10 @@ export const ChatPage = () => {
                                 sx={{margin:'10px 5px'}}
                                 variant="outlined"
                                 onClick={(e)=> {
-                                        socket.disconnect()
-                                        dispatch(removeToken())
-                                        }}>
+                                            socket.disconnect();
+                                            localStorage.removeItem('token');
+                                            dispatch(removeToken());
+                                            }}>
                                 Logout
                         </Button>
 

+ 3 - 1
frontend/src/components/chatPage/chatPage.scss

@@ -28,7 +28,9 @@
     cursor: pointer;
 }
 .editMessage{
-    background-color: rgb(31, 7, 75);
+    // background-color: rgb(246, 245, 235);
+    // transform:translate(-120px, -90px);
+
 }
 
 .messageBox { 

+ 24 - 54
frontend/src/components/loginForm/LoginForm.js

@@ -3,59 +3,27 @@ import Button from '@mui/material/Button';
 import TextField from '@mui/material/TextField';
 import Container from '@mui/material/Container';
 import Box from '@mui/material/Box';
-import { useState, useEffect } from 'react';
-import { sendForm } from './utils/sendForm';
-import {isValidPayload} from './utils/validations/isValidPayload';
-import {isValidUserName} from './utils/validations/isValidUserName';
-import { Modal } from '../modal/Modal';
+import { Modal } from '../modalMessage/Modal';
 import { useDispatch, useSelector } from 'react-redux';
-import { storeToken, removeToken } from '../../actions/actions';
-import { store } from '../../store';
+import { useEffect } from 'react';
+import  {setUserName, setUserPassword, getUserData} from '../../reducers/userDataReducer'
 
 export const LoginForm = () => {
 
-
     const dispatch = useDispatch();
-
-    const [userData, setUserdata] = useState({userName:'', password: ''});
-    const [textModal, setTextModal] = useState('')
-    const [display, setDisplay] = useState('none');
-
-    const POST_URL =  process.env.REACT_APP_POST_URL || 'http://localhost:5000/login';//add on handlesubmit
-
-    const handleSubmit = async (e) => {
-
-        e.preventDefault();
-
-        if(isValidPayload({...userData}) && isValidUserName({...userData})){
-            const data = await sendForm(POST_URL, userData);
-            const token = data.token;
-            if(token){
-                
-                localStorage.setItem('token', token); 
-                dispatch(storeToken(token))
-            }
-            setTextModal(data.message)
-            setDisplay('block')
-            setUserdata({userName:'', password: ''});
-        } else {
-            setTextModal('too short or using special symbols')
-            setDisplay('block')
-        }   
-    }
-
-    useEffect(()=>{
-        return () => {
-            setUserdata({userName:'', password: ''})
-        }
-    }, [])
-
-
+    const userName = useSelector(state => state.userName);
+    const password = useSelector(state => state.password);
+   console.log('logform', userName)
     return (
         <Container maxWidth="xs">
             <Box
                 component="form" 
-                onSubmit={(e) => handleSubmit(e)}
+                onSubmit={(e) => {
+                    e.preventDefault();
+                    console.log('submit', userName)
+                   dispatch(getUserData())
+            }
+                }
                 sx={{
                     marginTop: 40,
                     display: 'flex',
@@ -71,11 +39,8 @@ export const LoginForm = () => {
                         name="userName"
                         autoComplete="email"
                         autoFocus
-                        value={userData.userName}
-                        onChange={e => {
-                            setUserdata({...userData, userName: e.target.value})
-                            setDisplay('none')
-                        }}
+                        value={userName}
+                        onChange={e => dispatch(setUserName({userName: e.target.value}))}
                 />
                 <TextField
                         margin="normal"
@@ -86,18 +51,23 @@ export const LoginForm = () => {
                         type="password"
                         id="password"
                         autoComplete="current-password"
-                        value={userData.password}
-                        onChange={e => setUserdata({...userData, password: e.target.value})}
+                        value={password}
+                        onChange={e => 
+                            
+                            dispatch(setUserPassword({password: e.target.value}))
+                        }
                 />
                 <Modal 
-                    text={textModal}
-                    propDisplay = {display}
+                    //text={textModal}
+                    //propDisplay = {display}
                 
                 ></Modal>
                 <Button 
                     type="submit"
                     variant="contained"
-                    fullWidth>Login
+                    fullWidth
+                   >Login
+                    
                 </Button>
             </Box>
         </Container>

+ 27 - 19
frontend/src/components/loginForm/utils/handleSubmit.js

@@ -1,19 +1,27 @@
-export const handleSubmit = async (e, POST_URL, userData) => {
-    e.preventDefault();
-    if(isValidPayload({...userData}) && isValidUserName({...userData})){
-        const data = await sendForm(POST_URL, userData);
-        const token = data.token;
-        if(token){
-            onSubmit(token);     
-        }
-        setTextModal(data.message)
-        setDisplay('block')
-        setUserdata({userName:'', password: ''});
-        
-        
-    } else {
-        setTextModal('too short or using special symbols')
-        setDisplay('block')
-    }
-    
-}
+// import { isValidPayload } from './validations/isValidPayload';
+// import { isValidUserName } from './validations/isValidUserName';
+// import { sendForm } from './sendForm';
+
+
+// export const handleSubmit = async (e, userName , password) => {
+//     console.log(userName,password)
+//     const POST_URL =  process.env.REACT_APP_POST_URL || 'http://localhost:5000/login';//add on handlesubmit
+//     e.preventDefault();
+
+//     if(isValidPayload(userName,password) && isValidUserName(userName)){
+//         const data = await sendForm(POST_URL, userName, password);
+//         const token = data.token;
+//        if(token){
+//            localStorage.setItem('token', token); 
+//           // dispatch(storeToken(token))
+//        }
+//         // setTextModal(data.message)
+//         // setDisplay('block')
+       
+//         console.log(userName,password)
+//    } 
+// //    else {
+// //       //  setTextModal('too short or using special symbols')
+// //        // setDisplay('block')
+// //     }   
+// }

+ 2 - 6
frontend/src/components/loginForm/utils/sendForm.js

@@ -1,16 +1,12 @@
 export const sendForm = async (POST_URL, userData) => {
-    try {
+    console.log('sendform', userData)
         const response = await fetch(POST_URL, {
             method: 'POST',
             body: JSON.stringify(userData),
             headers: {
                 'Content-Type': 'application/json'
             }
-        });
+});
         const json = await response.json();
         return json;
-
-    } catch (e) {
-        console.log('Error:', e)
-    }
 }

frontend/src/components/modal/Modal.js → frontend/src/components/modalMessage/Modal.js


+ 0 - 0
frontend/src/reducers/index.js


+ 22 - 0
frontend/src/reducers/socketReducer.js

@@ -0,0 +1,22 @@
+const initialState = {
+    socket: null
+  }
+  
+const socketReducer = (state = initialState, action) => {
+    switch (action.type){
+    case 'SET_SOCKET':  
+        return {...state, 
+            socket:
+              action.socket
+            };
+    case 'REMOVE_SOCKET':  
+        return {...state, 
+            socket: 
+              initialState.socket
+            };
+    default:
+      return state
+    }
+  };
+
+ export default socketReducer;

+ 2 - 2
frontend/src/reducers/reducer.js

@@ -2,7 +2,7 @@ const initialState = {
     token: ''
   }
   
-const reducer = (state = initialState, action) => {
+const tokenReducer = (state = initialState, action) => {
     switch (action.type){
     case 'SET_TOKEN':  
         return {...state, 
@@ -19,4 +19,4 @@ const reducer = (state = initialState, action) => {
     }
   };
 
- export default reducer;
+ export default tokenReducer;

+ 65 - 0
frontend/src/reducers/userDataReducer.js

@@ -0,0 +1,65 @@
+import { isValidPayload } from "../components/loginForm/utils/validations/isValidPayload";
+import { isValidUserName } from '../components/loginForm/utils/validations/isValidUserName';
+import { sendForm } from '../components/loginForm/utils/sendForm';
+import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
+
+const initialState = {
+    userName:'',
+    password: '',
+    userLoadingStatus: 'idle',
+    token: '',
+    socket: null,
+    responseMessage: ''
+}
+
+
+const POST_URL =  process.env.REACT_APP_POST_URL || 'http://localhost:5000/login';
+
+export const getUserData = createAsyncThunk(
+    'userData/getUser',
+     ( t , thunkAPI) => {
+      const userData = thunkAPI.getState().userDataReducer;
+          if(userData.userName){
+        if(isValidPayload({...userData}) && isValidUserName({...userData}))
+            console.log('getUserData', userData)
+            try {
+                const response =  sendForm(POST_URL, userData);
+                return response;
+            }catch (err) {
+                return err?.message
+            }
+        }
+    });
+
+const getUserDataSlice = createSlice({
+    name: 'userData',
+    initialState,
+    reducers: {
+        setUserName: (state, action) => {state.userName = action.payload.userName},
+        setUserPassword: (state, action) => {state.password = action.payload.password},
+        removeToken: (state, action) => {state.token = ''}
+    },
+    extraReducers: (builder) => { 
+       builder
+          .addCase(getUserData.fulfilled, (state, action) => {
+            state.userLoadingStatus = 'fulfilled'
+            state.token = action.payload
+            localStorage.setItem('token', action.payload.token)
+            console.log('fulfilled',action.payload.token)
+          })
+           .addCase(getUserData.rejected, (state) => {
+               state.userLoadingStatus = 'error';
+               console.log('rejected', state)
+          })
+        }
+});
+
+const {actions, reducer} = getUserDataSlice;
+const userDataReducer = reducer;
+
+export default userDataReducer;
+export const {
+    setUserName,
+    setUserPassword,
+    removeToken
+} = actions;

+ 13 - 10
frontend/src/store.js

@@ -1,11 +1,14 @@
-import reducer from './reducers/reducer';
-import thunk from 'redux-thunk';
-import { createStore, compose, applyMiddleware } from 'redux';
-
-export const store = createStore(reducer, compose(
-  applyMiddleware(
-    thunk,
-  ),
-//  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
-));
+import tokenReducer from './reducers/tokenReducer';
+import socketReducer from './reducers/socketReducer';
+import userDataReducer from './reducers/userDataReducer';
+
+import { configureStore } from '@reduxjs/toolkit'
+
+
+export  const store = configureStore({
+    reducer: {tokenReducer, socketReducer, userDataReducer},
+    middleware: getDefaultMiddleware => getDefaultMiddleware(),
+    devTools: process.env.NODE_ENV !== 'production',
+})
+