From 68c5758eccbbe554e2e5f5cc4a7c42d704a8bbf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 14:25:47 +0200 Subject: [PATCH 01/30] Update dependencies, upgrade to Rails 7.1, require Ruby 3.x --- .ruby-version | 2 +- Gemfile | 13 +- Gemfile.lock | 359 +++++++++++++++++++----------------- app/models/user.rb | 2 +- config/application.rb | 2 - config/environments/test.rb | 2 +- 6 files changed, 201 insertions(+), 179 deletions(-) diff --git a/.ruby-version b/.ruby-version index 37c2961..15a2799 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.2 +3.3.0 diff --git a/Gemfile b/Gemfile index ee14a24..06c4c31 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 7.0.2' +gem 'rails', '~> 7.1' # Use Puma as the app server gem 'puma', '~> 4.1' # View components @@ -22,7 +22,7 @@ gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password -gem 'bcrypt', '~> 3.1.7' +gem 'bcrypt', '~> 3.1' # Configuration gem 'dotenv-rails' @@ -62,14 +62,13 @@ gem "sentry-rails" gem 'discourse_api' gem "lnurl" gem 'manifique', git: 'https://gitea.kosmos.org/5apps/manifique.git', branch: 'master' -gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', ref: 'd59f31a' +gem 'nostr' group :development, :test do # Use sqlite3 as the database for Active Record - gem 'sqlite3', '~> 1.4' + gem 'sqlite3', '~> 1.7.2' gem 'rspec-rails' gem 'rails-controller-testing' - gem "byebug", "~> 11.1" end group :development do @@ -90,8 +89,8 @@ group :test do end group :production do - # Use postgresql as the database for Active Record - gem 'pg', '~> 1.2.3' + gem 'pg', '~> 1.5' end + # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/Gemfile.lock b/Gemfile.lock index c04783a..33722e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,141 +1,137 @@ GIT remote: https://gitea.kosmos.org/5apps/manifique.git - revision: 8d79113438ee7c3e4288f840a135622519cffd5c + revision: aa1bd154270805124ffdecaf5c3bd7349fc9c7e1 branch: master specs: - manifique (0.1.0) - faraday (~> 2.7.11) + manifique (1.0.0) + faraday (~> 2.9.0) faraday-follow_redirects (= 0.3.0) - nokogiri (~> 1.15.4) - -GIT - remote: https://gitea.kosmos.org/kosmos/nostr-gem.git - revision: d59f31a3c63c7642fe2d3eb50b785da54fdabfab - ref: d59f31a - specs: - nostr (0.5.0) - bech32 (~> 1.4) - bip-schnorr (~> 0.6) - ecdsa (~> 1.2) - event_emitter (~> 0.2) - faye-websocket (~> 0.11) - json (~> 2.6) + nokogiri (~> 1.16.0) GEM remote: https://rubygems.org/ specs: - actioncable (7.0.8) - actionpack (= 7.0.8) - activesupport (= 7.0.8) + actioncable (7.1.3) + actionpack (= 7.1.3) + activesupport (= 7.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8) - actionpack (= 7.0.8) - activejob (= 7.0.8) - activerecord (= 7.0.8) - activestorage (= 7.0.8) - activesupport (= 7.0.8) + zeitwerk (~> 2.6) + actionmailbox (7.1.3) + actionpack (= 7.1.3) + activejob (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.8) - actionpack (= 7.0.8) - actionview (= 7.0.8) - activejob (= 7.0.8) - activesupport (= 7.0.8) + actionmailer (7.1.3) + actionpack (= 7.1.3) + actionview (= 7.1.3) + activejob (= 7.1.3) + activesupport (= 7.1.3) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp - rails-dom-testing (~> 2.0) - actionpack (7.0.8) - actionview (= 7.0.8) - activesupport (= 7.0.8) - rack (~> 2.0, >= 2.2.4) + rails-dom-testing (~> 2.2) + actionpack (7.1.3) + actionview (= 7.1.3) + activesupport (= 7.1.3) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.8) - actionpack (= 7.0.8) - activerecord (= 7.0.8) - activestorage (= 7.0.8) - activesupport (= 7.0.8) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.3) + actionpack (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8) - activesupport (= 7.0.8) + actionview (7.1.3) + activesupport (= 7.1.3) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.8) - activesupport (= 7.0.8) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.3) + activesupport (= 7.1.3) globalid (>= 0.3.6) - activemodel (7.0.8) - activesupport (= 7.0.8) - activerecord (7.0.8) - activemodel (= 7.0.8) - activesupport (= 7.0.8) - activestorage (7.0.8) - actionpack (= 7.0.8) - activejob (= 7.0.8) - activerecord (= 7.0.8) - activesupport (= 7.0.8) + activemodel (7.1.3) + activesupport (= 7.1.3) + activerecord (7.1.3) + activemodel (= 7.1.3) + activesupport (= 7.1.3) + timeout (>= 0.4.0) + activestorage (7.1.3) + actionpack (= 7.1.3) + activejob (= 7.1.3) + activerecord (= 7.1.3) + activesupport (= 7.1.3) marcel (~> 1.0) - mini_mime (>= 1.1.0) - activesupport (7.0.8) + activesupport (7.1.3) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) - aws-eventstream (1.2.0) - aws-partitions (1.839.0) - aws-sdk-core (3.185.1) - aws-eventstream (~> 1, >= 1.0.2) + aws-eventstream (1.3.0) + aws-partitions (1.886.0) + aws-sdk-core (3.191.0) + aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) + aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.72.0) - aws-sdk-core (~> 3, >= 3.184.0) + aws-sdk-kms (1.77.0) + aws-sdk-core (~> 3, >= 3.191.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.136.0) - aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-s3 (1.143.0) + aws-sdk-core (~> 3, >= 3.191.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.6) - aws-sigv4 (1.6.0) + aws-sigv4 (~> 1.8) + aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) backport (1.2.0) - base64 (0.1.1) - bcrypt (3.1.19) + base64 (0.2.0) + bcrypt (3.1.20) bech32 (1.4.2) thor (>= 1.1.0) - benchmark (0.2.1) + benchmark (0.3.0) + bigdecimal (3.1.6) bindex (0.8.1) bip-schnorr (0.7.0) ecdsa_ext (~> 0.5.0) - brow (0.4.1) builder (3.2.4) - byebug (11.1.3) - capybara (3.39.2) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) chunky_png (1.4.0) - concurrent-ruby (1.2.2) + concurrent-ruby (1.2.3) connection_pool (2.4.1) - crack (0.4.5) + crack (0.4.6) + bigdecimal rexml crass (1.0.6) - cssbundling-rails (1.3.3) + cssbundling-rails (1.4.0) railties (>= 6.0.0) database_cleaner (2.0.2) database_cleaner-active_record (>= 2, < 3) @@ -143,7 +139,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - date (3.3.3) + date (3.3.4) devise (4.9.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -153,7 +149,7 @@ GEM devise_ldap_authenticatable (0.8.7) devise (>= 3.4.1) net-ldap (>= 0.16.0) - diff-lcs (1.5.0) + diff-lcs (1.5.1) discourse_api (2.0.1) faraday (~> 2.7) faraday-follow_redirects @@ -165,6 +161,8 @@ GEM railties (>= 3.2) down (5.4.1) addressable (~> 2.8) + drb (2.2.0) + ruby2_keywords e2mmap (0.1.0) ecdsa (1.2.0) ecdsa_ext (0.5.0) @@ -174,58 +172,61 @@ GEM tzinfo event_emitter (0.2.6) eventmachine (1.2.7) - factory_bot (6.2.1) + factory_bot (6.4.6) activesupport (>= 5.0.0) - factory_bot_rails (6.2.0) - factory_bot (~> 6.2.0) + factory_bot_rails (6.4.3) + factory_bot (~> 6.4) railties (>= 5.0.0) - faker (3.2.1) + faker (3.2.3) i18n (>= 1.8.11, < 2) - faraday (2.7.11) - base64 - faraday-net_http (>= 2.0, < 3.1) - ruby2_keywords (>= 0.0.4) + faraday (2.9.0) + faraday-net_http (>= 2.0, < 3.2) faraday-follow_redirects (0.3.0) faraday (>= 1, < 3) faraday-multipart (1.0.4) multipart-post (~> 2) - faraday-net_http (3.0.2) + faraday-net_http (3.1.0) + net-http faye-websocket (0.11.3) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.16.3) - flipper (1.0.0) - brow (~> 0.4.1) + flipper (1.2.2) concurrent-ruby (< 2) - flipper-active_record (1.0.0) + flipper-active_record (1.2.2) activerecord (>= 4.2, < 8) - flipper (~> 1.0.0) - flipper-ui (1.0.0) + flipper (~> 1.2.2) + flipper-ui (1.2.2) erubi (>= 1.0.0, < 2.0.0) - flipper (~> 1.0.0) + flipper (~> 1.2.2) rack (>= 1.4, < 4) rack-protection (>= 1.5.3, <= 4.0.0) sanitize (< 7) - fugit (1.8.1) + fugit (1.9.0) et-orbi (~> 1, >= 1.2.7) raabro (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) - hashdiff (1.0.1) + hashdiff (1.1.0) i18n (1.14.1) concurrent-ruby (~> 1.0) image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - importmap-rails (1.2.1) + importmap-rails (2.0.1) actionpack (>= 6.0.0) + activesupport (>= 6.0.0) railties (>= 6.0.0) + io-console (0.7.2) + irb (1.11.1) + rdoc + reline (>= 0.4.2) jaro_winkler (1.5.6) jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.6.2) - json (2.6.3) + json (2.7.1) kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) @@ -245,8 +246,8 @@ GEM rb-inotify (~> 0.9, >= 0.9.10) lnurl (1.1.0) bech32 (~> 1.1) - lockbox (1.3.0) - loofah (2.21.4) + lockbox (1.3.2) + loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -260,57 +261,75 @@ GEM mini_magick (4.12.0) mini_mime (1.1.5) mini_portile2 (2.8.5) - minitest (5.20.0) + minitest (5.21.2) multipart-post (2.3.0) - net-imap (0.3.7) + mutex_m (0.2.0) + net-http (0.4.1) + uri + net-imap (0.4.9.1) date net-protocol - net-ldap (0.18.0) + net-ldap (0.19.0) net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout - net-smtp (0.4.0) + net-smtp (0.4.0.1) net-protocol - nio4r (2.5.9) - nokogiri (1.15.4) + nio4r (2.7.0) + nokogiri (1.16.0) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.15.4-arm64-darwin) + nokogiri (1.16.0-arm64-darwin) racc (~> 1.4) - nokogiri (1.15.4-x86_64-linux) + nokogiri (1.16.0-x86_64-linux) racc (~> 1.4) + nostr (0.5.0) + bech32 (~> 1.4) + bip-schnorr (~> 0.6) + ecdsa (~> 1.2) + event_emitter (~> 0.2) + faye-websocket (~> 0.11) + json (~> 2.6) orm_adapter (0.5.0) - pagy (6.1.0) - parallel (1.23.0) - parser (3.2.2.4) + pagy (6.4.3) + parallel (1.24.0) + parser (3.3.0.5) ast (~> 2.4.1) racc - pg (1.2.3) - public_suffix (5.0.3) + pg (1.5.4) + psych (5.1.2) + stringio + public_suffix (5.0.4) puma (4.3.12) nio4r (~> 2.0) raabro (1.4.0) - racc (1.7.1) + racc (1.7.3) rack (2.2.8) - rack-protection (3.1.0) + rack-protection (3.2.0) + base64 (>= 0.1.0) rack (~> 2.2, >= 2.2.4) + rack-session (1.0.2) + rack (< 3) rack-test (2.1.0) rack (>= 1.3) - rails (7.0.8) - actioncable (= 7.0.8) - actionmailbox (= 7.0.8) - actionmailer (= 7.0.8) - actionpack (= 7.0.8) - actiontext (= 7.0.8) - actionview (= 7.0.8) - activejob (= 7.0.8) - activemodel (= 7.0.8) - activerecord (= 7.0.8) - activestorage (= 7.0.8) - activesupport (= 7.0.8) + rackup (1.0.0) + rack (< 3) + webrick + rails (7.1.3) + actioncable (= 7.1.3) + actionmailbox (= 7.1.3) + actionmailer (= 7.1.3) + actionpack (= 7.1.3) + actiontext (= 7.1.3) + actionview (= 7.1.3) + activejob (= 7.1.3) + activemodel (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) bundler (>= 1.15.0) - railties (= 7.0.8) + railties (= 7.1.3) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -325,21 +344,26 @@ GEM rails-settings-cached (2.8.3) activerecord (>= 5.0.0) railties (>= 5.0.0) - railties (7.0.8) - actionpack (= 7.0.8) - activesupport (= 7.0.8) - method_source + railties (7.1.3) + actionpack (= 7.1.3) + activesupport (= 7.1.3) + irb + rackup (>= 1.0.0) rake (>= 12.2) - thor (~> 1.0) - zeitwerk (~> 2.5) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.0.6) + rake (13.1.0) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) rbs (2.8.4) + rdoc (6.6.2) + psych (>= 4.0.0) redis (4.8.1) - regexp_parser (2.8.2) + regexp_parser (2.9.0) + reline (0.4.2) + io-console (~> 0.5) responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) @@ -358,7 +382,7 @@ GEM rspec-mocks (3.12.6) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) - rspec-rails (6.0.3) + rspec-rails (6.1.1) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) @@ -367,19 +391,18 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) rspec-support (3.12.1) - rubocop (1.57.1) - base64 (~> 0.1.1) + rubocop (1.60.2) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.4) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.29.0) + rubocop-ast (1.30.0) parser (>= 3.2.1.0) ruby-progressbar (1.13.0) ruby-vips (2.2.0) @@ -390,10 +413,10 @@ GEM sanitize (6.1.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) - sentry-rails (5.12.0) + sentry-rails (5.16.1) railties (>= 5.0) - sentry-ruby (~> 5.12.0) - sentry-ruby (5.12.0) + sentry-ruby (~> 5.16.1) + sentry-ruby (5.16.1) concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (6.5.12) connection_pool (>= 2.2.5, < 3) @@ -403,7 +426,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 6, < 8) tilt (>= 1.4.0) - solargraph (0.49.0) + solargraph (0.50.0) backport (~> 1.2) benchmark bundler (~> 2.0) @@ -426,15 +449,16 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.6.7) + sqlite3 (1.7.2) mini_portile2 (~> 2.8.0) - sqlite3 (1.6.7-arm64-darwin) - sqlite3 (1.6.7-x86_64-linux) - stimulus-rails (1.3.0) + sqlite3 (1.7.2-arm64-darwin) + sqlite3 (1.7.2-x86_64-linux) + stimulus-rails (1.3.3) railties (>= 6.0.0) + stringio (3.1.0) thor (1.3.0) tilt (2.3.0) - timeout (0.4.0) + timeout (0.4.1) turbo-rails (1.5.0) actionpack (>= 6.0.0) activejob (>= 6.0.0) @@ -442,7 +466,8 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) - view_component (3.6.0) + uri (0.13.0) + view_component (3.10.0) activesupport (>= 5.2.0, < 8.0) concurrent-ruby (~> 1.0) method_source (~> 1.0) @@ -457,6 +482,7 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.8.1) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -472,8 +498,7 @@ PLATFORMS DEPENDENCIES aws-sdk-s3 - bcrypt (~> 3.1.7) - byebug (~> 11.1) + bcrypt (~> 3.1) capybara cssbundling-rails database_cleaner @@ -498,11 +523,11 @@ DEPENDENCIES lockbox manifique! net-ldap - nostr! + nostr pagy (~> 6.0, >= 6.0.2) - pg (~> 1.2.3) + pg (~> 1.5) puma (~> 4.1) - rails (~> 7.0.2) + rails (~> 7.1) rails-controller-testing rails-settings-cached (~> 2.8.3) rqrcode (~> 2.0) @@ -513,7 +538,7 @@ DEPENDENCIES sidekiq-scheduler solargraph sprockets-rails - sqlite3 (~> 1.4) + sqlite3 (~> 1.7.2) stimulus-rails turbo-rails tzinfo-data @@ -523,4 +548,4 @@ DEPENDENCIES webmock BUNDLED WITH - 2.3.7 + 2.5.5 diff --git a/app/models/user.rb b/app/models/user.rb index 27dfbfd..7bc6091 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,7 +7,7 @@ class User < ApplicationRecord attr_accessor :avatar_new attr_accessor :current_password - serialize :preferences, UserPreferences + serialize :preferences, coder: UserPreferences # # Relations diff --git a/config/application.rb b/config/application.rb index fe0be55..89d054a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -42,7 +42,5 @@ module Akkounts config.active_job.queue_adapter = :sidekiq config.action_mailer.deliver_later_queue_name = nil # use "default" queue - - config.active_record.legacy_connection_handling = false end end diff --git a/config/environments/test.rb b/config/environments/test.rb index 7d731e9..a459967 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -26,7 +26,7 @@ Rails.application.configure do config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + config.action_dispatch.show_exceptions = :none # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false From 420442c1c08f920c2c6ef0606532c625e583f38e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 14:34:09 +0200 Subject: [PATCH 02/30] Update Ruby for Dockerfile/Compose --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 612eace..7da4b88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM ruby:2.7.6 +FROM ruby:3.3.0 SHELL ["/bin/bash", "-o", "pipefail", "-c"] From 179a82d2dd6757efa9d8dc3c31b29be0e63b7c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 15:50:25 +0200 Subject: [PATCH 03/30] Use keyword arguments for ApplicationService calls Not all services are using keywords, which breaks those calls in Ruby 3 --- app/controllers/admin/users_controller.rb | 2 +- app/controllers/settings_controller.rb | 12 ++++++------ app/controllers/signup_controller.rb | 4 ++-- app/models/app_catalog/web_app.rb | 2 +- app/models/user.rb | 4 ++-- .../app_catalog_manager/update_metadata.rb | 2 +- app/services/application_service.rb | 4 ++-- app/services/create_account.rb | 14 +++++++------- app/services/ldap_manager/fetch_avatar.rb | 5 ++--- app/services/ldap_manager/update_avatar.rb | 2 +- app/services/ldap_manager/update_display_name.rb | 2 +- app/services/ldap_manager/update_email.rb | 2 +- .../ldap_manager/update_email_maildrop.rb | 2 +- .../ldap_manager/update_email_password.rb | 2 +- app/services/nostr_manager/validate_id.rb | 2 +- app/services/nostr_manager/verify_signature.rb | 2 +- spec/features/settings/email_spec.rb | 2 +- spec/features/settings/profile_spec.rb | 2 +- spec/features/signup_spec.rb | 4 ++-- spec/models/user_spec.rb | 2 +- spec/services/create_account_spec.rb | 16 ++++++++-------- 21 files changed, 44 insertions(+), 45 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 3cb5735..db5da30 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -21,7 +21,7 @@ class Admin::UsersController < Admin::BaseController @services_enabled = @user.services_enabled - @avatar = LdapManager::FetchAvatar.call(cn: @user.cn, ou: @user.ou) + @avatar = LdapManager::FetchAvatar.call(cn: @user.cn) end private diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index f1fa357..b054740 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -24,11 +24,11 @@ class SettingsController < ApplicationController if @user.save if @user.display_name && (@user.display_name != @user.ldap_entry[:display_name]) - LdapManager::UpdateDisplayName.call(@user.dn, @user.display_name) + LdapManager::UpdateDisplayName.call(dn: @user.dn, display_name: @user.display_name) end if @user.avatar_new.present? - LdapManager::UpdateAvatar.call(@user.dn, @user.avatar_new) + LdapManager::UpdateAvatar.call(dn: @user.dn, file: @user.avatar_new) end redirect_to setting_path(@settings_section), flash: { @@ -64,10 +64,10 @@ class SettingsController < ApplicationController @user.current_password = nil session[:new_email_password] = generate_email_password hashed_password = hash_email_password(session[:new_email_password]) - LdapManager::UpdateEmailPassword.call(@user.dn, hashed_password) + LdapManager::UpdateEmailPassword.call(dn: @user.dn, password_hash: hashed_password) if @user.ldap_entry[:email_maildrop] != @user.address - LdapManager::UpdateEmailMaildrop.call(@user.dn, @user.address) + LdapManager::UpdateEmailMaildrop.call(dn: @user.dn, address: @user.address) end redirect_to new_password_services_email_path @@ -88,8 +88,8 @@ class SettingsController < ApplicationController def set_nostr_pubkey signed_event = nostr_event_params[:signed_event].to_h.symbolize_keys - is_valid_id = NostrManager::ValidateId.call(signed_event) - is_valid_sig = NostrManager::VerifySignature.call(signed_event) + is_valid_id = NostrManager::ValidateId.call(event: signed_event) + is_valid_sig = NostrManager::VerifySignature.call(event: signed_event) is_correct_content = signed_event[:content] == "Connect my public key to #{current_user.address} (confirmation #{session[:shared_secret]})" unless is_valid_id && is_valid_sig && is_correct_content diff --git a/app/controllers/signup_controller.rb b/app/controllers/signup_controller.rb index c21820b..236db54 100644 --- a/app/controllers/signup_controller.rb +++ b/app/controllers/signup_controller.rb @@ -96,13 +96,13 @@ class SignupController < ApplicationController session[:new_user] = nil session[:validation_error] = nil - CreateAccount.call( + CreateAccount.call(account: { username: @user.cn, domain: Setting.primary_domain, email: @user.email, password: @user.password, invitation: @invitation - ) + }) end def set_context diff --git a/app/models/app_catalog/web_app.rb b/app/models/app_catalog/web_app.rb index b42bea7..0b88333 100644 --- a/app/models/app_catalog/web_app.rb +++ b/app/models/app_catalog/web_app.rb @@ -11,6 +11,6 @@ class AppCatalog::WebApp < ApplicationRecord if: Proc.new { |a| a.url.present? } def update_metadata - AppCatalogManager::UpdateMetadata.call(self) + AppCatalogManager::UpdateMetadata.call(app: self) end end diff --git a/app/models/user.rb b/app/models/user.rb index 7bc6091..9620bfe 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -92,7 +92,7 @@ class User < ApplicationRecord def devise_after_confirmation if ldap_entry[:mail] != self.email # E-Mail update confirmed - LdapManager::UpdateEmail.call(self.dn, self.email) + LdapManager::UpdateEmail.call(dn: self.dn, address: self.email) else # E-Mail from signup confirmed (i.e. account activation) @@ -164,7 +164,7 @@ class User < ApplicationRecord end def avatar - @avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn, ou: ou) + @avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn) end def services_enabled diff --git a/app/services/app_catalog_manager/update_metadata.rb b/app/services/app_catalog_manager/update_metadata.rb index d78c5d8..c11b864 100644 --- a/app/services/app_catalog_manager/update_metadata.rb +++ b/app/services/app_catalog_manager/update_metadata.rb @@ -3,7 +3,7 @@ require "down" module AppCatalogManager class UpdateMetadata < AppCatalogManagerService - def initialize(app) + def initialize(app:) @app = app end diff --git a/app/services/application_service.rb b/app/services/application_service.rb index 401fe02..2d0394b 100644 --- a/app/services/application_service.rb +++ b/app/services/application_service.rb @@ -1,7 +1,7 @@ class ApplicationService # This enables executing a service's `#call` method directly via # `MyService.call(args)`, without creating a class instance it first. - def self.call(*args, &block) - new(*args, &block).call + def self.call(**args, &block) + new(**args, &block).call end end diff --git a/app/services/create_account.rb b/app/services/create_account.rb index 8c732cf..4e31200 100644 --- a/app/services/create_account.rb +++ b/app/services/create_account.rb @@ -1,11 +1,11 @@ class CreateAccount < ApplicationService - def initialize(args) - @username = args[:username] - @domain = args[:ou] || Setting.primary_domain - @email = args[:email] - @password = args[:password] - @invitation = args[:invitation] - @confirmed = args[:confirmed] + def initialize(account:) + @username = account[:username] + @domain = account[:ou] || Setting.primary_domain + @email = account[:email] + @password = account[:password] + @invitation = account[:invitation] + @confirmed = account[:confirmed] end def call diff --git a/app/services/ldap_manager/fetch_avatar.rb b/app/services/ldap_manager/fetch_avatar.rb index 9d8f2b6..c2643f7 100644 --- a/app/services/ldap_manager/fetch_avatar.rb +++ b/app/services/ldap_manager/fetch_avatar.rb @@ -1,12 +1,11 @@ module LdapManager class FetchAvatar < LdapManagerService - def initialize(cn:, ou: nil) + def initialize(cn:) @cn = cn - @ou = ou end def call - treebase = @ou ? "ou=#{@ou},cn=users,#{suffix}" : ldap_config["base"] + treebase = ldap_config["base"] attributes = %w{ jpegPhoto } filter = Net::LDAP::Filter.eq("cn", @cn) diff --git a/app/services/ldap_manager/update_avatar.rb b/app/services/ldap_manager/update_avatar.rb index f26b92c..f3c8975 100644 --- a/app/services/ldap_manager/update_avatar.rb +++ b/app/services/ldap_manager/update_avatar.rb @@ -2,7 +2,7 @@ require "image_processing/vips" module LdapManager class UpdateAvatar < LdapManagerService - def initialize(dn, file) + def initialize(dn:, file:) @dn = dn @img_data = process(file) end diff --git a/app/services/ldap_manager/update_display_name.rb b/app/services/ldap_manager/update_display_name.rb index 2d3e90f..85418d3 100644 --- a/app/services/ldap_manager/update_display_name.rb +++ b/app/services/ldap_manager/update_display_name.rb @@ -1,6 +1,6 @@ module LdapManager class UpdateDisplayName < LdapManagerService - def initialize(dn, display_name) + def initialize(dn:, display_name:) @dn = dn @display_name = display_name end diff --git a/app/services/ldap_manager/update_email.rb b/app/services/ldap_manager/update_email.rb index 80f40e4..9df3f17 100644 --- a/app/services/ldap_manager/update_email.rb +++ b/app/services/ldap_manager/update_email.rb @@ -1,6 +1,6 @@ module LdapManager class UpdateEmail < LdapManagerService - def initialize(dn, address) + def initialize(dn:, address:) @dn = dn @address = address end diff --git a/app/services/ldap_manager/update_email_maildrop.rb b/app/services/ldap_manager/update_email_maildrop.rb index d26cf16..1945308 100644 --- a/app/services/ldap_manager/update_email_maildrop.rb +++ b/app/services/ldap_manager/update_email_maildrop.rb @@ -1,6 +1,6 @@ module LdapManager class UpdateEmailMaildrop < LdapManagerService - def initialize(dn, address) + def initialize(dn:, address:) @dn = dn @address = address end diff --git a/app/services/ldap_manager/update_email_password.rb b/app/services/ldap_manager/update_email_password.rb index e9cde6a..7ef327a 100644 --- a/app/services/ldap_manager/update_email_password.rb +++ b/app/services/ldap_manager/update_email_password.rb @@ -1,6 +1,6 @@ module LdapManager class UpdateEmailPassword < LdapManagerService - def initialize(dn, password_hash) + def initialize(dn:, password_hash:) @dn = dn @password_hash = password_hash end diff --git a/app/services/nostr_manager/validate_id.rb b/app/services/nostr_manager/validate_id.rb index d184b75..e838441 100644 --- a/app/services/nostr_manager/validate_id.rb +++ b/app/services/nostr_manager/validate_id.rb @@ -1,6 +1,6 @@ module NostrManager class ValidateId < NostrManagerService - def initialize(event) + def initialize(event:) @event = Nostr::Event.new(**event) end diff --git a/app/services/nostr_manager/verify_signature.rb b/app/services/nostr_manager/verify_signature.rb index 63b0489..9c62234 100644 --- a/app/services/nostr_manager/verify_signature.rb +++ b/app/services/nostr_manager/verify_signature.rb @@ -1,6 +1,6 @@ module NostrManager class VerifySignature < NostrManagerService - def initialize(event) + def initialize(event:) @event = Nostr::Event.new(**event) end diff --git a/spec/features/settings/email_spec.rb b/spec/features/settings/email_spec.rb index 348d0be..b8bac1d 100644 --- a/spec/features/settings/email_spec.rb +++ b/spec/features/settings/email_spec.rb @@ -50,7 +50,7 @@ RSpec.describe 'E-Mail settings', type: :feature do expect(LdapManager::UpdateEmailPassword).to receive(:call).and_return(true) expect(LdapManager::UpdateEmailMaildrop).to receive(:call) - .with(user.dn, user.address).and_return(true) + .with(dn: user.dn, address: user.address).and_return(true) visit setting_path(:email) fill_in 'Current account password', with: "valid password" diff --git a/spec/features/settings/profile_spec.rb b/spec/features/settings/profile_spec.rb index d6eb8ff..764da2d 100644 --- a/spec/features/settings/profile_spec.rb +++ b/spec/features/settings/profile_spec.rb @@ -29,7 +29,7 @@ RSpec.describe 'Profile settings', type: :feature do scenario 'works with valid input' do expect(LdapManager::UpdateDisplayName).to receive(:call) - .with(user.dn, "Marky Mark").and_return(true) + .with(dn: user.dn, display_name: "Marky Mark").and_return(true) visit setting_path(:profile) fill_in 'Display name', with: "Marky Mark" diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index 30511a7..e668e9d 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -53,7 +53,7 @@ RSpec.describe "Signup", type: :feature do expect(page).to have_content("Choose a password") expect(CreateAccount).to receive(:call) - .with({ + .with(account: { username: "tony", domain: "kosmos.org", email: "tony@example.com", password: "a-valid-password", invitation: Invitation.last @@ -97,7 +97,7 @@ RSpec.describe "Signup", type: :feature do expect(page).to have_content("Password is too short") expect(CreateAccount).to receive(:call) - .with({ + .with(account: { username: "tony", domain: "kosmos.org", email: "tony@example.com", password: "a-valid-password", invitation: Invitation.last diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5253c62..7011793 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -190,7 +190,7 @@ RSpec.describe User, type: :model do it "updates the LDAP 'mail' attribute" do expect(LdapManager::UpdateEmail).to receive(:call) - .with("cn=willherschel,ou=kosmos.org,cn=users,dc=kosmos,dc=org", "will@hrsch.el") + .with(dn: "cn=willherschel,ou=kosmos.org,cn=users,dc=kosmos,dc=org", address: "will@hrsch.el") user.send :devise_after_confirmation end diff --git a/spec/services/create_account_spec.rb b/spec/services/create_account_spec.rb index 064d1ab..5155f19 100644 --- a/spec/services/create_account_spec.rb +++ b/spec/services/create_account_spec.rb @@ -2,11 +2,11 @@ require 'rails_helper' RSpec.describe CreateAccount, type: :model do describe "#create_user_in_database" do - let(:service) { CreateAccount.new( + let(:service) { CreateAccount.new(account: { username: 'isaacnewton', email: 'isaacnewton@example.com', password: 'bright-ideas-in-autumn' - )} + })} it "creates a new user record in the akkounts database" do expect(User.count).to eq(0) @@ -19,12 +19,12 @@ RSpec.describe CreateAccount, type: :model do describe "#update_invitation" do let(:invitation) { create :invitation } - let(:service) { CreateAccount.new( + let(:service) { CreateAccount.new(account: { username: 'isaacnewton', email: 'isaacnewton@example.com', password: 'bright-ideas-in-autumn', invitation: invitation - )} + })} before(:each) do service.send(:update_invitation, 23) @@ -42,11 +42,11 @@ RSpec.describe CreateAccount, type: :model do describe "#add_ldap_document" do include ActiveJob::TestHelper - let(:service) { CreateAccount.new( + let(:service) { CreateAccount.new(account: { username: 'halfinney', email: 'halfinney@example.com', password: 'remember-remember-the-5th-of-november' - )} + })} it "enqueues a job to create the LDAP user document" do service.send(:add_ldap_document) @@ -68,10 +68,10 @@ RSpec.describe CreateAccount, type: :model do describe "#create_lndhub_account" do include ActiveJob::TestHelper - let(:service) { CreateAccount.new( + let(:service) { CreateAccount.new(account: { username: 'halfinney', email: 'halfinney@example.com', password: 'bright-ideas-in-winter' - )} + })} let(:new_user) { create :user, cn: "halfinney", ou: "kosmos.org" } it "enqueues a job to create an LndHub account" do From 28cfe4b1e75bd252d8f8b1e93a32d1d3e596a9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 16:58:04 +0200 Subject: [PATCH 04/30] Fix deprecation warning --- spec/rails_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index ae6309d..7f6ac8c 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -39,7 +39,7 @@ rescue ActiveRecord::PendingMigrationError => e end RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.fixture_paths = ["#{::Rails.root}/spec/fixtures"] # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false From 7e6e917ae1a55ea4affb18bf18de9ab6bf5b5c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 17:16:32 +0200 Subject: [PATCH 05/30] Use new CI image with Ruby 3.3.0 --- .drone.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index e17d39a..90d510d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,7 +17,7 @@ steps: branch: - master - name: rspec - image: gitea.kosmos.org/kosmos/akkounts-ci:0.1.0 + image: gitea.kosmos.org/kosmos/akkounts-ci:0.9.1 environment: RAILS_ENV: test REDIS_URL: redis://redis:6379/0 @@ -28,6 +28,8 @@ steps: - bundle config set cache_path 'vendor/cache' - bundle config set with 'development test' - bundle install --jobs=3 --retry=3 + - bundle exec rails db:create + - bundle exec rails db:migrate - yarn install - rake css:build - bundle exec rspec From 7796a22491f5b355ac68a98a16db65c079cc2422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 2 Feb 2024 17:55:20 +0200 Subject: [PATCH 06/30] Switch to newly published manifique gem --- Gemfile | 2 +- Gemfile.lock | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 06c4c31..beea23a 100644 --- a/Gemfile +++ b/Gemfile @@ -61,7 +61,7 @@ gem "sentry-rails" # Services gem 'discourse_api' gem "lnurl" -gem 'manifique', git: 'https://gitea.kosmos.org/5apps/manifique.git', branch: 'master' +gem 'manifique' gem 'nostr' group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 33722e3..6396dbd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,13 +1,3 @@ -GIT - remote: https://gitea.kosmos.org/5apps/manifique.git - revision: aa1bd154270805124ffdecaf5c3bd7349fc9c7e1 - branch: master - specs: - manifique (1.0.0) - faraday (~> 2.9.0) - faraday-follow_redirects (= 0.3.0) - nokogiri (~> 1.16.0) - GEM remote: https://rubygems.org/ specs: @@ -255,6 +245,10 @@ GEM net-imap net-pop net-smtp + manifique (1.0.1) + faraday (~> 2.9.0) + faraday-follow_redirects (= 0.3.0) + nokogiri (~> 1.16.0) marcel (1.0.2) matrix (0.4.2) method_source (1.0.0) @@ -521,7 +515,7 @@ DEPENDENCIES listen (~> 3.2) lnurl lockbox - manifique! + manifique net-ldap nostr pagy (~> 6.0, >= 6.0.2) From 1c54e4c0b5999f160b49a14f48977c5c960382f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sat, 3 Feb 2024 11:35:41 +0200 Subject: [PATCH 07/30] New CI image Dockerfile --- ci/Dockerfile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ci/Dockerfile b/ci/Dockerfile index 2393eb5..d595128 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -1,4 +1,10 @@ # syntax=docker/dockerfile:1 -FROM guildeducation/rails:2.7.2-14.20.0 +FROM ruby:3.3.0 -RUN apt-get update -qq && apt-get install -y --no-install-recommends ldap-utils libvips +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update -qq && apt-get install -y --no-install-recommends curl \ + ldap-utils tini libvips +RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - +RUN apt-get update && apt-get install -y nodejs +RUN npm install -g yarn From 176b1a10c6056fe6b79498e1c57c31d2e4947a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:10:14 +0100 Subject: [PATCH 08/30] Remove obsolete closing tag --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ef75312..2bd3f23 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -77,7 +77,7 @@
- <%= current_user.address %> + <%= current_user.address %>
<%= link_to "Log out", destroy_user_session_path, From 3b961304914a51e6397199234e604b2984f76a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:26:28 +0100 Subject: [PATCH 09/30] Upgrade web-console, fix it for Docker Was failing silently in Docker, because the warnings were turned off. --- Gemfile | 2 +- Gemfile.lock | 2 +- config/environments/development.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index beea23a..f8e375e 100644 --- a/Gemfile +++ b/Gemfile @@ -73,7 +73,7 @@ end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. - gem 'web-console', '>= 3.3.0' + gem 'web-console', '~> 4.2' gem 'listen', '~> 3.2' gem 'letter_opener' gem 'letter_opener_web' diff --git a/Gemfile.lock b/Gemfile.lock index 6396dbd..ff21ad9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -538,7 +538,7 @@ DEPENDENCIES tzinfo-data view_component warden - web-console (>= 3.3.0) + web-console (~> 4.2) webmock BUNDLED WITH diff --git a/config/environments/development.rb b/config/environments/development.rb index 1f96c8f..e13b809 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -69,7 +69,7 @@ Rails.application.configure do config.action_mailer.default_url_options = { host: "localhost:3000", protocol: "http" } # Allow requests from any IP - config.web_console.whiny_requests = false + config.web_console.permissions = '0.0.0.0/0' if ENV["S3_ENABLED"] config.active_storage.service = :s3 From c9052b35f6801a93bbbebac4dd15b5d34c379ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:29:11 +0100 Subject: [PATCH 10/30] Database update for Flipper --- ...80515_change_flipper_gates_value_to_text.rb | 18 ++++++++++++++++++ db/schema.rb | 10 +++++----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20240207080515_change_flipper_gates_value_to_text.rb diff --git a/db/migrate/20240207080515_change_flipper_gates_value_to_text.rb b/db/migrate/20240207080515_change_flipper_gates_value_to_text.rb new file mode 100644 index 0000000..cfa1eb6 --- /dev/null +++ b/db/migrate/20240207080515_change_flipper_gates_value_to_text.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class ChangeFlipperGatesValueToText < ActiveRecord::Migration[7.1] + def up + # Ensure this incremental update migration is idempotent + return unless connection.column_exists? :flipper_gates, :value, :string + + if index_exists? :flipper_gates, [:feature_key, :key, :value] + remove_index :flipper_gates, [:feature_key, :key, :value] + end + change_column :flipper_gates, :value, :text + add_index :flipper_gates, [:feature_key, :key, :value], unique: true, length: { value: 255 } + end + + def down + change_column :flipper_gates, :value, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f830293..e558da8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,12 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_10_24_104909) do +ActiveRecord::Schema[7.1].define(version: 2024_02_07_080515) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false - t.bigint "record_id", null: false - t.bigint "blob_id", null: false + t.integer "record_id", null: false + t.integer "blob_id", null: false t.datetime "created_at", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true @@ -34,7 +34,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_24_104909) do end create_table "active_storage_variant_records", force: :cascade do |t| - t.bigint "blob_id", null: false + t.integer "blob_id", null: false t.string "variation_digest", null: false t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end @@ -69,7 +69,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_24_104909) do create_table "flipper_gates", force: :cascade do |t| t.string "feature_key", null: false t.string "key", null: false - t.string "value" + t.text "value" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true From a7cbd8ce36937db357145df04cd1e8d5c99ae408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:48:30 +0100 Subject: [PATCH 11/30] Allow disabling S3 explicitly, disable in Docker Compose For example when there is a .env.development for running the app on a host machine directly, but as a developer you also want to run it with Docker Compose from time to time. --- app/models/setting.rb | 3 +++ config/environments/development.rb | 2 +- config/environments/production.rb | 2 +- config/storage.yml | 2 +- docker-compose.yml | 2 ++ 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/models/setting.rb b/app/models/setting.rb index 27acdcc..daa4b29 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -15,6 +15,9 @@ class Setting < RailsSettings::Base field :redis_url, type: :string, default: ENV["REDIS_URL"] || "redis://localhost:6379/0" + field :s3_enabled, type: :boolean, + default: ENV["S3_ENABLED"] && ENV["S3_ENABLED"].to_s != "false" + # # Registrations # diff --git a/config/environments/development.rb b/config/environments/development.rb index e13b809..9f73578 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -71,7 +71,7 @@ Rails.application.configure do # Allow requests from any IP config.web_console.permissions = '0.0.0.0/0' - if ENV["S3_ENABLED"] + if ENV["S3_ENABLED"] && ENV["S3_ENABLED"].to_s != "false" config.active_storage.service = :s3 else config.active_storage.service = :local diff --git a/config/environments/production.rb b/config/environments/production.rb index 5adf41e..16e7fa5 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -110,7 +110,7 @@ Rails.application.configure do # Set this to true and configure the email server for immediate delivery to raise delivery errors. config.action_mailer.raise_delivery_errors = true - if ENV["S3_ENABLED"] + if ENV["S3_ENABLED"] && ENV["S3_ENABLED"].to_s != "false" config.active_storage.service = :s3 else config.active_storage.service = :local diff --git a/config/storage.yml b/config/storage.yml index 3ddfbb8..9a15623 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -6,7 +6,7 @@ test: service: Disk root: <%= Rails.root.join("tmp/storage") %> -<% if ENV["S3_ENABLED"] %> +<% if ENV["S3_ENABLED"] && ENV["S3_ENABLED"].to_s != "false" %> s3: service: S3 endpoint: <%= ENV["S3_ENDPOINT"] %> diff --git a/docker-compose.yml b/docker-compose.yml index 5106dfd..6e0ff50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,6 +44,7 @@ services: REDIS_URL: redis://redis:6379/0 RS_REDIS_URL: redis://redis:6379/1 RS_STORAGE_URL: "http://localhost:4567" + S3_ENABLED: false depends_on: - ldap - redis @@ -67,6 +68,7 @@ services: REDIS_URL: redis://redis:6379/0 RS_REDIS_URL: redis://redis:6379/1 RS_STORAGE_URL: "http://localhost:4567" + S3_ENABLED: false depends_on: - ldap - redis From 70ac3b0a7087a1ce9c13b6f1857ac68262237738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:51:53 +0100 Subject: [PATCH 12/30] Fix RS dashboard for auths without Web App RS auths without a valid domain name will not fetch any metadata and therefore not create a WebApp record. This fixes icons being looked up anyway, resulting in exceptions --- .../web_app_icon_component.html.erb | 5 +++++ .../app_catalog/web_app_icon_component.rb | 21 +++++++++++++++++++ app/components/rs_auth_component.html.erb | 10 ++------- app/views/icons/_remotestorage.html.erb | 2 +- .../web_app_icon_component_spec.rb | 11 ++++++++++ 5 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 app/components/app_catalog/web_app_icon_component.html.erb create mode 100644 app/components/app_catalog/web_app_icon_component.rb create mode 100644 spec/components/app_catalog/web_app_icon_component_spec.rb diff --git a/app/components/app_catalog/web_app_icon_component.html.erb b/app/components/app_catalog/web_app_icon_component.html.erb new file mode 100644 index 0000000..3f9c5f3 --- /dev/null +++ b/app/components/app_catalog/web_app_icon_component.html.erb @@ -0,0 +1,5 @@ +<% if @image_url %> + <%= image_tag @image_url, class: "h-full w-full" %> +<% else %> + <%= render partial: "icons/remotestorage", locals: { custom_class: "h-full w-full p-0.5 text-gray-200" } %> +<% end %> diff --git a/app/components/app_catalog/web_app_icon_component.rb b/app/components/app_catalog/web_app_icon_component.rb new file mode 100644 index 0000000..8421d4f --- /dev/null +++ b/app/components/app_catalog/web_app_icon_component.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module AppCatalog + class WebAppIconComponent < ViewComponent::Base + def initialize(web_app:) + if web_app&.icon&.attached? + @image_url = image_url_for(web_app.icon) + elsif web_app&.apple_touch_icon&.attached? + @image_url = image_url_for(web_app.apple_touch_icon) + end + end + + def image_url_for(attachment) + if Setting.s3_enabled? + s3_image_url(attachment) + else + Rails.application.routes.url_helpers.rails_blob_path(attachment, only_path: true) + end + end + end +end diff --git a/app/components/rs_auth_component.html.erb b/app/components/rs_auth_component.html.erb index 18ffcc8..535dc1b 100644 --- a/app/components/rs_auth_component.html.erb +++ b/app/components/rs_auth_component.html.erb @@ -1,16 +1,10 @@
- <% if @web_app.icon.attached? %> - <%= image_tag s3_image_url(@web_app.icon), class: "h-full w-full" %> - <% elsif @web_app.apple_touch_icon.attached? %> - <%= image_tag s3_image_url(@web_app.apple_touch_icon), class: "h-full w-full" %> - <% else %> - <%= render partial: "icons/remotestorage", locals: { custom_class: "h-full w-full p-0.5 text-gray-200" } %> - <% end %> + <%= render AppCatalog::WebAppIconComponent.new(web_app: @web_app) %>

