Merge remote-tracking branch 'upstream/pull/2296'
authorTom Hughes <tom@compton.nu>
Mon, 15 Jul 2019 07:19:30 +0000 (08:19 +0100)
committerTom Hughes <tom@compton.nu>
Mon, 15 Jul 2019 07:19:30 +0000 (08:19 +0100)
27 files changed:
.gitignore
.travis.yml
Gemfile
Gemfile.lock
INSTALL.md
app/assets/images/avatar_large.png [moved from app/assets/images/users/images/large.png with 100% similarity]
app/assets/images/avatar_small.png [moved from app/assets/images/users/images/small.png with 100% similarity]
app/assets/images/avatars.svg [moved from app/assets/images/users/images/user-icons.svg with 100% similarity]
app/assets/javascripts/user.js
app/controllers/users_controller.rb
app/helpers/user_helper.rb
app/mailers/notifier.rb
app/models/user.rb
app/views/api/users/_user.builder
app/views/users/account.html.erb
config/.gitignore
config/environments/production.rb
config/example.storage.yml [new file with mode: 0644]
config/initializers/active_storage.rb [new file with mode: 0644]
config/initializers/config.rb
config/initializers/secure_headers.rb
config/settings.yml
config/storage.yml [deleted file]
db/migrate/20190702193519_create_active_storage_tables.rb [new file with mode: 0644]
db/structure.sql
test/controllers/users_controller_test.rb
test/helpers/user_helper_test.rb

index 386f0513af861f01cb92952a2cb6e2306346e799..1328658c6ab5b70d2809f6c665e51ff05b447514 100644 (file)
@@ -16,4 +16,5 @@ node_modules
 public/assets
 public/attachments
 public/export
+storage
 tmp
index 4d764d6ed3e45ab9fbd0770c6c2ff7147942153f..e4c81e4c1d401373648fd78d98258dd08ec64e6e 100644 (file)
@@ -25,6 +25,7 @@ before_script:
   - psql -U postgres -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '/tmp/libpgosm', 'tile_for_point' LANGUAGE C STRICT" openstreetmap
   - psql -U postgres -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '/tmp/libpgosm', 'xid_to_int4' LANGUAGE C STRICT" openstreetmap
   - cp config/travis.database.yml config/database.yml
+  - cp config/example.storage.yml config/storage.yml
   - touch config/settings.local.yml
   - bundle exec rake db:migrate
   - bundle exec rake i18n:js:export
diff --git a/Gemfile b/Gemfile
index f41ac015bf4adb14c28f3502724c7f63dcf782a1..0a00a6496e13b60c9eb31ede941a1f0bdb11c834 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -126,6 +126,12 @@ gem "mimemagic"
 # Used for browser detection
 gem "browser"
 
+# Used for S3 object storage
+gem "aws-sdk-s3"
+
+# Used to resize user images
+gem "mini_magick"
+
 # Gems useful for development
 group :development do
   gem "annotate"
index 65c6f2a89ae57088dbe256c1af638459df5228a7..467166f0f455b0fcf242529510b7d965d6b9d871 100644 (file)
@@ -60,6 +60,22 @@ GEM
     ast (2.4.0)
     autoprefixer-rails (8.6.5)
       execjs
+    aws-eventstream (1.0.3)
+    aws-partitions (1.184.0)
+    aws-sdk-core (3.59.0)
+      aws-eventstream (~> 1.0, >= 1.0.2)
+      aws-partitions (~> 1.0)
+      aws-sigv4 (~> 1.1)
+      jmespath (~> 1.0)
+    aws-sdk-kms (1.23.0)
+      aws-sdk-core (~> 3, >= 3.58.0)
+      aws-sigv4 (~> 1.1)
+    aws-sdk-s3 (1.45.0)
+      aws-sdk-core (~> 3, >= 3.58.0)
+      aws-sdk-kms (~> 1)
+      aws-sigv4 (~> 1.1)
+    aws-sigv4 (1.1.0)
+      aws-eventstream (~> 1.0, >= 1.0.2)
     better_errors (2.5.1)
       coderay (>= 1.0.0)
       erubi (>= 1.0.0)
@@ -206,6 +222,7 @@ GEM
     image_size (2.0.1)
     in_threads (1.5.2)
     jaro_winkler (1.5.3)
