tinyzap 0.1.4

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +98 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/tinyzap_manifest.js +1 -0
  6. data/app/assets/stylesheets/tinyzap/application.css +15 -0
  7. data/app/controllers/concerns/tinyzap/open_graph.rb +43 -0
  8. data/app/controllers/tinyzap/application_controller.rb +4 -0
  9. data/app/helpers/tinyzap/application_helper.rb +4 -0
  10. data/app/helpers/tinyzap/open_graph_tag_helper.rb +7 -0
  11. data/app/jobs/tinyzap/application_job.rb +4 -0
  12. data/app/mailers/tinyzap/application_mailer.rb +6 -0
  13. data/app/models/tinyzap/application_record.rb +5 -0
  14. data/app/models/tinyzap/open_graph/base.rb +51 -0
  15. data/app/models/tinyzap/open_graph/image.rb +12 -0
  16. data/app/models/tinyzap/open_graph/metatag.rb +11 -0
  17. data/app/models/tinyzap/open_graph/metatag_mapper.rb +35 -0
  18. data/app/models/tinyzap/open_graph/model.rb +35 -0
  19. data/app/models/tinyzap/open_graph/twitter.rb +11 -0
  20. data/app/views/layouts/tinyzap/application.html.erb +15 -0
  21. data/config/initializers/inflections.rb +3 -0
  22. data/config/initializers/mime_types.rb +3 -0
  23. data/config/routes.rb +2 -0
  24. data/exe/tinyzap +4 -0
  25. data/lib/generators/tinyzap/install/USAGE +11 -0
  26. data/lib/generators/tinyzap/install/install_generator.rb +19 -0
  27. data/lib/generators/tinyzap/install/templates/application.opengraph.erb +15 -0
  28. data/lib/generators/tinyzap/install/templates/tinyzap.rb.tt +14 -0
  29. data/lib/tasks/tinyzap_tasks.rake +4 -0
  30. data/lib/tinyzap/cli.rb +23 -0
  31. data/lib/tinyzap/client.rb +13 -0
  32. data/lib/tinyzap/configuration.rb +18 -0
  33. data/lib/tinyzap/engine.rb +5 -0
  34. data/lib/tinyzap/key_generator.rb +43 -0
  35. data/lib/tinyzap/url_signature.rb +44 -0
  36. data/lib/tinyzap/version.rb +3 -0
  37. data/lib/tinyzap.rb +28 -0
  38. metadata +126 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1accdcd2a97326d9828e08162431229177c9de87f73648bf39df58f36ccaf84e
