Sha256: 8a5979924f52875223cdd06bedd07fea8a980aab5f6ab00be98ad4c587d3c210

Contents?: true

Size: 1.95 KB

Versions: 5

Compression:

Stored size: 1.95 KB

Contents

# frozen_string_literal: true

module ActiveStorage
  module DirectUploadToken
    extend self

    SEPARATOR = "."
    DIRECT_UPLOAD_TOKEN_LENGTH = 32

    def generate_direct_upload_token(attachment_name, service_name, session)
      token = direct_upload_token(session, attachment_name)
      encode_direct_upload_token([service_name, token].join(SEPARATOR))
    end

    def verify_direct_upload_token(token, attachment_name, session)
      raise ActiveStorage::InvalidDirectUploadTokenError if token.nil?

      service_name, *token_components = decode_token(token).split(SEPARATOR)
      decoded_token = token_components.join(SEPARATOR)

      return service_name if valid_direct_upload_token?(decoded_token, attachment_name, session)

      raise ActiveStorage::InvalidDirectUploadTokenError
    end

    private
      def direct_upload_token(session, attachment_name) # :doc:
        direct_upload_token_hmac(session, "direct_upload##{attachment_name}")
      end

      def valid_direct_upload_token?(token, attachment_name, session) # :doc:
        correct_token = direct_upload_token(session, attachment_name)
        ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, correct_token)
      rescue ArgumentError
        raise ActiveStorage::InvalidDirectUploadTokenError
      end

      def direct_upload_token_hmac(session, identifier) # :doc:
        OpenSSL::HMAC.digest(
          OpenSSL::Digest::SHA256.new,
          real_direct_upload_token(session),
          identifier
        )
      end

      def real_direct_upload_token(session) # :doc:
        session[:_direct_upload_token] ||= SecureRandom.urlsafe_base64(DIRECT_UPLOAD_TOKEN_LENGTH, padding: false)
        encode_direct_upload_token(session[:_direct_upload_token])
      end

      def decode_token(encoded_token) # :nodoc:
        Base64.urlsafe_decode64(encoded_token)
      end

      def encode_direct_upload_token(raw_token) # :nodoc:
        Base64.urlsafe_encode64(raw_token)
      end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
activestorage-7.0.1 lib/active_storage/direct_upload_token.rb
activestorage-7.0.0 lib/active_storage/direct_upload_token.rb
activestorage-7.0.0.rc3 lib/active_storage/direct_upload_token.rb
activestorage-7.0.0.rc2 lib/active_storage/direct_upload_token.rb
activestorage-7.0.0.rc1 lib/active_storage/direct_upload_token.rb