Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hotfix/APPEALS-25321 and APPEALS-25955 #19030

Merged
merged 50 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
98630de
Merged 3 tests with 3 different expects into one test since they use …
TylerBroyles Jul 12, 2023
33b289e
Possible bug fix to the sql query for appeals_not_synced. It might ha…
TylerBroyles Jul 12, 2023
33a977e
APPEALS-25321 tweaked ready_for_resync query and filtering duplicates…
minhazur9 Jul 13, 2023
76bd26e
Merge pull request #18995 from department-of-veterans-affairs/TYLERB/…
ThorntonMatthew Jul 14, 2023
1ef5351
APPEALS-25321 added rspec tests
minhazur9 Jul 14, 2023
7e72595
Merge branch 'master' into hotfix/APPEALS-25321
minhazur9 Jul 14, 2023
0f5fb86
Fix name of exception class
ThorntonMatthew Jul 14, 2023
1492cf7
Use stub_consts in place of simply overriding constants
ThorntonMatthew Jul 15, 2023
9612479
Merge branch 'hotfix/APPEALS-25321' of https://github.com/department-…
ThorntonMatthew Jul 15, 2023
f8e6462
APPEALS-25321 added more rspec tests
minhazur9 Jul 17, 2023
a3028cf
Merge branch 'hotfix/APPEALS-25321' of github.com:department-of-veter…
minhazur9 Jul 17, 2023
d2ab4be
Merge branch 'master' into hotfix/APPEALS-25321
minhazur9 Jul 17, 2023
79b66c2
Merge branch 'master' into hotfix/APPEALS-25321
minhazur9 Jul 18, 2023
daaab82
Merge branch 'master' into hotfix/APPEALS-25321
ThorntonMatthew Jul 18, 2023
f5e30c4
Tweak line counts
ThorntonMatthew Jul 18, 2023
937f2a0
Brakeman update
ThorntonMatthew Jul 18, 2023
3589e92
Add SimpleCov CI step
ThorntonMatthew Jul 19, 2023
0605438
Skip test that won't work until fix is pushed to prod
ThorntonMatthew Jul 19, 2023
b5e9acd
Allow coverage to report to always run so I can test it
ThorntonMatthew Jul 19, 2023
9aa8f89
Add back in job depedency
ThorntonMatthew Jul 19, 2023
d432487
Use always()
ThorntonMatthew Jul 19, 2023
7dd75ac
Go back to only running the coverage report step if rspec nodes all pass
ThorntonMatthew Jul 19, 2023
78daab7
APPEALS-25321 added new rspec test
minhazur9 Jul 19, 2023
ca434b0
APPEALS-25321 tweaked perform test
minhazur9 Jul 19, 2023
a5466ef
CC Fix
ThorntonMatthew Jul 19, 2023
ec8fcaa
Merge remote-tracking branch 'origin/hotfix/APPEALS-25955' into hotfi…
ThorntonMatthew Jul 19, 2023
0de97d4
Merge branch 'hotfix/APPEALS-25321-and-APPEALS-25955' into hotfix/APP…
ThorntonMatthew Jul 19, 2023
91adb72
Merge pull request #19009 from department-of-veterans-affairs/hotfix/…
ThorntonMatthew Jul 19, 2023
9d50ad1
Skip bad test
ThorntonMatthew Jul 19, 2023
9586073
Merge branch 'dev-support/enable-rspec-code-coverage-enforcement' int…
ThorntonMatthew Jul 19, 2023
968848b
Update MST Badge Snapshot
ThorntonMatthew Jul 19, 2023
4179dad
Skip some more test for now
ThorntonMatthew Jul 19, 2023
a9ff916
Upload merged results
ThorntonMatthew Jul 19, 2023
8048bbb
Remove some of the crutches used to allow for tests to pass
ThorntonMatthew Jul 20, 2023
d0e24d1
Merge remote-tracking branch 'origin/master' into hotfix/APPEALS-2532…
ThorntonMatthew Jul 24, 2023
a15af14
Account for failures in ready for resync
ThorntonMatthew Jul 27, 2023
9179f81
Merge branch 'master' into hotfix/APPEALS-25321-and-APPEALS-25955
ThorntonMatthew Aug 3, 2023
8087158
Add in FT
ThorntonMatthew Aug 4, 2023
a0ef7f4
Add three phases to sync jobs
ThorntonMatthew Aug 25, 2023
4bf88e6
Merge remote-tracking branch 'origin/master' into hotfix/APPEALS-2532…
ThorntonMatthew Aug 25, 2023
f45460b
Switch to standard error
ThorntonMatthew Aug 25, 2023
ad1614d
Remove old FTs
ThorntonMatthew Aug 25, 2023
033b02c
Update log statement
ThorntonMatthew Aug 28, 2023
3795c34
Fix test
ThorntonMatthew Aug 28, 2023
a512eef
Better uniq
ThorntonMatthew Aug 28, 2023
e1c094f
Merge branch 'master' into hotfix/APPEALS-25321-and-APPEALS-25955
ThorntonMatthew Aug 28, 2023
ebd4150
Merge remote-tracking branch 'origin/master' into hotfix/APPEALS-2532…
ThorntonMatthew Aug 29, 2023
cbd1e7c
Merge branch 'master' into hotfix/APPEALS-25321-and-APPEALS-25955
ThorntonMatthew Aug 29, 2023
b0de7c4
Remove coverage step from workflow for now
ThorntonMatthew Aug 30, 2023
e9610d0
Add back in returns
ThorntonMatthew Aug 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions app/controllers/idt/api/v2/distributions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@ def format_response(response)
response_body = response.raw_body

