shimmer 0.0.12 → 0.0.15
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 +4 -4
- data/lib/shimmer/auth/apple_provider.rb +30 -0
- data/lib/shimmer/auth/authenticating.rb +37 -0
- data/lib/shimmer/auth/current.rb +15 -0
- data/lib/shimmer/auth/dev_provider.rb +14 -0
- data/lib/shimmer/auth/device.rb +23 -0
- data/lib/shimmer/auth/google_provider.rb +16 -0
- data/lib/shimmer/auth/user.rb +22 -0
- data/lib/shimmer/auth.rb +47 -0
- data/lib/shimmer/helpers/meta_helper.rb +32 -0
- data/lib/shimmer/railtie.rb +8 -0
- data/lib/shimmer/tasks/auth.rake +19 -0
- data/lib/shimmer/tasks/db.rake +9 -0
- data/lib/shimmer/tasks/s3.rake +46 -0
- data/lib/shimmer/utils/config.rb +33 -0
- data/lib/shimmer/utils/meta.rb +30 -0
- data/lib/shimmer/version.rb +1 -1
- data/lib/shimmer.rb +1 -0
- metadata +15 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 789f3862287d4a4e4ea0ea64429d5855d147853d25a85f896acde0f4a456f805
         | 
| 4 | 
            +
              data.tar.gz: 5fe592396ee46ae62468f4436835b1a3718fedfe60823287388bbe28cbb51f92
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3ca1e5c4a38b5b36da2b9cc20bae29c2a20df60550f8e9904db8de6cca92aea4c02f62cdb57d1c72cbfb0b4d660b2714ac3051e6c9eb8996914d954ba5ec14a4
         | 
| 7 | 
            +
              data.tar.gz: 50d5ffc3cac315ad169da4da82c621338b565598919930a3f3f72bd32f0321d2c781ba0598020762aaa5492b96a3988d6377ded829e4c650e4ebb3fb48361d5b
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                class AppleProvider < Provider
         | 
| 6 | 
            +
                  self.token_column = :apple_id
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  private
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def request_details(params)
         | 
| 11 | 
            +
                    name = params[:user] ? JSON.parse(params[:user])["name"] : {}
         | 
| 12 | 
            +
                    headers = {
         | 
| 13 | 
            +
                      'Content-Type': "application/x-www-form-urlencoded"
         | 
| 14 | 
            +
                    }
         | 
| 15 | 
            +
                    form = {
         | 
| 16 | 
            +
                      grant_type: "authorization_code",
         | 
| 17 | 
            +
                      code: params[:code],
         | 
| 18 | 
            +
                      client_id: Config.instance.apple_bundle_id!,
         | 
| 19 | 
            +
                      client_secret: Config.instance.apple_client_secret,
         | 
| 20 | 
            +
                      scope: "name email"
         | 
| 21 | 
            +
                    }
         | 
| 22 | 
            +
                    response = HTTParty.post("https://appleid.apple.com/auth/token", body: URI.encode_www_form(form), headers: headers)
         | 
| 23 | 
            +
                    raise InvalidTokenError, "Login check failed: #{response.body}" unless response.ok?
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    token = JWT.decode(response["id_token"], nil, false).first
         | 
| 26 | 
            +
                    UserDetails.new token: token["sub"], email: token["email"], first_name: name["firstName"], last_name: name["lastName"]
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                module Authenticating
         | 
| 6 | 
            +
                  extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  included do
         | 
| 9 | 
            +
                    before_action :authenticate
         | 
| 10 | 
            +
                    helper_method :current_user
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    def require_login
         | 
| 13 | 
            +
                      redirect_to login_path unless current_user
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def current_user
         | 
| 17 | 
            +
                      ::Current.user
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def login(device:)
         | 
| 21 | 
            +
                      ::Current.device = device
         | 
| 22 | 
            +
                      cookies.encrypted[:device_token] = {value: device.token, expires: 2.years.from_now}
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def logout
         | 
| 26 | 
            +
                      cookies.delete :device_token
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    private
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def authenticate
         | 
| 32 | 
            +
                      ::Current.device = cookies.encrypted[:device_token].presence&.then { |e| ::Device.find_by token: e }
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                class DevProvider < Provider
         | 
