el_finder_s3 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: da39c62708b7a593b641c04c5faf89b538a5c3d0
4
+ data.tar.gz: 064b8666cefc4d58d674d6686f550673dc777718
5
+ SHA512:
6
+ metadata.gz: fefb3d47003af89571909ff973534f80a0016c517c534a1a5a81624ce62fc2af24af8ed0a981e4526fb9d688ed799c24327209db8e019835a5c78dde0cc91fde
7
+ data.tar.gz: 27aa78745a92d4e40251a26e18b5999b023c58d639a59cd51636e9d23c9e6ca58f4fbda7976d3cd7a969a10673c0c5a6d25a5b9cdc32f5bdc4015c8ac65b3298
data/.editorconfig ADDED
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.md]
12
+ trim_trailing_whitespace = false
data/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ /Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
36
+ .idea
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Raúl Morales
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # el_finder_s3
2
+ Ruby gem to provide server side connector to elFinder using AWS S3 like a container
3
+
4
+ ## Description
5
+
6
+ This is based on cdmicacc's Ruby library to provide server side ftp functionality over elFinder ruby gem of Phallstrom.
7
+
8
+ - cdmicacc project: https://github.com/cdmicacc/el_finder_ftp
9
+ - phallstrom project: https://github.com/phallstrom/el_finder
10
+
11
+
12
+ ## Rails 4
13
+
14
+ ```ruby
15
+ include ElFinderS3::Action
16
+
17
+ def elfinder
18
+ ElFinderS3::Connector.new(
19
+ :mime_handler => ElFinderS3::MimeType,
20
+ :root => '/',
21
+ :url => 'CDN_BASE_PATH'
22
+ :thumbs => true,
23
+ :thumbs_size => 100,
24
+ :thumbs_directory => 'thumbs',
25
+ :home => t('admin.media.home'),
26
+ :original_filename_method => lambda { |file| "#{File.basename(file.original_filename, File.extname(file.original_filename)).parameterize}#{File.extname(file.original_filename)}" },
27
+ :default_perms => {:read => true, :write => true, :rm => true, :hidden => false},
28
+ :server => {
29
+ :bucket_name => 'BUCKET_NAME',
30
+ :region => 'AWS_REGION',
31
+ :access_key_id => 'ACCESS_KEY_ID',
32
+ :secret_access_key => 'SECRET_ACCESS_KEY',
33
+ :cdn_base_path => 'CDN_BASE_PATH'
34
+ }
35
+ ).run(params)
36
+ end
37
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'el_finder_s3'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'el_finder_s3/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'el_finder_s3'
8
+ spec.version = ElFinderS3::VERSION
9
+ spec.authors = ['Raúl Anatol']
10
+ spec.email = ['raul@natol.es']
11
+
12
+ spec.summary = %q{elFinder server side connector for Ruby, with an S3 aws service.}
13
+ spec.description = %q{Ruby gem to provide server side connector to elFinder using AWS S3 like a container}
14
+ spec.homepage = 'https://github.com/raulanatol/el_finder_s3'
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_dependency('aws-sdk', '~> 2')
31
+ #FIXME remove after testing
32
+ spec.add_dependency('net-ftp-list', '~> 3.2')
33
+
34
+ spec.add_development_dependency 'bundler', '~> 1.10'
35
+ spec.add_development_dependency 'rake', '~> 10.0'
36
+ end
@@ -0,0 +1,14 @@
1
+ # require 'fileutils'
2
+ # require 'net/ftp'
3
+
4
+ require 'el_finder_s3/cache_connector'
5
+ require 'el_finder_s3/adapter'
6
+ require 'el_finder_s3/railties'
7
+ require 'el_finder_s3/base64'
8
+ require 'el_finder_s3/s3_connector'
9
+ require 'el_finder_s3/s3_pathname'
10
+ require 'el_finder_s3/pathname'
11
+ require 'el_finder_s3/mime_type'
12
+ require 'el_finder_s3/image'
13
+ require 'el_finder_s3/connector'
14
+ require 'el_finder_s3/action'
@@ -0,0 +1,32 @@
1
+ module ElFinderS3
2
+ module Action
3
+ class << self
4
+ def included(klass)
5
+ klass.send(:extend, ElFinderS3::ActionClass)
6
+ end
7
+ end
8
+ end
9
+
10
+ module ActionClass
11
+ def el_finder_ftp(name = :elfinder, &block)
12
+ self.send(:define_method, name) do
13
+ h, r = ElFinderS3::Connector.new(instance_eval(&block)).run(params)
14
+ headers.merge!(h)
15
+ if r.include?(:file_data)
16
+ send_data r[:file_data], type: r[:mime_type], disposition: r[:disposition], filename: r[:filename]
17
+ else
18
+ if browser.ie8? || browser.ie9?
19
+ # IE 8 and IE 9 don't accept application/json as a response to a POST in some cases:
20
+ # http://blog.degree.no/2012/09/jquery-json-ie8ie9-treats-response-as-downloadable-file/
21
+ # so we send text/html instead
22
+ response = (r.empty? ? {:nothing => true} : {:text => r.to_json})
23
+ else
24
+ response = (r.empty? ? {:nothing => true} : {:json => r})
25
+ end
26
+
27
+ render response, :layout => false
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,222 @@
1
+ module ElFinderS3
2
+ class Adapter
3
+ attr_reader :connection, :server, :s3_connector
4
+
5
+ def initialize(server)
6
+ @server = {
7
+ response_cache_expiry_seconds: 3000
8
+ }
9
+ @cached_responses = {}
10
+ @s3_connector = ElFinderS3::S3Connector.new server
11
+ end
12
+
13
+ def connect
14
+ @connection
15
+ end
16
+
17
+ def close
18
+ true
19
+ end
20
+
21
+ def children(pathname, with_directory)
22
+ cached :children, pathname do
23
+ @s3_connector.ls_la(pathname, with_directory)
24
+ end
25
+ end
26
+
27
+ def touch(pathname, options={})
28
+ @s3_connector.touch(pathname.to_file_prefix_s)
29
+ end
30
+
31
+ def exist?(pathname)
32
+ cached :exist?, pathname do
33
+ @s3_connector.exist? pathname
34
+ end
35
+ end
36
+
37
+ # @param [ElFinderS3::Pathname] pathname
38
+ def path_type(pathname)
39
+ cached :path_type, pathname do
40
+ result = :directory
41
+ begin
42
+ if pathname.to_s == '/'
43
+ result = :directory
44
+ end
45
+ rescue
46
+ result = pathname[:type]
47
+ end
48
+ return result
49
+ end
50
+ end
51
+
52
+ def size(pathname)
53
+ #FIXME
54
+ # cached :size, pathname do
55
+ # ftp_context do
56
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Getting size of #{pathname}"
57
+ # begin
58
+ # size(pathname.to_s)
59
+ # rescue Net::FTPPermError => e
60
+ # nil
61
+ # rescue Net::FTPReplyError => e
62
+ # nil
63
+ # end
64
+ # end
65
+ # end
66
+ end
67
+
68
+ #FIXME
69
+ def mtime(pathname)
70
+ cached :mtime, pathname do
71
+ # ftp_context do
72
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Getting modified time of #{pathname}"
73
+ # begin
74
+ # mtime(pathname.to_s)
75
+ # rescue Net::FTPPermError => e
76
+ # This command doesn't work on directories
77
+ 0
78
+ # end
79
+ # end
80
+ end
81
+ end
82
+
83
+ #FIXME
84
+ def rename(pathname, new_name)
85
+ # ftp_context do
86
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Renaming #{pathname} to #{new_name}"
87
+ # rename(pathname.to_s, new_name.to_s)
88
+ # end
89
+ # clear_cache(pathname)
90
+ end
91
+
92
+ ##
93
+ # Both rename and move perform an FTP RNFR/RNTO (rename). Move differs because
94
+ # it first changes to the parent of the source pathname and uses a relative path for
95
+ # the RNFR. This seems to allow the (Microsoft) FTP server to rename a directory
96
+ # into another directory (e.g. /subdir/target -> /target )
97
+ def move(pathname, new_name)
98
+ #FIXME
99
+ # ftp_context(pathname.dirname) do
100
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Moving #{pathname} to #{new_name}"
101
+ # rename(pathname.basename.to_s, new_name.to_s)
102
+ # end
103
+ # clear_cache(pathname)
104
+ # clear_cache(new_name)
105
+ end
106
+
107
+ def mkdir(pathname)
108
+ if @s3_connector.mkdir(pathname.to_prefix_s)
109
+ #FIXME review cache clear
110
+ # clear_cache(pathname)
111
+ true
112
+ else
113
+ false
114
+ end
115
+ end
116
+
117
+ def rmdir(pathname)
118
+ #FIXME
119
+ # ftp_context do
120
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Removing directory #{pathname}"
121
+ # rmdir(pathname.to_s)
122
+ # end
123
+ # clear_cache(pathname)
124
+ end
125
+
126
+ def delete(pathname)
127
+ #FIXME
128
+ # ftp_context do
129
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Deleting #{pathname}"
130
+ # if pathname.directory?
131
+ # rmdir(pathname.to_s)
132
+ # else
133
+ # delete(pathname.to_s)
134
+ # end
135
+ # end
136
+ # clear_cache(pathname)
137
+ end
138
+
139
+ def retrieve(pathname)
140
+ #FIXME
141
+ # ftp_context do
142
+ # ElFinderS3::Connector.logger.debug " \e[1;32mFTP:\e[0m Retrieving #{pathname}"
143
+ # content = StringIO.new()
144
+ # begin
145
+ # retrbinary("RETR #{pathname}", 10240) do |block|
146
+ # content << block
147
+ # end
148
+ # content.string
149
+ # ensure
150
+ # content.close
151
+ # end
152
+ # end
153
+ end
154
+
155
+ def store(pathname, content)
156
+ @s3_connector.store(pathname.to_file_prefix_s, content)
157
+ #TODO clear_cache(pathname)
158
+ end
159
+
160
+ private
161
+
162
+ ##
163
+ # Remove all entries for the given pathname (and its parent folder)
164
+ # from the FTP cache
165
+ def clear_cache(pathname)
166
+ @cached_responses.delete(pathname.to_s)
167
+
168
+ if pathname.to_s != '/' && pathname.to_s != '.'
169
+ # Clear parent of this entry, too
170
+ @cached_responses.delete(pathname.dirname.to_s)
171
+ end
172
+ end
173
+
174
+ ##
175
+ # Looks in the cache for an entry for the given pathname and operation,
176
+ # returning the cached result if one is found. If one is not found, the given
177
+ # block is invoked and its result is stored in the cache and returned
178
+ #
179
+ # The FTP cache is used to prevent redundant FTP queries for information such as a
180
+ # file's size, or a directory's contents, during a *single* FTP session.
181
+ def cached(operation, pathname)
182
+ response = cache_get(operation, pathname)
183
+ unless response.nil?
184
+ return response
185
+ end
186
+
187
+ response = yield
188
+ cache_put operation, pathname, response
189
+
190
+ response
191
+ end
192
+
193
+ ##
194
+ # Store an FTP response in the cache
195
+ def cache_put(operation, pathname, response)
196
+ @cached_responses[pathname.to_s] = {} unless @cached_responses.include?(pathname.to_s)
197
+
198
+ @cached_responses[pathname.to_s][operation] = {
199
+ timestamp: Time.now,
200
+ response: response
201
+ }
202
+ end
203
+
204
+ ##
205
+ # Fetch an FTP response from the cache
206
+ def cache_get(operation, pathname)
207
+ if @cached_responses.include?(pathname.to_s) && @cached_responses[pathname.to_s].include?(operation)
208
+ response = @cached_responses[pathname.to_s][operation]
209
+
210
+ #FIXME cache timeout
211
+ # max_staleness = Time.now - @server[:response_cache_expiry_seconds]
212
+
213
+ # if response[:timestamp] < max_staleness
214
+ # @cached_responses[pathname.to_s].delete(operation)
215
+ # nil
216
+ # else
217
+ response[:response]
218
+ # end
219
+ end
220
+ end
221
+ end
222
+ end