- <%= @web_app.name %> + <%= @web_app&.name || @auth.app_name %>

<%= @auth.client_id %> diff --git a/app/views/icons/_remotestorage.html.erb b/app/views/icons/_remotestorage.html.erb index 2daafc4..4de0c04 100644 --- a/app/views/icons/_remotestorage.html.erb +++ b/app/views/icons/_remotestorage.html.erb @@ -1,5 +1,5 @@ - + diff --git a/spec/components/app_catalog/web_app_icon_component_spec.rb b/spec/components/app_catalog/web_app_icon_component_spec.rb new file mode 100644 index 0000000..f9ed3e5 --- /dev/null +++ b/spec/components/app_catalog/web_app_icon_component_spec.rb @@ -0,0 +1,11 @@ +require "rails_helper" + +RSpec.describe AppCatalog::WebAppIconComponent, type: :component do + describe "No web app given" do + it "renders the default icon" do + expect( + render_inline(described_class.new(web_app: nil)) {}.to_html + ).to include("icon-remotestorage") + end + end +end From 84e915ece95250a0eef1884bc4ad94bf7a3fb14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 12:59:37 +0100 Subject: [PATCH 13/30] Allow custom path for ActiveStorage local/disk backend --- config/storage.yml | 2 +- docker-compose.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/storage.yml b/config/storage.yml index 9a15623..010aeb8 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -1,6 +1,6 @@ local: service: Disk - root: <%= Rails.root.join("storage") %> + root: <%= ENV["ACTIVE_STORAGE_PATH"] || Rails.root.join("storage") %> test: service: Disk diff --git a/docker-compose.yml b/docker-compose.yml index 6e0ff50..340925f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,7 @@ services: LDAP_ADMIN_PASSWORD: passthebutter LDAP_USE_TLS: "false" REDIS_URL: redis://redis:6379/0 + ACTIVE_STORAGE_PATH: "/akkounts/tmp/attachments" RS_REDIS_URL: redis://redis:6379/1 RS_STORAGE_URL: "http://localhost:4567" S3_ENABLED: false From 411587456b4d3c40354fc62fdf040ab31580e907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 13:01:19 +0100 Subject: [PATCH 14/30] Destroy dependent RS auths when destroying a WebApp --- app/models/app_catalog/web_app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/app_catalog/web_app.rb b/app/models/app_catalog/web_app.rb index 0b88333..388e610 100644 --- a/app/models/app_catalog/web_app.rb +++ b/app/models/app_catalog/web_app.rb @@ -1,7 +1,7 @@ class AppCatalog::WebApp < ApplicationRecord store :metadata, coder: JSON - has_many :remote_storage_authorizations + has_many :remote_storage_authorizations, dependent: :destroy has_one_attached :icon has_one_attached :apple_touch_icon From a7410058fadd27eef1147977499a244fb46c2494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 13:02:08 +0100 Subject: [PATCH 15/30] Save WebApp before fetching icons --- app/services/app_catalog_manager/update_metadata.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/app_catalog_manager/update_metadata.rb b/app/services/app_catalog_manager/update_metadata.rb index c11b864..a23b3d6 100644 --- a/app/services/app_catalog_manager/update_metadata.rb +++ b/app/services/app_catalog_manager/update_metadata.rb @@ -18,6 +18,8 @@ module AppCatalogManager @app.metadata[prop] = metadata.send(prop) if prop end + @app.save! + if icon = metadata.select_icon(sizes: "256x256") || icon = metadata.select_icon(sizes: "192x192") attach_remote_image(:icon, icon) @@ -27,8 +29,6 @@ module AppCatalogManager if apple_touch_icon = metadata.select_icon(purpose: "apple-touch-icon") attach_remote_image(:apple_touch_icon, apple_touch_icon) end - - @app.save! rescue Manifique::Error => e msg = "Fetching web app manifest failed for #{e.url}: #{e.type}" Rails.logger.warn(msg) From 3f110995a4ca8b440e5b0695a2d9dd9ef0aec65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 13:02:47 +0100 Subject: [PATCH 16/30] Add timestamp to icon filenames There can be race condition when a background job is supposed to delete an icon while there is a new one being attached. Also, this encodes the date/time when the icon has been added, for inspection and convenience. --- app/services/app_catalog_manager/update_metadata.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/app_catalog_manager/update_metadata.rb b/app/services/app_catalog_manager/update_metadata.rb index a23b3d6..d212a45 100644 --- a/app/services/app_catalog_manager/update_metadata.rb +++ b/app/services/app_catalog_manager/update_metadata.rb @@ -42,8 +42,8 @@ module AppCatalogManager else download_url = "#{@app.url}/#{icon["src"].gsub(/^\//,'')}" end - filename = "#{attachment_name}.png" - key = "web_apps/#{@app.id}/icons/#{attachment_name}.png" + filename = "#{attachment_name}-#{Time.now.to_i}.png" + key = "web_apps/#{@app.id}/icons/#{filename}" begin tempfile = Down.download(download_url) From bd1b177993f4189fd86d82a609442de164c94afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 8 Feb 2024 13:36:17 +0100 Subject: [PATCH 17/30] Rescue all icon download/upload errors, send to Sentry --- app/services/app_catalog_manager/update_metadata.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/services/app_catalog_manager/update_metadata.rb b/app/services/app_catalog_manager/update_metadata.rb index d212a45..a506013 100644 --- a/app/services/app_catalog_manager/update_metadata.rb +++ b/app/services/app_catalog_manager/update_metadata.rb @@ -20,6 +20,8 @@ module AppCatalogManager @app.save! + # TODO move icon downloads to separate, async job + if icon = metadata.select_icon(sizes: "256x256") || icon = metadata.select_icon(sizes: "192x192") attach_remote_image(:icon, icon) @@ -49,7 +51,12 @@ module AppCatalogManager tempfile = Down.download(download_url) @app.send(attachment_name).attach(key: key, io: tempfile, filename: filename) rescue Down::NotFound - Rails.logger.warn "Icon download failed: NotFound error for #{download_url}" + msg = "Download of \"#{attachment_name}\" failed: NotFound error for #{download_url}" + Rails.logger.warn(msg) + Sentry.capture_message(msg) + rescue => e + Rails.logger.warn "Saving attachment \"#{attachment_name}\" failed: \"#{e.message}\"" + Sentry.capture_exception(e) if Setting.sentry_enabled? end end end From 22ffcd54db94a643e8dc21066c57b902dca8f569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 9 Feb 2024 17:58:28 +0100 Subject: [PATCH 18/30] Patch away a deprecation warning caused by Devise --- config/initializers/devise.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index bb264bf..d59cdd9 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -325,3 +325,10 @@ Devise.setup do |config| # changed. Defaults to true, so a user is signed in automatically after changing a password. # config.sign_in_after_change_password = true end + +# https://github.com/heartcombo/devise/issues/5644 +class Devise::SecretKeyFinder + def find + @application.secret_key_base + end +end From 67689dcce3d61c0a58728c2848650a1cfacbd5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 9 Feb 2024 17:53:02 +0100 Subject: [PATCH 19/30] Add service for creating invites --- app/mailers/notification_mailer.rb | 6 +++ app/services/create_invitations.rb | 17 ++++++++ .../new_invitations_available.text.erb | 11 +++++ spec/services/create_invitations_spec.rb | 40 +++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 app/services/create_invitations.rb create mode 100644 app/views/notification_mailer/new_invitations_available.text.erb create mode 100644 spec/services/create_invitations_spec.rb diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 81132b9..004f94f 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -17,4 +17,10 @@ class NotificationMailer < ApplicationMailer @subject = "New app connected to your storage" mail to: @user.email, subject: @subject end + + def new_invitations_available + @user = params[:user] + @subject = "New invitations added to your account" + mail to: @user.email, subject: @subject + end end diff --git a/app/services/create_invitations.rb b/app/services/create_invitations.rb new file mode 100644 index 0000000..3003b1a --- /dev/null +++ b/app/services/create_invitations.rb @@ -0,0 +1,17 @@ +class CreateInvitations < ApplicationService + def initialize(user:, amount:, notify: true) + @user = user + @amount = amount + @notify = notify + end + + def call + @amount.times do + Invitation.create(user: @user) + end + + if @notify + NotificationMailer.with(user: @user).new_invitations_available.deliver_later + end + end +end diff --git a/app/views/notification_mailer/new_invitations_available.text.erb b/app/views/notification_mailer/new_invitations_available.text.erb new file mode 100644 index 0000000..9cf8adc --- /dev/null +++ b/app/views/notification_mailer/new_invitations_available.text.erb @@ -0,0 +1,11 @@ +Hi <%= @user.display_name.presence || @user.cn %>, + +New invitations have just been added to your Kosmos account, so you can invite more people to our cooperative services: + +<%= invitations_url %> + +Have a nice day! + +--- + +Tip: if you want to invite someone you're meeting in person, log into your account panel on a mobile device and let people scan the invitation QR code from theirs. diff --git a/spec/services/create_invitations_spec.rb b/spec/services/create_invitations_spec.rb new file mode 100644 index 0000000..4e5de23 --- /dev/null +++ b/spec/services/create_invitations_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +RSpec.describe CreateInvitations, type: :model do + include ActiveJob::TestHelper + + let(:user) { create :user } + + describe "#call" do + before do + CreateInvitations.call(user: user, amount: 5) + end + + after(:each) { clear_enqueued_jobs } + + it "creates the right amount of invitations for the given user" do + expect(user.invitations.count).to eq(5) + end + + it "sends an email notification to the user" do + expect(enqueued_jobs.size).to eq(1) + expect(enqueued_jobs.first["job_class"]).to eq("ActionMailer::MailDeliveryJob") + args = enqueued_jobs.first['arguments'] + expect(args[0]).to eq("NotificationMailer") + expect(args[1]).to eq("new_invitations_available") + expect(args[3]["params"]["user"]["_aj_globalid"]).to eq("gid://akkounts/User/1") + end + end + + describe "#call with notification disabled" do + before do + CreateInvitations.call(user: user, amount: 3, notify: false) + end + + after(:each) { clear_enqueued_jobs } + + it "does not send an email notification to the user" do + expect(enqueued_jobs.size).to eq(0) + end + end +end From fcda3b9c8c243e32c3dfb4e622f9ba57b4f1e5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 9 Feb 2024 18:57:07 +0100 Subject: [PATCH 20/30] WIP Make dropdowns more configurable, add invitations menu to admin page --- app/components/dropdown_component.html.erb | 14 +++++++++++--- app/components/dropdown_component.rb | 5 ++++- app/views/admin/users/show.html.erb | 21 ++++++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/app/components/dropdown_component.html.erb b/app/components/dropdown_component.html.erb index 3ea3bce..eb04538 100644 --- a/app/components/dropdown_component.html.erb +++ b/app/components/dropdown_component.html.erb @@ -2,13 +2,21 @@

