friendship.befriendee = @new_friend
if current_user.is_friends_with?(@new_friend)
flash[:warning] = t "friendships.make_friend.already_a_friend", :name => @new_friend.display_name
+ elsif current_user.friendships.where("created_at >= ?", Time.now.getutc - 1.hour).count >= current_user.max_friends_per_hour
+ flash.now[:error] = t "friendships.make_friend.limit_exceeded"
elsif friendship.save
flash[:notice] = t "friendships.make_friend.success", :name => @new_friend.display_name
UserMailer.friendship_notification(friendship).deliver_later
max_messages.clamp(0, Settings.max_messages_per_hour)
end
+ def max_friends_per_hour
+ account_age_in_seconds = Time.now.utc - creation_time
+ account_age_in_hours = account_age_in_seconds / 3600
+ recent_friends = friendships.where("created_at >= ?", Time.now.utc - 3600).count
+ active_reports = issues.with_status(:open).sum(:reports_count)
+ max_messages = account_age_in_hours.ceil + recent_friends - active_reports * 10
+ max_messages.clamp(0, Settings.max_friends_per_hour)
+ end
+
private
def set_defaults
success: "%{name} is now your friend!"
failed: "Sorry, failed to add %{name} as a friend."
already_a_friend: "You are already friends with %{name}."
+ limit_exceeded: "You have friended a lot of users recently. Please wait a while before trying to friend any more."
remove_friend:
heading: "Unfriend %{user}?"
button: "Unfriend"
user_block_periods: [0, 1, 3, 6, 12, 24, 48, 96, 168, 336, 731, 4383, 8766, 87660]
# Rate limit for message sending
max_messages_per_hour: 60
+# Rate limit for friending
+max_friends_per_hour: 60
# Domain for handling message replies
#messages_domain: "messages.openstreetmap.org"
# Geonames authentication details
--- /dev/null
+class AddTimeToFriendships < ActiveRecord::Migration[6.0]
+ disable_ddl_transaction!
+
+ def change
+ add_column :friends, :created_at, :datetime
+ add_index :friends, [:user_id, :created_at], :algorithm => :concurrently
+ remove_index :friends, :column => :user_id, :name => "friends_user_id_idx"
+ end
+end
CREATE TABLE public.friends (
id bigint NOT NULL,
user_id bigint NOT NULL,
- friend_user_id bigint NOT NULL
+ friend_user_id bigint NOT NULL,
+ created_at timestamp without time zone
);
CREATE INDEX diary_entry_user_id_created_at_index ON public.diary_entries USING btree (user_id, created_at);
---
--- Name: friends_user_id_idx; Type: INDEX; Schema: public; Owner: -
---
-
-CREATE INDEX friends_user_id_idx ON public.friends USING btree (user_id);
-
-
--
-- Name: gpx_file_tags_gpxid_idx; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_diary_entry_subscriptions_on_diary_entry_id ON public.diary_entry_subscriptions USING btree (diary_entry_id);
+--
+-- Name: index_friends_on_user_id_and_created_at; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_friends_on_user_id_and_created_at ON public.friends USING btree (user_id, created_at);
+
+
--
-- Name: index_issue_comments_on_issue_id; Type: INDEX; Schema: public; Owner: -
--
('20201006213836'),
('20201006220807'),
('20201214144017'),
+('20210511104518'),
('21'),
('22'),
('23'),