Skip to content

Commit 665338e

Browse files
authored
Merge branch 'main' into enhancement/platform-setup-wizard
2 parents 53cd902 + d285fda commit 665338e

File tree

24 files changed

+469
-139
lines changed

24 files changed

+469
-139
lines changed

.github/workflows/brakeman.yml

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
1-
# This workflow uses actions that are not certified by GitHub.
2-
# They are provided by a third-party and are governed by
3-
# separate terms of service, privacy policy, and support
4-
# documentation.
5-
6-
# This workflow integrates Brakeman with GitHub's Code Scanning feature
7-
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
8-
91
name: Brakeman Scan
102

113
on:
124
push:
135
branches: [ "main" ]
146
pull_request:
15-
# The branches below must be a subset of the branches above
167
branches: [ "main" ]
178
schedule:
189
- cron: '26 3 * * 0'
@@ -22,37 +13,38 @@ permissions:
2213

2314
jobs:
2415
brakeman-scan:
25-
permissions:
26-
contents: read # for actions/checkout to fetch code
27-
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
28-
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
2916
name: Brakeman Scan
17+
# Option A: stay on latest (24.04) – requires up-to-date setup-ruby
3018
runs-on: ubuntu-latest
19+
# Option B (fallback): force older image if you prefer
20+
# runs-on: ubuntu-22.04
21+
22+
permissions:
23+
contents: read
24+
security-events: write
25+
actions: read
26+
3127
steps:
32-
# Checkout the repository to the GitHub Actions runner
33-
- name: Checkout
34-
uses: actions/checkout@v3
35-
36-
# Customize the ruby version depending on your needs
37-
- name: Setup Ruby
38-
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
39-
with:
40-
ruby-version: '3.2'
41-
42-
- name: Setup Brakeman
43-
env:
44-
BRAKEMAN_VERSION: '4.10' # SARIF support is provided in Brakeman version 4.10+
45-
run: |
46-
gem install brakeman --version $BRAKEMAN_VERSION
47-
48-
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
49-
- name: Scan
50-
continue-on-error: true
51-
run: |
52-
brakeman -f sarif -o output.sarif.json .
53-
54-
# Upload the SARIF file generated in the previous step
55-
- name: Upload SARIF
56-
uses: github/codeql-action/upload-sarif@v2
57-
with:
58-
sarif_file: output.sarif.json
28+
- name: Checkout
29+
uses: actions/checkout@v4
30+
31+
- name: Setup Ruby
32+
# Use the rolling v1 tag so you get fixes for new runner images
33+
uses: ruby/setup-ruby@v1
34+
with:
35+
ruby-version: '3.2' # or your exact patch, e.g. '3.2.2'
36+
# bundler-cache not needed since we install brakeman directly
37+
38+
- name: Setup Brakeman
39+
run: |
40+
gem install brakeman
41+
42+
- name: Scan (SARIF)
43+
continue-on-error: true
44+
run: |
45+
brakeman -f sarif -o output.sarif.json .
46+
47+
- name: Upload SARIF
48+
uses: github/codeql-action/upload-sarif@v3
49+
with:
50+
sarif_file: output.sarif.json

.github/workflows/codeql.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050

5151
# Initializes the CodeQL tools for scanning.
5252
- name: Initialize CodeQL
53-
uses: github/codeql-action/init@v2
53+
uses: github/codeql-action/init@v3
5454
with:
5555
languages: ${{ matrix.language }}
5656
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -64,7 +64,7 @@ jobs:
6464
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
6565
# If this step fails, then you should remove it and run the build manually (see below)
6666
- name: Autobuild
67-
uses: github/codeql-action/autobuild@v2
67+
uses: github/codeql-action/autobuild@v3
6868

6969
# ℹ️ Command-line programs to run using the OS shell.
7070
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -77,6 +77,6 @@ jobs:
7777
# ./location_of_script_within_repo/buildscript.sh
7878

7979
- name: Perform CodeQL Analysis
80-
uses: github/codeql-action/analyze@v2
80+
uses: github/codeql-action/analyze@v3
8181
with:
8282
category: "/language:${{matrix.language}}"

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ gem 'redis', '~> 5.4'
3535
gem 'rswag'
3636

3737
# Sidekiq for background processing
38-
gem 'sidekiq', '~> 8.0.6'
38+
gem 'sidekiq', '~> 8.0.7'
3939

4040
# Error and performance monitoring with Sentry
4141
gem 'sentry-rails'

