Skip to content

Commit

Permalink
Merge pull request #88 from simaob/release/login-and-favorites
Browse files Browse the repository at this point in the history
Release/login and favorites
  • Loading branch information
simaob committed Jul 10, 2020
2 parents fe85277 + 6f818a1 commit d82814d
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 61 deletions.
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,10 @@ Style/HashTransformKeys:

Style/HashTransformValues:
Enabled: true

Rails/UnknownEnv:
Environments:
- production
- development
- test
- staging
106 changes: 53 additions & 53 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 10 additions & 5 deletions app/controllers/api/v1/auth_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ 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?
render json: {error: 'email already registered'}, status: :unauthorized and return
render json: {error: 'email already registered'}, status: :forbidden and return
end

new_user = nil
Expand All @@ -26,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
Expand All @@ -39,21 +42,23 @@ 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: {success: 'login successful'}, status: :ok
render json: UserSerializer.new(user, options).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
if context[:current_user]&.email.present?
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

Expand Down
53 changes: 53 additions & 0 deletions app/controllers/api/v1/favorites_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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: StoreSerializer.new(favorite.store).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 user_id: @user.id, store_id: params[:id]
return render json: {errors: "Couldn't find favorite"}, status: :not_found unless favorite

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].stores
render json: StoreSerializer.new(favorites).serialized_json
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
5 changes: 3 additions & 2 deletions app/controllers/api_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions app/models/favorite.rb
Original file line number Diff line number Diff line change
@@ -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
#
class Favorite < ApplicationRecord
belongs_to :store
belongs_to :user

validates :store_id, uniqueness: {scope: :user_id}
end
2 changes: 2 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ 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_many :stores, through: :favorites, source: :store
has_one :api_key

has_secure_token :store_owner_code
Expand Down
21 changes: 21 additions & 0 deletions app/resources/api/v1/favorite_resource.rb
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions app/serializers/user_serializer.rb
Original file line number Diff line number Diff line change
@@ -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

11 changes: 11 additions & 0 deletions config/environments/staging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
Loading

0 comments on commit d82814d

Please sign in to comment.