diff --git a/.rubocop.yml b/.rubocop.yml index fffba2e..117c496 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -13,6 +13,12 @@ Style/AndOr: StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or' Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false + +Style/RegexpLiteral: + Enabled: false + AllCops: Exclude: - 'bin/**/*' diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/custom.js index 0c955ee..7cc98ef 100644 --- a/app/assets/javascripts/custom.js +++ b/app/assets/javascripts/custom.js @@ -1,4 +1,4 @@ -$(document).ready(function() { +$(document).ready(function() { var slider = ["ALERT","SMART","COMPETITIVE"]; $("#animate").addClass('animated infinite fadeInDown'); $("#animate").text(slider[0]); @@ -118,6 +118,8 @@ function openNav() { document.getElementById("mySidenav").style.width = "0"; } +$('[data-toggle="tooltip"]').tooltip(); + function showListWiseGraph(id, index){ var isExpanded = $("#collection" + index).attr("aria-expanded"); diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 2c78916..a0ac4d9 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -969,11 +969,11 @@ margin-top:4%; text-decoration:none; color:white; font-weight:700; - font-size:22px; + font-size:17px; } .collections-navbar-right-links{ a{ - font-size:22px; + font-size:17px; font-family: Palatino, serif; } } @@ -987,11 +987,13 @@ margin-top:4%; padding-left:10%; a{ color: white; + font-size: 15px; } } .domain-delete{ padding-left:10%; color:white; + font-size: 14px; font-style:italic; } } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 421fef8..8130a6c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,10 +2,16 @@ class ApplicationController < ActionController::Base include Pundit protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? + rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end + + def user_not_authorized + flash[:alert] = 'You are not authorized to perform this action.' + redirect_back(fallback_location: root_path) + end end diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 98277e3..5f9376e 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -7,7 +7,9 @@ def create end def destroy - Collections::Delete.call(params[:id], current_user) + collection = Collection.find(params[:id]) + authorize(collection, :destroy?) + Collections::Delete.call(collection, current_user) redirect_to root_url end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 9894cc6..304805a 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -8,7 +8,6 @@ def index def create invite = Invite.new(invite_params) invite.save! - flash[:note] = 'Thank You for requesting an invitation to use RankHub. We will shortly send you an invitation code to register at RankHub' redirect_to static_invite_path end @@ -17,7 +16,7 @@ def approve invite = Invite.find(params[:id]) invite.update(approved: true) UserMailer.invite_email(invite).deliver_later - redirect_to admin_analytics_path + redirect_to admin_invites_path end private diff --git a/app/models/collection.rb b/app/models/collection.rb index f5ba4ab..d3fbf86 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -1,6 +1,8 @@ class Collection < ApplicationRecord belongs_to :user + has_many :collection_websites, dependent: :destroy has_many :websites, through: :collection_websites + validates :name, presence: true end diff --git a/app/models/website.rb b/app/models/website.rb index 675e000..298fa13 100644 --- a/app/models/website.rb +++ b/app/models/website.rb @@ -1,10 +1,13 @@ class Website < ApplicationRecord + before_validation :add_protocol_to_website + + validates :url, url: true + validates :url, uniqueness: true + has_many :collection_websites has_many :collections, through: :collection_websites has_many :alexaranks, dependent: :destroy - validates :url, presence: true - validates :url, uniqueness: true - + def fetch_alexa_rank_and_update! rank = Alexarank.fetch_rank(domain: url.to_s) alexaranks.create(rank: rank) @@ -33,5 +36,16 @@ def fetch_meta_description description = page.search("meta[name='description']").map { |n| n['content'] } update(description: description) end -end + private + + def add_protocol_to_website + return if protocol_present? + self.url = "http://#{url}" + end + + def protocol_present? + return false if url.blank? + url[/^http:\/\//] || url[/^https:\/\//] + end +end diff --git a/app/policies/collection_policy.rb b/app/policies/collection_policy.rb new file mode 100644 index 0000000..b443f81 --- /dev/null +++ b/app/policies/collection_policy.rb @@ -0,0 +1,5 @@ +class CollectionPolicy < ApplicationPolicy + def destroy? + record.user == user + end +end diff --git a/app/services/collections/delete.rb b/app/services/collections/delete.rb index a1cffb0..a2fa2f9 100644 --- a/app/services/collections/delete.rb +++ b/app/services/collections/delete.rb @@ -1,11 +1,11 @@ module Collections class Delete - def self.call(collection_id, user) - new(collection_id, user).call + def self.call(collection, user) + new(collection, user).call end - def initialize(collection_id, user) - @collection = Collection.find(collection_id) + def initialize(collection, user) + @collection = collection @user = user end diff --git a/app/services/websites/create.rb b/app/services/websites/create.rb index cc3be08..f2cb279 100644 --- a/app/services/websites/create.rb +++ b/app/services/websites/create.rb @@ -14,9 +14,11 @@ def initialize(params, user) end def call - url_exist = Website.find_by(url: params[:website][:url]) + url = params[:website][:url] + url = "http://#{url}" unless protocol_given?(url) + url_exist = Website.find_by(url: url) if url_exist && params[:website][:collection_id] - CollectionWebsite.where(collection: params[:website][:collection_id], website: url_exist).first_or_create + CollectionWebsite.where(collection: params[:website][:collection_id], website: url_exist).first_or_create else create_website find_or_create_user @@ -48,6 +50,9 @@ def fetch_rank return if website.alexaranks.any? FetchRankJob.perform_later(website) end + + def protocol_given?(url) + (url.start_with? 'http://') || (url.start_with? 'https://') + end end end - diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb new file mode 100644 index 0000000..2008f34 --- /dev/null +++ b/app/validators/url_validator.rb @@ -0,0 +1,22 @@ +class UrlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + uri = URI.parse(value) + record.errors.add(attribute, 'is invalid') unless valid_url?(uri) + end + + private + + def valid_url?(uri) + uri && valid_host?(uri.host) + rescue URI::InvalidURIError + false + end + + def valid_host?(host) + host.present? && valid_characters?(host) + end + + def valid_characters?(host) + !host[/[\s\!\\"$%&'\(\)*+_,:;<=>?@\[\]^|£§°ç\/]/] && host.include?('.') + end +end diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index 0faa4c6..674a4c5 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -1,30 +1,27 @@ \ No newline at end of file diff --git a/app/views/static_pages/_collection.html.erb b/app/views/static_pages/_collection.html.erb index e91d3d0..f48eab6 100644 --- a/app/views/static_pages/_collection.html.erb +++ b/app/views/static_pages/_collection.html.erb @@ -1,7 +1,3 @@ - - - - @@ -29,71 +25,62 @@ +
+ ☰ + +
-
- <% if flash[:error] %> -
- <%= flash[:error]%> +
+ <% if flash[:error] %> +
+ <%= flash[:error]%> +
+ <% end %>
- <% end %> -
-
- -
- +
+
<% else %> <%= render 'check' %> - <% end %> - + <% end %> - \ No newline at end of file + \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 76e5988..1281ad0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -51,7 +51,6 @@ t.integer "website_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "descript" t.index ["website_id", "created_at"], name: "index_alexaranks_on_website_id_and_created_at", unique: true, using: :btree t.index ["website_id"], name: "index_alexaranks_on_website_id", using: :btree end diff --git a/db/seeds.rb b/db/seeds.rb index f7df508..a71c7f0 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,12 +5,10 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) -user = User.first -urls = ['csnipp.com', 'redpanthers.co', 'google.com'] -urls.each do |url| - user.websites.create!(url: url) -end +user = User.create!(name: 'abc', email: 'abc@mail.com', password: '123456', password_confirmation: '123456') +collection = user.collections.create!(name: 'First Collection') +collection.websites.create!(url: 'https://www.owler.com') Website.all.each do |site| 20.times do |n| diff --git a/test/services/websites/create_test.rb b/test/services/websites/create_test.rb index 0350169..0a0b959 100644 --- a/test/services/websites/create_test.rb +++ b/test/services/websites/create_test.rb @@ -6,32 +6,47 @@ class CreateTest < ActiveSupport::TestCase user = users(:hari) collection = user.collections.create!(name: 'My Collection') + params = { website: { url: 'http://twitter.com', collection_id: collection.id } } + + Websites::Create.call(params, user) + + user.reload + assert_equal 1, user.websites.count, 'websites_count' + assert_equal 1, Website.count + assert_equal ['http://twitter.com'], user.websites.pluck(:url) + assert_equal ['http://twitter.com'], collection.websites.pluck(:url) + end + + test 'adding a new website without http prefix' do + user = users(:hari) + collection = user.collections.create!(name: 'My Collection') + params = { website: { url: 'twitter.com', collection_id: collection.id } } Websites::Create.call(params, user) user.reload - assert_equal 1, user.site_number, 'site number' + assert_equal 1, user.websites.count, 'websites_count' assert_equal 1, Website.count - assert_equal ['twitter.com'], user.websites.pluck(:url) - assert_equal ['twitter.com'], collection.websites.pluck(:url) + assert_equal ['http://twitter.com'], user.websites.pluck(:url) + assert_equal ['http://twitter.com'], collection.websites.pluck(:url) end test 'does not create duplicate website' do user = users(:hari) collection = user.collections.create!(name: 'My Collection') - Website.create!(url: 'twitter.com') + Website.create!(url: 'http://twitter.com') - params = { website: { url: 'twitter.com', collection_id: collection.id } } + params = { website: { url: 'http://twitter.com', collection_id: collection.id } } assert_no_difference 'Website.count' do Websites::Create.call(params, user) end user.reload - assert_equal 1, user.site_number - assert_equal ['twitter.com'], user.websites.pluck(:url) - assert_equal ['twitter.com'], collection.websites.pluck(:url) + assert_equal 1, user.websites.count + assert_equal ['http://twitter.com'], user.websites.pluck(:url) + assert_equal ['http://twitter.com'], collection.websites.pluck(:url) end end end