diff --git a/src/components/forms/formGenerator.js b/src/components/forms/formGenerator.js index efba6d5..300da2d 100644 --- a/src/components/forms/formGenerator.js +++ b/src/components/forms/formGenerator.js @@ -13,48 +13,58 @@ export const FormGenerator = ({ const handler = async (event) => { event.preventDefault() - for ( let i = 0; i < refList.length; i++ ) { - if ( - refList[i].current.value === '' + for (let i = 0; i < refList.length; i++) { + if (refList[i].current.value === '' && inputList[0].action !== 'Update' - || i === 0 && refList.length !== 1 + || i === 0 + && refList.length !== 1 ) { refList[i].current.focus() - } else if ( i === refList.length - 1 ) { - await action( refList ) + } else if (i === refList.length - 1) { + await action(refList) } } } - + let info return ( -
handler( event ) }> - { - inputList.map( (input, key) => { - - if ( input.type === 'info' ) { + handler(event)}> + { + inputList.map((input, key) => { + + if (input.type === 'info') { info = input - } else if ( input.type === 'text' ) { - return ( - - ) - } else if ( input.type === 'file' ) { + } else if (input.type === 'text') { return ( - + ) + } else if (input.type === 'password') { + return ( + + ) + } else if (input.type === 'file') { + return ( + ) } - }) + }) } - ) } @@ -74,16 +84,47 @@ export const FormGenerator = ({ * endpoint: 'Album' * } } info - information about form */ -const TextInputGenerator = ({ +const TextInputGenerator = ({ input, info }) => { return (
- { input.name + ':' } - +
+ ) +} + +/** + * Text input generator, example: + * @param { + * { + * type: 'password', + * name: 'name', + * ref: React.createRef() + * } } input - basic text input + * @param { + * { + * type: 'info', + * action: 'Update' + * endpoint: 'Album' + * } } info - information about form + */ +const PasswordInputGenerator = ({ + input, info +}) => { + return ( +
+ {input.name + ':'} +
) @@ -101,55 +142,55 @@ const TextInputGenerator = ({ * file: file, setFile: setFile() #useState * } } input - */ -const UploadInputGenerator = ({ +const UploadInputGenerator = ({ input, info }) => { - - const onLoadFile = async ( event ) => { + + const onLoadFile = async (event) => { event.preventDefault() let data = event.target.files[0] - input.setFile( await toBase64( data ) ) + input.setFile(await toBase64(data)) setDropInfos(data.name, data.size) } - const onLoadFileDrop = async ( event ) => { + const onLoadFileDrop = async (event) => { event.preventDefault() event.persist() let data = event.dataTransfer.files[0] - input.setFile( await toBase64( data ) ) + input.setFile(await toBase64(data)) setDropInfos(data.name, data.size) } - const toBase64 = ( file ) => new Promise( (resolve, reject) => { + const toBase64 = (file) => new Promise((resolve, reject) => { let fileReader = new FileReader() - fileReader.readAsDataURL( file ) - fileReader.onload = () => resolve( fileReader.result ) - fileReader.onerror = error => reject( error ) + fileReader.readAsDataURL(file) + fileReader.onload = () => resolve(fileReader.result) + fileReader.onerror = error => reject(error) }) const setDropInfos = (name, size) => { - input.setDropInfo( - 'name: "' - + name - + '"\nsize: ' - + (Math.round(size / 100 + 'e-2') / 100 ) - + ' MB' + input.setDropInfo( + 'name: "' + + name + + '"\nsize: ' + + (Math.round(size / 100 + 'e-2') / 100) + + ' MB' ) } return ( -
onLoadFileDrop( event ) } > -
-                { input.dropInfo }
+        
onLoadFileDrop(event)} > +
+                {input.dropInfo}
             
- onLoadFile( event ) } + onChange={event => onLoadFile(event)} />
) diff --git a/src/components/forms/user_auth/userLogin.js b/src/components/forms/user_auth/userLogin.js index e69de29..77fd589 100644 --- a/src/components/forms/user_auth/userLogin.js +++ b/src/components/forms/user_auth/userLogin.js @@ -0,0 +1,66 @@ +import React, { useState, useEffect } from 'react' + +import { useSelector, useDispatch } from 'react-redux' + +import { userAuthSelector } from '../../../redux/slices/userAuthSlice' +import userAuthAsyncThunk from '../../../redux/asyncThunks/userAuthAsyncThunk' + +import FormGenerator from '../formGenerator' + + +const UserLoginForm = () => { + + const usernameInput = React.createRef() + const passwordInput = React.createRef() + + const dispatch = useDispatch() + + let refList = [ + usernameInput, + passwordInput + ] + + let inputList = [ + { + type: 'info', + action: 'Create', + endpint: 'user/auth/login', + button_value: 'Sign In' + }, + { + type: 'text', + name: 'Username', + ref: usernameInput + }, + { + type: 'password', + name: 'Password', + ref: passwordInput + } + ] + + const login = async ( refs ) => { + let pass = { + username: refs[0].current.value, + password: refs[1].current.value + } + dispatch( + userAuthAsyncThunk.fetchLogin( + pass + ) + ) + } + + return ( + <> + + + ) + +} + +export default UserLoginForm \ No newline at end of file diff --git a/src/components/forms/user_auth/userRegister.js b/src/components/forms/user_auth/userRegister.js index e69de29..eadeedd 100644 --- a/src/components/forms/user_auth/userRegister.js +++ b/src/components/forms/user_auth/userRegister.js @@ -0,0 +1,74 @@ +import React, { useState, useEffect } from 'react' + +import { useSelector, useDispatch } from 'react-redux' + +import { userCrudSelector } from '../../../redux/slices/userCrudSlice' +import userCrudAsyncThunk from '../../../redux/asyncThunks/userCrudAsyncThunk' + +import FormGenerator from '../formGenerator' + + +const UserRegisterForm = () => { + + const usernameInput = React.createRef() + const passwordInput = React.createRef() + const emailInput = React.createRef() + + const dispatch = useDispatch() + + let refList = [ + usernameInput, + passwordInput, + emailInput + ] + + let inputList = [ + { + type: 'info', + action: 'Create', + endpint: 'user/auth/login', + button_value: 'Sign In' + }, + { + type: 'text', + name: 'Username', + ref: usernameInput + }, + { + type: 'password', + name: 'Password', + ref: passwordInput + }, + { + type: 'text', + name: 'Email', + ref: emailInput + } + ] + + const register = async ( refs ) => { + let pass = { + username: refs[0].current.value, + password: refs[1].current.value, + email: refs[2].current.value, + } + dispatch( + userCrudAsyncThunk.fetchRegister( + pass + ) + ) + } + + return ( + <> + + + ) + +} + +export default UserRegisterForm \ No newline at end of file diff --git a/src/pages/func_group/rootUtils.js b/src/pages/func_group/rootUtils.js index c7d194a..7786566 100644 --- a/src/pages/func_group/rootUtils.js +++ b/src/pages/func_group/rootUtils.js @@ -80,7 +80,7 @@ const __verifyUserSession = (token, user) => { if ( user.id !== 0 && user.username !== '' && user.email !== '' && token !== '' ) return true else - return true + return false } diff --git a/src/pages/func_group/user_auth/userAuthIndex.js b/src/pages/func_group/user_auth/userAuthIndex.js index b6ab53a..942d191 100644 --- a/src/pages/func_group/user_auth/userAuthIndex.js +++ b/src/pages/func_group/user_auth/userAuthIndex.js @@ -1,9 +1,13 @@ import React, { useState, useEffect } from 'react' +import UserLoginForm from '../../../components/forms/user_auth/userLogin' + + const UserAuthIndex = () => { return (
+
) } diff --git a/src/redux/asyncThunks/abstracts/abstractService.js b/src/redux/asyncThunks/abstracts/abstractService.js index 3866e1f..816e130 100644 --- a/src/redux/asyncThunks/abstracts/abstractService.js +++ b/src/redux/asyncThunks/abstracts/abstractService.js @@ -74,31 +74,53 @@ const responseAbstract = async (endpoint, method, token, body) => { const headerBuilder = (url, method, token, body) => { let headers_r = { - 'Authorization': token, + 'authorization': token, + 'x-csrftoken': getCookie('csrftoken'), 'accept': 'application/json', - 'Content-Type': 'application/json', + 'content-type': 'application/json', } if ('file' in body) { headers_r = { - 'Authorization': token, + 'authorization': token, + 'x-csrftoken': getCookie('csrftoken'), 'accept': 'multipart/form-data', - 'Content-Type': 'multipart/form-data', + 'content-type': 'multipart/form-data', } } let headers = { url: url, method: method, - headers: headers_r + headers: headers_r, + credentials: 'same-origin' } if (method === 'PUT' || method === 'POST' || method === 'PATCH') { headers = Object.assign({}, headers, { data: JSON.stringify(body), - withCredentials: true, }) } + console.log(headers) return headers } +/** + * get cookie method for CSRF verification + * @param {string} name - name of handled cookie + */ +const getCookie = (name) => { + if (!document.cookie) { + return null; + } + const token = document.cookie.split(';') + .map(c => c.trim()) + .filter(c => c.startsWith(name + '=')); + + if (token.length === 0) { + return null; + } + return decodeURIComponent(token[0].split('=')[1]); +} + + export default { APIAddress, diff --git a/src/redux/slices/userAuthSlice.js b/src/redux/slices/userAuthSlice.js index b4b8fe0..124792a 100644 --- a/src/redux/slices/userAuthSlice.js +++ b/src/redux/slices/userAuthSlice.js @@ -15,11 +15,15 @@ const userAuthSlice = createSlice( reducers: {}, extraReducers: { [userAuthAsyncThunk.fetchLogin.fulfilled.type]: (state, action) => { - state.token = action.payload.data.Authorization - state.user.id = action.payload.data.user.id - state.user.username = action.payload.data.user.username - state.user.email = action.payload.data.user.email - state.info = 'login success' + try { + state.token = action.payload.data.Authorization + state.user.id = action.payload.data.user.id + state.user.username = action.payload.data.user.username + state.user.email = action.payload.data.user.email + state.info = 'login success' + } catch { + state.info = 'login failed' + } }, [userAuthAsyncThunk.fetchLogout.fulfilled.type]: (state, action) => { state.token = ''