Add component for signing S3 url

This commit is contained in:
Tim Daubenschütz 2016-02-17 11:38:01 +01:00
parent 2cb8fb2dd9
commit f2c7f02480
6 changed files with 109 additions and 15 deletions

View File

@ -0,0 +1,91 @@
'use strict';
import React from 'react';
import S3Fetcher from '../../fetchers/s3_fetcher';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils';
import { queryParamsToArgs } from '../../utils/url_utils';
const { string } = React.PropTypes;
const S3DownloadButton = React.createClass({
propTypes: {
url: string,
title: string,
artistName: string,
fileExtension: string
},
getInitialState() {
return {
downloadUrl: null
};
},
componentDidMount() {
/**
* Initially, we request a signed url from
* the backend
*/
this.signUrl();
},
transformS3UrlToS3Key(url) {
return url.replace(`https://${AppConstants.cloudfrontDomain}/`, '');
},
signUrl(next) {
const { url, title, artistName } = this.props;
S3Fetcher
.signUrl(this.transformS3UrlToS3Key(url), title, artistName)
.then(({ signed_url: downloadUrl }) => this.setState({ downloadUrl }, next))
.catch(console.logGlobal);
},
reSignUrl(event) {
/**
* The signed url, however can expire, which is why
* we need to renew it when it expires.
*/
const { downloadUrl } = this.state;
const { expires } = queryParamsToArgs(downloadUrl.split('?')[1]);
const nowInSeconds = new Date().getTime() / 1000;
if(nowInSeconds > expires) {
event.preventDefault();
this.signUrl(() => this.refs.downloadButton.getDOMNode().click());
}
},
render() {
const { fileExtension, url } = this.props;
const { downloadUrl } = this.state;
return (
<span>
<a
ref="downloadButton"
download
className="btn btn-xs btn-default ascribe-margin-1px"
target="_blank"
onClick={this.reSignUrl}
href={downloadUrl || url}>
{/*
If it turns out that `fileExtension` is an empty string, we're just
using the label 'file'.
*/}
{getLangText('Download')} .{fileExtension || 'file'} <Glyphicon glyph="cloud-download" />
</a>
</span>
);
}
});
export default S3DownloadButton;

View File

@ -3,13 +3,14 @@
import React from 'react';
import Button from 'react-bootstrap/lib/Button';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import MediaPlayer from './../ascribe_media/media_player';
import FacebookShareButton from '../ascribe_social_share/facebook_share_button';
import TwitterShareButton from '../ascribe_social_share/twitter_share_button';
import S3DownloadButton from '../ascribe_buttons/s3_download_button';
import CollapsibleButton from './../ascribe_collapsible/collapsible_button';
import AclProxy from '../acl_proxy';
@ -131,17 +132,11 @@ let MediaContainer = React.createClass({
show={['video', 'audio', 'image'].indexOf(mimetype) === -1 || content.acl.acl_download}
aclObject={content.acl}
aclName="acl_download">
<a
download
className="btn btn-xs btn-default ascribe-margin-1px"
href={content.digital_work.url}
target="_blank">
{/*
If it turns out that `fileExtension` is an empty string, we're just
using the label 'file'.
*/}
{getLangText('Download')} .{fileExtension || 'file'} <Glyphicon glyph="cloud-download" />
</a>
<S3DownloadButton
url={content.digital_work.url}
title={content.title}
artistName={content.artist_name}
fileExtension={fileExtension} />
</AclProxy>
{embed}
</p>

View File

@ -76,7 +76,8 @@ let ApiUrls = {
'webhooks': AppConstants.apiEndpoint + 'webhooks/',
'webhooks_events': AppConstants.apiEndpoint + 'webhooks/events/',
'whitelabel_settings': AppConstants.apiEndpoint + 'whitelabel/settings/${subdomain}/',
'delete_s3_file': AppConstants.serverUrl + 's3/delete/'
'delete_s3_file': AppConstants.serverUrl + 's3/delete/',
'sign_url_s3': AppConstants.serverUrl + 's3/sign_url/'
};

View File

@ -119,7 +119,7 @@ const constants = {
'twitter': {
'sdkUrl': 'https://platform.twitter.com/widgets.js'
},
'cloudfrontDomain': 'd1qjsxua1o9x03.cloudfront.net',
'errorMessagesToIgnore': [
'Authentication credentials were not provided.',
'Informations d\'authentification non fournies.'

View File

@ -11,6 +11,13 @@ let S3Fetcher = {
key,
bucket
});
},
signUrl(key, title, artistName) {
return requests.get('sign_url_s3', {
'artist_name': artistName,
key,
title
});
}
};

View File

@ -70,7 +70,7 @@ class Requests {
}
}).catch(reject);
});
}
};
}
getUrl(url) {