snapimage 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/README.md +2 -2
  2. data/bin/snapimage_generate_config +40 -7
  3. data/lib/snapimage.rb +5 -13
  4. data/lib/snapimage/adapters/cloudinary/config.rb +13 -0
  5. data/lib/snapimage/adapters/cloudinary/storage.rb +22 -0
  6. data/lib/snapimage/adapters/local/config.rb +14 -0
  7. data/lib/snapimage/adapters/local/storage.rb +48 -0
  8. data/lib/snapimage/config.rb +3 -1
  9. data/lib/snapimage/exceptions.rb +0 -6
  10. data/lib/snapimage/middleware.rb +2 -1
  11. data/lib/snapimage/rack/request.rb +1 -1
  12. data/lib/snapimage/rack/response.rb +2 -10
  13. data/lib/snapimage/server.rb +12 -17
  14. data/lib/snapimage/storage.rb +10 -0
  15. data/lib/snapimage/version.rb +1 -1
  16. data/snapimage.gemspec +0 -1
  17. data/spec/acceptance/upload_spec.rb +45 -3
  18. data/spec/snapimage/adapters/local/storage_spec.rb +44 -0
  19. data/spec/snapimage/middleware_spec.rb +2 -0
  20. data/spec/snapimage/rack/request_spec.rb +3 -9
  21. data/spec/snapimage/server_spec.rb +27 -11
  22. data/spec/support/assets/config.json +2 -0
  23. data/spec/support/assets/config.yml +2 -0
  24. metadata +9 -34
  25. data/lib/snapimage/image/image.rb +0 -103
  26. data/lib/snapimage/image/image_name_utils.rb +0 -131
  27. data/lib/snapimage/server_actions/server_actions.authorize.rb +0 -69
  28. data/lib/snapimage/server_actions/server_actions.delete_resource_images.rb +0 -23
  29. data/lib/snapimage/server_actions/server_actions.generate_image.rb +0 -169
  30. data/lib/snapimage/server_actions/server_actions.list_resource_images.rb +0 -23
  31. data/lib/snapimage/server_actions/server_actions.sync_resource.rb +0 -78
  32. data/lib/snapimage/storage/storage.rb +0 -120
  33. data/lib/snapimage/storage/storage_server.local.rb +0 -120
  34. data/lib/snapimage/storage/storage_server.rb +0 -110