begin
parsed_response = JSON.parse(response_body)
parsed_response = if [ActiveSupport::HashWithIndifferentAccess, Hash].include?(response_body.class)
response_body
else
JSON.parse(response_body)
end

# Convert keys from camelCase to snake_case
parsed_response.deep_transform_keys do |key|
key.to_s.underscore.gsub(/e(\d)/, 'e_\1')
end
rescue JSON::ParseError => error
log_error(error + " Distribution ID: #{params[:distribution_id]}")
rescue StandardError => error
log_error(error)

response_body
end
Expand Down
35 changes: 26 additions & 9 deletions app/jobs/ama_notification_efolder_sync_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ class AmaNotificationEfolderSyncJob < CaseflowJob
def perform
RequestStore[:current_user] = User.system_user

all_active_ama_appeals = appeals_recently_outcoded + appeals_never_synced + ready_for_resync

sync_notification_reports(all_active_ama_appeals.first(BATCH_LIMIT.to_i))
all_active_ama_appeals = if FeatureToggle.enabled?(:phase_1_notification_sync_job_rollout)
appeals_never_synced
elsif FeatureToggle.enabled?(:phase_2_notification_sync_job_rollout)
appeals_never_synced + ready_for_resync
else
appeals_recently_outcoded + appeals_never_synced + ready_for_resync
end

sync_notification_reports(all_active_ama_appeals.uniq(&:id).first(BATCH_LIMIT.to_i))
end