| 6 | 
            +
                  def login(email:, user_agent: nil, ip: nil)
         | 
| 7 | 
            +
                    user = model.find_or_create_by!(email: email)
         | 
| 8 | 
            +
                    device = user.devices.create! user_agent: user_agent
         | 
| 9 | 
            +
                    log_login(user, device_id: device.id, user_agent: user_agent, ip: ip)
         | 
| 10 | 
            +
                    device
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                module Device
         | 
| 6 | 
            +
                  extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  included do
         | 
| 9 | 
            +
                    has_secure_token
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def name
         | 
| 12 | 
            +
                      [browser.platform.name, browser.name].join(" ")
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    private
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def browser
         | 
| 18 | 
            +
                      @browser ||= Browser.new user_agent
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                class GoogleProvider < Provider
         | 
| 6 | 
            +
                  self.token_column = :google_id
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  private
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def request_details(params)
         | 
| 11 | 
            +
                    payload = GoogleIDToken::Validator.new.check(params[:credential], Config.instance.google_client_id!)
         | 
| 12 | 
            +
                    UserDetails.new token: payload["sub"], email: payload["email"], first_name: payload["given_name"].presence, last_name: payload["family_name"].presence
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                module User
         | 
| 6 | 
            +
                  extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  included do
         | 
| 9 | 
            +
                    def authenticate!(user_agent: nil, ip: nil)
         | 
| 10 | 
            +
                      Provider.new(self.class).create_device(user: self, user_agent: user_agent, ip: ip)
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  class_methods do
         | 
| 15 | 
            +
                    def login!(provider:, **attributes)
         | 
| 16 | 
            +
                      "Shimmer::Auth::#{provider.to_s.classify}Provider".constantize
         | 
| 17 | 
            +
                        .new(self).login(**attributes)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
    
        data/lib/shimmer/auth.rb
    ADDED
    
    | @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                class Provider
         | 
| 6 | 
            +
                  class InvalidTokenError < StandardError; end
         | 
| 7 | 
            +
                  UserDetails = Struct.new(:token, :email, :first_name, :last_name, keyword_init: true)
         | 
| 8 | 
            +
                  attr_reader :model
         | 
| 9 | 
            +
                  cattr_accessor :token_column
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def initialize(model)
         | 
| 12 | 
            +
                    @model = model
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def login(params:, user_agent: nil, ip: nil)
         | 
| 16 | 
            +
                    user = fetch_user request_details(params)
         | 
| 17 | 
            +
                    create_device user: user, user_agent: user_agent, ip: ip
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def create_device(user:, user_agent: nil, ip: nil)
         | 
| 21 | 
            +
                    user.devices.create!(user_agent: user_agent).tap do |device|
         | 
| 22 | 
            +
                      log_login(user, device_id: device.id, user_agent: user_agent, ip: ip)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def log_login(user, device_id:, user_agent: nil, ip: nil)
         | 
| 29 | 
            +
                    return unless user.respond_to? :publish
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    user.publish :login, provider: self.class.name.demodulize.underscore, device_id: device_id, user_agent: user_agent, ip: ip
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def fetch_user(details)
         | 
| 35 | 
            +
                    user = model.find_by(token_column => details.token) || model.find_by(email: details.email) || model.new
         | 
| 36 | 
            +
                    user[token_column] ||= details.token
         | 
| 37 | 
            +
                    user.email ||= details.email
         | 
| 38 | 
            +
                    user.first_name ||= details.first_name
         | 
| 39 | 
            +
                    user.last_name ||= details.last_name
         | 
| 40 | 
            +
                    user.save! if user.changed?
         | 
| 41 | 
            +
                    user
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            Dir["#{File.expand_path("./auth", __dir__)}/*"].sort.each { |e| require e }
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              module MetaHelper
         | 
| 5 | 
            +
                def meta
         | 
| 6 | 
            +
                  @meta ||= Meta.new.tap do |meta|
         | 
| 7 | 
            +
                    meta.canonical = url_for(only_path: false)
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def title(value)
         | 
