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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +98 -0
- data/Rakefile +8 -0
- data/app/assets/config/tinyzap_manifest.js +1 -0
- data/app/assets/stylesheets/tinyzap/application.css +15 -0
- data/app/controllers/concerns/tinyzap/open_graph.rb +43 -0
- data/app/controllers/tinyzap/application_controller.rb +4 -0
- data/app/helpers/tinyzap/application_helper.rb +4 -0
- data/app/helpers/tinyzap/open_graph_tag_helper.rb +7 -0
- data/app/jobs/tinyzap/application_job.rb +4 -0
- data/app/mailers/tinyzap/application_mailer.rb +6 -0
- data/app/models/tinyzap/application_record.rb +5 -0
- data/app/models/tinyzap/open_graph/base.rb +51 -0
- data/app/models/tinyzap/open_graph/image.rb +12 -0
- data/app/models/tinyzap/open_graph/metatag.rb +11 -0
- data/app/models/tinyzap/open_graph/metatag_mapper.rb +35 -0
- data/app/models/tinyzap/open_graph/model.rb +35 -0
- data/app/models/tinyzap/open_graph/twitter.rb +11 -0
- data/app/views/layouts/tinyzap/application.html.erb +15 -0
- data/config/initializers/inflections.rb +3 -0
- data/config/initializers/mime_types.rb +3 -0
- data/config/routes.rb +2 -0
- data/exe/tinyzap +4 -0
- data/lib/generators/tinyzap/install/USAGE +11 -0
- data/lib/generators/tinyzap/install/install_generator.rb +19 -0
- data/lib/generators/tinyzap/install/templates/application.opengraph.erb +15 -0
- data/lib/generators/tinyzap/install/templates/tinyzap.rb.tt +14 -0
- data/lib/tasks/tinyzap_tasks.rake +4 -0
- data/lib/tinyzap/cli.rb +23 -0
- data/lib/tinyzap/client.rb +13 -0
- data/lib/tinyzap/configuration.rb +18 -0
- data/lib/tinyzap/engine.rb +5 -0
- data/lib/tinyzap/key_generator.rb +43 -0
- data/lib/tinyzap/url_signature.rb +44 -0
- data/lib/tinyzap/version.rb +3 -0
- data/lib/tinyzap.rb +28 -0
- 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
|
+
[](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 @@
|
|
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,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,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
|
data/config/routes.rb
ADDED
data/exe/tinyzap
ADDED
@@ -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
|
data/lib/tinyzap/cli.rb
ADDED
@@ -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,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
|
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: []
|