From 83f298e5f3d65deb6af621f088bb729cc3efd650 Mon Sep 17 00:00:00 2001 From: stage-rl Date: Mon, 27 Nov 2023 10:56:49 +0100 Subject: [PATCH 01/88] Implement login/logout events --- app/controllers/sessions_controller.rb | 2 ++ app/lib/event_bus.rb | 2 ++ app/models/audit_log.rb | 19 ++++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index bf17d36f1..dbd699531 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -10,9 +10,11 @@ def login def create create_session + EventBus.publish(:user_logged_in, Current.user) end def destroy + EventBus.publish(:user_logged_out, User.find_by(id: session[:user_id])) clean_session redirect_to root_path diff --git a/app/lib/event_bus.rb b/app/lib/event_bus.rb index 23cc117a2..d0e1a13df 100644 --- a/app/lib/event_bus.rb +++ b/app/lib/event_bus.rb @@ -59,3 +59,5 @@ def self.reset! EventBus.subscribe :message_thread_note_created, ->(note) { AuditLog::MessageThreadNoteCreated.create_audit_record(note) } EventBus.subscribe :message_thread_note_changed, ->(note) { AuditLog::MessageThreadNoteChanged.create_audit_record(note) } EventBus.subscribe :message_thread_tag_changed, ->(thread_tag) { AuditLog::MessageThreadTagChanged.create_audit_record(thread_tag) } +EventBus.subscribe :user_logged_in, ->(user) { AuditLog::UserLoggedIn.create_audit_record(user) } +EventBus.subscribe :user_logged_out, ->(user) { AuditLog::UserLoggedOut.create_audit_record(user) } diff --git a/app/models/audit_log.rb b/app/models/audit_log.rb index 6ec004c54..325bd56b6 100644 --- a/app/models/audit_log.rb +++ b/app/models/audit_log.rb @@ -3,7 +3,7 @@ class AuditLog < ApplicationRecord belongs_to :tenant belongs_to :actor, class_name: "User" - belongs_to :message_thread + belongs_to :message_thread, optional: true class MessageThreadNoteCreated < AuditLog def self.create_audit_record(note) @@ -38,6 +38,23 @@ def self.create_audit_record(thread_tag) end end + class UserLoggedIn < AuditLog + def self.create_audit_record(user) + create_record(object: user, tenant: user.tenant) + end + end + + class UserLoggedOut < AuditLog + def self.create_audit_record(user) + create_record( + object: user, + tenant: user.tenant, + actor: user, + actor_name: user.name + ) + end + end + def self.create_record(object:, **args) create( tenant: Current.tenant, From 4768914b77257f6229e125220128fb6a86560179 Mon Sep 17 00:00:00 2001 From: stage-rl Date: Mon, 27 Nov 2023 14:55:04 +0100 Subject: [PATCH 02/88] Audit logs of admin actions --- .rubocop.yml | 2 + app/lib/event_bus.rb | 25 ++- app/models/audit_log.rb | 149 +++++++++++++++++- app/models/automation/rule.rb | 1 + app/models/concerns/auditable.rb | 23 +++ app/models/filter.rb | 1 + app/models/group.rb | 2 + app/models/group_membership.rb | 3 +- app/models/message_thread_note.rb | 4 +- app/models/tag.rb | 2 +- app/models/tag_group.rb | 1 + app/models/user.rb | 1 + ...date_audit_logs_from_changed_to_updated.rb | 6 + db/schema.rb | 2 +- 14 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 app/models/concerns/auditable.rb create mode 100644 db/migrate/20231127112038_update_audit_logs_from_changed_to_updated.rb diff --git a/.rubocop.yml b/.rubocop.yml index 09b6e01b8..d83c3a462 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,3 +12,5 @@ Style/WordArray: Enabled: false Style/Lambda: Enabled: false +Style/StringLiteralsInInterpolation: + EnforcedStyle: double_quotes diff --git a/app/lib/event_bus.rb b/app/lib/event_bus.rb index d0e1a13df..75d43ff35 100644 --- a/app/lib/event_bus.rb +++ b/app/lib/event_bus.rb @@ -57,7 +57,28 @@ def self.reset! EventBus.subscribe :box_destroyed, ->(box_id) { Govbox::DestroyBoxDataJob.perform_later(box_id) } EventBus.subscribe :message_thread_note_created, ->(note) { AuditLog::MessageThreadNoteCreated.create_audit_record(note) } -EventBus.subscribe :message_thread_note_changed, ->(note) { AuditLog::MessageThreadNoteChanged.create_audit_record(note) } -EventBus.subscribe :message_thread_tag_changed, ->(thread_tag) { AuditLog::MessageThreadTagChanged.create_audit_record(thread_tag) } +EventBus.subscribe :message_thread_note_updated, ->(note) { AuditLog::MessageThreadNoteUpdated.create_audit_record(note) } +EventBus.subscribe :message_thread_tag_updated, ->(thread_tag) { AuditLog::MessageThreadTagUpdated.create_audit_record(thread_tag) } EventBus.subscribe :user_logged_in, ->(user) { AuditLog::UserLoggedIn.create_audit_record(user) } EventBus.subscribe :user_logged_out, ->(user) { AuditLog::UserLoggedOut.create_audit_record(user) } +EventBus.subscribe :user_created, ->(user) { AuditLog::UserCreated.create_audit_record(user) } +EventBus.subscribe :user_updated, ->(user) { AuditLog::UserUpdated.create_audit_record(user) } +EventBus.subscribe :user_destroyed, ->(user) { AuditLog::UserDestroyed.create_audit_record(user) } +EventBus.subscribe :group_created, ->(group) { AuditLog::GroupCreated.create_audit_record(group) } +EventBus.subscribe :group_updated, ->(group) { AuditLog::GroupUpdated.create_audit_record(group) } +EventBus.subscribe :group_destroyed, ->(group) { AuditLog::GroupDestroyed.create_audit_record(group) } +EventBus.subscribe :group_membership_created, ->(group_membership) { AuditLog::GroupMembershipCreated.create_audit_record(group_membership) } +EventBus.subscribe :group_membership_updated, ->(group_membership) { AuditLog::GroupMembershipUpdated.create_audit_record(group_membership) } +EventBus.subscribe :group_membership_destroyed, ->(group_membership) { AuditLog::GroupMembershipDestroyed.create_audit_record(group_membership) } +EventBus.subscribe :tag_created, ->(tag) { AuditLog::TagCreated.create_audit_record(tag) } +EventBus.subscribe :tag_updated, ->(tag) { AuditLog::TagUpdated.create_audit_record(tag) } +EventBus.subscribe :tag_destroyed, ->(tag) { AuditLog::TagDestroyed.create_audit_record(tag) } +EventBus.subscribe :tag_group_created, ->(tag_group) { AuditLog::TagGroupCreated.create_audit_record(tag_group) } +EventBus.subscribe :tag_group_updated, ->(tag_group) { AuditLog::TagGroupUpdated.create_audit_record(tag_group) } +EventBus.subscribe :tag_group_destroyed, ->(tag_group) { AuditLog::TagGroupDestroyed.create_audit_record(tag_group) } +EventBus.subscribe :automation_rule_created, ->(automation_rule) { AuditLog::AutomationRuleCreated.create_audit_record(automation_rule) } +EventBus.subscribe :automation_rule_updated, ->(automation_rule) { AuditLog::AutomationRuleUpdated.create_audit_record(automation_rule) } +EventBus.subscribe :automation_rule_destroyed, ->(automation_rule) { AuditLog::AutomationRuleDestroyed.create_audit_record(automation_rule) } +EventBus.subscribe :filter_created, ->(filter) { AuditLog::FilterCreated.create_audit_record(filter) } +EventBus.subscribe :filter_updated, ->(filter) { AuditLog::FilterUpdated.create_audit_record(filter) } +EventBus.subscribe :filter_destroyed, ->(filter) { AuditLog::FilterDestroyed.create_audit_record(filter) } diff --git a/app/models/audit_log.rb b/app/models/audit_log.rb index 325bd56b6..b903540c5 100644 --- a/app/models/audit_log.rb +++ b/app/models/audit_log.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: audit_logs +# +# id :bigint not null, primary key +# actor_name :string +# changeset :jsonb +# happened_at :datetime not null +# new_value :string +# previous_value :string +# thread_id_archived :integer +# thread_title :string +# type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# actor_id :bigint +# message_thread_id :bigint +# tenant_id :bigint +# require "csv" class AuditLog < ApplicationRecord @@ -15,7 +34,7 @@ def self.create_audit_record(note) end end - class MessageThreadNoteChanged < AuditLog + class MessageThreadNoteUpdated < AuditLog def self.create_audit_record(note) create_record( object: note, @@ -27,7 +46,7 @@ def self.create_audit_record(note) end # TODO: Pre tagy sa asi budeme musiet subscribnut na nove eventy, kedze tu nevieme, ci to je destroy/create (dokonca teoreticky update) - class MessageThreadTagChanged < AuditLog + class MessageThreadTagUpdated < AuditLog def self.create_audit_record(thread_tag) create_record( object: thread_tag, @@ -55,6 +74,132 @@ def self.create_audit_record(user) end end + class FilterCreated < AuditLog + def self.create_audit_record(filter) + create_record(object: filter, new_value: filter.name) + end + end + + class FilterUpdated < AuditLog + def self.create_audit_record(filter) + create_record(object: filter, new_value: filter.name, previous_value: filter.name_previously_was) + end + end + + class FilterDestroyed < AuditLog + def self.create_audit_record(filter) + create_record(object: filter, previous_value: filter.name) + end + end + + class TagCreated < AuditLog + def self.create_audit_record(tag) + create_record(object: tag, new_value: tag.name) + end + end + + class TagUpdated < AuditLog + def self.create_audit_record(tag) + create_record(object: tag, new_value: tag.name, previous_value: tag.name_previously_was) + end + end + + class TagDestroyed < AuditLog + def self.create_audit_record(tag) + create_record(object: tag, previous_value: tag.name) + end + end + + class TagGroupCreated < AuditLog + def self.create_audit_record(tag_group) + create_record(object: tag_group) + end + end + + class TagGroupUpdated < AuditLog + def self.create_audit_record(tag_group) + create_record(object: tag_group) + end + end + + class TagGroupDestroyed < AuditLog + def self.create_audit_record(tag_group) + create_record(object: tag_group) + end + end + + class GroupCreated < AuditLog + def self.create_audit_record(group) + create_record(object: group, new_value: group.name) + end + end + + class GroupUpdated < AuditLog + def self.create_audit_record(group) + create_record(object: group, new_value: group.name, previous_value: group.name_previously_was) + end + end + + class GroupDestroyed < AuditLog + def self.create_audit_record(group) + create_record(object: group, previous_value: group.name) + end + end + + class GroupMembershipCreated < AuditLog + def self.create_audit_record(group_membership) + create_record(object: group_membership) + end + end + + class GroupMembershipUpdated < AuditLog + def self.create_audit_record(group_membership) + create_record(object: group_membership) + end + end + + class GroupMembershipDestroyed < AuditLog + def self.create_audit_record(group_membership) + create_record(object: group_membership) + end + end + + class UserCreated < AuditLog + def self.create_audit_record(user) + create_record(object: user, new_value: user.name) + end + end + + class UserUpdated < AuditLog + def self.create_audit_record(user) + create_record(object: user, new_value: user.name, previous_value: user.name_previously_was) + end + end + + class UserDestroyed < AuditLog + def self.create_audit_record(user) + create_record(object: user, previous_value: user.name) + end + end + + class AutomationRuleCreated < AuditLog + def self.create_audit_record(automation_rule) + create_record(object: automation_rule, new_value: automation_rule.name) + end + end + + class AutomationRuleUpdated < AuditLog + def self.create_audit_record(automation_rule) + create_record(object: automation_rule, new_value: automation_rule.name, previous_value: automation_rule.name_previously_was) + end + end + + class AutomationRuleDestroyed < AuditLog + def self.create_audit_record(automation_rule) + create_record(object: automation_rule, previous_value: automation_rule.name) + end + end + def self.create_record(object:, **args) create( tenant: Current.tenant, diff --git a/app/models/automation/rule.rb b/app/models/automation/rule.rb index de1494bac..7de1319db 100644 --- a/app/models/automation/rule.rb +++ b/app/models/automation/rule.rb @@ -24,6 +24,7 @@ class Rule < ApplicationRecord dependent: :destroy, foreign_key: :automation_rule_id, inverse_of: :automation_rule + include Auditable accepts_nested_attributes_for :conditions, :actions, allow_destroy: true diff --git a/app/models/concerns/auditable.rb b/app/models/concerns/auditable.rb new file mode 100644 index 000000000..ee607b3c8 --- /dev/null +++ b/app/models/concerns/auditable.rb @@ -0,0 +1,23 @@ +module Auditable + extend ActiveSupport::Concern + included do + after_destroy :audit_destroy + after_create :audit_create + after_update :audit_update + end + def audit_destroy + EventBus.publish(event_name(:destroyed), self) + end + + def audit_create + EventBus.publish(event_name(:created), self) + end + + def audit_update + EventBus.publish(event_name(:updated), self) + end + + def event_name(action) + "#{self.class.name.underscore.gsub("/", "_")}_#{action}".to_sym + end +end diff --git a/app/models/filter.rb b/app/models/filter.rb index ce8e437b8..a20b136a9 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -14,6 +14,7 @@ class Filter < ApplicationRecord belongs_to :author, class_name: 'User' belongs_to :tenant + include Auditable validates :tenant_id, :author_id, :name, :query, presence: true diff --git a/app/models/group.rb b/app/models/group.rb index 4c473143c..b2d1bd359 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -16,6 +16,8 @@ class Group < ApplicationRecord has_many :tag_groups, dependent: :destroy has_many :tags, through: :tag_groups + include Auditable + validates_presence_of :name validates_uniqueness_of :name, scope: :tenant_id validates :group_type, inclusion: { in: ['ALL', 'USER', 'ADMIN', 'CUSTOM'], allow_blank: false } diff --git a/app/models/group_membership.rb b/app/models/group_membership.rb index f1b1e4712..9cda11227 100644 --- a/app/models/group_membership.rb +++ b/app/models/group_membership.rb @@ -11,9 +11,10 @@ class GroupMembership < ApplicationRecord belongs_to :group belongs_to :user + include Auditable def group_membership_modifiable? # can't be removed from default groups - "TENANT_NAME"_ALL group and named user default group "USER_NAME"_USER - !group.group_type.in? ['ALL', 'USER'] + !group.group_type.in? ['ALL', 'USER'] end end diff --git a/app/models/message_thread_note.rb b/app/models/message_thread_note.rb index a4988e44b..60d955bee 100644 --- a/app/models/message_thread_note.rb +++ b/app/models/message_thread_note.rb @@ -10,7 +10,5 @@ # class MessageThreadNote < ApplicationRecord belongs_to :message_thread - - after_create_commit ->(note) { EventBus.publish(:message_thread_note_created, note) } - after_update_commit ->(note) { EventBus.publish(:message_thread_note_changed, note) } + include Auditable end diff --git a/app/models/tag.rb b/app/models/tag.rb index bb0a62554..7aa7ca395 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -28,9 +28,9 @@ class Tag < ApplicationRecord scope :visible, -> { where(visible: true) } + include Auditable after_create_commit ->(tag) { tag.mark_readable_by_groups(tag.tenant.admin_groups) } after_update_commit ->(tag) { EventBus.publish(:tag_renamed, tag) if previous_changes.key?("name") } - after_destroy ->(tag) { EventBus.publish(:tag_destroyed, tag) } DRAFT_SYSTEM_NAME = 'draft' diff --git a/app/models/tag_group.rb b/app/models/tag_group.rb index 942e7d623..0ae5f1ae1 100644 --- a/app/models/tag_group.rb +++ b/app/models/tag_group.rb @@ -14,4 +14,5 @@ class TagGroup < ApplicationRecord # used for joins only has_many :group_memberships, primary_key: :group_id, foreign_key: :group_id + include Auditable end diff --git a/app/models/user.rb b/app/models/user.rb index 53d0d7286..c1e77dd82 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,6 +23,7 @@ class User < ApplicationRecord before_destroy :delete_user_group, prepend: true after_create :handle_default_groups + include Auditable def site_admin? ENV['SITE_ADMIN_EMAILS'].to_s.split(',').include?(email) diff --git a/db/migrate/20231127112038_update_audit_logs_from_changed_to_updated.rb b/db/migrate/20231127112038_update_audit_logs_from_changed_to_updated.rb new file mode 100644 index 000000000..2f04e336e --- /dev/null +++ b/db/migrate/20231127112038_update_audit_logs_from_changed_to_updated.rb @@ -0,0 +1,6 @@ +class UpdateAuditLogsFromChangedToUpdated < ActiveRecord::Migration[7.0] + def change + AuditLog.connection.execute("update audit_logs set type = 'AuditLog::MessageThreadTagUpdated' where type = 'AuditLog::MessageThreadTagChanged'") + AuditLog.connection.execute("update audit_logs set type = 'AuditLog::MessageThreadNoteUpdated' where type = 'AuditLog::MessageThreadNoteChanged'") + end +end diff --git a/db/schema.rb b/db/schema.rb index a64d6eb8d..a9572cc63 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_11_23_085142) do +ActiveRecord::Schema[7.0].define(version: 2023_11_27_112038) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" From fbba4fd6158463fa5e8060a5b3f5aa804973ebb0 Mon Sep 17 00:00:00 2001 From: stage-rl Date: Tue, 28 Nov 2023 09:01:26 +0100 Subject: [PATCH 03/88] Health check API --- app/controllers/health_check_controller.rb | 39 ++++++++++++++++++++++ config/routes.rb | 4 +++ 2 files changed, 43 insertions(+) create mode 100644 app/controllers/health_check_controller.rb diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb new file mode 100644 index 000000000..c611b0610 --- /dev/null +++ b/app/controllers/health_check_controller.rb @@ -0,0 +1,39 @@ +class HealthCheckController < ApplicationController + skip_before_action :authenticate + skip_after_action :verify_authorized + skip_after_action :verify_policy_scoped + skip_before_action :set_menu_context + + FETCH_LIMIT = 10 + JOB_STUCK_MINUTES = 30 + + def show + if ActiveRecord::Base.connection.active? + render status: :ok, json: { ok: true } + else + render status: :service_unavailable, json: { ok: false } + end + rescue Exception + render status: :service_unavailable, json: { ok: false } + end + + def failing_jobs + failed_jobs = GoodJob::Job.where.not(error: nil).limit(FETCH_LIMIT) + if failed_jobs.any? + render status: :service_unavailable, + json: { failed_jobs: failed_jobs.count == FETCH_LIMIT ? ">#{FETCH_LIMIT}" : failed_jobs.count.to_s } + else + render status: :ok, json: { ok: true } + end + end + + def stuck_jobs + stuck_jobs = GoodJob::Job.where(finished_at: nil).where("COALESCE(scheduled_at, created_at) < ?", JOB_STUCK_MINUTES.minutes.ago).limit(11) + if stuck_jobs.any? + render status: :service_unavailable, + json: { stuck_jobs: stuck_jobs.count == FETCH_LIMIT ? ">#{FETCH_LIMIT}" : stuck_jobs.count.to_s } + else + render status: :ok, json: { ok: true } + end + end +end diff --git a/config/routes.rb b/config/routes.rb index a2e367520..4f2b14bd1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -131,6 +131,10 @@ get "/service-worker.js" => "service_worker#service_worker" get "/manifest.json" => "service_worker#manifest" + get "/health", to: "health_check#show" + get "/health/jobs/failing", to: "health_check#failing_jobs" + get "/health/jobs/stuck", to: "health_check#stuck_jobs" + root 'message_threads#index' class GoodJobAdmin From cd77c002174d0821cfe7d631d826eb6fe4f125ac Mon Sep 17 00:00:00 2001 From: stage-rl Date: Tue, 28 Nov 2023 10:19:28 +0100 Subject: [PATCH 04/88] Refactor based on PR review --- app/models/automation/rule.rb | 3 ++- app/models/concerns/{auditable.rb => auditable_events.rb} | 4 +++- app/models/filter.rb | 3 ++- app/models/group.rb | 4 ++-- app/models/message_thread_note.rb | 3 ++- app/models/tag.rb | 3 ++- app/models/user.rb | 3 ++- 7 files changed, 15 insertions(+), 8 deletions(-) rename app/models/concerns/{auditable.rb => auditable_events.rb} (95%) diff --git a/app/models/automation/rule.rb b/app/models/automation/rule.rb index 7de1319db..754f14718 100644 --- a/app/models/automation/rule.rb +++ b/app/models/automation/rule.rb @@ -12,6 +12,8 @@ # module Automation class Rule < ApplicationRecord + include AuditableEvents + belongs_to :tenant belongs_to :user has_many :conditions, @@ -24,7 +26,6 @@ class Rule < ApplicationRecord dependent: :destroy, foreign_key: :automation_rule_id, inverse_of: :automation_rule - include Auditable accepts_nested_attributes_for :conditions, :actions, allow_destroy: true diff --git a/app/models/concerns/auditable.rb b/app/models/concerns/auditable_events.rb similarity index 95% rename from app/models/concerns/auditable.rb rename to app/models/concerns/auditable_events.rb index ee607b3c8..98334c844 100644 --- a/app/models/concerns/auditable.rb +++ b/app/models/concerns/auditable_events.rb @@ -1,10 +1,12 @@ -module Auditable +module AuditableEvents extend ActiveSupport::Concern + included do after_destroy :audit_destroy after_create :audit_create after_update :audit_update end + def audit_destroy EventBus.publish(event_name(:destroyed), self) end diff --git a/app/models/filter.rb b/app/models/filter.rb index a20b136a9..e64e2e8ef 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -12,9 +12,10 @@ # tenant_id :bigint not null # class Filter < ApplicationRecord + include AuditableEvents + belongs_to :author, class_name: 'User' belongs_to :tenant - include Auditable validates :tenant_id, :author_id, :name, :query, presence: true diff --git a/app/models/group.rb b/app/models/group.rb index b2d1bd359..06c63a416 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -10,14 +10,14 @@ # tenant_id :bigint not null # class Group < ApplicationRecord + include AuditableEvents + belongs_to :tenant has_many :group_memberships, dependent: :destroy has_many :users, through: :group_memberships has_many :tag_groups, dependent: :destroy has_many :tags, through: :tag_groups - include Auditable - validates_presence_of :name validates_uniqueness_of :name, scope: :tenant_id validates :group_type, inclusion: { in: ['ALL', 'USER', 'ADMIN', 'CUSTOM'], allow_blank: false } diff --git a/app/models/message_thread_note.rb b/app/models/message_thread_note.rb index 60d955bee..81d291c5f 100644 --- a/app/models/message_thread_note.rb +++ b/app/models/message_thread_note.rb @@ -9,6 +9,7 @@ # message_thread_id :bigint not null # class MessageThreadNote < ApplicationRecord + include AuditableEvents + belongs_to :message_thread - include Auditable end diff --git a/app/models/tag.rb b/app/models/tag.rb index 7aa7ca395..8b343f880 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -13,6 +13,8 @@ # user_id :bigint # class Tag < ApplicationRecord + include AuditableEvents + belongs_to :tenant belongs_to :owner, class_name: 'User', optional: true, foreign_key: :user_id has_many :tag_groups, dependent: :destroy @@ -28,7 +30,6 @@ class Tag < ApplicationRecord scope :visible, -> { where(visible: true) } - include Auditable after_create_commit ->(tag) { tag.mark_readable_by_groups(tag.tenant.admin_groups) } after_update_commit ->(tag) { EventBus.publish(:tag_renamed, tag) if previous_changes.key?("name") } diff --git a/app/models/user.rb b/app/models/user.rb index c1e77dd82..bf69d5e57 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,8 @@ # tenant_id :bigint # class User < ApplicationRecord + include AuditableEvents + belongs_to :tenant has_many :group_memberships, dependent: :destroy has_many :groups, through: :group_memberships @@ -23,7 +25,6 @@ class User < ApplicationRecord before_destroy :delete_user_group, prepend: true after_create :handle_default_groups - include Auditable def site_admin? ENV['SITE_ADMIN_EMAILS'].to_s.split(',').include?(email) From 18decea41cb392d03bbea21b3ec65236c9fcdfd9 Mon Sep 17 00:00:00 2001 From: stage-rl Date: Tue, 28 Nov 2023 10:19:47 +0100 Subject: [PATCH 05/88] Refactor based on PR review --- app/models/group_membership.rb | 3 ++- app/models/tag_group.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/group_membership.rb b/app/models/group_membership.rb index 9cda11227..50bc29458 100644 --- a/app/models/group_membership.rb +++ b/app/models/group_membership.rb @@ -9,9 +9,10 @@ # user_id :bigint not null # class GroupMembership < ApplicationRecord + include AuditableEvents + belongs_to :group belongs_to :user - include Auditable def group_membership_modifiable? # can't be removed from default groups - "TENANT_NAME"_ALL group and named user default group "USER_NAME"_USER diff --git a/app/models/tag_group.rb b/app/models/tag_group.rb index 0ae5f1ae1..66ea09b14 100644 --- a/app/models/tag_group.rb +++ b/app/models/tag_group.rb @@ -9,10 +9,11 @@ # tag_id :bigint not null # class TagGroup < ApplicationRecord + include AuditableEvents + belongs_to :group belongs_to :tag # used for joins only has_many :group_memberships, primary_key: :group_id, foreign_key: :group_id - include Auditable end From b80b44d6a354ce007ce0f5c6c879f24c88e0a022 Mon Sep 17 00:00:00 2001 From: Miroslav Hettes Date: Tue, 28 Nov 2023 17:58:19 +0100 Subject: [PATCH 06/88] Fix inline rename and use one component --- .../admin/boxes/box_rename_component.html.erb | 28 ------------------- .../admin/boxes/box_rename_component.rb | 5 ---- .../boxes/boxes_list_row_component.html.erb | 2 +- .../groups/group_rename_component.html.erb | 28 ------------------- .../admin/groups/group_rename_component.rb | 5 ---- .../admin/groups/groups_list_component.rb | 4 +-- .../groups/groups_list_row_component.html.erb | 4 +-- .../admin/tags/tag_rename_component.html.erb | 28 ------------------- .../admin/tags/tag_rename_component.rb | 5 ---- .../tags/tags_list_row_component.html.erb | 2 +- .../tenants/tenant_rename_component.html.erb | 28 ------------------- .../admin/tenants/tenant_rename_component.rb | 5 ---- .../tenants_list_row_component.html.erb | 2 +- .../users/user_rename_component.html.erb | 28 ------------------- .../admin/users/user_rename_component.rb | 5 ---- .../users/users_list_row_component.html.erb | 2 +- .../inline_rename_component.html.erb} | 18 ++++++------ .../common/inline_rename_component.rb | 11 ++++++++ .../filters/filter_rename_component.rb | 5 ---- .../filters_list_row_component.html.erb | 2 +- app/controllers/admin/boxes_controller.rb | 2 +- app/controllers/admin/tenants_controller.rb | 2 +- app/controllers/admin/users_controller.rb | 2 +- 23 files changed, 32 insertions(+), 191 deletions(-) delete mode 100644 app/components/admin/boxes/box_rename_component.html.erb delete mode 100644 app/components/admin/boxes/box_rename_component.rb delete mode 100644 app/components/admin/groups/group_rename_component.html.erb delete mode 100644 app/components/admin/groups/group_rename_component.rb delete mode 100644 app/components/admin/tags/tag_rename_component.html.erb delete mode 100644 app/components/admin/tags/tag_rename_component.rb delete mode 100644 app/components/admin/tenants/tenant_rename_component.html.erb delete mode 100644 app/components/admin/tenants/tenant_rename_component.rb delete mode 100644 app/components/admin/users/user_rename_component.html.erb delete mode 100644 app/components/admin/users/user_rename_component.rb rename app/components/{filters/filter_rename_component.html.erb => common/inline_rename_component.html.erb} (60%) create mode 100644 app/components/common/inline_rename_component.rb delete mode 100644 app/components/filters/filter_rename_component.rb diff --git a/app/components/admin/boxes/box_rename_component.html.erb b/app/components/admin/boxes/box_rename_component.html.erb deleted file mode 100644 index 2949e405f..000000000 --- a/app/components/admin/boxes/box_rename_component.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
diff --git a/app/components/admin/boxes/box_rename_component.rb b/app/components/admin/boxes/box_rename_component.rb deleted file mode 100644 index 2e51070d0..000000000 --- a/app/components/admin/boxes/box_rename_component.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::Boxes::BoxRenameComponent < ViewComponent::Base - def initialize(box) - @box = box - end -end diff --git a/app/components/admin/boxes/boxes_list_row_component.html.erb b/app/components/admin/boxes/boxes_list_row_component.html.erb index fcea25a51..88959af9c 100644 --- a/app/components/admin/boxes/boxes_list_row_component.html.erb +++ b/app/components/admin/boxes/boxes_list_row_component.html.erb @@ -4,7 +4,7 @@
- <%= render Admin::Boxes::BoxRenameComponent.new(@box) %> + <%= render Common::InlineRenameComponent.new(name: @box.name, model: [:admin, @box.tenant, @box]) %>
<%= @box.uri %> diff --git a/app/components/admin/groups/group_rename_component.html.erb b/app/components/admin/groups/group_rename_component.html.erb deleted file mode 100644 index 440168d25..000000000 --- a/app/components/admin/groups/group_rename_component.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
diff --git a/app/components/admin/groups/group_rename_component.rb b/app/components/admin/groups/group_rename_component.rb deleted file mode 100644 index 6b8d012f4..000000000 --- a/app/components/admin/groups/group_rename_component.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::Groups::GroupRenameComponent < ViewComponent::Base - def initialize(group) - @group = group - end -end diff --git a/app/components/admin/groups/groups_list_component.rb b/app/components/admin/groups/groups_list_component.rb index d3760e96c..5a227e2de 100644 --- a/app/components/admin/groups/groups_list_component.rb +++ b/app/components/admin/groups/groups_list_component.rb @@ -1,6 +1,6 @@ class Admin::Groups::GroupsListComponent < ViewComponent::Base def initialize(editable_groups:, non_editable_groups:) - @editable_groups = editable_groups - @non_editable_groups = non_editable_groups + @editable_groups = editable_groups.to_a.sort_by(&:name) + @non_editable_groups = non_editable_groups.to_a.sort_by(&:name) end end diff --git a/app/components/admin/groups/groups_list_row_component.html.erb b/app/components/admin/groups/groups_list_row_component.html.erb index 0f6c41be2..501b86225 100644 --- a/app/components/admin/groups/groups_list_row_component.html.erb +++ b/app/components/admin/groups/groups_list_row_component.html.erb @@ -5,8 +5,8 @@
<% if @group.renamable? %> - <%= render Admin::Groups::GroupRenameComponent.new(@group) %> - <% else %> + <%= render Common::InlineRenameComponent.new(name: @group.name, model: [:admin, @group.tenant, @group], url: admin_tenant_group_path(@group.tenant, @group)) %> + <% else %> <%= @group.name %> <% end %>
diff --git a/app/components/admin/tags/tag_rename_component.html.erb b/app/components/admin/tags/tag_rename_component.html.erb deleted file mode 100644 index b3fe13a64..000000000 --- a/app/components/admin/tags/tag_rename_component.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
diff --git a/app/components/admin/tags/tag_rename_component.rb b/app/components/admin/tags/tag_rename_component.rb deleted file mode 100644 index f8cc372b5..000000000 --- a/app/components/admin/tags/tag_rename_component.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::Tags::TagRenameComponent < ViewComponent::Base - def initialize(tag) - @tag = tag - end -end diff --git a/app/components/admin/tags/tags_list_row_component.html.erb b/app/components/admin/tags/tags_list_row_component.html.erb index e3ba0cb85..0285e0a32 100644 --- a/app/components/admin/tags/tags_list_row_component.html.erb +++ b/app/components/admin/tags/tags_list_row_component.html.erb @@ -1,7 +1,7 @@
- <%= render Admin::Tags::TagRenameComponent.new(@tag) %> + <%= render Common::InlineRenameComponent.new(name: @tag.name, model: [:admin, @tag.tenant, @tag]) %>
diff --git a/app/components/admin/tenants/tenant_rename_component.html.erb b/app/components/admin/tenants/tenant_rename_component.html.erb deleted file mode 100644 index 269a21abc..000000000 --- a/app/components/admin/tenants/tenant_rename_component.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
diff --git a/app/components/admin/tenants/tenant_rename_component.rb b/app/components/admin/tenants/tenant_rename_component.rb deleted file mode 100644 index 23762b681..000000000 --- a/app/components/admin/tenants/tenant_rename_component.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::Tenants::TenantRenameComponent < ViewComponent::Base - def initialize(tenant) - @tenant = tenant - end -end diff --git a/app/components/admin/tenants/tenants_list_row_component.html.erb b/app/components/admin/tenants/tenants_list_row_component.html.erb index 8ce6252a7..344a78fbb 100644 --- a/app/components/admin/tenants/tenants_list_row_component.html.erb +++ b/app/components/admin/tenants/tenants_list_row_component.html.erb @@ -4,7 +4,7 @@
- <%= render Admin::Tenants::TenantRenameComponent.new(@tenant) %> + <%= render Common::InlineRenameComponent.new(name: @tenant.name, model: [:admin, @tenant]) %>
diff --git a/app/components/admin/users/user_rename_component.html.erb b/app/components/admin/users/user_rename_component.html.erb deleted file mode 100644 index 7adc23009..000000000 --- a/app/components/admin/users/user_rename_component.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -
- - -
diff --git a/app/components/admin/users/user_rename_component.rb b/app/components/admin/users/user_rename_component.rb deleted file mode 100644 index bf315a750..000000000 --- a/app/components/admin/users/user_rename_component.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::Users::UserRenameComponent < ViewComponent::Base - def initialize(user) - @user = user - end -end diff --git a/app/components/admin/users/users_list_row_component.html.erb b/app/components/admin/users/users_list_row_component.html.erb index e0c7601a1..d324b2551 100644 --- a/app/components/admin/users/users_list_row_component.html.erb +++ b/app/components/admin/users/users_list_row_component.html.erb @@ -4,7 +4,7 @@
- <%= render Admin::Users::UserRenameComponent.new(@user) %> + <%= render Common::InlineRenameComponent.new(name: @user.name, model: [:admin, @user.tenant, @user]) %>
<%= @user.email %> diff --git a/app/components/filters/filter_rename_component.html.erb b/app/components/common/inline_rename_component.html.erb similarity index 60% rename from app/components/filters/filter_rename_component.html.erb rename to app/components/common/inline_rename_component.html.erb index b57c0e201..7b9700051 100644 --- a/app/components/filters/filter_rename_component.html.erb +++ b/app/components/common/inline_rename_component.html.erb @@ -1,24 +1,24 @@
- -