+ <% if @size == :large %> - <%= render partial: "icons/kebab-menu", locals: { - custom_class: "inline text-gray-500 h-6 w-6" - } %> + <%= render partial: "icons/#{@icon_name}", + locals: { custom_class: "inline text-gray-500 h-6 w-6" } %> + <% elsif @size == :small %> + + + <%= render partial: "icons/#{@icon_name}", + locals: { custom_class: "inline h-4 w-4" } %> + + + <% end %>
Invitations available - <%= @user.invitations.count %> +
+ + <%= @user.invitations.count %> + + + <%= render DropdownComponent.new(size: :small, icon_name: "edit") do %> + <%= render DropdownLinkComponent.new( + href: "" + ) do %> + Add more + <% end %> + <%= render DropdownLinkComponent.new( + href: "", + separator: true, add_class: "text-red-700" + ) do %> + Remove all + <% end %> + <% end %> + +
From 8747ce4eb018fcb49c193883241f7cfe14daeaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sat, 10 Feb 2024 08:54:28 +0100 Subject: [PATCH 21/30] Remove multi-domain support on admin user pages refs #166 --- app/controllers/admin/users_controller.rb | 7 +++---- app/views/admin/users/index.html.erb | 18 ++---------------- app/views/admin/users/show.html.erb | 2 +- config/routes.rb | 7 ++++++- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index db5da30..1849fa6 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -4,8 +4,7 @@ class Admin::UsersController < Admin::BaseController def index ldap = LdapService.new - @ou = params[:ou] || Setting.primary_domain - @orgs = ldap.fetch_organizations + @ou = Setting.primary_domain @pagy, @users = pagy(User.where(ou: @ou).order(cn: :asc)) @stats = { @@ -27,8 +26,8 @@ class Admin::UsersController < Admin::BaseController private def set_user - address = params[:address].split("@") - @user = User.where(cn: address.first, ou: address.last).first + @user = User.find_by(cn: params[:username], ou: Setting.primary_domain) + http_status :not_found unless @user end def set_current_section diff --git a/app/views/admin/users/index.html.erb b/app/views/admin/users/index.html.erb index e0eb90d..830057a 100644 --- a/app/views/admin/users/index.html.erb +++ b/app/views/admin/users/index.html.erb @@ -1,4 +1,4 @@ -<%= render HeaderComponent.new(title: "Users: #{@ou}") %> +<%= render HeaderComponent.new(title: "Users") %> <%= render MainSimpleComponent.new do %>
@@ -16,19 +16,6 @@ <% end %>
- <% if @orgs.length > 1 %> -
- -
    - <% @orgs.each do |org| %> -
  • - <%= link_to org[:ou], admin_users_path(ou: org[:ou]), class: "ks-text-link" %> -
  • - <% end %> -
