我有一个要求,第一次用户登录后会看到一个他们需要同意的弹出窗口。我在Cognito中创建了一个标记为“是”的自定义属性,直到用户单击“同意”按钮。所有这些逻辑均有效,除了刷新页面时,尽管用户同意并在Cognito中更改了属性,但仍会再次向用户显示弹出窗口。
我正在使用带有useContext钩子的React上下文api。我在React工具中注意到上下文没有得到更新,这可能是问题所在。
AuthContext.js
import React from 'react';
export const AuthContext = React.createContext();
export const AuthProvider = AuthContext.Provider;
App.js
import React from 'react';
import { withRouter } from 'react-router-dom';
import Header from './components/Header';
import Routes from './Routes';
import useAmplifyAuth from './libs/useAmplifyAuth';
import { AuthProvider } from './context/AuthContext';
import InitialLoginModal from './components/InitialLoginModal';
function App() {
const {
state: { user },
handleSignout
} = useAmplifyAuth();
return (
<>
<AuthProvider value={{ user, handleSignout }}>
<>
<Header />
<Routes />
<InitialLoginModal />
</>
</AuthProvider>
</>
);
}
export default withRouter(App);
InitialLoginModal.js
import React, { useContext, useState, useEffect } from 'react';
import { Modal, Button, Image } from 'react-bootstrap';
import { Auth } from 'aws-amplify';
import imgLogo from '../img/logo.jpg';
import { AuthContext } from '../context/AuthContext';
const InitialLoginModal = () => {
const { user, handleSignout } = useContext(AuthContext);
const [showModal, setShowModal] = useState(false);
const [initialLogin, setInitialLogin] = useState('');
const noAccept = () => {
setShowModal(false);
handleSignout();
};
useEffect(() => {
if (user) {
console.log(user.attributes['custom:initiallogin']);
if (user.attributes['custom:initiallogin'] === 'Yes') {
setShowModal(true);
}
}
}, [user]);
const accept = () => {
updateInitialLogin();
setShowModal(false);
};
const updateInitialLogin = async () => {
await Auth.updateUserAttributes(user, { 'custom:initiallogin': 'No' });
setInitialLogin('No');
setShowModal(false);
};
return (
<>
{/* Initial login modal */}
<Modal
show={showModal}
onHide={noAccept}
dialogClassName="modal-70w modal-item"
aria-labelledby="Initial Login Modal"
>
<Modal.Header closeButton>
<Modal.Title>
<Image
src={imgLogo}
alt="Logo"
fluid
className="modal-image-center"
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
Text that I must agree to.
</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={accept}>Next</Button>
</Modal.Footer>
</Modal>
</>
);
};
export default InitialLoginModal;
useAmplifyAuth.js
import { useReducer, useState, useEffect } from 'react';
import { Auth, Hub } from 'aws-amplify';
const amplifyAuthReducer = (state, action) => {
switch (action.type) {
case 'FETCH_USER_DATA_INIT':
return {
...state,
isLoading: true,
isError: false
};
case 'FETCH_USER_DATA_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
user: action.payload.user
};
case 'FETCH_USER_DATA_FAILURE':
return { ...state, isLoading: false, isError: true };
case 'RESET_USER_DATA':
return { ...state, user: null };
default:
throw new Error();
}
};
const useAmplifyAuth = () => {
const initialState = {
isLoading: true,
isError: false,
user: null
};
const [state, dispatch] = useReducer(amplifyAuthReducer, initialState);
const [triggerFetch, setTriggerFetch] = useState(false);
useEffect(() => {
let isMounted = true;
const fetchUserData = async () => {
if (isMounted) {
dispatch({ type: 'FETCH_USER_DATA_INIT' });
}
try {
if (isMounted) {
const data = await Auth.currentAuthenticatedUser();
if (data) {
dispatch({
type: 'FETCH_USER_DATA_SUCCESS',
payload: { user: data }
});
}
}
} catch (error) {
if (isMounted) {
dispatch({ type: 'FETCH_USER_DATA_FAILURE' });
}
}
};
const HubListener = () => {
Hub.listen('auth', data => {
const { payload } = data;
onAuthEvent(payload);
});
};
const onAuthEvent = payload => {
switch (payload.event) {
case 'signIn':
if (isMounted) {
setTriggerFetch(true);
console.log('signed in');
}
break;
default:
return;
}
};
HubListener();
fetchUserData();
return () => {
Hub.remove('auth');
isMounted = false;
};
}, [triggerFetch]);
const handleSignout = async () => {
try {
console.log('signed out');
await Auth.signOut();
setTriggerFetch(false);
dispatch({ type: 'RESET_USER_DATA' });
} catch (error) {
console.error('Error signing out user ', error);
}
};
return { state, handleSignout };
};
export default useAmplifyAuth;
最后,我只需要用户能够同意这些条款,更新其自定义属性,然后不再向其提供模态。任何帮助,将不胜感激。谢谢。
import React, { useContext, useEffect, useState } from 'react';
import { Modal, Button, Image } from 'react-bootstrap';
import { Auth } from 'aws-amplify';
import imgLogo from '../img/logo.jpg';
import { AuthContext } from '../context/AuthContext';
const InitialLoginModal = () => {
const {
user,
handleSignout,
shouldShowModal,
setShouldShowModal
} = useContext(AuthContext);
const [showModal, setShowModal] = useState(shouldShowModal);
// const [initialLogin, setInitialLogin] = useState('');
const noAccept = () => {
setShowModal(false);
handleSignout();
};
useEffect(() => {
if (user) {
if (user.attributes['custom:initiallogin'] === 'Yes') {
setShowModal(true);
}
}
}, [user, setShouldShowModal]);
const accept = () => {
updateInitialLogin();
// setShouldShowModal(false);
};
const updateInitialLogin = async () => {
if (user) {
await Auth.updateUserAttributes(user, { 'custom:initiallogin': 'No' });
setShowModal(false);
}
};
return (
<>
{/* Initial login modal */}
<Modal
show={showModal}
onHide={noAccept}
dialogClassName="modal-70w modal-item"
aria-labelledby="Initial Login Modal"
>
<Modal.Header closeButton>
<Modal.Title>
<Image
src={imgLogo}
alt="Logo"
fluid
className="modal-image-center"
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
Info here
</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={accept}>Next</Button>
</Modal.Footer>
</Modal>
</>
);
};
export default InitialLoginModal;
答案 0 :(得分:1)
我本人只是遇到了这个问题,我认为这是需要更新的行:
<?php
namespace REDACTED\REDACTEDVeranstaltungen\Routing\Aspect;
use TYPO3\CMS\Core\Routing\Aspect\PersistedMappableAspectInterface;
use TYPO3\CMS\Core\Site\SiteLanguageAwareTrait;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
class TerminValueMapper implements PersistedMappableAspectInterface
{
use SiteLanguageAwareTrait;
/**
* @param string $value
*
* @return string|null
*/
public function generate(string $value): ?string
{
if($uid=intval($value)){
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_REDACTEDveranstaltungen_domain_model_termin');
$statement = $queryBuilder
->select('t.uid', 'v.titel', 'v.urltitel', 't.beginn')
->from('tx_REDACTEDveranstaltungen_domain_model_termin','t')
->leftJoin('t', 'tx_REDACTEDveranstaltungen_domain_model_veranstaltung', 'v', 't.veranstaltung = v.uid')
->where(
$queryBuilder->expr()->eq('t.uid', $uid)//$queryBuilder->createNamedParameter('horst')
)
->execute();
if($record = $statement->fetch()){
if(is_array($record) && mb_strlen(trim($record['urltitel']))){
$beginn = new \DateTime();
$beginn->setTimestamp(intval($record['beginn']));
return $uid.'--'.str_replace('--', '-', $record['urltitel'].'-'.$beginn->format('d-m-Y') );
}
}
}
return $value;
}
/**
* @param string $value
*
* @return string|null
*/
public function resolve(string $value): ?string
{
return intval(explode('--',$value)[0]);
}
}
收件人:
routeEnhancers:
REDACTEDveranstaltungen_veranstaltungen:
type: Extbase
extension: REDACTEDVeranstaltungen
plugin: Veranstaltungen
routes:
- { routePath: '/themenbereiche/{thema_titel}', _controller: 'Termin::search', _arguments: {'thema_titel': 'veranstaltungsarten/0'} }
- { routePath: '/veranstaltung/{termin_titel}', _controller: 'Veranstaltung::show', _arguments: {'termin_titel': 'termin'} }
aspects:
termin_titel:
#type: PersistedAliasMapper
#tableName: 'tx_REDACTEDveranstaltungen_domain_model_termin'
#routeFieldName: 'uid'
type: TerminValueMapper
thema_titel:
type: PersistedAliasMapper
tableName: 'sys_category'
routeFieldName: 'title'
这将直接从Cognito检索更新的属性,以便当属性设置为custom:initiallogin ='No'时,不会向用户显示模式。
答案 1 :(得分:0)
不确定这是否正确,但是您应该在上下文中确定一个状态,以决定是否应显示模式。
function App() {
const [shouldShowModal, setShouldShowModal] = useState(true) // you can choose if you want true or false
const {
state: { user },
handleSignout
} = useAmplifyAuth();
return (
<>
<AuthProvider value={{ user, handleSignout, shouldShowModal, setShouldShowModal }}>
<>
<Header />
<Routes />
<InitialLoginModal />
</>
</AuthProvider>
</>
);
}
showModal
的默认值应来自上下文。
const InitialLoginModal = () => {
const { user, handleSignout, shouldShowModal, setShouldShowModal } = useContext(AuthContext);
const [showModal, setShowModal] = useState(shouldShowModal );
...
}
然后您可以使用setShouldShowModal
做更多的事情,因此在获得身份验证时,您可以选择是否显示该身份。
答案 2 :(得分:0)
在cognito AWS界面的“ oauth范围”下为需要访问数据的应用程序客户端选择“配置文件”。