From 66ad8e1be24e59d97dd453a9a5d9c0965e2a1455 Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Sun, 28 Jun 2020 16:13:46 +0100 Subject: [PATCH 01/14] update rails --- Gemfile.lock | 106 +++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index de4c18f6..db7bb053 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,59 +1,59 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.0.3.1) - actionpack (= 6.0.3.1) + actioncable (6.0.3.2) + actionpack (= 6.0.3.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.1) - actionpack (= 6.0.3.1) - activejob (= 6.0.3.1) - activerecord (= 6.0.3.1) - activestorage (= 6.0.3.1) - activesupport (= 6.0.3.1) + actionmailbox (6.0.3.2) + actionpack (= 6.0.3.2) + activejob (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) mail (>= 2.7.1) - actionmailer (6.0.3.1) - actionpack (= 6.0.3.1) - actionview (= 6.0.3.1) - activejob (= 6.0.3.1) + actionmailer (6.0.3.2) + actionpack (= 6.0.3.2) + actionview (= 6.0.3.2) + activejob (= 6.0.3.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.1) - actionview (= 6.0.3.1) - activesupport (= 6.0.3.1) + actionpack (6.0.3.2) + actionview (= 6.0.3.2) + activesupport (= 6.0.3.2) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.1) - actionpack (= 6.0.3.1) - activerecord (= 6.0.3.1) - activestorage (= 6.0.3.1) - activesupport (= 6.0.3.1) + actiontext (6.0.3.2) + actionpack (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) nokogiri (>= 1.8.5) - actionview (6.0.3.1) - activesupport (= 6.0.3.1) + actionview (6.0.3.2) + activesupport (= 6.0.3.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.1) - activesupport (= 6.0.3.1) + activejob (6.0.3.2) + activesupport (= 6.0.3.2) globalid (>= 0.3.6) - activemodel (6.0.3.1) - activesupport (= 6.0.3.1) - activerecord (6.0.3.1) - activemodel (= 6.0.3.1) - activesupport (= 6.0.3.1) + activemodel (6.0.3.2) + activesupport (= 6.0.3.2) + activerecord (6.0.3.2) + activemodel (= 6.0.3.2) + activesupport (= 6.0.3.2) activerecord-postgis-adapter (6.0.0) activerecord (~> 6.0) rgeo-activerecord (~> 6.0) - activestorage (6.0.3.1) - actionpack (= 6.0.3.1) - activejob (= 6.0.3.1) - activerecord (= 6.0.3.1) + activestorage (6.0.3.2) + actionpack (= 6.0.3.2) + activejob (= 6.0.3.2) + activerecord (= 6.0.3.2) marcel (~> 0.3.1) - activesupport (6.0.3.1) + activesupport (6.0.3.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -179,7 +179,7 @@ GEM httparty (0.18.0) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.2) + i18n (1.8.3) concurrent-ruby (~> 1.0) image_processing (1.11.0) mini_magick (>= 4.9.5, < 5) @@ -209,7 +209,7 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) - loofah (2.5.0) + loofah (2.6.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -258,20 +258,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.0.3.1) - actioncable (= 6.0.3.1) - actionmailbox (= 6.0.3.1) - actionmailer (= 6.0.3.1) - actionpack (= 6.0.3.1) - actiontext (= 6.0.3.1) - actionview (= 6.0.3.1) - activejob (= 6.0.3.1) - activemodel (= 6.0.3.1) - activerecord (= 6.0.3.1) - activestorage (= 6.0.3.1) - activesupport (= 6.0.3.1) + rails (6.0.3.2) + actioncable (= 6.0.3.2) + actionmailbox (= 6.0.3.2) + actionmailer (= 6.0.3.2) + actionpack (= 6.0.3.2) + actiontext (= 6.0.3.2) + actionview (= 6.0.3.2) + activejob (= 6.0.3.2) + activemodel (= 6.0.3.2) + activerecord (= 6.0.3.2) + activestorage (= 6.0.3.2) + activesupport (= 6.0.3.2) bundler (>= 1.3.0) - railties (= 6.0.3.1) + railties (= 6.0.3.2) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) @@ -281,9 +281,9 @@ GEM rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) - railties (6.0.3.1) - actionpack (= 6.0.3.1) - activesupport (= 6.0.3.1) + railties (6.0.3.2) + actionpack (= 6.0.3.2) + activesupport (= 6.0.3.2) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -387,7 +387,7 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (4.0.0) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.1) From 7b992a8816b9ae3e4c60cd3adca0b761f1ca6e75 Mon Sep 17 00:00:00 2001 From: Tiago Santos <santos.tiago@gmail.com> Date: Sun, 28 Jun 2020 22:52:55 +0100 Subject: [PATCH 02/14] Created the model for favorites --- app/models/favorite.rb | 14 ++++++++++++++ db/migrate/20200628215106_create_favorites.rb | 10 ++++++++++ db/schema.rb | 13 ++++++++++++- spec/factories/favorites.rb | 16 ++++++++++++++++ spec/models/favorite_spec.rb | 15 +++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 app/models/favorite.rb create mode 100644 db/migrate/20200628215106_create_favorites.rb create mode 100644 spec/factories/favorites.rb create mode 100644 spec/models/favorite_spec.rb diff --git a/app/models/favorite.rb b/app/models/favorite.rb new file mode 100644 index 00000000..9d312519 --- /dev/null +++ b/app/models/favorite.rb @@ -0,0 +1,14 @@ +# == Schema Information +# +# Table name: favorites +# +# id :bigint not null, primary key +# store_id :bigint not null +# user_id :bigint not null +# created_at :datetime not null +# updated_at :datetime not null +# +class Favorite < ApplicationRecord + belongs_to :store + belongs_to :user +end diff --git a/db/migrate/20200628215106_create_favorites.rb b/db/migrate/20200628215106_create_favorites.rb new file mode 100644 index 00000000..6de45b1f --- /dev/null +++ b/db/migrate/20200628215106_create_favorites.rb @@ -0,0 +1,10 @@ +class CreateFavorites < ActiveRecord::Migration[6.0] + def change + create_table :favorites do |t| + t.references :store, null: false, foreign_key: true + t.references :user, null: false, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 65f9d507..50168f29 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: 2020_06_24_110119) do +ActiveRecord::Schema.define(version: 2020_06_28_215106) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -85,6 +85,15 @@ t.index ["water_quality"], name: "index_beach_configurations_on_water_quality" end + create_table "favorites", force: :cascade do |t| + t.bigint "store_id", null: false + t.bigint "user_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["store_id"], name: "index_favorites_on_store_id" + t.index ["user_id"], name: "index_favorites_on_user_id" + end + create_table "phones", force: :cascade do |t| t.string "phone_number", null: false t.string "name" @@ -265,6 +274,8 @@ add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "api_keys", "users", on_delete: :cascade add_foreign_key "beach_configurations", "stores", on_delete: :cascade + add_foreign_key "favorites", "stores" + add_foreign_key "favorites", "users" add_foreign_key "phones", "stores", on_delete: :cascade add_foreign_key "status_crowdsource_users", "stores", on_delete: :cascade add_foreign_key "status_crowdsource_users", "users", on_delete: :cascade diff --git a/spec/factories/favorites.rb b/spec/factories/favorites.rb new file mode 100644 index 00000000..a83c0806 --- /dev/null +++ b/spec/factories/favorites.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: favorites +# +# id :bigint not null, primary key +# store_id :bigint not null +# user_id :bigint not null +# created_at :datetime not null +# updated_at :datetime not null +# +FactoryBot.define do + factory :favorite do + store { nil } + user { nil } + end +end diff --git a/spec/models/favorite_spec.rb b/spec/models/favorite_spec.rb new file mode 100644 index 00000000..631247a7 --- /dev/null +++ b/spec/models/favorite_spec.rb @@ -0,0 +1,15 @@ +# == Schema Information +# +# Table name: favorites +# +# id :bigint not null, primary key +# store_id :bigint not null +# user_id :bigint not null +# created_at :datetime not null +# updated_at :datetime not null +# +require 'rails_helper' + +RSpec.describe Favorite, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 28c3b82386a3316060fae9b5f9bcb5c28e3ac606 Mon Sep 17 00:00:00 2001 From: Tiago Santos <santos.tiago@gmail.com> Date: Mon, 29 Jun 2020 00:13:13 +0100 Subject: [PATCH 03/14] Finished the crud for favorites --- .../api/v1/favorites_controller.rb | 56 +++++++++++++++++++ app/controllers/api_controller.rb | 5 +- app/models/favorite.rb | 2 + app/models/user.rb | 1 + app/resources/api/v1/favorite_resource.rb | 21 +++++++ app/serializers/favorite_serializer.rb | 40 +++++++++++++ config/routes.rb | 2 + db/migrate/20200628215106_create_favorites.rb | 2 + db/schema.rb | 1 + 9 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 app/controllers/api/v1/favorites_controller.rb create mode 100644 app/resources/api/v1/favorite_resource.rb create mode 100644 app/serializers/favorite_serializer.rb diff --git a/app/controllers/api/v1/favorites_controller.rb b/app/controllers/api/v1/favorites_controller.rb new file mode 100644 index 00000000..2d1e3a3e --- /dev/null +++ b/app/controllers/api/v1/favorites_controller.rb @@ -0,0 +1,56 @@ +module Api + module V1 + class FavoritesController < ApiController + def create + return if no_user + return if no_store + + favorite = Favorite.new(store: @store, user: @user) + if favorite.save + render json: FavoriteSerializer.new(favorite).serialized_json, status: :created + else + render json: {errors: favorite.errors.full_messages.join(', ')}, status: :conflict + end + end + + def destroy + return if no_user + + favorite = Favorite.find_by id: params[:id] + return render json: {errors: "Couldn't find favorite"}, status: :not_found unless favorite + unless @user == favorite.user + return render json: {errors: "Favorite doesn't belong to user"}, status: :forbidden + end + + if favorite.destroy + render json: {}, status: :no_content + else + render json: {errors: favorite.errors.full_messages.join(', ')}, status: :conflict + end + end + + def index + @favorites = context[:current_user].favorites + super + end + + private + + def no_user + @user = context[:current_user] + return false if @user&.confirmed? + + render json: {error: 'You must be authenticated'}, status: :forbidden + true + end + + def no_store + @store = Store.find params.dig(:data, :attributes, :"store-id") + false + rescue ActiveRecord::RecordNotFound + render json: {error: 'Store not found'} + true + end + end + end +end diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index fdfe8855..2b77da49 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -18,7 +18,7 @@ def context private def authenticate_with_jwt! - return @current_user = User.first if Rails.env.development? + # return @current_user = User.first if Rails.env.development? payload = JwtService.decode(token: token) if DateTime.parse(payload['expiration_date']) <= DateTime.current @@ -36,7 +36,8 @@ def current_user @current_user ||= if store_owner_code User.find_by(store_owner_code: store_owner_code, role: :store_owner) else - User.find_by(app_uuid: JwtService.decode(token: token)['uuid']) + tmp_uuid = JwtService.decode(token: token)['uuid'] + tmp_uuid.present? ? User.find_by(app_uuid: tmp_uuid) : nil end rescue StandardError @current_user = nil diff --git a/app/models/favorite.rb b/app/models/favorite.rb index 9d312519..e96b4a58 100644 --- a/app/models/favorite.rb +++ b/app/models/favorite.rb @@ -11,4 +11,6 @@ class Favorite < ApplicationRecord belongs_to :store belongs_to :user + + validates :store_id, uniqueness: {scope: :user_id} end diff --git a/app/models/user.rb b/app/models/user.rb index e160233e..762206b4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,6 +40,7 @@ class User < ApplicationRecord has_many :stores, through: :user_stores has_many :created_stores, class_name: 'Store', foreign_key: :created_by_id, inverse_of: :created_by has_many :status_crowdsource_users + has_many :favorites has_one :api_key has_secure_token :store_owner_code diff --git a/app/resources/api/v1/favorite_resource.rb b/app/resources/api/v1/favorite_resource.rb new file mode 100644 index 00000000..932dc9ab --- /dev/null +++ b/app/resources/api/v1/favorite_resource.rb @@ -0,0 +1,21 @@ +module Api + module V1 + class FavoriteResource < ApplicationResource + caching + + attributes :store_id, :created_at + + has_one :user + has_one :store + + filters :user, :store + + def self.records(options = {}) + current_user = options[:context][:current_user] + current_user&.favorites + end + + exclude_links :default + end + end +end diff --git a/app/serializers/favorite_serializer.rb b/app/serializers/favorite_serializer.rb new file mode 100644 index 00000000..6f017cc3 --- /dev/null +++ b/app/serializers/favorite_serializer.rb @@ -0,0 +1,40 @@ +# == Schema Information +# +# Table name: stores +# +# id :bigint not null, primary key +# name :string +# group :string +# street :string +# city :string +# district :string +# country :string +# zip_code :string +# latitude :float +# longitude :float +# capacity :integer +# details :text +# store_type :integer default("1"), not null +# created_at :datetime not null +# updated_at :datetime not null +# lonlat :geometry point, 0 +# state :integer default("1") +# reason_to_delete :text +# open :boolean default("true") +# created_by_id :bigint +# updated_by_id :bigint +# from_osm :boolean default("false") +# original_id :bigint +# source :string +# make_phone_calls :boolean default("false") +# phone_call_interval :integer default("60") +# municipality :string +# + +class FavoriteSerializer + include FastJsonapi::ObjectSerializer + set_key_transform :dash + set_type :favorites + + attributes :store_id, :user_id +end diff --git a/config/routes.rb b/config/routes.rb index c7f18d01..865acfec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,6 +34,8 @@ jsonapi_resources :status_crowdsources, only: [:index] do end jsonapi_resources :status_generals, only: [:index] do end jsonapi_resources :random_status_generals, only: [:index] do end + jsonapi_resources :favorites, only: [:index, :create, :destroy] do end + get 'beach-status', to: 'beaches#index' get 'beach-general-status', to: 'beaches#general_status' diff --git a/db/migrate/20200628215106_create_favorites.rb b/db/migrate/20200628215106_create_favorites.rb index 6de45b1f..ef5e5236 100644 --- a/db/migrate/20200628215106_create_favorites.rb +++ b/db/migrate/20200628215106_create_favorites.rb @@ -5,6 +5,8 @@ def change t.references :user, null: false, foreign_key: true t.timestamps + + t.index [:store_id, :user_id] end end end diff --git a/db/schema.rb b/db/schema.rb index 50168f29..4d7fbca2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -90,6 +90,7 @@ t.bigint "user_id", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.index ["store_id", "user_id"], name: "index_favorites_on_store_id_and_user_id" t.index ["store_id"], name: "index_favorites_on_store_id" t.index ["user_id"], name: "index_favorites_on_user_id" end From 41ccdfae2d766b75f8f34f65871dd8e5cc070d4e Mon Sep 17 00:00:00 2001 From: Tiago Santos <santos.tiago@gmail.com> Date: Mon, 29 Jun 2020 00:24:39 +0100 Subject: [PATCH 04/14] Lists users' favorites on login in --- app/controllers/api/v1/auth_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 3892ed65..26dab6dc 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -40,7 +40,7 @@ def login # rubocop:disable Rails/SkipsModelValidations User.where.not(id: user.id).where(app_uuid: user.app_uuid).update_all(app_uuid: nil) # rubocop:enable Rails/SkipsModelValidations - render json: {success: 'login successful'}, status: :ok + render json: FavoriteSerializer.new(user.favorites).serialized_json, status: :ok else render json: {error: 'wrong password'}, status: :unauthorized end From 8f52319c8730f53b769021e8b96eb54cb07c4fd2 Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Mon, 29 Jun 2020 09:15:08 +0100 Subject: [PATCH 05/14] Makes sure favorites index on store_id and user_id are unique --- db/migrate/20200629081037_set_index_unique_on_favorites.rb | 6 ++++++ db/schema.rb | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20200629081037_set_index_unique_on_favorites.rb diff --git a/db/migrate/20200629081037_set_index_unique_on_favorites.rb b/db/migrate/20200629081037_set_index_unique_on_favorites.rb new file mode 100644 index 00000000..ba032dd0 --- /dev/null +++ b/db/migrate/20200629081037_set_index_unique_on_favorites.rb @@ -0,0 +1,6 @@ +class SetIndexUniqueOnFavorites < ActiveRecord::Migration[6.0] + def change + remove_index :favorites, name: :index_favorites_on_store_id_and_user_id + add_index :favorites, [:store_id, :user_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 4d7fbca2..7f6d64ac 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: 2020_06_28_215106) do +ActiveRecord::Schema.define(version: 2020_06_29_081037) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -90,7 +90,7 @@ t.bigint "user_id", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false - t.index ["store_id", "user_id"], name: "index_favorites_on_store_id_and_user_id" + t.index ["store_id", "user_id"], name: "index_favorites_on_store_id_and_user_id", unique: true t.index ["store_id"], name: "index_favorites_on_store_id" t.index ["user_id"], name: "index_favorites_on_user_id" end From 65893ce04e5955d00102d3e8536635a3a06d6edf Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Mon, 29 Jun 2020 11:11:36 +0100 Subject: [PATCH 06/14] use different status code --- app/controllers/api/v1/auth_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 26dab6dc..30f62a4b 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -5,7 +5,7 @@ class AuthController < ApiController def register if User.find_by(email: @attrs[:email]) || @attrs[:email].blank? - render json: {error: 'email already registered'}, status: :unauthorized and return + render json: {error: 'email already registered'}, status: :forbidden and return end new_user = nil @@ -42,10 +42,10 @@ def login # rubocop:enable Rails/SkipsModelValidations render json: FavoriteSerializer.new(user.favorites).serialized_json, status: :ok else - render json: {error: 'wrong password'}, status: :unauthorized + render json: {error: 'wrong password'}, status: :forbidden end rescue StandardError - render json: {error: 'authentication failed'}, status: :unauthorized + render json: {error: 'authentication failed'}, status: :forbidden end def logout @@ -53,7 +53,7 @@ def logout context[:current_user].update(app_uuid: "#{context[:current_user].app_uuid}_old_#{Time.current.to_i}") render json: {success: 'user logged out'}, status: :ok else - render json: {error: 'user not logged in'}, status: :unauthorized + render json: {error: 'user not logged in'}, status: :forbidden end end From 3b11bf5aeaaf2b6a36c721f3ede756e2b2766f5d Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 2 Jul 2020 10:47:54 +0100 Subject: [PATCH 07/14] don't verify authenticity token --- app/controllers/api/v1/auth_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 30f62a4b..2e81c658 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -2,6 +2,7 @@ module Api module V1 class AuthController < ApiController before_action :set_attrs + skip_before_action :verify_authenticity_token def register if User.find_by(email: @attrs[:email]) || @attrs[:email].blank? From 15737e80101cc3cae87a849d99bd65cfdb06f361 Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 2 Jul 2020 11:00:59 +0100 Subject: [PATCH 08/14] enable emails with sendgrid ons taging --- config/environments/staging.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 20ee76fe..4f49043e 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -104,4 +104,15 @@ # config.active_record.database_selector = { delay: 2.seconds } # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session + config.action_mailer.default_url_options = {host: 'posso-ir-staging.herokuapp.com'} + + ActionMailer::Base.smtp_settings = { + :user_name => ENV['SENDGRID_USERNAME'], + :password => ENV['SENDGRID_PASSWORD'], + :domain => 'yourdomain.com', + :address => 'smtp.sendgrid.net', + :port => 587, + :authentication => :plain, + :enable_starttls_auto => true + } end From 4f18f102d31e2499539b21a2f6b9b32a4eae0a30 Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 2 Jul 2020 22:44:25 +0100 Subject: [PATCH 09/14] confirm users when created on staging --- app/controllers/api/v1/auth_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 2e81c658..218eb1a1 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -27,6 +27,8 @@ def register if new_user.errors.any? render json: {error: "unable to create user: #{new_user.errors.full_messages.join(', ')}"}, status: :conflict else + # confirm user straight away if using staging + new_user.confirm if Rails.env.staging? render json: {success: 'User created successfully'}, status: :created end end From 791118ddf3431a54a023d523e36b92228162db5d Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 2 Jul 2020 23:00:56 +0100 Subject: [PATCH 10/14] adds environments --- .rubocop.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index ac71352a..f85d993b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -100,3 +100,10 @@ Style/HashTransformKeys: Style/HashTransformValues: Enabled: true + +Rails/UnknownEnv: + Environments: + - production + - development + - test + - staging From 91c3e615df561819bc93b5864687803f20a7802b Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Sun, 5 Jul 2020 22:50:42 +0100 Subject: [PATCH 11/14] Enables editing season start and season end --- app/views/beaches/_form.html.erb | 19 +++++++++++++++---- config/locales/pt.yml | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/views/beaches/_form.html.erb b/app/views/beaches/_form.html.erb index b490bbd3..e4b701d5 100644 --- a/app/views/beaches/_form.html.erb +++ b/app/views/beaches/_form.html.erb @@ -127,8 +127,19 @@ <%= form.fields_for :beach_configuration do |builder| %> <div class="form-row"> <div class="form-group col-md-6"> - <%= builder.label :quality_flag, class: "col-sm-4 col-form-label" %> - <%= builder.check_box :quality_flag, class: "form-control" %> + <%= builder.label :season_start, class: "col-sm-4 col-form-label" %> + <%= builder.date_field :season_start, class: "form-control" %> + </div> + <div class="form-group col-md-6"> + <%= builder.label :season_end, class: "col-sm-6 col-form-label" %> + <%= builder.date_field :season_end, class: "form-control" %> + </div> + </div> + + <div class="form-row"> + <div class="form-group col-md-6"> + <%= builder.label :water_classification, class: "col-sm-8 col-form-label" %> + <%= builder.text_field :water_classification, class: "form-control" %> </div> <div class="form-group col-md-6"> <%= builder.label :sapo_code, class: "col-sm-6 col-form-label" %> @@ -208,8 +219,8 @@ <%= builder.check_box :bathing_support, class: "form-control" %> </div> <div class="form-group col-md-4"> - <%= builder.label :water_classification, class: "col-sm-8 col-form-label" %> - <%= builder.text_field :water_classification, class: "form-control" %> + <%= builder.label :quality_flag, class: "col-sm-6 col-form-label" %> + <%= builder.check_box :quality_flag, class: "form-control" %> </div> </div> <% end %> diff --git a/config/locales/pt.yml b/config/locales/pt.yml index a7221c8a..5b871043 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -252,7 +252,7 @@ pt: <strong>Activa</strong>: Praia disponível na aplicação.<br> <strong>Marcada para remoção</strong>: Remoção será revista e confirmada por um administrador." info_deleting: 'NOTA: Quando marcar uma praia para remoção por favor escreva o porquê dessa marcação no campo de detalhes.' - beaches_attributes: 'Atributos das praias' + beach_attributes: 'Atributos das praias' status_crowdsource_users: index: title: 'Estados reportados' From a95141d07461f4299ee8db413f23e7fe96c88a7d Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 9 Jul 2020 09:35:34 +0100 Subject: [PATCH 12/14] Use stores serializer instead of specific favorites serializer --- app/controllers/api/v1/auth_controller.rb | 2 +- .../api/v1/favorites_controller.rb | 6 +-- app/models/user.rb | 1 + app/serializers/favorite_serializer.rb | 40 ------------------- 4 files changed, 5 insertions(+), 44 deletions(-) delete mode 100644 app/serializers/favorite_serializer.rb diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 218eb1a1..3fd0020e 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -43,7 +43,7 @@ def login # rubocop:disable Rails/SkipsModelValidations User.where.not(id: user.id).where(app_uuid: user.app_uuid).update_all(app_uuid: nil) # rubocop:enable Rails/SkipsModelValidations - render json: FavoriteSerializer.new(user.favorites).serialized_json, status: :ok + render json: StoreSerializer.new(user.favorite_stores).serialized_json, status: :ok else render json: {error: 'wrong password'}, status: :forbidden end diff --git a/app/controllers/api/v1/favorites_controller.rb b/app/controllers/api/v1/favorites_controller.rb index 2d1e3a3e..a0fb03db 100644 --- a/app/controllers/api/v1/favorites_controller.rb +++ b/app/controllers/api/v1/favorites_controller.rb @@ -7,7 +7,7 @@ def create favorite = Favorite.new(store: @store, user: @user) if favorite.save - render json: FavoriteSerializer.new(favorite).serialized_json, status: :created + render json: StoreSerializer.new(favorite.store).serialized_json, status: :created else render json: {errors: favorite.errors.full_messages.join(', ')}, status: :conflict end @@ -30,8 +30,8 @@ def destroy end def index - @favorites = context[:current_user].favorites - super + favorites = context[:current_user].favorite_stores + render json: StoreSerializer.new(favorites).serialized_json end private diff --git a/app/models/user.rb b/app/models/user.rb index 762206b4..c8e52df9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -41,6 +41,7 @@ class User < ApplicationRecord has_many :created_stores, class_name: 'Store', foreign_key: :created_by_id, inverse_of: :created_by has_many :status_crowdsource_users has_many :favorites + has_many :favorite_stores, through: :favorites, source: :store has_one :api_key has_secure_token :store_owner_code diff --git a/app/serializers/favorite_serializer.rb b/app/serializers/favorite_serializer.rb deleted file mode 100644 index 6f017cc3..00000000 --- a/app/serializers/favorite_serializer.rb +++ /dev/null @@ -1,40 +0,0 @@ -# == Schema Information -# -# Table name: stores -# -# id :bigint not null, primary key -# name :string -# group :string -# street :string -# city :string -# district :string -# country :string -# zip_code :string -# latitude :float -# longitude :float -# capacity :integer -# details :text -# store_type :integer default("1"), not null -# created_at :datetime not null -# updated_at :datetime not null -# lonlat :geometry point, 0 -# state :integer default("1") -# reason_to_delete :text -# open :boolean default("true") -# created_by_id :bigint -# updated_by_id :bigint -# from_osm :boolean default("false") -# original_id :bigint -# source :string -# make_phone_calls :boolean default("false") -# phone_call_interval :integer default("60") -# municipality :string -# - -class FavoriteSerializer - include FastJsonapi::ObjectSerializer - set_key_transform :dash - set_type :favorites - - attributes :store_id, :user_id -end From 93ccd0c3e9533752857dcb7aa7f225e9906009ce Mon Sep 17 00:00:00 2001 From: Simao Belchior <simaobelchior@gmail.com> Date: Thu, 9 Jul 2020 20:41:37 +0100 Subject: [PATCH 13/14] include email and user's name, plus favorite stores and metrics --- app/controllers/api/v1/auth_controller.rb | 4 +++- app/controllers/api/v1/favorites_controller.rb | 2 +- app/models/user.rb | 2 +- app/serializers/user_serializer.rb | 17 +++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 app/serializers/user_serializer.rb diff --git a/app/controllers/api/v1/auth_controller.rb b/app/controllers/api/v1/auth_controller.rb index 3fd0020e..f23b4d31 100644 --- a/app/controllers/api/v1/auth_controller.rb +++ b/app/controllers/api/v1/auth_controller.rb @@ -42,8 +42,10 @@ def login # Invalidate other users on the same devise # rubocop:disable Rails/SkipsModelValidations User.where.not(id: user.id).where(app_uuid: user.app_uuid).update_all(app_uuid: nil) + options = {} + options[:include] = [:stores] # rubocop:enable Rails/SkipsModelValidations - render json: StoreSerializer.new(user.favorite_stores).serialized_json, status: :ok + render json: UserSerializer.new(user, options).serialized_json, status: :ok else render json: {error: 'wrong password'}, status: :forbidden end diff --git a/app/controllers/api/v1/favorites_controller.rb b/app/controllers/api/v1/favorites_controller.rb index a0fb03db..ad251dac 100644 --- a/app/controllers/api/v1/favorites_controller.rb +++ b/app/controllers/api/v1/favorites_controller.rb @@ -30,7 +30,7 @@ def destroy end def index - favorites = context[:current_user].favorite_stores + favorites = context[:current_user].stores render json: StoreSerializer.new(favorites).serialized_json end diff --git a/app/models/user.rb b/app/models/user.rb index c8e52df9..a344e76c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -41,7 +41,7 @@ class User < ApplicationRecord has_many :created_stores, class_name: 'Store', foreign_key: :created_by_id, inverse_of: :created_by has_many :status_crowdsource_users has_many :favorites - has_many :favorite_stores, through: :favorites, source: :store + has_many :stores, through: :favorites, source: :store has_one :api_key has_secure_token :store_owner_code diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb new file mode 100644 index 00000000..30a8e41f --- /dev/null +++ b/app/serializers/user_serializer.rb @@ -0,0 +1,17 @@ +class UserSerializer + include FastJsonapi::ObjectSerializer + set_key_transform :dash + set_type :user + + attribute :email + attribute :name + attribute :reports_made do + rand(1..100) + end + attribute :reporter_ranking do + rand(1..100) + end + + has_many :stores, type: :stores, serializer: StoreSerializer +end + From e2c47707dff950bc5ba883d1851318c3679c42f5 Mon Sep 17 00:00:00 2001 From: Tiago Santos <santos.tiago@gmail.com> Date: Thu, 9 Jul 2020 23:55:47 +0200 Subject: [PATCH 14/14] Deleting a favorite now takes the store_id instead of the favorite_id --- app/controllers/api/v1/favorites_controller.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/controllers/api/v1/favorites_controller.rb b/app/controllers/api/v1/favorites_controller.rb index ad251dac..030d2fb7 100644 --- a/app/controllers/api/v1/favorites_controller.rb +++ b/app/controllers/api/v1/favorites_controller.rb @@ -16,11 +16,8 @@ def create def destroy return if no_user - favorite = Favorite.find_by id: params[:id] + favorite = Favorite.find_by user_id: @user.id, store_id: params[:id] return render json: {errors: "Couldn't find favorite"}, status: :not_found unless favorite - unless @user == favorite.user - return render json: {errors: "Favorite doesn't belong to user"}, status: :forbidden - end if favorite.destroy render json: {}, status: :no_content