diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index be05d66..462ae01 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -17,7 +17,7 @@ class AccountsController < ApplicationController
end
def account_params
- params.require(:account).permit(:name, :logo)
+ params.require(:account).permit(:name, :logo, settings: {})
end
def account_users
diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb
index 559e195..22c6c4a 100644
--- a/app/helpers/accounts_helper.rb
+++ b/app/helpers/accounts_helper.rb
@@ -2,4 +2,13 @@ module AccountsHelper
def account_logo_tag(style: nil)
tag.figure image_tag(fresh_account_logo_path, alt: "Account logo", size: 300), class: "account-logo avatar #{style}"
end
+
+ def button_to_toggle_setting(label, setting)
+ button_to account_path(account: { settings: { setting => !Current.account.settings.send("#{setting}?") } }),
+ method: :put,
+ role: "checkbox", aria: { checked: true, labelledby: "#{setting}_account_setting" }, tabindex: 0,
+ class: "btn" do
+ tag.span(label, id: "#{setting}_account_setting")
+ end
+ end
end
diff --git a/app/models/account.rb b/app/models/account.rb
index 36a7648..71ceb7c 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -2,4 +2,5 @@ class Account < ApplicationRecord
include Joinable
has_one_attached :logo
+ has_json settings: { restrict_room_creation_to_administrators: :boolean }, delegate: true
end
diff --git a/app/views/accounts/edit.html.erb b/app/views/accounts/edit.html.erb
index 93a828a..2b6d5ab 100644
--- a/app/views/accounts/edit.html.erb
+++ b/app/views/accounts/edit.html.erb
@@ -64,6 +64,12 @@
<% end %>
<% end %>
+
+ <% if Current.account.restrict_room_creation_to_administrators? %>
+ <%= button_to_toggle_setting "Allow everyone to create new rooms", :restrict_room_creation_to_administrators %>
+ <% else %>
+ <%= button_to_toggle_setting "Only allow admins to create new rooms", :restrict_room_creation_to_administrators %>
+ <% end %>
<% else %>
<%= account_logo_tag style: "txt-xx-large center" %>
<%= @account.name %>
diff --git a/db/migrate/20251126130131_add_account_settings.rb b/db/migrate/20251126130131_add_account_settings.rb
new file mode 100644
index 0000000..6c97f4e
--- /dev/null
+++ b/db/migrate/20251126130131_add_account_settings.rb
@@ -0,0 +1,5 @@
+class AddAccountSettings < ActiveRecord::Migration[7.2]
+ def change
+ add_column :accounts, :settings, :json, default: {}
+ end
+end
diff --git a/lib/rails_ext/active_record_has_json.rb b/lib/rails_ext/active_record_has_json.rb
new file mode 100644
index 0000000..8a3bdd7
--- /dev/null
+++ b/lib/rails_ext/active_record_has_json.rb
@@ -0,0 +1,52 @@
+module ActiveRecord
+ class TypedJson
+ def initialize(schema, data:)
+ @schema, @data = schema, data
+ end
+
+ def assign_data_with_type_casting(new_data)
+ new_data.each do |key, value|
+ @data[key] = ActiveModel::Type.lookup(@schema[key.to_sym]).cast(value)
+ end
+ end
+
+ private
+ def method_missing(method_name, *args, **kwargs)
+ key = method_name.to_s.remove(/(\?|=)/)
+
+ if key_type = @schema[key.to_sym]
+ if method_name.ends_with?("?")
+ @data[key].present?
+ elsif method_name.ends_with?("=")
+ value = args.first
+ @data[key] = ActiveModel::Type.lookup(key_type).cast(value)
+ else
+ @data.fetch(key)
+ end
+ else
+ super
+ end
+ end
+
+ def respond_to_missing?(method_name, include_private = false)
+ @schema.key?(method_name.to_s.remove(/[?=]/).to_sym) || super
+ end
+ end
+
+ class Base
+ class << self
+ def has_json(delegate: false, **schemas)
+ schemas.each do |name, schema|
+ define_method(name) { ActiveRecord::TypedJson.new(schema, data: self[name]) }
+ define_method("#{name}=") { |data| send(name).assign_data_with_type_casting(data) }
+
+ schema.keys.each do |schema_key|
+ define_method(schema_key) { send(name).send(schema_key) }
+ define_method("#{schema_key}?") { send(name).send("#{schema_key}?") }
+ define_method("#{schema_key}=") { |value| send(name).send("#{schema_key}=", value) }
+ end if delegate
+ end
+ end
+ end
+ end
+end
diff --git a/test/models/account_test.rb b/test/models/account_test.rb
index 94d4f83..e4e3673 100644
--- a/test/models/account_test.rb
+++ b/test/models/account_test.rb
@@ -1,4 +1,18 @@
require "test_helper"
class AccountTest < ActiveSupport::TestCase
+ test "settings" do
+ accounts(:signal).restrict_room_creation_to_administrators = true
+ assert accounts(:signal).restrict_room_creation_to_administrators?
+ assert_equal({ "restrict_room_creation_to_administrators" => true }, accounts(:signal)[:settings])
+
+ accounts(:signal).update!(settings: { "restrict_room_creation_to_administrators" => "true" })
+ assert accounts(:signal).reload.restrict_room_creation_to_administrators?
+
+ accounts(:signal).restrict_room_creation_to_administrators = false
+ assert_not accounts(:signal).restrict_room_creation_to_administrators?
+ assert_equal({ "restrict_room_creation_to_administrators" => false }, accounts(:signal)[:settings])
+ accounts(:signal).update!(settings: { "restrict_room_creation_to_administrators" => "false" })
+ assert_not accounts(:signal).reload.restrict_room_creation_to_administrators?
+ end
end