From 9f925e9ba5f88b063d1a910e48c8af7f1af88e5e Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 09:48:06 -0700 Subject: [PATCH 01/59] Fix deprecation warning in rspec change success? to successful? --- spec/api/v1/restrooms_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api/v1/restrooms_spec.rb b/spec/api/v1/restrooms_spec.rb index 5e3ec181..8dd2ea53 100644 --- a/spec/api/v1/restrooms_spec.rb +++ b/spec/api/v1/restrooms_spec.rb @@ -24,7 +24,7 @@ edit.update(approved: false, edit_id: 1) get '/api/v1/restrooms' - expect(response).to be_success + expect(response).to be_successful json = JSON.parse(response.body) expect(json.length).to eq(1) From a013857d9e00704b91d252f4be33147b0ede74d4 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 12:27:50 -0700 Subject: [PATCH 02/59] Add bulk_upload model --- app/models/bulk_upload.rb | 2 ++ db/migrate/20190330192650_create_bulk_uploads.rb | 8 ++++++++ spec/factories/bulk_uploads.rb | 5 +++++ spec/models/bulk_upload_spec.rb | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 app/models/bulk_upload.rb create mode 100644 db/migrate/20190330192650_create_bulk_uploads.rb create mode 100644 spec/factories/bulk_uploads.rb create mode 100644 spec/models/bulk_upload_spec.rb diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb new file mode 100644 index 00000000..53ca67ad --- /dev/null +++ b/app/models/bulk_upload.rb @@ -0,0 +1,2 @@ +class BulkUpload < ApplicationRecord +end diff --git a/db/migrate/20190330192650_create_bulk_uploads.rb b/db/migrate/20190330192650_create_bulk_uploads.rb new file mode 100644 index 00000000..6218585e --- /dev/null +++ b/db/migrate/20190330192650_create_bulk_uploads.rb @@ -0,0 +1,8 @@ +class CreateBulkUploads < ActiveRecord::Migration[5.2] + def change + create_table :bulk_uploads do |t| + + t.timestamps + end + end +end diff --git a/spec/factories/bulk_uploads.rb b/spec/factories/bulk_uploads.rb new file mode 100644 index 00000000..5ee0bbfc --- /dev/null +++ b/spec/factories/bulk_uploads.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :bulk_upload do + + end +end diff --git a/spec/models/bulk_upload_spec.rb b/spec/models/bulk_upload_spec.rb new file mode 100644 index 00000000..27ec90e6 --- /dev/null +++ b/spec/models/bulk_upload_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe BulkUpload, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 689f2a7bd1813f0f7d06fd30eb6f9ce5ffa97d59 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 14:31:27 -0700 Subject: [PATCH 03/59] Create active storage tables and migrate database --- ...te_active_storage_tables.active_storage.rb | 27 +++++++++++++++++ db/schema.rb | 29 ++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190330205102_create_active_storage_tables.active_storage.rb diff --git a/db/migrate/20190330205102_create_active_storage_tables.active_storage.rb b/db/migrate/20190330205102_create_active_storage_tables.active_storage.rb new file mode 100644 index 00000000..0b2ce257 --- /dev/null +++ b/db/migrate/20190330205102_create_active_storage_tables.active_storage.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 0565c32c..dede54a6 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.define(version: 20180613231032) do +ActiveRecord::Schema.define(version: 2019_03_30_205102) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -30,6 +30,27 @@ t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id" end + create_table "active_storage_attachments", force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.bigint "record_id", null: false + t.bigint "blob_id", null: false + t.datetime "created_at", null: false + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true + end + + create_table "active_storage_blobs", force: :cascade 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"], name: "index_active_storage_blobs_on_key", unique: true + end + create_table "admin_users", id: :serial, force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false @@ -47,6 +68,11 @@ t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end + create_table "bulk_uploads", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "restrooms", id: :serial, force: :cascade do |t| t.string "name" t.string "street" @@ -68,4 +94,5 @@ t.boolean "approved", default: true end + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" end From 7ee3e53ec75e3757d1887180a0854ffc39afff77 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 14:32:04 -0700 Subject: [PATCH 04/59] Add flag to not always setup database on docker-compose run --- setup/entry | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup/entry b/setup/entry index 37c06f7d..ca79a1f5 100755 --- a/setup/entry +++ b/setup/entry @@ -1,7 +1,9 @@ #!/bin/bash set -e -# Set up the database for development, and seed with placeholder data from `db/export.csv` -SEEDING_DONT_GEOCODE="true" rails db:setup +if [[ -z ${SKIP_CREATE_DB+x} ]]; then + # Set up the database for development, and seed with placeholder data from `db/export.csv` + SEEDING_DONT_GEOCODE="true" rails db:setup +fi exec "$@" From 35377952613da1f6afe04c158404ce3a08a3595b Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 14:44:45 -0700 Subject: [PATCH 05/59] Add attachment to bulk_upload model --- app/models/bulk_upload.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index 53ca67ad..371c6328 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -1,2 +1,3 @@ class BulkUpload < ApplicationRecord + has_one_attached :file end From 5baffd27e6310bc54a965ead65dc8092dff7a44a Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 15:36:16 -0700 Subject: [PATCH 06/59] Add bulk upload link to _formsubmit in views/restrooms --- app/controllers/bulk_uploads_controller.rb | 4 ++++ app/views/bulk_uploads/new.html.haml | 0 app/views/restrooms/_formsubmit.html.haml | 1 + config/routes.rb | 21 +++++++++++---------- 4 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 app/controllers/bulk_uploads_controller.rb create mode 100644 app/views/bulk_uploads/new.html.haml diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb new file mode 100644 index 00000000..f490b91e --- /dev/null +++ b/app/controllers/bulk_uploads_controller.rb @@ -0,0 +1,4 @@ +class BulkUploadsController < ApplicationController + def new + end +end \ No newline at end of file diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml new file mode 100644 index 00000000..e69de29b diff --git a/app/views/restrooms/_formsubmit.html.haml b/app/views/restrooms/_formsubmit.html.haml index f8c9cdaf..27b0fe0a 100644 --- a/app/views/restrooms/_formsubmit.html.haml +++ b/app/views/restrooms/_formsubmit.html.haml @@ -1,6 +1,7 @@ %h1= t('restroom.add_new') = simple_form_for @restroom, :url => restrooms_path, :method => :post, html: {class: 'submit-new-bathroom-form form-vertical'} do |f| + = link_to "Add a CSV file", new_bulk_upload_path %h5= t('restroom.required') .clearfix %button.btn.btn-light-purple.guess-btn{:type => "button", :value => t('restroom.guess_location')} diff --git a/config/routes.rb b/config/routes.rb index 47a7974f..4710402b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,19 +1,20 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + resources :bulk_uploads, only: [:new, :create, :show] devise_for :admin_users, ActiveAdmin::Devise.config - ActiveAdmin.routes(self) - resources :restrooms, except: [:edit, :destroy] + ActiveAdmin.routes(self) + resources :restrooms, except: [:edit, :destroy] - namespace :api do - resources :docs, only: [:index] - end + namespace :api do + resources :docs, only: [:index] + end - mount API::Base => '/api' + mount API::Base => '/api' - get '/contact', to: 'contacts#new' - get "/*id" => 'pages#show', as: :page, format: false - root 'pages#index' + get '/contact', to: 'contacts#new' + get "/*id" => 'pages#show', as: :page, format: false + root 'pages#index' - resources "contacts", only: [:new, :create] + resources "contacts", only: [:new, :create] end From 9a59c46fe7c8d7ad349f7130b7f209b280763953 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sat, 30 Mar 2019 16:10:56 -0700 Subject: [PATCH 07/59] Install delayed_job --- Gemfile | 1 + Gemfile.lock | 6 +++++ bin/delayed_job | 5 +++++ .../20190330225402_create_delayed_jobs.rb | 22 +++++++++++++++++++ db/schema.rb | 17 +++++++++++++- 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100755 bin/delayed_job create mode 100644 db/migrate/20190330225402_create_delayed_jobs.rb diff --git a/Gemfile b/Gemfile index 5aef4997..f299a770 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'bootstrap-sass', '>= 3.4.1' gem 'bugsnag' gem 'coffee-rails', '~> 4.2' gem 'country_select' +gem 'delayed_job_active_record' gem 'devise', '~> 4.6' gem 'geocoder', '~> 1.2.1' gem 'grape', '1.1' diff --git a/Gemfile.lock b/Gemfile.lock index 55b9f1ee..d1179e92 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,6 +112,11 @@ GEM crass (1.0.4) database_cleaner (1.7.0) debug_inspector (0.0.3) + delayed_job (4.1.5) + activesupport (>= 3.0, < 5.3) + delayed_job_active_record (4.1.3) + activerecord (>= 3.0, < 5.3) + delayed_job (>= 3.0, < 5) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) devise (4.6.1) @@ -385,6 +390,7 @@ DEPENDENCIES coffee-rails (~> 4.2) country_select database_cleaner + delayed_job_active_record devise (~> 4.6) dotenv-rails (~> 2.2.1) factory_bot_rails (~> 4.8.2) diff --git a/bin/delayed_job b/bin/delayed_job new file mode 100755 index 00000000..edf19598 --- /dev/null +++ b/bin/delayed_job @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) +require 'delayed/command' +Delayed::Command.new(ARGV).daemonize diff --git a/db/migrate/20190330225402_create_delayed_jobs.rb b/db/migrate/20190330225402_create_delayed_jobs.rb new file mode 100644 index 00000000..d10f2400 --- /dev/null +++ b/db/migrate/20190330225402_create_delayed_jobs.rb @@ -0,0 +1,22 @@ +class CreateDelayedJobs < ActiveRecord::Migration[5.2] + def self.up + create_table :delayed_jobs, force: true do |table| + table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue + table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually. + table.text :handler, null: false # YAML-encoded string of the object that will do work + table.text :last_error # reason for last failure (See Note below) + table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. + table.datetime :locked_at # Set when a client is working on this object + table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) + table.string :locked_by # Who is working on this object (if locked) + table.string :queue # The name of the queue this job is in + table.timestamps null: true + end + + add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority" + end + + def self.down + drop_table :delayed_jobs + end +end diff --git a/db/schema.rb b/db/schema.rb index dede54a6..156231fc 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.define(version: 2019_03_30_205102) do +ActiveRecord::Schema.define(version: 2019_03_30_225402) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -73,6 +73,21 @@ t.datetime "updated_at", null: false end + create_table "delayed_jobs", force: :cascade do |t| + t.integer "priority", default: 0, null: false + t.integer "attempts", default: 0, null: false + t.text "handler", null: false + t.text "last_error" + t.datetime "run_at" + t.datetime "locked_at" + t.datetime "failed_at" + t.string "locked_by" + t.string "queue" + t.datetime "created_at" + t.datetime "updated_at" + t.index ["priority", "run_at"], name: "delayed_jobs_priority" + end + create_table "restrooms", id: :serial, force: :cascade do |t| t.string "name" t.string "street" From 8aeadf3012a034e86f59c4ca7c3bb40b92161420 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sat, 30 Mar 2019 16:11:22 -0700 Subject: [PATCH 08/59] Add BulkImportJob stub --- app/jobs/bulk_import_job.rb | 7 +++++++ spec/jobs/bulk_import_job_spec.rb | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 app/jobs/bulk_import_job.rb create mode 100644 spec/jobs/bulk_import_job_spec.rb diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb new file mode 100644 index 00000000..43db1096 --- /dev/null +++ b/app/jobs/bulk_import_job.rb @@ -0,0 +1,7 @@ +class BulkImportJob < ApplicationJob + queue_as :default + + def perform(*args) + # Do something later + end +end diff --git a/spec/jobs/bulk_import_job_spec.rb b/spec/jobs/bulk_import_job_spec.rb new file mode 100644 index 00000000..e750f70e --- /dev/null +++ b/spec/jobs/bulk_import_job_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe BulkImportJob, type: :job do + pending "add some examples to (or delete) #{__FILE__}" +end From 810ac0f425fb4807d1c075b3630a16d8f30dd773 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sat, 30 Mar 2019 16:26:00 -0700 Subject: [PATCH 09/59] Add ability to upload CSV --- .gitignore | 1 + app/controllers/bulk_uploads_controller.rb | 19 +++++++++++++++++++ app/views/bulk_uploads/new.html.haml | 5 +++++ app/views/bulk_uploads/show.html.haml | 0 config/locales/en/restroom.en.yml | 2 ++ spec/fixtures/bulk_upload_test.csv | 1 + 6 files changed, 28 insertions(+) create mode 100644 app/views/bulk_uploads/show.html.haml create mode 100644 spec/fixtures/bulk_upload_test.csv diff --git a/.gitignore b/.gitignore index 82e2a91f..7312d9d4 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ ruby /node_modules yarn-debug.log* .yarn-integrity +/storage/* diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index f490b91e..08373b18 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -1,4 +1,23 @@ class BulkUploadsController < ApplicationController def new + @bulk_upload = BulkUpload.new end + + def create + @bulk_upload = BulkUpload.new(bulk_upload_params) + if @bulk_upload.save + redirect_to bulk_upload_path(@bulk_upload) + else + render action: :new + end + end + + def show + + end + + private + def bulk_upload_params + params.require(:bulk_upload).permit(:file) + end end \ No newline at end of file diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index e69de29b..74709fcb 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -0,0 +1,5 @@ +%h3= t('restroom.add_bulk') + += simple_form_for @bulk_upload do |f| + = f.file_field :file + = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" diff --git a/app/views/bulk_uploads/show.html.haml b/app/views/bulk_uploads/show.html.haml new file mode 100644 index 00000000..e69de29b diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index 9245be61..74c665a8 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -15,6 +15,8 @@ en: restroom: add_new: 'Submit a restroom to our database' + add_bulk: 'Upload CSV file' + csv_submit: 'Save CSV' preview: 'Preview' required: '* marks required field' guess_location: 'Guess current location' diff --git a/spec/fixtures/bulk_upload_test.csv b/spec/fixtures/bulk_upload_test.csv new file mode 100644 index 00000000..1de0e01c --- /dev/null +++ b/spec/fixtures/bulk_upload_test.csv @@ -0,0 +1 @@ +I, am, having, a, lovely day, coding, with, friends From 2c23856500228046f7819f40fed0187ac8543a6d Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sat, 30 Mar 2019 16:55:42 -0700 Subject: [PATCH 10/59] Configure ActiveJob to use delayed_job --- config/application.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/application.rb b/config/application.rb index c3bf487c..b57ebf1d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,7 +27,7 @@ class Application < Rails::Application config.i18n.available_locales = [:en, :es, :fr, :hi, :it, :pl, :"pt-BR"] #config.i18n.default_locale = :fr - - + # ActiveJob + config.active_job.queue_adapter = :delayed_job end end From 057c4645d8743782ff7c60785555e9a736f4bc74 Mon Sep 17 00:00:00 2001 From: chelseatroy Date: Sat, 30 Mar 2019 10:55:02 -0700 Subject: [PATCH 11/59] Updates readme to add mitigation strategy for rough docker-compose flows --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d4fc08d..a75d8435 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,8 @@ You can now run the app with: docker-compose up ``` +If this results in a syntax error in cli.js, remove the docker image and re-run `docker-compose build` (this is especially likely to be the issue if your `docker-compose` commands got interrupted and had to be re-run a few times). + The container will be reachable at this address: `localhost:3000` _(Point your web browser at `localhost:3000` or `127.0.0.1:3000`, or even `[IP address of computer running the container]:3000` from any computer on the same LAN. The last method is useful for testing the app/site on smart phones and tablets.)_ From 8d55addac1cb8f1a04ddc567f41cd33a9bcab067 Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Sat, 30 Mar 2019 16:45:46 -0700 Subject: [PATCH 12/59] Install user model for devise --- app/models/user.rb | 6 + app/views/users/confirmations/new.html.erb | 20 ++++ .../mailer/confirmation_instructions.html.erb | 5 + app/views/users/mailer/email_changed.html.erb | 7 ++ .../users/mailer/password_change.html.erb | 3 + .../reset_password_instructions.html.erb | 8 ++ .../users/mailer/unlock_instructions.html.erb | 7 ++ app/views/users/passwords/edit.html.erb | 24 ++++ app/views/users/passwords/new.html.erb | 18 +++ app/views/users/registrations/edit.html.erb | 35 ++++++ app/views/users/registrations/new.html.erb | 25 ++++ app/views/users/sessions/new.html.erb | 20 ++++ .../users/shared/_error_messages.html.erb | 15 +++ app/views/users/shared/_links.html.erb | 25 ++++ app/views/users/unlocks/new.html.erb | 19 +++ config/initializers/devise.rb | 112 ++++++++++++------ config/locales/devise.en.yml | 65 ++++++++++ config/routes.rb | 24 ++-- .../20190330233323_devise_create_users.rb | 44 +++++++ db/schema.rb | 14 ++- spec/factories/users.rb | 5 + spec/models/user_spec.rb | 5 + 22 files changed, 459 insertions(+), 47 deletions(-) create mode 100644 app/models/user.rb create mode 100644 app/views/users/confirmations/new.html.erb create mode 100644 app/views/users/mailer/confirmation_instructions.html.erb create mode 100644 app/views/users/mailer/email_changed.html.erb create mode 100644 app/views/users/mailer/password_change.html.erb create mode 100644 app/views/users/mailer/reset_password_instructions.html.erb create mode 100644 app/views/users/mailer/unlock_instructions.html.erb create mode 100644 app/views/users/passwords/edit.html.erb create mode 100644 app/views/users/passwords/new.html.erb create mode 100644 app/views/users/registrations/edit.html.erb create mode 100644 app/views/users/registrations/new.html.erb create mode 100644 app/views/users/sessions/new.html.erb create mode 100644 app/views/users/shared/_error_messages.html.erb create mode 100644 app/views/users/shared/_links.html.erb create mode 100644 app/views/users/unlocks/new.html.erb create mode 100644 config/locales/devise.en.yml create mode 100644 db/migrate/20190330233323_devise_create_users.rb create mode 100644 spec/factories/users.rb create mode 100644 spec/models/user_spec.rb diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 00000000..47567994 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,6 @@ +class User < ApplicationRecord + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :validatable +end diff --git a/app/views/users/confirmations/new.html.erb b/app/views/users/confirmations/new.html.erb new file mode 100644 index 00000000..2f40968f --- /dev/null +++ b/app/views/users/confirmations/new.html.erb @@ -0,0 +1,20 @@ +

Resend confirmation instructions

+ +<%= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + <%= f.full_error :confirmation_token %> + +
+ <%= f.input :email, + required: true, + autofocus: true, + value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), + input_html: { autocomplete: "email" } %> +
+ +
+ <%= f.button :submit, "Resend confirmation instructions" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/app/views/users/mailer/confirmation_instructions.html.erb b/app/views/users/mailer/confirmation_instructions.html.erb new file mode 100644 index 00000000..dc55f64f --- /dev/null +++ b/app/views/users/mailer/confirmation_instructions.html.erb @@ -0,0 +1,5 @@ +

Welcome <%= @email %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/users/mailer/email_changed.html.erb b/app/views/users/mailer/email_changed.html.erb new file mode 100644 index 00000000..32f4ba80 --- /dev/null +++ b/app/views/users/mailer/email_changed.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @email %>!

+ +<% if @resource.try(:unconfirmed_email?) %> +

We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.

+<% else %> +

We're contacting you to notify you that your email has been changed to <%= @resource.email %>.

+<% end %> diff --git a/app/views/users/mailer/password_change.html.erb b/app/views/users/mailer/password_change.html.erb new file mode 100644 index 00000000..b41daf47 --- /dev/null +++ b/app/views/users/mailer/password_change.html.erb @@ -0,0 +1,3 @@ +

Hello <%= @resource.email %>!

+ +

We're contacting you to notify you that your password has been changed.

diff --git a/app/views/users/mailer/reset_password_instructions.html.erb b/app/views/users/mailer/reset_password_instructions.html.erb new file mode 100644 index 00000000..f667dc12 --- /dev/null +++ b/app/views/users/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +

Hello <%= @resource.email %>!

+ +

Someone has requested a link to change your password. You can do this through the link below.

+ +

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

+ +

If you didn't request this, please ignore this email.

+

Your password won't change until you access the link above and create a new one.

diff --git a/app/views/users/mailer/unlock_instructions.html.erb b/app/views/users/mailer/unlock_instructions.html.erb new file mode 100644 index 00000000..41e148bf --- /dev/null +++ b/app/views/users/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @resource.email %>!

+ +

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

+ +

Click the link below to unlock your account:

+ +

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/users/passwords/edit.html.erb b/app/views/users/passwords/edit.html.erb new file mode 100644 index 00000000..e16f2745 --- /dev/null +++ b/app/views/users/passwords/edit.html.erb @@ -0,0 +1,24 @@ +

Change your password

+ +<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> + <%= f.error_notification %> + + <%= f.input :reset_password_token, as: :hidden %> + <%= f.full_error :reset_password_token %> + +
+ <%= f.input :password, + label: "New password", + required: true, + autofocus: true, + hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length), + input_html: { autocomplete: "new-password" } %> + <%= f.input :password_confirmation, label: "Confirm your new password", required: true %> +
+ +
+ <%= f.button :submit, "Change my password" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/app/views/users/passwords/new.html.erb b/app/views/users/passwords/new.html.erb new file mode 100644 index 00000000..aac1eaa6 --- /dev/null +++ b/app/views/users/passwords/new.html.erb @@ -0,0 +1,18 @@ +

Forgot your password?

+ +<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + +
+ <%= f.input :email, + required: true, + autofocus: true, + input_html: { autocomplete: "email" } %> +
+ +
+ <%= f.button :submit, "Send me reset password instructions" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/app/views/users/registrations/edit.html.erb b/app/views/users/registrations/edit.html.erb new file mode 100644 index 00000000..dfb7eb94 --- /dev/null +++ b/app/views/users/registrations/edit.html.erb @@ -0,0 +1,35 @@ +

Edit <%= resource_name.to_s.humanize %>

+ +<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= f.error_notification %> + +
+ <%= f.input :email, required: true, autofocus: true %> + + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +

Currently waiting confirmation for: <%= resource.unconfirmed_email %>

+ <% end %> + + <%= f.input :password, + hint: "leave it blank if you don't want to change it", + required: false, + input_html: { autocomplete: "new-password" } %> + <%= f.input :password_confirmation, + required: false, + input_html: { autocomplete: "new-password" } %> + <%= f.input :current_password, + hint: "we need your current password to confirm your changes", + required: true, + input_html: { autocomplete: "current-password" } %> +
+ +
+ <%= f.button :submit, "Update" %> +
+<% end %> + +

Cancel my account

+ +

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

+ +<%= link_to "Back", :back %> diff --git a/app/views/users/registrations/new.html.erb b/app/views/users/registrations/new.html.erb new file mode 100644 index 00000000..58719bea --- /dev/null +++ b/app/views/users/registrations/new.html.erb @@ -0,0 +1,25 @@ +

Sign up

+ +<%= simple_form_for(resource, as: resource_name, url: new_user_registration_path(resource_name)) do |f| %> + <%= f.error_notification %> + +
+ <%= f.input :email, + required: true, + autofocus: true, + input_html: { autocomplete: "email" }%> + <%= f.input :password, + required: true, + hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length), + input_html: { autocomplete: "new-password" } %> + <%= f.input :password_confirmation, + required: true, + input_html: { autocomplete: "new-password" } %> +
+ +
+ <%= f.button :submit, "Sign up" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/app/views/users/sessions/new.html.erb b/app/views/users/sessions/new.html.erb new file mode 100644 index 00000000..95087f24 --- /dev/null +++ b/app/views/users/sessions/new.html.erb @@ -0,0 +1,20 @@ +

Log in

+ +<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.input :email, + required: false, + autofocus: true, + input_html: { autocomplete: "email" } %> + <%= f.input :password, + required: false, + input_html: { autocomplete: "current-password" } %> + <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> +
+ +
+ <%= f.button :submit, "Log in" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/app/views/users/shared/_error_messages.html.erb b/app/views/users/shared/_error_messages.html.erb new file mode 100644 index 00000000..ba7ab887 --- /dev/null +++ b/app/views/users/shared/_error_messages.html.erb @@ -0,0 +1,15 @@ +<% if resource.errors.any? %> +
+

+ <%= I18n.t("errors.messages.not_saved", + count: resource.errors.count, + resource: resource.class.model_name.human.downcase) + %> +

+
    + <% resource.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+<% end %> diff --git a/app/views/users/shared/_links.html.erb b/app/views/users/shared/_links.html.erb new file mode 100644 index 00000000..084af701 --- /dev/null +++ b/app/views/users/shared/_links.html.erb @@ -0,0 +1,25 @@ +<%- if controller_name != 'sessions' %> + <%= link_to "Log in", new_session_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to "Sign up", new_registration_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> + <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %>
+ <% end %> +<% end %> diff --git a/app/views/users/unlocks/new.html.erb b/app/views/users/unlocks/new.html.erb new file mode 100644 index 00000000..225e85df --- /dev/null +++ b/app/views/users/unlocks/new.html.erb @@ -0,0 +1,19 @@ +

Resend unlock instructions

+ +<%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + <%= f.full_error :unlock_token %> + +
+ <%= f.input :email, + required: true, + autofocus: true, + input_html: { autocomplete: "email" } %> +
+ +
+ <%= f.button :submit, "Resend unlock instructions" %> +
+<% end %> + +<%= render "users/shared/links" %> diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9cd6498c..d48b0c76 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,9 +1,14 @@ +# frozen_string_literal: true + # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| # The secret key used by Devise. Devise uses this key to generate # random tokens. Changing this key will render invalid all existing # confirmation, reset password and unlock tokens in the database. + # Devise will use the `secret_key_base` as its `secret_key` + # by default. You can change it below and use your own secret key. + # config.secret_key = '613ee7927d2dd9f1a86c54decfccfd012e72637b48b8b485a6431f7f9ea44d9dd69b88a79895cacff6926efc88ae2c2ea44ce9e79500a1b433cd2169284e2ee8' config.secret_key = ENV["DEVISE_SECRET_KEY"] @@ -16,6 +21,9 @@ # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' + # Configure the parent class responsible to send e-mails. + # config.parent_mailer = 'ActionMailer::Base' + # ==> ORM configuration # Load and configure the ORM. Supports :active_record (default) and # :mongoid (bson_ext recommended) by default. Other ORMs may be @@ -30,7 +38,7 @@ # session. If you need permissions, you should implement that in a before filter. # You can also supply a hash where the value is a boolean determining whether # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [ :email ] + # config.authentication_keys = [:email] # Configure parameters from the request object used for authentication. Each entry # given should be a request method and it will automatically be passed to the @@ -42,12 +50,12 @@ # Configure which authentication keys should be case-insensitive. # These keys will be downcased upon creating or modifying a user and when used # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [ :email ] + config.case_insensitive_keys = [:email] # Configure which authentication keys should have whitespace stripped. # These keys will have whitespace before and after removed upon creating or # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [ :email ] + config.strip_whitespace_keys = [:email] # Tell if authentication through request.params is enabled. True by default. # It can be set to an array that will enable params authentication only for the @@ -62,7 +70,7 @@ # :database = Support basic authentication with authentication key + password # config.http_authenticatable = false - # If http headers should be returned for AJAX requests. True by default. + # If 401 status code should be returned for AJAX requests. True by default. # config.http_authenticatable_on_xhr = true # The realm used in Http Basic Authentication. 'Application' by default. @@ -77,7 +85,7 @@ # particular strategies by setting this option. # Notice that if you are skipping storage for all authentication paths, you # may want to disable generating routes to Devise's sessions controller by - # passing :skip => :sessions to `devise_for` in your config/routes.rb + # passing skip: :sessions to `devise_for` in your config/routes.rb config.skip_session_storage = [:http_auth] # By default, Devise cleans up the CSRF token on authentication to @@ -86,24 +94,41 @@ # from the server. You can disable this option at your own risk. # config.clean_up_csrf_token_on_authentication = true + # When false, Devise will not attempt to reload routes on eager load. + # This can reduce the time taken to boot the app but if your application + # requires the Devise mappings to be loaded during boot time the application + # won't boot properly. + # config.reload_routes = true + # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 10. If - # using other encryptors, it sets how many times you want the password re-encrypted. + # For bcrypt, this is the cost for hashing the password and defaults to 11. If + # using other algorithms, it sets how many times you want the password to be hashed. # # Limiting the stretches to just one in testing will increase the performance of # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use - # a value less than 10 in other environments. - config.stretches = Rails.env.test? ? 1 : 10 + # a value less than 10 in other environments. Note that, for bcrypt (the default + # algorithm), the cost increases exponentially with the number of stretches (e.g. + # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). + config.stretches = Rails.env.test? ? 1 : 11 + + # Set up a pepper to generate the hashed password. + # config.pepper = '9f1179e2dc6b352475dfa152e1d116c58b76b1b915589db71f8297f29af4b06cd09b7678294f3df943a51a7ed8739e698fdaa83472b7912fe61e28a542d66854' - # Setup a pepper to generate the encrypted password. - # config.pepper = '2b5fdc6d3c311d882d37d52414c61f479024c84cc0bd12b213cec674de7b113bcafe5d18aff37004b39ca712917191b7604d3af0a35e79101151fc09fa648b16' + # Send a notification to the original email when the user's email is changed. + # config.send_email_changed_notification = false + + # Send a notification email when the user's password is changed. + # config.send_password_change_notification = false # ==> Configuration for :confirmable # A period that the user is allowed to access the website even without - # confirming his account. For instance, if set to 2.days, the user will be - # able to access the website for two days without confirming his account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming his account. + # confirming their account. For instance, if set to 2.days, the user will be + # able to access the website for two days without confirming their account, + # access will be blocked just in the third day. + # You can also set it to nil, which will allow the user to access the website + # without confirming their account. + # Default is 0.days, meaning the user cannot access the website without + # confirming their account. # config.allow_unconfirmed_access_for = 2.days # A period that the user is allowed to confirm their account before their @@ -116,41 +141,41 @@ # If true, requires any email changes to be confirmed (exactly the same way as # initial account confirmation) to be applied. Requires additional unconfirmed_email - # db field (see migrations). Until confirmed new email is stored in - # unconfirmed email column, and copied to email column on successful confirmation. + # db field (see migrations). Until confirmed, new email is stored in + # unconfirmed_email column, and copied to email column on successful confirmation. config.reconfirmable = true # Defines which key will be used when confirming an account - # config.confirmation_keys = [ :email ] + # config.confirmation_keys = [:email] # ==> Configuration for :rememberable # The time the user will be remembered without asking for credentials again. # config.remember_for = 2.weeks + # Invalidates all the remember me tokens when the user signs out. + config.expire_all_remember_me_on_sign_out = true + # If true, extends the user's remember period when remembered via cookie. # config.extend_remember_period = false # Options to be passed to the created cookie. For instance, you can set - # :secure => true in order to force SSL only cookies. + # secure: true in order to force SSL only cookies. # config.rememberable_options = {} # ==> Configuration for :validatable - # Range for password length. Default is 8..128. + # Range for password length. config.password_length = 8..128 # Email regex used to validate email formats. It simply asserts that # one (and only one) @ exists in the given string. This is mainly # to give user feedback and not to assert the e-mail validity. - # config.email_regexp = /\A[^@]+@[^@]+\z/ + config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ # ==> Configuration for :timeoutable # The time you want to timeout the user session without activity. After this # time the user will be asked for credentials again. Default is 30 minutes. # config.timeout_in = 30.minutes - # If true, expires auth token on session timeout. - # config.expire_auth_token_on_timeout = false - # ==> Configuration for :lockable # Defines which strategy will be used to lock an account. # :failed_attempts = Locks an account after a number of failed attempts to sign in. @@ -158,7 +183,7 @@ # config.lock_strategy = :failed_attempts # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [ :email ] + # config.unlock_keys = [:email] # Defines which strategy will be used to unlock an account. # :email = Sends an unlock link to the user email @@ -175,24 +200,28 @@ # config.unlock_in = 1.hour # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = false + # config.last_attempt_warning = true # ==> Configuration for :recoverable # # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [ :email ] + # config.reset_password_keys = [:email] # Time interval you can reset your password with a reset password key. # Don't put a too small interval or your users won't have the time to # change their passwords. config.reset_password_within = 6.hours + # When set to false, does not sign a user in automatically after their password is + # reset. Defaults to true, so a user is signed in automatically after a reset. + # config.sign_in_after_reset_password = true + # ==> Configuration for :encryptable - # Allow you to use another encryption algorithm besides bcrypt (default). You can use - # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, - # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) - # and :restful_authentication_sha1 (then you should set stretches to 10, and copy - # REST_AUTH_SITE_KEY to pepper). + # Allow you to use another hashing or encryption algorithm besides bcrypt (default). + # You can use :sha1, :sha512 or algorithms from others authentication tools as + # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 + # for default behavior) and :restful_authentication_sha1 (then you should set + # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). # # Require the `devise-encryptable` gem when using anything other than bcrypt # config.encryptor = :sha512 @@ -228,7 +257,7 @@ # ==> OmniAuth # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. - # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' + # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or @@ -236,7 +265,7 @@ # # config.warden do |manager| # manager.intercept_401 = false - # manager.default_strategies(:scope => :user).unshift :some_external_strategy + # manager.default_strategies(scope: :user).unshift :some_external_strategy # end # ==> Mountable engine configurations @@ -249,7 +278,20 @@ # The router that invoked `devise_for`, in the example above, would be: # config.router_name = :my_engine # - # When using omniauth, Devise cannot automatically set Omniauth path, + # When using OmniAuth, Devise cannot automatically set OmniAuth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' + + # ==> Turbolinks configuration + # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: + # + # ActiveSupport.on_load(:devise_failure_app) do + # include Turbolinks::Controller + # end + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true end diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml new file mode 100644 index 00000000..55617bdf --- /dev/null +++ b/config/locales/devise.en.yml @@ -0,0 +1,65 @@ +# Additional translations at https://github.com/plataformatec/devise/wiki/I18n + +en: + devise: + confirmations: + confirmed: "Your email address has been successfully confirmed." + send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." + failure: + already_authenticated: "You are already signed in." + inactive: "Your account is not activated yet." + invalid: "Invalid %{authentication_keys} or password." + locked: "Your account is locked." + last_attempt: "You have one more attempt before your account is locked." + not_found_in_database: "Invalid %{authentication_keys} or password." + timeout: "Your session expired. Please sign in again to continue." + unauthenticated: "You need to sign in or sign up before continuing." + unconfirmed: "You have to confirm your email address before continuing." + mailer: + confirmation_instructions: + subject: "Confirmation instructions" + reset_password_instructions: + subject: "Reset password instructions" + unlock_instructions: + subject: "Unlock instructions" + email_changed: + subject: "Email Changed" + password_change: + subject: "Password Changed" + omniauth_callbacks: + failure: "Could not authenticate you from %{kind} because \"%{reason}\"." + success: "Successfully authenticated from %{kind} account." + passwords: + no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." + send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." + updated: "Your password has been changed successfully. You are now signed in." + updated_not_active: "Your password has been changed successfully." + registrations: + destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." + signed_up: "Welcome! You have signed up successfully." + signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." + signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." + update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." + updated: "Your account has been updated successfully." + updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again" + sessions: + signed_in: "Signed in successfully." + signed_out: "Signed out successfully." + already_signed_out: "Signed out successfully." + unlocks: + send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." + send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." + unlocked: "Your account has been unlocked successfully. Please sign in to continue." + errors: + messages: + already_confirmed: "was already confirmed, please try signing in" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" + expired: "has expired, please request a new one" + not_found: "not found" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/config/routes.rb b/config/routes.rb index 4710402b..712fb9ed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,20 +1,22 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - resources :bulk_uploads, only: [:new, :create, :show] + devise_for :users, controllers: { + sessions: 'users/sessions' + } devise_for :admin_users, ActiveAdmin::Devise.config - ActiveAdmin.routes(self) - resources :restrooms, except: [:edit, :destroy] + ActiveAdmin.routes(self) + resources :restrooms, except: [:edit, :destroy] - namespace :api do - resources :docs, only: [:index] - end + namespace :api do + resources :docs, only: [:index] + end - mount API::Base => '/api' + mount API::Base => '/api' - get '/contact', to: 'contacts#new' - get "/*id" => 'pages#show', as: :page, format: false - root 'pages#index' + get '/contact', to: 'contacts#new' + get "/*id" => 'pages#show', as: :page, format: false + root 'pages#index' - resources "contacts", only: [:new, :create] + resources "contacts", only: [:new, :create] end diff --git a/db/migrate/20190330233323_devise_create_users.rb b/db/migrate/20190330233323_devise_create_users.rb new file mode 100644 index 00000000..e4fe133a --- /dev/null +++ b/db/migrate/20190330233323_devise_create_users.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class DeviseCreateUsers < ActiveRecord::Migration[5.2] + def change + create_table :users do |t| + ## Database authenticatable + t.string :email, null: false, default: "" + t.string :encrypted_password, null: false, default: "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + # t.integer :sign_in_count, default: 0, null: false + # t.datetime :current_sign_in_at + # t.datetime :last_sign_in_at + # t.inet :current_sign_in_ip + # t.inet :last_sign_in_ip + + ## Confirmable + # t.string :confirmation_token + # t.datetime :confirmed_at + # t.datetime :confirmation_sent_at + # t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + + t.timestamps null: false + end + + add_index :users, :email, unique: true + add_index :users, :reset_password_token, unique: true + # add_index :users, :confirmation_token, unique: true + # add_index :users, :unlock_token, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 156231fc..5c75774f 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.define(version: 2019_03_30_225402) do +ActiveRecord::Schema.define(version: 2019_03_30_233323) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -109,5 +109,17 @@ t.boolean "approved", default: true end + create_table "users", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + end + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" end diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 00000000..628434c3 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :user do + + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 00000000..47a31bb4 --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe User, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 9c524ff87651dbc11f68d9dc1db17034f7db45e5 Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 10:17:56 -0700 Subject: [PATCH 13/59] give access to devise users controller --- .../users/confirmations_controller.rb | 30 +++++++++ .../users/omniauth_callbacks_controller.rb | 30 +++++++++ app/controllers/users/passwords_controller.rb | 34 ++++++++++ .../users/registrations_controller.rb | 62 +++++++++++++++++++ app/controllers/users/sessions_controller.rb | 27 ++++++++ app/controllers/users/unlocks_controller.rb | 30 +++++++++ 6 files changed, 213 insertions(+) create mode 100644 app/controllers/users/confirmations_controller.rb create mode 100644 app/controllers/users/omniauth_callbacks_controller.rb create mode 100644 app/controllers/users/passwords_controller.rb create mode 100644 app/controllers/users/registrations_controller.rb create mode 100644 app/controllers/users/sessions_controller.rb create mode 100644 app/controllers/users/unlocks_controller.rb diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb new file mode 100644 index 00000000..fa535c0a --- /dev/null +++ b/app/controllers/users/confirmations_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::ConfirmationsController < Devise::ConfirmationsController + # GET /resource/confirmation/new + # def new + # super + # end + + # POST /resource/confirmation + # def create + # super + # end + + # GET /resource/confirmation?confirmation_token=abcdef + # def show + # super + # end + + # protected + + # The path used after resending confirmation instructions. + # def after_resending_confirmation_instructions_path_for(resource_name) + # super(resource_name) + # end + + # The path used after confirmation. + # def after_confirmation_path_for(resource_name, resource) + # super(resource_name, resource) + # end +end diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb new file mode 100644 index 00000000..565c6ed2 --- /dev/null +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController + # You should configure your model like this: + # devise :omniauthable, omniauth_providers: [:twitter] + + # You should also create an action method in this controller like this: + # def twitter + # end + + # More info at: + # https://github.com/plataformatec/devise#omniauth + + # GET|POST /resource/auth/twitter + # def passthru + # super + # end + + # GET|POST /users/auth/twitter/callback + # def failure + # super + # end + + # protected + + # The path used when OmniAuth fails + # def after_omniauth_failure_path_for(scope) + # super(scope) + # end +end diff --git a/app/controllers/users/passwords_controller.rb b/app/controllers/users/passwords_controller.rb new file mode 100644 index 00000000..259dbb08 --- /dev/null +++ b/app/controllers/users/passwords_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class Users::PasswordsController < Devise::PasswordsController + # GET /resource/password/new + # def new + # super + # end + + # POST /resource/password + # def create + # super + # end + + # GET /resource/password/edit?reset_password_token=abcdef + # def edit + # super + # end + + # PUT /resource/password + # def update + # super + # end + + # protected + + # def after_resetting_password_path_for(resource) + # super(resource) + # end + + # The path used after sending reset password instructions + # def after_sending_reset_password_instructions_path_for(resource_name) + # super(resource_name) + # end +end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb new file mode 100644 index 00000000..b9e664fe --- /dev/null +++ b/app/controllers/users/registrations_controller.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +class Users::RegistrationsController < Devise::RegistrationsController + # before_action :configure_sign_up_params, only: [:create] + # before_action :configure_account_update_params, only: [:update] + + # GET /resource/sign_up + # def new + # super + # end + + # POST /resource + # def create + # super + # end + + # GET /resource/edit + # def edit + # super + # end + + # PUT /resource + # def update + # super + # end + + # DELETE /resource + # def destroy + # super + # end + + # GET /resource/cancel + # Forces the session data which is usually expired after sign + # in to be expired now. This is useful if the user wants to + # cancel oauth signing in/up in the middle of the process, + # removing all OAuth session data. + # def cancel + # super + # end + + # protected + + # If you have extra params to permit, append them to the sanitizer. + # def configure_sign_up_params + # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) + # end + + # If you have extra params to permit, append them to the sanitizer. + # def configure_account_update_params + # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) + # end + + # The path used after sign up. + # def after_sign_up_path_for(resource) + # super(resource) + # end + + # The path used after sign up for inactive accounts. + # def after_inactive_sign_up_path_for(resource) + # super(resource) + # end +end diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb new file mode 100644 index 00000000..a0f9b48e --- /dev/null +++ b/app/controllers/users/sessions_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class Users::SessionsController < Devise::SessionsController + # before_action :configure_sign_in_params, only: [:create] + + # GET /resource/sign_in + # def new + # super + # end + + # POST /resource/sign_in + # def create + # super + # end + + # DELETE /resource/sign_out + # def destroy + # super + # end + + # protected + + # If you have extra params to permit, append them to the sanitizer. + # def configure_sign_in_params + # devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute]) + # end +end diff --git a/app/controllers/users/unlocks_controller.rb b/app/controllers/users/unlocks_controller.rb new file mode 100644 index 00000000..2c410dc0 --- /dev/null +++ b/app/controllers/users/unlocks_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::UnlocksController < Devise::UnlocksController + # GET /resource/unlock/new + # def new + # super + # end + + # POST /resource/unlock + # def create + # super + # end + + # GET /resource/unlock?unlock_token=abcdef + # def show + # super + # end + + # protected + + # The path used after sending unlock password instructions + # def after_sending_unlock_instructions_path_for(resource) + # super(resource) + # end + + # The path used after unlocking the resource + # def after_unlock_path_for(resource) + # super(resource) + # end +end From 7e6501308af350e351aa549e711d23b93d9df4d6 Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 10:23:01 -0700 Subject: [PATCH 14/59] reformat routes --- config/routes.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 712fb9ed..78122e7e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,18 +5,18 @@ } devise_for :admin_users, ActiveAdmin::Devise.config - ActiveAdmin.routes(self) - resources :restrooms, except: [:edit, :destroy] + ActiveAdmin.routes(self) + resources :restrooms, except: [:edit, :destroy] - namespace :api do - resources :docs, only: [:index] - end + namespace :api do + resources :docs, only: [:index] + end - mount API::Base => '/api' + mount API::Base => '/api' - get '/contact', to: 'contacts#new' - get "/*id" => 'pages#show', as: :page, format: false - root 'pages#index' + get '/contact', to: 'contacts#new' + get "/*id" => 'pages#show', as: :page, format: false + root 'pages#index' - resources "contacts", only: [:new, :create] + resources "contacts", only: [:new, :create] end From 92a5025805c3fa30784830ca480a7ca7cbda1cfc Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sun, 31 Mar 2019 10:27:58 -0700 Subject: [PATCH 15/59] Stand up container for job processor --- app/jobs/bulk_import_job.rb | 5 +++-- docker-compose.yml | 8 ++++++++ setup/jobsEntry | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100755 setup/jobsEntry diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index 43db1096..1720e485 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -1,7 +1,8 @@ class BulkImportJob < ApplicationJob queue_as :default - def perform(*args) - # Do something later + def perform(bulk_job) + Rails.logger.info bulk_job.class + Rails.logger.info bulk_job end end diff --git a/docker-compose.yml b/docker-compose.yml index bef98d3d..b319311d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,3 +13,11 @@ services: - "3000:3000" depends_on: - db + jobber: + build: . + entrypoint: [setup/jobsEntry] + command: bundle exec rake jobs:work + volumes: + - .:/refugerestrooms + depends_on: + - db diff --git a/setup/jobsEntry b/setup/jobsEntry new file mode 100755 index 00000000..a6453106 --- /dev/null +++ b/setup/jobsEntry @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +exec "$@" From fd2ef216aa600e2f06af86340b0c6338aadf02ee Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 10:48:08 -0700 Subject: [PATCH 16/59] add Approved column to devise-generated user table Co-authored-by: Chelsea Troy --- db/migrate/20190331174147_add_approval_to_users.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190331174147_add_approval_to_users.rb diff --git a/db/migrate/20190331174147_add_approval_to_users.rb b/db/migrate/20190331174147_add_approval_to_users.rb new file mode 100644 index 00000000..a1ecb9d1 --- /dev/null +++ b/db/migrate/20190331174147_add_approval_to_users.rb @@ -0,0 +1,5 @@ +class AddApprovalToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :approved, :boolean, :default => false + end +end diff --git a/db/schema.rb b/db/schema.rb index 5c75774f..2b167298 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.define(version: 2019_03_30_233323) do +ActiveRecord::Schema.define(version: 2019_03_31_174147) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -117,6 +117,7 @@ t.datetime "remember_created_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "approved", default: false t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end From 5b012b90a76e173ad0403b1264e67b4e47cc144a Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 11:48:06 -0700 Subject: [PATCH 17/59] readd routes for bulk upload --- config/routes.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 78122e7e..853611b5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,11 +3,12 @@ devise_for :users, controllers: { sessions: 'users/sessions' } - devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) resources :restrooms, except: [:edit, :destroy] + resources :bulk_uploads, only: [:new, :create, :show] + namespace :api do resources :docs, only: [:index] end From 09893e087a76b42dbbae998cef0d3ae2288714b2 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 12:01:27 -0700 Subject: [PATCH 18/59] Add user authorization to bulk_uploads_controller --- app/controllers/bulk_uploads_controller.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index 08373b18..40dbcd67 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -1,4 +1,6 @@ class BulkUploadsController < ApplicationController + before_action :authenticate_approved_user!, only: [:create] + def new @bulk_upload = BulkUpload.new end @@ -15,8 +17,16 @@ def create def show end + private + def authenticate_approved_user! + unless user_signed_in? + redirect_to new_user_session_path + return false + end + end + def bulk_upload_params params.require(:bulk_upload).permit(:file) end From cd1d287be66b9afc573f1d51a9d137cf900f912a Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 12:31:44 -0700 Subject: [PATCH 19/59] Add association between bulk_upload and user --- app/models/bulk_upload.rb | 1 + app/models/user.rb | 2 ++ app/views/bulk_uploads/new.html.haml | 7 ++++--- db/migrate/20190331182012_add_user_id_to_bulk_upload.rb | 5 +++++ db/schema.rb | 4 +++- 5 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20190331182012_add_user_id_to_bulk_upload.rb diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index 371c6328..4bf3e86a 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -1,3 +1,4 @@ class BulkUpload < ApplicationRecord has_one_attached :file + belongs_to :user, required: true end diff --git a/app/models/user.rb b/app/models/user.rb index 47567994..49fdd470 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,4 +3,6 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable + + has_many :bulk_uploads end diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index 74709fcb..6df0740d 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -1,5 +1,6 @@ %h3= t('restroom.add_bulk') -= simple_form_for @bulk_upload do |f| - = f.file_field :file - = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" +- if user_signed_in? + = simple_form_for @bulk_upload do |f| + = f.file_field :file + = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" diff --git a/db/migrate/20190331182012_add_user_id_to_bulk_upload.rb b/db/migrate/20190331182012_add_user_id_to_bulk_upload.rb new file mode 100644 index 00000000..2c3457fd --- /dev/null +++ b/db/migrate/20190331182012_add_user_id_to_bulk_upload.rb @@ -0,0 +1,5 @@ +class AddUserIdToBulkUpload < ActiveRecord::Migration[5.2] + def change + add_reference :bulk_uploads, :user + end +end diff --git a/db/schema.rb b/db/schema.rb index 2b167298..0a4a3113 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.define(version: 2019_03_31_174147) do +ActiveRecord::Schema.define(version: 2019_03_31_182012) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -71,6 +71,8 @@ create_table "bulk_uploads", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "user_id" + t.index ["user_id"], name: "index_bulk_uploads_on_user_id" end create_table "delayed_jobs", force: :cascade do |t| From cbf7091ed7a040bdedeb3820d18d28b449de7278 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 12:31:55 -0700 Subject: [PATCH 20/59] Add signout link --- app/views/layouts/_footer.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index 7bf1920e..7bdc3fd9 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -1,5 +1,6 @@ %footer .footer + %h4= link_to "Signout", destroy_user_session_path, method: :delete %a.iconLink{:href => "https://github.com/RefugeRestrooms/refugerestrooms", :aria => { :label => t('.aria-labels.github')}} %i.icon.fa.fa-github-square.fa-3x %a.iconLink{:href => "https://twitter.com/refugerestrooms", :aria => { :label => t('.aria-labels.twitter')}} From a5cea8fa1a14ea2f5f51678cf6538d6587020242 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 13:57:02 -0700 Subject: [PATCH 21/59] Fix route for bulk_uploads --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index 78122e7e..fdc1c1a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + resources :bulk_uploads, only: [:new, :create, :show] devise_for :users, controllers: { sessions: 'users/sessions' } From 7450224da8c6b1fb4c22fa575c2b561a3b7de2c0 Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 13:57:54 -0700 Subject: [PATCH 22/59] formatting and attempt at mailer --- app/admin/restroom.rb | 5 ++--- .../users/registrations_controller.rb | 5 ++++- config/initializers/setup_mail.rb | 16 ++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/admin/restroom.rb b/app/admin/restroom.rb index 150bd599..de06e163 100644 --- a/app/admin/restroom.rb +++ b/app/admin/restroom.rb @@ -1,5 +1,4 @@ ActiveAdmin.register Restroom do - -permit_params :name, :street, :city, :state, :accessible, :changing_table, :unisex, :directions, - :comment, :latitude, :longitude, :country, :edit_id, :approved + permit_params :name, :street, :city, :state, :accessible, :changing_table, :unisex, :directions, + :comment, :latitude, :longitude, :country, :edit_id, :approved end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index b9e664fe..39234f88 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -11,7 +11,10 @@ class Users::RegistrationsController < Devise::RegistrationsController # POST /resource # def create - # super + # super do |resource| + # puts "**********************************************************" + # UserMailer.approve_new_user_email(resource).deliver_now + # end # end # GET /resource/edit diff --git a/config/initializers/setup_mail.rb b/config/initializers/setup_mail.rb index 5980bd8e..ce550d52 100644 --- a/config/initializers/setup_mail.rb +++ b/config/initializers/setup_mail.rb @@ -1,10 +1,10 @@ ActionMailer::Base.delivery_method = :smtp ActionMailer::Base.smtp_settings = { -:address => "smtp.gmail.com", -:port => 587, -:domain => "whatever.org", -:user_name => ENV['EMAIL'], -:password => ENV['EMAIL_PASSWORD'], -:authentication => "plain", -:enable_starttls_auto => true -} \ No newline at end of file + :address => "smtp.gmail.com", + :port => 587, + :domain => "whatever.org", + :user_name => ENV['EMAIL'], + :password => ENV['EMAIL_PASSWORD'], + :authentication => "plain", + :enable_starttls_auto => true +} From 594a428bf689247c791a3634473db8e452f59b19 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 14:03:21 -0700 Subject: [PATCH 23/59] Add link to signin on bulk_uploads view when not signed in --- app/views/bulk_uploads/new.html.haml | 4 ++++ config/locales/en/restroom.en.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index 6df0740d..8cce1df2 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -4,3 +4,7 @@ = simple_form_for @bulk_upload do |f| = f.file_field :file = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" +- else + %p + = t('restroom.signin_for_bulk_upload') + = link_to "here", new_user_registration_path \ No newline at end of file diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index 74c665a8..586b5a73 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -16,6 +16,7 @@ en: restroom: add_new: 'Submit a restroom to our database' add_bulk: 'Upload CSV file' + signin_for_bulk_upload: 'Want to add a CSV? Signin' csv_submit: 'Save CSV' preview: 'Preview' required: '* marks required field' From 53f30338f1b37f54f1a7fb7d66043b7e039bc7bd Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 14:39:52 -0700 Subject: [PATCH 24/59] put in aws configs for active storage --- config/environments/production.rb | 4 ++-- config/storage.yml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 9baf7edc..e5e2e636 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -21,7 +21,7 @@ # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - + # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass @@ -39,7 +39,7 @@ # 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 = :aws # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil diff --git a/config/storage.yml b/config/storage.yml index d32f76e8..deee25cb 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -7,12 +7,12 @@ local: 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 +amazon: + service: S3 + access_key_id: <%= ENV['AWS_ACCESS_KEY_ID']%> + secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> + region: us-east-1 + bucket: refugerestrooms-uploads # Remember not to checkin your GCS keyfile to a repository # google: From f6068437cd8225611aae5135cb949dd0bc06d2d2 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 14:42:05 -0700 Subject: [PATCH 25/59] fix routes --- config/routes.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index d55d2ab0..d93085b3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,15 +1,15 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html resources :bulk_uploads, only: [:new, :create, :show] + devise_for :users, controllers: { sessions: 'users/sessions' } + devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) resources :restrooms, except: [:edit, :destroy] - resources :bulk_uploads, only: [:new, :create, :show] - namespace :api do resources :docs, only: [:index] end From e28030d6fc209338525676ad028806b0b2e9a965 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 14:45:04 -0700 Subject: [PATCH 26/59] enforce config inheritance --- app.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app.json b/app.json index 9b85f921..bb8e0ac2 100644 --- a/app.json +++ b/app.json @@ -8,6 +8,12 @@ "AKISMET_KEY": { "required": true }, + "AWS_ACCESS_KEY_ID": { + "required": true + }, + "AWS_SECRET_ACCESS_KEY": { + "required": true + }, "BUGSNAG_API_TOKEN": { "required": true }, From 2a2d3b7f90d1166193e18c373120105f4ede03c7 Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 14:45:06 -0700 Subject: [PATCH 27/59] Adjust devise routes to get sign_in to access our mailer --- app/admin/user.rb | 3 +++ app/controllers/users/registrations_controller.rb | 11 +++++------ app/mailers/application_mailer.rb | 4 ++++ app/mailers/user_mailer.rb | 6 ++++++ app/views/layouts/mailer.html.erb | 13 +++++++++++++ app/views/layouts/mailer.text.erb | 1 + .../user_mailer/approve_new_user_email.html.erb | 6 ++++++ .../user_mailer/approve_new_user_email.text.erb | 4 ++++ app/views/users/registrations/new.html.erb | 2 +- config/routes.rb | 3 ++- spec/mailers/previews/user_mailer_preview.rb | 4 ++++ spec/mailers/user_mailer_spec.rb | 5 +++++ 12 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 app/admin/user.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/mailers/user_mailer.rb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100644 app/views/user_mailer/approve_new_user_email.html.erb create mode 100644 app/views/user_mailer/approve_new_user_email.text.erb create mode 100644 spec/mailers/previews/user_mailer_preview.rb create mode 100644 spec/mailers/user_mailer_spec.rb diff --git a/app/admin/user.rb b/app/admin/user.rb new file mode 100644 index 00000000..8c14974f --- /dev/null +++ b/app/admin/user.rb @@ -0,0 +1,3 @@ +ActiveAdmin.register User do + permit_params :email, :approved +end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index 39234f88..58db3e35 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -10,12 +10,11 @@ class Users::RegistrationsController < Devise::RegistrationsController # end # POST /resource - # def create - # super do |resource| - # puts "**********************************************************" - # UserMailer.approve_new_user_email(resource).deliver_now - # end - # end + def create + puts "**********************************************************" + super + UserMailer.approve_new_user_email(@user).deliver_now + end # GET /resource/edit # def edit diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 00000000..5ee6e719 --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'refugerestrooms@gmail.com' + layout 'mailer' +end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb new file mode 100644 index 00000000..f5bae081 --- /dev/null +++ b/app/mailers/user_mailer.rb @@ -0,0 +1,6 @@ +class UserMailer < ApplicationMailer + def approve_new_user_email(user) + @user = user + mail(to: 'refugerestrooms@gmail.com', subject: 'New user requires approval') + end +end diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 00000000..cbd34d2e --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 00000000..37f0bddb --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb new file mode 100644 index 00000000..8e4ca0d6 --- /dev/null +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -0,0 +1,6 @@ +

A new user requires approval

+

+ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
+ Please check this person out and approve or reject them.
+ Here is an ActiveAdmin link: http://www.refugerestrooms.org/admin/users/<%= @user.id %> +

diff --git a/app/views/user_mailer/approve_new_user_email.text.erb b/app/views/user_mailer/approve_new_user_email.text.erb new file mode 100644 index 00000000..fb673035 --- /dev/null +++ b/app/views/user_mailer/approve_new_user_email.text.erb @@ -0,0 +1,4 @@ +A new user requires approval + +The user with email: <%= @user.email %> would like to join Refuge Restrooms. +Please check this person out and approve or reject them. diff --git a/app/views/users/registrations/new.html.erb b/app/views/users/registrations/new.html.erb index 58719bea..fa5bd02b 100644 --- a/app/views/users/registrations/new.html.erb +++ b/app/views/users/registrations/new.html.erb @@ -1,6 +1,6 @@

Sign up

-<%= simple_form_for(resource, as: resource_name, url: new_user_registration_path(resource_name)) do |f| %> +<%= simple_form_for(resource, as: resource_name, url: user_registration_path) do |f| %> <%= f.error_notification %>
diff --git a/config/routes.rb b/config/routes.rb index fdc1c1a9..d5bca517 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,7 +2,8 @@ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html resources :bulk_uploads, only: [:new, :create, :show] devise_for :users, controllers: { - sessions: 'users/sessions' + sessions: 'users/sessions', + registrations: 'users/registrations' } devise_for :admin_users, ActiveAdmin::Devise.config diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb new file mode 100644 index 00000000..957e12b6 --- /dev/null +++ b/spec/mailers/previews/user_mailer_preview.rb @@ -0,0 +1,4 @@ +# Preview all emails at http://localhost:3000/rails/mailers/user_mailer +class UserMailerPreview < ActionMailer::Preview + +end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb new file mode 100644 index 00000000..4a78b857 --- /dev/null +++ b/spec/mailers/user_mailer_spec.rb @@ -0,0 +1,5 @@ +require "rails_helper" + +RSpec.describe UserMailer, type: :mailer do + pending "add some examples to (or delete) #{__FILE__}" +end From ba2ab814e2b1f50328ab37db3e46740e46649f95 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 14:48:27 -0700 Subject: [PATCH 28/59] use amazon instead of aws --- config/environments/production.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index e5e2e636..669bcafd 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -39,7 +39,7 @@ # 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 = :aws + config.active_storage.service = :amazon # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil From ad48e203c5a6fd5e3e7522bccceab7fdcb497758 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 15:00:10 -0700 Subject: [PATCH 29/59] add aws gem --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index f299a770..43365ac1 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ ruby '2.5.3' gem 'rails', '5.2.2.1' gem 'activeadmin', '~> 1.4.1' +gem "aws-sdk-s3", '~> 1.36.0', require: false gem 'bootsnap', require: false gem 'bootstrap-sass', '>= 3.4.1' gem 'bugsnag' From dd708d23a9655b33f512a71f60124dfab8b31041 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Sun, 31 Mar 2019 15:06:16 -0700 Subject: [PATCH 30/59] update lockfile --- Gemfile.lock | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Gemfile.lock b/Gemfile.lock index d1179e92..1469f0c5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -61,6 +61,22 @@ GEM arel (9.0.0) autoprefixer-rails (9.5.0) execjs + aws-eventstream (1.0.2) + aws-partitions (1.148.0) + aws-sdk-core (3.48.3) + aws-eventstream (~> 1.0, >= 1.0.2) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-kms (1.16.0) + aws-sdk-core (~> 3, >= 3.48.2) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.36.0) + aws-sdk-core (~> 3, >= 3.48.2) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.1.0) + aws-eventstream (~> 1.0, >= 1.0.2) axiom-types (0.1.1) descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) @@ -180,6 +196,7 @@ GEM jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) + jmespath (1.4.0) jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -381,6 +398,7 @@ PLATFORMS DEPENDENCIES activeadmin (~> 1.4.1) + aws-sdk-s3 (~> 1.36.0) better_errors (~> 2.4.0) binding_of_caller bootsnap From 190026d85c6faa55291e0f40d9ae7621be26d78d Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sun, 31 Mar 2019 15:06:42 -0700 Subject: [PATCH 31/59] First pass at bulk import and geocoding job --- .env | 2 -- .env.example | 1 + app/controllers/bulk_uploads_controller.rb | 7 +++--- app/jobs/bulk_import_job.rb | 25 +++++++++++++++++++--- spec/fixtures/restrooms.csv | 22 +++++++++++++++++++ 5 files changed, 49 insertions(+), 8 deletions(-) delete mode 100644 .env create mode 100644 .env.example create mode 100644 spec/fixtures/restrooms.csv diff --git a/.env b/.env deleted file mode 100644 index b863316b..00000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -export DEVISE_SECRET_KEY=3f4915489bd10fdbacb4f22dbf772a4be6e2d2d1616a1af7913f0f6645784ddffd6a71ab9f69a99ed7941f16d3092e1872bc4bc9add5a0615c630c90f94fc032 -export RAILS_SECRET_KEY=4944cf251e3dbf309ed71ebcd8990a1479d793011cd4011761e3fbea9ecc59edefd0cb49a0ed9b5c0261ab0dda841962bb7dd28fd3f99579bfa2beec26329961 diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..5e9a5405 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +export GOOGLE_MAPS_API_KEY=AIzaSyBXcCrqzMlm-ZmtNQve7AuipNdE4vySUF0 diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index 40dbcd67..4b16de6b 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -7,18 +7,19 @@ def new def create @bulk_upload = BulkUpload.new(bulk_upload_params) + @bulk_upload.user = current_user if @bulk_upload.save redirect_to bulk_upload_path(@bulk_upload) else + Rails.logger.error "Errors saving bulk_upload:" + @bulk_upload.errors.each { |field, message| Rails.logger.error "Field: #{field}, Message: #{message}" } render action: :new end end def show - end - private def authenticate_approved_user! unless user_signed_in? @@ -30,4 +31,4 @@ def authenticate_approved_user! def bulk_upload_params params.require(:bulk_upload).permit(:file) end -end \ No newline at end of file +end diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index 1720e485..6e47617a 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -1,8 +1,27 @@ +require 'csv' +require 'geocoder' + class BulkImportJob < ApplicationJob queue_as :default - def perform(bulk_job) - Rails.logger.info bulk_job.class - Rails.logger.info bulk_job + def perform(bulk_upload) + contents = bulk_upload.file.download + Rails.logger.info Geocoder.config + + CSV.parse(contents, headers: true) do |row| + values = row.to_hash.slice "name", "street", "city", "state", "country" + rr = Restroom.new values + if rr.valid? + if rr.latitude && rr.longitude + rr.save + else + # TODO: add row_error + Rails.logger.warn "Unable to geocode data: #{values}" + end + else + # TODO: also add row_error + Rails.logger.warn "Unable to validate data: #{values}" + end + end end end diff --git a/spec/fixtures/restrooms.csv b/spec/fixtures/restrooms.csv new file mode 100644 index 00000000..c54320ee --- /dev/null +++ b/spec/fixtures/restrooms.csv @@ -0,0 +1,22 @@ +id,name,street,city,state,x,y,directions,comment,lat,long,created,updated,z,w,country,a,b,c +1,Mission Creek Cafe,968 Valencia Street,San Francisco,CA,false,false,Head straight back. behind a divider.,no key,37.757358,-122.42133,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +2,Rainbow Grocery Co-op,1745 Folsom St,San Francisco,CA,true,false,"behind customer server, near the parking garage","need a key --- on cust service desk. sometimes they're both taken, wait by the comment board",37.769009,-122.415649,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +3,Beanery,1307 9th Ave,San Francisco,CA,true,false,"in back, behind the counter",,37.76375,-122.466456,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +4,Coffee To The People,1206 Masonic St,San Francisco,CA,true,false,towards the rear of the coffee shop.,usually clean,37.770064,-122.445174,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +5,Cafe Roma,526 Columbus Ave,San Francisco,CA,true,false,down a steep flight of stairs!,"kinda sketch, but hey, it's a place to pee in north beach...",37.79986,-122.409267,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +6,Maxfield's House of Caffine,398 Dolores St,san francisco,ca,true,false,in back to the left,no key,37.76314,-122.426473,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +7,Cafe Espresso,462 Powell,san francisco,CA,true,false,,up a steep hill,37.788854,-122.408345,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +8,Church Street Cafe,262 Church St,San Francisco,CA,true,false,in the back,Need to get a key,37.766657,-122.428856,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +9,Muddy Water's,1308 Valencia,San Francisco,CA,true,false,,,37.751843,-122.420841,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +10,Philz Coffee,3901 18th St,SAN FRANCISCO,CA,true,false,"to the right of the counter, in back",,37.761047,-122.430769,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +11,Bang San Thai Restuarant,791 Ofarrell St,San Francisco,CA,true,true,in back to the left,two single stall gendered. different owners from mekong (closed in 2008) but still a nice place,37.785067,-122.417648,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +12,New College,50 Fell St,SAN FRANCISCO,CA,true,false,,,37.776615,-122.418718,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +13,Rocking Java,1821 Haight St,SAN FRANCISCO,CA,true,false,,cool walls,37.76921,-122.452309,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +14,Pottery Barn,2390 Market Street,SAN FRANCISCO,CA,true,true,"Second floor, in the back.","You may have to walk around and pretend that you're looking at stuff to use the restrooms. There are 2 stalls (gendered) and they both lock. It's in a corner, so no one will really see which stall anyone goes into.",37.762896,-122.435026,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +15,Sparky's Diner,242 Church St,SAN FRANCISCO,CA,false,true,"in the back, down some steps","two single stalls. gender binary not rigidly enforced, people of a variety of genders openly use either.",37.766879,-122.429028,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +16,Muddy Water's Coffee,521 Valencia St,SAN FRANCISCO,CA,true,false,"in the back, you need to be buzzed in",,37.764496,-122.421674,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +17,GLBT Historical Society,657 Mission Street #300,SAN FRANCISCO,CA,true,false,"3rd Floor, has elevator. Open Tues-Sat, 1-5 pm.",Also worth a visit for their collection of GLBT historical material!,37.787017,-122.400826,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +18,El Rio,3158 Mission St,SAN FRANCISCO,CA,true,false,Back right of main bar room.,"Restrooms are labeled based on hardware available: urinals in one, toilets in the other. Not labeled by gender.",37.746667,-122.419385,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +19,LGBT Community Center,1800 Market St.,SAN FRANCISCO,CA,true,false,"Gender-free restroom on the main floor near the elevators, and also in the Three Dollar Bill Cafe.",,37.771704,-122.423845,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +20,maggie mudd ice cream,903 Cortland,SAN FRANCISCO,CA,true,false,in back by the newspapers!,"amazing vegan ice cream! genderfree, locking, accessible, changing station.",37.739067,-122.413768,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +21,Dolores Park Cafe,501 Dolores,SAN FRANCISCO,CA,true,false,in the back!,,37.761278,-122.425808,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true From a0d126bfa67e6b01b331211404e5a227c707a241 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 15:10:40 -0700 Subject: [PATCH 32/59] Conditionally display bulk_upload --- app/controllers/bulk_uploads_controller.rb | 1 + app/views/bulk_uploads/new.html.haml | 7 +++++-- config/locales/en/restroom.en.yml | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index 40dbcd67..dad0ec6e 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -3,6 +3,7 @@ class BulkUploadsController < ApplicationController def new @bulk_upload = BulkUpload.new + @user = current_user end def create diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index 8cce1df2..08ea690b 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -1,10 +1,13 @@ %h3= t('restroom.add_bulk') -- if user_signed_in? +- case +- when user_signed_in? && @user.approved? = simple_form_for @bulk_upload do |f| = f.file_field :file = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" +- when user_signed_in? + %p= t('restroom.add_bulk_request_pending') - else %p = t('restroom.signin_for_bulk_upload') - = link_to "here", new_user_registration_path \ No newline at end of file + = link_to "here.", new_user_registration_path \ No newline at end of file diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index 586b5a73..ecd01d1c 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -16,7 +16,8 @@ en: restroom: add_new: 'Submit a restroom to our database' add_bulk: 'Upload CSV file' - signin_for_bulk_upload: 'Want to add a CSV? Signin' + add_bulk_request_pending: 'You have successfully signed up, but you have not been approved to upload restroom CSVs yet. Your request is awaiting approval by the admins. Thank you for your patience and please check back later.' + signin_for_bulk_upload: 'Want to add a CSV? Only approved users may upload CSVs. When you sign up, an email will be sent to the admins to approve you. Please contact the admins if you have not recieved a response within a few days. Signup' csv_submit: 'Save CSV' preview: 'Preview' required: '* marks required field' From f6aa75019dd0e9afdfdb9babdcdca94625bf40d3 Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 15:14:27 -0700 Subject: [PATCH 33/59] Add messages to homepage to inform user of sign in status --- app/views/pages/index.html.haml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/pages/index.html.haml b/app/views/pages/index.html.haml index 0d3b6b7f..b249118c 100644 --- a/app/views/pages/index.html.haml +++ b/app/views/pages/index.html.haml @@ -1,3 +1,7 @@ +- flash.each do |key, value| + %div{class: "alert alert-#{key}"} + = value + .splash-content .row .col-xs-12.col-sm-8.col-sm-offset-2 From 898689e2402fd0bd56b90222cbfaad8f65cc3a75 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Sun, 31 Mar 2019 16:33:40 -0700 Subject: [PATCH 34/59] Enqueue job on successful upload --- app/controllers/bulk_uploads_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index 7ca7922c..43d9f20d 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -10,6 +10,7 @@ def create @bulk_upload = BulkUpload.new(bulk_upload_params) @bulk_upload.user = current_user if @bulk_upload.save + BulkImportJob.perform_later @bulk_upload redirect_to bulk_upload_path(@bulk_upload) else Rails.logger.error "Errors saving bulk_upload:" From 66acff0e620ee8a0b2b71eff82bbe95c4bbe4b4c Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Sun, 31 Mar 2019 16:48:42 -0700 Subject: [PATCH 35/59] Add messaging after bulk upload completed --- app/views/bulk_uploads/show.html.haml | 1 + config/locales/en/restroom.en.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/views/bulk_uploads/show.html.haml b/app/views/bulk_uploads/show.html.haml index e69de29b..1fd395cf 100644 --- a/app/views/bulk_uploads/show.html.haml +++ b/app/views/bulk_uploads/show.html.haml @@ -0,0 +1 @@ +%p= t('restroom.thank_you_for_your_submission') \ No newline at end of file diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index ecd01d1c..8c191c1f 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -18,6 +18,7 @@ en: add_bulk: 'Upload CSV file' add_bulk_request_pending: 'You have successfully signed up, but you have not been approved to upload restroom CSVs yet. Your request is awaiting approval by the admins. Thank you for your patience and please check back later.' signin_for_bulk_upload: 'Want to add a CSV? Only approved users may upload CSVs. When you sign up, an email will be sent to the admins to approve you. Please contact the admins if you have not recieved a response within a few days. Signup' + thank_you_for_your_submission: 'Thank you for your submission. Your entry is being processed and will be added soon.' csv_submit: 'Save CSV' preview: 'Preview' required: '* marks required field' From 32384dea5cc29ea18ae421a0acb43de74a5fb1cd Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Sun, 31 Mar 2019 16:45:36 -0700 Subject: [PATCH 36/59] conditionally show signout/login, remove remember field --- app/views/layouts/_footer.html.haml | 6 ++++-- app/views/users/sessions/new.html.erb | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index 7bdc3fd9..bf5292ab 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -1,6 +1,9 @@ %footer .footer - %h4= link_to "Signout", destroy_user_session_path, method: :delete + - if current_user + %h4= link_to "Signout", destroy_user_session_path, method: :delete + - else + %h4= link_to "Login", new_user_session_path %a.iconLink{:href => "https://github.com/RefugeRestrooms/refugerestrooms", :aria => { :label => t('.aria-labels.github')}} %i.icon.fa.fa-github-square.fa-3x %a.iconLink{:href => "https://twitter.com/refugerestrooms", :aria => { :label => t('.aria-labels.twitter')}} @@ -19,4 +22,3 @@ %a{:href => "https://patreon.com/refugerestrooms"} #{t('.on-patreon')} %br/ = "\© #{t('.copyleft')} #{Date.today.year} #{t('.refuge-restrooms')}".html_safe - diff --git a/app/views/users/sessions/new.html.erb b/app/views/users/sessions/new.html.erb index 95087f24..425eca85 100644 --- a/app/views/users/sessions/new.html.erb +++ b/app/views/users/sessions/new.html.erb @@ -9,7 +9,6 @@ <%= f.input :password, required: false, input_html: { autocomplete: "current-password" } %> - <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
From aec9fe57089de59f1d9cd51f739b8f461a1c75bd Mon Sep 17 00:00:00 2001 From: Lisa Vogt Date: Mon, 1 Apr 2019 09:48:47 -0700 Subject: [PATCH 37/59] move login/signout link from footer to navbar Co-authored-by: Morgan Fogarty --- app/views/layouts/_footer.html.haml | 4 ---- app/views/layouts/_navigation.html.haml | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index bf5292ab..784abb51 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -1,9 +1,5 @@ %footer .footer - - if current_user - %h4= link_to "Signout", destroy_user_session_path, method: :delete - - else - %h4= link_to "Login", new_user_session_path %a.iconLink{:href => "https://github.com/RefugeRestrooms/refugerestrooms", :aria => { :label => t('.aria-labels.github')}} %i.icon.fa.fa-github-square.fa-3x %a.iconLink{:href => "https://twitter.com/refugerestrooms", :aria => { :label => t('.aria-labels.twitter')}} diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml index ed4ad3b6..d8066db4 100644 --- a/app/views/layouts/_navigation.html.haml +++ b/app/views/layouts/_navigation.html.haml @@ -23,4 +23,8 @@ %li %li= link_to t('.download-unisex-restroom-signs-hyperlink-label'), page_path('signs') %li= link_to t('.public-api-hyperlink-label'), '/api/docs/' + - if current_user + %li= link_to "Signout", destroy_user_session_path, method: :delete + - else + %li= link_to "Login", new_user_session_path / /.navbar-collapse From 078455ef973ef8d98f8eb59f0050be4fba87c0b2 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Mon, 1 Apr 2019 09:55:46 -0700 Subject: [PATCH 38/59] update csv --- spec/fixtures/restrooms.csv | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/spec/fixtures/restrooms.csv b/spec/fixtures/restrooms.csv index c54320ee..2d6eb02f 100644 --- a/spec/fixtures/restrooms.csv +++ b/spec/fixtures/restrooms.csv @@ -1,22 +1,11 @@ -id,name,street,city,state,x,y,directions,comment,lat,long,created,updated,z,w,country,a,b,c -1,Mission Creek Cafe,968 Valencia Street,San Francisco,CA,false,false,Head straight back. behind a divider.,no key,37.757358,-122.42133,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -2,Rainbow Grocery Co-op,1745 Folsom St,San Francisco,CA,true,false,"behind customer server, near the parking garage","need a key --- on cust service desk. sometimes they're both taken, wait by the comment board",37.769009,-122.415649,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -3,Beanery,1307 9th Ave,San Francisco,CA,true,false,"in back, behind the counter",,37.76375,-122.466456,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -4,Coffee To The People,1206 Masonic St,San Francisco,CA,true,false,towards the rear of the coffee shop.,usually clean,37.770064,-122.445174,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -5,Cafe Roma,526 Columbus Ave,San Francisco,CA,true,false,down a steep flight of stairs!,"kinda sketch, but hey, it's a place to pee in north beach...",37.79986,-122.409267,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -6,Maxfield's House of Caffine,398 Dolores St,san francisco,ca,true,false,in back to the left,no key,37.76314,-122.426473,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -7,Cafe Espresso,462 Powell,san francisco,CA,true,false,,up a steep hill,37.788854,-122.408345,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -8,Church Street Cafe,262 Church St,San Francisco,CA,true,false,in the back,Need to get a key,37.766657,-122.428856,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -9,Muddy Water's,1308 Valencia,San Francisco,CA,true,false,,,37.751843,-122.420841,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -10,Philz Coffee,3901 18th St,SAN FRANCISCO,CA,true,false,"to the right of the counter, in back",,37.761047,-122.430769,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -11,Bang San Thai Restuarant,791 Ofarrell St,San Francisco,CA,true,true,in back to the left,two single stall gendered. different owners from mekong (closed in 2008) but still a nice place,37.785067,-122.417648,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -12,New College,50 Fell St,SAN FRANCISCO,CA,true,false,,,37.776615,-122.418718,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -13,Rocking Java,1821 Haight St,SAN FRANCISCO,CA,true,false,,cool walls,37.76921,-122.452309,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -14,Pottery Barn,2390 Market Street,SAN FRANCISCO,CA,true,true,"Second floor, in the back.","You may have to walk around and pretend that you're looking at stuff to use the restrooms. There are 2 stalls (gendered) and they both lock. It's in a corner, so no one will really see which stall anyone goes into.",37.762896,-122.435026,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -15,Sparky's Diner,242 Church St,SAN FRANCISCO,CA,false,true,"in the back, down some steps","two single stalls. gender binary not rigidly enforced, people of a variety of genders openly use either.",37.766879,-122.429028,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -16,Muddy Water's Coffee,521 Valencia St,SAN FRANCISCO,CA,true,false,"in the back, you need to be buzzed in",,37.764496,-122.421674,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -17,GLBT Historical Society,657 Mission Street #300,SAN FRANCISCO,CA,true,false,"3rd Floor, has elevator. Open Tues-Sat, 1-5 pm.",Also worth a visit for their collection of GLBT historical material!,37.787017,-122.400826,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -18,El Rio,3158 Mission St,SAN FRANCISCO,CA,true,false,Back right of main bar room.,"Restrooms are labeled based on hardware available: urinals in one, toilets in the other. Not labeled by gender.",37.746667,-122.419385,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -19,LGBT Community Center,1800 Market St.,SAN FRANCISCO,CA,true,false,"Gender-free restroom on the main floor near the elevators, and also in the Three Dollar Bill Cafe.",,37.771704,-122.423845,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -20,maggie mudd ice cream,903 Cortland,SAN FRANCISCO,CA,true,false,in back by the newspapers!,"amazing vegan ice cream! genderfree, locking, accessible, changing station.",37.739067,-122.413768,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true -21,Dolores Park Cafe,501 Dolores,SAN FRANCISCO,CA,true,false,in the back!,,37.761278,-122.425808,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,false,0,true +name,street,city,state,country,accessible,changing_table,unisex,directions,comment,lat,long +NatureBridge Office,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8322178,-122.536513 +NatureBridge Building 1,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325482,-122.536623 +NatureBridge Building 2,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325861,-122.5374493 +NatureBridge Building 3,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8326581,-122.5379213 +NatureBridge Building 4,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8327381,-122.5384153 +NatureBridge Building 5,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8327681,-122.5387533 +NatureBridge Building 6,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8328611,-122.5392413 +NatureBridge Building 7,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8326411,-122.5392893 +NatureBridge Building 8,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325941,-122.5388763 +NatureBridge Building 9,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325091,-122.5383183 From e51f35737d06e9e4afc25fc951bf4ced1dda333b Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 10:39:41 -0700 Subject: [PATCH 39/59] add default styling to flash messages --- app/assets/stylesheets/components/alert.scss | 5 +++++ app/views/pages/index.html.haml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/components/alert.scss diff --git a/app/assets/stylesheets/components/alert.scss b/app/assets/stylesheets/components/alert.scss new file mode 100644 index 00000000..af506cd4 --- /dev/null +++ b/app/assets/stylesheets/components/alert.scss @@ -0,0 +1,5 @@ +.alert { + margin: 10px; + border-radius: 10px; + background: #ffff0080; +} \ No newline at end of file diff --git a/app/views/pages/index.html.haml b/app/views/pages/index.html.haml index b249118c..bf659e03 100644 --- a/app/views/pages/index.html.haml +++ b/app/views/pages/index.html.haml @@ -1,4 +1,4 @@ -- flash.each do |key, value| +-flash.each do |key, value| %div{class: "alert alert-#{key}"} = value From 11308f7cdb5f2780e93b964319dbe142d181638c Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Mon, 1 Apr 2019 10:53:03 -0700 Subject: [PATCH 40/59] Add instructions for uploading CSV and add link to sample downloadable CSV Co-authored-by: Lisa Vogt --- app/controllers/bulk_uploads_controller.rb | 8 ++++++++ app/views/bulk_uploads/new.html.haml | 15 +++++++++++++++ config/locales/en/restroom.en.yml | 1 + config/routes.rb | 7 +++++-- public/sample.csv | 3 +++ 5 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 public/sample.csv diff --git a/app/controllers/bulk_uploads_controller.rb b/app/controllers/bulk_uploads_controller.rb index 43d9f20d..fafb8aa8 100644 --- a/app/controllers/bulk_uploads_controller.rb +++ b/app/controllers/bulk_uploads_controller.rb @@ -22,6 +22,14 @@ def create def show end + def download_csv + send_file( + "#{Rails.root}/public/sample.csv", + filename: "sample.csv", + type: ".csv" + ) + end + private def authenticate_approved_user! unless user_signed_in? diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index 08ea690b..4c5df312 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -2,6 +2,21 @@ - case - when user_signed_in? && @user.approved? + %p= t('restroom.add_bulk_instructions') + %ul + %li= "name" + %li= "street" + %li= "city" + %li= "state" + %li= "country" + %li= "accessible" + %li= "changing_table" + %li= "unisex" + %li= "directions" + %li= "comment" + %li= "lat" + %li= "long" + = link_to "Sample downloadable CSV", bulk_uploads_download_csv_path = simple_form_for @bulk_upload do |f| = f.file_field :file = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index 8c191c1f..0c33dd44 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -16,6 +16,7 @@ en: restroom: add_new: 'Submit a restroom to our database' add_bulk: 'Upload CSV file' + add_bulk_instructions: 'To upload multiple restrooms, put your information into a CSV file with the following headers, in this order:' add_bulk_request_pending: 'You have successfully signed up, but you have not been approved to upload restroom CSVs yet. Your request is awaiting approval by the admins. Thank you for your patience and please check back later.' signin_for_bulk_upload: 'Want to add a CSV? Only approved users may upload CSVs. When you sign up, an email will be sent to the admins to approve you. Please contact the admins if you have not recieved a response within a few days. Signup' thank_you_for_your_submission: 'Thank you for your submission. Your entry is being processed and will be added soon.' diff --git a/config/routes.rb b/config/routes.rb index acc7f77d..a4557dce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,10 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - resources :bulk_uploads, only: [:new, :create, :show] - + resources :bulk_uploads, only: [:new, :create, :show] do + collection do + get 'download_csv' + end + end devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations' diff --git a/public/sample.csv b/public/sample.csv new file mode 100644 index 00000000..8b73c165 --- /dev/null +++ b/public/sample.csv @@ -0,0 +1,3 @@ +name,street,city,state,country,accessible,changing_table,unisex,directions,comment,lat,long +NatureBridge Office,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8322178,-122.536513 +NatureBridge Building 1,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325482,-122.536623 \ No newline at end of file From a64532f176a7e7d5431c6fae63ae2685dd9b008c Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Sun, 31 Mar 2019 16:33:03 -0400 Subject: [PATCH 41/59] db/seeds.rb: Give restroom entries an edit_id (#567) Only applies during development and testing when we use the "db/export.csv" data. Doesn't affect production, which uses the real data in its db. --- db/seeds.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index c7328759..80a6ff26 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,7 +10,7 @@ Restroom.transaction do CSV.foreach('db/export.csv') do |row| - Restroom.create( + restroom = Restroom.create( :name => row[1], :street => row[3], :city => row[4], @@ -23,5 +23,6 @@ :longitude => row[9], :country => row[6] ) + restroom.update(edit_id: restroom.id) end -end \ No newline at end of file +end From 600256d7de5a95cc98e7f60bdd2f89a9383267c7 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 10:55:40 -0700 Subject: [PATCH 42/59] Tag restrooms with upload; use service to save --- app/jobs/bulk_import_job.rb | 3 ++- app/models/bulk_upload.rb | 1 + app/models/restroom.rb | 8 ++++++-- app/services/save_restroom.rb | 5 +++-- .../20190401160436_add_bulk_upload_ref_to_restroom.rb | 5 +++++ db/schema.rb | 5 ++++- 6 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20190401160436_add_bulk_upload_ref_to_restroom.rb diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index 6e47617a..c2effb31 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -11,9 +11,10 @@ def perform(bulk_upload) CSV.parse(contents, headers: true) do |row| values = row.to_hash.slice "name", "street", "city", "state", "country" rr = Restroom.new values + rr.bulk_upload = bulk_upload if rr.valid? if rr.latitude && rr.longitude - rr.save + SaveRestroom.new(rr, false).call else # TODO: add row_error Rails.logger.warn "Unable to geocode data: #{values}" diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index 4bf3e86a..637bb82a 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -1,4 +1,5 @@ class BulkUpload < ApplicationRecord has_one_attached :file belongs_to :user, required: true + has_many :restrooms end diff --git a/app/models/restroom.rb b/app/models/restroom.rb index 2306beb2..2ba28423 100644 --- a/app/models/restroom.rb +++ b/app/models/restroom.rb @@ -3,6 +3,7 @@ # (accessible) is coded by 1 class Restroom < ApplicationRecord + belongs_to :bulk_upload, optional: true include PgSearch pg_search_scope :search, against: { @@ -34,7 +35,7 @@ class Restroom < ApplicationRecord include Rakismet::Model rakismet_attrs content: proc { - name + street + city + state + comment + directions + country + name + street + city + state + (comment || '') + (directions || '') + country } after_find :strip_slashes @@ -82,8 +83,11 @@ def strip_slashes end def perform_geocoding + return true if @geocoded_already return true if Rails.env == "test" return true if ENV["SEEDING_DONT_GEOCODE"] - geocode + geocode_succeeded = geocode + @geocoded_already = true + geocode_succeeded end end diff --git a/app/services/save_restroom.rb b/app/services/save_restroom.rb index 97a5edac..6b07b553 100644 --- a/app/services/save_restroom.rb +++ b/app/services/save_restroom.rb @@ -1,10 +1,11 @@ class SaveRestroom - def initialize(restroom) + def initialize(restroom, check_spam = true) @restroom = restroom + @check_spam = check_spam end def call - if @restroom.spam? + if @check_spam && @restroom.spam? @restroom.errors.add(:spam, 'This restroom is spam') else Restroom.transaction do diff --git a/db/migrate/20190401160436_add_bulk_upload_ref_to_restroom.rb b/db/migrate/20190401160436_add_bulk_upload_ref_to_restroom.rb new file mode 100644 index 00000000..a6dc1abd --- /dev/null +++ b/db/migrate/20190401160436_add_bulk_upload_ref_to_restroom.rb @@ -0,0 +1,5 @@ +class AddBulkUploadRefToRestroom < ActiveRecord::Migration[5.2] + def change + add_reference :restrooms, :bulk_upload, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 0a4a3113..05a2c377 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.define(version: 2019_03_31_182012) do +ActiveRecord::Schema.define(version: 2019_04_01_160436) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -109,6 +109,8 @@ t.boolean "changing_table", default: false t.integer "edit_id", default: 0 t.boolean "approved", default: true + t.bigint "bulk_upload_id" + t.index ["bulk_upload_id"], name: "index_restrooms_on_bulk_upload_id" end create_table "users", force: :cascade do |t| @@ -125,4 +127,5 @@ end add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "restrooms", "bulk_uploads" end From 2d64fd070d1b2c8051c6e6aedf45ce643dabff44 Mon Sep 17 00:00:00 2001 From: Betsy Haibel Date: Mon, 1 Apr 2019 13:59:04 -0400 Subject: [PATCH 43/59] hacky error handling for imports --- app/jobs/bulk_import_job.rb | 26 ++++++++++++++++++++++++-- spec/jobs/bulk_import_job_spec.rb | 2 +- spec/mailers/user_mailer_spec.rb | 2 +- spec/models/bulk_upload_spec.rb | 2 +- spec/models/user_spec.rb | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index c2effb31..f5ba99ff 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -7,6 +7,7 @@ class BulkImportJob < ApplicationJob def perform(bulk_upload) contents = bulk_upload.file.download Rails.logger.info Geocoder.config + row_level_errors = [] CSV.parse(contents, headers: true) do |row| values = row.to_hash.slice "name", "street", "city", "state", "country" @@ -16,13 +17,34 @@ def perform(bulk_upload) if rr.latitude && rr.longitude SaveRestroom.new(rr, false).call else - # TODO: add row_error + row_level_errors << NonGeocodableRow.new(values) Rails.logger.warn "Unable to geocode data: #{values}" end else - # TODO: also add row_error + row_level_errors << InvalidRow.new(values) Rails.logger.warn "Unable to validate data: #{values}" end end + + # This is a stupidest-thing-that-could-work solution + # due to limited time at a hackathon. + # Please replace me with real validation error handling in the future. + if row_level_errors.length > 0 + raise "problems with at least one CSV row" + end + + rescue e + raise GenericError.new(message: e.message, upload: bulk_upload, row_level_errors: row_level_errors) end + + class GenericError < StandardError + def initialize(message:, upload:, row_level_errors:) + @upload = upload + @row_level_errors = row_level_errors + super(message) + end + end + + NonGeocodableRow = Struct.new(:row) + InvalidRow = Struct.new(:row) end diff --git a/spec/jobs/bulk_import_job_spec.rb b/spec/jobs/bulk_import_job_spec.rb index e750f70e..21c8d8fe 100644 --- a/spec/jobs/bulk_import_job_spec.rb +++ b/spec/jobs/bulk_import_job_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' RSpec.describe BulkImportJob, type: :job do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 4a78b857..00ce5494 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -1,4 +1,4 @@ -require "rails_helper" +require "spec_helper" RSpec.describe UserMailer, type: :mailer do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/models/bulk_upload_spec.rb b/spec/models/bulk_upload_spec.rb index 27ec90e6..a009915c 100644 --- a/spec/models/bulk_upload_spec.rb +++ b/spec/models/bulk_upload_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' RSpec.describe BulkUpload, type: :model do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 47a31bb4..bb3a5d45 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' RSpec.describe User, type: :model do pending "add some examples to (or delete) #{__FILE__}" From 82ad0603954d9cba567a2e466826556798486829 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Mon, 1 Apr 2019 11:11:04 -0700 Subject: [PATCH 44/59] Fix CSV download link path --- app/views/bulk_uploads/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/bulk_uploads/new.html.haml b/app/views/bulk_uploads/new.html.haml index 4c5df312..86bfbe0a 100644 --- a/app/views/bulk_uploads/new.html.haml +++ b/app/views/bulk_uploads/new.html.haml @@ -16,7 +16,7 @@ %li= "comment" %li= "lat" %li= "long" - = link_to "Sample downloadable CSV", bulk_uploads_download_csv_path + = link_to "Sample downloadable CSV", download_csv_bulk_uploads_path = simple_form_for @bulk_upload do |f| = f.file_field :file = f.button :submit, t('restroom.csv_submit'), :class => "linkbutton" From 035a761947e4355da7c29c67215a13d934599d4b Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 11:20:23 -0700 Subject: [PATCH 45/59] Add blurb about bulk uploades to the FAQ. --- config/locales/en/about.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en/about.en.yml b/config/locales/en/about.en.yml index 7e3ff50c..2a3c998a 100644 --- a/config/locales/en/about.en.yml +++ b/config/locales/en/about.en.yml @@ -13,7 +13,7 @@ en: p4: "One of the biggest battlefields upon which the fight for transgender rights is taking place daily are restrooms. It seems that every other week a transgender child is made the center of a national news story because they used the restroom assigned to the gender they identify with. Obviously, we believe that every transgender person should have the right to use the restroom they want to. However, we also realize that despite legislative victories in recent years regarding restroom usage, many transgender individuals still face both verbal and physical harassment simply for using the restroom. Nobody should have to face that - and that is why we created REFUGE." p5header: 'What can we do to help?' p5: - first: "First: Add listings. The database is only as big as you make it. The more listings, the more comprehensive and valuable the resource can be." + first: "First: Add listings. The database is only as big as you make it. The more listings, the more comprehensive and valuable the resource can be. If you have a lot of restrooms to add, we have a bulk upload feature! You can register to use it from the 'Add a CSV' link on the 'Add a Restroom' page." second: "Secondly: Spread the word. Tweet. Facebook. Tumblr. Blog. Whatever it is that you do, do it. Let people know about this resource." third: "Thirdly: If you know how to code, visit GitHub and let us know about a bug, suggest an improvement, or even contribute a little bit of code and help out the project. REFUGE is open source and we can't do it without you." fourth: "Fourthly: Donate. Keep your eyes peeled for an upcoming crowd funding campaign to fund some of the technology we need to use as well as to pay our fabulous designers and engineers a little bit of money for their hard and tireless work. They have been working for free to bring this service to you and we don't want anybody to work for free. Most of the core team are transgender and underemployed at this time." From 337d03e59013a18b6484d5d8db862e5c6aa30ba5 Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Mon, 1 Apr 2019 11:21:04 -0700 Subject: [PATCH 46/59] add notes to user --- app/admin/user.rb | 2 +- app/controllers/users/registrations_controller.rb | 9 +++++++++ app/views/users/registrations/new.html.erb | 3 +++ config/webpacker.yml | 2 +- db/migrate/20190401174056_add_notes_to_users.rb | 5 +++++ db/schema.rb | 3 ++- 6 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20190401174056_add_notes_to_users.rb diff --git a/app/admin/user.rb b/app/admin/user.rb index 8c14974f..861ac1c0 100644 --- a/app/admin/user.rb +++ b/app/admin/user.rb @@ -1,3 +1,3 @@ ActiveAdmin.register User do - permit_params :email, :approved + permit_params :email, :approved, :notes end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index 58db3e35..8ebc1c6f 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -16,6 +16,15 @@ def create UserMailer.approve_new_user_email(@user).deliver_now end + private + + def sign_up_params + params.require(:user).permit(:email, :password, :password_confirmation, :notes) + end + + def account_update_params + params.require(:user).permit(:email, :password, :password_confirmation, :current_password, :notes) + end # GET /resource/edit # def edit # super diff --git a/app/views/users/registrations/new.html.erb b/app/views/users/registrations/new.html.erb index fa5bd02b..30e414f9 100644 --- a/app/views/users/registrations/new.html.erb +++ b/app/views/users/registrations/new.html.erb @@ -15,6 +15,9 @@ <%= f.input :password_confirmation, required: true, input_html: { autocomplete: "new-password" } %> + <%= f.input :notes, + required: true, + input_html: { autocomplete: "notes" } %>
diff --git a/config/webpacker.yml b/config/webpacker.yml index 24546aa1..80735d6e 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -31,7 +31,7 @@ default: &default development: <<: *default - compile: true + compile: false # Reference: https://webpack.js.org/configuration/dev-server/ dev_server: diff --git a/db/migrate/20190401174056_add_notes_to_users.rb b/db/migrate/20190401174056_add_notes_to_users.rb new file mode 100644 index 00000000..c9574a2f --- /dev/null +++ b/db/migrate/20190401174056_add_notes_to_users.rb @@ -0,0 +1,5 @@ +class AddNotesToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :notes, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 0a4a3113..44304b4d 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.define(version: 2019_03_31_182012) do +ActiveRecord::Schema.define(version: 2019_04_01_174056) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -120,6 +120,7 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "approved", default: false + t.string "notes" t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end From f2c5a054970ee225733925f34630647c2d6a4669 Mon Sep 17 00:00:00 2001 From: Morgan Fogarty Date: Mon, 1 Apr 2019 11:23:42 -0700 Subject: [PATCH 47/59] Add text to thank users for uploading --- config/locales/en/restroom.en.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en/restroom.en.yml b/config/locales/en/restroom.en.yml index 0c33dd44..2a458c69 100644 --- a/config/locales/en/restroom.en.yml +++ b/config/locales/en/restroom.en.yml @@ -18,8 +18,8 @@ en: add_bulk: 'Upload CSV file' add_bulk_instructions: 'To upload multiple restrooms, put your information into a CSV file with the following headers, in this order:' add_bulk_request_pending: 'You have successfully signed up, but you have not been approved to upload restroom CSVs yet. Your request is awaiting approval by the admins. Thank you for your patience and please check back later.' - signin_for_bulk_upload: 'Want to add a CSV? Only approved users may upload CSVs. When you sign up, an email will be sent to the admins to approve you. Please contact the admins if you have not recieved a response within a few days. Signup' - thank_you_for_your_submission: 'Thank you for your submission. Your entry is being processed and will be added soon.' + signin_for_bulk_upload: 'Want to add a CSV? Only approved users may upload CSVs. When you sign up, an email will be sent to the admins to approve you. Please contact the admins if you have not recieved a response within a few days. Signup or Login' + thank_you_for_your_submission: 'Thank you for your submission! You are beautiful. Your entry is being processed and will be added soon.' csv_submit: 'Save CSV' preview: 'Preview' required: '* marks required field' From c40eb61a392ff59c182fe556baa2f27d82e72fab Mon Sep 17 00:00:00 2001 From: Mikena Wood Date: Mon, 1 Apr 2019 11:25:46 -0700 Subject: [PATCH 48/59] add error rescue clause --- app/jobs/bulk_import_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index f5ba99ff..9a3b071a 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -33,7 +33,7 @@ def perform(bulk_upload) raise "problems with at least one CSV row" end - rescue e + rescue Exception => e raise GenericError.new(message: e.message, upload: bulk_upload, row_level_errors: row_level_errors) end From 230b83bdd2b5a8de236bed2780aded4965e7375e Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 11:31:43 -0700 Subject: [PATCH 49/59] Fix method scoping issues --- app/jobs/bulk_import_job.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index 9a3b071a..f3cc186d 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -26,12 +26,12 @@ def perform(bulk_upload) end end - # This is a stupidest-thing-that-could-work solution - # due to limited time at a hackathon. - # Please replace me with real validation error handling in the future. - if row_level_errors.length > 0 - raise "problems with at least one CSV row" - end + # This is a stupidest-thing-that-could-work solution + # due to limited time at a hackathon. + # Please replace me with real validation error handling in the future. + if row_level_errors.length > 0 + raise "problems with at least one CSV row" + end rescue Exception => e raise GenericError.new(message: e.message, upload: bulk_upload, row_level_errors: row_level_errors) From 1cf267fcf124258dc10913d5cbc4a3b648a93454 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 11:46:28 -0700 Subject: [PATCH 50/59] Add example bad CSV file --- spec/fixtures/example_bad_file.csv | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 spec/fixtures/example_bad_file.csv diff --git a/spec/fixtures/example_bad_file.csv b/spec/fixtures/example_bad_file.csv new file mode 100644 index 00000000..606e007e --- /dev/null +++ b/spec/fixtures/example_bad_file.csv @@ -0,0 +1,22 @@ +id,name,city,state,x,y,directions,comment,lat,long,created,updated,z,w,country,a,b,c +1,Mission Creek Cafe,San Francisco,CA,FALSE,FALSE,Head straight back. behind a divider.,no key,37.757358,-122.42133,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +2,Rainbow Grocery Co-op,San Francisco,CA,TRUE,FALSE,"behind customer server, near the parking garage","need a key --- on cust service desk. sometimes they're both taken, wait by the comment board",37.769009,-122.415649,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +3,Beanery,San Francisco,CA,TRUE,FALSE,"in back, behind the counter",,37.76375,-122.466456,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +4,Coffee To The People,San Francisco,CA,TRUE,FALSE,towards the rear of the coffee shop.,usually clean,37.770064,-122.445174,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +5,Cafe Roma,San Francisco,CA,TRUE,FALSE,down a steep flight of stairs!,"kinda sketch, but hey, it's a place to pee in north beach...",37.79986,-122.409267,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +6,Maxfield's House of Caffine,san francisco,ca,TRUE,FALSE,in back to the left,no key,37.76314,-122.426473,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +7,Cafe Espresso,san francisco,CA,TRUE,FALSE,,up a steep hill,37.788854,-122.408345,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +8,Church Street Cafe,San Francisco,CA,TRUE,FALSE,in the back,Need to get a key,37.766657,-122.428856,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +9,Muddy Water's,San Francisco,CA,TRUE,FALSE,,,37.751843,-122.420841,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +10,Philz Coffee,SAN FRANCISCO,CA,TRUE,FALSE,"to the right of the counter, in back",,37.761047,-122.430769,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +11,Bang San Thai Restuarant,San Francisco,CA,TRUE,TRUE,in back to the left,two single stall gendered. different owners from mekong (closed in 2008) but still a nice place,37.785067,-122.417648,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +12,New College,SAN FRANCISCO,CA,TRUE,FALSE,,,37.776615,-122.418718,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +13,Rocking Java,SAN FRANCISCO,CA,TRUE,FALSE,,cool walls,37.76921,-122.452309,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +14,Pottery Barn,SAN FRANCISCO,CA,TRUE,TRUE,"Second floor, in the back.","You may have to walk around and pretend that you're looking at stuff to use the restrooms. There are 2 stalls (gendered) and they both lock. It's in a corner, so no one will really see which stall anyone goes into.",37.762896,-122.435026,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +15,Sparky's Diner,SAN FRANCISCO,CA,FALSE,TRUE,"in the back, down some steps","two single stalls. gender binary not rigidly enforced, people of a variety of genders openly use either.",37.766879,-122.429028,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +16,Muddy Water's Coffee,SAN FRANCISCO,CA,TRUE,FALSE,"in the back, you need to be buzzed in",,37.764496,-122.421674,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +17,GLBT Historical Society,SAN FRANCISCO,CA,TRUE,FALSE,"3rd Floor, has elevator. Open Tues-Sat, 1-5 pm.",Also worth a visit for their collection of GLBT historical material!,37.787017,-122.400826,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +18,El Rio,SAN FRANCISCO,CA,TRUE,FALSE,Back right of main bar room.,"Restrooms are labeled based on hardware available: urinals in one, toilets in the other. Not labeled by gender.",37.746667,-122.419385,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +19,LGBT Community Center,SAN FRANCISCO,CA,TRUE,FALSE,"Gender-free restroom on the main floor near the elevators, and also in the Three Dollar Bill Cafe.",,37.771704,-122.423845,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +20,maggie mudd ice cream,SAN FRANCISCO,CA,TRUE,FALSE,in back by the newspapers!,"amazing vegan ice cream! genderfree, locking, accessible, changing station.",37.739067,-122.413768,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE +21,Dolores Park Cafe,SAN FRANCISCO,CA,TRUE,FALSE,in the back!,,37.761278,-122.425808,2019-03-31 17:49:46 UTC,2019-03-31 17:49:46 UTC,0,0,US,FALSE,0,TRUE \ No newline at end of file From 9b5a145f630f11d7bc033767ef0246b5e45b908e Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 11:47:06 -0700 Subject: [PATCH 51/59] Support directions and comments in bulk import --- app/jobs/bulk_import_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index f3cc186d..e7018b29 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -10,7 +10,7 @@ def perform(bulk_upload) row_level_errors = [] CSV.parse(contents, headers: true) do |row| - values = row.to_hash.slice "name", "street", "city", "state", "country" + values = row.to_hash.slice 'name', 'street', 'city', 'state', 'country', 'directions', 'comment' rr = Restroom.new values rr.bulk_upload = bulk_upload if rr.valid? From 9b403f0d85bb05eb6b8f03a7d0a6f598b29c44d8 Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 11:57:13 -0700 Subject: [PATCH 52/59] Discard import job on GenericError; disable geocoding for demo --- app/jobs/bulk_import_job.rb | 17 +++++++++-------- app/models/restroom.rb | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index e7018b29..f60871fd 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -2,7 +2,16 @@ require 'geocoder' class BulkImportJob < ApplicationJob + class GenericError < StandardError + def initialize(message:, upload:, row_level_errors:) + @upload = upload + @row_level_errors = row_level_errors + super(message) + end + end + queue_as :default + discard_on(GenericError) def perform(bulk_upload) contents = bulk_upload.file.download @@ -37,14 +46,6 @@ def perform(bulk_upload) raise GenericError.new(message: e.message, upload: bulk_upload, row_level_errors: row_level_errors) end - class GenericError < StandardError - def initialize(message:, upload:, row_level_errors:) - @upload = upload - @row_level_errors = row_level_errors - super(message) - end - end - NonGeocodableRow = Struct.new(:row) InvalidRow = Struct.new(:row) end diff --git a/app/models/restroom.rb b/app/models/restroom.rb index 2ba28423..f3916a6c 100644 --- a/app/models/restroom.rb +++ b/app/models/restroom.rb @@ -83,6 +83,7 @@ def strip_slashes end def perform_geocoding + return true # TODO: remove after demo return true if @geocoded_already return true if Rails.env == "test" return true if ENV["SEEDING_DONT_GEOCODE"] From c749ef49ab341aeb53b77d6c7d5bcd4e2535ecce Mon Sep 17 00:00:00 2001 From: Caleb Harris Date: Mon, 1 Apr 2019 12:13:04 -0700 Subject: [PATCH 53/59] Support lat and long in import job --- app/jobs/bulk_import_job.rb | 11 ++++++++++- spec/fixtures/restrooms.csv | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/jobs/bulk_import_job.rb b/app/jobs/bulk_import_job.rb index f60871fd..c974d7ad 100644 --- a/app/jobs/bulk_import_job.rb +++ b/app/jobs/bulk_import_job.rb @@ -19,7 +19,16 @@ def perform(bulk_upload) row_level_errors = [] CSV.parse(contents, headers: true) do |row| - values = row.to_hash.slice 'name', 'street', 'city', 'state', 'country', 'directions', 'comment' + values = row.to_hash.slice('name', + 'street', + 'city', + 'state', + 'country', + 'directions', + 'comment', + 'latitude', + 'longitude' + ) rr = Restroom.new values rr.bulk_upload = bulk_upload if rr.valid? diff --git a/spec/fixtures/restrooms.csv b/spec/fixtures/restrooms.csv index 2d6eb02f..5eb5cfca 100644 --- a/spec/fixtures/restrooms.csv +++ b/spec/fixtures/restrooms.csv @@ -1,4 +1,4 @@ -name,street,city,state,country,accessible,changing_table,unisex,directions,comment,lat,long +name,street,city,state,country,accessible,changing_table,unisex,directions,comment,latitude,longitude NatureBridge Office,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8322178,-122.536513 NatureBridge Building 1,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325482,-122.536623 NatureBridge Building 2,1033 Fort Cronkhite,Sausalito,CA,US,true,false,true,You are here!,Hi Ruby by the Bay!,37.8325861,-122.5374493 From 2961bc22db6f4adebfa7fcdf960257a2c10ca3c3 Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 12:15:55 -0700 Subject: [PATCH 54/59] Adjust URL in user confirmation email to match in production and staging --- app/views/user_mailer/approve_new_user_email.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index 8e4ca0d6..7be3f675 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -2,5 +2,6 @@

The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
- Here is an ActiveAdmin link: http://www.refugerestrooms.org/admin/users/<%= @user.id %> + Here is an ActiveAdmin link: + <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %>

From ee21307883a561d2464c223dbe03334fb73e7da9 Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 12:16:57 -0700 Subject: [PATCH 55/59] Add http, it's late and I'm tired --- app/views/user_mailer/approve_new_user_email.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index 7be3f675..b19d4651 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -3,5 +3,5 @@ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
Here is an ActiveAdmin link: - <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %> + <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "http://refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %>

From 247284c1fa054cb7977c77b9cf01074addae6d7b Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 12:17:34 -0700 Subject: [PATCH 56/59] One last URL adjustment --- app/views/user_mailer/approve_new_user_email.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index b19d4651..177b57d2 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -3,5 +3,5 @@ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
Here is an ActiveAdmin link: - <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "http://refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %> + <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "http://www.refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %>

From 6cafd79c8ccf4c33e1a53ee8781c2f4f5e1ce9f5 Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 12:25:02 -0700 Subject: [PATCH 57/59] REVERT AFTER DEMO --- app/views/user_mailer/approve_new_user_email.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index 177b57d2..947109d2 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -3,5 +3,5 @@ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
Here is an ActiveAdmin link: - <%= Rails.env.production? ? "http://www.refugerestrooms.org" : "http://www.refuge-staging-14-pr-569.herokuapp.com" %>/admin/users/<%= @user.id %> + http://www.refuge-staging-14-pr-569.herokuapp.com/admin/users/<%= @user.id %>

From 938b3bfed0ef7d8ef4689ee1c64c48d24d503976 Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 13:36:34 -0700 Subject: [PATCH 58/59] I am so upset --- app/views/user_mailer/approve_new_user_email.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index 947109d2..4efcae21 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -3,5 +3,5 @@ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
Here is an ActiveAdmin link: - http://www.refuge-staging-14-pr-569.herokuapp.com/admin/users/<%= @user.id %> + http://refuge-staging-14-pr-569.herokuapp.com/admin/users/<%= @user.id %>

From 7c6ee36d108ee3c3eb406f95a07a1398b69956cb Mon Sep 17 00:00:00 2001 From: Chelsea Troy Date: Mon, 1 Apr 2019 13:38:41 -0700 Subject: [PATCH 59/59] Finished --- app/views/user_mailer/approve_new_user_email.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/user_mailer/approve_new_user_email.html.erb b/app/views/user_mailer/approve_new_user_email.html.erb index 4efcae21..63be0027 100644 --- a/app/views/user_mailer/approve_new_user_email.html.erb +++ b/app/views/user_mailer/approve_new_user_email.html.erb @@ -3,5 +3,5 @@ The user with email: <%= @user.email %> would like to join Refuge Restrooms.
Please check this person out and approve or reject them.
Here is an ActiveAdmin link: - http://refuge-staging-14-pr-569.herokuapp.com/admin/users/<%= @user.id %> + https://refuge-staging-14-pr-569.herokuapp.com/admin/users/<%= @user.id %>