Merge branch 'guest' into 'develop'

Add feature to force authentication

See merge request soapbox-pub/soapbox-fe!1400
merge-requests/1402/head
Justin 2022-05-16 22:24:53 +00:00
commit 02edd5cd36
9 zmienionych plików z 102 dodań i 18 usunięć

Wyświetl plik

@ -26,7 +26,7 @@ const useButtonStyles = ({
accent: 'border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2',
danger: 'border-transparent text-danger-700 bg-danger-100 hover:bg-danger-200 focus:ring-danger-500 focus:ring-2 focus:ring-offset-2',
transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80',
link: 'border-transparent text-primary-600 dark:text-primary-400 hover:bg-gray-100 hover:text-primary-700 dark:hover:bg-slate-900/50',
link: 'border-transparent text-primary-600 dark:text-primary-400 hover:bg-primary-100 hover:text-primary-700 dark:hover:bg-slate-900/50',
};
const sizes = {

Wyświetl plik

@ -22,6 +22,7 @@ import WaitlistPage from 'soapbox/features/verification/waitlist_page';
import { createGlobals } from 'soapbox/globals';
import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures, useSoapboxConfig, useSettings, useSystemTheme } from 'soapbox/hooks';
import MESSAGES from 'soapbox/locales/messages';
import { useCachedLocationHandler } from 'soapbox/utils/redirect';
import { generateThemeCss } from 'soapbox/utils/theme';
import { checkOnboardingStatus } from '../actions/onboarding';
@ -64,6 +65,7 @@ const loadInitial = () => {
};
const SoapboxMount = () => {
useCachedLocationHandler();
const dispatch = useAppDispatch();
const me = useAppSelector(state => state.me);

Wyświetl plik

@ -1,13 +1,14 @@
import React from 'react';
import { Link, Redirect, Route, Switch } from 'react-router-dom';
import { defineMessages, useIntl } from 'react-intl';
import { Link, Redirect, Route, Switch, useHistory } from 'react-router-dom';
import LandingGradient from 'soapbox/components/landing-gradient';
import SiteLogo from 'soapbox/components/site-logo';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import { NotificationsContainer } from 'soapbox/features/ui/util/async-components';
import { useAppSelector } from 'soapbox/hooks';
import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
import { Card, CardBody } from '../../components/ui';
import { Button, Card, CardBody } from '../../components/ui';
import LoginPage from '../auth_login/components/login_page';
import PasswordReset from '../auth_login/components/password_reset';
import PasswordResetConfirm from '../auth_login/components/password_reset_confirm';
@ -17,22 +18,52 @@ import RegisterInvite from '../register_invite';
import Verification from '../verification';
import EmailPassthru from '../verification/email_passthru';
const messages = defineMessages({
register: { id: 'auth_layout.register', defaultMessage: 'Create an account' },
});
const AuthLayout = () => {
const intl = useIntl();
const history = useHistory();
const siteTitle = useAppSelector(state => state.instance.title);
const soapboxConfig = useSoapboxConfig();
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
const features = useFeatures();
const instance = useAppSelector((state) => state.instance);
const isOpen = features.accountCreation && instance.registrations;
const pepeOpen = useAppSelector(state => state.verification.getIn(['instance', 'registrations'], false) === true);
const isLoginPage = history.location.pathname === '/login';
const shouldShowRegisterLink = (isLoginPage && (isOpen || (pepeEnabled && pepeOpen)));
return (
<div className='h-full'>
<LandingGradient />
<main className='relative min-h-full sm:flex sm:items-center sm:justify-center py-12'>
<div className='w-full sm:max-w-lg md:max-w-2xl space-y-8'>
<header className='flex justify-center relative'>
<Link to='/' className='cursor-pointer'>
<SiteLogo alt={siteTitle} className='h-7' />
</Link>
<main className='relative min-h-full sm:flex sm:justify-center'>
<div className='w-full sm:max-w-lg md:max-w-2xl lg:max-w-6xl'>
<header className='flex justify-between relative py-12 px-2'>
<div className='relative z-0 flex-1 px-2 lg:flex lg:items-center lg:justify-center lg:absolute lg:inset-0'>
<Link to='/' className='cursor-pointer'>
<SiteLogo alt={siteTitle} className='h-7' />
</Link>
</div>
{shouldShowRegisterLink && (
<div className='relative z-10 ml-auto flex items-center'>
<Button
theme='link'
icon={require('@tabler/icons/icons/user.svg')}
to='/signup'
>
{intl.formatMessage(messages.register)}
</Button>
</div>
)}
</header>
<div className='flex flex-col justify-center items-center'>
<div className='flex flex-col h-full justify-center items-center'>
<div className='pb-10 sm:mx-auto w-full sm:max-w-lg md:max-w-2xl'>
<Card variant='rounded' size='xl'>
<CardBody>

Wyświetl plik

@ -7,6 +7,7 @@ import { Redirect } from 'react-router-dom';
import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
import { fetchInstance } from 'soapbox/actions/instance';
import { closeModal } from 'soapbox/actions/modals';
import { getRedirectUrl } from 'soapbox/utils/redirect';
import { isStandalone } from 'soapbox/utils/state';
import LoginForm from './login_form';
@ -78,7 +79,10 @@ class LoginPage extends ImmutablePureComponent {
if (standalone) return <Redirect to='/login/external' />;
if (shouldRedirect) return <Redirect to='/' />;
if (shouldRedirect) {
const redirectUri = getRedirectUrl();
return <Redirect to={redirectUri} />;
}
if (mfa_auth_needed) return <OtpAuthForm mfa_token={mfa_token} />;

Wyświetl plik

@ -37,6 +37,7 @@ import RemoteInstancePage from 'soapbox/pages/remote_instance_page';
import StatusPage from 'soapbox/pages/status_page';
import { getAccessToken } from 'soapbox/utils/auth';
import { getVapidKey } from 'soapbox/utils/auth';
import { cacheCurrentUrl } from 'soapbox/utils/redirect';
import { isStandalone } from 'soapbox/utils/state';
// import GroupSidebarPanel from '../groups/sidebar_panel';
@ -278,7 +279,7 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
<WrappedRoute path='/@:username/following' publicRoute={!authenticatedProfile} component={Following} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/media' publicRoute={!authenticatedProfile} component={AccountGallery} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/tagged/:tag' exact component={AccountTimeline} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/posts/:statusId' publicRoute exact page={StatusPage} component={Status} content={children} />
<Redirect from='/@:username/:statusId' to='/@:username/posts/:statusId' />
@ -330,6 +331,7 @@ const UI: React.FC = ({ children }) => {
const intl = useIntl();
const history = useHistory();
const dispatch = useDispatch();
const { guestExperience } = useSoapboxConfig();
const [draggingOver, setDraggingOver] = useState<boolean>(false);
const [mobile, setMobile] = useState<boolean>(isMobile(window.innerWidth));
@ -479,7 +481,7 @@ const UI: React.FC = ({ children }) => {
document.addEventListener('drop', handleDrop, false);
document.addEventListener('dragleave', handleDragLeave, false);
if ('serviceWorker' in navigator) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('message', handleServiceWorkerPostMessage);
}
@ -608,6 +610,11 @@ const UI: React.FC = ({ children }) => {
// Wait for login to succeed or fail
if (me === null) return null;
if (!me && !guestExperience) {
cacheCurrentUrl(history.location);
return <Redirect to='/login' />;
}
type HotkeyHandlers = { [key: string]: (keyEvent?: KeyboardEvent) => void };
const handlers: HotkeyHandlers = {

Wyświetl plik

@ -86,13 +86,14 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
</>
);
const renderLoading = () => renderWithLayout(<ColumnLoading />);
const renderLoading = () => renderWithLayout(<ColumnLoading />);
const renderForbidden = () => renderWithLayout(<ColumnForbidden />);
const renderError = (props: any) => renderWithLayout(<BundleColumnError {...props} />);
const renderError = (props: any) => renderWithLayout(<BundleColumnError {...props} />);
const loginRedirect = () => {
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
return <Redirect to={`/login?redirect_uri=${actualUrl}`} />;
localStorage.setItem('soapbox:redirect_uri', actualUrl);
return <Redirect to='/login' />;
};
const authorized = [

Wyświetl plik

@ -11,6 +11,7 @@ import snackbar from 'soapbox/actions/snackbar';
import { createAccount } from 'soapbox/actions/verification';
import { removeStoredVerification } from 'soapbox/actions/verification';
import { useAppSelector } from 'soapbox/hooks';
import { getRedirectUrl } from 'soapbox/utils/redirect';
import { Button, Form, FormGroup, Input } from '../../components/ui';
@ -81,7 +82,8 @@ const Registration = () => {
}, []);
if (shouldRedirect) {
return <Redirect to='/' />;
const redirectUri = getRedirectUrl();
return <Redirect to={redirectUri} />;
}
return (

Wyświetl plik

@ -115,6 +115,7 @@ export const SoapboxConfigRecord = ImmutableRecord({
singleUserMode: false,
singleUserModeProfile: '',
linkFooterMessage: '',
guestExperience: true,
links: ImmutableMap<string, string>(),
}, 'SoapboxConfig');

Wyświetl plik

@ -0,0 +1,36 @@
import { Location } from 'history';
import { useEffect } from 'react';
const LOCAL_STORAGE_REDIRECT_KEY = 'soapbox:redirect-uri';
const cacheCurrentUrl = (location: Location<unknown>) => {
const actualUrl = encodeURIComponent(`${location.pathname}${location.search}`);
localStorage.setItem(LOCAL_STORAGE_REDIRECT_KEY, actualUrl);
return actualUrl;
};
const getRedirectUrl = () => {
let redirectUri = localStorage.getItem(LOCAL_STORAGE_REDIRECT_KEY);
if (redirectUri) {
redirectUri = decodeURIComponent(redirectUri);
}
localStorage.removeItem(LOCAL_STORAGE_REDIRECT_KEY);
return redirectUri || '/';
};
const useCachedLocationHandler = () => {
const removeCachedRedirectUri = () => localStorage.removeItem(LOCAL_STORAGE_REDIRECT_KEY);
useEffect(() => {
window.addEventListener('beforeunload', removeCachedRedirectUri);
return () => {
window.removeEventListener('beforeunload', removeCachedRedirectUri);
};
}, []);
return null;
};
export { cacheCurrentUrl, getRedirectUrl, useCachedLocationHandler };