浏览代码

Added google login button and API call

feature/google_login
Safet Purkovic 3 年前
父节点
当前提交
50c9d692ff

+ 11
- 0
package-lock.json 查看文件

"i18next": "^20.3.1", "i18next": "^20.3.1",
"json-server": "^0.17.0", "json-server": "^0.17.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lodash.isempty": "^4.4.0", "lodash.isempty": "^4.4.0",
"owasp-password-strength-test": "^1.3.0", "owasp-password-strength-test": "^1.3.0",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"keyv": { "keyv": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",

+ 1
- 0
package.json 查看文件

"i18next": "^20.3.1", "i18next": "^20.3.1",
"json-server": "^0.17.0", "json-server": "^0.17.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lodash.isempty": "^4.4.0", "lodash.isempty": "^4.4.0",
"owasp-password-strength-test": "^1.3.0", "owasp-password-strength-test": "^1.3.0",

+ 1
- 0
public/index.html 查看文件

Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>React App</title> <title>React App</title>
<script src="https://accounts.google.com/gsi/client" async defer></script>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

+ 31
- 0
src/pages/LoginPage/LoginPageMUI.js 查看文件

import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import HrLogo from "../../assets/images/hrcenter.png"; import HrLogo from "../../assets/images/hrcenter.png";
import DiligLogo from "../../assets/images/logo_horizontal_black.png"; import DiligLogo from "../../assets/images/logo_horizontal_black.png";
import jwt_decode from 'jwt-decode';
import googleLogo from "../../assets/images/google1.png"; import googleLogo from "../../assets/images/google1.png";
import { import {
clearLoginErrors, clearLoginErrors,
fetchUser, fetchUser,
fetchGoogleUser
} from "../../store/actions/login/loginActions"; } from "../../store/actions/login/loginActions";
import { selectLoginError } from "../../store/selectors/loginSelectors"; import { selectLoginError } from "../../store/selectors/loginSelectors";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages"; import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages";
// redirectClient(); // redirectClient();
// }, [history]); // }, [history]);


const handleCallbackResponse = (response) => {
console.log(response.credential);
const userObject = jwt_decode(response.credential);
console.log(userObject);
const username = userObject.email;
dispatch(clearLoginErrors());
dispatch(
fetchGoogleUser({
username,
handleApiResponseSuccess,
})
);
}

const isLoading = useSelector( const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING) selectIsLoadingByActionType(LOGIN_USER_LOADING)
); );
); );
}; };


const handleGoogleSubmit = (values) => {
/* global google */
google.accounts.id.initialize({
client_id: "734219382849-nvnulsu7ibfl4bk3n164bgb7c1h5dgca.apps.googleusercontent.com",
callback: handleCallbackResponse
});

google.accounts.id.renderButton(
document.getElementById("signInDiv"),
{ theme: "outline", size: "large"}
);
};

const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
username: "", username: "",
<Button <Button
className="c-btn c-btn--gray flex-center" className="c-btn c-btn--gray flex-center"
sx={{ width: "100%", mt: 2 }} sx={{ width: "100%", mt: 2 }}
onClick={handleGoogleSubmit}
> >
<img src={googleLogo} style={{ marginRight: "15px" }} /> <img src={googleLogo} style={{ marginRight: "15px" }} />
<Typography sx={{ m: 0, p: 0 }} variant="buttonText"> <Typography sx={{ m: 0, p: 0 }} variant="buttonText">
</div> </div>
</Box> </Box>
</Box> </Box>
<div id='signInDiv'></div>
</Container> </Container>
); );
}; };

+ 4
- 1
src/request/apiEndpoints.js 查看文件

const base = "http://localhost:26081/v1";

export default { export default {
authentications: { authentications: {
login: 'http://localhost:26081/v1/users/authenticate',
login: base + '/users/authenticate',
googleLogin: base + '/users/authenticateGoogle',
}, },
}; };

+ 3
- 0
src/request/loginRequest.js 查看文件

export const attemptLogin = (payload) => export const attemptLogin = (payload) =>
postRequest(apiEndpoints.authentications.login, payload); postRequest(apiEndpoints.authentications.login, payload);


export const attemptGoogleLogin = (payload) =>
postRequest(apiEndpoints.authentications.googleLogin, payload);

export const updateSecurityAnswer = (payload) => export const updateSecurityAnswer = (payload) =>
postRequest(apiEndpoints.authentications.confirmSecurityQuestion, payload); postRequest(apiEndpoints.authentications.confirmSecurityQuestion, payload);



+ 9
- 0
src/store/actions/login/loginActionConstants.js 查看文件

); );
export const LOGIN_USER_LOADING = createLoadingType(LOGIN_USER_SCOPE); export const LOGIN_USER_LOADING = createLoadingType(LOGIN_USER_SCOPE);


const LOGIN_GOOGLE_USER_SCOPE = 'LOGIN_GOOGLE_USER';
export const LOGIN_GOOGLE_USER_FETCH = createFetchType(LOGIN_GOOGLE_USER_SCOPE);
export const LOGIN_GOOGLE_USER_SUCCESS = createSuccessType(LOGIN_GOOGLE_USER_SCOPE);
export const LOGIN_GOOGLE_USER_ERROR = createErrorType(LOGIN_GOOGLE_USER_SCOPE);
export const CLEAR_LOGIN_GOOGLE_USER_ERROR = createClearType(
`${LOGIN_GOOGLE_USER_SCOPE}_ERROR`,
);
export const LOGIN_GOOGLE_USER_LOADING = createLoadingType(LOGIN_USER_SCOPE);



