2016-10-16 12:37:37 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
import React from 'react';
|
|
|
|
|
import { connect } from 'react-redux';
|
2019-04-22 15:08:38 +12:00
|
|
|
import { bindActionCreators } from 'redux';
|
2016-10-16 12:37:37 +13:00
|
|
|
|
2019-04-22 15:08:38 +12:00
|
|
|
import * as helpers from '../../helpers';
|
2018-04-19 13:34:16 +12:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
import * as uiActions from '../../services/ui/actions';
|
|
|
|
|
import * as spotifyActions from '../../services/spotify/actions';
|
|
|
|
|
|
2019-12-09 07:17:45 +13:00
|
|
|
class SpotifyAuthenticationFrame extends React.Component {
|
2019-09-05 15:36:11 +12:00
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
authorizing: false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.handleMessage = this.handleMessage.bind(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
window.addEventListener('message', this.handleMessage, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
window.removeEventListener('message', this.handleMessage, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMessage(event) {
|
|
|
|
|
const data = helpers.toJSON(event.data);
|
|
|
|
|
|
|
|
|
|
// Only digest messages relevant to us
|
|
|
|
|
if (data.origin != 'auth_spotify') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only allow incoming data from our authorized authenticator proxy
|
|
|
|
|
const authorization_domain = this.props.authorization_url.substring(0, this.props.authorization_url.indexOf('/', 8));
|
|
|
|
|
if (event.origin != authorization_domain) {
|
|
|
|
|
this.props.uiActions.createNotification({ content: `Authorization failed. ${event.origin} is not the configured authorization_url.`, type: 'bad' });
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Spotify bounced with an error
|
|
|
|
|
if (data.error !== undefined) {
|
|
|
|
|
this.props.uiActions.createNotification({ content: data.error, type: 'bad' });
|
|
|
|
|
|
|
|
|
|
// No errors? We're in!
|
|
|
|
|
} else {
|
|
|
|
|
this.props.spotifyActions.authorizationGranted(data);
|
|
|
|
|
this.props.spotifyActions.getMe();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Turn off our authorizing switch
|
|
|
|
|
this.setState({ authorizing: false });
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-09 07:17:45 +13:00
|
|
|
startAuthorization() {
|
2019-09-05 15:36:11 +12:00
|
|
|
const self = this;
|
|
|
|
|
this.setState({ authorizing: true });
|
|
|
|
|
|
|
|
|
|
// Open an authentication request window (to spotify)
|
|
|
|
|
const url = `${this.props.authorization_url}?action=authorize`;
|
|
|
|
|
const scopes = [
|
|
|
|
|
'playlist-modify-private',
|
|
|
|
|
'playlist-modify-public',
|
|
|
|
|
'playlist-read-private',
|
|
|
|
|
'playlist-modify-private',
|
|
|
|
|
'user-library-read',
|
|
|
|
|
'user-library-modify',
|
|
|
|
|
'user-follow-modify',
|
|
|
|
|
'user-follow-read',
|
|
|
|
|
'user-read-email',
|
|
|
|
|
'user-top-read',
|
|
|
|
|
'user-read-currently-playing',
|
|
|
|
|
'user-read-playback-state',
|
|
|
|
|
'playlist-read-collaborative',
|
|
|
|
|
'ugc-image-upload', // playlist image uploading
|
|
|
|
|
];
|
|
|
|
|
const popup = window.open(`${url}&scope=${scopes.join('%20')}`, 'popup', 'height=580,width=350');
|
|
|
|
|
|
|
|
|
|
// Start timer to check our popup's state
|
|
|
|
|
const timer = setInterval(checkPopup, 1000);
|
2019-12-09 07:17:45 +13:00
|
|
|
function checkPopup() {
|
2017-06-12 09:14:09 +12:00
|
|
|
// Popup has been closed
|
2019-09-05 15:36:11 +12:00
|
|
|
if (typeof (popup) !== 'undefined' && popup) {
|
|
|
|
|
if (popup.closed) {
|
|
|
|
|
self.setState({ authorizing: false });
|
|
|
|
|
clearInterval(timer);
|
2017-06-12 09:14:09 +12:00
|
|
|
}
|
2016-10-21 09:56:07 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
// Popup does not exist, so must have been blocked
|
|
|
|
|
} else {
|
|
|
|
|
self.props.uiActions.createNotification({ content: 'Popup blocked. Please allow popups and try again.', type: 'bad' });
|
|
|
|
|
self.setState({ authorizing: false });
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
2019-12-09 07:17:45 +13:00
|
|
|
const { authorizing } = this.state;
|
|
|
|
|
const { authorized } = this.props;
|
|
|
|
|
|
|
|
|
|
if (authorized) {
|
2019-09-05 15:36:11 +12:00
|
|
|
return (
|
2019-12-09 07:17:45 +13:00
|
|
|
<a className={`button button--destructive ${authorizing ? 'button--working' :''}`} onClick={(e) => this.props.spotifyActions.revokeAuthorization()}>Log out</a>
|
2019-09-05 15:36:11 +12:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
2019-12-09 07:17:45 +13:00
|
|
|
<a className={`button button--primary ${authorizing ? 'button--working' :''}`} onClick={(e) => this.startAuthorization()}>Log in</a>
|
|
|
|
|
);
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
2016-10-16 12:37:37 +13:00
|
|
|
}
|
|
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
const mapStateToProps = (state, ownProps) => ({
|
|
|
|
|
authorization_url: state.spotify.authorization_url,
|
|
|
|
|
authorized: state.spotify.authorization,
|
|
|
|
|
authorizing: state.spotify.authorizing,
|
|
|
|
|
});
|
2016-10-16 12:37:37 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
uiActions: bindActionCreators(uiActions, dispatch),
|
|
|
|
|
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
|
|
|
|
});
|
2016-10-16 12:37:37 +13:00
|
|
|
|
2019-12-09 07:17:45 +13:00
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(SpotifyAuthenticationFrame);
|