4
+ data.tar.gz: 1872a8d9330c3a77eba6848ba181b48e6de9285241478b5ba16f5ad4f7eb20aa
5
+ SHA512:
6
+ metadata.gz: ba985f66472361e4c5957d49537f83e4d31e92928888fd6b59b11d47b1d37c16fb93a2beb6f60b5ed028f676173af3bb8f633763d0a0d7b9041d145a4302f04b
7
+ data.tar.gz: e564ae50f51ef060029354f88760412c1777e06c993d1d03003230fcb08d7ab712f1aa92f570df494a6fbc1dcdfd9d829810c0f21a5e914b9892527dbcfde426
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Brad Gessler
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # TinyZap
2
+
3
+ [![Ruby](https://github.com/tinyzap/ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/tinyzap/ruby/actions/workflows/ruby.yml)
4
+
5
+ The easiest way to make Rails applications look great in Apple Messages, Facebook, LinkedIn, Twitter, and any other website that use Open Graph.
6
+
7
+
8
+ ## Installation
9
+
10
+ From the root of your Rails application, run:
11
+
12
+ ```bash
13
+ $ bundle add "tinyzap"
14
+ ```
15
+
16
+ Then run:
17
+
18
+ ```bash
19
+ $ rails generate tinyzap:install
20
+ ```
21
+
22
+ This creates a `app/views/layout/application.opengraph.erb` file and adds `include TinyZap::OpenGraph` to `ApplicationController`.
23
+
24
+ Add to your `app/views/layouts/application.html.erb` file:
25
+
26
+ ```
27
+ <head>
28
+ <%= opengraph_meta_tags %>
29
+ </head>
30
+ ```
31
+
32
+ That's it for the bare minimum! A screenshot of the top part of the webpage will appear by default for all open graph images. Custom badges are where its at though, so read on my friend.
33
+
34
+ ## Setting OpenGraph data
35
+
36
+ Open graph data can be set from the view or controller via the `opengraph` method.
37
+
38
+ ### Controller
39
+
40
+ Here's a few ways to set opengraph data from a controller.
41
+
42
+ ```ruby
43
+ class PostsController < ApplicationController
44
+ before_action: :assign_opengraph_data
45
+
46
+ def edit
47
+ # This overrides the title that's set from `assign_opengraph_data`
48
+ opengraph.title = "Editing #{@post.title}"
49
+ end
50
+
51
+ protected
52
+
53
+ def assign_opengraph_data
54
+ opengraph.title = @post.title
55
+ opengraph.description = @post.summary
56
+ # Displays the first image of a blog post, instead of a screenshot, for the opengraph image.
57
+ # Assumes the image was managed via ActiveStorage.
58
+ opengraph.image = url_for(@post.images.first)
59
+ end
60
+ end
61
+ ```
62
+
63
+ ### View
64
+
65
+ OpenGraph data may also be set from the view:
66
+
67
+ ```erb
68
+ <%
69
+ opengraph.title = @post.title
70
+ opengraph.description = @post.summary
71
+ %>
72
+
73
+ <h1><%= @post.title %></h1>
74
+ <article><%= @post.body %></article>
75
+ ```
76
+
77
+ ## Custom badges with Rails Views
78
+
79
+ The real power in TinyZap Open Graph is creating custom badges via the `opengraph` format in your rails views. For the example below, we'll create an Open Graph badge for a blog post. Assuming a blog application has a `/posts/:id` with a view at `app/views/posts/show.html.erb`, we'd create a new view with the `opengraph` format:
80
+
81
+ ```bash
82
+ $ touch ./app/views/posts/show.opengraph.erb
83
+ ```
84
+
85
+ Open the file and add something like:
86
+
87
+ ```erb
88
+
89
+ <h1><%= @post.title %></h1>
90
+ <article><%= truncate @post.body, length: 100 %></article>
91
+ <p>This article will take <%= time_to_read @post.body %> minutes to read</p>
92
+ ```
93
+
94
+ The TinyZap screenshot service will take a screenshot of the content at this URL and use it for the Open Graph image.
95
+
96
+ ## License
97
+
98
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/tinyzap .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,43 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ extend ActiveSupport::Concern
4
+
5
+ DEFAULT_OPENGRAPH_TYPE = "website".freeze
6
+
7
+ DEFAULT_OPENGRAPH_FALLBACK_FORMATS = [ :opengraph, :html ]
8
+ included do
9
+ before_action :assign_opengraph_fallback_formats, if: :opengraph_request?
10
+ before_action :assign_opengraph_defaults
11
+
12
+ helper TinyZap::OpenGraphTagHelper
13
+
14
+ helper_method :opengraph
15
+ end
16
+
17
+ protected
18
+ def assign_opengraph_fallback_formats
19
+ request.formats = DEFAULT_OPENGRAPH_FALLBACK_FORMATS
20
+ end
21
+
22
+ def opengraph_request?
23
+ request.format.opengraph?
24
+ end
25
+
26
+ def url_for_opengraph_image
27
+ tinyzap_opengraph_url url: url_for(format: :opengraph)
28
+ end
29
+
30
+ def tinyzap_opengraph_url(*args, **kwargs)
31
+ TinyZap.client.url_signature.url_for "opengraph", *args, **kwargs
32
+ end
33
+
34
+ def opengraph
35
+ @opengraph ||= Model.new
36
+ end
37
+
38
+ def assign_opengraph_defaults
39
+ opengraph.image ||= url_for_opengraph_image
40
+ opengraph.type ||= DEFAULT_OPENGRAPH_TYPE
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,4 @@
1
+ module TinyZap
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module TinyZap
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module TinyZap
2
+ module OpenGraphTagHelper
3
+ def opengraph_meta_tags(model=opengraph)
4
+ model.to_html
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module TinyZap
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module TinyZap
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module TinyZap
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,51 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ # Provides a way to specify OpenGraph keys for an OpenGraphModel, which can later
4
+ # be iterated upon to generate OpenGraph meta tags.
5
+ class Base
6
+ # Encapsulates OpenGraph properties and provides helpers that are
7
+ # useful for documentation purposes or for reflecting on Ruby objects.
8
+ class Property
9
+ attr_accessor :key, :name, :description, :default
10
+
11
+ def initialize(key, description = nil, default: nil)
12
+ @key = key
13
+ @description = description
14
+ # If we get a string like `og:image:url`, this would give us `url`
15
+ *_, @name = key.rpartition(":")
16
+ @default = default
17
+ end
18
+ end
19
+
20
+ # Allows for the object to be initialized with args like `Image.new(url: "https://example.com/logo.png", alt: "Logo image")`.
21
+ def initialize(**kwargs)
22
+ kwargs.each do |kwarg, value|
23
+ self.send("#{kwarg}=", value)
24
+ rescue NoMethodError
25
+ raise NoMethodError, "#{kwarg.inspect} is not a property of #{self.inspect}"
26
+ end
27
+ end
28
+
29
+ # DSL for creating properties when defining a model.
30
+ def self.property(*args, **kwargs)
31
+ property = Property.new *args, **kwargs
32
+ attr_accessor property.name
33
+ self.properties.append property
34
+ end
35
+
36
+ # Array where properties are registered.
37
+ def self.properties
38
+ @properties ||= []
39
+ end
40
+
41
+ # Iterates through the properties and also gets their value.
42
+ def properties
43
+ Enumerator.new do |y|
44
+ self.class.properties.each do |property|
45
+ y << [ property, (self.send(property.name) || property.default) ]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,12 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ class Image < Base
4
+ property "og:image:url", "Identical to og:image."
5
+ property "og:image:secure_url", "An alternate url to use if the webpage requires HTTPS."
6
+ property "og:image:type", "A MIME type for this image."
7
+ property "og:image:width", "The number of pixels wide."
8
+ property "og:image:height", "The number of pixels high."
9
+ property "og:image:alt", "A description of what is in the image (not a caption). If the page specifies an og:image it should specify og:image:alt."
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ class Metatag < Struct.new(:property, :content)
4
+ include ActionView::Helpers::TagHelper
5
+
6
+ def to_html
7
+ tag :meta, property: property, content: content
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ # Iterates recursively through an OpenGraph object and gets a bunch of
4
+ # metatags and keys.
5
+ class MetatagMapper
6
+ include ActionView::Helpers::OutputSafetyHelper
7
+
8
+ attr_reader :model
9
+ delegate :context,
10
+ to: :model
11
+
12
+ def initialize(model)
13
+ @model = model
14
+ end
15
+
16
+ def metatags
17
+ Enumerator.new do |y|
18
+ model.properties.each do |property, content|
19
+ if content.respond_to? :properties
20
+ MetatagMapper.new(content).metatags.each do |tag|
21
+ y << tag
22
+ end
23
+ else
24
+ y << Metatag.new(property.key, content) if content.present?
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def to_html
31
+ safe_join metatags.map(&:to_html), "\n"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ class Model < Base
4
+ property "og:title", %[The title of your object as it should appear within the graph, e.g., "The Rock".]
5
+ property "og:type", %[The type of your object, e.g., "video.movie". Depending on the type you specify, other properties may also be required.]
6
+ property "og:image", %[An image URL which should represent your object within the graph.]
7
+ property "og:url", %[The canonical URL of your object that will be used as its permanent ID in the graph, e.g., "https://www.imdb.com/title/tt0117500/".]
8
+ property "og:description", %[A one to two sentence description of your object.]
9
+ property "twitter", %[A one to two sentence description of your object.]
10
+
11
+ delegate :to_html, to: :metatag_mapper
12
+
13
+ def image
14
+ @image ||= Image.new
15
+ end
16
+
17
+ def image=(url)
18
+ image.url = url
19
+ end
20
+
21
+ def twitter
22
+ @twitter ||= Twitter.new.tap do |twitter|
23
+ twitter.title = title
24
+ twitter.description = description
25
+ twitter.image = image.url
26
+ end
27
+ end
28
+
29
+ private
30
+ def metatag_mapper
31
+ MetatagMapper.new(self)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module TinyZap
2
+ module OpenGraph
3
+ class Twitter < Base
4
+ property "twitter:card", "Type of card, which is 'summary_large_image'", default: "summary_large_image"
5
+ property "twitter:site", "Twitter @handle of the account"
6
+ property "twitter:title", "Title of the card, similar to og:title"
7
+ property "twitter:description", "Description of the card, similar to og:description"
8
+ property "twitter:image", "Image URL of the card, similar to og:image"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>TinyZap</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "tinyzap/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,3 @@
1
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
2
+ inflect.acronym "TinyZap"
3
+ end
@@ -0,0 +1,3 @@
1
+ # Used to represent the HTML pages that will be converted into an
2
+ # image and served up for open graph image previews.
3
+ Mime::Type.register_alias "text/html", :opengraph
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ TinyZap::Engine.routes.draw do
2
+ end
data/exe/tinyzap ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "tinyzap"
3
+
4
+ TinyZap::CLI.start ARGV
@@ -0,0 +1,11 @@
1
+ Description:
2
+ Installs TinyZap in Rails
3
+
4
+ Example:
5
+ bin/rails generate install:tinyzap
6
+
7
+ Creates the files:
8
+ app/views/layouts/application.opengraph.html
9
+
10
+ Patches ApplicationController by adding:
11
+ include TinyZap::OpenGraph
@@ -0,0 +1,19 @@
1
+ class TinyZap::InstallGenerator < Rails::Generators::Base
2
+ source_root File.expand_path("templates", __dir__)
3
+
4
+ def include_controller_helper
5
+ inject_into_file 'app/controllers/application_controller.rb', after: "class ApplicationController < ActionController::Base\n" do <<-'RUBY'
6
+ include TinyZap::OpenGraph
7
+
8
+ RUBY
9
+ end
10
+ end
11
+
12
+ def copy_layout
13
+ copy_file "application.opengraph.erb", "app/views/layouts/application.opengraph.erb"
14
+ end
15
+
16
+ def copy_configuration_file
17
+ template "tinyzap.rb.tt", "config/initializers/tinyzap.rb"
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= opengraph.title %></title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <%= csrf_meta_tags %>
7
+ <%= csp_meta_tag %>
8
+
9
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
10
+ <%= javascript_importmap_tags %>
11
+ </head>
12
+ <body>
13
+ <%= yield %>
14
+ </body>
15
+ </html>
@@ -0,0 +1,14 @@
1
+ TinyZap.configure do |config|
2
+ if Rails.env.production?
3
+ # For production deployments, set the following environment keys:
4
+ #
5
+ # ```
6
+ # TINYZAP_SECRET_KEY=
7
+ # TINYZAP_PUBLIC_KEY=
8
+ # ```
9
+ config.load_env
10
+ else
11
+ config.secret_key = "<%= TinyZap.key_generator.secret_key %>"
12
+ config.public_key = "<%= TinyZap.key_generator.public_key %>"
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :tinyzap do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,23 @@
1
+ require "thor"
2
+
3
+ module TinyZap
4
+ class CLI < Thor
5
+ include Thor::Actions
6
+
7
+ desc "install", "Install TinyZap to the Rails application"
8
+ def install
9
+ run "./bin/bundle add tinyzap"
10
+ run "./bin/rails generate tinyzap:install"
11
+ end
12
+
13
+ desc "version", "Prints the version of tinyzap"
14
+ def version
15
+ puts TinyZap::VERSION
16
+ end
17
+
18
+ desc "environment [ENVIRONMENT]", "Generates environment variables for target enrivonment"
19
+ def environment(environment = TinyZap::KeyGenerator::ENVIRONMENT)
20
+ puts TinyZap.key_generator(environment: environment).env_vars
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module TinyZap
2
+ class Client
3
+ delegate :secret_key, :public_key, to: :configuration
4
+
5
+ def url_signature
6
+ @url_signature ||= UrlSignature.new(secret_key: secret_key, public_key: public_key)
7
+ end
8
+
9
+ def configuration
10
+ @configuration ||= Configuration.new
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module TinyZap
2
+ class Configuration
3
+ attr_accessor :secret_key, :public_key
4
+
5
+ def load_secret_key_env
6
+ self.secret_key = ENV["TINYZAP_SECRET_KEY"]
7
+ end
8
+
9
+ def load_public_key_env
10
+ self.public_key = ENV["TINYZAP_PUBLIC_KEY"]
11
+ end
12
+
13
+ def load_env
14
+ load_secret_key_env
15
+ load_public_key_env
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module TinyZap
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace TinyZap
4
+ end
5
+ end
@@ -0,0 +1,43 @@
1
+ require "securerandom"
2
+
3
+ module TinyZap
4
+ # Generates random keys for environments.
5
+ class KeyGenerator
6
+ LENGTH = 14
7
+ DELIMITER = "_".freeze
8
+ ENVIRONMENT = :development
9
+
10
+ attr_reader :environment
11
+
12
+ def initialize(environment: ENVIRONMENT)
13
+ @environment = environment
14
+ end
15
+
16
+ def public_key
17
+ generate :public
18
+ end
19
+
20
+ def secret_key
21
+ generate :secret
22
+ end
23
+
24
+ def env_vars
25
+ <<~ENVARS
26
+ TINYZAP_SECRET_KEY=#{secret_key}
27
+ TINYZAP_PUBLIC_KEY=#{public_key}
28
+ ENVARS
29
+ end
30
+
31
+ def generate(*scopes)
32
+ scopes
33
+ .prepend(environment)
34
+ .append(random)
35
+ .join(DELIMITER)
36
+ end
37
+
38
+ private
39
+ def random
40
+ SecureRandom.hex(LENGTH)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ require "openssl"
2
+ require "uri"
3
+
4
+ module TinyZap
5
+ class UrlSignature
6
+ # Use for `OpenSSL::HMAC`
7
+ DIGEST = "SHA256".freeze
8
+
9
+ attr_reader :secret_key, :public_key, :path_prefix
10
+
11
+ def initialize(secret_key:, public_key:)
12
+ @secret_key = secret_key
13
+ @public_key = public_key
14
+ @path_prefix = File.join("/", "v1", public_key)
15
+ end
16
+
17
+ def signed_url(path)
18
+ URI.join("https://tinyzap.com/", signed_path(path))
19
+ end
20
+
21
+ def valid?(url)
22
+ path = URI(url).request_uri
23
+ version, account_key, signature, path = Regexp.new("/(v1)/(.+?)/(.+?)(/.+)").match(path).captures
24
+ signature == sign(path)
25
+ end
26
+
27
+ def url_for(path, **query)
28
+ path = URI(path).tap do |url|
29
+ url.path = path
30
+ url.query = query.to_query
31
+ end
32
+ signed_url path
33
+ end
34
+
35
+ private
36
+ def signed_path(path)
37
+ File.join(path_prefix, sign(File.join("/", path.to_s)), path.to_s)
38
+ end
39
+
40
+ def sign(data)
41
+ OpenSSL::HMAC.hexdigest(DIGEST, secret_key, data)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module TinyZap
2
+ VERSION = "0.1.4"
3
+ end
data/lib/tinyzap.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "tinyzap/version"
2
+ require "tinyzap/engine" if defined? Rails
3
+ require "zeitwerk"
4
+
5
+ module TinyZap
6
+ Loader = Zeitwerk::Loader.for_gem.tap do |loader|
7
+ loader.ignore "#{__dir__}/generators"
8
+ loader.inflector.inflect(
9
+ "tinyzap" => "TinyZap",
10
+ "cli" => "CLI"
11
+ )
12
+ loader.setup
13
+ end
14
+
15
+ class << self
16
+ def client
17
+ @client ||= Client.new
18
+ end
19
+
20
+ def key_generator(environment: Rails.env)
21
+ @key_generator ||= KeyGenerator.new(environment: environment)
22
+ end
23
+
24
+ def configure(&block)
25
+ block.call client.configuration
26
+ end
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tinyzap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Brad Gessler
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ description: Easiest way to generate fresh images for Rails applications.
56
+ email:
57
+ - brad@tinyzap.com
58
+ executables:
59
+ - tinyzap
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - app/assets/config/tinyzap_manifest.js
67
+ - app/assets/stylesheets/tinyzap/application.css
68
+ - app/controllers/concerns/tinyzap/open_graph.rb
69
+ - app/controllers/tinyzap/application_controller.rb
70
+ - app/helpers/tinyzap/application_helper.rb
71
+ - app/helpers/tinyzap/open_graph_tag_helper.rb
72
+ - app/jobs/tinyzap/application_job.rb
73
+ - app/mailers/tinyzap/application_mailer.rb
74
+ - app/models/tinyzap/application_record.rb
75
+ - app/models/tinyzap/open_graph/base.rb
76
+ - app/models/tinyzap/open_graph/image.rb
77
+ - app/models/tinyzap/open_graph/metatag.rb
78
+ - app/models/tinyzap/open_graph/metatag_mapper.rb
79
+ - app/models/tinyzap/open_graph/model.rb
80
+ - app/models/tinyzap/open_graph/twitter.rb
81
+ - app/views/layouts/tinyzap/application.html.erb
82
+ - config/initializers/inflections.rb
83
+ - config/initializers/mime_types.rb
84
+ - config/routes.rb
85
+ - exe/tinyzap
86
+ - lib/generators/tinyzap/install/USAGE
87
+ - lib/generators/tinyzap/install/install_generator.rb
88
+ - lib/generators/tinyzap/install/templates/application.opengraph.erb
89
+ - lib/generators/tinyzap/install/templates/tinyzap.rb.tt
90
+ - lib/tasks/tinyzap_tasks.rake
91
+ - lib/tinyzap.rb
92
+ - lib/tinyzap/cli.rb
93
+ - lib/tinyzap/client.rb
94
+ - lib/tinyzap/configuration.rb
95
+ - lib/tinyzap/engine.rb
96
+ - lib/tinyzap/key_generator.rb
97
+ - lib/tinyzap/url_signature.rb
98
+ - lib/tinyzap/version.rb
99
+ homepage: https://tinyzap.com/
100
+ licenses:
101
+ - MIT
102
+ metadata:
103
+ allowed_push_host: https://rubygems.org/
104
+ homepage_uri: https://tinyzap.com/
105
+ source_code_uri: https://github.com/tinyzap/ruby
106
+ changelog_uri: https://github.com/tinyzap/ruby/releases
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubygems_version: 3.4.6
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Easiest way to generate fresh images for Rails applications.
126
+ test_files: []