Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update WebApp to handle Twitter V2 API -- Sign in with Twitter is working again #3849

Merged
merged 2 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/working/SECURE_CERTIFICATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ In WebApp/src/js/config.js, set SECURE_CERTIFICATE_INSTALLED to true, and then u

WebApp will startup at http://localhost:3000

## Signing in with Facebook on your dev machine
## Signing in with Facebook and Twitter on your dev machine
### Make a small necessary change to your /etc/hosts

Facebook will no longer redirect to localhost, so we make a second alias for 127.0.0.1 with this specific made up
domain: `wevotedeveloper.com` by running the following command in a terminal:

This `wevotedeveloper.com` is also needed to debug "Sign in with Twitter" while using the `wevotedeveloper.com` domain for your local Python API server.
NOTE: As of March 2024, Chrome stopped responding to this domain (possibly since it can't match it with a public DNS lookup), so you will have to debug this setup with Safari.
Safari has a version of Devtools called "Web Inspector" that you get to by right-clicking in the tab, and clicking "Inspect Element". Devtools and Web
Inspector share the Chromium code base and have almost identical capabilities.

`sudo node node/updateHosts.js`

The run will look like this
Expand Down
1 change: 1 addition & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ class App extends Component {
<Route path="/terms" component={TermsOfService} />
<Route path="/twitter_sign_in" exact><TwitterSignInProcess /></Route>
<Route path="/twittersigninprocess/:sign_in_step" component={TwitterSignInProcess} />
<Route path="/twittersigninprocess" component={TwitterSignInProcess} />
<Route path="/unsubscribe/:subscription_secret_key/:unsubscribe_modifier/instant" exact component={(props) => <UnsubscribeRoot {...props} instantUnsubscribe />} />
<Route path="/unsubscribe/:subscription_secret_key/:unsubscribe_modifier" exact component={UnsubscribeRoot} />
<Route path="/unsubscribe/:subscription_secret_key" exact component={UnsubscribeRoot} />
Expand Down
17 changes: 9 additions & 8 deletions src/js/actions/TwitterActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ export default {
});
},

twitterNativeSignInSave (twitterAccessToken, twitterAccessTokenSecret) {
Dispatcher.loadEndpoint('twitterNativeSignInSave',
{
twitter_access_token: twitterAccessToken,
twitter_access_token_secret: twitterAccessTokenSecret,
});
},

twitterProcessDeferredImages (twitterImageLoadInfo) {
Dispatcher.loadEndpoint('twitterProcessDeferredImages', {
status: twitterImageLoadInfo.status,
Expand All @@ -54,4 +46,13 @@ export default {
});
},

twitterOauth1UserHandler (oauthToken, oauthVerifier) { // For twitter V2 API, March 2024
// console.log('twitterOauth1UserHandler: ', oauthToken, oauthVerifier);
Dispatcher.loadEndpoint('twitterOauth1UserHandler',
{
oauth_token: oauthToken,
oauth_verifier: oauthVerifier,
});
},

};
1 change: 1 addition & 0 deletions src/js/components/Twitter/TwitterSignIn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class TwitterSignIn extends Component {
twitterSignInCrash: false,
twitterSignInStartSubmitted: false,
};
oAuthLog(`twitterSignIn redirect url = ${returnURL}`);
}