private
Expand Down Expand Up @@ -98,18 +104,21 @@ def ready_for_resync
# Return: Array of active appeals
def get_appeals_from_prev_synced_ids(appeal_ids)
appeal_ids.in_groups_of(1000, false).flat_map do |ids|
Appeal.active.find_by_sql(
Appeal.find_by_sql(
<<-SQL
SELECT appeals.*
FROM appeals
SELECT appeals.* FROM appeals
JOIN tasks t ON appeals.id = t.appeal_id
AND t.appeal_type = 'Appeal'
JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON
notifs.appeals_id = appeals."uuid"::text AND notifs.appeals_type = 'Appeal'
JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON
vbms_uploads.appeal_id = appeals.id AND vbms_uploads.appeal_type = 'Appeal'
WHERE
WHERE (
notifs.notified_at > vbms_uploads.attempted_at
OR
notifs.created_at > vbms_uploads.attempted_at
)
AND t.TYPE = 'RootTask' AND t.status NOT IN ('completed', 'cancelled')
GROUP BY appeals.id
SQL
)
Expand All @@ -120,8 +129,16 @@ def appeals_on_latest_notifications(appeal_ids)
<<-SQL
SELECT n1.* FROM appeals a
JOIN notifications n1 on n1.appeals_id = a."uuid"::text AND n1.appeals_type = 'Appeal'
LEFT OUTER JOIN notifications n2 ON (n2.appeals_id = a."uuid"::text AND n1.appeals_type = 'Appeal' AND
(n1.notified_at < n2.notified_at OR (n1.notified_at = n2.notified_at AND n1.id < n2.id)))
AND (n1.email_notification_status IS NULL OR
n1.email_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n1.sms_notification_status IS NULL OR
n1.sms_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
LEFT OUTER JOIN notifications n2 ON (n2.appeals_id = a."uuid"::text AND n1.appeals_type = 'Appeal'
AND (n2.email_notification_status IS NULL OR
n2.email_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n2.sms_notification_status IS NULL OR
n2.sms_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n1.notified_at < n2.notified_at OR (n1.notified_at = n2.notified_at AND n1.id < n2.id)))
WHERE n2.id IS NULL
AND n1.id IS NOT NULL
AND (n1.email_notification_status <> 'Failure Due to Deceased'
Expand Down
44 changes: 30 additions & 14 deletions app/jobs/legacy_notification_efolder_sync_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ class LegacyNotificationEfolderSyncJob < CaseflowJob
def perform
RequestStore[:current_user] = User.system_user

all_active_legacy_appeals = appeals_recently_outcoded + appeals_never_synced + ready_for_resync

sync_notification_reports(all_active_legacy_appeals.first(BATCH_LIMIT.to_i))
all_active_legacy_appeals = if FeatureToggle.enabled?(:phase_1_notification_sync_job_rollout)
appeals_never_synced
elsif FeatureToggle.enabled?(:phase_2_notification_sync_job_rollout)
appeals_never_synced + ready_for_resync
else
appeals_recently_outcoded + appeals_never_synced + ready_for_resync
end

sync_notification_reports(all_active_legacy_appeals.uniq(&:id).first(BATCH_LIMIT.to_i))
end

private
Expand Down Expand Up @@ -71,7 +77,7 @@ def previous_case_notifications_document_join_clause
end

def open_root_task_join_clause
"JOIN tasks t ON t.appeal_type = 'LegacyAppeal' AND t.id = legacy_appeals.id \
"JOIN tasks t ON t.appeal_type = 'LegacyAppeal' AND t.appeal_id = legacy_appeals.id \
AND t.type = 'RootTask' AND t.status NOT IN ('completed', 'cancelled')"
end

Expand Down Expand Up @@ -99,31 +105,41 @@ def ready_for_resync
# Return: Array of active appeals
def get_appeals_from_prev_synced_ids(appeal_ids)
appeal_ids.in_groups_of(1000, false).flat_map do |ids|
LegacyAppeal.where(id: RootTask.open.where(appeal_type: "LegacyAppeal").pluck(:appeal_id))
.find_by_sql(
<<-SQL
SELECT la.*
FROM legacy_appeals la
LegacyAppeal.find_by_sql(
<<-SQL
SELECT la.* FROM legacy_appeals la
JOIN tasks t ON la.id = t.appeal_id
AND t.appeal_type = 'LegacyAppeal'
JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON
notifs.appeals_id = la.vacols_id AND notifs.appeals_type = 'LegacyAppeal'
JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON
vbms_uploads.appeal_id = la.id AND vbms_uploads.appeal_type = 'LegacyAppeal'
WHERE
WHERE (
notifs.notified_at > vbms_uploads.attempted_at
OR
notifs.created_at > vbms_uploads.attempted_at
)
AND t.type = 'RootTask' AND t.status NOT IN ('completed', 'cancelled')
GROUP BY la.id
SQL
)
SQL
)
end
end

def appeals_on_latest_notifications(appeal_ids)
<<-SQL
SELECT n1.* FROM legacy_appeals a
JOIN notifications n1 on n1.appeals_id = a.vacols_id AND n1.appeals_type = 'LegacyAppeal'
LEFT OUTER JOIN notifications n2 ON (n2.appeals_id = a.vacols_id AND n1.appeals_type = 'LegacyAppeal' AND
(n1.notified_at < n2.notified_at OR (n1.notified_at = n2.notified_at AND n1.id < n2.id)))
AND (n1.email_notification_status IS NULL OR
n1.email_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n1.sms_notification_status IS NULL OR
n1.sms_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
LEFT OUTER JOIN notifications n2 ON (n2.appeals_id = a.vacols_id AND n1.appeals_type = 'LegacyAppeal'
AND (n2.email_notification_status IS NULL OR
n2.email_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n2.sms_notification_status IS NULL OR
n2.sms_notification_status NOT IN ('No Participant Id Found', 'No Claimant Found', 'No External Id'))
AND (n1.notified_at < n2.notified_at OR (n1.notified_at = n2.notified_at AND n1.id < n2.id)))
WHERE n2.id IS NULL
AND n1.id IS NOT NULL
AND (n1.email_notification_status <> 'Failure Due to Deceased'
Expand Down
78 changes: 39 additions & 39 deletions config/brakeman.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,63 @@
"confidence": "Medium",
"note": ""
},
{
"warning_type": "File Access",
"warning_code": 16,
"fingerprint": "51625fbaea06d71b4cf619f3192432518766296d1356e21eb5f31f3d517a1c7a",
"check_name": "SendFile",
"message": "Model attribute used in file name",
"file": "app/controllers/document_controller.rb",
"line": 33,
"link": "https://brakemanscanner.org/docs/warning_types/file_access/",
"code": "send_file(Document.find(params[:id]).serve, :type => \"application/pdf\", :disposition => ((\"inline\" or \"attachment; filename='#{params[:type]}-#{params[:id]}.pdf'\")))",
"render_path": null,
"location": {
"type": "method",
"class": "DocumentController",
"method": "pdf"
},
"user_input": "Document.find(params[:id]).serve",
"confidence": "Medium",
"note": ""
},
{
"warning_type": "SQL Injection",
"warning_code": 0,
"fingerprint": "3563fb89283da15302f7a0e5f9be93f31eb5aabfa18ff7bdb7080230f2dea4cf",
"fingerprint": "72ec86565b55db864b6072d21637438007fd304209abc58a4864288d309ed818",
"check_name": "SQL",
"message": "Possible SQL injection",
"file": "app/jobs/legacy_notification_efolder_sync_job.rb",
"line": 106,
"file": "app/jobs/ama_notification_efolder_sync_job.rb",
"line": 105,
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
"code": "LegacyAppeal.where(:id => RootTask.open.where(:appeal_type => \"LegacyAppeal\").pluck(:appeal_id)).find_by_sql(\" SELECT la.*\\n FROM legacy_appeals la\\n JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON\\n notifs.appeals_id = la.vacols_id AND notifs.appeals_type = 'LegacyAppeal'\\n JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON\\n vbms_uploads.appeal_id = la.id AND vbms_uploads.appeal_type = 'LegacyAppeal'\\n WHERE\\n notifs.notified_at > vbms_uploads.attempted_at\\n OR\\n notifs.created_at > vbms_uploads.attempted_at\\n GROUP BY la.id\\n\")",
"code": "Appeal.find_by_sql(\" SELECT appeals.* FROM appeals\\n JOIN tasks t ON appeals.id = t.appeal_id\\n AND t.appeal_type = 'Appeal'\\n JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON\\n notifs.appeals_id = appeals.\\\"uuid\\\"::text AND notifs.appeals_type = 'Appeal'\\n JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON\\n vbms_uploads.appeal_id = appeals.id AND vbms_uploads.appeal_type = 'Appeal'\\n WHERE (\\n notifs.notified_at > vbms_uploads.attempted_at\\n OR\\n notifs.created_at > vbms_uploads.attempted_at\\n )\\n AND t.TYPE = 'RootTask' AND t.status NOT IN ('completed', 'cancelled')\\n GROUP BY appeals.id\\n\")",
"render_path": null,
"location": {
"type": "method",
"class": "LegacyNotificationEfolderSyncJob",
"class": "AmaNotificationEfolderSyncJob",
"method": "get_appeals_from_prev_synced_ids"
},
"user_input": "appeals_on_latest_notifications(ids)",
"confidence": "Medium",
"note": ""
},
{
"warning_type": "File Access",
"warning_code": 16,
"fingerprint": "51625fbaea06d71b4cf619f3192432518766296d1356e21eb5f31f3d517a1c7a",
"check_name": "SendFile",
"message": "Model attribute used in file name",
"file": "app/controllers/document_controller.rb",
"line": 33,
"link": "https://brakemanscanner.org/docs/warning_types/file_access/",
"code": "send_file(Document.find(params[:id]).serve, :type => \"application/pdf\", :disposition => ((\"inline\" or \"attachment; filename='#{params[:type]}-#{params[:id]}.pdf'\")))",
"warning_type": "SQL Injection",
"warning_code": 0,
"fingerprint": "9f33c98ba6283fe641049e694d167ce0416d39e4c0fe9ee2dc3b637fa59a52b5",
"check_name": "SQL",
"message": "Possible SQL injection",
"file": "app/jobs/legacy_notification_efolder_sync_job.rb",
"line": 106,
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
"code": "LegacyAppeal.find_by_sql(\" SELECT la.* FROM legacy_appeals la\\n JOIN tasks t ON la.id = t.appeal_id\\n AND t.appeal_type = 'LegacyAppeal'\\n JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON\\n notifs.appeals_id = la.vacols_id AND notifs.appeals_type = 'LegacyAppeal'\\n JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON\\n vbms_uploads.appeal_id = la.id AND vbms_uploads.appeal_type = 'LegacyAppeal'\\n WHERE (\\n notifs.notified_at > vbms_uploads.attempted_at\\n OR\\n notifs.created_at > vbms_uploads.attempted_at\\n )\\n AND t.type = 'RootTask' AND t.status NOT IN ('completed', 'cancelled')\\n GROUP BY la.id\\n\")",
"render_path": null,
"location": {
"type": "method",
"class": "DocumentController",
"method": "pdf"
"class": "LegacyNotificationEfolderSyncJob",
"method": "get_appeals_from_prev_synced_ids"
},
"user_input": "Document.find(params[:id]).serve",
"user_input": "appeals_on_latest_notifications(ids)",
"confidence": "Medium",
"note": ""
},
Expand Down Expand Up @@ -87,7 +107,7 @@
"check_name": "SendFile",
"message": "Model attribute used in file name",
"file": "app/controllers/idt/api/v2/appeals_controller.rb",
"line": 61,
"line": 70,
"link": "https://brakemanscanner.org/docs/warning_types/file_access/",
"code": "send_file(Document.find(document_id).serve, :type => \"application/pdf\", :disposition => (\"attachment; filename='#{current_document[0][\"type\"]}-#{document_id}.pdf'\"))",
"render_path": null,
Expand All @@ -99,28 +119,8 @@
"user_input": "Document.find(document_id).serve",
"confidence": "Medium",
"note": ""
},
{
"warning_type": "SQL Injection",
"warning_code": 0,
"fingerprint": "c9d432e0f7bca941b3cd382a9979de3b85717cdfab0055c3229378e07f84ba70",
"check_name": "SQL",
"message": "Possible SQL injection",
"file": "app/jobs/ama_notification_efolder_sync_job.rb",
"line": 104,
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
"code": "Appeal.active.find_by_sql(\" SELECT appeals.*\\n FROM appeals\\n JOIN (#{appeals_on_latest_notifications(ids)}) AS notifs ON\\n notifs.appeals_id = appeals.\\\"uuid\\\"::text AND notifs.appeals_type = 'Appeal'\\n JOIN (#{appeals_on_latest_doc_uploads(ids)}) AS vbms_uploads ON\\n vbms_uploads.appeal_id = appeals.id AND vbms_uploads.appeal_type = 'Appeal'\\n WHERE\\n notifs.notified_at > vbms_uploads.attempted_at\\n OR\\n notifs.created_at > vbms_uploads.attempted_at\\n GROUP BY appeals.id\\n\")",
"render_path": null,
"location": {
"type": "method",
"class": "AmaNotificationEfolderSyncJob",
"method": "get_appeals_from_prev_synced_ids"
},
"user_input": "appeals_on_latest_notifications(ids)",
"confidence": "Medium",
"note": ""
}
],
"updated": "2023-06-26 09:46:58 -0400",
"updated": "2023-07-18 18:21:26 -0400",
"brakeman_version": "4.7.1"
}
2 changes: 1 addition & 1 deletion lib/tasks/ci.rake
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace :ci do
task :gha_verify_code_coverage do
require "simplecov"

# Using the same dir as :circleci_verify_code_coverage
# Using the same dir as :gha_verify_code_coverage
coverage_dir = "./coverage/combined"
SimpleCov.coverage_dir(coverage_dir)
SimpleCov.merge_timeout(3600 * 24 * 30)
Expand Down
16 changes: 15 additions & 1 deletion spec/controllers/idt/api/v2/distributions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,26 @@
}
end

subject { get :distribution, params: { distribution_id: vbms_distribution.id } }

it "returns the expected converted response" do
get :distribution, params: { distribution_id: vbms_distribution.id }
subject

expect(response).to have_http_status(200)
expect(JSON.parse(response.body.to_json)).to eq(expected_response.to_json)
end

it "Returns Pacman's response whenever we receive something we cannot parse as JSON and logs the error" do
allow(PacmanService).to receive(:get_distribution_request).and_return(
HTTPI::Response.new(200, {}, "An invalid JSON string")
)

expect_any_instance_of(Idt::Api::V2::DistributionsController).to receive(:log_error)

subject

expect(response.body).to eq "An invalid JSON string"
end
end

context "render_error" do
Expand Down
Loading
Loading