Gemfile.lock

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ GEM
189189
descendants_tracker (~> 0.0.4)
190190
ice_nine (~> 0.11.0)
191191
thread_safe (~> 0.3, >= 0.3.1)
192-
base64 (0.2.0)
192+
base64 (0.3.0)
193193
bcrypt (3.1.20)
194194
benchmark (0.4.1)
195195
better_errors (2.10.1)
@@ -304,7 +304,7 @@ GEM
304304
erb (5.0.2)
305305
erubi (1.13.1)
306306
event_stream_parser (1.0.0)
307-
excon (1.2.7)
307+
excon (1.2.8)
308308
logger
309309
execjs (2.10.0)
310310
factory_bot (6.5.4)
@@ -314,19 +314,19 @@ GEM
314314
railties (>= 6.1.0)
315315
faker (3.5.2)
316316
i18n (>= 1.8.11, < 2)
317-
faraday (2.13.0)
317+
faraday (2.13.4)
318318
faraday-net_http (>= 2.0, < 3.5)
319319
json
320320
logger
321-
faraday-multipart (1.1.0)
321+
faraday-multipart (1.1.1)
322322
multipart-post (~> 2.0)
323-
faraday-net_http (3.4.0)
323+
faraday-net_http (3.4.1)
324324
net-http (>= 0.5.0)
325325
ffi (1.17.2-aarch64-linux-gnu)
326326
ffi (1.17.2-arm64-darwin)
327327
ffi (1.17.2-x86_64-linux-gnu)
328-
fog-aws (3.32.0)
329-
base64 (~> 0.2.0)
328+
fog-aws (3.33.0)
329+
base64 (>= 0.2, < 0.4)
330330
fog-core (~> 2.6)
331331
fog-json (~> 1.1)
332332
fog-xml (~> 0.1)
@@ -343,7 +343,7 @@ GEM
343343
nokogiri (>= 1.5.11, < 2.0.0)
344344
font-awesome-sass (6.7.2)
345345
sassc (~> 2.0)
346-
formatador (1.1.0)
346+
formatador (1.1.1)
347347
friendly_id (5.4.2)
348348
activerecord (>= 4.0.0)
349349
friendly_id-mobility (1.0.4)
@@ -454,7 +454,7 @@ GEM
454454
mime-types (3.7.0)
455455
logger
456456
mime-types-data (~> 3.2025, >= 3.2025.0507)
457-
mime-types-data (3.2025.0527)
457+
mime-types-data (3.2025.0805)
458458
mini_magick (5.2.0)
459459
benchmark
460460
logger
@@ -467,7 +467,7 @@ GEM
467467
actiontext (>= 6.0)
468468
mobility (~> 1.2)
469469
msgpack (1.8.0)
470-
multi_json (1.15.0)
470+
multi_json (1.17.0)
471471
multipart-post (2.4.1)
472472
mutex_m (0.3.0)
473473
net-http (0.6.0)
@@ -595,7 +595,7 @@ GEM
595595
psych (>= 4.0.0)
596596
redis (5.4.1)
597597
redis-client (>= 0.22.0)
598-
redis-client (0.25.1)
598+
redis-client (0.25.2)
599599
connection_pool
600600
reform (2.6.2)
601601
disposable (>= 0.5.0, < 1.0.0)
@@ -604,7 +604,7 @@ GEM
604604
reform-rails (0.2.6)
605605
activemodel (>= 5.0)
606606
reform (>= 2.3.1, < 3.0.0)
607-
regexp_parser (2.11.0)
607+
regexp_parser (2.11.1)
608608
reline (0.6.2)
609609
io-console (~> 0.5)
610610
representable (3.2.0)
@@ -678,7 +678,7 @@ GEM
678678
rubocop-factory_bot (2.27.1)
679679
lint_roller (~> 1.1)
680680
rubocop (~> 1.72, >= 1.72.1)
681-
rubocop-rails (2.32.0)
681+
rubocop-rails (2.33.0)
682682
activesupport (>= 4.2.0)
683683
lint_roller (~> 1.1)
684684
rack (>= 1.1)
@@ -691,7 +691,7 @@ GEM
691691
lint_roller (~> 1.1)
692692
rubocop (~> 1.72, >= 1.72.1)
693693
rubocop-rspec (~> 3.5)
694-
ruby-openai (8.1.0)
694+
ruby-openai (8.2.0)
695695
event_stream_parser (>= 0.3.0, < 2.0.0)
696696
faraday (>= 1)
697697
faraday-multipart (>= 1)
@@ -727,7 +727,7 @@ GEM
727727
activesupport (>= 3)
728728
shoulda-matchers (6.5.0)
729729
activesupport (>= 5.2.0)
730-
sidekiq (8.0.6)
730+
sidekiq (8.0.7)
731731
connection_pool (>= 2.5.0)
732732
json (>= 2.9.0)
733733
logger (>= 1.6.2)
@@ -741,7 +741,7 @@ GEM
741741
simplecov_json_formatter (~> 0.1)
742742
simplecov-html (0.13.1)
743743
simplecov_json_formatter (0.1.4)
744-
spring (4.3.0)
744+
spring (4.4.0)
745745
spring-watcher-listen (2.1.0)
746746
listen (>= 2.7, < 4.0)
747747
spring (>= 4)
@@ -863,7 +863,7 @@ DEPENDENCIES
863863
sentry-ruby
864864
shoulda-callback-matchers
865865
shoulda-matchers
866-
sidekiq (~> 8.0.6)
866+
sidekiq (~> 8.0.7)
867867
simplecov
868868
spring
869869
spring-watcher-listen (~> 2.1.0)

