Remove store.user.accessToken (#740)

This commit is contained in:
infinite-persistence 2022-01-20 08:20:58 +08:00
commit aef3c346a0
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
18 changed files with 56 additions and 570 deletions

View file

@ -567,7 +567,6 @@
"Embedded": "Embedded",
"Failed to load %language% translations.": "Failed to load %language% translations.",
"odysee.com Account": "odysee.com Account",
"Creating a odysee.com account will allow you to earn rewards, receive content and security updates, and optionally backup your data.": "Creating a odysee.com account will allow you to earn rewards, receive content and security updates, and optionally backup your data.",
"Paid content cannot be embedded": "Paid content cannot be embedded",
"This content cannot be embedded": "This content cannot be embedded",
"Your videos are ready to be transferred.": "Your videos are ready to be transferred.",

View file

@ -1,8 +1,8 @@
import { hot } from 'react-hot-loader/root';
import { connect } from 'react-redux';
import { selectGetSyncErrorMessage, selectSyncFatalError, selectSyncIsLocked } from 'redux/selectors/sync';
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
import { doUserSetReferrer } from 'redux/actions/user';
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { doFetchChannelListMine, doFetchCollectionListMine, doResolveUris } from 'redux/actions/claims';
import { selectMyChannelClaimIds } from 'redux/selectors/claims';
@ -24,7 +24,6 @@ import App from './view';
const select = (state) => ({
user: selectUser(state),
accessToken: selectAccessToken(state),
theme: selectThemePath(state),
language: selectLanguage(state),
languages: selectLoadedLanguages(state),
@ -44,7 +43,6 @@ const select = (state) => ({
});
const perform = (dispatch) => ({
fetchAccessToken: () => dispatch(doFetchAccessToken()),
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
fetchCollectionListMine: () => dispatch(doFetchCollectionListMine()),
setLanguage: (language) => dispatch(doSetLanguage(language)),

View file

@ -60,7 +60,6 @@ type Props = {
user: ?{ id: string, has_verified_email: boolean, is_reward_approved: boolean },
location: { pathname: string, hash: string, search: string },
history: { push: (string) => void },
fetchAccessToken: () => void,
fetchChannelListMine: () => void,
fetchCollectionListMine: () => void,
signIn: () => void,
@ -93,7 +92,6 @@ function App(props: Props) {
const {
theme,
user,
fetchAccessToken,
fetchChannelListMine,
fetchCollectionListMine,
signIn,
@ -285,13 +283,11 @@ function App(props: Props) {
ReactModal.setAppElement(wrapperElement);
}
fetchAccessToken();
// @if TARGET='app'
fetchChannelListMine(); // This is fetched after a user is signed in on web
fetchCollectionListMine();
// @endif
}, [appRef, fetchAccessToken, fetchChannelListMine, fetchCollectionListMine]);
}, [appRef, fetchChannelListMine, fetchCollectionListMine]);
useEffect(() => {
// $FlowFixMe

View file

@ -2,18 +2,15 @@ import { connect } from 'react-redux';
import { selectPublishFormValues } from 'redux/selectors/publish';
import { doUpdatePublishForm } from 'redux/actions/publish';
import PublishAdditionalOptions from './view';
import { selectUser, selectAccessToken } from 'redux/selectors/user';
import { doFetchAccessToken } from 'redux/actions/user';
import { selectUser } from 'redux/selectors/user';
const select = (state) => ({
...selectPublishFormValues(state),
accessToken: selectAccessToken(state),
user: selectUser(state),
});
const perform = (dispatch) => ({
updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
fetchAccessToken: () => dispatch(doFetchAccessToken()),
});
export default connect(select, perform)(PublishAdditionalOptions);

View file

@ -27,8 +27,6 @@ type Props = {
updatePublishForm: ({}) => void,
useLBRYUploader: boolean,
needsYTAuth: boolean,
fetchAccessToken: () => void,
accessToken: string,
showSchedulingOptions: boolean,
};

View file

@ -1,18 +0,0 @@
import { connect } from 'react-redux';
import { doUserResendVerificationEmail, doUserCheckEmailVerified, doFetchAccessToken } from 'redux/actions/user';
import { selectEmailToVerify, selectUser, selectAccessToken } from 'redux/selectors/user';
import UserEmailVerify from './view';
const select = state => ({
email: selectEmailToVerify(state),
user: selectUser(state),
accessToken: selectAccessToken(state),
});
const perform = dispatch => ({
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)),
checkEmailVerified: () => dispatch(doUserCheckEmailVerified()),
fetchAccessToken: () => dispatch(doFetchAccessToken()),
});
export default connect(select, perform)(UserEmailVerify);

View file

@ -1,73 +0,0 @@
// @flow
import * as PAGES from 'constants/pages';
import type { Node } from 'react';
import React, { useEffect } from 'react';
import Button from 'component/button';
import { FormField } from 'component/common/form';
import UserSignOutButton from 'component/userSignOutButton';
import Card from 'component/common/card';
type Props = {
cancelButton: Node,
email: string,
resendVerificationEmail: (string) => void,
checkEmailVerified: () => void,
user: {
has_verified_email: boolean,
},
fetchAccessToken: () => void,
accessToken: string,
};
function UserEmail(props: Props) {
const { email, user, accessToken, fetchAccessToken } = props;
let isVerified = false;
if (user) {
isVerified = user.has_verified_email;
}
useEffect(() => {
if (!accessToken) {
fetchAccessToken();
}
}, [accessToken, fetchAccessToken]);
return (
<Card
title={__('odysee.com Account')}
subtitle={
isVerified
? undefined
: __(
'Creating a odysee.com account will allow you to earn rewards, receive content and security updates, and optionally backup your data.'
)
}
actions={
isVerified ? (
<FormField
type="text"
className="form-field--copyable"
readOnly
label={
<React.Fragment>
{__('Your email')}{' '}
<Button
button="link"
label={__('Update mailing preferences')}
href={`http://lbry.io/list/edit/${accessToken}`}
/>
</React.Fragment>
}
inputButton={<UserSignOutButton button="secondary" />}
value={email || ''}
/>
) : (
<Button button="primary" label={__('Log In')} navigate={`/$/${PAGES.AUTH}`} />
)
}
/>
);
}
export default UserEmail;

View file

@ -4,13 +4,7 @@ import { selectGetSyncIsPending, selectSyncHash, selectPrefsReady } from 'redux/
import { doClaimRewardType } from 'redux/actions/rewards';
import { doSetClientSetting } from 'redux/actions/settings';
import { selectClaimedRewards, makeSelectIsRewardClaimPending } from 'redux/selectors/rewards';
import {
selectUserIsPending,
selectYoutubeChannels,
selectEmailToVerify,
selectUser,
selectAccessToken,
} from 'redux/selectors/user';
import { selectUserIsPending, selectYoutubeChannels, selectEmailToVerify, selectUser } from 'redux/selectors/user';
import { selectMyChannelClaims, selectFetchingMyChannels, selectCreatingChannel } from 'redux/selectors/claims';
import { selectBalance } from 'redux/selectors/wallet';
import * as SETTINGS from 'constants/settings';
@ -22,7 +16,6 @@ import UserSignIn from './view';
const select = (state) => ({
emailToVerify: selectEmailToVerify(state),
user: selectUser(state),
accessToken: selectAccessToken(state),
channels: selectMyChannelClaims(state),
claimedRewards: selectClaimedRewards(state),
claimingReward: makeSelectIsRewardClaimPending()(state, {

View file

@ -288,7 +288,6 @@ export const USER_INVITE_STATUS_FETCH_FAILURE = 'USER_INVITE_STATUS_FETCH_FAILUR
export const USER_INVITE_NEW_STARTED = 'USER_INVITE_NEW_STARTED';
export const USER_INVITE_NEW_SUCCESS = 'USER_INVITE_NEW_SUCCESS';
export const USER_INVITE_NEW_FAILURE = 'USER_INVITE_NEW_FAILURE';
export const FETCH_ACCESS_TOKEN_SUCCESS = 'FETCH_ACCESS_TOKEN_SUCCESS';
export const USER_YOUTUBE_IMPORT_STARTED = 'USER_YOUTUBE_IMPORT_STARTED';
export const USER_YOUTUBE_IMPORT_FAILURE = 'USER_YOUTUBE_IMPORT_FAILURE';
export const USER_YOUTUBE_IMPORT_SUCCESS = 'USER_YOUTUBE_IMPORT_SUCCESS';

View file

@ -18,7 +18,6 @@ export const TRANSACTION_FAILED = 'transaction_failed';
export const REWARD_GENERATED_CODE = 'reward_generated_code';
export const AFFIRM_PURCHASE = 'affirm_purchase';
export const CONFIRM_CLAIM_REVOKE = 'confirm_claim_revoke';
export const FIRST_SUBSCRIPTION = 'firstSubscription';
export const SEND_TIP = 'send_tip';
export const CONFIRM_SEND_TIP = 'confirm_send_tip';
export const SOCIAL_SHARE = 'social_share';

View file

@ -1,17 +0,0 @@
import { connect } from 'react-redux';
import { doHideModal } from 'redux/actions/app';
import { selectAccessToken, selectUser } from 'redux/selectors/user';
import { withRouter } from 'react-router';
import ModalFirstSubscription from './view';
const select = state => ({
accessToken: selectAccessToken(state),
user: selectUser(state),
});
const perform = dispatch => () => ({
closeModal: () => dispatch(doHideModal()),
});
export default withRouter(connect(select, perform)(ModalFirstSubscription));

View file

@ -1,73 +0,0 @@
// @flow
import { SITE_NAME } from 'config';
import React from 'react';
import { Modal } from 'modal/modal';
import Button from 'component/button';
import * as PAGES from 'constants/pages';
import Card from 'component/common/card';
type Props = {
closeModal: () => void,
accessToken: string,
user: any,
doAuth: () => void,
history: { push: string => void },
location: UrlLocation,
};
const ModalFirstSubscription = (props: Props) => {
const {
closeModal,
accessToken,
user,
history,
location: { pathname },
} = props;
const title = __('You Followed Your First Channel!');
return (
<Modal type="card" isOpen contentLabel={title}>
<Card
title={title}
subtitle={
<>
{__('Awesome! You just followed your first channel.')}{' '}
{user && user.primary_email
? __('You will receive notifications related to new content.')
: __('Log in with %SITE_NAME% to receive notifications about new content.', { SITE_NAME })}
</>
}
actions={
<div className="section__actions">
<Button button="primary" onClick={closeModal} label={__('Got it')} />
<React.Fragment>
{user && user.primary_email ? (
<React.Fragment>
<Button
button="link"
href={`https://lbry.com/list/edit/${accessToken}`}
label={__('Update email preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<Button
button="link"
onClick={() => {
closeModal();
history.push(`/$/${PAGES.AUTH}?redirect=${pathname}`);
}}
label={__('Log in')}
/>
</React.Fragment>
)}
</React.Fragment>
</div>
}
/>
</Modal>
);
};
export default ModalFirstSubscription;

View file

@ -41,9 +41,6 @@ const ModalFileSelection = lazyImport(() =>
);
const ModalFileTimeout = lazyImport(() => import('modal/modalFileTimeout' /* webpackChunkName: "modalFileTimeout" */));
const ModalFirstReward = lazyImport(() => import('modal/modalFirstReward' /* webpackChunkName: "modalFirstReward" */));
const ModalFirstSubscription = lazyImport(() =>
import('modal/modalFirstSubscription' /* webpackChunkName: "modalFirstSubscription" */)
);
const ModalImageUpload = lazyImport(() => import('modal/modalImageUpload' /* webpackChunkName: "modalImageUpload" */));
const ModalMassTipsUnlock = lazyImport(() =>
import('modal/modalMassTipUnlock' /* webpackChunkName: "modalMassTipUnlock" */)
@ -124,8 +121,6 @@ function getModal(id) {
return ModalRevokeClaim;
case MODALS.PHONE_COLLECTION:
return ModalPhoneCollection;
case MODALS.FIRST_SUBSCRIPTION:
return ModalFirstSubscription;
case MODALS.SEND_TIP:
return ModalSendTip;
case MODALS.SOCIAL_SHARE:

View file

@ -1,19 +1,3 @@
import * as PAGES from 'constants/pages';
import { connect } from 'react-redux';
import { doFetchAccessToken } from 'redux/actions/user';
import { selectAccessToken, selectUser } from 'redux/selectors/user';
import { selectDaemonSettings } from 'redux/selectors/settings';
import HelpPage from './view';
const select = state => ({
user: selectUser(state),
accessToken: selectAccessToken(state),
deamonSettings: selectDaemonSettings(state),
});
const perform = (dispatch, ownProps) => ({
doAuth: () => ownProps.history.push(`/$/${PAGES.AUTH}?redirect=/$/${PAGES.HELP}`),
fetchAccessToken: () => dispatch(doFetchAccessToken()),
});
export default connect(select, perform)(HelpPage);
export default HelpPage;

View file

@ -1,165 +1,26 @@
// @flow
import { SITE_NAME, SIMPLE_SITE, SITE_HELP_EMAIL } from 'config';
import { SITE_NAME, SITE_HELP_EMAIL } from 'config';
import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages';
import * as React from 'react';
// @if TARGET='app'
import { shell } from 'electron';
import WalletBackup from 'component/walletBackup';
// @endif
import Lbry from 'lbry';
import Native from 'native';
import Button from 'component/button';
import Page from 'component/page';
import Card from 'component/common/card';
import I18nMessage from 'component/i18nMessage';
type DeamonSettings = {
data_dir: string | any,
};
type Props = {
deamonSettings: DeamonSettings,
accessToken: string,
fetchAccessToken: () => void,
doAuth: () => void,
user: any,
};
type VersionInfo = {
os_system: string,
os_release: string,
platform: string,
lbrynet_version: string,
};
type State = {
versionInfo: VersionInfo | any,
lbryId: String | any,
uiVersion: ?string,
upgradeAvailable: ?boolean,
accessTokenHidden: ?boolean,
};
class HelpPage extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
versionInfo: null,
lbryId: null,
uiVersion: null,
upgradeAvailable: null,
accessTokenHidden: true,
};
(this: any).showAccessToken = this.showAccessToken.bind(this);
(this: any).openLogFile = this.openLogFile.bind(this);
}
componentDidMount() {
// @if TARGET='app'
Native.getAppVersionInfo().then(({ localVersion, upgradeAvailable }) => {
this.setState({
uiVersion: localVersion,
upgradeAvailable,
});
});
if (!this.props.accessToken) this.props.fetchAccessToken();
// @endif
Lbry.version().then((info) => {
this.setState({
versionInfo: info,
});
});
Lbry.status().then((info) => {
this.setState({
lbryId: info.installation_id,
});
});
}
showAccessToken() {
this.setState({
accessTokenHidden: false,
});
}
openLogFile(userHomeDirectory: string) {
const logFileName = 'lbrynet.log';
const os = this.state.versionInfo.os_system;
if (os === 'Darwin' || os === 'Linux') {
shell.openPath(`${userHomeDirectory}/${logFileName}`);
} else {
shell.openPath(`${userHomeDirectory}\\${logFileName}`);
}
}
render() {
let ver;
let osName;
let platform;
let newVerLink;
const { accessToken, doAuth, user, deamonSettings } = this.props;
const { data_dir: dataDirectory } = deamonSettings;
if (this.state.versionInfo) {
ver = this.state.versionInfo;
if (ver.os_system === 'Darwin') {
osName = parseInt(ver.os_release.match(/^\d+/), 10) < 16 ? 'Mac OS X' : 'Mac OS';
platform = `${osName} ${ver.os_release}`;
newVerLink = 'https://lbry.com/get/lbry.dmg';
} else if (process.env.APPIMAGE !== undefined) {
platform = `Linux (AppImage)`;
newVerLink = 'https://lbry.com/get/lbry.AppImage';
} else if (ver.os_system === 'Linux') {
platform = `Linux (${ver.platform})`;
newVerLink = 'https://lbry.com/get/lbry.deb';
} else {
platform = `Windows (${ver.platform})`;
newVerLink = 'https://lbry.com/get/lbry.msi';
}
} else {
ver = null;
}
export default function HelpPage() {
return (
<Page className="card-stack">
<Card
title={SIMPLE_SITE ? __('Visit the %SITE_NAME% Help Hub', { SITE_NAME }) : __('Read the FAQ')}
subtitle={
SIMPLE_SITE
? __('Our support posts answer many common questions.')
: __('Our FAQ answers many common questions.')
}
title={__('Visit the %SITE_NAME% Help Hub', { SITE_NAME })}
subtitle={__('Our support posts answer many common questions.')}
actions={
<div className="section__actions">
{SIMPLE_SITE ? (
<Button
href="https://odysee.com/@OdyseeHelp:b"
label={__('View %SITE_NAME% Help Hub', { SITE_NAME })}
icon={ICONS.HELP}
button="secondary"
/>
) : (
<>
<Button
href="https://odysee.com/@OdyseeHelp:b/OdyseeBasics:c"
label={__('Read Odysee Basics FAQ')}
icon={ICONS.HELP}
button="secondary"
/>
<Button
href="https://odysee.com/@OdyseeHelp:b"
label={__('View all Odysee FAQs')}
icon={ICONS.HELP}
button="secondary"
/>
</>
)}
</div>
}
/>
@ -168,8 +29,8 @@ class HelpPage extends React.PureComponent<Props, State> {
title={__('Find assistance')}
subtitle={
<I18nMessage tokens={{ channel: <strong>#help</strong>, help_email: SITE_HELP_EMAIL }}>
Live help is available most hours in the %channel% channel of our Discord chat room. Or you can always
email us at %help_email%.
Live help is available most hours in the %channel% channel of our Discord chat room. Or you can always email
us at %help_email%.
</I18nMessage>
}
actions={
@ -187,142 +48,13 @@ class HelpPage extends React.PureComponent<Props, State> {
<Card
title={__('Report a bug or suggest something')}
subtitle={
<React.Fragment>
{__('Did you find something wrong? Think Odysee could add something useful and cool?')}
</React.Fragment>
}
subtitle={__('Did you find something wrong? Think Odysee could add something useful and cool?')}
actions={
<div className="section__actions">
<Button navigate="/$/report" label={__('Submit Feedback')} icon={ICONS.FEEDBACK} button="secondary" />
</div>
}
/>
{/* @if TARGET='app' */}
<Card
title={__('View your log')}
subtitle={
<I18nMessage
tokens={{
support_link: (
<Button button="link" label={__('support')} href="https://odysee.com/@OdyseeHelp:b?view=about" />
),
}}
>
Did something go wrong? Have a look in your log file, or send it to %support_link%.
</I18nMessage>
}
actions={
<div className="section__actions">
<Button
button="secondary"
label={__('Open Log')}
icon={ICONS.OPEN_LOG}
onClick={() => this.openLogFile(dataDirectory)}
/>
<Button
button="secondary"
label={__('Open Log Folder')}
icon={ICONS.OPEN_LOG_FOLDER}
onClick={() => shell.openPath(dataDirectory)}
/>
</div>
}
/>
<WalletBackup />
{/* @endif */}
{!SIMPLE_SITE && (
<>
<Card
title={__('About --[About section in Help Page]--')}
subtitle={
this.state.upgradeAvailable !== null && this.state.upgradeAvailable ? (
<span>
{__('A newer version of LBRY is available.')}{' '}
<Button button="link" href={newVerLink} label={__('Download now!')} />
</span>
) : null
}
isBodyList
body={
<div className="table__wrapper">
<table className="table table--stretch">
<tbody>
<tr>
<td>{__('App')}</td>
<td>
{this.state.uiVersion ? this.state.uiVersion + ' - ' : ''}
<Button
button="link"
label={__('Changelog')}
href="https://github.com/lbryio/lbry-desktop/blob/master/CHANGELOG.md"
/>
</td>
</tr>
<tr>
<td>{__('Daemon (lbrynet)')}</td>
<td>{ver ? ver.lbrynet_version : __('Loading...')}</td>
</tr>
<tr>
<td>{__('Connected Email')}</td>
<td>
{user && user.primary_email ? (
<React.Fragment>
{user.primary_email}{' '}
<Button
button="link"
navigate={`/$/${PAGES.SETTINGS_NOTIFICATIONS}`}
label={__('Update mailing preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<span className="empty">{__('none')} </span>
<Button button="link" onClick={() => doAuth()} label={__('set email')} />
</React.Fragment>
)}
</td>
</tr>
<tr>
<td>{__('Reward Eligible')}</td>
<td>{user && user.is_reward_approved ? __('Yes') : __('No')}</td>
</tr>
<tr>
<td>{__('Platform')}</td>
<td>{platform}</td>
</tr>
<tr>
<td>{__('Installation ID')}</td>
<td>{this.state.lbryId}</td>
</tr>
<tr>
<td>{__('Access Token')}</td>
<td>
{this.state.accessTokenHidden && (
<Button button="link" label={__('View')} onClick={this.showAccessToken} />
)}
{!this.state.accessTokenHidden && accessToken && (
<div>
<p>{accessToken}</p>
<div className="help--warning">
{__('This is equivalent to a password. Do not post or share this.')}
</div>
</div>
)}
</td>
</tr>
</tbody>
</table>
</div>
}
/>
</>
)}
</Page>
);
}
}
export default HelpPage;

View file

@ -573,17 +573,6 @@ export function doUserEmailVerify(verificationToken, recaptcha) {
};
}
export function doFetchAccessToken() {
return (dispatch) => {
const success = (token) =>
dispatch({
type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS,
data: { token },
});
Lbryio.getAuthToken().then(success);
};
}
export function doUserIdentityVerify(stripeToken) {
return (dispatch) => {
dispatch({

View file

@ -25,7 +25,6 @@ const defaultState = {
referralLink: undefined,
referralCode: undefined,
user: undefined,
accessToken: undefined,
youtubeChannelImportPending: false,
youtubeChannelImportErrorMessage: '',
referrerSetIsPending: false,
@ -36,14 +35,12 @@ reducers[ACTIONS.AUTHENTICATION_STARTED] = (state) =>
Object.assign({}, state, {
authenticationIsPending: true,
userIsPending: true,
accessToken: defaultState.accessToken,
});
reducers[ACTIONS.AUTHENTICATION_SUCCESS] = (state, action) =>
Object.assign({}, state, {
authenticationIsPending: false,
userIsPending: false,
accessToken: action.data.accessToken,
user: action.data.user,
});
@ -221,14 +218,6 @@ reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = (state, action) =>
identityVerifyErrorMessage: action.data.error,
});
reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = (state, action) => {
const { token } = action.data;
return Object.assign({}, state, {
accessToken: token,
});
};
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = (state) =>
Object.assign({}, state, {
inviteStatusIsPending: true,

View file

@ -73,7 +73,6 @@ export const selectUserIsVerificationCandidate = createSelector(
(user) => user && (!user.has_verified_email || !user.is_identity_verified)
);
export const selectAccessToken = (state) => selectState(state).accessToken;
export const selectUserInviteStatusIsPending = (state) => selectState(state).inviteStatusIsPending;
export const selectUserInvitesRemaining = (state) => selectState(state).invitesRemaining;
export const selectUserInvitees = (state) => selectState(state).invitees;