| 12 | 
            +
                  meta.title = value
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def description(value)
         | 
| 16 | 
            +
                  meta.description = value
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def image(value)
         | 
| 20 | 
            +
                  meta.image = image_file_url(value, width: 1200)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def render_meta
         | 
| 24 | 
            +
                  tags = meta.tags.map do |tag|
         | 
| 25 | 
            +
                    type = tag.delete(:type) || "meta"
         | 
| 26 | 
            +
                    value = tag.delete(:value)
         | 
| 27 | 
            +
                    content_tag(type, value, tag)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  safe_join tags, "\n"
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/shimmer/railtie.rb
    CHANGED
    
    | @@ -8,3 +8,11 @@ module Shimmer | |
| 8 8 | 
             
                end
         | 
| 9 9 | 
             
              end
         | 
| 10 10 | 
             
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ActiveSupport.on_load(:action_view) do
         | 
| 13 | 
            +
              Dir.glob("#{File.expand_path(__dir__)}/helpers/**/*.rb").each do |file|
         | 
| 14 | 
            +
                load file
         | 
| 15 | 
            +
                name = file.split("/").last.delete_suffix(".rb").classify
         | 
| 16 | 
            +
                include "Shimmer::#{name}".constantize
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            namespace :auth do
         | 
| 4 | 
            +
              desc "Generates a Sign in with Apple Token"
         | 
| 5 | 
            +
              task :apple_token do
         | 
| 6 | 
            +
                ecdsa_key = OpenSSL::PKey::EC.new IO.read ".apple-key.p8"
         | 