componentDidMount () {
Expand Down
53 changes: 53 additions & 0 deletions src/js/config - wevotedeveloper SSL Web and local API.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-disable */
// Note that we import these values where needed as "webAppConfig"
module.exports = {
WE_VOTE_URL_PROTOCOL: 'https://', // "http://" for local dev or "https://" for live server
WE_VOTE_HOSTNAME: 'wevotedeveloper.com:3000', // This should be without "http...". This is "WeVote.US" on live server.
WE_VOTE_IMAGE_PATH_FOR_CORDOVA: 'https://wevote.us', // If you are not working with Cordova, you don't need to change this
SECURE_CERTIFICATE_INSTALLED: false,

WE_VOTE_SERVER_ROOT_URL: 'https://wevotedeveloper.com:8000/',
WE_VOTE_SERVER_ADMIN_ROOT_URL: 'https://wevotedeveloper.com:8000/admin/',
WE_VOTE_SERVER_API_ROOT_URL: 'https://wevotedeveloper.com:8000/apis/v1/',
WE_VOTE_SERVER_API_CDN_ROOT_URL: 'https://wevotedeveloper.com:8000/apis/v1/',

ENABLE_NEXT_RELEASE_FEATURES: false,
ENABLE_WORKBOX_SERVICE_WORKER: false, // After setting this false, recompile, then in Chrome DevTools go to Application Tab, Application/Service Worker and for the sw.js click the "unregister" button to the right

DEBUG_MODE: false,
SHOW_TEST_OPTIONS: false, // On the DeviceDialog

LOG_RENDER_EVENTS: false,
LOG_ONLY_FIRST_RENDER_EVENTS: false,
LOG_HTTP_REQUESTS: false,
LOG_ROUTING: false,
LOG_SIGNIN_STEPS: false,
LOG_CORDOVA_OFFSETS: false,
SHOW_CORDOVA_URL_FIELD: false, // Only needed for debugging in Cordova

// Use 1 or 0 as opposed to true or false
test: {
use_test_election: 0,
},

location: {
text_for_map_search: '',
},

ENABLE_FACEBOOK: false,
ENABLE_TWITTER: true,
ENABLE_PAY_TO_PROMOTE: false,

// API Keys, some of these are publishable (not secret)
FACEBOOK_APP_ID: "1097389196952441",
FULL_STORY_ORG: '',
GOOGLE_ADS_TRACKING_ID: 'T',
GOOGLE_ANALYTICS_TRACKING_ID: '',
GOOGLE_MAPS_API_KEY: '',
GOOGLE_PEOPLE_API_KEY: '',
GOOGLE_PEOPLE_API_CLIENT_ID: '',
GOOGLE_RECAPTCHA_KEY: '',
OPEN_REPLAY_PROJECT_KEY: '',
OPEN_REPLAY_INGEST_POINT: 'https://openreplay.wevote.us/ingest',
STRIPE_API_KEY: "",
};
30 changes: 28 additions & 2 deletions src/js/pages/Process/TwitterSignInProcess.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,30 @@ export default class TwitterSignInProcess extends Component {
savingAccount: false,
redirectInProgress: false,
twitterAuthResponse: {},
redirectCount: 0,
};
this.twitterOauthLeg3 = this.twitterOauthLeg3.bind(this);
}

componentDidMount () {
// console.log('--------------- TwitterSignInProcess componentDidMount');
this.appStateSubscription = messageService.getMessage().subscribe(() => this.onAppObservableStoreChange());
this.twitterStoreListener = TwitterStore.addListener(this.onTwitterStoreChange.bind(this));
this.voterStoreListener = VoterStore.addListener(this.onVoterStoreChange.bind(this));
this.twitterSignInRetrieve();
window.scrollTo(0, 0);
this.twitterSignInRetrieve();
const { location: { search } } = this.props;
const { redirectCount } = this.state;
oAuthLog('TwitterSignInProcess search props: ', search);
const urlParams = new URLSearchParams(search);
const oauthToken = urlParams.get('oauth_token');
const oauthVerifier = urlParams.get('oauth_verifier');
if (oauthToken && oauthVerifier && redirectCount === 0) {
oAuthLog('TwitterSignInProcess received redirect from Twitter redirectCount: ', redirectCount, ', oauthToken: ', oauthToken, ', oauthVerifier: ', oauthVerifier);
this.setState({ redirectCount: (redirectCount + 1) });
TwitterActions.twitterOauth1UserHandler(oauthToken, oauthVerifier);
this.twitterSignInRetrieve();
}
}

