tinyzap 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![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 @@
|
|
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: []
|