From c745c11c43ca2ebdebd4945d452a4a4a7a69d03b Mon Sep 17 00:00:00 2001 From: Ahmad Farhat <ahmad.af.farhat@gmail.com> Date: Wed, 5 Jul 2023 15:29:48 -0400 Subject: [PATCH] Added google cloud support (#5308) * Added google cloud support * Rubocop * Update development env * Rubocop again * Add to sample.env --- Gemfile | 1 + Gemfile.lock | 54 +++++++++++++++++++ config/environments/development.rb | 10 +++- config/environments/production.rb | 2 + config/storage.yml | 20 +++++-- ..._to_active_storage_blobs.active_storage.rb | 24 +++++++++ ..._storage_variant_records.active_storage.rb | 31 +++++++++++ ...e_storage_blobs_checksum.active_storage.rb | 10 ++++ db/schema.rb | 2 +- sample.env | 10 ++++ 10 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20230705183745_add_service_name_to_active_storage_blobs.active_storage.rb create mode 100644 db/migrate/20230705183746_create_active_storage_variant_records.active_storage.rb create mode 100644 db/migrate/20230705183747_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb diff --git a/Gemfile b/Gemfile index 6b17f812..495b4d6d 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem 'bootsnap', require: false gem 'cssbundling-rails' gem 'data_migrate' gem 'dotenv-rails' +gem 'google-cloud-storage', '~> 1.44', require: false gem 'hcaptcha' gem 'hiredis', '~> 0.6.0' gem 'i18n-language-mapping' diff --git a/Gemfile.lock b/Gemfile.lock index f86fc320..7348ebf8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -136,7 +136,10 @@ GEM debug (1.7.1) irb (>= 1.5.0) reline (>= 0.3.1) + declarative (0.0.20) diff-lcs (1.5.0) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) dotenv (2.8.1) dotenv-rails (2.8.1) dotenv (= 2.8.1) @@ -158,6 +161,40 @@ GEM ffi (1.15.5) globalid (1.1.0) activesupport (>= 5.0) + google-apis-core (0.11.0) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.6.0) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) hashdiff (1.0.1) hashie (5.0.0) hcaptcha (7.1.0) @@ -203,12 +240,14 @@ GEM net-smtp marcel (1.0.2) matrix (0.4.2) + memoist (0.16.2) method_source (1.0.0) mini_magick (4.12.0) mini_mime (1.1.2) mini_portile2 (2.8.2) minitest (5.18.0) msgpack (1.6.0) + multi_json (1.15.0) net-imap (0.3.4) date net-protocol @@ -245,6 +284,7 @@ GEM validate_email validate_url webfinger (~> 1.2) + os (1.1.4) pagy (5.10.1) activesupport parallel (1.22.1) @@ -301,8 +341,13 @@ GEM io-console (~> 0.5) remote_syslog_logger (1.0.4) syslog_protocol + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) request_store (1.5.1) rack (>= 1.4) + retriable (3.1.2) rexml (3.2.5) rspec-core (3.12.1) rspec-support (~> 3.12.0) @@ -353,6 +398,11 @@ GEM websocket (~> 1.0) shoulda-matchers (5.3.0) activesupport (>= 5.2.0) + signet (0.17.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) sprockets (4.2.0) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) @@ -367,8 +417,10 @@ GEM syslog_protocol (0.9.2) thor (1.2.2) timeout (0.3.2) + trailblazer-option (0.1.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) + uber (0.1.0) unicode-display_width (2.4.2) validate_email (0.1.6) activemodel (>= 3.0) @@ -392,6 +444,7 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.8.1) websocket (1.2.9) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) @@ -420,6 +473,7 @@ DEPENDENCIES dotenv-rails factory_bot_rails faker + google-cloud-storage (~> 1.44) hcaptcha hiredis (~> 0.6.0) i18n-language-mapping diff --git a/config/environments/development.rb b/config/environments/development.rb index c4f401ba..0f1121f3 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -52,7 +52,15 @@ Rails.application.configure do end # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :local + config.active_storage.service = if ENV['S3_ACCESS_KEY_ID'].present? && ENV['S3_ENDPOINT'].present? + :s3 + elsif ENV['S3_ACCESS_KEY_ID'].present? + :amazon + elsif ENV['GCS_PROJECT'].present? + :google + else + :local + end if ENV['SMTP_SERVER'].present? config.action_mailer.perform_deliveries = true diff --git a/config/environments/production.rb b/config/environments/production.rb index f3f5a4a0..a7b23143 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -60,6 +60,8 @@ Rails.application.configure do :s3 elsif ENV['S3_ACCESS_KEY_ID'].present? :amazon + elsif ENV['GCS_PROJECT'].present? + :google else :local end diff --git a/config/storage.yml b/config/storage.yml index 0c67dd21..4287c0f0 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -38,11 +38,21 @@ s3: bucket: <%= ENV['S3_BUCKET'] %> # Remember not to checkin your GCS keyfile to a repository -# google: -# service: GCS -# project: your_project -# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> -# bucket: your_own_bucket-<%= Rails.env %> +google: + service: GCS + project: "<%= ENV['GCS_PROJECT'] %>" + bucket: "<%= ENV['GCS_BUCKET'] %>" + credentials: + type: 'service_account' + project_id: "<%= ENV['GCS_PROJECT_ID'] %>" + private_key_id: "<%= ENV['GCS_PRIVATE_KEY_ID'] %>" + private_key: "<%= ENV['GCS_PRIVATE_KEY']&.lines&.join("\\n") %>" + client_email: "<%= ENV['GCS_CLIENT_EMAIL'] %>" + client_id: "<%= ENV['GCS_CLIENT_ID'] %>" + auth_uri: 'https://accounts.google.com/o/oauth2/auth' + token_uri: 'https://accounts.google.com/o/oauth2/token' + auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs' + client_x509_cert_url: "<%= ENV['GCS_CLIENT_CERT'] %>" # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) # microsoft: diff --git a/db/migrate/20230705183745_add_service_name_to_active_storage_blobs.active_storage.rb b/db/migrate/20230705183745_add_service_name_to_active_storage_blobs.active_storage.rb new file mode 100644 index 00000000..2002bd25 --- /dev/null +++ b/db/migrate/20230705183745_add_service_name_to_active_storage_blobs.active_storage.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# This migration comes from active_storage (originally 20190112182829) +class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] + def up + return unless table_exists?(:active_storage_blobs) + + return if column_exists?(:active_storage_blobs, :service_name) + + add_column :active_storage_blobs, :service_name, :string + + if (configured_service = ActiveStorage::Blob.service.name) + ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) # rubocop:disable Rails/SkipsModelValidations + end + + change_column :active_storage_blobs, :service_name, :string, null: false + end + + def down + return unless table_exists?(:active_storage_blobs) + + remove_column :active_storage_blobs, :service_name + end +end diff --git a/db/migrate/20230705183746_create_active_storage_variant_records.active_storage.rb b/db/migrate/20230705183746_create_active_storage_variant_records.active_storage.rb new file mode 100644 index 00000000..91e341db --- /dev/null +++ b/db/migrate/20230705183746_create_active_storage_variant_records.active_storage.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# This migration comes from active_storage (originally 20191206030411) +class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + # Use Active Record's configured type for primary key + + create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t| # rubocop:disable Rails/CreateTableWithTimestamps + t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type + t.string :variation_digest, null: false + + t.index %i[blob_id variation_digest], name: 'index_active_storage_variant_records_uniqueness', unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + end + end + + private + + def primary_key_type + config = Rails.configuration.generators + config.options[config.orm][:primary_key_type] || :primary_key + end + + def blobs_primary_key_type + pkey_name = connection.primary_key(:active_storage_blobs) + pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name } + pkey_column.bigint? ? :bigint : pkey_column.type + end +end diff --git a/db/migrate/20230705183747_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb b/db/migrate/20230705183747_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb new file mode 100644 index 00000000..6f318221 --- /dev/null +++ b/db/migrate/20230705183747_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# This migration comes from active_storage (originally 20211119233751) +class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + change_column_null(:active_storage_blobs, :checksum, true) + end +end diff --git a/db/schema.rb b/db/schema.rb index f4579674..f0760fed 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_03_07_184209) do +ActiveRecord::Schema[7.0].define(version: 2023_07_05_183747) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" diff --git a/sample.env b/sample.env index 3f2a2694..25da1adb 100644 --- a/sample.env +++ b/sample.env @@ -57,6 +57,16 @@ REDIS_URL= #S3_BUCKET= #S3_ENDPOINT= +# Set these environment variables if you are using Google Cloud Storage +#GCS_PROJECT= +#GCS_BUCKET= +#GCS_PROJECT_ID= +#GCS_PRIVATE_KEY_ID= +#GCS_PRIVATE_KEY= +#GCS_CLIENT_EMAIL= +#GCS_CLIENT_ID= +#GCS_CLIENT_CERT= + # Define the default locale language code (i.e. 'en' for English) from the following list: # [en, ar, fr, es] #DEFAULT_LOCALE=en -- GitLab