componentWillUnmount () {
Expand All @@ -54,7 +69,10 @@ export default class TwitterSignInProcess extends Component {
const { mergingTwoAccounts, savingAccount } = this.state;
console.log('TwitterSignInProcess onTwitterStoreChange, twitterAuthResponse:', twitterAuthResponse);

if (twitterAuthResponse.twitter_sign_in_failed) {
if (twitterAuthResponse.twitter_sign_in_failed === undefined && twitterAuthResponse.twitter_oauth_voter_info_stored_in_db) {
oAuthLog('Twitter sign undefined, but oauth_voter_info_stored_in_db - calling twitterSignInRetrieve()');
this.twitterSignInRetrieve();
} else if (twitterAuthResponse.twitter_sign_in_failed) {
oAuthLog('Twitter sign in failed - push to /settings/account');
historyPush({
pathname: '/settings/account', // SnackNotifier that handles this is in SettingsDashboard
Expand Down Expand Up @@ -191,9 +209,17 @@ export default class TwitterSignInProcess extends Component {
}

twitterSignInRetrieve () {
oAuthLog('Twitter twitterSignInRetrieve on TwitterSignInProcess component mount');
TwitterActions.twitterSignInRetrieve();
}

twitterOauthLeg3 (oauthToken, oauthVerifier) {
const { redirectCount } = this.state;
oAuthLog('TwitterSignInProcess received redirect from Twitter redirectCount: ', redirectCount, ', oauthToken: ', oauthToken, ', oauthVerifier: ', oauthVerifier);
this.setState({ redirectCount: (redirectCount + 1) });
TwitterActions.twitterOauth1UserHandler(oauthToken, oauthVerifier);
}

render () {
renderLog('TwitterSignInProcess'); // Set LOG_RENDER_EVENTS to log all renders
const { redirectInProgress, twitterAuthResponse } = this.state;
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/BallotStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,6 @@ class BallotStore extends ReduceStore {
BallotActions.voterBallotItemsRetrieve();
return this.resetState();

case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/FriendStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ class FriendStore extends ReduceStore {
currentFriendsOrganizationWeVoteIds,
};

case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/IssueStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,6 @@ class IssueStore extends ReduceStore {
issueWeVoteIdsUnderEachBallotItem,
organizationWeVoteIdsLinkedToIssueDict,
};
case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/OrganizationStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,6 @@ class OrganizationStore extends ReduceStore {
organizationWeVoteIdsVoterIsIgnoring,
};

case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/SupportStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ class SupportStore extends ReduceStore {
SupportActions.voterAllPositionsRetrieve();
return this.resetState();

case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
40 changes: 17 additions & 23 deletions src/js/stores/TwitterStore.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ReduceStore } from 'flux/utils';
import CandidateActions from '../actions/CandidateActions';
import OrganizationActions from '../actions/OrganizationActions';
import TwitterActions from '../actions/TwitterActions';
import VoterActions from '../actions/VoterActions';
import Dispatcher from '../common/dispatcher/Dispatcher';

class TwitterStore extends ReduceStore {
getInitialState () {
// return {
// success: true,
// };
return {
twitter_store_initialized: true,
twitter_oauth_voter_info_stored_in_db: false,
};
}

get () {
Expand Down Expand Up @@ -101,6 +101,7 @@ class TwitterStore extends ReduceStore {
existing_twitter_account_found: this.getState().existing_twitter_account_found,
voter_we_vote_id_attached_to_twitter: this.getState().voter_we_vote_id_attached_to_twitter,
twitter_image_load_info: this.getState().twitter_image_load_info,
twitter_oauth_voter_info_stored_in_db: this.getState().twitter_oauth_voter_info_stored_in_db,
};
}

Expand Down Expand Up @@ -156,21 +157,6 @@ class TwitterStore extends ReduceStore {
status: action.res.status,
};

case 'twitterNativeSignInSave':
// Exit if we don't have a successful response (since we expect certain variables in a successful response below)
if (!action.res || !action.res.success) return state;
if (action.res.success) {
TwitterActions.twitterSignInRetrieve();
}

return {
// ...state,
voter_device_id: action.res.voter_device_id,
twitter_handle: action.res.twitter_handle,
twitter_handle_found: action.res.twitter_handle_found,
twitter_secret_key: action.res.twitter_secret_key,
};

case 'twitterProcessDeferredImages':
if (!action.res || !action.res.success) return state;
// console.log('twitter twitterProcessDeferredImages', action.res);
Expand All @@ -183,10 +169,12 @@ class TwitterStore extends ReduceStore {
we_vote_hosted_profile_image_url_tiny: action.res.we_vote_hosted_profile_image_url_tiny,
};


case 'twitterSignInRetrieve':
// Exit if we don't have a successful response (since we expect certain variables in a successful response below)
if (!action.res || !action.res.success) return state;
// console.log('twitterSignInRetrieve in TwitterStore received: ', action.res);
if (!action.res || !action.res.success) {
// Exit if we don't have a successful response (since we expect certain variables in a successful response below)
return state;
}
if (action.res.twitter_sign_in_verified) {
VoterActions.voterRetrieve();
VoterActions.twitterRetrieveIdsIfollow();
Expand Down Expand Up @@ -217,10 +205,16 @@ class TwitterStore extends ReduceStore {
// return this.resetState();
return this.resetVoterSpecificData();

default:
case 'twitterOauth1UserHandler':
if (!action.res || !action.res.success) return state;
console.log('twitterOauth1UserHandler res: ', action.res);
return {
...state,
twitter_oauth_voter_info_stored_in_db: true,
};

default:
return state;
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/js/stores/VoterGuideStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,6 @@ class VoterGuideStore extends ReduceStore {
organizationWeVoteIdsToFollowForLatestBallotItem: state.organizationWeVoteIdsToFollowForLatestBallotItem.filter((existingOrgWeVoteId) => existingOrgWeVoteId !== organizationWeVoteId),
};

case 'twitterNativeSignInSave':
case 'twitterSignInRetrieve':
case 'voterEmailAddressSignIn':
case 'voterFacebookSignInRetrieve':
Expand Down
Loading