diff --git a/README.md b/README.md index 564b833..13e20ac 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ so: 1. Make sure [Docker Compose is installed][1] and Docker is running (included in Docker Desktop) -3. Run `docker compose up` and wait until 389ds announces its successful start - in the log output +3. Run `docker compose up --build` and wait until all services have started + (389ds might take an extra minute to be ready). This will take a while when + running for the first time, so you might want to do something else in the + meantime. 4. `docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev"` 5. `docker compose run web rails ldap:setup` 6. `docker compose run web rails db:setup` @@ -28,38 +30,44 @@ have the password "user is user". ### Rails app +_Note: when using Docker Compose, prefix the following commands with `docker-compose +run web`._ + Installing dependencies: bundle install yarn install -Setting up local database (SQLite): +Migrating the local database (after schema changes): - bundle exec rails db:create bundle exec rails db:migrate -Running the dev server and auto-building CSS files on change: +Running the dev server, and auto-building CSS files on change _(automatic with Docker Compose)_: bin/dev -Running the background workers (requires Redis): +Running the background workers (requires Redis) _(automatic with Docker Compose)_: bundle exec sidekiq -C config/sidekiq.yml -Running all specs: +Running the test suite: bundle exec rspec -### Docker (Compose) +Running the test suite with Docker Compose requires overriding the Rails +environment: -There is a working Docker Compose config file, which define a number of services including -an app server for Rails as well as a local 389ds (LDAP) server. + docker-compose run -e "RAILS_ENV=test" web rspec -For Rails developers, you probably just want to start the LDAP server: `docker-compose up ldap`, -listening on port 389 on your machine. +### Docker Compose -You can pick and choose your services adding them by name (listed in `docker-compose.yml`) at -the end of the docker compose command. eg. `docker compose up ldap redis` +Services/containers are configured in `docker-compose.yml`. + +You can run services selectively, for example if you want to run the Rails app +and test suite on the host machine. Just add the service names of the +containers you want to run to the `up` command, like so: + + docker-compose up ldap redis #### LDAP server @@ -76,13 +84,15 @@ Now you can seed the back-end with data using this Rails task: The setup task will first delete any existing entries in the directory tree ("dc=kosmos,dc=org"), and then create our development entries. -Note that all 389ds data is stored in `tmp/389ds`. So if you want to start over -with a fresh installation, delete both that directory as well as the container. +Note that all 389ds data is stored in the `389ds-data` volume. So if you want +to start over with a fresh installation, delete both that volume as well as the +container. -#### Minio / RS +#### Minio / remoteStorage If you want to run remoteStorage accounts locally, you will have to create the -respective bucket first: +respective bucket first. With the `minio` container running (run by default +when using Docker Compose), follow these steps: * `docker compose up web redis minio liquor-cabinet` * Head to http://localhost:9001 and log in with user `minioadmin`, password diff --git a/app/controllers/admin/settings/registrations_controller.rb b/app/controllers/admin/settings/registrations_controller.rb index 1d888a5..4c6cb83 100644 --- a/app/controllers/admin/settings/registrations_controller.rb +++ b/app/controllers/admin/settings/registrations_controller.rb @@ -1,8 +1,8 @@ class Admin::Settings::RegistrationsController < Admin::SettingsController - def index + def show end - def create + def update update_settings redirect_to admin_settings_registrations_path, flash: { diff --git a/app/controllers/admin/settings/services_controller.rb b/app/controllers/admin/settings/services_controller.rb index a228f5e..95a01b3 100644 --- a/app/controllers/admin/settings/services_controller.rb +++ b/app/controllers/admin/settings/services_controller.rb @@ -1,19 +1,32 @@ class Admin::Settings::ServicesController < Admin::SettingsController - def index - @service = params[:s] + before_action :set_service, only: [:show, :update] - if @service.blank? - redirect_to admin_settings_services_path(params: { s: "btcpay" }) - end + def index + redirect_to admin_settings_service_path("btcpay") end - def create - service = params.require(:service) + def show + end + def update update_settings - redirect_to admin_settings_services_path(params: { s: service }), flash: { + redirect_to admin_settings_service_path(@service), flash: { success: "Settings saved" } end + + private + + def set_subsection + @subsection = "services" + end + + def set_service + @service = params[:service] + + if @service.blank? + redirect_to admin_settings_services_path and return + end + end end diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index 8a168b1..0ac029b 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -20,7 +20,7 @@ class Admin::SettingsController < Admin::BaseController end if @errors.any? - render :index and return + render :show and return end changed_keys.each do |key| diff --git a/app/views/admin/settings/registrations/index.html.erb b/app/views/admin/settings/registrations/show.html.erb similarity index 97% rename from app/views/admin/settings/registrations/index.html.erb rename to app/views/admin/settings/registrations/show.html.erb index 90b67af..0028c15 100644 --- a/app/views/admin/settings/registrations/index.html.erb +++ b/app/views/admin/settings/registrations/show.html.erb @@ -1,7 +1,7 @@ <%= render HeaderComponent.new(title: "Settings") %> <%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/admin_sidenav_settings') do %> - <%= form_for(Setting.new, url: admin_settings_registrations_path) do |f| %> + <%= form_for(Setting.new, url: admin_settings_registrations_path, method: :put) do |f| %>

