bsky page scanning auditing
This commit is contained in:
@@ -203,6 +203,27 @@ module Domain::UsersHelper
|
||||
due_for_scan ? "fa-hourglass-half" : "fa-check"
|
||||
end
|
||||
|
||||
if user.is_a?(Domain::User::BlueskyUser) && can_view_timestamps
|
||||
rows << StatRow.new(
|
||||
name: "Page scanned",
|
||||
value: user.profile_scan,
|
||||
link_to:
|
||||
user.last_scan_log_entry && log_entry_path(user.last_scan_log_entry),
|
||||
fa_icon_class: icon_for.call(user.profile_scan.due?),
|
||||
hover_title: user.profile_scan.interval.inspect,
|
||||
)
|
||||
|
||||
rows << StatRow.new(
|
||||
name: "Posts scanned",
|
||||
value: user.posts_scan,
|
||||
link_to:
|
||||
user.last_posts_scan_log_entry &&
|
||||
log_entry_path(user.last_posts_scan_log_entry),
|
||||
fa_icon_class: icon_for.call(user.posts_scan.due?),
|
||||
hover_title: user.posts_scan.interval.inspect,
|
||||
)
|
||||
end
|
||||
|
||||
if user.is_a?(Domain::User::FaUser) && can_view_timestamps
|
||||
if can_view_log_entries && hle = user.guess_last_user_page_log_entry
|
||||
rows << StatRow.new(
|
||||
|
||||
@@ -29,6 +29,7 @@ class Domain::Bluesky::Job::ScanPostsJob < Domain::Bluesky::Job::Base
|
||||
end
|
||||
|
||||
scan_user_posts(user)
|
||||
user.last_posts_scan_log_entry = first_log_entry
|
||||
logger.info(format_tags("completed posts scan"))
|
||||
ensure
|
||||
user.save! if user
|
||||
@@ -109,6 +110,7 @@ class Domain::Bluesky::Job::ScanPostsJob < Domain::Bluesky::Job::Base
|
||||
url = cursor ? "#{posts_url}&cursor=#{cursor}" : posts_url
|
||||
|
||||
response = http_client.get(url)
|
||||
|
||||
num_pages += 1
|
||||
if response.status_code != 200
|
||||
fatal_error(
|
||||
|
||||
@@ -38,6 +38,7 @@ class Domain::Bluesky::Job::ScanUserJob < Domain::Bluesky::Job::Base
|
||||
"https://bsky.social/xrpc/com.atproto.repo.getRecord?repo=#{user.did}&collection=app.bsky.actor.profile&rkey=self"
|
||||
|
||||
response = http_client.get(profile_url)
|
||||
user.last_scan_log_entry = response.log_entry
|
||||
|
||||
if response.status_code != 200
|
||||
fatal_error(
|
||||
|
||||
@@ -6,7 +6,13 @@ class Domain::User::BlueskyUser < Domain::User
|
||||
due_timestamp :scanned_posts_at, 3.years
|
||||
|
||||
has_created_posts! Domain::Post::BlueskyPost
|
||||
has_faved_posts! Domain::Post::BlueskyPost
|
||||
# TODO - when we scrape liked posts, add this back in
|
||||
# has_faved_posts! Domain::Post::BlueskyPost
|
||||
|
||||
belongs_to :last_scan_log_entry, class_name: "HttpLogEntry", optional: true
|
||||
belongs_to :last_posts_scan_log_entry,
|
||||
class_name: "HttpLogEntry",
|
||||
optional: true
|
||||
|
||||
enum :state,
|
||||
{ ok: "ok", account_disabled: "account_disabled", error: "error" },
|
||||
|
||||
6
app/views/domain/users/bsky/_overview_details.html.erb
Normal file
6
app/views/domain/users/bsky/_overview_details.html.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
<% cache [user, "overview_details"] do %>
|
||||
<div class="flex flex-col">
|
||||
<span class="font-medium italic text-slate-500">State</span>
|
||||
<span class=""><%= user.account_state_for_view %></span>
|
||||
</div>
|
||||
<% end %>
|
||||
34
app/views/domain/users/bsky/_stats.html.erb
Normal file
34
app/views/domain/users/bsky/_stats.html.erb
Normal file
@@ -0,0 +1,34 @@
|
||||
<section class="sky-section animated-shadow-sky divide-y">
|
||||
<h2 class="section-header">User Stats</h2>
|
||||
<% stat_rows_for_user(user).each do |stat_row| %>
|
||||
<% label = stat_row.name %>
|
||||
<% value = stat_row.value %>
|
||||
<% fa_icon_class = stat_row.fa_icon_class %>
|
||||
<div class="flex items-center px-4 py-2 gap-2">
|
||||
<span class="grow text-slate-900 truncate"><%= label %></span>
|
||||
<span class="text-slate-500 relative group">
|
||||
<% value_str = case value %>
|
||||
<% when Integer %>
|
||||
<% number_with_delimiter(value, delimiter: ",") %>
|
||||
<% when HasTimestampsWithDueAt::TimestampScanInfo %>
|
||||
<% value.ago_in_words %>
|
||||
<% else %>
|
||||
<% value %>
|
||||
<% end %>
|
||||
<% if stat_row.link_to %>
|
||||
<%= link_to value_str, stat_row.link_to, class: "blue-link" %>
|
||||
<% else %>
|
||||
<%= value_str %>
|
||||
<% end %>
|
||||
<% if fa_icon_class %>
|
||||
<i class="fa-solid <%= fa_icon_class %>"></i>
|
||||
<% end %>
|
||||
<% if stat_row.hover_title %>
|
||||
<div class="absolute hidden group-hover:block bg-slate-800 text-white text-sm rounded px-2 py-1 top-1/2 -translate-y-1/2 right-full mr-2 whitespace-nowrap">
|
||||
<%= stat_row.hover_title %>
|
||||
</div>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
11
db/migrate/20250812214415_create_bsky_user_last_scan.rb
Normal file
11
db/migrate/20250812214415_create_bsky_user_last_scan.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class CreateBskyUserLastScan < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
change_table :domain_users_bluesky_aux do |t|
|
||||
t.references :last_scan_log_entry,
|
||||
foreign_key: {
|
||||
to_table: :http_log_entries,
|
||||
},
|
||||
index: false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateBskyUserLastPostsScan < ActiveRecord::Migration[7.2]
|
||||
sig { void }
|
||||
def change
|
||||
change_table :domain_users_bluesky_aux do |t|
|
||||
t.references :last_posts_scan_log_entry,
|
||||
foreign_key: {
|
||||
to_table: :http_log_entries,
|
||||
},
|
||||
index: false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1955,7 +1955,9 @@ CREATE TABLE public.domain_users_bluesky_aux (
|
||||
posts_count integer,
|
||||
scanned_profile_at timestamp(6) without time zone,
|
||||
scanned_posts_at timestamp(6) without time zone,
|
||||
profile_raw jsonb DEFAULT '{}'::jsonb
|
||||
profile_raw jsonb DEFAULT '{}'::jsonb,
|
||||
last_scan_log_entry_id bigint,
|
||||
last_posts_scan_log_entry_id bigint
|
||||
);
|
||||
|
||||
|
||||
@@ -5523,6 +5525,14 @@ ALTER TABLE ONLY public.domain_user_job_event_add_tracked_objects
|
||||
ADD CONSTRAINT fk_rails_03ea351597 FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users_bluesky_aux fk_rails_095a111783; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_users_bluesky_aux
|
||||
ADD CONSTRAINT fk_rails_095a111783 FOREIGN KEY (last_posts_scan_log_entry_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users_fa_aux fk_rails_0d64d940cf; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5795,6 +5805,14 @@ ALTER TABLE ONLY public.domain_user_post_favs
|
||||
ADD CONSTRAINT fk_rails_c79733f291 FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users_bluesky_aux fk_rails_cdeabf49ad; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_users_bluesky_aux
|
||||
ADD CONSTRAINT fk_rails_cdeabf49ad FOREIGN KEY (last_scan_log_entry_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_favs fk_rails_ce892be9a6; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5866,6 +5884,8 @@ ALTER TABLE ONLY public.domain_twitter_tweets
|
||||
SET search_path TO "$user", public;
|
||||
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20250812214902'),
|
||||
('20250812214415'),
|
||||
('20250812211640'),
|
||||
('20250812182033'),
|
||||
('20250811172839'),
|
||||
|
||||
3
sorbet/rbi/dsl/application_controller.rbi
generated
3
sorbet/rbi/dsl/application_controller.rbi
generated
@@ -26,7 +26,10 @@ class ApplicationController
|
||||
include ::Webpacker::Helper
|
||||
include ::ActionController::Base::HelperMethods
|
||||
include ::ApplicationHelper
|
||||
include ::ActionView::Helpers::ContentExfiltrationPreventionHelper
|
||||
include ::ActionView::Helpers::UrlHelper
|
||||
include ::HelpersInterface
|
||||
include ::Domain::BlueskyPostHelper
|
||||
include ::LogEntriesHelper
|
||||
include ::Pundit::Authorization
|
||||
include ::Domain::UsersHelper
|
||||
|
||||
3
sorbet/rbi/dsl/devise_controller.rbi
generated
3
sorbet/rbi/dsl/devise_controller.rbi
generated
@@ -23,7 +23,10 @@ class DeviseController
|
||||
include ::Webpacker::Helper
|
||||
include ::ActionController::Base::HelperMethods
|
||||
include ::ApplicationHelper
|
||||
include ::ActionView::Helpers::ContentExfiltrationPreventionHelper
|
||||
include ::ActionView::Helpers::UrlHelper
|
||||
include ::HelpersInterface
|
||||
include ::Domain::BlueskyPostHelper
|
||||
include ::LogEntriesHelper
|
||||
include ::Pundit::Authorization
|
||||
include ::Domain::UsersHelper
|
||||
|
||||
174
sorbet/rbi/dsl/domain/user/bluesky_user.rbi
generated
174
sorbet/rbi/dsl/domain/user/bluesky_user.rbi
generated
@@ -533,6 +533,12 @@ class Domain::User::BlueskyUser
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersBlueskyAux) }
|
||||
def build_bluesky_aux(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_last_posts_scan_log_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def build_last_scan_log_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::Domain::UserAvatar) }
|
||||
def create_avatar(*args, &blk); end
|
||||
|
||||
@@ -545,18 +551,30 @@ class Domain::User::BlueskyUser
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::DomainUsersBlueskyAux) }
|
||||
def create_bluesky_aux!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_posts_scan_log_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_posts_scan_log_entry!(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_scan_log_entry(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(::HttpLogEntry) }
|
||||
def create_last_scan_log_entry!(*args, &blk); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User::BlueskyUser` class because it declared `has_many :faved_posts, through: :user_post_favs`.
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :faved_posts, through: :user_post_favs`.
|
||||
# 🔗 [Rails guide for `has_many_through` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association)
|
||||
sig { returns(::Domain::Post::BlueskyPost::PrivateCollectionProxy) }
|
||||
sig { returns(::Domain::Post::PrivateCollectionProxy) }
|
||||
def faved_posts; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::Post::BlueskyPost]).void }
|
||||
sig { params(value: T::Enumerable[::Domain::Post]).void }
|
||||
def faved_posts=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
@@ -601,6 +619,30 @@ class Domain::User::BlueskyUser
|
||||
sig { params(value: T::Enumerable[::Domain::User]).void }
|
||||
def followed_users=(value); end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def last_posts_scan_log_entry; end
|
||||
|
||||
sig { params(value: T.nilable(::HttpLogEntry)).void }
|
||||
def last_posts_scan_log_entry=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_previously_changed?; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def last_scan_log_entry; end
|
||||
|
||||
sig { params(value: T.nilable(::HttpLogEntry)).void }
|
||||
def last_scan_log_entry=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_changed?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_previously_changed?; end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def post_ids; end
|
||||
|
||||
@@ -621,12 +663,24 @@ class Domain::User::BlueskyUser
|
||||
sig { returns(T.nilable(::DomainUsersBlueskyAux)) }
|
||||
def reload_bluesky_aux; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_last_posts_scan_log_entry; end
|
||||
|
||||
sig { returns(T.nilable(::HttpLogEntry)) }
|
||||
def reload_last_scan_log_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_avatar; end
|
||||
|
||||
sig { void }
|
||||
def reset_bluesky_aux; end
|
||||
|
||||
sig { void }
|
||||
def reset_last_posts_scan_log_entry; end
|
||||
|
||||
sig { void }
|
||||
def reset_last_scan_log_entry; end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def user_post_creation_ids; end
|
||||
|
||||
@@ -1327,6 +1381,96 @@ class Domain::User::BlueskyUser
|
||||
sig { void }
|
||||
def json_attributes_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def last_posts_scan_log_entry_id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_was; end
|
||||
|
||||
sig { void }
|
||||
def last_posts_scan_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def last_scan_log_entry_id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_was; end
|
||||
|
||||
sig { void }
|
||||
def last_scan_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Time)) }
|
||||
def migrated_user_favs_at; end
|
||||
|
||||
@@ -1492,6 +1636,12 @@ class Domain::User::BlueskyUser
|
||||
sig { void }
|
||||
def restore_json_attributes!; end
|
||||
|
||||
sig { void }
|
||||
def restore_last_posts_scan_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_last_scan_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_migrated_user_favs_at!; end
|
||||
|
||||
@@ -1591,6 +1741,18 @@ class Domain::User::BlueskyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_json_attributes?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_last_posts_scan_log_entry_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_last_scan_log_entry_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Time), T.nilable(::Time)])) }
|
||||
def saved_change_to_migrated_user_favs_at; end
|
||||
|
||||
@@ -2179,6 +2341,12 @@ class Domain::User::BlueskyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_json_attributes?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_migrated_user_favs_at?; end
|
||||
|
||||
|
||||
114
sorbet/rbi/dsl/domain_users_bluesky_aux.rbi
generated
114
sorbet/rbi/dsl/domain_users_bluesky_aux.rbi
generated
@@ -1015,6 +1015,96 @@ class DomainUsersBlueskyAux
|
||||
sig { void }
|
||||
def id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def last_posts_scan_log_entry_id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_posts_scan_log_entry_id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_posts_scan_log_entry_id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_posts_scan_log_entry_id_was; end
|
||||
|
||||
sig { void }
|
||||
def last_posts_scan_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def last_scan_log_entry_id_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def last_scan_log_entry_id_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::Integer), to: T.nilable(::Integer)).returns(T::Boolean) }
|
||||
def last_scan_log_entry_id_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def last_scan_log_entry_id_was; end
|
||||
|
||||
sig { void }
|
||||
def last_scan_log_entry_id_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def posts_count; end
|
||||
|
||||
@@ -1129,6 +1219,12 @@ class DomainUsersBlueskyAux
|
||||
sig { void }
|
||||
def restore_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_last_posts_scan_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_last_scan_log_entry_id!; end
|
||||
|
||||
sig { void }
|
||||
def restore_posts_count!; end
|
||||
|
||||
@@ -1192,6 +1288,18 @@ class DomainUsersBlueskyAux
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_last_posts_scan_log_entry_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_last_scan_log_entry_id; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_posts_count; end
|
||||
|
||||
@@ -1411,6 +1519,12 @@ class DomainUsersBlueskyAux
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_last_posts_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_last_scan_log_entry_id?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_posts_count?; end
|
||||
|
||||
|
||||
3
sorbet/rbi/dsl/rails/application_controller.rbi
generated
3
sorbet/rbi/dsl/rails/application_controller.rbi
generated
@@ -26,7 +26,10 @@ class Rails::ApplicationController
|
||||
include ::Webpacker::Helper
|
||||
include ::ActionController::Base::HelperMethods
|
||||
include ::ApplicationHelper
|
||||
include ::ActionView::Helpers::ContentExfiltrationPreventionHelper
|
||||
include ::ActionView::Helpers::UrlHelper
|
||||
include ::HelpersInterface
|
||||
include ::Domain::BlueskyPostHelper
|
||||
include ::LogEntriesHelper
|
||||
include ::Pundit::Authorization
|
||||
include ::Domain::UsersHelper
|
||||
|
||||
@@ -26,7 +26,10 @@ class Rails::Conductor::BaseController
|
||||
include ::Webpacker::Helper
|
||||
include ::ActionController::Base::HelperMethods
|
||||
include ::ApplicationHelper
|
||||
include ::ActionView::Helpers::ContentExfiltrationPreventionHelper
|
||||
include ::ActionView::Helpers::UrlHelper
|
||||
include ::HelpersInterface
|
||||
include ::Domain::BlueskyPostHelper
|
||||
include ::LogEntriesHelper
|
||||
include ::Pundit::Authorization
|
||||
include ::Domain::UsersHelper
|
||||
|
||||
3
sorbet/rbi/dsl/rails/health_controller.rbi
generated
3
sorbet/rbi/dsl/rails/health_controller.rbi
generated
@@ -26,7 +26,10 @@ class Rails::HealthController
|
||||
include ::Webpacker::Helper
|
||||
include ::ActionController::Base::HelperMethods
|
||||
include ::ApplicationHelper
|
||||
include ::ActionView::Helpers::ContentExfiltrationPreventionHelper
|
||||
include ::ActionView::Helpers::UrlHelper
|
||||
include ::HelpersInterface
|
||||
include ::Domain::BlueskyPostHelper
|
||||
include ::LogEntriesHelper
|
||||
include ::Pundit::Authorization
|
||||
include ::Domain::UsersHelper
|
||||
|
||||
@@ -143,6 +143,7 @@ RSpec.describe Domain::Bluesky::Job::ScanPostsJob do
|
||||
|
||||
user.reload
|
||||
expect(user.scanned_posts_at).to be_present
|
||||
expect(user.last_posts_scan_log_entry).to eq(@log_entries.first)
|
||||
end
|
||||
|
||||
it "sets the first_seen_entry for posts" do
|
||||
@@ -360,6 +361,14 @@ RSpec.describe Domain::Bluesky::Job::ScanPostsJob do
|
||||
expect(post1.first_seen_entry).to eq(@log_entries[0])
|
||||
expect(post2.first_seen_entry).to eq(@log_entries[1])
|
||||
end
|
||||
|
||||
it "sets last_posts_scan_log_entry to the first HTTP request log entry" do
|
||||
perform_now({ user: user })
|
||||
|
||||
user.reload
|
||||
expect(user.last_posts_scan_log_entry).to be_present
|
||||
expect(user.last_posts_scan_log_entry).to eq(@log_entries.first)
|
||||
end
|
||||
end
|
||||
|
||||
context "when rescanning user with existing posts but pending files" do
|
||||
|
||||
@@ -60,6 +60,15 @@ RSpec.describe Domain::Bluesky::Job::ScanUserJob do
|
||||
expect(user.description).to eq("A test user profile")
|
||||
expect(user.scanned_profile_at).to be_present
|
||||
expect(user.state).to eq("ok")
|
||||
expect(user.last_scan_log_entry).to eq(@log_entries.first)
|
||||
end
|
||||
|
||||
it "sets last_scan_log_entry to the HTTP response log entry" do
|
||||
perform_now({ user: user })
|
||||
|
||||
user.reload
|
||||
expect(user.last_scan_log_entry).to be_present
|
||||
expect(user.last_scan_log_entry).to eq(@log_entries.first)
|
||||
end
|
||||
|
||||
it "enqueues ScanPostsJob for posts scanning" do
|
||||
|
||||
Reference in New Issue
Block a user