-
- <% end %> -
@@ -36,13 +23,12 @@ - <% @users.each do |user| %> - + diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb index dc904fd..0003172 100644 --- a/app/views/admin/users/show.html.erb +++ b/app/views/admin/users/show.html.erb @@ -1,4 +1,4 @@ -<%= render HeaderComponent.new(title: "User: #{@user.address}") %> +<%= render HeaderComponent.new(title: "User: #{@user.cn}") %> <%= render MainSimpleComponent.new do %>
diff --git a/config/routes.rb b/config/routes.rb index 643b095..8dee02d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -73,9 +73,14 @@ Rails.application.routes.draw do namespace :admin do root to: 'dashboard#index' - resources 'users', param: 'address', only: ['index', 'show'], constraints: { address: /.*/ } + resources 'users', param: 'username', only: ['index', 'show'] do + + end + get 'invitations', to: 'invitations#index' + resources :donations + get 'lightning', to: 'lightning#index' namespace :app_catalog do From ca238be6f464d52443f16bf8c7ae6f73cfd05cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sat, 10 Feb 2024 10:24:09 +0100 Subject: [PATCH 22/30] Add option for hiding close button in modal windows --- app/components/modal_component.html.erb | 2 ++ app/components/modal_component.rb | 3 +++ 2 files changed, 5 insertions(+) diff --git a/app/components/modal_component.html.erb b/app/components/modal_component.html.erb index fa92a72..f8d4baf 100644 --- a/app/components/modal_component.html.erb +++ b/app/components/modal_component.html.erb @@ -18,9 +18,11 @@
<%= content %> + <% if @show_close_button %>
+ <% end %>
diff --git a/app/components/modal_component.rb b/app/components/modal_component.rb index 249ec37..bbc86f4 100644 --- a/app/components/modal_component.rb +++ b/app/components/modal_component.rb @@ -1,2 +1,5 @@ class ModalComponent < ViewComponent::Base + def initialize(show_close_button: true) + @show_close_button = show_close_button + end end From f3159d30f18a997f02cda528eea0c4e6ee50bdde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sat, 10 Feb 2024 11:21:45 +0100 Subject: [PATCH 23/30] Allow admins to add and remove invitations per account --- .../fieldset_toggle_component.html.erb | 2 ++ .../fieldset_toggle_component.rb | 2 +- app/controllers/admin/users_controller.rb | 28 ++++++++++++++++- .../admin/users/_create_invitations.html.erb | 21 +++++++++++++ app/views/admin/users/show.html.erb | 30 +++++++++++-------- app/views/icons/_plus-circle.html.erb | 2 +- app/views/icons/_x-circle.html.erb | 2 +- config/routes.rb | 7 ++++- 8 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 app/views/admin/users/_create_invitations.html.erb diff --git a/app/components/form_elements/fieldset_toggle_component.html.erb b/app/components/form_elements/fieldset_toggle_component.html.erb index f4acd3d..9965490 100644 --- a/app/components/form_elements/fieldset_toggle_component.html.erb +++ b/app/components/form_elements/fieldset_toggle_component.html.erb @@ -5,7 +5,9 @@ } : nil do %>
+ <% if @description.present? %>

