From d4f71e98ed01ef69d9ef00fc3e74e1b9b255f624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Mon, 23 Oct 2023 15:31:22 +0200 Subject: [PATCH] Download and attach icons for web apps --- Gemfile | 2 + Gemfile.lock | 21 +++++++++ app/models/app_catalog/web_app.rb | 13 +++++- .../app_catalog_manager/fetch_metadata.rb | 26 ----------- .../app_catalog_manager/update_metadata.rb | 44 +++++++++++++++++++ config/storage.yml | 10 ++--- 6 files changed, 84 insertions(+), 32 deletions(-) delete mode 100644 app/services/app_catalog_manager/fetch_metadata.rb create mode 100644 app/services/app_catalog_manager/update_metadata.rb diff --git a/Gemfile b/Gemfile index 2f814ba..df0e515 100644 --- a/Gemfile +++ b/Gemfile @@ -47,6 +47,8 @@ gem 'flipper-ui' # HTTP requests gem 'faraday' +gem 'down' +gem 'aws-sdk-s3', require: false # Background/scheduled jobs gem 'sidekiq', '< 7' diff --git a/Gemfile.lock b/Gemfile.lock index 954f8d7..f9c03a3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,6 +92,22 @@ GEM addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) + aws-eventstream (1.2.0) + aws-partitions (1.839.0) + aws-sdk-core (3.185.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.72.0) + aws-sdk-core (~> 3, >= 3.184.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.136.0) + aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.6) + aws-sigv4 (1.6.0) + aws-eventstream (~> 1, >= 1.0.2) backport (1.2.0) base64 (0.1.1) bcrypt (3.1.19) @@ -147,6 +163,8 @@ GEM dotenv-rails (2.8.1) dotenv (= 2.8.1) railties (>= 3.2) + down (5.4.1) + addressable (~> 2.8) e2mmap (0.1.0) ecdsa (1.2.0) ecdsa_ext (0.5.0) @@ -206,6 +224,7 @@ GEM jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) + jmespath (1.6.2) json (2.6.3) kramdown (2.4.0) rexml @@ -445,6 +464,7 @@ PLATFORMS x86_64-linux DEPENDENCIES + aws-sdk-s3 byebug (~> 11.1) capybara cssbundling-rails @@ -453,6 +473,7 @@ DEPENDENCIES devise_ldap_authenticatable discourse_api dotenv-rails + down factory_bot_rails faker faraday diff --git a/app/models/app_catalog/web_app.rb b/app/models/app_catalog/web_app.rb index 4287a11..d2f75fd 100644 --- a/app/models/app_catalog/web_app.rb +++ b/app/models/app_catalog/web_app.rb @@ -1,9 +1,20 @@ class AppCatalog::WebApp < ApplicationRecord - store :metadata, coder: JSON + has_one_attached :icon do |attachable| + attachable.variant :medium, resize_to_limit: [128,128] + attachable.variant :large, resize_to_limit: [256,256] + end + + has_one_attached :apple_touch_icon + validates :url, presence: true, uniqueness: true validates :url, format: { with: URI.regexp }, if: Proc.new { |a| a.url.present? } + # before_create :update_metadata + + def update_metadata + AppCatalogManager::UpdateMetadata.call(self) + end end diff --git a/app/services/app_catalog_manager/fetch_metadata.rb b/app/services/app_catalog_manager/fetch_metadata.rb deleted file mode 100644 index 3e6f11d..0000000 --- a/app/services/app_catalog_manager/fetch_metadata.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'manifique' - -module AppCatalogManager - class FetchMetadata < AppCatalogManagerService - def initialize(app) - @app = app - end - - def call - agent = Manifique::Agent.new(url: @app.url) - metadata = agent.fetch_metadata - - @app.name = metadata.name - - [:name, :short_name, :description, :theme_color, :background_color, - :display, :start_url, :scope, :share_target].each do |prop| - @app.metadata[prop] = metadata.send(prop) if prop - end - rescue Manifique::Error => e - msg = "Fetching web app manifest failed for #{e.url}: #{e.type}" - Rails.logger.warn(msg) - Sentry.capture_message(msg) if Setting.sentry_enabled? - false - end - end -end diff --git a/app/services/app_catalog_manager/update_metadata.rb b/app/services/app_catalog_manager/update_metadata.rb new file mode 100644 index 0000000..32e9203 --- /dev/null +++ b/app/services/app_catalog_manager/update_metadata.rb @@ -0,0 +1,44 @@ +require "manifique" +require "down" + +module AppCatalogManager + class UpdateMetadata < AppCatalogManagerService + def initialize(app) + @app = app + end + + def call + agent = Manifique::Agent.new(url: @app.url) + metadata = agent.fetch_metadata + + @app.name = metadata.name + + [:name, :short_name, :description, :theme_color, :background_color, + :display, :start_url, :scope, :share_target, :icons].each do |prop| + @app.metadata[prop] = metadata.send(prop) if prop + end + + if icon = metadata.select_icon(sizes: "256x256") + attach_remote_image(:icon, icon) + end + if apple_touch_icon = metadata.select_icon(purpose: "apple-touch-icon") + attach_remote_image(:apple_touch_icon, apple_touch_icon) + end + + byebug + rescue Manifique::Error => e + msg = "Fetching web app manifest failed for #{e.url}: #{e.type}" + Rails.logger.warn(msg) + Sentry.capture_message(msg) if Setting.sentry_enabled? + false + end + + def attach_remote_image(attachment_name, icon) + download_url = "#{@app.url}/#{icon["src"].gsub(/^\//,'')}" + filename = "web_apps/#{@app.id}/icons/#{attachment_name}.png" + + tempfile = Down.download(download_url) + @app.send(attachment_name).attach(io: tempfile, filename: filename) + end + end +end diff --git a/config/storage.yml b/config/storage.yml index 6b8a50a..3ddfbb8 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -9,9 +9,9 @@ test: <% if ENV["S3_ENABLED"] %> s3: service: S3 - endpoint: ENV["S3_ENDPOINT"] - region: ENV["S3_REGION"] - bucket: ENV["S3_BUCKET"] - access_key_id: ENV["S3_ACCESS_KEY"] - secret_access_key: ENV["S3_SECRET_KEY"] + endpoint: <%= ENV["S3_ENDPOINT"] %> + region: <%= ENV["S3_REGION"] %> + bucket: <%= ENV["S3_BUCKET"] %> + access_key_id: <%= ENV["S3_ACCESS_KEY"] %> + secret_access_key: <%= ENV["S3_SECRET_KEY"] %> <% end %>