app/controllers/better_together/conversations_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def show # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
4747
# Move this to separate action/bg process only activated when the messages are actually read.
4848
events = BetterTogether::NewMessageNotifier.where(record_id: @messages.pluck(:id)).select(:id)
4949

50-
notifications = helpers.current_person.notifications.where(event_id: events.pluck(:id))
50+
notifications = helpers.current_person.notifications.unread.where(event_id: events.pluck(:id))
5151
notifications.update_all(read_at: Time.current)
5252
end
5353

app/controllers/better_together/notifications_controller.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ def index
1111
end
1212

1313
# TODO: Make a Stimulus controller to dispatch this action async when messages are viewed
14-
# rubocop:todo Metrics/MethodLength
1514
def mark_as_read # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
1615
if params[:id]
17-
@notification = helpers.current_person.notifications.find(params[:id])
18-
@notification.update(read_at: Time.current)
16+
mark_notification_as_read(params[:id])
17+
elsif params[:record_id]
18+
mark_record_notification_as_read(params[:record_id])
1919
else
2020
helpers.current_person.notifications.unread.update_all(read_at: Time.current)
2121
end
@@ -35,6 +35,17 @@ def mark_as_read # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
3535
end
3636
end
3737
end
38-
# rubocop:enable Metrics/MethodLength
38+
39+
def mark_notification_as_read(id)
40+
@notification = helpers.current_person.notifications.find(id)
41+
@notification.update(read_at: Time.current)
42+
end
43+
44+
def mark_record_notification_as_read(id)
45+
@notifications = helpers.current_person.notifications.unread.includes(
46+
:event
47+
).references(:event).where(event: { record_id: id })
48+
@notifications.update_all(read_at: Time.current)
49+
end
3950
end
4051
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Controller } from "@hotwired/stimulus"
2+
3+
// Connects to data-controller="message-visibility"
4+
export default class extends Controller {
5+
connect() {
6+
console.log('message visibility controller connected')
7+
const rootElement = document.getElementById('conversation-messages');
8+
9+
const observer = new IntersectionObserver(this.onIntersect, {
10+
root: rootElement,
11+
rootMargin: '0px',
12+
threshold: 1.0
13+
});
14+
15+
observer.observe(this.element);
16+
this.observer = observer;
17+
}
18+
19+
onIntersect = (entries, observer) => {
20+
entries.forEach(entry => {
21+
if (entry.isIntersecting) {
22+
const messageId = this.element.dataset.messageId;
23+
console.log(`Message ${messageId} is on screen.`);
24+
25+
if (this.element.dataset.readStatus === 'unread') { this.markAsRead(messageId); }
26+
27+
observer.unobserve(this.element);
28+
}
29+
});
30+
}
31+
32+
markAsRead(messageId) {
33+
fetch(`/en/notifications/mark_record_as_read`, {
34+
method: 'POST',
35+
headers: {
36+
'Content-Type': 'application/json',
37+
'X-CSRF-Token': this.getCSRFToken()
38+
},
39+
body: JSON.stringify({
40+
record_id: messageId
41+
})
42+
})
43+
.then(response => {
44+
if (response.ok) {
45+
console.log(`Notification for message ${messageId} marked as read.`)
46+
} else {
47+
console.error(`Failed to mark notification for message ${messageId} as read.`)
48+
}
49+
})
50+
}
51+
52+
getCSRFToken() {
53+
const tokenElement = document.querySelector("meta[name='csrf-token']")
54+
return tokenElement ? tokenElement.getAttribute("content") : ""
55+
}
56+
57+
disconnect() {
58+
if (this.observer) {
59+
this.observer.disconnect()
60+
}
61+
}
62+
}

app/views/better_together/conversations/_conversation_content.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<%= turbo_stream_from conversation %>
1818

1919
<div id="conversation_messages" class="card-body p-4" data-controller="better_together--conversation-messages" data-better_together--conversation-messages-current-person-id-value="<%= current_person.id %>">
20-
<%= render(partial: 'better_together/messages/message', collection: messages, as: :message) || render(partial: 'better_together/conversations/empty', locals: { conversation: }) %>
20+
<%= render(partial: 'better_together/messages/message', collection: messages, as: :message, locals: {read_status: 'read'}) || render(partial: 'better_together/conversations/empty', locals: { conversation: }) %>
2121
</div>
2222

2323
<div class="card-footer">

0 commit comments

Comments
 (0)