<%= @descripton %>

+ <% end %>
<%= render FormElements::ToggleComponent.new( diff --git a/app/components/form_elements/fieldset_toggle_component.rb b/app/components/form_elements/fieldset_toggle_component.rb index 686f5f1..09fd36d 100644 --- a/app/components/form_elements/fieldset_toggle_component.rb +++ b/app/components/form_elements/fieldset_toggle_component.rb @@ -3,7 +3,7 @@ module FormElements class FieldsetToggleComponent < ViewComponent::Base def initialize(tag: "li", form: nil, attribute: nil, field_name: nil, - enabled: false, input_enabled: true, title:, description:) + enabled: false, input_enabled: true, title:, description: nil) @tag = tag @form = form @attribute = attribute diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 1849fa6..6b6f510 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,7 +1,8 @@ class Admin::UsersController < Admin::BaseController - before_action :set_user, only: [:show] + before_action :set_user, except: [:index] before_action :set_current_section + # GET /admin/users def index ldap = LdapService.new @ou = Setting.primary_domain @@ -13,6 +14,7 @@ class Admin::UsersController < Admin::BaseController } end + # GET /admin/users/:username def show if Setting.lndhub_admin_enabled? @lndhub_user = @user.lndhub_user @@ -23,6 +25,30 @@ class Admin::UsersController < Admin::BaseController @avatar = LdapManager::FetchAvatar.call(cn: @user.cn) end + # POST /admin/users/:username/invitations + def create_invitations + amount = params[:amount].to_i + notify_user = ActiveRecord::Type::Boolean.new.cast(params[:notify_user]) + + CreateInvitations.call(user: @user, amount: amount, notify: notify_user) + + redirect_to admin_user_path(@user.cn), flash: { + success: "Added #{amount} invitations to #{@user.cn}'s account" + } + end + + # DELETE /admin/users/:username/invitations + def delete_invitations + invitations = @user.invitations.unused + amount = invitations.count + + invitations.destroy_all + + redirect_to admin_user_path(@user.cn), flash: { + success: "Removed #{amount} invitations from #{@user.cn}'s account" + } + end + private def set_user diff --git a/app/views/admin/users/_create_invitations.html.erb b/app/views/admin/users/_create_invitations.html.erb new file mode 100644 index 0000000..dfffa36 --- /dev/null +++ b/app/views/admin/users/_create_invitations.html.erb @@ -0,0 +1,21 @@ +