Registrations

diff --git a/app/views/admin/settings/services/index.html.erb b/app/views/admin/settings/services/show.html.erb similarity index 85% rename from app/views/admin/settings/services/index.html.erb rename to app/views/admin/settings/services/show.html.erb index f63653d..97db9dc 100644 --- a/app/views/admin/settings/services/index.html.erb +++ b/app/views/admin/settings/services/show.html.erb @@ -1,9 +1,7 @@ <%= render HeaderComponent.new(title: "Settings") %> <%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/admin_sidenav_settings') do %> - <%= form_for(Setting.new, url: admin_settings_services_path) do |f| %> - <%= hidden_field_tag :service, @service %> - + <%= form_for(Setting.new, url: admin_settings_service_path(@service), method: :put) do |f| %> <% if @errors && @errors.any? %>
<%= render partial: "admin/settings/errors", locals: { errors: @errors } %> diff --git a/app/views/shared/_admin_sidenav_settings.html.erb b/app/views/shared/_admin_sidenav_settings.html.erb index 387cd9b..48c5ced 100644 --- a/app/views/shared/_admin_sidenav_settings.html.erb +++ b/app/views/shared/_admin_sidenav_settings.html.erb @@ -4,9 +4,9 @@ ) %> <%= render SidenavLinkComponent.new( name: "Services", path: admin_settings_services_path, icon: "grid", - active: current_page?(admin_settings_services_path) + active: controller_name == "services" ) %> -<% if current_page?(admin_settings_services_path) %> +<% if controller_name == "services" %> <%= render partial: "shared/admin_sidenav_settings_services" %> <% end %> <%= render SidenavLinkComponent.new( diff --git a/app/views/shared/_admin_sidenav_settings_services.html.erb b/app/views/shared/_admin_sidenav_settings_services.html.erb index a69f3cc..e4ab082 100644 --- a/app/views/shared/_admin_sidenav_settings_services.html.erb +++ b/app/views/shared/_admin_sidenav_settings_services.html.erb @@ -1,77 +1,77 @@ <%= render SidenavLinkComponent.new( level: 2, name: "BTCPay", - path: admin_settings_services_path(params: { s: "btcpay" }), + path: admin_settings_service_path("btcpay"), text_icon: Setting.btcpay_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "btcpay" })), + active: current_page?(admin_settings_service_path("btcpay")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "Discourse", - path: admin_settings_services_path(params: { s: "discourse" }), + path: admin_settings_service_path("discourse"), text_icon: Setting.discourse_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "discourse" })), + active: current_page?(admin_settings_service_path("discourse")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "Drone CI", - path: admin_settings_services_path(params: { s: "droneci" }), + path: admin_settings_service_path("droneci"), text_icon: Setting.droneci_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "droneci" })), + active: current_page?(admin_settings_service_path("droneci")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "E-Mail", - path: admin_settings_services_path(params: { s: "email" }), + path: admin_settings_service_path("email"), text_icon: Setting.email_enabled? ? "◉" : "○", active: current_page?(admin_settings_services_path(params: { s: "email" })), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "ejabberd", - path: admin_settings_services_path(params: { s: "ejabberd" }), + path: admin_settings_service_path("ejabberd"), text_icon: Setting.ejabberd_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "ejabberd" })), + active: current_page?(admin_settings_service_path("ejabberd")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "Gitea", - path: admin_settings_services_path(params: { s: "gitea" }), + path: admin_settings_service_path("gitea"), text_icon: Setting.gitea_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "gitea" })), + active: current_page?(admin_settings_service_path("gitea")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "LNDHub", - path: admin_settings_services_path(params: { s: "lndhub" }), + path: admin_settings_service_path("lndhub"), text_icon: Setting.lndhub_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "lndhub" })), + active: current_page?(admin_settings_service_path("lndhub")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "Mastodon", - path: admin_settings_services_path(params: { s: "mastodon" }), + path: admin_settings_service_path("mastodon"), text_icon: Setting.mastodon_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "mastodon" })), + active: current_page?(admin_settings_service_path("mastodon")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "MediaWiki", - path: admin_settings_services_path(params: { s: "mediawiki" }), + path: admin_settings_service_path("mediawiki"), text_icon: Setting.mediawiki_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "mediawiki" })), + active: current_page?(admin_settings_service_path("mediawiki")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "Nostr", - path: admin_settings_services_path(params: { s: "nostr" }), + path: admin_settings_service_path("nostr"), text_icon: Setting.nostr_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "nostr" })), + active: current_page?(admin_settings_service_path("nostr")), ) %> <%= render SidenavLinkComponent.new( level: 2, name: "RemoteStorage", - path: admin_settings_services_path(params: { s: "remotestorage" }), + path: admin_settings_service_path("remotestorage"), text_icon: Setting.remotestorage_enabled? ? "◉" : "○", - active: current_page?(admin_settings_services_path(params: { s: "remotestorage" })), + active: current_page?(admin_settings_service_path("remotestorage")), ) %> diff --git a/config/environments/test.rb b/config/environments/test.rb index a459967..65473dd 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -52,10 +52,9 @@ Rails.application.configure do config.active_job.queue_adapter = :test - if ENV["S3_ENABLED"] + if ENV["S3_ENABLED"] && ENV["S3_ENABLED"].to_s != "false" config.active_storage.service = :s3 else - # Store attachments on the local disk (in ./tmp) - config.active_storage.service = :test + config.active_storage.service = :local end end diff --git a/config/routes.rb b/config/routes.rb index 4307f9e..47b5988 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -97,8 +97,8 @@ Rails.application.routes.draw do end namespace :settings do - resources 'registrations', only: ['index', 'create'] - resources 'services', only: ['index', 'create'] + resource 'registrations', only: ['show', 'update'] + resources 'services', param: 'service', only: ['index', 'show', 'update'] end end diff --git a/db/schema.rb b/db/schema.rb index dd267df..934c5f3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -60,6 +60,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_16_124640) do t.string "payment_method" t.string "btcpay_invoice_id" t.string "payment_status" + t.index ["payment_status"], name: "index_donations_on_payment_status" t.index ["user_id"], name: "index_donations_on_user_id" end diff --git a/spec/features/admin/settings_spec.rb b/spec/features/admin/settings_spec.rb index 01a43f4..91d8ffe 100644 --- a/spec/features/admin/settings_spec.rb +++ b/spec/features/admin/settings_spec.rb @@ -23,35 +23,35 @@ RSpec.describe 'Admin/global settings', type: :feature do scenario "Opening service settings shows page for first service" do visit admin_settings_services_path - expect(current_url).to eq(admin_settings_services_url(params: { s: "btcpay" })) + expect(current_url).to eq(admin_settings_service_url("btcpay")) end scenario "View service settings" do - visit admin_settings_services_path(params: { s: "ejabberd" }) + visit admin_settings_service_path("ejabberd") expect(page).to have_content("Enable ejabberd integration") expect(page).to have_field("API URL", with: "http://xmpp.example.com/api") end scenario "Disable a service integration" do - visit admin_settings_services_path(params: { s: "ejabberd" }) + visit admin_settings_service_path("ejabberd") expect(page).to have_checked_field("setting[ejabberd_enabled]") uncheck "setting[ejabberd_enabled]" click_button "Save" - expect(current_url).to eq(admin_settings_services_url(params: { s: "ejabberd" })) + expect(current_url).to eq(admin_settings_service_url("ejabberd")) expect(page).to_not have_checked_field("setting[ejabberd_enabled]") expect(page).to_not have_field("API URL", disabled: true) end scenario "Resettable fields" do - visit admin_settings_services_path(params: { s: "ejabberd" }) + visit admin_settings_service_path("ejabberd") expect(page).to have_field("API URL", with: "http://xmpp.example.com/api") expect(page).to_not have_css('input#setting_ejabberd_api_url+button') Setting.ejabberd_api_url = "http://example.com/foo" - visit admin_settings_services_path(params: { s: "ejabberd" }) + visit admin_settings_service_path("ejabberd") expect(page).to have_field("API URL", with: "http://example.com/foo") expect(page).to have_css('input#setting_ejabberd_api_url+button') end diff --git a/spec/requests/webfinger_spec.rb b/spec/requests/webfinger_spec.rb index 1dcdfa3..27cd361 100644 --- a/spec/requests/webfinger_spec.rb +++ b/spec/requests/webfinger_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "WebFinger", type: :request do res = JSON.parse(response.body) rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"} - expect(rs_link["href"]).to eql("https://storage.kosmos.org/tony") + expect(rs_link["href"]).to eql("#{Setting.rs_storage_url}/tony") oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"] expect(oauth_url).to eql("http://www.example.com/rs/oauth/tony")