@@ -1,120 +0,0 @@
1
- module SnapImage
2
- module StorageServer
3
- class Local < SnapImage::StorageServer::Base
4
- def validate_config
5
- super
6
- raise InvalidStorageConfig, 'Missing "local_root"' unless @config["local_root"]
7
- end
8
-
9
- def store_file(file, type, resource_id)
10
- image = SnapImage::Image.from_blob(file.read)
11
- name = SnapImage::ImageNameUtils.generate_image_name(image.width, image.height, type)
12
- store(image, name, resource_id)
13
- end
14
-
15
- def store_url(url, type, resource_id)
16
- image = SnapImage::Image.from_blob(URI.parse(url).read)
17
- name = SnapImage::ImageNameUtils.generate_image_name(image.width, image.height, type)
18
- store(image, name, resource_id)
19
- end
20
-
21
- def store_image(image, name, resource_id)
22
- store(image, name, resource_id)
23
- end
24
-
25
- def get(url)
26
- path = public_url_to_local_path(url)
27
- raise SnapImage::FileDoesNotExist, "Missing file: #{path}" unless File.exists?(path)
28
- SnapImage::Image.from_path(path, url)
29
- end
30
-
31
- def get_resource_urls(resource_id, timestamp = nil)
32
- urls = []
33
- get_resource_filenames(resource_id).each do |filename|
34
- urls.push(local_path_to_public_url(filename)) if file_modified_before_timestamp?(filename, timestamp)
35
- end
36
- urls
37
- end
38
-
39
- def delete(url)
40
- path = public_url_to_local_path(url)
41
- raise SnapImage::FileDoesNotExist, "Missing file: #{path}" unless File.exists?(path)
42
- File.delete(path)
43
- end
44
-
45
- def delete_resource_images(resource_id)
46
- deleted_urls = get_resource_urls(resource_id)
47
- FileUtils.rm_rf(File.join(root, resource_id)) if deleted_urls.size > 0
48
- deleted_urls
49
- end
50
-
51
- private
52
-
53
- # Stores the image and returns a SnapImage::Image object.
54
- # If the image does not fit within the server max width/height, the image
55
- # is resized and the modified image is returned.
56
- # Arguments:
57
- # * image:: SnapImage::Image to store
58
- # * name:: Suggested name to use
59
- # * resource_id:: Resource identifier
60
- def store(image, name, resource_id)
61
- result = resize_to_fit(image, name)
62
- image = result[:image]
63
- name = result[:name]
64
-
65
- # Generate the filename and public url.
66
- local_path = File.join(resource_id, name)
67
- image.public_url = "#{File.join(@config["public_url"], local_path)}"
68
-
69
- # Store the file.
70
- path = File.join(root, local_path)
71
- # Ensure the directory exists accounting for the resource_id.
72
- dir = File.dirname(path)
73
- FileUtils.mkdir_p(dir)
74
- # Write the file to the storage.
75
- File.open(path, "wb") { |f| f.write(image.blob) }
76
-
77
- # Return the image.
78
- image
79
- end
80
-
81
- def root
82
- unless @root_exists
83
- FileUtils.mkdir_p(@config["local_root"]) unless File.directory?(@config["local_root"])
84
- @root_exists = true
85
- end
86
- @config["local_root"]
87
- end
88
-
89
- def get_local_path_parts(path)
90
- match = path.match(/#{root}\/(.+)\/([^\/]+\.(png|jpg|gif))/)
91
- return match && {
92
- resource_id: match[1],
93
- filename: match[2]
94
- }
95
- end
96
-
97
- def local_path_to_public_url(path)
98
- parts = get_local_path_parts(path)
99
- "#{File.join(@config["public_url"], parts[:resource_id], parts[:filename])}"
100
- end
101
-
102
- def public_url_to_local_path(url)
103
- parts = get_url_parts(url)
104
- path = File.join(root, parts[:path])
105
- end
106
-
107
- def get_resource_filenames(resource_id)
108
- Dir.glob(File.join(root, resource_id, "/**/*.{png,jpg,gif}"))
109
- end
110
-
111
- # Returns true if no timestamp is given or the file was modified before
112
- # the timestamp.
113
- def file_modified_before_timestamp?(filename, timestamp = nil)
114
- # File.mtime returns a Time object. Convert it to a DateTime because
115
- # timestamp is a DateTime.
116
- !timestamp || File.mtime(filename).to_datetime < timestamp
117
- end
118
- end
119
- end
120
- end
@@ -1,110 +0,0 @@
1
- module SnapImage
2
- module StorageServer
3
- class Base
4
- # Config:
5
- # * name:: Name of the storage.
6
- # * public_url:: URL to acces the storage.
7
- def initialize(config)
8
- @config = config
9
- validate_config
10
- end
11
-
12
- def name
13
- @config["name"]
14
- end
15
-
16
- # Returns a regular expression for matching urls handled by this storage
17
- # server.
18
- def url_regexp
19
- @url_regexp ||= /#{@config["public_url"]}\/.+?\.(png|gif|jpg)/
20
- end
21
-
22
- def local?(url)
23
- !!url.match(url_regexp)
24
- end
25
-
26
- # Stores the file in the storage and returns a SnapImage::Image object.
27
- # Arguments:
28
- # * file:: File object representing the file to store.
29
- # * type:: File type
30
- # * resource_id:: Resource identifier.
31
- def store_file(file, type, resource_id)
32
- raise "#store_file needs to be overridden."
33
- end
34
-
35
- # Downloads the file and adds it to the storage and returns a
36
- # SnapImage::Image object.
37
- # Arguments:
38
- # * url:: Url to get the image
39
- # * type:: File type
40
- # * resource_id:: Resource identifier.
41
- def store_url(url, type, resource_id)
42
- raise "#store_url needs to be overridden."
43
- end
44
-
45
- # Adds the image to the storage. Overwrites existing file.
46
- # Arguments:
47
- # * image:: SnapImage::Image object
48
- # * name:: Name of the image
49
- # * resource_id:: Resource identifier
50
- def store_image(image, name, resource_id)
51
- raise "#store_image needs to be overridden."
52
- end
53
-
54
- # Returns the SnapImage:Image object from the url.
55
- def get(url)
56
- raise "#get needs to be overriden."
57
- end
58
-
59
- # Returns all the image urls for the given resource in the storage.
60
- # Arguments:
61
- # * resource_id:: Filter by resource identifier
62
- # * timestamp:: Only images that were updated before the DateTime
63
- def get_resource_urls(resource_id, timestamp = nil)
64
- raise "#get_all_urls needs to be overriden."
65
- end
66
-
67
- # Deletes the given url.
68
- def delete(url)
69
- raise "#delete needs to be overridden."
70
- end
71
-
72
- # Deletes the given resource images.
73
- def delete_resource_images(resource_id)
74
- raise "#delete_resource needs to be overridden."
75
- end
76
-
77
- private
78
-
79
- # Validates the config. Subclasses should add to this.
80
- def validate_config
81
- raise InvalidStorageConfig, 'Missing "name"' unless @config["name"]
82
- raise InvalidStorageConfig, 'Missing "public_url"' unless @config["public_url"]
83
- raise InvalidStorageConfig, 'Missing "max_width"' unless @config["max_width"]
84
- raise InvalidStorageConfig, 'Missing "max_height"' unless @config["max_height"]
85
- end
86
-
87
- def get_url_parts(url)
88
- match = url.match(/^(([a-z]+):|)(#{@config["public_url"]})\/(.+)$/)
89
- return match && {
90
- protocol: match[2],
91
- public_url: match[3],
92
- path: match[4]
93
- }
94
- end
95
-
96
- # Resizes the image if it doesn't fit on the server. Updates the name if
97
- # needed.
98
- # Returns { image: resized_image, name: resized_name }.
99
- def resize_to_fit(image, name)
100
- # Resize the image if it's larger than the max width/height.
101
- if image.width > @config["max_width"] || image.height > @config["max_height"]
102
- image.resize([image.width, @config["max_width"]].min, [image.height, @config["max_height"]].min)
103
- # Generate a new name.
104
- name = SnapImage::ImageNameUtils.get_resized_image_name(name, image.width, image.height)
105
- end
106
- { image: image, name: name }
107
- end
108
- end
109
- end
110
- end