Add new invitations to <%= @user.cn %>'s account

+<%= form_with(url: invitations_admin_user_path, method: :post) do |form| %> +
    + <%= render FormElements::FieldsetComponent.new( + positioning: :horizontal, + title: "Amount" + ) do %> + <%= form.select :amount, options_for_select([ + ["3", "3"], ["5", "5"], ["10", "10"], ["20", "20"] + ]) %> + <% end %> + <%= render FormElements::FieldsetToggleComponent.new( + field_name: "notify_user", + enabled: true, + title: "Notify user via email" + ) %> +
+

+ <%= form.submit 'Add', class: "btn-md btn-blue w-full" %> +

+<% end %> diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb index 0003172..14f8c7d 100644 --- a/app/views/admin/users/show.html.erb +++ b/app/views/admin/users/show.html.erb @@ -42,27 +42,33 @@
- diff --git a/app/views/icons/_plus-circle.html.erb b/app/views/icons/_plus-circle.html.erb index 4291ff0..14ae0bf 100644 --- a/app/views/icons/_plus-circle.html.erb +++ b/app/views/icons/_plus-circle.html.erb @@ -1 +1 @@ - \ No newline at end of file + diff --git a/app/views/icons/_x-circle.html.erb b/app/views/icons/_x-circle.html.erb index 94aad5e..c1bea72 100644 --- a/app/views/icons/_x-circle.html.erb +++ b/app/views/icons/_x-circle.html.erb @@ -1 +1 @@ - \ No newline at end of file + diff --git a/config/routes.rb b/config/routes.rb index 8dee02d..39e69f2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,9 +74,14 @@ Rails.application.routes.draw do root to: 'dashboard#index' resources 'users', param: 'username', only: ['index', 'show'] do - + member do + post 'invitations', to: 'users#create_invitations' + delete 'invitations', to: 'users#delete_invitations' + end end + # post 'users/:username/invitations', to: 'users#create_invitations' + get 'invitations', to: 'invitations#index' resources :donations From 2753388e1ee42c13d2e7b55d43d3eb50645ae153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Sat, 10 Feb 2024 12:53:11 +0100 Subject: [PATCH 24/30] Add specs for admin user management --- app/views/admin/users/show.html.erb | 2 +- spec/features/admin/users_spec.rb | 55 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 spec/features/admin/users_spec.rb diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb index 14f8c7d..ca0cd09 100644 --- a/app/views/admin/users/show.html.erb +++ b/app/views/admin/users/show.html.erb @@ -48,7 +48,7 @@ <%= @user.invitations.count %> - - <% if @user.invitations.unused.count > 0 %> - <%= link_to invitations_admin_user_path(@user.cn), data: { - turbo_method: :delete, - turbo_confirm: "Delete all of #{@user.cn}'s available invitations?" - } do %> - <%= render partial: "icons/x-circle", locals: { - custom_class: "text-red-600 hover:text-red-500 -mt-2 -mb-1 h-6 w-6 inline-block" - } %> + <% if @user.invitations.unused.count > 0 %> + <%= link_to invitations_admin_user_path(@user.cn), + id: "remove-invitations", data: { + turbo_method: :delete, + turbo_confirm: "Delete all of #{@user.cn}'s available invitations?" + } do %> + <%= render partial: "icons/x-circle", locals: { + custom_class: "text-red-600 hover:text-red-500 -mt-2 -mb-1 h-6 w-6 inline-block" + } %> <% end %> <% end %> From bbf3fb91a0389ab4c3fd9440b049a703425b28e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 22 Feb 2024 10:47:21 +0100 Subject: [PATCH 26/30] Fix Ruby in Docker container on Apple silicon --- Dockerfile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7da4b88..00d8559 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,18 @@ # syntax=docker/dockerfile:1 -FROM ruby:3.3.0 +FROM debian:bullseye-slim as base SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update -qq && apt-get install -y --no-install-recommends curl \ - ldap-utils tini libvips +# TODO Remove when upstream Ruby works properly on Apple silicon +RUN apt update && apt install -y build-essential wget autoconf libpq-dev +RUN wget https://github.com/postmodern/ruby-install/releases/download/v0.9.3/ruby-install-0.9.3.tar.gz \ + && tar -xzvf ruby-install-0.9.3.tar.gz \ + && cd ruby-install-0.9.3/ \ + && make install +RUN ruby-install -p https://github.com/ruby/ruby/pull/9371.diff ruby 3.3.0 +ENV PATH="/opt/rubies/ruby-3.3.0/bin:${PATH}" + +RUN apt-get install -y --no-install-recommends curl ldap-utils tini libvips RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - RUN apt-get update && apt-get install -y nodejs From ba7c3795f810191054c3929e2d8310d370de1aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 22 Feb 2024 11:29:56 +0100 Subject: [PATCH 27/30] Add pkg-config --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 00d8559..a6f8081 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM debian:bullseye-slim as base SHELL ["/bin/bash", "-o", "pipefail", "-c"] # TODO Remove when upstream Ruby works properly on Apple silicon -RUN apt update && apt install -y build-essential wget autoconf libpq-dev +RUN apt update && apt install -y build-essential wget autoconf libpq-dev pkg-config RUN wget https://github.com/postmodern/ruby-install/releases/download/v0.9.3/ruby-install-0.9.3.tar.gz \ && tar -xzvf ruby-install-0.9.3.tar.gz \ && cd ruby-install-0.9.3/ \ From 56d91083e5d732fab43e459d968f83477f4cf843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 22 Feb 2024 13:24:41 +0100 Subject: [PATCH 28/30] Fix seeds for new keyword argument --- db/seeds.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index dd13a45..fa957a6 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -3,10 +3,10 @@ require 'sidekiq/testing' ldap = LdapService.new Sidekiq::Testing.inline! do - CreateAccount.call( + CreateAccount.call(account: { username: "admin", domain: "kosmos.org", email: "admin@example.com", password: "admin is admin", confirmed: true - ) + }) ldap.add_attribute "cn=admin,ou=kosmos.org,cn=users,dc=kosmos,dc=org", :admin, "true" @@ -15,9 +15,9 @@ Sidekiq::Testing.inline! do email = Faker::Internet.unique.email next if username.length < 3 - CreateAccount.call( + CreateAccount.call(account: { username: username, domain: "kosmos.org", email: email, password: "user is user", confirmed: true - ) + }) end end From a852ab75ae0da78f0a285600df6c391701b17a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Fri, 23 Feb 2024 16:43:56 +0100 Subject: [PATCH 29/30] Fix Docker volume permissions on some host platforms Use named volumes instead of bind mounts. --- docker-compose.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5106dfd..f046edf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ services: ldap: image: 4teamwork/389ds:latest volumes: - - ./tmp/389ds:/data + - 389ds-data:/data networks: - external_network - internal_network @@ -20,7 +20,7 @@ services: healthcheck: test: ['CMD', 'redis-cli', 'ping'] volumes: - - ./tmp/redis:/data + - redis-data:/data web: build: . @@ -81,7 +81,7 @@ services: - "9000:9000" - "9001:9001" volumes: - - ./tmp/minio:/data + - minio-data:/data liquor-cabinet: image: gitea.kosmos.org/5apps/liquor-cabinet:2.0.0-beta.2 @@ -116,3 +116,11 @@ networks: external_network: internal_network: internal: true + +volumes: + 389ds-data: + driver: local + minio-data: + driver: local + redis-data: + driver: local From b33b8104a8cd5c96e5570d360e8f8c190c9b4965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Tue, 27 Feb 2024 14:33:37 +0100 Subject: [PATCH 30/30] Fix typo --- app/views/icons/{_kebab-menu.html.erb => _kebap-menu.html.erb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/views/icons/{_kebab-menu.html.erb => _kebap-menu.html.erb} (100%) diff --git a/app/views/icons/_kebab-menu.html.erb b/app/views/icons/_kebap-menu.html.erb similarity index 100% rename from app/views/icons/_kebab-menu.html.erb rename to app/views/icons/_kebap-menu.html.erb
UID Status Roles
<%= link_to(user.cn, admin_user_path(user.address), class: 'ks-text-link') %><%= link_to(user.cn, admin_user_path(user.cn), class: 'ks-text-link') %> <%= user.confirmed_at.nil? ? badge("pending", :yellow) : "" %> <%= user.is_admin? ? badge("admin", :red) : "" %>
Invitations available +
<%= @user.invitations.count %> - <%= render DropdownComponent.new(size: :small, icon_name: "edit") do %> - <%= render DropdownLinkComponent.new( - href: "" - ) do %> - Add more - <% end %> - <%= render DropdownLinkComponent.new( - href: "", - separator: true, add_class: "text-red-700" - ) do %> - Remove all + + <% if @user.invitations.unused.count > 0 %> + <%= link_to invitations_admin_user_path(@user.cn), data: { + turbo_method: :delete, + turbo_confirm: "Delete all of #{@user.cn}'s available invitations?" + } do %> + <%= render partial: "icons/x-circle", locals: { + custom_class: "text-red-600 hover:text-red-500 -mt-2 -mb-1 h-6 w-6 inline-block" + } %> <% end %> <% end %>
+ <%= render ModalComponent.new(show_close_button: false) do %> + <%= render partial: "admin/users/create_invitations", + locals: { user: @user } %> + <% end %>