| 7 | 
            +
                headers = {
         | 
| 8 | 
            +
                  "kid" => Shimmer::Config.instance.apple_key_id!
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
                claims = {
         | 
| 11 | 
            +
                  "iss" => Shimmer::Config.instance.apple_team_id!,
         | 
| 12 | 
            +
                  "iat" => Time.now.to_i,
         | 
| 13 | 
            +
                  "exp" => 180.days.from_now.to_i,
         | 
| 14 | 
            +
                  "aud" => "https://appleid.apple.com",
         | 
| 15 | 
            +
                  "sub" => Shimmer::Config.instance.apple_bundle_id!
         | 
| 16 | 
            +
                }
         | 
| 17 | 
            +
                puts JWT.encode claims, ecdsa_key, "ES256", headers
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
    
        data/lib/shimmer/tasks/db.rake
    CHANGED
    
    | @@ -43,4 +43,13 @@ namespace :db do | |
| 43 43 |  | 
| 44 44 | 
             
              desc "Download all app data, including assets"
         | 
| 45 45 | 
             
              task pull: [:pull_data, :pull_assets]
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              desc "Migrates if the database has any tables."
         | 
| 48 | 
            +
              task migrate_if_tables: :environment do
         | 
| 49 | 
            +
                if ActiveRecord::Base.connection.tables.any?
         | 
| 50 | 
            +
                  Rake::Task["db:migrate"].invoke
         | 
| 51 | 
            +
                else
         | 
| 52 | 
            +
                  puts "No tables in database yet, skipping migration"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 46 55 | 
             
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            namespace :s3 do
         | 
| 4 | 
            +
              desc "Creates a new S3 bucket and outputs or uploads the credentials."
         | 
| 5 | 
            +
              task :create_bucket do
         | 
| 6 | 
            +
                puts "Please enter the name for your new bucket"
         | 
| 7 | 
            +
                name = $stdin.gets.strip
         | 
| 8 | 
            +
                region = "eu-central-1"
         | 
| 9 | 
            +
                sh "aws s3 mb s3://#{name} --region #{region}"
         | 
| 10 | 
            +
                sh "aws iam create-user --user-name #{name}"
         | 
| 11 | 
            +
                policy = <<~JSON
         | 
| 12 | 
            +
                  {
         | 
| 13 | 
            +
                    "Version": "2012-10-17",
         | 
| 14 | 
            +
                    "Statement": [
         | 
| 15 | 
            +
                        {
         | 
| 16 | 
            +
                            "Effect": "Allow",
         | 
| 17 | 
            +
                            "Action": [
         | 
| 18 | 
            +
                                "s3:CreateBucket",
         | 
| 19 | 
            +
                                "s3:DeleteObject",
         | 
| 20 | 
            +
                                "s3:Put*",
         | 
| 21 | 
            +
                                "s3:Get*",
         | 
| 22 | 
            +
                                "s3:List*"
         | 
| 23 | 
            +
                            ],
         | 
| 24 | 
            +
                            "Resource": [
         | 
| 25 | 
            +
                                "arn:aws:s3:::#{name}",
         | 
| 26 | 
            +
                                "arn:aws:s3:::#{name}/*"
         | 
| 27 | 
            +
                            ]
         | 
| 28 | 
            +
                        }
         | 
| 29 | 
            +
                    ]
         | 
| 30 | 
            +
                  }
         | 
| 31 | 
            +
                JSON
         | 
| 32 | 
            +
                File.write("policy.json", policy)
         | 
| 33 | 
            +
                sh "aws iam put-user-policy --user-name #{name} --policy-name #{name} --policy-document file://policy.json"
         | 
| 34 | 
            +
                File.delete("policy.json")
         | 
| 35 | 
            +
                content = JSON.parse `aws iam create-access-key --user-name #{name}`
         | 
| 36 | 
            +
                id = content.dig("AccessKey", "AccessKeyId")
         | 
| 37 | 
            +
                secret = content.dig("AccessKey", "SecretAccessKey")
         | 
| 38 | 
            +
                puts "Credentials and bucket were generated. Automatically assign them to the associated Heroku project? This will override and delete all current keys on Heroku. (y/n)"
         | 
| 39 | 
            +
                vars = {AWS_REGION: region, AWS_BUCKET: name, AWS_ACCESS_KEY_ID: id, AWS_SECRET_ACCESS_KEY: secret}
         | 
| 40 | 
            +
                if $stdin.gets.strip == "y"
         | 
| 41 | 
            +
                  sh "heroku config:set #{vars.map { |k, v| "#{k}=#{v}" }.join(" ")}"
         | 
| 42 | 
            +
                else
         | 
| 43 | 
            +
                  vars.each { |k, v| puts "#{k}=#{v}" }
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              class Config
         | 
| 5 | 
            +
                include Singleton
         | 
| 6 | 
            +
                class MissingConfigError < StandardError; end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def method_missing(method_name)
         | 
| 9 | 
            +
                  method_name = method_name.to_s
         | 
| 10 | 
            +
                  type = :string
         | 
| 11 | 
            +
                  key = method_name.delete_suffix("!").delete_suffix("?")
         | 
| 12 | 
            +
                  required = method_name.end_with?("!")
         | 
| 13 | 
            +
                  type = :bool if method_name.end_with?("?")
         | 
| 14 | 
            +
                  value = ENV[key.upcase].presence
         | 
| 15 | 
            +
                  value ||= Rails.application.credentials.send(key)
         | 
| 16 | 
            +
                  raise MissingConfigError, "#{key.upcase} environment value is missing" if required && value.blank?
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  coerce value, type
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def respond_to_missing?(method_name)
         | 
| 22 | 
            +
                  true
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                private
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def coerce(value, type)
         | 
| 28 | 
            +
                  return !value.in?(["n", "0", "no", "false"]) if type == :bool && value.is_a?(String)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  value
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Shimmer
         | 
| 4 | 
            +
              class Meta
         | 
| 5 | 
            +
                class_attribute :app_name
         | 
| 6 | 
            +
                attr_accessor :title, :description, :image, :canonical
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def tags
         | 
| 9 | 
            +
                  tags = []
         | 
| 10 | 
            +
                  title = self.title.present? ? "#{self.title} | #{app_name}" : app_name
         | 
| 11 | 
            +
                  tags.push(type: :title, value: title)
         | 
| 12 | 
            +
                  tags.push(property: "og:title", content: title)
         | 
| 13 | 
            +
                  if description.present?
         | 
| 14 | 
            +
                    tags.push(name: :description, content: description)
         | 
| 15 | 
            +
                    tags.push(property: "og:description", content: description)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                  if image.present?
         | 
| 18 | 
            +
                    tags.push(property: "og:image", content: image)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  if canonical.present?
         | 
| 21 | 
            +
                    tags.push(type: :link, rel: :canonical, href: canonical)
         | 
| 22 | 
            +
                    tags.push(property: "og:url", content: canonical)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                  tags.push(property: "og:type", content: :website)
         | 
| 25 | 
            +
                  tags.push(property: "og:locale", content: I18n.locale)
         | 
| 26 | 
            +
                  tags.push(name: "twitter:card", content: :summary_large_image)
         | 
| 27 | 
            +
                  tags
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
    
        data/lib/shimmer/version.rb
    CHANGED
    
    
    
        data/lib/shimmer.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ Dir["#{File.expand_path("../lib/shimmer/middlewares", __dir__)}/*"].sort.each { | |
| 6 6 | 
             
            Dir["#{File.expand_path("../lib/shimmer/controllers", __dir__)}/*"].sort.each { |e| require e }
         | 
| 7 7 | 
             
            Dir["#{File.expand_path("../lib/shimmer/jobs", __dir__)}/*"].sort.each { |e| require e }
         | 
| 8 8 | 
             
            Dir["#{File.expand_path("../lib/shimmer/utils", __dir__)}/*"].sort.each { |e| require e }
         | 
| 9 | 
            +
            require_relative "shimmer/auth"
         | 
| 9 10 |  | 
| 10 11 | 
             
            module Shimmer
         | 
| 11 12 | 
             
              class Error < StandardError; end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: shimmer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.15
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jens Ravens
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-06- | 
| 11 | 
            +
            date: 2022-06-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rake
         | 
| @@ -135,16 +135,29 @@ files: | |
| 135 135 | 
             
            - bin/solargraph
         | 
| 136 136 | 
             
            - config/rubocop_base.yml
         | 
| 137 137 | 
             
            - lib/shimmer.rb
         | 
| 138 | 
            +
            - lib/shimmer/auth.rb
         | 
| 139 | 
            +
            - lib/shimmer/auth/apple_provider.rb
         | 
| 140 | 
            +
            - lib/shimmer/auth/authenticating.rb
         | 
| 141 | 
            +
            - lib/shimmer/auth/current.rb
         | 
| 142 | 
            +
            - lib/shimmer/auth/dev_provider.rb
         | 
| 143 | 
            +
            - lib/shimmer/auth/device.rb
         | 
| 144 | 
            +
            - lib/shimmer/auth/google_provider.rb
         | 
| 145 | 
            +
            - lib/shimmer/auth/user.rb
         | 
| 138 146 | 
             
            - lib/shimmer/controllers/files_controller.rb
         | 
| 139 147 | 
             
            - lib/shimmer/controllers/sitemaps_controller.rb
         | 
| 148 | 
            +
            - lib/shimmer/helpers/meta_helper.rb
         | 
| 140 149 | 
             
            - lib/shimmer/jobs/sitemap_job.rb
         | 
| 141 150 | 
             
            - lib/shimmer/middlewares/cloudflare.rb
         | 
| 142 151 | 
             
            - lib/shimmer/railtie.rb
         | 
| 152 | 
            +
            - lib/shimmer/tasks/auth.rake
         | 
| 143 153 | 
             
            - lib/shimmer/tasks/db.rake
         | 
| 144 154 | 
             
            - lib/shimmer/tasks/lint.rake
         | 
| 155 | 
            +
            - lib/shimmer/tasks/s3.rake
         | 
| 156 | 
            +
            - lib/shimmer/utils/config.rb
         | 
| 145 157 | 
             
            - lib/shimmer/utils/file_helper.rb
         | 
| 146 158 | 
             
            - lib/shimmer/utils/file_proxy.rb
         | 
| 147 159 | 
             
            - lib/shimmer/utils/localizable.rb
         | 
| 160 | 
            +
            - lib/shimmer/utils/meta.rb
         | 
| 148 161 | 
             
            - lib/shimmer/utils/remote_navigation.rb
         | 
| 149 162 | 
             
            - lib/shimmer/utils/sitemap_adapter.rb
         | 
| 150 163 | 
             
            - lib/shimmer/version.rb
         |