attache_client 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -0
- data/app/assets/javascripts/attache/bootstrap3.js +6 -5
- data/app/assets/javascripts/attache/bootstrap3.js.jsx +6 -5
- data/app/assets/javascripts/attache/cors_upload.js +15 -5
- data/lib/attache_client.rb +11 -1
- data/lib/attache_client/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85797f28c584f9b228fa2109cd30bd897f1fb722
|
4
|
+
data.tar.gz: 9d8bcc930c642e7b53ff2103bd847b7d6e3590fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b62f1989a4eac6e82ca9b155694535f73c6eb88f6a9f4f3bc70898ab4172dbb3504f94806912a9b15c49b573d143d01012b5c7443e8b1415af3be06c753c3474
|
7
|
+
data.tar.gz: 7d5f934642057ba36dd4ce6c9a79d29fc8899d03e156805012885652f1e487e4a9e9ff69b7b21cac4c1ab3034ba0ee953530523d75c5641a3c4d670219af54f1
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Ruby on Rails integration for [attache server](https://github.com/choonkeat/attache)
|
4
4
|
|
5
|
+
NOTE: You can learn how to use this gem by looking at the [changes made to our example app](https://github.com/choonkeat/attache-railsapp/commit/16cb1274dcce5be01b6c9d42ad60c30c106ad7f9) or follow the step by step instructions in this `README`
|
6
|
+
|
5
7
|
## Dependencies
|
6
8
|
|
7
9
|
[React](https://github.com/reactjs/react-rails), jQuery, Bootstrap 3
|
@@ -123,6 +125,20 @@ Alternatively, you can get the list of urls and manipulate it however you want
|
|
123
125
|
= image_tag attache_urls(@user.photo_path, '128x128#').sample
|
124
126
|
```
|
125
127
|
|
128
|
+
### Environment configs
|
129
|
+
|
130
|
+
`ATTACHE_UPLOAD_URL` points to the attache server upload url. e.g. `http://localhost:9292/upload`
|
131
|
+
|
132
|
+
`ATTACHE_DOWNLOAD_URL` points to url prefix for downloading the resized images, e.g. `http://cdn.lvh.me:9292/view`
|
133
|
+
|
134
|
+
`ATTACHE_UPLOAD_DURATION` refers to the number of seconds before a signed upload request is considered expired, e.g. `600`
|
135
|
+
|
136
|
+
`ATTACHE_SECRET_KEY` is the shared secret with the `attache` server. e.g. `t0psecr3t`
|
137
|
+
|
138
|
+
* If this variable is not set, then upload requests will not be signed & `ATTACHE_UPLOAD_DURATION` will be ignored
|
139
|
+
* If this variable is set, it must be the same value as `SECRET_KEY` is set on the `attache` server
|
140
|
+
|
141
|
+
|
126
142
|
# License
|
127
143
|
|
128
144
|
MIT
|
@@ -23,9 +23,10 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
|
23
23
|
this.state.files = {};
|
24
24
|
this.setState(this.state);
|
25
25
|
// upload the file via CORS
|
26
|
+
var that = this;
|
26
27
|
new CORSUpload({
|
27
28
|
file_element: file_element, onComplete: this.setFileValue, onProgress: this.setFileValue,
|
28
|
-
onError: function(uid, status) {
|
29
|
+
onError: function(uid, status) { that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' }); }
|
29
30
|
});
|
30
31
|
// we don't want the file binary to be uploaded in the main form
|
31
32
|
file_element.value = '';
|
@@ -73,13 +74,13 @@ var AttacheFilePreview = React.createClass({displayName: "AttacheFilePreview",
|
|
73
74
|
},
|
74
75
|
|
75
76
|
render: function() {
|
76
|
-
var className = "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
77
|
-
var pctString = (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
78
|
-
var pctDesc = (this.props.src ? 'Loading...' : pctString);
|
77
|
+
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
78
|
+
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
79
|
+
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
79
80
|
var img = (this.props.src ? (React.createElement("img", {src: this.props.src, onLoad: this.removeProgressBar})) : '');
|
80
81
|
var pctStyle = { width: pctString, minWidth: '3em' };
|
81
82
|
var cptStyle = { textOverflow: "ellipsis" };
|
82
|
-
var caption = React.createElement("div", {className: "pull-left", style: cptStyle}, this.props.filename || this.props.path.split('/').pop());
|
83
|
+
var caption = React.createElement("div", {className: "pull-left", style: cptStyle}, this.props.filename || this.props.path && this.props.path.split('/').pop());
|
83
84
|
|
84
85
|
if (this.state.srcWas != this.props.src) {
|
85
86
|
var progress = (
|
@@ -23,9 +23,10 @@ var AttacheFileInput = React.createClass({
|
|
23
23
|
this.state.files = {};
|
24
24
|
this.setState(this.state);
|
25
25
|
// upload the file via CORS
|
26
|
+
var that = this;
|
26
27
|
new CORSUpload({
|
27
28
|
file_element: file_element, onComplete: this.setFileValue, onProgress: this.setFileValue,
|
28
|
-
onError: function(uid, status) {
|
29
|
+
onError: function(uid, status) { that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' }); }
|
29
30
|
});
|
30
31
|
// we don't want the file binary to be uploaded in the main form
|
31
32
|
file_element.value = '';
|
@@ -73,13 +74,13 @@ var AttacheFilePreview = React.createClass({
|
|
73
74
|
},
|
74
75
|
|
75
76
|
render: function() {
|
76
|
-
var className = "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
77
|
-
var pctString = (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
78
|
-
var pctDesc = (this.props.src ? 'Loading...' : pctString);
|
77
|
+
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
78
|
+
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
79
|
+
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
79
80
|
var img = (this.props.src ? (<img src={this.props.src} onLoad={this.removeProgressBar} />) : '');
|
80
81
|
var pctStyle = { width: pctString, minWidth: '3em' };
|
81
82
|
var cptStyle = { textOverflow: "ellipsis" };
|
82
|
-
var caption = <div className="pull-left" style={cptStyle}>{this.props.filename || this.props.path.split('/').pop()}</div>;
|
83
|
+
var caption = <div className="pull-left" style={cptStyle}>{this.props.filename || this.props.path && this.props.path.split('/').pop()}</div>;
|
83
84
|
|
84
85
|
if (this.state.srcWas != this.props.src) {
|
85
86
|
var progress = (
|
@@ -14,8 +14,17 @@ var CORSUpload = (function() {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
CORSUpload.prototype.handleFileSelect = function(file_element) {
|
17
|
-
var f, files, output, _i, _len, _results, url;
|
18
|
-
|
17
|
+
var f, files, output, _i, _len, _results, url, $ele;
|
18
|
+
$ele = $(file_element);
|
19
|
+
url = $ele.data('uploadurl');
|
20
|
+
if ($ele.data('hmac')) {
|
21
|
+
url = url +
|
22
|
+
"?hmac=" + encodeURIComponent($ele.data('hmac')) +
|
23
|
+
"&uuid=" + encodeURIComponent($ele.data('uuid')) +
|
24
|
+
"&expiration=" + encodeURIComponent($ele.data('expiration')) +
|
25
|
+
""
|
26
|
+
}
|
27
|
+
|
19
28
|
files = file_element.files;
|
20
29
|
output = [];
|
21
30
|
_results = [];
|
@@ -45,7 +54,8 @@ var CORSUpload = (function() {
|
|
45
54
|
CORSUpload.prototype.performUpload = function(file, url) {
|
46
55
|
var this_s3upload, xhr;
|
47
56
|
this_s3upload = this;
|
48
|
-
|
57
|
+
url = url + (url.indexOf('?') == -1 ? '?' : '&') + 'file=' + encodeURIComponent(file.name);
|
58
|
+
xhr = this.createCORSRequest('PUT', url);
|
49
59
|
if (!xhr) {
|
50
60
|
this.onError(file.uid, 'CORS not supported');
|
51
61
|
} else {
|
@@ -53,11 +63,11 @@ var CORSUpload = (function() {
|
|
53
63
|
if (xhr.status === 200) {
|
54
64
|
this_s3upload.onComplete(file.uid, JSON.parse(e.target.responseText));
|
55
65
|
} else {
|
56
|
-
return this_s3upload.onError(file.uid,
|
66
|
+
return this_s3upload.onError(file.uid, xhr.status + ' ' + xhr.statusText);
|
57
67
|
}
|
58
68
|
};
|
59
69
|
xhr.onerror = function() {
|
60
|
-
return this_s3upload.onError(file.uid, '
|
70
|
+
return this_s3upload.onError(file.uid, 'Unable to reach server');
|
61
71
|
};
|
62
72
|
xhr.upload.onprogress = function(e) {
|
63
73
|
var percentLoaded;
|
data/lib/attache_client.rb
CHANGED
@@ -4,6 +4,7 @@ module AttacheClient
|
|
4
4
|
module ViewHelper
|
5
5
|
ATTACHE_UPLOAD_URL = ENV.fetch('ATTACHE_UPLOAD_URL') { 'http://localhost:9292/upload' }
|
6
6
|
ATTACHE_DOWNLOAD_URL = ENV.fetch('ATTACHE_DOWNLOAD_URL') { 'http://localhost:9292/view' }
|
7
|
+
ATTACHE_UPLOAD_DURATION = ENV.fetch('ATTACHE_UPLOAD_DURATION') { '600' }.to_i # 10 minutes
|
7
8
|
|
8
9
|
def attache_urls(json, geometry)
|
9
10
|
array = json.kind_of?(Array) ? json : [*json]
|
@@ -17,6 +18,15 @@ module AttacheClient
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def attache_options(geometry, current_value)
|
21
|
+
auth = if ENV['ATTACHE_SECRET_KEY']
|
22
|
+
uuid = SecureRandom.uuid
|
23
|
+
expiration = (Time.now + ATTACHE_UPLOAD_DURATION).to_i
|
24
|
+
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), ENV['ATTACHE_SECRET_KEY'], "#{uuid}#{expiration}")
|
25
|
+
{ uuid: uuid, expiration: expiration, hmac: hmac }
|
26
|
+
else
|
27
|
+
{}
|
28
|
+
end
|
29
|
+
|
20
30
|
{
|
21
31
|
class: 'enable-attache',
|
22
32
|
data: {
|
@@ -24,7 +34,7 @@ module AttacheClient
|
|
24
34
|
value: [*current_value],
|
25
35
|
uploadurl: ATTACHE_UPLOAD_URL,
|
26
36
|
downloadurl: ATTACHE_DOWNLOAD_URL,
|
27
|
-
},
|
37
|
+
}.merge(auth),
|
28
38
|
}
|
29
39
|
end
|
30
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attache_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- choonkeat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|