export const UPDATE_USER_JWT_TOKEN = 'UPDATE_USER_JWT_TOKEN'; export const UPDATE_USER_JWT_TOKEN = 'UPDATE_USER_JWT_TOKEN';
export const RESET_LOGIN_STATE = 'RESET_LOGIN_STATE'; export const RESET_LOGIN_STATE = 'RESET_LOGIN_STATE';

+ 18
- 0
src/store/actions/login/loginActions.js 查看文件

LOGIN_USER_ERROR, LOGIN_USER_ERROR,
LOGIN_USER_FETCH, LOGIN_USER_FETCH,
LOGIN_USER_SUCCESS, LOGIN_USER_SUCCESS,
LOGIN_GOOGLE_USER_ERROR,
LOGIN_GOOGLE_USER_FETCH,
LOGIN_GOOGLE_USER_SUCCESS,
LOGOUT_USER, LOGOUT_USER,
RESET_LOGIN_STATE, RESET_LOGIN_STATE,
UPDATE_USER_JWT_TOKEN, UPDATE_USER_JWT_TOKEN,
payload, payload,
}); });


export const fetchGoogleUser = (payload) => ({
type: LOGIN_GOOGLE_USER_FETCH,
payload,
});

export const fetchUserSuccess = (payload) => ({ export const fetchUserSuccess = (payload) => ({
type: LOGIN_USER_SUCCESS, type: LOGIN_USER_SUCCESS,
payload, payload,
}); });


export const fetchGoogleUserSuccess = (payload) => ({
type: LOGIN_GOOGLE_USER_SUCCESS,
payload,
});

export const fetchUserError = (payload) => ({ export const fetchUserError = (payload) => ({
type: LOGIN_USER_ERROR, type: LOGIN_USER_ERROR,
payload, payload,
}); });


export const fetchGoogleUserError = (payload) => ({
type: LOGIN_GOOGLE_USER_ERROR,
payload,
});

export const updateUserToken = (payload) => ({ export const updateUserToken = (payload) => ({
type: UPDATE_USER_JWT_TOKEN, type: UPDATE_USER_JWT_TOKEN,
payload, payload,

+ 28
- 0
src/store/saga/loginSaga.js 查看文件

import history from '../utils/history'; import history from '../utils/history';
import { import {
AUTHENTICATE_USER, AUTHENTICATE_USER,
LOGIN_GOOGLE_USER_FETCH,
LOGIN_USER_FETCH, LOGIN_USER_FETCH,
LOGOUT_USER, LOGOUT_USER,
REFRESH_TOKEN, REFRESH_TOKEN,
GENERATE_TOKEN, GENERATE_TOKEN,
} from '../actions/login/loginActionConstants'; } from '../actions/login/loginActionConstants';
import { import {
attemptGoogleLogin,
attemptLogin, attemptLogin,
logoutUserRequest, logoutUserRequest,
refreshTokenRequest, refreshTokenRequest,
} }
} }
} }
function* fetchGoogleUser({ payload }) {
try {
const { data } = yield call(attemptGoogleLogin, payload);
if (data.token) {
const user = jwt.decode(data.token);
yield call(authScopeSetHelper, JWT_TOKEN, data.token);
yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken);
yield call(authScopeSetHelper, REFRESH_TOKEN_CONST, data.RefreshToken);
yield call(addHeaderToken, data.token);
yield put(setUser(user));
}
yield put(fetchUserSuccess(data));
if (payload.handleApiResponseSuccess) {
yield call(payload.handleApiResponseSuccess);
}
} catch (e) {
if (e.response && e.response.data) {
if (payload.handleApiResponseFailed) {
yield call(payload.handleApiResponseFailed);
}
const errorMessage = yield call(rejectErrorCodeHelper, e);
yield put(fetchUserError(errorMessage));
}
}
}
function* authenticateUser() { function* authenticateUser() {
try { try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
export default function* loginSaga() { export default function* loginSaga() {
yield all([ yield all([
takeLatest(LOGIN_USER_FETCH, fetchUser), takeLatest(LOGIN_USER_FETCH, fetchUser),
takeLatest(LOGIN_GOOGLE_USER_FETCH, fetchGoogleUser),
takeLatest(AUTHENTICATE_USER, authenticateUser), takeLatest(AUTHENTICATE_USER, authenticateUser),
takeLatest(LOGOUT_USER, logoutUser), takeLatest(LOGOUT_USER, logoutUser),
takeLatest(REFRESH_TOKEN, refreshToken), takeLatest(REFRESH_TOKEN, refreshToken),

+ 5
- 0
yarn.lock 查看文件

"jwa" "^1.4.1" "jwa" "^1.4.1"
"safe-buffer" "^5.0.1" "safe-buffer" "^5.0.1"


"jwt-decode@^3.1.2":
"integrity" "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
"resolved" "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz"
"version" "3.1.2"

"keyv@^3.0.0": "keyv@^3.0.0":
"integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA=="
"resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz"

正在加载...
取消
保存