+    jmespath (1.4.0)
     jquery-rails (4.3.5)
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
@@ -241,6 +258,7 @@ GEM
       mime-types-data (~> 3.2015)
     mime-types-data (3.2019.0331)
     mimemagic (0.3.3)
+    mini_magick (4.9.3)
     mini_mime (1.0.1)
     mini_portile2 (2.4.0)
     minitest (5.11.3)
@@ -446,6 +464,7 @@ DEPENDENCIES
   activerecord-import
   annotate
   autoprefixer-rails (~> 8.6.3)
+  aws-sdk-s3
   better_errors
   bigdecimal (~> 1.1.0)
   binding_of_caller
@@ -482,6 +501,7 @@ DEPENDENCIES
   listen
   logstasher
   mimemagic
+  mini_magick
   minitest (~> 5.1)
   oauth-plugin (>= 0.5.1)
   omniauth
index 1c40470699b07aeb7ee6a6602714eb9aaa5aad3c..097d4500eef403b2b0c98734ea602d823995cb77 100644 (file)
@@ -124,6 +124,15 @@ We use [Yarn](https://yarnpkg.com/) to manage the Node.js modules required for t
 bundle exec rake yarn:install
 ```
 
+## Storage setup
+
+The Rails port needs to be configured with an object storage facility - for
+development and testing purposes you can use the example configuration:
+
+```
+cp config/example.storage.yml config/storage.yml
+```
+
 ## Database setup
 
 The Rails Port uses three databases -  one for development, one for testing, and one for production. The database-specific configuration
index 69cc259f0c9e0195ecf5157ebb8d20d3e7703cac..7cbdb1e110b24c843dc8504c505a1363b15e0acb 100644 (file)
@@ -85,8 +85,8 @@ $(document).ready(function () {
 
   $("select#user_auth_provider").on("change", updateAuthUID);
 
-  $("input#user_image").on("change", function () {
-    $("#image_action_new").prop("checked", true);
+  $("input#user_avatar").on("change", function () {
+    $("#avatar_action_new").prop("checked", true);
   });
 
   function enableAuth() {
index 17031848d7c4503f822400dcbb4a3bf8b5587596..8c234006e4477172d457eeb583928b8872256e79 100644 (file)
@@ -660,15 +660,15 @@ class UsersController < ApplicationController
 
     user.languages = params[:user][:languages].split(",")
 
-    case params[:image_action]
+    case params[:avatar_action]
     when "new" then
-      user.image = params[:user][:image]
+      user.avatar.attach(params[:user][:avatar])
       user.image_use_gravatar = false
     when "delete" then
-      user.image = nil
+      user.avatar.purge
       user.image_use_gravatar = false
     when "gravatar" then
-      user.image = nil
+      user.avatar.purge
       user.image_use_gravatar = true
     end
 
index 1fc8e3ed2f1e0b6f82f6e325d0425c278a3d1e87..c22fef1ea2fa71e8d2f0a922a89e13316d5c5564 100644 (file)
@@ -7,8 +7,12 @@ module UserHelper
 
     if user.image_use_gravatar
       user_gravatar_tag(user, options)
-    else
+    elsif user.avatar.attached?
+      image_tag user.avatar.variant(:resize => "100x100>"), options
+    elsif user.image.file?
       image_tag user.image.url(:large), options
+    else
+      image_tag "avatar_large.png", options
     end
   end
 
@@ -18,8 +22,12 @@ module UserHelper
 
     if user.image_use_gravatar
       user_gravatar_tag(user, options)
-    else
+    elsif user.avatar.attached?
+      image_tag user.avatar.variant(:resize => "50x50>"), options
+    elsif user.image.file?
       image_tag user.image.url(:small), options
+    else
+      image_tag "avatar_small.png", options
     end
   end
 
@@ -29,16 +37,24 @@ module UserHelper
 
     if user.image_use_gravatar
       user_gravatar_tag(user, options)
-    else
+    elsif user.avatar.attached?
+      image_tag user.avatar.variant(:resize => "50x50>"), options
+    elsif user.image.file?
       image_tag user.image.url(:small), options
+    else
+      image_tag "avatar_small.png", options
     end
   end
 
   def user_image_url(user, options = {})
     if user.image_use_gravatar
       user_gravatar_url(user, options)
-    else
+    elsif user.avatar.attached?
+      url_for(user.avatar.variant(:resize => "100x100>"))
+    elsif user.image.file?
       image_url(user.image.url(:large))
+    else
+      image_url("avatar_large.png")
     end
   end
 
@@ -65,7 +81,7 @@ module UserHelper
   def user_gravatar_url(user, options = {})
     size = options[:size] || 100
     hash = Digest::MD5.hexdigest(user.email.downcase)
-    default_image_url = image_url("users/images/large.png")
+    default_image_url = image_url("avatar_large.png")
     "#{request.protocol}www.gravatar.com/avatar/#{hash}.jpg?s=#{size}&d=#{u(default_image_url)}"
   end
 
index e705efb006756f09a6f5ff21ea8b7665689725cc..bd2c83b56e245f34f5058003f1b382fe2f2a4517 100644 (file)
@@ -1,4 +1,6 @@
 class Notifier < ActionMailer::Base
+  include ActionView::Helpers::AssetUrlHelper
+
   default :from => Settings.email_from,
           :return_path => Settings.email_return_path,
           :auto_submitted => "auto-generated"
@@ -177,7 +179,16 @@ class Notifier < ActionMailer::Base
   end
 
   def attach_user_avatar(user)
-    attachments.inline["avatar.png"] = File.read(user_avatar_file_path(user))
+    attachments.inline["avatar.png"] = user_avatar_file(user)
+  end
+
+  def user_avatar_file(user)
+    avatar = user&.avatar
+    if avatar&.attached?
+      return avatar.variant(:resize => "50x50>").blob.download
+    else
+      return File.read(user_avatar_file_path(user))
+    end
   end
 
   def user_avatar_file_path(user)
@@ -185,7 +196,7 @@ class Notifier < ActionMailer::Base
     if image&.file?
       return image.path(:small)
     else
-      return Rails.root.join("app", "assets", "images", "users", "images", "small.png")
+      return Rails.root.join("app", "assets", "images", "avatar_small.png")
     end
   end
 
index 1d008959905e85a50428c0433c04dbe16799d8a8..13248e4fb4c4136273b3b2028fe272bbdfea6a12 100644 (file)
@@ -85,6 +85,8 @@ class User < ActiveRecord::Base
   scope :active, -> { where(:status => %w[active confirmed]) }
   scope :identifiable, -> { where(:data_public => true) }
 
+  has_one_attached :avatar
+
   has_attached_file :image,
                     :default_url => "/assets/:class/:attachment/:style.png",
                     :styles => { :large => "100x100>", :small => "50x50>" }
@@ -267,6 +269,8 @@ class User < ActiveRecord::Base
   ##
   # delete a user - leave the account but purge most personal data
   def delete
+    avatar.purge
+
     self.display_name = "user_#{id}"
     self.description = ""
     self.home_lat = nil
@@ -277,6 +281,7 @@ class User < ActiveRecord::Base
     self.auth_provider = nil
     self.auth_uid = nil
     self.status = "deleted"
+
     save
   end
 
index 7bf8e18a5a3019537bc1f2ab24940be03aa7db41..638e8583fb5b0de6ff454847dda8270b83a92a50 100644 (file)
@@ -8,7 +8,7 @@ xml.tag! "user", :id => user.id,
   else
     xml.tag! "contributor-terms", :agreed => user.terms_agreed.present?
   end
-  xml.tag! "img", :href => user_image_url(user) if user.image.file? || user.image_use_gravatar
+  xml.tag! "img", :href => user_image_url(user) if user.avatar.attached? || user.image.file? || user.image_use_gravatar
   xml.tag! "roles" do
     user.roles.each do |role|
       xml.tag! role.role
index b0839ad563573efb82b541a885c8f52ce4419196..7e8d533b066eb45046a92d5ea3e00357652e7c12 100644 (file)
       <label class="standard-label"><%= t ".image" %></label>
         <%= user_image current_user %>
         <ul class='form-list accountImage-options'>
-        <% if current_user.image.file? %>
+        <% if current_user.avatar.attached? || current_user.image.file? %>
         <li>
-          <%= radio_button_tag "image_action", "keep", !current_user.image_use_gravatar %>
-          <label class='standard-label' for='image_action_keep'><%= t ".keep image" %></label>
+          <%= radio_button_tag "avatar_action", "keep", !current_user.image_use_gravatar %>
+          <label class='standard-label' for='avatar_action_keep'><%= t ".keep image" %></label>
         </li>
         <% end %>
-        <% if current_user.image.file? || current_user.image_use_gravatar? %>
+        <% if current_user.avatar.attached? || current_user.image.file? || current_user.image_use_gravatar? %>
         <li>
-          <%= radio_button_tag "image_action", "delete" %>
-          <label class='standard-label' for='image_action_delete'><%= t ".delete image" %></label>
+          <%= radio_button_tag "avatar_action", "delete" %>
+          <label class='standard-label' for='avatar_action_delete'><%= t ".delete image" %></label>
         </li>
         <% end %>
-        <% if current_user.image.file? %>
+        <% if current_user.avatar.attached? || current_user.image.file? %>
           <li>
-            <%= radio_button_tag "image_action", "new" %>
-            <label class='standard-label' for='image_action_new'>
+            <%= radio_button_tag "avatar_action", "new" %>
+            <label class='standard-label' for='avatar_action_new'>
                 <%= t ".replace image" %>
                 <span class="form-help deemphasize"><%= t ".image size hint" %></span>
             </label>
-            <%= f.file_field :image %>
+            <%= f.file_field :avatar %>
           </li>
         <% else %>
         <li>
-          <%= radio_button_tag "image_action", "new" %>
-          <label class='standard-label' for='image_action_new'>
+          <%= radio_button_tag "avatar_action", "new" %>
+          <label class='standard-label' for='avatar_action_new'>
             <%= t ".new image" %>
             <span class="form-help deemphasize"><%= t ".image size hint" %></span>
           </label>
-          <%= f.file_field :image %>
+          <%= f.file_field :avatar %>
         </li>
         <% end %>
         <li>
-          <%= radio_button_tag "image_action", "gravatar", current_user.image_use_gravatar %>
-          <label class='standard-label' for='image_action_gravatar'>
+          <%= radio_button_tag "avatar_action", "gravatar", current_user.image_use_gravatar %>
+          <label class='standard-label' for='avatar_action_gravatar'>
             <%= t ".gravatar.gravatar" %>
             <span class='form-help deemphasize'> (<a href="<%= t ".gravatar.link" %>" target="_new"><%= t ".gravatar.link text" %></a>)</span>
           </label>
index b5649dd032e81aa0bf153efcb1d90e9bbfe20df4..95ba2dbdbf92b85744545000c99cc1e97a21b6cc 100644 (file)
@@ -1 +1,2 @@
 database.yml
+storage.yml
index 97121d5a72825f31009a75edcabcdccfed8676d3..90c0c1c40829ec58b17d865a2f687816ac72196e 100644 (file)
@@ -39,7 +39,7 @@ Rails.application.configure do
   # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
 
   # Store uploaded files on the local file system (see config/storage.yml for options)
-  config.active_storage.service = :local
+  config.active_storage.service = Settings.storage_service.to_symbol
 
   # Mount Action Cable outside main process or domain
   # config.action_cable.mount_path = nil
diff --git a/config/example.storage.yml b/config/example.storage.yml
new file mode 100644 (file)
index 0000000..695f17b
--- /dev/null
@@ -0,0 +1,7 @@
+test:
+  service: Disk
+  root: <%= Rails.root.join("tmp/storage") %>
+
+local:
+  service: Disk
+  root: <%= Rails.root.join("storage") %>
diff --git a/config/initializers/active_storage.rb b/config/initializers/active_storage.rb
new file mode 100644 (file)
index 0000000..3d2c912
--- /dev/null
@@ -0,0 +1,31 @@
+Rails.configuration.after_initialize do
+  require "active_storage/service/s3_service"
+  require_dependency "active_storage/variant"
+
+  module OpenStreetMap
+    module ActiveStorage
+      module Variant
+        private
+
+        def upload(image)
+          File.open(image.path, "r") { |file| service.upload(key, file, :content_type => content_type) }
+        end
+      end
+
+      module S3Service
+        def upload(key, io, content_type:, **options)
+          @upload_options[:content_type] = content_type
+          super(key, io, **options)
+          @upload_options.delete(:content_type)
+        end
+      end
+    end
+  end
+
+  ActiveStorage::Variant.prepend(OpenStreetMap::ActiveStorage::Variant)
+  ActiveStorage::Service::S3Service.prepend(OpenStreetMap::ActiveStorage::S3Service)
+
+  ActiveSupport::Reloader.to_complete do
+    ActiveStorage::Variant.prepend(OpenStreetMap::ActiveStorage::Variant)
+  end
+end
index f7d5d79249eb43243caabc463273871e98bee8b6..271bd79e7c881349f924b8d2e7b81b03d0bbf8b4 100644 (file)
@@ -77,5 +77,6 @@ Config.setup do |config|
     required(:api_timeout).filled(:int?)
     required(:imagery_blacklist).maybe(:array?)
     required(:status).filled(:str?, :included_in? => ALLOWED_STATUS)
+    required(:storage_service).filled(:str?)
   end
 end
index 54702a39915818ebbd0bace6a7486766c0b445cc..b24eb5c4264250c9f65c5ba5bd27bd91322a670f 100644 (file)
@@ -21,6 +21,9 @@ csp_policy = {
 csp_policy[:connect_src] << PIWIK["location"] if defined?(PIWIK)
 csp_policy[:img_src] << PIWIK["location"] if defined?(PIWIK)
 csp_policy[:script_src] << PIWIK["location"] if defined?(PIWIK)
+
+csp_policy[:img_src] << Settings.storage_url if Settings.key?(:storage_url)
+
 csp_policy[:report_uri] << Settings.csp_report_url if Settings.key?(:csp_report_url)
 
 cookie_policy = {
index a664b78b0f883fe4cf15d23f14ae26688f22be5b..0f64382c9f4e39fe837765def550a8a063b620f8 100644 (file)
@@ -122,3 +122,7 @@ fossgis_osrm_url: "https://routing.openstreetmap.de/"
 csp_enforce: false
 # URL for reporting Content-Security-Policy violations
 #csp_report_url: ""
+# Storage service to use in production mode
+storage_service: "local"
+# Root URL for storage service
+# storage_url:
diff --git a/config/storage.yml b/config/storage.yml
deleted file mode 100644 (file)
index d32f76e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-test:
-  service: Disk
-  root: <%= Rails.root.join("tmp/storage") %>
-
-local:
-  service: Disk
-  root: <%= Rails.root.join("storage") %>
-
-# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
-# amazon:
-#   service: S3
-#   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
-#   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
-#   region: us-east-1
-#   bucket: your_own_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
-
-# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
-# microsoft:
-#   service: AzureStorage
-#   storage_account_name: your_account_name
-#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
-#   container: your_container_name
-
-# mirror:
-#   service: Mirror
-#   primary: local
-#   mirrors: [ amazon, google, microsoft ]
diff --git a/db/migrate/20190702193519_create_active_storage_tables.rb b/db/migrate/20190702193519_create_active_storage_tables.rb
new file mode 100644 (file)
index 0000000..1968b7b
--- /dev/null
@@ -0,0 +1,27 @@
+# This migration comes from active_storage (originally 20170806125915)
+class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
+  def change
+    create_table :active_storage_blobs do |t|
+      t.string   :key,        :null => false
+      t.string   :filename,   :null => false
+      t.string   :content_type
+      t.text     :metadata
+      t.bigint   :byte_size,  :null => false
+      t.string   :checksum,   :null => false
+      t.datetime :created_at, :null => false
+
+      t.index [:key], :unique => true
+    end
+
+    create_table :active_storage_attachments do |t|
+      t.string     :name,     :null => false
+      t.references :record,   :null => false, :polymorphic => true, :index => false
+      t.references :blob,     :null => false
+
+      t.datetime :created_at, :null => false
+
+      t.index [:record_type, :record_id, :name, :blob_id], :name => "index_active_storage_attachments_uniqueness", :unique => true
+      t.foreign_key :active_storage_blobs, :column => :blob_id
+    end
+  end
+end
index d115140d147fc22fca630067116aae44e6242041..8f4fe3e793c5809a754a01fb2539853d38daaf4a 100644 (file)
@@ -192,6 +192,74 @@ CREATE SEQUENCE public.acls_id_seq
 ALTER SEQUENCE public.acls_id_seq OWNED BY public.acls.id;
 
 
+--
+-- Name: active_storage_attachments; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.active_storage_attachments (
+    id bigint NOT NULL,
+    name character varying NOT NULL,
+    record_type character varying NOT NULL,
+    record_id bigint NOT NULL,
+    blob_id bigint NOT NULL,
+    created_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: active_storage_attachments_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.active_storage_attachments_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: active_storage_attachments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.active_storage_attachments_id_seq OWNED BY public.active_storage_attachments.id;
+
+
+--
+-- Name: active_storage_blobs; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.active_storage_blobs (
+    id bigint NOT NULL,
+    key character varying NOT NULL,
+    filename character varying NOT NULL,
+    content_type character varying,
+    metadata text,
+    byte_size bigint NOT NULL,
+    checksum character varying NOT NULL,
+    created_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: active_storage_blobs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.active_storage_blobs_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: active_storage_blobs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.active_storage_blobs_id_seq OWNED BY public.active_storage_blobs.id;
+
+
 --
 -- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: -
 --
@@ -1363,6 +1431,20 @@ CREATE TABLE public.ways (
 ALTER TABLE ONLY public.acls ALTER COLUMN id SET DEFAULT nextval('public.acls_id_seq'::regclass);
 
 
+--
+-- Name: active_storage_attachments id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.active_storage_attachments ALTER COLUMN id SET DEFAULT nextval('public.active_storage_attachments_id_seq'::regclass);
+
+
+--
+-- Name: active_storage_blobs id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.active_storage_blobs ALTER COLUMN id SET DEFAULT nextval('public.active_storage_blobs_id_seq'::regclass);
+
+
 --
 -- Name: changeset_comments id; Type: DEFAULT; Schema: public; Owner: -
 --
@@ -1546,6 +1628,22 @@ ALTER TABLE ONLY public.acls
     ADD CONSTRAINT acls_pkey PRIMARY KEY (id);
 
 
+--
+-- Name: active_storage_attachments active_storage_attachments_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.active_storage_attachments
+    ADD CONSTRAINT active_storage_attachments_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: active_storage_blobs active_storage_blobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.active_storage_blobs
+    ADD CONSTRAINT active_storage_blobs_pkey PRIMARY KEY (id);
+
+
 --
 -- Name: ar_internal_metadata ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: -
 --
@@ -2086,6 +2184,27 @@ CREATE INDEX index_acls_on_domain ON public.acls USING btree (domain);
 CREATE INDEX index_acls_on_mx ON public.acls USING btree (mx);
 
 
+--
+-- Name: index_active_storage_attachments_on_blob_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_active_storage_attachments_on_blob_id ON public.active_storage_attachments USING btree (blob_id);
+
+
+--
+-- Name: index_active_storage_attachments_uniqueness; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE UNIQUE INDEX index_active_storage_attachments_uniqueness ON public.active_storage_attachments USING btree (record_type, record_id, name, blob_id);
+
+
+--
+-- Name: index_active_storage_blobs_on_key; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE UNIQUE INDEX index_active_storage_blobs_on_key ON public.active_storage_blobs USING btree (key);
+
+
 --
 -- Name: index_changeset_comments_on_created_at; Type: INDEX; Schema: public; Owner: -
 --
@@ -2598,6 +2717,14 @@ ALTER TABLE ONLY public.diary_entry_subscriptions
     ADD CONSTRAINT diary_entry_subscriptions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
 
 
+--
+-- Name: active_storage_attachments fk_rails_c3b3935057; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.active_storage_attachments
+    ADD CONSTRAINT fk_rails_c3b3935057 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id);
+
+
 --
 -- Name: friends friends_friend_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
 --
@@ -2958,6 +3085,7 @@ INSERT INTO "schema_migrations" (version) VALUES
 ('20181031113522'),
 ('20190518115041'),
 ('20190623093642'),
+('20190702193519'),
 ('21'),
 ('22'),
 ('23'),
index 984ea8d46cce6bfc3fa49a3c1ec752fe2f87c337..8b438e903283e849d23f7971c62fdecedae10e22 100644 (file)
@@ -876,28 +876,28 @@ class UsersControllerTest < ActionController::TestCase
 
     # Changing to an uploaded image should work
     image = Rack::Test::UploadedFile.new("test/gpx/fixtures/a.gif", "image/gif")
-    post :account, :params => { :display_name => user.display_name, :image_action => "new", :user => user.attributes.merge(:image => image) }, :session => { :user => user }
+    post :account, :params => { :display_name => user.display_name, :avatar_action => "new", :user => user.attributes.merge(:avatar => image) }, :session => { :user => user }
     assert_response :success
     assert_template :account
     assert_select "div#errorExplanation", false
     assert_select ".notice", /^User information updated successfully/
-    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=image_action][checked][value=?]", "keep"
+    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=avatar_action][checked][value=?]", "keep"
 
     # Changing to a gravatar image should work
-    post :account, :params => { :display_name => user.display_name, :image_action => "gravatar", :user => user.attributes }, :session => { :user => user }
+    post :account, :params => { :display_name => user.display_name, :avatar_action => "gravatar", :user => user.attributes }, :session => { :user => user }
     assert_response :success
     assert_template :account
     assert_select "div#errorExplanation", false
     assert_select ".notice", /^User information updated successfully/
-    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=image_action][checked][value=?]", "gravatar"
+    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=avatar_action][checked][value=?]", "gravatar"
 
     # Removing the image should work
-    post :account, :params => { :display_name => user.display_name, :image_action => "delete", :user => user.attributes }, :session => { :user => user }
+    post :account, :params => { :display_name => user.display_name, :avatar_action => "delete", :user => user.attributes }, :session => { :user => user }
     assert_response :success
     assert_template :account
     assert_select "div#errorExplanation", false
     assert_select ".notice", /^User information updated successfully/
-    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=image_action][checked]", false
+    assert_select "form#accountForm > fieldset > div.form-row.accountImage input[name=avatar_action][checked]", false
 
     # Adding external authentication should redirect to the auth provider
     post :account, :params => { :display_name => user.display_name, :user => user.attributes.merge(:auth_provider => "openid", :auth_uid => "gmail.com") }, :session => { :user => user }
index c57299a96d4f3e4db339d710cfc18e078380dabf..0fcbc3d90cfb7060d4f7ef77ec25f00890712af7 100644 (file)
@@ -8,10 +8,10 @@ class UserHelperTest < ActionView::TestCase
     gravatar_user = create(:user, :image_use_gravatar => true)
 
     image = user_image(user)
-    assert_match %r{^<img class="user_image" .* src="/assets/users/images/large-.*" />$}, image
+    assert_match %r{^<img class="user_image" .* src="/images/avatar_large.png" />$}, image
 
     image = user_image(user, :class => "foo")
-    assert_match %r{^<img class="foo" .* src="/assets/users/images/large-.*" />$}, image
+    assert_match %r{^<img class="foo" .* src="/images/avatar_large.png" />$}, image
 
     image = user_image(gravatar_user)
     assert_match %r{^<img class="user_image" .* src="http://www.gravatar.com/avatar/.*" />$}, image
@@ -25,10 +25,10 @@ class UserHelperTest < ActionView::TestCase
     gravatar_user = create(:user, :image_use_gravatar => true)
 
     image = user_thumbnail(user)
-    assert_match %r{^<img class="user_thumbnail" .* src="/assets/users/images/small-.*" />$}, image
+    assert_match %r{^<img class="user_thumbnail" .* src="/images/avatar_small.png" />$}, image
 
     image = user_thumbnail(user, :class => "foo")
-    assert_match %r{^<img class="foo" .* src="/assets/users/images/small-.*" />$}, image
+    assert_match %r{^<img class="foo" .* src="/images/avatar_small.png" />$}, image
 
     image = user_thumbnail(gravatar_user)
     assert_match %r{^<img class="user_thumbnail" .* src="http://www.gravatar.com/avatar/.*" />$}, image
@@ -42,10 +42,10 @@ class UserHelperTest < ActionView::TestCase
     gravatar_user = create(:user, :image_use_gravatar => true)
 
     image = user_thumbnail_tiny(user)
-    assert_match %r{^<img class="user_thumbnail_tiny" .* src="/assets/users/images/small-.*" />$}, image
+    assert_match %r{^<img class="user_thumbnail_tiny" .* src="/images/avatar_small.png" />$}, image
 
     image = user_thumbnail_tiny(user, :class => "foo")
-    assert_match %r{^<img class="foo" .* src="/assets/users/images/small-.*" />$}, image
+    assert_match %r{^<img class="foo" .* src="/images/avatar_small.png" />$}, image
 
     image = user_thumbnail_tiny(gravatar_user)
     assert_match %r{^<img class="user_thumbnail_tiny" .* src="http://www.gravatar.com/avatar/.*" />$}, image