diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 7b2938fd879..44311095392 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -45,7 +45,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
+ uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -58,7 +58,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
+ uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -71,6 +71,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
+ uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 77d45a51c4d..168058dfbb3 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
+ uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
with:
sarif_file: results.sarif
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 29f6aae442a..66bf812f8df 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -72,6 +72,6 @@ jobs:
- name: Upload coverage to Codecov
if: matrix.rubygems.name == 'locked' && (success() || failure())
- uses: codecov/codecov-action@3b1354a6c45db9f1008891f4eafc1a7e94ce1d18 # v5.0.1
+ uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/Gemfile b/Gemfile
index 1ecd30dbcc9..7cb3848187d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,8 +5,8 @@ ruby file: ".ruby-version"
gem "rails", "~> 7.2.1"
gem "rails-i18n", "~> 7.0"
-gem "aws-sdk-s3", "~> 1.171"
-gem "aws-sdk-sqs", "~> 1.88"
+gem "aws-sdk-s3", "~> 1.174"
+gem "aws-sdk-sqs", "~> 1.89"
gem "bootsnap", "~> 1.18"
gem "clearance", "~> 2.9"
gem "dalli", "~> 3.2"
@@ -29,12 +29,12 @@ gem "omniauth", "~> 2.1"
gem "omniauth-rails_csrf_protection", "~> 1.0"
gem "openid_connect", "~> 2.3"
gem "pg", "~> 1.5"
-gem "puma", "~> 6.4"
+gem "puma", "~> 6.5"
gem "rack", "~> 3.1"
gem "rackup", "~> 2.2"
gem "rack-sanitizer", "~> 2.0"
gem "rbtrace", "~> 0.5.1"
-gem "rdoc", "~> 6.7"
+gem "rdoc", "~> 6.8"
gem "roadie-rails", "~> 3.3"
gem "ruby-magic", "~> 0.6"
gem "shoryuken", "~> 6.2", require: false
@@ -49,22 +49,23 @@ gem "rack-attack", "~> 6.6"
gem "rqrcode", "~> 2.1"
gem "rotp", "~> 6.2"
gem "unpwn", "~> 1.0"
-gem "webauthn", "~> 3.1"
+gem "webauthn", "~> 3.2"
gem "browser", "~> 6.1"
gem "bcrypt", "~> 3.1"
-gem "maintenance_tasks", "~> 2.8"
+gem "maintenance_tasks", "~> 2.9"
gem "strong_migrations", "~> 2.1"
gem "phlex-rails", "~> 1.2"
gem "discard", "~> 1.4"
gem "user_agent_parser", "~> 2.18"
gem "pghero", "~> 3.6"
-gem "timescaledb", "~> 0.3.0"
gem "faraday-multipart", "~> 1.0"
+gem "timescaledb", "~> 0.3"
+gem "sigstore", "~> 0.2.1"
# Admin dashboard
gem "avo", "~> 3.13"
gem "pagy", "~> 8.4"
-gem "view_component", "~> 3.14.0"
+gem "view_component", "~> 3.20.0"
gem "pundit", "~> 2.4"
gem "chartkick", "~> 5.1"
gem "groupdate", "~> 6.5"
@@ -128,17 +129,17 @@ group :development do
end
group :test do
- gem "datadog-ci", "~> 1.8"
+ gem "datadog-ci", "~> 1.9"
gem "minitest", "~> 5.25", require: false
gem "minitest-retry", "~> 0.2.3"
gem "capybara", "~> 3.40"
gem "launchy", "~> 3.0"
gem "rack-test", "~> 2.1", require: "rack/test"
gem "rails-controller-testing", "~> 1.0"
- gem "mocha", "~> 2.5", require: false
+ gem "mocha", "~> 2.6", require: false
gem "shoulda-context", "~> 3.0.0.rc1"
gem "shoulda-matchers", "~> 6.4"
- gem "selenium-webdriver", "~> 4.26"
+ gem "selenium-webdriver", "~> 4.27"
gem "webmock", "~> 3.24"
gem "simplecov", "~> 0.22", require: false
gem "simplecov-cobertura", "~> 2.1", require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 6baade10b9f..21b6b846e38 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,29 +1,29 @@
GEM
remote: https://packager.dev/avo-hq/
specs:
- avo-advanced (3.14.0)
- avo (= 3.14.0)
- avo-dynamic_filters (= 3.14.0)
- avo-pro (= 3.14.0)
+ avo-advanced (3.14.3)
+ avo (= 3.14.3)
+ avo-dynamic_filters (= 3.14.3)
+ avo-pro (= 3.14.3)
zeitwerk (>= 2.6.12)
- avo-dashboards (3.14.0)
- avo (= 3.14.0)
+ avo-dashboards (3.14.3)
+ avo (= 3.14.3)
turbo-rails
view_component (>= 3.7.0)
zeitwerk (>= 2.6.12)
- avo-dynamic_filters (3.14.0)
- avo (= 3.14.0)
+ avo-dynamic_filters (3.14.3)
+ avo (= 3.14.3)
ransack (>= 4.2.0)
view_component (>= 3.7.0)
zeitwerk (>= 2.6.12)
- avo-menu (3.14.0)
- avo (= 3.14.0)
+ avo-menu (3.14.3)
+ avo (= 3.14.3)
docile
zeitwerk (>= 2.6.12)
- avo-pro (3.14.0)
- avo (= 3.14.0)
- avo-dashboards (= 3.14.0)
- avo-menu (= 3.14.0)
+ avo-pro (3.14.3)
+ avo (= 3.14.3)
+ avo-dashboards (= 3.14.3)
+ avo-menu (= 3.14.3)
zeitwerk (>= 2.6.12)
GEM
@@ -115,7 +115,7 @@ GEM
ffi-compiler (~> 1.0)
ast (2.4.2)
attr_required (1.0.2)
- avo (3.14.0)
+ avo (3.14.3)
actionview (>= 6.1)
active_link_to
activerecord (>= 6.1)
@@ -133,22 +133,21 @@ GEM
avo_upgrade (0.1.1)
rails (>= 6.0.0)
zeitwerk
- awrence (1.2.1)
aws-eventstream (1.3.0)
- aws-partitions (1.1008.0)
- aws-sdk-core (3.213.0)
+ aws-partitions (1.1013.0)
+ aws-sdk-core (3.214.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
- aws-sdk-kms (1.95.0)
+ aws-sdk-kms (1.96.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.171.0)
+ aws-sdk-s3 (1.174.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
- aws-sdk-sqs (1.88.0)
+ aws-sdk-sqs (1.89.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.10.1)
@@ -202,7 +201,7 @@ GEM
compact_index (0.15.0)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
- cose (1.3.0)
+ cose (1.3.1)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0)
crack (1.0.0)
@@ -218,7 +217,7 @@ GEM
libdatadog (~> 14.1.0.1.0)
libddwaf (~> 1.15.0.0.0)
msgpack
- datadog-ci (1.8.1)
+ datadog-ci (1.9.0)
datadog (~> 2.4)
msgpack
datadog-ruby_core_source (3.3.6)
@@ -354,7 +353,7 @@ GEM
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
- job-iteration (1.5.1)
+ job-iteration (1.7.0)
activejob (>= 5.2)
json (2.8.2)
json-jwt (1.16.7)
@@ -364,7 +363,8 @@ GEM
bindata
faraday (~> 2.0)
faraday-follow_redirects
- jwt (2.7.1)
+ jwt (2.9.3)
+ base64
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
@@ -440,13 +440,13 @@ GEM
net-imap
net-pop
net-smtp
- maintenance_tasks (2.8.0)
- actionpack (>= 6.0)
- activejob (>= 6.0)
- activerecord (>= 6.0)
+ maintenance_tasks (2.9.0)
+ actionpack (>= 6.1)
+ activejob (>= 6.1)
+ activerecord (>= 6.1)
csv
job-iteration (>= 1.3.6)
- railties (>= 6.0)
+ railties (>= 6.1)
zeitwerk (>= 2.6.2)
marcel (1.0.4)
matrix (0.4.2)
@@ -457,7 +457,7 @@ GEM
mini_histogram (0.3.1)
mini_mime (1.1.5)
mini_portile2 (2.8.8)
- minitest (5.25.1)
+ minitest (5.25.2)
minitest-gcstats (1.3.1)
minitest (~> 5.0)
minitest-reporters (1.7.1)
@@ -467,7 +467,7 @@ GEM
ruby-progressbar
minitest-retry (0.2.3)
minitest (>= 5.0)
- mocha (2.5.0)
+ mocha (2.6.0)
ruby2_keywords (>= 0.0.5)
msgpack (1.7.5)
multi_json (1.15.0)
@@ -486,7 +486,7 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
- nio4r (2.7.3)
+ nio4r (2.7.4)
nokogiri (1.16.7)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
@@ -587,7 +587,7 @@ GEM
psych (5.2.0)
stringio
public_suffix (6.0.1)
- puma (6.4.3)
+ puma (6.5.0)
nio4r (~> 2.0)
pundit (2.4.0)
activesupport (>= 3.0.0)
@@ -673,7 +673,7 @@ GEM
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
- rdoc (6.7.0)
+ rdoc (6.8.1)
psych (>= 4.0.0)
redcarpet (3.6.0)
regexp_parser (2.9.2)
@@ -749,7 +749,7 @@ GEM
activemodel (>= 6.1)
hashie
securerandom (0.3.2)
- selenium-webdriver (4.26.0)
+ selenium-webdriver (4.27.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -765,7 +765,7 @@ GEM
shoulda-context (3.0.0.rc1)
shoulda-matchers (6.4.0)
activesupport (>= 5.2.0)
- sigstore (0.1.1)
+ sigstore (0.2.1)
net-http
protobug_sigstore_protos (~> 0.1.0)
uri
@@ -811,7 +811,7 @@ GEM
activesupport
pg (~> 1.2)
toxiproxy (2.0.2)
- tpm-key_attestation (0.12.0)
+ tpm-key_attestation (0.12.1)
bindata (~> 2.4)
openssl (> 2.0)
openssl-signature_algorithm (~> 1.0)
@@ -835,13 +835,12 @@ GEM
validates_formatting_of (0.9.0)
activemodel
version_gem (1.1.1)
- view_component (3.14.0)
- activesupport (>= 5.2.0, < 8.0)
+ view_component (3.20.0)
+ activesupport (>= 5.2.0, < 8.1)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
- webauthn (3.1.0)
+ webauthn (3.2.2)
android_key_attestation (~> 0.3.0)
- awrence (~> 1.1)
bindata (~> 2.4)
cbor (~> 0.5.9)
cose (~> 1.1)
@@ -883,8 +882,8 @@ DEPENDENCIES
avo (~> 3.13)
avo-advanced (~> 3.14)!
avo_upgrade (~> 0.1.1)
- aws-sdk-s3 (~> 1.171)
- aws-sdk-sqs (~> 1.88)
+ aws-sdk-s3 (~> 1.174)
+ aws-sdk-sqs (~> 1.89)
bcrypt (~> 3.1)
better_html (~> 2.1)
bootsnap (~> 1.18)
@@ -897,7 +896,7 @@ DEPENDENCIES
csv (~> 3.3)
dalli (~> 3.2)
datadog (~> 2.7)
- datadog-ci (~> 1.8)
+ datadog-ci (~> 1.9)
derailed_benchmarks (~> 2.2)
discard (~> 1.4)
dogstatsd-ruby (~> 5.6)
@@ -925,13 +924,13 @@ DEPENDENCIES
local_time (~> 3.0)
lookbook (~> 2.3)
mail (~> 2.8)
- maintenance_tasks (~> 2.8)
+ maintenance_tasks (~> 2.9)
memory_profiler (~> 1.1)
minitest (~> 5.25)
minitest-gcstats (~> 1.3)
minitest-reporters (~> 1.7)
minitest-retry (~> 0.2.3)
- mocha (~> 2.5)
+ mocha (~> 2.6)
observer (~> 0.1.2)
octokit (~> 9.2)
omniauth (~> 2.1)
@@ -949,7 +948,7 @@ DEPENDENCIES
propshaft (~> 1.1.0)
prosopite (~> 1.4)
pry-byebug (~> 3.10)
- puma (~> 6.4)
+ puma (~> 6.5)
pundit (~> 2.4)
rack (~> 3.1)
rack-attack (~> 6.6)
@@ -962,7 +961,7 @@ DEPENDENCIES
rails-i18n (~> 7.0)
rails_semantic_logger (~> 4.17)
rbtrace (~> 0.5.1)
- rdoc (~> 6.7)
+ rdoc (~> 6.8)
roadie-rails (~> 3.3)
rotp (~> 6.2)
rqrcode (~> 2.1)
@@ -974,11 +973,11 @@ DEPENDENCIES
rubocop-rails (~> 2.25)
ruby-magic (~> 0.6)
searchkick (~> 5.4)
- selenium-webdriver (~> 4.26)
+ selenium-webdriver (~> 4.27)
shoryuken (~> 6.2)
shoulda-context (~> 3.0.0.rc1)
shoulda-matchers (~> 6.4)
- sigstore (~> 0.1.1)
+ sigstore (~> 0.2.1)
simplecov (~> 0.22)
simplecov-cobertura (~> 2.1)
statsd-instrument (~> 3.9)
@@ -990,8 +989,8 @@ DEPENDENCIES
unpwn (~> 1.0)
user_agent_parser (~> 2.18)
validates_formatting_of (~> 0.9)
- view_component (~> 3.14.0)
- webauthn (~> 3.1)
+ view_component (~> 3.20.0)
+ webauthn (~> 3.2)
webmock (~> 3.24)
xml-simple (~> 1.1)
@@ -1017,20 +1016,19 @@ CHECKSUMS
argon2 (2.3.0) sha256=980ef65172bf512ad37b6cbb0d61eef40b6dccab6a7db4e70557527e1dce9557
ast (2.4.2) sha256=1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12
attr_required (1.0.2) sha256=f0ebfc56b35e874f4d0ae799066dbc1f81efefe2364ca3803dc9ea6a4de6cb99
- avo (3.14.0) sha256=ae8744b3bde7c9b3d41869e58214abf288d7ef6f230420746f012df083f1c0be
- avo-advanced (3.14.0) sha256=9b4a450819e7ea4aa2b25ff07d4e6f0bd36bcb6c99e86469a2fd1be733b9fe17
- avo-dashboards (3.14.0) sha256=5b2c30fee710fdfec6d47d940d5018cb1afcd2020720e5ef436001dc2ee6387b
- avo-dynamic_filters (3.14.0) sha256=05fd9e5846ad247310fbffed61b40be310d9334646e8d59afe6c724faff5b28e
- avo-menu (3.14.0) sha256=f07243d2a52921d28718d7d9bdddb11eaebdc0dd5b07deed7a7fb767550be554
- avo-pro (3.14.0) sha256=0a20743f5c5e685a9088c9b753bc8419a68aac57f7fa2966485e9ceb61a82c5f
+ avo (3.14.3) sha256=14cc7e5ab58f77b78cfdfefb7f267a5728633c465439ac6baf963fe6ab959b09
+ avo-advanced (3.14.3) sha256=39f5c88b8a135c54839b9d1572b68b42a38b19f76cf0b12f43e25bf844d56cab
+ avo-dashboards (3.14.3) sha256=7caec15df4511d8ed6a4a605172d7ab929cfa68d8efb202773beee8fa419f94e
+ avo-dynamic_filters (3.14.3) sha256=aa61534e51c5c8ee75775fcb6b3cacdbb04e12bdc9b425dd642ca9d325b6e1ef
+ avo-menu (3.14.3) sha256=0f86612687bead97b382fc21eba82af5590ec890cb4d340fc150cf82166e4bf5
+ avo-pro (3.14.3) sha256=3c2bb725e9396c44ed8934cb035d19f267a7d76967666d27a78d885be2d97e6e
avo_upgrade (0.1.1) sha256=8d841083b9956392f5c8fe195f25bec0d139e3646d276f8a59e66b7d2e9ebf30
- awrence (1.2.1) sha256=dd1d214c12a91f449d1ef81d7ee3babc2816944e450752e7522c65521872483e
aws-eventstream (1.3.0) sha256=f1434cc03ab2248756eb02cfa45e900e59a061d7fbdc4a9fd82a5dd23d796d3f
- aws-partitions (1.1008.0) sha256=6fb5e6b843ea1169480c804fc861a5de7407762097de75cf4734fbcd35466227
- aws-sdk-core (3.213.0) sha256=6ca685be1d72d61776fdaaddf3c293e45a472ff0dd0b624880e7813d0c82db19
- aws-sdk-kms (1.95.0) sha256=2ae508c642ddc59baa1296229108e9601a2fa00e57cf7a2153c9488f0587fd5e
- aws-sdk-s3 (1.171.0) sha256=94a2210c20f6102d8867937b021ef40683aa351e28912ac9cc6ef20509f85f4f
- aws-sdk-sqs (1.88.0) sha256=3e4e022b9af1796eb87bb368a8bb2001ebcad3b5025d76aa9ba731acea01a2eb
+ aws-partitions (1.1013.0) sha256=60e72ff88ae49a114bea693f4479ef7d3c0cdc4795009c1d9761db79ffc1d1fe
+ aws-sdk-core (3.214.0) sha256=24f2a0f29dc3b5d9ee38d6ff8341a66fba48a4ebca2424688f7bac9952d8488b
+ aws-sdk-kms (1.96.0) sha256=b1818e140b4d1b3cbe154e6b2df1d157f8c65aa297d488f69b5745995a6ba375
+ aws-sdk-s3 (1.174.0) sha256=9a80d43a7816abd49dc8becc6bf6675d8dbc8bc01ad49dcc252899fc4c021f3f
+ aws-sdk-sqs (1.89.0) sha256=1db1e8a1dcf1a83a6328fe12a034fe89e1c7a73c6305b8cad089656e3a5389ba
aws-sigv4 (1.10.1) sha256=8a140753f34de18125686b11e7adaed4ca3db06dfb50a478993bd437f7a203bb
base64 (0.2.0) sha256=0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507
bcrypt (3.1.20) sha256=8410f8c7b3ed54a3c00cd2456bf13917d695117f033218e2483b2e40b0784099
@@ -1056,14 +1054,14 @@ CHECKSUMS
compact_index (0.15.0) sha256=5c6c404afca8928a7d9f4dde9524f6e1610db17e675330803055db282da84a8b
concurrent-ruby (1.3.4) sha256=d4aa926339b0a86b5b5054a0a8c580163e6f5dcbdfd0f4bb916b1a2570731c32
connection_pool (2.4.1) sha256=0f40cf997091f1f04ff66da67eabd61a9fe0d4928b9a3645228532512fab62f4
- cose (1.3.0) sha256=63247c66a5bc76e53926756574fe3724cc0a88707e358c90532ae2a320e98601
+ cose (1.3.1) sha256=d5d4dbcd6b035d513edc4e1ab9bc10e9ce13b4011c96e3d1b8fe5e6413fd6de5
crack (1.0.0) sha256=c83aefdb428cdc7b66c7f287e488c796f055c0839e6e545fec2c7047743c4a49
crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d
css_parser (1.19.1) sha256=1940dce01e3b9be18d6880e6d65162d984cc04ff28998cf4759beb999275209e
csv (3.3.0) sha256=0bbd1defdc31134abefed027a639b3723c2753862150f4c3ee61cab71b20d67d
dalli (3.2.8) sha256=2e63595084d91fae2655514a02c5d4fc0f16c0799893794abe23bf628bebaaa5
datadog (2.7.0) sha256=cea0c125acff6630966a2ad0bc01863ba1e1ff2886b4d38dc29f254f89ad02a2
- datadog-ci (1.8.1) sha256=c461acd83d36b5894716ea7b1c207fd4b7fa103994c0773e3936a68da4dfa594
+ datadog-ci (1.9.0) sha256=f48a2ec91961b65ada1e13b964a42ed1e3ae6ee586736e3ee5690d0ceb302069
datadog-ruby_core_source (3.3.6) sha256=007c72450d3f5838c6d0ae4a6a77e5008bb29dd97d10ea3bf367f978d7c02f36
date (3.4.0) sha256=2e7fadaded625c9b3e35e254e42068d4bd8b8646ceab0744cbcbcfdafaa0a711
derailed_benchmarks (2.2.1) sha256=654280664fded41c9cd8fc27fc0fcfaf096023afab90eb4ac1185ba70c5d4439
@@ -1122,10 +1120,10 @@ CHECKSUMS
io-console (0.7.2) sha256=f0dccff252f877a4f60d04a4dc6b442b185ebffb4b320ab69212a92b48a7a221
irb (1.14.1) sha256=5975003b58d36efaf492380baa982ceedf5aed36967a4d5b40996bc5c66e80f8
jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1
- job-iteration (1.5.1) sha256=1428ad5b308adbaae8776c16b7792a846eb1ad7f4ab3c6e0f9668dd2ab1179e5
+ job-iteration (1.7.0) sha256=7e9db935ce021280a030414995047f370b458597405b316a0bf59ecc9c9cad5d
json (2.8.2) sha256=dd4fa6c9c81daecf72b86ea36e56ed8955fdbb4d4dc379c93d313a59344486cf
json-jwt (1.16.7) sha256=ccabff4c6d1a14276b23178e8bebe513ef236399b72a0b886d7ed94800d172a5
- jwt (2.7.1) sha256=07357cd2f180739b2f8184eda969e252d850ac996ed0a23f616e8ff0a90ae19b
+ jwt (2.9.3) sha256=55fd07ccdd64c622d36859748f2290fb9c119ce30b482867504e9f12654d6a65
kaminari (1.2.2) sha256=c4076ff9adccc6109408333f87b5c4abbda5e39dc464bd4c66d06d9f73442a3e
kaminari-actionview (1.2.2) sha256=1330f6fc8b59a4a4ef6a549ff8a224797289ebf7a3a503e8c1652535287cc909
kaminari-activerecord (1.2.2) sha256=0dd3a67bab356a356f36b3b7236bcb81cef313095365befe8e98057dd2472430
@@ -1151,7 +1149,7 @@ CHECKSUMS
loofah (2.23.1) sha256=d0a07422cb3b69272e124afa914ef6d517e30d5496b7f1c1fc5b95481f13f75e
lookbook (2.3.4) sha256=16484c9eb514ac0c23c4b59cfd5a52697141d35056e3a9c2a22b314c1b887605
mail (2.8.1) sha256=ec3b9fadcf2b3755c78785cb17bc9a0ca9ee9857108a64b6f5cfc9c0b5bfc9ad
- maintenance_tasks (2.8.0) sha256=7ee8aa37ab39c6c3a5f4637878c1a343cc296596742248112458b922968d4a16
+ maintenance_tasks (2.9.0) sha256=7146aa49f66c17b83c8a8d097ed503260c857fa698f3038a6cffbb36df1257c5
marcel (1.0.4) sha256=0d5649feb64b8f19f3d3468b96c680bae9746335d02194270287868a661516a4
matrix (0.4.2) sha256=71083ccbd67a14a43bfa78d3e4dc0f4b503b9cc18e5b4b1d686dc0f9ef7c4cc0
memory_profiler (1.1.0) sha256=79a17df7980a140c83c469785905409d3027ca614c42c086089d128b805aa8f8
@@ -1160,11 +1158,11 @@ CHECKSUMS
mini_histogram (0.3.1) sha256=6a114b504e4618b0e076cc672996036870f7cc6f16b8e5c25c0c637726d2dd94
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
mini_portile2 (2.8.8) sha256=8e47136cdac04ce81750bb6c09733b37895bf06962554e4b4056d78168d70a75
- minitest (5.25.1) sha256=3db6795a80634def1cf86fda79d2d83b59b25ce5e186fa675f73c565589d2ad8
+ minitest (5.25.2) sha256=59b379d63e0058159127b545c4725d3106624c9be2b3e030ddaee825d59e83eb
minitest-gcstats (1.3.1) sha256=cb25490f93aac02e3a5ff307e560d41afcdcafa7952c1c32efdeb9886b1f4711
minitest-reporters (1.7.1) sha256=5060413a0c95b8c32fe73e0606f3631c173a884d7900e50013e15094eb50562c
minitest-retry (0.2.3) sha256=7b7f4896efb9b931a1acb442a40e5273c441f44946cf4c6a8eb8895838e7bf29
- mocha (2.5.0) sha256=7852595064e8ef4c6a3f6d8a5a5ab8c705168f913bb17929ab1c35f4dd4c7717
+ mocha (2.6.0) sha256=76ac4f4702d7c86be602e61a957f719e7e9df48ac3799b1a892655ca416a5638
msgpack (1.7.5) sha256=ffb04979f51e6406823c03abe50e1da2c825c55a37dee138518cdd09d9d3aea8
multi_json (1.15.0) sha256=1fd04138b6e4a90017e8d1b804c039031399866ff3fbabb7822aea367c78615d
multi_xml (0.7.1) sha256=4fce100c68af588ff91b8ba90a0bb3f0466f06c909f21a32f4962059140ba61b
@@ -1175,7 +1173,7 @@ CHECKSUMS
net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8
net-smtp (0.5.0) sha256=5fc0415e6ea1cc0b3dfea7270438ec22b278ca8d524986a3ae4e5ae8d087b42a
- nio4r (2.7.3) sha256=54b94cdd4b8f9dc39aaad5f699e97afae13efb44f2b180a6e724df76105ff604
+ nio4r (2.7.4) sha256=d95dee68e0bb251b8ff90ac3423a511e3b784124e5db7ff5f4813a220ae73ca9
nokogiri (1.16.7) sha256=f819cbfdfb0a7b19c9c52c6f2ca63df0e58a6125f4f139707b586b9511d7fe95
nokogiri (1.16.7-aarch64-linux) sha256=78778d35f165b59513be31c0fe232c63a82cf97626ffba695b5f822e5da1d74b
nokogiri (1.16.7-arm64-darwin) sha256=276dcea1b988a5b22b5acc1ba901d24b8e908c40b71dccd5d54a2ae279480dad
@@ -1215,7 +1213,7 @@ CHECKSUMS
pry-byebug (3.10.1) sha256=c8f975c32255bfdb29e151f5532130be64ff3d0042dc858d0907e849125581f8
psych (5.2.0) sha256=6603fe756bcaf14daa25bc17625f36c90931dcf70452ac1e8da19760dc310573
public_suffix (6.0.1) sha256=61d44e1cab5cbbbe5b31068481cf16976dd0dc1b6b07bd95617ef8c5e3e00c6f
- puma (6.4.3) sha256=24a4645c006811d83f2480057d1f54a96e7627b6b90e1c99b260b9dc630eb43e
+ puma (6.5.0) sha256=94d1b75cab7f356d52e4f1b17b9040a090889b341dbeee6ee3703f441dc189f2
pundit (2.4.0) sha256=43e6d27a9df082c04f0020999ce4dcf6742ecc5775d102ef2bfe9df041417572
pwned (2.3.0) sha256=63f5a9576f109203684e9dd053f815649fd5bc0a0348b7190568272641b22353
raabro (1.4.0) sha256=d4fa9ff5172391edb92b242eed8be802d1934b1464061ae5e70d80962c5da882
@@ -1242,7 +1240,7 @@ CHECKSUMS
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
rb-inotify (0.10.1) sha256=050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca
rbtrace (0.5.1) sha256=e8cba64d462bfb8ba102d7be2ecaacc789247d52ac587d8003549d909cb9c5dc
- rdoc (6.7.0) sha256=b17d5f0f57b0853d7b880d4360a32c7caf8dbb81f8503a36426df809e617f379
+ rdoc (6.8.1) sha256=0128002d1bfc4892bdd780940841e4ca41275f63781fd832d11bc8ba4461462c
redcarpet (3.6.0) sha256=8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9
regexp_parser (2.9.2) sha256=5a27e767ad634f8a4b544520d5cd28a0db7aa1198a5d7c9d7e11d7b3d9066446
reline (0.5.11) sha256=868d5f4dbfd9caafa70182f7f6fa258b70baee4e565d7cd9e70b4d5b11a7cb65
@@ -1275,13 +1273,13 @@ CHECKSUMS
sawyer (0.9.2) sha256=fa3a72d62a4525517b18857ddb78926aab3424de0129be6772a8e2ba240e7aca
searchkick (5.4.0) sha256=75d7256d3ec2af2dc11c2ba8160c86d80451f3f86447aae2ace1f79553de0bf3
securerandom (0.3.2) sha256=e8b2ffa651dfbbb26eb4bfb8ddcfff94221a93e3f118f39e0f7f94c14fea9dc0
- selenium-webdriver (4.26.0) sha256=bb0426ffe50e5940a6a5ed2978b4dfb1cb29e0e1c4d0a420d6aabf0f6c8e0690
+ selenium-webdriver (4.27.0) sha256=8821f4ad60b935cfcdc5954c0a6642d894e936250aece8bf37a6fcbebe5eb6e0
semantic (1.6.1) sha256=3cdbb48f59198ebb782a3fdfb87b559e0822a311610db153bae22777a7d0c163
semantic_logger (4.16.0) sha256=ffba0bd0e008ceaf6be26da588f610a61208b9a9f55676b32729e962904023d9
shoryuken (6.2.1) sha256=95ddc0a717624a54e799d25a0a05100cb5a0c3728a96211935c214faaf16b3b6
shoulda-context (3.0.0.rc1) sha256=6e0d9d52ab798c13bc2b490c8537d4bf30cfd318a1ea839c39a66d1d293c6a1a
shoulda-matchers (6.4.0) sha256=9055bb7f4bb342125fb860809798855c630e05ef5e75837b3168b8e6ee1608b0
- sigstore (0.1.1) sha256=0c2c3c5d175b204252eeb1507bfb79e330009188d160525d2871b5272f958897
+ sigstore (0.2.1) sha256=58031c34c7899dd6aac43c54d0ab1a5282a551804013d4b7cb6930a32cbc8775
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
simplecov-cobertura (2.1.0) sha256=2c6532e34df2e38a379d72cef9a05c3b16c64ce90566beebc6887801c4ad3f02
simplecov-html (0.12.3) sha256=4b1aad33259ffba8b29c6876c12db70e5750cb9df829486e4c6e5da4fa0aa07b
@@ -1303,7 +1301,7 @@ CHECKSUMS
timeout (0.4.2) sha256=8aca2d5ff98eb2f7a501c03f8c3622065932cc58bc58f725cd50a09e63b4cc19
timescaledb (0.3.0) sha256=9ce2b39417d30544054cb609fbd84e18e304c7b7952a793846b8f4489551a28f
toxiproxy (2.0.2) sha256=2e3b53604fb921d40da3db8f78a52b3133fcae33e93d440725335b15974e440a
- tpm-key_attestation (0.12.0) sha256=e133d80cf24fef0e7a7dfad00fd6aeff01fc79875fbfc66cd8537bbd622b1e6d
+ tpm-key_attestation (0.12.1) sha256=3c1315bed06ba3563aee98ff69c270d9b45b586a43ac2da250b23cad3c3caca3
turbo-rails (2.0.11) sha256=fc47674736372780abd2a4dc0d84bef242f5ca156a457cd7fa6308291e397fcf
turbo_power (0.6.2) sha256=c9080d0d1bb79deed67bee2a7654dd38f9c903b57ad52b98d19d000958fde2cc
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
@@ -1315,8 +1313,8 @@ CHECKSUMS
validate_url (1.0.15) sha256=72fe164c0713d63a9970bd6700bea948babbfbdcec392f2342b6704042f57451
validates_formatting_of (0.9.0) sha256=139590a4b87596dbfb04d93e897bd2e6d30fb849d04fab0343e71ed2ca856e7e
version_gem (1.1.1) sha256=3c2da6ded29045ddcc0387e152dc634e1f0c490b7128dce0697ccc1cf0915b6c
- view_component (3.14.0) sha256=96816de1c40d276d9fac49316ee4d196de90b1ce6eb39373b887c639749e630c
- webauthn (3.1.0) sha256=e545fcf17d8a6b821161a37c1c4bc8c3d2ead0ff6ff3b098f57f417e731790b7
+ view_component (3.20.0) sha256=ac3192b80c2936521e5e60e585960942f40f745cf0a78d037bf6d36e703e228b
+ webauthn (3.2.2) sha256=46e70b234963c85bbf8ea8febc9a3cbf04569e34a73a570d86f68556f3f36a38
webfinger (2.1.3) sha256=567a52bde77fb38ca6b67e55db755f988766ec4651c1d24916a65aa70540695c
webmock (3.24.0) sha256=be01357f6fc773606337ca79f3ba332b7d52cbe5c27587671abc0572dbec7122
websocket (1.2.11) sha256=b7e7a74e2410b5e85c25858b26b3322f29161e300935f70a0e0d3c35e0462737
diff --git a/app/assets/images/icons.svg b/app/assets/images/icons.svg
index f261c13645c..981a3294875 100644
--- a/app/assets/images/icons.svg
+++ b/app/assets/images/icons.svg
@@ -6,7 +6,7 @@
<%= user.full_name %>
- <% end %> +<%= user.full_name %>
+ <% end %> +<%= - mail_to(user.email, encode: "hex") - %>
-<%= + mail_to(user.email, encode: "hex") + %>
+<%= - link_to( - twitter_username(user), - twitter_url(user) - ) - %>
-<%= + link_to( + twitter_username(user), + twitter_url(user) + ) + %>
+<%= membership.organization.name %>
+ <%= c.list_item_to(organization_path(membership.organization)) do %> +<%= membership.organization.name %>
+<%= membership.organization.handle %>
+<%= membership.role %>
<%= organization.handle %>
++ + <%= icon_tag("organizations", size: 6, class: "-mt-1 -ml-1 mr-1 inline-block") -%><%= t("organizations.show.organization") %> + +
+<%= membership.organization.name %>
+<%= membership.organization.handle %>
+<%= membership.role %>
+<%= membership.user.name %>
+<%= membership.role %>
+<%= t('.enter_password') %>
- <%= form.password_field :password, autocomplete: 'current-password', class: 'form__input' %> + <%= form.password_field :password, autocomplete: 'current-password', class: 'form__input', required: true %><%= short_info(gem.most_recent_version) %>
+ <%= c.list do %> + <% @subscribed_gems.each do |gem| %> + <%= c.list_item do %> +<%= short_info(gem.most_recent_version) %>
+ <% end %> + <%= button_to( + rubygem_subscription_path(gem.slug), + method: :delete, + title: t("rubygems.aside.links.unsubscribe"), + class: "h-8 w-8 ml-6 items-center justify-center outline-none -mr-2", + aria: { label: t("rubygems.aside.links.unsubscribe") } + ) do %> + <%= icon_tag "close", class: "w-6 h-6" %> + <% end %> +1.63.1
+ HTML
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/test/components/previews/card_component_preview.rb b/test/components/previews/card_component_preview.rb
new file mode 100644
index 00000000000..417febf5c74
--- /dev/null
+++ b/test/components/previews/card_component_preview.rb
@@ -0,0 +1,56 @@
+class CardComponentPreview < Lookbook::Preview
+ layout "hammy_component_preview"
+
+ # @param title text "Card title"
+ # @param icon text "icon name"
+ # @param count number "count (blank for no count)"
+ # @param url url "view all link (blank for no link)"
+ def default(title: "Gems", icon: "gems", count: nil, url: nil)
+ render CardComponent.new do |c|
+ c.head(title, icon: icon, count: count, url: url)
+ c.list do
+ c.list_item { "list > list_item" }
+ end
+ end
+ end
+
+ def divided_list(title: "Gems", icon: "gems", count: nil, url: nil)
+ render CardComponent.new do |c|
+ c.head(title, icon: icon, count: count)
+ c.divided_list do
+ c.list_item { "divided_list > list_item" }
+ c.list_item_to("#") { "divided_list > list_item_to" }
+ c.list_item { "divided_list > list_item" }
+ end
+ c.list_item_to(url) { "View all" } if url
+ end
+ end
+
+ def scrollable(title: "History")
+ render CardComponent.new do |c|
+ c.head do
+ c.title(title, icon: :history)
+ end
+ c.scrollable do
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(Time.current) { "timeline_item > content" }
+ end
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(1.day.ago) { "timeline_item > content" }
+ end
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(2.days.ago) { "timeline_item > content" }
+ end
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(1.week.ago) { "timeline_item > content" }
+ end
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(1.month.ago) { "timeline_item > content" }
+ end
+ render Card::TimelineComponent.new do |t|
+ t.timeline_item(1.year.ago) { "timeline_item > content" }
+ end
+ end
+ end
+ end
+end
diff --git a/test/functional/profiles_controller_test.rb b/test/functional/profiles_controller_test.rb
index 1cfbb165ec8..0cb3ab5a29d 100644
--- a/test/functional/profiles_controller_test.rb
+++ b/test/functional/profiles_controller_test.rb
@@ -12,6 +12,19 @@ class ProfilesControllerTest < ActionController::TestCase
end
end
+ context "for a user whose email is not confirmed" do
+ setup do
+ @user = create(:user)
+ @user.update(email_confirmed: false)
+ end
+
+ should "render not found page" do
+ get :show, params: { id: @user.handle }
+
+ assert_response :not_found
+ end
+ end
+
context "when not logged in" do
setup { @user = create(:user) }
diff --git a/test/integration/i18n_test.rb b/test/integration/i18n_test.rb
index 1212f677ccd..f7a1e80fe4a 100644
--- a/test/integration/i18n_test.rb
+++ b/test/integration/i18n_test.rb
@@ -30,10 +30,12 @@ def collect_combined_keys(hash, namespace = nil)
assert_predicate reference, :present?
+ suggestion = "\nRun bin/fill-locales to add missing keys."
+
locale_keys.each do |locale, keys|
missing = reference - keys
- assert_predicate missing, :blank?, "#{locale} locale is missing: #{missing.join(', ')}"
+ assert_predicate missing, :blank?, "#{locale} locale is missing: #{missing.join(', ')}#{suggestion}"
extra = keys - reference
assert_predicate extra, :blank?, "#{locale} locale has extra: #{extra.join(', ')}"
diff --git a/test/integration/organizations/gems_test.rb b/test/integration/organizations/gems_test.rb
new file mode 100644
index 00000000000..03dbf5857cc
--- /dev/null
+++ b/test/integration/organizations/gems_test.rb
@@ -0,0 +1,25 @@
+require "test_helper"
+
+class Organizations::GemsTest < ActionDispatch::IntegrationTest
+ setup do
+ @user = create(:user, remember_token_expires_at: Gemcutter::REMEMBER_FOR.from_now)
+ post session_path(session: { who: @user.handle, password: PasswordHelpers::SECURE_TEST_PASSWORD })
+ end
+
+ test "should get index" do
+ @organization = create(:organization, owners: [@user])
+ @organization.rubygems << create(:rubygem, name: "arrakis", number: "1.0.0")
+
+ get "/organizations/#{@organization.to_param}/gems"
+
+ assert page.has_content? "arrakis"
+ end
+
+ test "should get index with no gems" do
+ @organization = create(:organization, owners: [@user])
+
+ get "/organizations/#{@organization.to_param}/gems"
+
+ assert page.has_content? "No gems yet"
+ end
+end
diff --git a/test/integration/organizations_test.rb b/test/integration/organizations_test.rb
new file mode 100644
index 00000000000..b4b3e95faf6
--- /dev/null
+++ b/test/integration/organizations_test.rb
@@ -0,0 +1,62 @@
+require "test_helper"
+
+class OrganizationsTest < ActionDispatch::IntegrationTest
+ setup do
+ @user = create(:user, remember_token_expires_at: Gemcutter::REMEMBER_FOR.from_now)
+ post session_path(session: { who: @user.handle, password: PasswordHelpers::SECURE_TEST_PASSWORD })
+ end
+
+ test "should show an organization" do
+ organization = create(:organization, owners: [@user], handle: "arrakis", name: "Arrakis")
+ organization.rubygems << create(:rubygem, name: "arrakis", number: "1.0.0")
+
+ get "/organizations/#{organization.to_param}"
+
+ assert_response :success
+ assert page.has_content? "arrakis"
+ end
+
+ test "should render not found when an organization doesn't exist" do
+ get "/organizations/notfound"
+
+ assert_response :not_found
+ end
+
+ test "should list no organization for a user with none" do
+ get "/organizations"
+
+ assert_response :success
+ end
+
+ test "should list organizations for a user" do
+ organization = create(:organization, owners: [@user])
+
+ get "/organizations"
+
+ assert_response :success
+ assert page.has_content? organization.name
+ end
+
+ test "should render organization edit form" do
+ organization = create(:organization, owners: [@user])
+
+ get "/organizations/#{organization.to_param}/edit"
+
+ assert_response :success
+ assert_select "form[action=?]", organization_path(organization)
+ assert_select "input[name=?]", "organization[name]"
+ end
+
+ test "should update an organization display name" do
+ organization = create(:organization, owners: [@user])
+
+ patch "/organizations/#{organization.to_param}", params: {
+ organization: { name: "New Name" }
+ }
+
+ assert_redirected_to organization_path(organization)
+ follow_redirect!
+
+ assert page.has_content? "New Name"
+ end
+end
diff --git a/test/integration/rubygems_test.rb b/test/integration/rubygems_test.rb
index 1fc945eed7e..4ec6796efa7 100644
--- a/test/integration/rubygems_test.rb
+++ b/test/integration/rubygems_test.rb
@@ -28,4 +28,29 @@ class RubygemsTest < ActionDispatch::IntegrationTest
assert page.has_content? "Provenance"
end
+
+ test "GET to show for a fully yanked gem as owner" do
+ user = create(:user, remember_token_expires_at: Gemcutter::REMEMBER_FOR.from_now)
+ rubygem = create(:rubygem, owners: [user], number: "1.0.0", created_at: 2.months.ago)
+ version = rubygem.versions.sole
+ user.deletions.create!(version:)
+ rubygem.reload
+
+ assert_predicate rubygem.public_versions.to_a, :empty?
+
+ get "/gems/#{rubygem.name}"
+
+ assert page.has_content? "This gem previously existed, but has been removed by its owner."
+ refute page.has_link? "Owners"
+ refute page.has_link? "Trusted publishers"
+ refute page.has_link? "Security Events"
+
+ post session_path(session: { who: user.handle, password: PasswordHelpers::SECURE_TEST_PASSWORD })
+
+ get "/gems/#{rubygem.name}"
+
+ assert page.has_link? "Owners"
+ assert page.has_link? "Trusted publishers"
+ assert page.has_link? "Security Events"
+ end
end
diff --git a/test/policies/api/nil_class_policy_test.rb b/test/policies/api/nil_class_policy_test.rb
new file mode 100644
index 00000000000..3472f8c9147
--- /dev/null
+++ b/test/policies/api/nil_class_policy_test.rb
@@ -0,0 +1,21 @@
+require "test_helper"
+
+class Api::NilClassPolicyTest < ApiPolicyTestCase
+ def policy!(api_key)
+ Pundit.policy!(api_key, [:api, nil])
+ end
+
+ context "::Scope.resolve" do
+ should "raise" do
+ assert_raises Pundit::NotDefinedError do
+ Api::NilClassPolicy::Scope.new(nil, nil).resolve
+ end
+ end
+ end
+
+ context "#destroy?" do
+ should "not be authorized" do
+ refute_authorized policy!(nil), :destroy?, "Forbidden"
+ end
+ end
+end
diff --git a/test/policies/membership_policy_test.rb b/test/policies/membership_policy_test.rb
index cc3e3465a3c..39a383f707e 100644
--- a/test/policies/membership_policy_test.rb
+++ b/test/policies/membership_policy_test.rb
@@ -96,26 +96,24 @@ def policy!(user, record = Membership)
context "removing owner" do
should "be authorized for org owners only" do
membership = create(:membership, :owner, organization: @organization)
- membership.role = :admin
- assert_authorized policy!(@owner, membership), :update?
+ assert_authorized policy!(@owner, membership), :destroy?
- refute_authorized policy!(@admin, membership), :update?
- refute_authorized policy!(@maintainer, membership), :update?
- refute_authorized policy!(@guest, membership), :update?
+ refute_authorized policy!(@admin, membership), :destroy?
+ refute_authorized policy!(@maintainer, membership), :destroy?
+ refute_authorized policy!(@guest, membership), :destroy?
end
end
context "removing admin" do
should "be authorized for org admins and owners" do
membership = create(:membership, :admin, organization: @organization)
- membership.role = :maintainer
- assert_authorized policy!(@owner, membership), :update?
- assert_authorized policy!(@admin, membership), :update?
+ assert_authorized policy!(@owner, membership), :destroy?
+ assert_authorized policy!(@admin, membership), :destroy?
- refute_authorized policy!(@maintainer, membership), :update?
- refute_authorized policy!(@guest, membership), :update?
+ refute_authorized policy!(@maintainer, membership), :destroy?
+ refute_authorized policy!(@guest, membership), :destroy?
end
end
end
diff --git a/test/policies/rubygem_policy_test.rb b/test/policies/rubygem_policy_test.rb
index 4979fa27697..505dc93a4fd 100644
--- a/test/policies/rubygem_policy_test.rb
+++ b/test/policies/rubygem_policy_test.rb
@@ -33,6 +33,14 @@ def org_policy!(user)
Pundit.policy!(user, @org_rubygem)
end
+ context "#create?" do
+ should "allow users" do
+ assert_authorized policy!(@owner), :create?
+ assert_authorized policy!(@user), :create?
+ refute_authorized policy!(nil), :create?
+ end
+ end
+
context "#configure_oidc?" do
should "only allow the owner" do
assert_authorized policy!(@owner), :configure_oidc?
diff --git a/test/system/profile_test.rb b/test/system/profile_test.rb
new file mode 100644
index 00000000000..5afb8195384
--- /dev/null
+++ b/test/system/profile_test.rb
@@ -0,0 +1,38 @@
+require "application_system_test_case"
+require "test_helper"
+
+class ProfileTest < ApplicationSystemTestCase
+ setup do
+ @user = create(:user, email: "nick@example.com", password: PasswordHelpers::SECURE_TEST_PASSWORD, handle: "nick1", mail_fails: 1)
+ end
+
+ def sign_in
+ visit sign_in_path
+ fill_in "Email or Username", with: @user.reload.email
+ fill_in "Password", with: @user.password
+ click_button "Sign in"
+ end
+
+ test "adding X(formerly Twitter) username without filling in your password" do
+ twitter_username = "nick1twitter"
+
+ sign_in
+ visit profile_path("nick1")
+
+ click_link "Edit Profile"
+ fill_in "user_twitter_username", with: twitter_username
+
+ assert_equal twitter_username, page.find_by_id("user_twitter_username").value
+
+ click_button "Update"
+
+ # Verify that the newly added Twitter username is still on the form so that the user does not need to re-enter it
+ assert_equal twitter_username, page.find_by_id("user_twitter_username").value
+
+ fill_in "Password", with: PasswordHelpers::SECURE_TEST_PASSWORD
+ click_button "Update"
+
+ assert page.has_content? "Your profile was updated."
+ assert_equal twitter_username, page.find_by_id("user_twitter_username").value
+ end
+end
diff --git a/test/views/card/timeline_component_test.rb b/test/views/card/timeline_component_test.rb
new file mode 100644
index 00000000000..8357c0be118
--- /dev/null
+++ b/test/views/card/timeline_component_test.rb
@@ -0,0 +1,16 @@
+require "test_helper"
+
+class Card::TimelineComponentTest < ComponentTest
+ should "render timeline item without link to user" do
+ datetime = 1.2.days.ago
+
+ render Card::TimelineComponent.new do |c|
+ c.timeline_item(datetime) do
+ "additional content"
+ end
+ end
+
+ assert_selector "time[datetime='#{datetime.iso8601}']"
+ assert_text "additional content"
+ end
+end
diff --git a/test/views/card_component_test.rb b/test/views/card_component_test.rb
new file mode 100644
index 00000000000..a36daccf46f
--- /dev/null
+++ b/test/views/card_component_test.rb
@@ -0,0 +1,44 @@
+require "test_helper"
+
+class CardComponentTest < ComponentTest
+ def render(...)
+ response = super
+ Capybara.string(response)
+ end
+
+ should "render a card with title, icon, and list content" do
+ render CardComponent.new do |c|
+ c.head("Gems", icon: "gems", count: 3)
+ c.list do
+ c.list_item_to("rubygem_version_path(1)") { "RubyGem1 (0.0.1)" }
+ c.list_item_to("rubygem_version_path(2)") { "RubyGem2 (0.0.2)" }
+ c.list_item_to("rubygem_version_path(3)") { "RubyGem3 (0.0.3)" }
+ end
+ end
+
+ assert_selector "article"
+ assert_selector "h3", text: "Gems"
+ assert_selector "svg.fill-orange"
+ assert_selector "span", text: "3"
+ assert_link "RubyGem1 (0.0.1)", href: "rubygem_version_path(1)"
+ assert_link "RubyGem2 (0.0.2)", href: "rubygem_version_path(2)"
+ assert_link "RubyGem3 (0.0.3)", href: "rubygem_version_path(3)"
+ refute_text "View all"
+ end
+
+ should "render a card with custom title and scrollable content" do
+ render CardComponent.new do |c|
+ c.head do
+ c.title("History")
+ end
+ c.scrollable do
+ "content"
+ end
+ end
+
+ assert_selector "article"
+ assert_selector "h3", text: "History"
+ assert_text "content"
+ refute_text "View all"
+ end
+end