From 4653038ecaeecc46f15d672bb21aa66bbd233323 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 9 Jan 2024 23:56:32 -0700 Subject: [PATCH] [WIP] Upgrade to avo 3 --- Gemfile | 3 +- Gemfile.lock | 25 +++--- app/avo/actions/add_owner.rb | 12 +-- .../{base_action.rb => application_action.rb} | 46 +++++------ app/avo/actions/block_user.rb | 4 +- app/avo/actions/change_user_email.rb | 8 +- app/avo/actions/create_user.rb | 8 +- app/avo/actions/delete_webhook.rb | 4 +- app/avo/actions/refresh_oidc_provider.rb | 4 +- app/avo/actions/release_reserved_namespace.rb | 4 +- app/avo/actions/reset_api_key.rb | 18 +++-- app/avo/actions/reset_user_2fa.rb | 4 +- app/avo/actions/restore_version.rb | 6 +- app/avo/actions/upload_info_file.rb | 4 +- app/avo/actions/upload_names_file.rb | 2 +- app/avo/actions/upload_versions_file.rb | 2 +- app/avo/actions/yank_rubygem.rb | 18 +++-- app/avo/actions/yank_rubygems_for_user.rb | 6 +- app/avo/actions/yank_user.rb | 4 +- app/avo/cards/dashboard_welcome_card.rb | 2 +- app/avo/cards/pushes_chart.rb | 2 +- app/avo/cards/rubygems_metric.rb | 2 +- app/avo/cards/users_metric.rb | 2 +- app/avo/cards/versions_metric.rb | 2 +- app/avo/dashboards/dashy.rb | 14 ++-- app/avo/fields/array_of_field.rb | 4 +- app/avo/fields/audited_changes_field.rb | 2 +- app/avo/fields/json_viewer_field.rb | 2 +- app/avo/fields/nested_field.rb | 4 +- app/avo/fields/select_record_field.rb | 2 +- app/avo/filters/email_filter.rb | 2 +- app/avo/filters/scope_boolean_filter.rb | 2 +- app/avo/resources/admin_github_user.rb | 34 ++++++++ .../resources/admin_github_user_resource.rb | 30 ------- app/avo/resources/api_key.rb | 46 +++++++++++ app/avo/resources/api_key_resource.rb | 39 ---------- app/avo/resources/api_key_rubygem_scope.rb | 11 +++ .../api_key_rubygem_scope_resource.rb | 9 --- app/avo/resources/audit.rb | 40 ++++++++++ app/avo/resources/audit_resource.rb | 36 --------- .../concerns/avo_auditable_resource.rb | 24 +++--- app/avo/resources/deletion.rb | 15 ++++ app/avo/resources/deletion_resource.rb | 17 ---- app/avo/resources/dependency.rb | 18 +++++ app/avo/resources/dependency_resource.rb | 19 ----- app/avo/resources/gem_download.rb | 32 ++++++++ app/avo/resources/gem_download_resource.rb | 27 ------- app/avo/resources/gem_name_reservation.rb | 14 ++++ .../gem_name_reservation_resource.rb | 10 --- app/avo/resources/gem_typo_exception.rb | 19 +++++ .../resources/gem_typo_exception_resource.rb | 15 ---- app/avo/resources/link_verification.rb | 17 ++++ .../resources/link_verification_resource.rb | 19 ----- app/avo/resources/linkset.rb | 14 ++++ app/avo/resources/linkset_resource.rb | 12 --- app/avo/resources/log_ticket.rb | 22 ++++++ app/avo/resources/log_ticket_resource.rb | 18 ----- app/avo/resources/maintenance_tasks_run.rb | 30 +++++++ .../maintenance_tasks_run_resource.rb | 29 ------- app/avo/resources/oidc_api_key_role.rb | 34 ++++++++ .../resources/oidc_api_key_role_resource.rb | 36 --------- app/avo/resources/oidc_id_token.rb | 21 +++++ app/avo/resources/oidc_id_token_resource.rb | 23 ------ .../oidc_pending_trusted_publisher.rb | 20 +++++ ...oidc_pending_trusted_publisher_resource.rb | 16 ---- app/avo/resources/oidc_provider.rb | 23 ++++++ app/avo/resources/oidc_provider_resource.rb | 20 ----- .../oidc_rubygem_trusted_publisher.rb | 12 +++ ...oidc_rubygem_trusted_publisher_resource.rb | 11 --- .../oidc_trusted_publisher_github_action.rb | 20 +++++ ...rusted_publisher_github_action_resource.rb | 19 ----- app/avo/resources/ownership.rb | 34 ++++++++ app/avo/resources/ownership_resource.rb | 29 ------- app/avo/resources/rubygem.rb | 54 +++++++++++++ app/avo/resources/rubygem_resource.rb | 46 ----------- app/avo/resources/sendgrid_event.rb | 27 +++++++ app/avo/resources/sendgrid_event_resource.rb | 25 ------ app/avo/resources/user.rb | 77 ++++++++++++++++++ app/avo/resources/user_resource.rb | 71 ----------------- app/avo/resources/version.rb | 78 +++++++++++++++++++ app/avo/resources/version_resource.rb | 69 ---------------- app/avo/resources/web_hook.rb | 43 ++++++++++ app/avo/resources/web_hook_resource.rb | 35 --------- app/avo/resources/webauthn_credential.rb | 14 ++++ .../resources/webauthn_credential_resource.rb | 13 ---- app/avo/resources/webauthn_verification.rb | 14 ++++ .../webauthn_verification_resource.rb | 13 ---- config/initializers/avo.rb | 2 +- 88 files changed, 917 insertions(+), 822 deletions(-) rename app/avo/actions/{base_action.rb => application_action.rb} (68%) create mode 100644 app/avo/resources/admin_github_user.rb delete mode 100644 app/avo/resources/admin_github_user_resource.rb create mode 100644 app/avo/resources/api_key.rb delete mode 100644 app/avo/resources/api_key_resource.rb create mode 100644 app/avo/resources/api_key_rubygem_scope.rb delete mode 100644 app/avo/resources/api_key_rubygem_scope_resource.rb create mode 100644 app/avo/resources/audit.rb delete mode 100644 app/avo/resources/audit_resource.rb create mode 100644 app/avo/resources/deletion.rb delete mode 100644 app/avo/resources/deletion_resource.rb create mode 100644 app/avo/resources/dependency.rb delete mode 100644 app/avo/resources/dependency_resource.rb create mode 100644 app/avo/resources/gem_download.rb delete mode 100644 app/avo/resources/gem_download_resource.rb create mode 100644 app/avo/resources/gem_name_reservation.rb delete mode 100644 app/avo/resources/gem_name_reservation_resource.rb create mode 100644 app/avo/resources/gem_typo_exception.rb delete mode 100644 app/avo/resources/gem_typo_exception_resource.rb create mode 100644 app/avo/resources/link_verification.rb delete mode 100644 app/avo/resources/link_verification_resource.rb create mode 100644 app/avo/resources/linkset.rb delete mode 100644 app/avo/resources/linkset_resource.rb create mode 100644 app/avo/resources/log_ticket.rb delete mode 100644 app/avo/resources/log_ticket_resource.rb create mode 100644 app/avo/resources/maintenance_tasks_run.rb delete mode 100644 app/avo/resources/maintenance_tasks_run_resource.rb create mode 100644 app/avo/resources/oidc_api_key_role.rb delete mode 100644 app/avo/resources/oidc_api_key_role_resource.rb create mode 100644 app/avo/resources/oidc_id_token.rb delete mode 100644 app/avo/resources/oidc_id_token_resource.rb create mode 100644 app/avo/resources/oidc_pending_trusted_publisher.rb delete mode 100644 app/avo/resources/oidc_pending_trusted_publisher_resource.rb create mode 100644 app/avo/resources/oidc_provider.rb delete mode 100644 app/avo/resources/oidc_provider_resource.rb create mode 100644 app/avo/resources/oidc_rubygem_trusted_publisher.rb delete mode 100644 app/avo/resources/oidc_rubygem_trusted_publisher_resource.rb create mode 100644 app/avo/resources/oidc_trusted_publisher_github_action.rb delete mode 100644 app/avo/resources/oidc_trusted_publisher_github_action_resource.rb create mode 100644 app/avo/resources/ownership.rb delete mode 100644 app/avo/resources/ownership_resource.rb create mode 100644 app/avo/resources/rubygem.rb delete mode 100644 app/avo/resources/rubygem_resource.rb create mode 100644 app/avo/resources/sendgrid_event.rb delete mode 100644 app/avo/resources/sendgrid_event_resource.rb create mode 100644 app/avo/resources/user.rb delete mode 100644 app/avo/resources/user_resource.rb create mode 100644 app/avo/resources/version.rb delete mode 100644 app/avo/resources/version_resource.rb create mode 100644 app/avo/resources/web_hook.rb delete mode 100644 app/avo/resources/web_hook_resource.rb create mode 100644 app/avo/resources/webauthn_credential.rb delete mode 100644 app/avo/resources/webauthn_credential_resource.rb create mode 100644 app/avo/resources/webauthn_verification.rb delete mode 100644 app/avo/resources/webauthn_verification_resource.rb diff --git a/Gemfile b/Gemfile index 5ef6e016d27..485885b8cd1 100644 --- a/Gemfile +++ b/Gemfile @@ -62,7 +62,8 @@ gem "strong_migrations", "~> 1.7" gem "phlex-rails", "~> 1.1" # Admin dashboard -gem "avo", "~> 2.46" +gem "avo", "~> 3.2" +# gem "avo-pro", "~> 3.2", source: "https://packager.dev/avo-hq/" gem "view_component", "~> 3.9" gem "pundit", "~> 2.3" gem "chartkick", "~> 5.0" diff --git a/Gemfile.lock b/Gemfile.lock index cf88fdaa76c..824781d7e73 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -84,10 +84,11 @@ GEM attr_required (1.0.2) autoprefixer-rails (10.4.16.0) execjs (~> 2) - avo (2.46.0) - actionview (>= 6.0) + avo (3.2.3) + actionview (>= 6.1) active_link_to - activerecord (>= 6.0) + activerecord (>= 6.1) + activesupport (>= 6.1) addressable docile dry-initializer @@ -96,9 +97,9 @@ GEM meta-tags pagy turbo-rails - turbo_power (~> 0.5.0) - view_component (>= 2.54.0) - zeitwerk (>= 2.6.2) + turbo_power (>= 0.6.0) + view_component (>= 3.7.0) + zeitwerk (>= 2.6.12) awrence (1.2.1) aws-eventstream (1.3.0) aws-partitions (1.873.0) @@ -347,8 +348,8 @@ GEM marcel (1.0.2) matrix (0.4.2) memory_profiler (1.0.1) - meta-tags (2.19.0) - actionpack (>= 3.2.0, < 7.2) + meta-tags (2.20.0) + actionpack (>= 6.0.0, < 7.2) method_source (1.0.0) mini_histogram (0.3.1) mini_mime (1.1.5) @@ -427,7 +428,7 @@ GEM openssl-signature_algorithm (1.3.0) openssl (> 2.0) optimist (3.1.0) - pagy (6.2.0) + pagy (6.3.0) parallel (1.22.1) parser (3.2.2.4) ast (~> 2.4.1) @@ -646,8 +647,8 @@ GEM actionpack (>= 6.0.0) activejob (>= 6.0.0) railties (>= 6.0.0) - turbo_power (0.5.0) - turbo-rails (~> 1.3) + turbo_power (0.6.1) + turbo-rails (>= 1.3.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) @@ -699,7 +700,7 @@ DEPENDENCIES aggregate_assertions (~> 0.2.0) amazing_print (~> 1.4) autoprefixer-rails (~> 10.4) - avo (~> 2.46) + avo (~> 3.2) aws-sdk-s3 (~> 1.142) aws-sdk-sqs (~> 1.69) bcrypt (~> 3.1) diff --git a/app/avo/actions/add_owner.rb b/app/avo/actions/add_owner.rb index bd98d1b8993..b24cbd71f94 100644 --- a/app/avo/actions/add_owner.rb +++ b/app/avo/actions/add_owner.rb @@ -1,10 +1,12 @@ -class AddOwner < BaseAction +class Avo::Actions::AddOwner < Avo::Actions::ApplicationAction self.name = "Add owner" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show } - field :owner, as: :select_record, searchable: true, name: "New owner", use_resource: UserResource + def fields + field :owner, as: :select_record, searchable: true, name: "New owner", use_resource: Avo::Resources::User + end self.message = lambda { "Are you sure you would like to add an owner to #{record.name}?" @@ -22,16 +24,16 @@ class ActionHandler < ActionHandler error "Cannot add #{@owner.name} as an owner since they are unconfirmed" if @owner.unconfirmed? end - def do_handle_model(rubygem) + def do_handle_record(rubygem) @rubygem = rubygem super end - set_callback :handle_model, :before do + set_callback :handle_record, :before do error "Cannot add #{@owner.name} as an owner since they are already an owner of #{@rubygem.name}" if @owner.rubygems.include?(@rubygem) end - def handle_model(rubygem) + def handle_record(rubygem) authorizer = User.security_user rubygem.ownerships.create!(user: @owner, authorizer: authorizer, confirmed_at: Time.current) succeed "Added #{@owner.name} to #{@rubygem.name}" diff --git a/app/avo/actions/base_action.rb b/app/avo/actions/application_action.rb similarity index 68% rename from app/avo/actions/base_action.rb rename to app/avo/actions/application_action.rb index 4e985aef5b2..43a0776dbc6 100644 --- a/app/avo/actions/base_action.rb +++ b/app/avo/actions/application_action.rb @@ -1,16 +1,18 @@ -class BaseAction < Avo::BaseAction +class Avo::Actions::ApplicationAction < Avo::BaseAction include SemanticLogger::Loggable - field :comment, as: :textarea, required: true, - help: "A comment explaining why this action was taken.
Will be saved in the audit log.
Must be more than 10 characters." - - def self.inherited(base) - super - base.items_holder = Avo::ItemsHolder.new - base.items_holder.instance_variable_get(:@items).replace items_holder.instance_variable_get(:@items).deep_dup - base.items_holder.invalid_fields.replace items_holder.invalid_fields.deep_dup + def fields + field :comment, as: :textarea, required: true, + help: "A comment explaining why this action was taken.
Will be saved in the audit log.
Must be more than 10 characters." end + # def self.inherited(base) + # super + # base.items_holder = Avo::Resources::Items::Holder.new + # base.items_holder.instance_variable_get(:@items).replace items_holder.instance_variable_get(:@items).deep_dup + # base.items_holder.invalid_fields.replace items_holder.invalid_fields.deep_dup + # end + class ActionHandler include Auditable include SemanticLogger::Loggable @@ -20,7 +22,7 @@ class ActionHandler result_lambda.call target.errored? } - define_callbacks :handle_model, terminator: lambda { |target, result_lambda| + define_callbacks :handle_record, terminator: lambda { |target, result_lambda| result_lambda.call target.errored? } @@ -35,9 +37,9 @@ def initialize( # rubocop:disable Metrics/ParameterLists arguments:, resource:, action:, - models: nil + records: nil ) - @models = models + @records = records @fields = fields @current_user = current_user @arguments = arguments @@ -46,7 +48,7 @@ def initialize( # rubocop:disable Metrics/ParameterLists @action = action end - attr_reader :models, :fields, :current_user, :arguments, :resource + attr_reader :records, :fields, :current_user, :arguments, :resource delegate :error, :avo, :keep_modal_open, :redirect_to, :inform, :action_name, :succeed, :logger, to: :@action @@ -72,9 +74,9 @@ def do_handle keep_modal_open if errored? end - def do_handle_model(model) - run_callbacks :handle_model do - handle_model(model) + def do_handle_record(record) + run_callbacks :handle_record do + handle_record(record) end end @@ -89,7 +91,7 @@ def do_handle_standalone action: action_name, fields:, arguments:, - models: + records: ) do run_callbacks :handle_standalone do handle_standalone @@ -99,17 +101,17 @@ def do_handle_standalone end def handle - return do_handle_standalone if models.nil? - models.each do |model| + return do_handle_standalone if records.nil? + records.each do |record| _, audit = in_audited_transaction( - auditable: model, + auditable: record, admin_github_user: current_user, action: action_name, fields:, arguments:, - models: + records: ) do - do_handle_model(model) + do_handle_record(record) end redirect_to avo.resources_audit_path(audit) end diff --git a/app/avo/actions/block_user.rb b/app/avo/actions/block_user.rb index d73eb3fb7f8..6bde6c44fc0 100644 --- a/app/avo/actions/block_user.rb +++ b/app/avo/actions/block_user.rb @@ -1,4 +1,4 @@ -class BlockUser < BaseAction +class Avo::Actions::BlockUser < Avo::Actions::ApplicationAction self.name = "Block User" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -11,7 +11,7 @@ class BlockUser < BaseAction self.confirm_button_label = "Block User" class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) user.block! end end diff --git a/app/avo/actions/change_user_email.rb b/app/avo/actions/change_user_email.rb index 949a0f82feb..a24e5782957 100644 --- a/app/avo/actions/change_user_email.rb +++ b/app/avo/actions/change_user_email.rb @@ -1,5 +1,7 @@ -class ChangeUserEmail < BaseAction - field :from_email, name: "Email", as: :text, required: true +class Avo::Actions::ChangeUserEmail < Avo::Actions::ApplicationAction + def fields + field :from_email, name: "Email", as: :text, required: true + end self.name = "Change User Email" self.visible = lambda { @@ -9,7 +11,7 @@ class ChangeUserEmail < BaseAction self.confirm_button_label = "Change User Email" class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) user.email = fields["from_email"] user.email_confirmed = false user.generate_confirmation_token diff --git a/app/avo/actions/create_user.rb b/app/avo/actions/create_user.rb index 1c990b018c5..752ab0154b7 100644 --- a/app/avo/actions/create_user.rb +++ b/app/avo/actions/create_user.rb @@ -1,6 +1,4 @@ -class CreateUser < BaseAction - field :email, name: "Email", as: :text, required: true - +class Avo::Actions::CreateUser < Avo::Actions::ApplicationAction self.name = "Create User" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :index && !Rails.env.production? @@ -9,6 +7,10 @@ class CreateUser < BaseAction self.confirm_button_label = "Create User" + def fields + field :email, name: "Email", as: :text, required: true + end + class ActionHandler < ActionHandler def handle_standalone user = User.new( diff --git a/app/avo/actions/delete_webhook.rb b/app/avo/actions/delete_webhook.rb index 4a696fbc5c8..0aa4ba4d5d3 100644 --- a/app/avo/actions/delete_webhook.rb +++ b/app/avo/actions/delete_webhook.rb @@ -1,4 +1,4 @@ -class DeleteWebhook < BaseAction +class Avo::Actions::DeleteWebhook < Avo::Actions::ApplicationAction self.name = "Delete Webhook" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -11,7 +11,7 @@ class DeleteWebhook < BaseAction self.confirm_button_label = "Delete Webhook" class ActionHandler < ActionHandler - def handle_model(webhook) + def handle_record(webhook) webhook.destroy! WebHooksMailer.webhook_deleted(webhook.user_id, webhook.rubygem_id, webhook.url, webhook.failure_count).deliver_later end diff --git a/app/avo/actions/refresh_oidc_provider.rb b/app/avo/actions/refresh_oidc_provider.rb index c53e53d766f..a1f025d9be2 100644 --- a/app/avo/actions/refresh_oidc_provider.rb +++ b/app/avo/actions/refresh_oidc_provider.rb @@ -1,4 +1,4 @@ -class RefreshOIDCProvider < BaseAction +class Avo::Actions::RefreshOIDCProvider < Avo::Actions::ApplicationAction self.name = "Refresh OIDC Provider" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -11,7 +11,7 @@ class RefreshOIDCProvider < BaseAction self.confirm_button_label = "Refresh" class ActionHandler < ActionHandler - def handle_model(provider) + def handle_record(provider) RefreshOIDCProviderJob.perform_now(provider:) end end diff --git a/app/avo/actions/release_reserved_namespace.rb b/app/avo/actions/release_reserved_namespace.rb index 1cbbe8b793c..0dcad48a02a 100644 --- a/app/avo/actions/release_reserved_namespace.rb +++ b/app/avo/actions/release_reserved_namespace.rb @@ -1,4 +1,4 @@ -class ReleaseReservedNamespace < BaseAction +class Avo::Actions::ReleaseReservedNamespace < Avo::Actions::ApplicationAction self.name = "Release reserved namespace" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -11,7 +11,7 @@ class ReleaseReservedNamespace < BaseAction self.confirm_button_label = "Release namespace" class ActionHandler < ActionHandler - def handle_model(rubygem) + def handle_record(rubygem) rubygem.release_reserved_namespace! end end diff --git a/app/avo/actions/reset_api_key.rb b/app/avo/actions/reset_api_key.rb index 9f5240c4958..a2a1a8f50bc 100644 --- a/app/avo/actions/reset_api_key.rb +++ b/app/avo/actions/reset_api_key.rb @@ -1,4 +1,4 @@ -class ResetApiKey < BaseAction +class Avo::Actions::ResetApiKey < Avo::Actions::ApplicationAction self.name = "Reset Api Key" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -8,15 +8,17 @@ class ResetApiKey < BaseAction } self.confirm_button_label = "Reset Api Key" - field :template, as: :select, - options: { - "Public Gem": :public_gem_reset_api_key, - Honeycomb: :honeycomb_reset_api_key - }, - help: "Select mailer template" + def fields + field :template, as: :select, + options: { + "Public Gem": :public_gem_reset_api_key, + Honeycomb: :honeycomb_reset_api_key + }, + help: "Select mailer template" + end class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) user.reset_api_key! Mailer.reset_api_key(user, fields["template"]).deliver_later diff --git a/app/avo/actions/reset_user_2fa.rb b/app/avo/actions/reset_user_2fa.rb index 03e19a1d518..dc6d2f83f77 100644 --- a/app/avo/actions/reset_user_2fa.rb +++ b/app/avo/actions/reset_user_2fa.rb @@ -1,4 +1,4 @@ -class ResetUser2fa < BaseAction +class Avo::Actions::ResetUser2fa < Avo::Actions::ApplicationAction self.name = "Reset User 2FA" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -11,7 +11,7 @@ class ResetUser2fa < BaseAction self.confirm_button_label = "Reset MFA" class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) user.disable_totp! user.password = SecureRandom.hex(20).encode("UTF-8") user.save! diff --git a/app/avo/actions/restore_version.rb b/app/avo/actions/restore_version.rb index 2a5bf7f250f..15b9f816984 100644 --- a/app/avo/actions/restore_version.rb +++ b/app/avo/actions/restore_version.rb @@ -1,9 +1,9 @@ -class RestoreVersion < BaseAction +class Avo::Actions::RestoreVersion < Avo::Actions::ApplicationAction self.name = "Restore version" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show && - resource.model.deletion.present? + resource.record.deletion.present? } self.message = lambda { "Are you sure you would like to restore #{record.slug} with " @@ -11,7 +11,7 @@ class RestoreVersion < BaseAction self.confirm_button_label = "Restore version" class ActionHandler < ActionHandler - def handle_model(version) + def handle_record(version) version.deletion&.restore! end end diff --git a/app/avo/actions/upload_info_file.rb b/app/avo/actions/upload_info_file.rb index 38740af0a4f..2e9bfb6191f 100644 --- a/app/avo/actions/upload_info_file.rb +++ b/app/avo/actions/upload_info_file.rb @@ -1,4 +1,4 @@ -class UploadInfoFile < BaseAction +class Avo::Actions::UploadInfoFile < Avo::Actions::ApplicationAction self.name = "Upload Info File" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -6,7 +6,7 @@ class UploadInfoFile < BaseAction self.confirm_button_label = "Upload" class ActionHandler < ActionHandler - def handle_model(rubygem) + def handle_record(rubygem) UploadInfoFileJob.perform_later(rubygem_name: rubygem.name) succeed("Upload job scheduled") diff --git a/app/avo/actions/upload_names_file.rb b/app/avo/actions/upload_names_file.rb index 1ab53b4ce95..52ca1fb383d 100644 --- a/app/avo/actions/upload_names_file.rb +++ b/app/avo/actions/upload_names_file.rb @@ -1,4 +1,4 @@ -class UploadNamesFile < BaseAction +class Avo::Actions::UploadNamesFile < Avo::Actions::ApplicationAction self.name = "Upload Names File" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :index diff --git a/app/avo/actions/upload_versions_file.rb b/app/avo/actions/upload_versions_file.rb index ee5f700a02a..a051aafc48c 100644 --- a/app/avo/actions/upload_versions_file.rb +++ b/app/avo/actions/upload_versions_file.rb @@ -1,4 +1,4 @@ -class UploadVersionsFile < BaseAction +class Avo::Actions::UploadVersionsFile < Avo::Actions::ApplicationAction self.name = "Upload Versions File" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :index diff --git a/app/avo/actions/yank_rubygem.rb b/app/avo/actions/yank_rubygem.rb index 13de715d4d7..24828bc00fe 100644 --- a/app/avo/actions/yank_rubygem.rb +++ b/app/avo/actions/yank_rubygem.rb @@ -1,17 +1,19 @@ -class YankRubygem < BaseAction +class Avo::Actions::YankRubygem < Avo::Actions::ApplicationAction OPTION_ALL = "All".freeze - field :version, as: :select, - options: lambda { |model:, resource:, view:, field:| # rubocop:disable Lint/UnusedBlockArgument - [OPTION_ALL] + model.versions.indexed.pluck(:number, :id) - }, - help: "Select Version which needs to be yanked." + def fields + field :version, as: :select, + options: lambda { |record:, resource:, view:, field:| # rubocop:disable Lint/UnusedBlockArgument + [OPTION_ALL] + record.versions.indexed.pluck(:number, :id) + }, + help: "Select Version which needs to be yanked." + end self.name = "Yank Rubygem" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show && - resource.model.versions.indexed.present? + resource.record.versions.indexed.present? } self.message = lambda { @@ -21,7 +23,7 @@ class YankRubygem < BaseAction self.confirm_button_label = "Yank Rubygem" class ActionHandler < ActionHandler - def handle_model(rubygem) + def handle_record(rubygem) version_id = fields["version"] version_id_to_yank = version_id if version_id != OPTION_ALL diff --git a/app/avo/actions/yank_rubygems_for_user.rb b/app/avo/actions/yank_rubygems_for_user.rb index 3d88769b0cc..7ce5ca1564a 100644 --- a/app/avo/actions/yank_rubygems_for_user.rb +++ b/app/avo/actions/yank_rubygems_for_user.rb @@ -1,9 +1,9 @@ -class YankRubygemsForUser < BaseAction +class Avo::Actions::YankRubygemsForUser < Avo::Actions::ApplicationAction self.name = "Yank all Rubygems" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show && - resource.model.rubygems.present? + resource.record.rubygems.present? } self.message = lambda { @@ -13,7 +13,7 @@ class YankRubygemsForUser < BaseAction self.confirm_button_label = "Yank all Rubygems" class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) user.rubygems.find_each(&:yank_versions!) end end diff --git a/app/avo/actions/yank_user.rb b/app/avo/actions/yank_user.rb index 81e6dc41106..14dc9735eef 100644 --- a/app/avo/actions/yank_user.rb +++ b/app/avo/actions/yank_user.rb @@ -1,4 +1,4 @@ -class YankUser < BaseAction +class Avo::Actions::YankUser < Avo::Actions::ApplicationAction self.name = "Yank User" self.visible = lambda { current_user.team_member?("rubygems-org") && view == :show @@ -9,7 +9,7 @@ class YankUser < BaseAction self.confirm_button_label = "Yank User" class ActionHandler < ActionHandler - def handle_model(user) + def handle_record(user) rubygems = user.rubygems rubygems.find_each(&:yank_versions!) diff --git a/app/avo/cards/dashboard_welcome_card.rb b/app/avo/cards/dashboard_welcome_card.rb index 8cbadb73c47..e5d37e51490 100644 --- a/app/avo/cards/dashboard_welcome_card.rb +++ b/app/avo/cards/dashboard_welcome_card.rb @@ -1,4 +1,4 @@ -class DashboardWelcomeCard < Avo::Dashboards::PartialCard +class Avo::Cards::DashboardWelcomeCard < Avo::Cards::PartialCard self.id = "dashboard_welcome_card" self.label = "Welcome to the RubyGems.org admin dashboard!" self.partial = "avo/cards/dashboard_welcome_card" diff --git a/app/avo/cards/pushes_chart.rb b/app/avo/cards/pushes_chart.rb index 5d45743df0b..523970c762f 100644 --- a/app/avo/cards/pushes_chart.rb +++ b/app/avo/cards/pushes_chart.rb @@ -1,4 +1,4 @@ -class PushesChart < Avo::Dashboards::ChartkickCard +class Avo::Cards::PushesChart < Avo::Cards::ChartkickCard self.id = "pushes_chart" self.label = "Pushes by day" self.chart_type = :line_chart diff --git a/app/avo/cards/rubygems_metric.rb b/app/avo/cards/rubygems_metric.rb index 03f9dfc57a6..cd74a871bed 100644 --- a/app/avo/cards/rubygems_metric.rb +++ b/app/avo/cards/rubygems_metric.rb @@ -1,4 +1,4 @@ -class RubygemsMetric < Avo::Dashboards::MetricCard +class Avo::Cards::RubygemsMetric < Avo::Cards::MetricCard self.id = "rubygems_metric" self.label = "RubyGems " self.cols = 2 diff --git a/app/avo/cards/users_metric.rb b/app/avo/cards/users_metric.rb index 18033d49463..e9eb71941f2 100644 --- a/app/avo/cards/users_metric.rb +++ b/app/avo/cards/users_metric.rb @@ -1,4 +1,4 @@ -class UsersMetric < Avo::Dashboards::MetricCard +class Avo::Cards::UsersMetric < Avo::Cards::MetricCard self.id = "users_metric" self.label = "Total users" self.cols = 2 diff --git a/app/avo/cards/versions_metric.rb b/app/avo/cards/versions_metric.rb index fefa912a30f..0c245831f40 100644 --- a/app/avo/cards/versions_metric.rb +++ b/app/avo/cards/versions_metric.rb @@ -1,4 +1,4 @@ -class VersionsMetric < Avo::Dashboards::MetricCard +class Avo::Cards::VersionsMetric < Avo::Cards::MetricCard self.id = "versions_metric" self.label = "Versions pushed" diff --git a/app/avo/dashboards/dashy.rb b/app/avo/dashboards/dashy.rb index 3a5ef54376c..08214f75084 100644 --- a/app/avo/dashboards/dashy.rb +++ b/app/avo/dashboards/dashy.rb @@ -1,21 +1,21 @@ -class Dashy < Avo::Dashboards::BaseDashboard +class Avo::Dashboards::Dashy < Avo::Dashboards::BaseDashboard self.id = "dashy" - self.name = "Dashy" + self.name = "Avo::Dashboards::Dashy" self.grid_cols = 6 self.visible = lambda { current_user.team_member?("rubygems-org") } # cards go here - card DashboardWelcomeCard + card Avo::Cards::DashboardWelcomeCard divider label: "Metrics" - card UsersMetric - card VersionsMetric - card RubygemsMetric + card Avo::Cards::UsersMetric + card Avo::Cards::VersionsMetric + card Avo::Cards::RubygemsMetric divider label: "Charts" - card PushesChart + card Avo::Cards::PushesChart end diff --git a/app/avo/fields/array_of_field.rb b/app/avo/fields/array_of_field.rb index e798c45244b..962403db029 100644 --- a/app/avo/fields/array_of_field.rb +++ b/app/avo/fields/array_of_field.rb @@ -1,9 +1,9 @@ -class ArrayOfField < Avo::Fields::BaseField +class Avo::Fields::ArrayOfField < Avo::Fields::BaseField def initialize(name, field:, field_options: {}, **args, &block) super(name, **args, &nil) @make_field = lambda do |id:, index: nil, value: nil| - items_holder = Avo::ItemsHolder.new + items_holder = Avo::Resources::Items::Holder.new items_holder.field(id, name: index&.to_s || self.name, as: field, required: -> { false }, value:, **field_options, &block) items_holder.items.sole.hydrate(view:, resource:) end diff --git a/app/avo/fields/audited_changes_field.rb b/app/avo/fields/audited_changes_field.rb index 4d4398abcb3..3f4e8b522bb 100644 --- a/app/avo/fields/audited_changes_field.rb +++ b/app/avo/fields/audited_changes_field.rb @@ -1,2 +1,2 @@ -class AuditedChangesField < Avo::Fields::BaseField +class Avo::Fields::AuditedChangesField < Avo::Fields::BaseField end diff --git a/app/avo/fields/json_viewer_field.rb b/app/avo/fields/json_viewer_field.rb index df4d52e45d3..aedb7030e5f 100644 --- a/app/avo/fields/json_viewer_field.rb +++ b/app/avo/fields/json_viewer_field.rb @@ -1,4 +1,4 @@ -class JsonViewerField < Avo::Fields::CodeField +class Avo::Fields::JsonViewerField < Avo::Fields::CodeField def initialize(name, **args, &) super(name, **args, language: :javascript, line_wrapping: true, &) end diff --git a/app/avo/fields/nested_field.rb b/app/avo/fields/nested_field.rb index b621fa3eb02..0b2cdc70f61 100644 --- a/app/avo/fields/nested_field.rb +++ b/app/avo/fields/nested_field.rb @@ -1,8 +1,8 @@ -class NestedField < Avo::Fields::BaseField +class Avo::Fields::NestedField < Avo::Fields::BaseField include Avo::Concerns::HasFields def initialize(name, stacked: true, **args, &block) - @items_holder = Avo::ItemsHolder.new + @items_holder = Avo::Resources::Items::Holder.new hide_on [:index] super(name, stacked:, **args, &nil) instance_exec(&block) if block diff --git a/app/avo/fields/select_record_field.rb b/app/avo/fields/select_record_field.rb index 83da8985919..b5b2a25a45e 100644 --- a/app/avo/fields/select_record_field.rb +++ b/app/avo/fields/select_record_field.rb @@ -1,4 +1,4 @@ -class SelectRecordField < Avo::Fields::BelongsToField +class Avo::Fields::SelectRecordField < Avo::Fields::BelongsToField def foreign_key id end diff --git a/app/avo/filters/email_filter.rb b/app/avo/filters/email_filter.rb index 2a3375c86c5..2cbc9e19912 100644 --- a/app/avo/filters/email_filter.rb +++ b/app/avo/filters/email_filter.rb @@ -1,4 +1,4 @@ -class EmailFilter < Avo::Filters::TextFilter +class Avo::Filters::EmailFilter < Avo::Filters::TextFilter self.name = "Email filter" self.button_label = "Filter by email" diff --git a/app/avo/filters/scope_boolean_filter.rb b/app/avo/filters/scope_boolean_filter.rb index 6addbbcb400..67543347576 100644 --- a/app/avo/filters/scope_boolean_filter.rb +++ b/app/avo/filters/scope_boolean_filter.rb @@ -1,4 +1,4 @@ -class ScopeBooleanFilter < Avo::Filters::BooleanFilter +class Avo::Filters::ScopeBooleanFilter < Avo::Filters::BooleanFilter def name arguments.fetch(:name) { self.class.to_s.demodulize.underscore.sub(/_filter$/, "").titleize } end diff --git a/app/avo/resources/admin_github_user.rb b/app/avo/resources/admin_github_user.rb new file mode 100644 index 00000000000..40a2a6febb6 --- /dev/null +++ b/app/avo/resources/admin_github_user.rb @@ -0,0 +1,34 @@ +class Avo::Resources::AdminGitHubUser < Avo::BaseResource + self.title = :login + self.includes = [] + self.model_class = ::Admin::GitHubUser + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("login LIKE ?", "%#{params[:q]}%") + } + end + + self.description = "GitHub users that have authenticated via the admin OAuth flow." + + def fields + field :id, as: :id + + field :is_admin, as: :boolean, readonly: true + field :login, as: :text, readonly: true, + as_html: true, + format_using: -> { link_to value, "https://github.com/#{value}" } + field :avatar_url, as: :external_image, name: "Avatar", readonly: true + field :github_id, as: :text, readonly: true + field :oauth_token, as: :text, visible: -> { false } + + field :details, as: :heading + + field :teams, as: :tags, readonly: true, format_using: -> { value.pluck(:slug) } + + field :info_data, + as: :code, readonly: true, language: :javascript, + format_using: -> { JSON.pretty_generate value } + + field :audits, as: :has_many + end +end diff --git a/app/avo/resources/admin_github_user_resource.rb b/app/avo/resources/admin_github_user_resource.rb deleted file mode 100644 index d9a915f1af5..00000000000 --- a/app/avo/resources/admin_github_user_resource.rb +++ /dev/null @@ -1,30 +0,0 @@ -class AdminGitHubUserResource < Avo::BaseResource - self.title = :login - self.includes = [] - self.model_class = ::Admin::GitHubUser - self.search_query = lambda { - scope.where("login LIKE ?", "%#{params[:q]}%") - } - - self.description = "GitHub users that have authenticated via the admin OAuth flow." - - field :id, as: :id - - field :is_admin, as: :boolean, readonly: true - field :login, as: :text, readonly: true, - as_html: true, - format_using: -> { link_to value, "https://github.com/#{value}" } - field :avatar_url, as: :external_image, name: "Avatar", readonly: true - field :github_id, as: :text, readonly: true - field :oauth_token, as: :text, visible: ->(resource:) { false } # rubocop:disable Lint/UnusedBlockArgument - - heading "Details" - - field :teams, as: :tags, readonly: true, format_using: -> { value.pluck(:slug) } - - field :info_data, - as: :code, readonly: true, language: :javascript, - format_using: -> { JSON.pretty_generate value } - - field :audits, as: :has_many -end diff --git a/app/avo/resources/api_key.rb b/app/avo/resources/api_key.rb new file mode 100644 index 00000000000..c3c2251565e --- /dev/null +++ b/app/avo/resources/api_key.rb @@ -0,0 +1,46 @@ +class Avo::Resources::ApiKey < Avo::BaseResource + self.title = :name + self.includes = [] + + class ExpiredFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter ExpiredFilter, arguments: { default: { expired: false, unexpired: true } } + end + + def fields + main_panel do + field :id, as: :id, hide_on: :index + + field :name, as: :text, link_to_resource: true + field :hashed_key, as: :text, visible: -> { false } + field :user, as: :belongs_to, visible: -> { false } + field :owner, as: :belongs_to, + polymorphic_as: :owner, + types: [::User, ::OIDC::TrustedPublisher::GitHubAction] + field :last_accessed_at, as: :date_time + field :soft_deleted_at, as: :date_time + field :soft_deleted_rubygem_name, as: :text + field :expires_at, as: :date_time + + field :enabled_scopes, as: :tags + + sidebar do + field :permissions, as: :heading + + field :index_rubygems, as: :boolean + field :push_rubygem, as: :boolean + field :yank_rubygem, as: :boolean + field :add_owner, as: :boolean + field :remove_owner, as: :boolean + field :access_webhooks, as: :boolean + field :show_dashboard, as: :boolean + field :mfa, as: :boolean + end + end + + field :api_key_rubygem_scope, as: :has_one + field :ownership, as: :has_one + field :oidc_id_token, as: :has_one + end +end diff --git a/app/avo/resources/api_key_resource.rb b/app/avo/resources/api_key_resource.rb deleted file mode 100644 index 70832a69514..00000000000 --- a/app/avo/resources/api_key_resource.rb +++ /dev/null @@ -1,39 +0,0 @@ -class ApiKeyResource < Avo::BaseResource - self.title = :name - self.includes = [] - - class ExpiredFilter < ScopeBooleanFilter; end - filter ExpiredFilter, arguments: { default: { expired: false, unexpired: true } } - - field :id, as: :id, hide_on: :index - - field :name, as: :text, link_to_resource: true - field :hashed_key, as: :text, visible: ->(_) { false } - field :user, as: :belongs_to, visible: ->(_) { false } - field :owner, as: :belongs_to, - polymorphic_as: :owner, - types: [::User, ::OIDC::TrustedPublisher::GitHubAction] - field :last_accessed_at, as: :date_time - field :soft_deleted_at, as: :date_time - field :soft_deleted_rubygem_name, as: :text - field :expires_at, as: :date_time - - field :enabled_scopes, as: :tags - - sidebar do - heading "Permissions" - - field :index_rubygems, as: :boolean - field :push_rubygem, as: :boolean - field :yank_rubygem, as: :boolean - field :add_owner, as: :boolean - field :remove_owner, as: :boolean - field :access_webhooks, as: :boolean - field :show_dashboard, as: :boolean - field :mfa, as: :boolean - end - - field :api_key_rubygem_scope, as: :has_one - field :ownership, as: :has_one - field :oidc_id_token, as: :has_one -end diff --git a/app/avo/resources/api_key_rubygem_scope.rb b/app/avo/resources/api_key_rubygem_scope.rb new file mode 100644 index 00000000000..e8105285828 --- /dev/null +++ b/app/avo/resources/api_key_rubygem_scope.rb @@ -0,0 +1,11 @@ +class Avo::Resources::ApiKeyRubygemScope < Avo::BaseResource + self.title = :cache_key + self.includes = [] + + def fields + field :id, as: :id + + field :api_key, as: :belongs_to + field :ownership, as: :belongs_to + end +end diff --git a/app/avo/resources/api_key_rubygem_scope_resource.rb b/app/avo/resources/api_key_rubygem_scope_resource.rb deleted file mode 100644 index 9560edba16c..00000000000 --- a/app/avo/resources/api_key_rubygem_scope_resource.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ApiKeyRubygemScopeResource < Avo::BaseResource - self.title = :cache_key - self.includes = [] - - field :id, as: :id - - field :api_key, as: :belongs_to - field :ownership, as: :belongs_to -end diff --git a/app/avo/resources/audit.rb b/app/avo/resources/audit.rb new file mode 100644 index 00000000000..f674b6b7785 --- /dev/null +++ b/app/avo/resources/audit.rb @@ -0,0 +1,40 @@ +class Avo::Resources::Audit < Avo::BaseResource + self.title = :id + self.includes = %i[ + admin_github_user + auditable + ] + + def fields + field :action, as: :text + + panel do + sidebar do + field :admin_github_user, as: :belongs_to + field :created_at, as: :date_time + field :comment, as: :text + + field :auditable, as: :belongs_to, + polymorphic_as: :auditable, + types: [::User, ::WebHook], + name: "Edited Record" + + field :action_details, as: :heading + + field :audited_changes_arguments, as: :json_viewer, only_on: :show do |_model| + record.audited_changes["arguments"] + end + field :audited_changes_fields, as: :json_viewer, only_on: :show do |_model| + record.audited_changes["fields"] + end + field :audited_changes_models, as: :text, as_html: true, only_on: :show do + record.audited_changes["models"] + end + + field :id, as: :id + end + end + + field :audited_changes, as: :audited_changes, except_on: :index + end +end diff --git a/app/avo/resources/audit_resource.rb b/app/avo/resources/audit_resource.rb deleted file mode 100644 index 1fc1af10f79..00000000000 --- a/app/avo/resources/audit_resource.rb +++ /dev/null @@ -1,36 +0,0 @@ -class AuditResource < Avo::BaseResource - self.title = :id - self.includes = %i[ - admin_github_user - auditable - ] - - field :action, as: :text - - sidebar do - field :admin_github_user, as: :belongs_to - field :created_at, as: :date_time - field :comment, as: :text - - field :auditable, as: :belongs_to, - polymorphic_as: :auditable, - types: [::User, ::WebHook], - name: "Edited Record" - - heading "Action Details" - - field :audited_changes_arguments, as: :json_viewer, only_on: :show do |model| - model.audited_changes["arguments"] - end - field :audited_changes_fields, as: :json_viewer, only_on: :show do |model| - model.audited_changes["fields"] - end - field :audited_changes_models, as: :text, as_html: true, only_on: :show do - model.audited_changes["models"] - end - - field :id, as: :id - end - - field :audited_changes, as: :audited_changes, except_on: :index -end diff --git a/app/avo/resources/concerns/avo_auditable_resource.rb b/app/avo/resources/concerns/avo_auditable_resource.rb index 5eb219fb67b..2c4ae137983 100644 --- a/app/avo/resources/concerns/avo_auditable_resource.rb +++ b/app/avo/resources/concerns/avo_auditable_resource.rb @@ -1,20 +1,24 @@ -module Concerns::AvoAuditableResource +module Avo::Resources::Concerns::AvoAuditableResource extend ActiveSupport::Concern class_methods do - def inherited(base) - super - base.items_holder = Avo::ItemsHolder.new - base.items_holder.instance_variable_get(:@items).replace items_holder.instance_variable_get(:@items).deep_dup - base.items_holder.invalid_fields.replace items_holder.invalid_fields.deep_dup + if false + def inherited(base) + super + base.items_holder = Avo::Resources::Items::Holder.new + base.items_holder.instance_variable_get(:@items).replace items_holder.instance_variable_get(:@items).deep_dup + base.items_holder.invalid_fields.replace items_holder.invalid_fields.deep_dup + end end end included do - panel "Auditable" do - field :comment, as: :textarea, required: true, - help: "A comment explaining why this action was taken.
Will be saved in the audit log.
Must be more than 10 characters.", - only_on: %i[new edit] + if false + panel "Auditable" do + field :comment, as: :textarea, required: true, + help: "A comment explaining why this action was taken.
Will be saved in the audit log.
Must be more than 10 characters.", + only_on: %i[new edit] + end end end end diff --git a/app/avo/resources/deletion.rb b/app/avo/resources/deletion.rb new file mode 100644 index 00000000000..a52385d8afa --- /dev/null +++ b/app/avo/resources/deletion.rb @@ -0,0 +1,15 @@ +class Avo::Resources::Deletion < Avo::BaseResource + self.title = :id + self.includes = [:version] + + def fields + field :id, as: :id + + field :created_at, as: :date_time, sortable: true, title: "Deleted At" + field :rubygem, as: :text + field :number, as: :text + field :platform, as: :text + field :user, as: :belongs_to + field :version, as: :belongs_to + end +end diff --git a/app/avo/resources/deletion_resource.rb b/app/avo/resources/deletion_resource.rb deleted file mode 100644 index fdf0cca5387..00000000000 --- a/app/avo/resources/deletion_resource.rb +++ /dev/null @@ -1,17 +0,0 @@ -class DeletionResource < Avo::BaseResource - self.title = :id - self.includes = [:version] - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - field :id, as: :id - # Fields generated from the model - field :created_at, as: :date_time, sortable: true, title: "Deleted At" - field :rubygem, as: :text - field :number, as: :text - field :platform, as: :text - field :user, as: :belongs_to - field :version, as: :belongs_to - # add fields here -end diff --git a/app/avo/resources/dependency.rb b/app/avo/resources/dependency.rb new file mode 100644 index 00000000000..1e7d213ed68 --- /dev/null +++ b/app/avo/resources/dependency.rb @@ -0,0 +1,18 @@ +class Avo::Resources::Dependency < Avo::BaseResource + self.title = :id + self.includes = [] + + def fields + field :id, as: :id, link_to_resource: true + + field :version, as: :belongs_to + field :rubygem, as: :belongs_to + field :requirements, as: :text + field :unresolved_name, as: :text + + field :scope, as: :badge, + options: { + warning: "development" + } + end +end diff --git a/app/avo/resources/dependency_resource.rb b/app/avo/resources/dependency_resource.rb deleted file mode 100644 index a3751556d8f..00000000000 --- a/app/avo/resources/dependency_resource.rb +++ /dev/null @@ -1,19 +0,0 @@ -class DependencyResource < Avo::BaseResource - self.title = :id - self.includes = [] - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - field :id, as: :id, link_to_resource: true - - field :version, as: :belongs_to - field :rubygem, as: :belongs_to - field :requirements, as: :text - field :unresolved_name, as: :text - - field :scope, as: :badge, - options: { - warning: "development" - } -end diff --git a/app/avo/resources/gem_download.rb b/app/avo/resources/gem_download.rb new file mode 100644 index 00000000000..40c23591359 --- /dev/null +++ b/app/avo/resources/gem_download.rb @@ -0,0 +1,32 @@ +class Avo::Resources::GemDownload < Avo::BaseResource + self.title = :inspect + self.includes = %i[rubygem version] + + self.index_query = lambda { + query.order(count: :desc) + } + + class SpecificityFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter SpecificityFilter, arguments: { default: { for_versions: true, for_rubygems: true, total: true } } + end + + def fields + field :title, as: :text, link_to_resource: true do |_model, _resource, _view| + if record.version + "#{record.version.full_name} (#{record.count.to_fs(:delimited)})" + elsif record.rubygem + "#{record.rubygem} (#{record.count.to_fs(:delimited)})" + else + "All Gems (#{record.count.to_fs(:delimited)})" + end + end + + field :rubygem, as: :belongs_to + field :version, as: :belongs_to + field :count, as: :number, sortable: true, index_text_align: :right, format_using: -> { value.to_fs(:delimited) }, default: 0 + + field :id, as: :id, hide_on: :index + end +end diff --git a/app/avo/resources/gem_download_resource.rb b/app/avo/resources/gem_download_resource.rb deleted file mode 100644 index 4cc08993f07..00000000000 --- a/app/avo/resources/gem_download_resource.rb +++ /dev/null @@ -1,27 +0,0 @@ -class GemDownloadResource < Avo::BaseResource - self.title = :inspect - self.includes = %i[rubygem version] - - self.resolve_query_scope = lambda { |model_class:| - model_class.order(count: :desc) - } - - class SpecificityFilter < ScopeBooleanFilter; end - filter SpecificityFilter, arguments: { default: { for_versions: true, for_rubygems: true, total: true } } - - field :title, as: :text, link_to_resource: true do |model, _resource, _view| - if model.version - "#{model.version.full_name} (#{model.count.to_fs(:delimited)})" - elsif model.rubygem - "#{model.rubygem} (#{model.count.to_fs(:delimited)})" - else - "All Gems (#{model.count.to_fs(:delimited)})" - end - end - - field :rubygem, as: :belongs_to - field :version, as: :belongs_to - field :count, as: :number, sortable: true, index_text_align: :right, format_using: -> { value.to_fs(:delimited) }, default: 0 - - field :id, as: :id, hide_on: :index -end diff --git a/app/avo/resources/gem_name_reservation.rb b/app/avo/resources/gem_name_reservation.rb new file mode 100644 index 00000000000..74ff7d3c43d --- /dev/null +++ b/app/avo/resources/gem_name_reservation.rb @@ -0,0 +1,14 @@ +class Avo::Resources::GemNameReservation < Avo::BaseResource + self.title = :name + self.includes = [] + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("name LIKE ?", "%#{params[:q]}%") + } + end + + def fields + field :id, as: :id + field :name, as: :text + end +end diff --git a/app/avo/resources/gem_name_reservation_resource.rb b/app/avo/resources/gem_name_reservation_resource.rb deleted file mode 100644 index 0b44fa49e59..00000000000 --- a/app/avo/resources/gem_name_reservation_resource.rb +++ /dev/null @@ -1,10 +0,0 @@ -class GemNameReservationResource < Avo::BaseResource - self.title = :name - self.includes = [] - self.search_query = lambda { - scope.where("name LIKE ?", "%#{params[:q]}%") - } - - field :id, as: :id - field :name, as: :text -end diff --git a/app/avo/resources/gem_typo_exception.rb b/app/avo/resources/gem_typo_exception.rb new file mode 100644 index 00000000000..7015f359dc6 --- /dev/null +++ b/app/avo/resources/gem_typo_exception.rb @@ -0,0 +1,19 @@ +class Avo::Resources::GemTypoException < Avo::BaseResource + self.title = :name + self.includes = [] + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("name ILIKE ?", "%#{params[:q]}%") + } + end + + def fields + field :id, as: :id, hide_on: :index + + field :name, as: :text, link_to_resource: true + field :info, as: :textarea + + field :created_at, as: :date_time, sortable: true, readonly: true, only_on: %i[index show] + field :updated_at, as: :date_time, sortable: true, readonly: true, only_on: %i[index show] + end +end diff --git a/app/avo/resources/gem_typo_exception_resource.rb b/app/avo/resources/gem_typo_exception_resource.rb deleted file mode 100644 index 8512e03d2f3..00000000000 --- a/app/avo/resources/gem_typo_exception_resource.rb +++ /dev/null @@ -1,15 +0,0 @@ -class GemTypoExceptionResource < Avo::BaseResource - self.title = :name - self.includes = [] - self.search_query = lambda { - scope.where("name ILIKE ?", "%#{params[:q]}%") - } - - field :id, as: :id, hide_on: :index - # Fields generated from the model - field :name, as: :text, link_to_resource: true - field :info, as: :textarea - # add fields here - field :created_at, as: :date_time, sortable: true, readonly: true, only_on: %i[index show] - field :updated_at, as: :date_time, sortable: true, readonly: true, only_on: %i[index show] -end diff --git a/app/avo/resources/link_verification.rb b/app/avo/resources/link_verification.rb new file mode 100644 index 00000000000..90bf8b12481 --- /dev/null +++ b/app/avo/resources/link_verification.rb @@ -0,0 +1,17 @@ +class Avo::Resources::LinkVerification < Avo::BaseResource + self.title = :id + self.includes = [] + + def fields + field :id, as: :id + + field :linkable, as: :belongs_to, + polymorphic_as: :linkable, + types: [::Rubygem] + field :uri, as: :text + field :verified?, as: :boolean + field :last_verified_at, as: :date_time + field :last_failure_at, as: :date_time + field :failures_since_last_verification, as: :number + end +end diff --git a/app/avo/resources/link_verification_resource.rb b/app/avo/resources/link_verification_resource.rb deleted file mode 100644 index 19806ea613e..00000000000 --- a/app/avo/resources/link_verification_resource.rb +++ /dev/null @@ -1,19 +0,0 @@ -class LinkVerificationResource < Avo::BaseResource - self.title = :id - self.includes = [] - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - field :id, as: :id - # Fields generated from the model - field :linkable, as: :belongs_to, - polymorphic_as: :linkable, - types: [::Rubygem] - field :uri, as: :text - field :verified?, as: :boolean - field :last_verified_at, as: :date_time - field :last_failure_at, as: :date_time - field :failures_since_last_verification, as: :number - # add fields here -end diff --git a/app/avo/resources/linkset.rb b/app/avo/resources/linkset.rb new file mode 100644 index 00000000000..7498288e8f9 --- /dev/null +++ b/app/avo/resources/linkset.rb @@ -0,0 +1,14 @@ +class Avo::Resources::Linkset < Avo::BaseResource + self.title = :id + self.includes = [:rubygem] + self.visible_on_sidebar = false + + def fields + field :id, as: :id, link_to_resource: true + field :rubygem, as: :belongs_to + + Linkset::LINKS.each do |link| + field link, as: :text, format_using: -> { link_to value, value if value.present? } + end + end +end diff --git a/app/avo/resources/linkset_resource.rb b/app/avo/resources/linkset_resource.rb deleted file mode 100644 index ac5966a45bf..00000000000 --- a/app/avo/resources/linkset_resource.rb +++ /dev/null @@ -1,12 +0,0 @@ -class LinksetResource < Avo::BaseResource - self.title = :id - self.includes = [:rubygem] - self.visible_on_sidebar = false - - field :id, as: :id, link_to_resource: true - field :rubygem, as: :belongs_to - - Linkset::LINKS.each do |link| - field link, as: :text, format_using: -> { link_to value, value if value.present? } - end -end diff --git a/app/avo/resources/log_ticket.rb b/app/avo/resources/log_ticket.rb new file mode 100644 index 00000000000..893f8382a2b --- /dev/null +++ b/app/avo/resources/log_ticket.rb @@ -0,0 +1,22 @@ +class Avo::Resources::LogTicket < Avo::BaseResource + self.title = :id + self.includes = [] + + class BackendFilter < Avo::Filters::ScopeBooleanFilter; end + class StatusFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter BackendFilter, arguments: { default: LogTicket.backends.transform_values { true } } + filter StatusFilter, arguments: { default: LogTicket.statuses.transform_values { true } } + end + + def fields + field :id, as: :id, link_to_resource: true + + field :key, as: :text + field :directory, as: :text + field :backend, as: :select, enum: LogTicket.backends + field :status, as: :select, enum: LogTicket.statuses + field :processed_count, as: :number, sortable: true + end +end diff --git a/app/avo/resources/log_ticket_resource.rb b/app/avo/resources/log_ticket_resource.rb deleted file mode 100644 index 1a6c88419e2..00000000000 --- a/app/avo/resources/log_ticket_resource.rb +++ /dev/null @@ -1,18 +0,0 @@ -class LogTicketResource < Avo::BaseResource - self.title = :id - self.includes = [] - - class BackendFilter < ScopeBooleanFilter; end - filter BackendFilter, arguments: { default: LogTicket.backends.transform_values { true } } - - class StatusFilter < ScopeBooleanFilter; end - filter StatusFilter, arguments: { default: LogTicket.statuses.transform_values { true } } - - field :id, as: :id, link_to_resource: true - - field :key, as: :text - field :directory, as: :text - field :backend, as: :select, enum: LogTicket.backends - field :status, as: :select, enum: LogTicket.statuses - field :processed_count, as: :number, sortable: true -end diff --git a/app/avo/resources/maintenance_tasks_run.rb b/app/avo/resources/maintenance_tasks_run.rb new file mode 100644 index 00000000000..623519b2de5 --- /dev/null +++ b/app/avo/resources/maintenance_tasks_run.rb @@ -0,0 +1,30 @@ +class Avo::Resources::MaintenanceTasksRun < Avo::BaseResource + self.title = :id + self.includes = [] + self.model_class = ::MaintenanceTasks::Run + + class StatusFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter StatusFilter, arguments: { default: MaintenanceTasks::Run.statuses.transform_values { true } } + end + + def fields + field :id, as: :id + + field :task_name, as: :text + field :started_at, as: :date_time, sortable: true + field :ended_at, as: :date_time, sortable: true + field :time_running, as: :number, sortable: true + field :tick_count, as: :number + field :tick_total, as: :number + field :job_id, as: :text + field :cursor, as: :number + field :status, as: :select, enum: MaintenanceTasks::Run.statuses + field :error_class, as: :text + field :error_message, as: :text + field :backtrace, as: :textarea + field :arguments, as: :textarea + field :lock_version, as: :number + end +end diff --git a/app/avo/resources/maintenance_tasks_run_resource.rb b/app/avo/resources/maintenance_tasks_run_resource.rb deleted file mode 100644 index 0f553fdb3a5..00000000000 --- a/app/avo/resources/maintenance_tasks_run_resource.rb +++ /dev/null @@ -1,29 +0,0 @@ -class MaintenanceTasksRunResource < Avo::BaseResource - self.title = :id - self.includes = [] - self.model_class = ::MaintenanceTasks::Run - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - class StatusFilter < ScopeBooleanFilter; end - filter StatusFilter, arguments: { default: MaintenanceTasks::Run.statuses.transform_values { true } } - - field :id, as: :id - # Fields generated from the model - field :task_name, as: :text - field :started_at, as: :date_time, sortable: true - field :ended_at, as: :date_time, sortable: true - field :time_running, as: :number, sortable: true - field :tick_count, as: :number - field :tick_total, as: :number - field :job_id, as: :text - field :cursor, as: :number - field :status, as: :select, enum: MaintenanceTasks::Run.statuses - field :error_class, as: :text - field :error_message, as: :text - field :backtrace, as: :textarea - field :arguments, as: :textarea - field :lock_version, as: :number - # add fields here -end diff --git a/app/avo/resources/oidc_api_key_role.rb b/app/avo/resources/oidc_api_key_role.rb new file mode 100644 index 00000000000..8dc81b51b6a --- /dev/null +++ b/app/avo/resources/oidc_api_key_role.rb @@ -0,0 +1,34 @@ +class Avo::Resources::OIDCApiKeyRole < Avo::BaseResource + self.title = :token + self.includes = [] + self.model_class = ::OIDC::ApiKeyRole + + def fields + field :token, as: :text, link_to_resource: true, readonly: true + field :id, as: :id, link_to_resource: true, hide_on: :index + # Fields generated from the model + field :name, as: :text + field :provider, as: :belongs_to + field :user, as: :belongs_to, searchable: true + field :api_key_permissions, as: :nested do + field :valid_for, as: :text, format_using: -> { value&.iso8601 } + field :scopes, as: :tags, suggestions: ApiKey::API_SCOPES.map { { label: _1, value: _1 } }, enforce_suggestions: true + field :gems, as: :tags, suggestions: -> { Rubygem.limit(10).pluck(:name).map { { value: _1, label: _1 } } } + end + field :access_policy, as: :nested do + field :statements, as: :array_of, field: :nested do + field :effect, as: :select, options: { "Allow" => "allow" }, default: "Allow" + field :principal, as: :nested, field_options: { stacked: false } do + field :oidc, as: :text + end + field :conditions, as: :array_of, field: :nested, field_options: { stacked: false } do + field :operator, as: :select, options: OIDC::AccessPolicy::Statement::Condition::OPERATORS.index_by(&:titleize) + field :claim, as: :text + field :value, as: :text + end + end + end + + field :id_tokens, as: :has_many + end +end diff --git a/app/avo/resources/oidc_api_key_role_resource.rb b/app/avo/resources/oidc_api_key_role_resource.rb deleted file mode 100644 index 3f59087e912..00000000000 --- a/app/avo/resources/oidc_api_key_role_resource.rb +++ /dev/null @@ -1,36 +0,0 @@ -class OIDCApiKeyRoleResource < Avo::BaseResource - self.title = :token - self.includes = [] - self.model_class = ::OIDC::ApiKeyRole - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - field :token, as: :text, link_to_resource: true, readonly: true - field :id, as: :id, link_to_resource: true, hide_on: :index - # Fields generated from the model - field :name, as: :text - field :provider, as: :belongs_to - field :user, as: :belongs_to, searchable: true - field :api_key_permissions, as: :nested do - field :valid_for, as: :text, format_using: -> { value&.iso8601 } - field :scopes, as: :tags, suggestions: ApiKey::API_SCOPES.map { { label: _1, value: _1 } }, enforce_suggestions: true - field :gems, as: :tags, suggestions: -> { Rubygem.limit(10).pluck(:name).map { { value: _1, label: _1 } } } - end - field :access_policy, as: :nested do - field :statements, as: :array_of, field: :nested do - field :effect, as: :select, options: { "Allow" => "allow" }, default: "Allow" - field :principal, as: :nested, field_options: { stacked: false } do - field :oidc, as: :text - end - field :conditions, as: :array_of, field: :nested, field_options: { stacked: false } do - field :operator, as: :select, options: OIDC::AccessPolicy::Statement::Condition::OPERATORS.index_by(&:titleize) - field :claim, as: :text - field :value, as: :text - end - end - end - - field :id_tokens, as: :has_many - # add fields here -end diff --git a/app/avo/resources/oidc_id_token.rb b/app/avo/resources/oidc_id_token.rb new file mode 100644 index 00000000000..48ae92fe2c0 --- /dev/null +++ b/app/avo/resources/oidc_id_token.rb @@ -0,0 +1,21 @@ +class Avo::Resources::OIDCIdToken < Avo::BaseResource + self.title = :id + self.includes = [] + self.model_class = ::OIDC::IdToken + + def fields + field :id, as: :id + # Fields generated from the model + field :api_key_role, as: :belongs_to + field :provider, as: :has_one + field :api_key, as: :has_one + + field :jwt, as: :heading + field :claims, as: :key_value, stacked: true do + record.jwt.fetch("claims") + end + field :header, as: :key_value, stacked: true do + record.jwt.fetch("header") + end + end +end diff --git a/app/avo/resources/oidc_id_token_resource.rb b/app/avo/resources/oidc_id_token_resource.rb deleted file mode 100644 index bda90ed7025..00000000000 --- a/app/avo/resources/oidc_id_token_resource.rb +++ /dev/null @@ -1,23 +0,0 @@ -class OIDCIdTokenResource < Avo::BaseResource - self.title = :id - self.includes = [] - self.model_class = ::OIDC::IdToken - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - field :id, as: :id - # Fields generated from the model - field :api_key_role, as: :belongs_to - field :provider, as: :has_one - field :api_key, as: :has_one - - heading "JWT" - field :claims, as: :key_value, stacked: true do - model.jwt.fetch("claims") - end - field :header, as: :key_value, stacked: true do - model.jwt.fetch("header") - end - # add fields here -end diff --git a/app/avo/resources/oidc_pending_trusted_publisher.rb b/app/avo/resources/oidc_pending_trusted_publisher.rb new file mode 100644 index 00000000000..885166c0818 --- /dev/null +++ b/app/avo/resources/oidc_pending_trusted_publisher.rb @@ -0,0 +1,20 @@ +class Avo::Resources::OIDCPendingTrustedPublisher < Avo::BaseResource + self.title = :id + self.includes = [] + self.model_class = ::OIDC::PendingTrustedPublisher + + class ExpiredFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter ExpiredFilter, arguments: { default: { expired: false, unexpired: true } } + end + + def fields + field :id, as: :id + + field :rubygem_name, as: :text + field :user, as: :belongs_to + field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher + field :expires_at, as: :date_time + end +end diff --git a/app/avo/resources/oidc_pending_trusted_publisher_resource.rb b/app/avo/resources/oidc_pending_trusted_publisher_resource.rb deleted file mode 100644 index f546d3a8df1..00000000000 --- a/app/avo/resources/oidc_pending_trusted_publisher_resource.rb +++ /dev/null @@ -1,16 +0,0 @@ -class OIDCPendingTrustedPublisherResource < Avo::BaseResource - self.title = :id - self.includes = [] - self.model_class = ::OIDC::PendingTrustedPublisher - - class ExpiredFilter < ScopeBooleanFilter; end - filter ExpiredFilter, arguments: { default: { expired: false, unexpired: true } } - - field :id, as: :id - # Fields generated from the model - field :rubygem_name, as: :text - field :user, as: :belongs_to - field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher - field :expires_at, as: :date_time - # add fields here -end diff --git a/app/avo/resources/oidc_provider.rb b/app/avo/resources/oidc_provider.rb new file mode 100644 index 00000000000..74cf4d35f10 --- /dev/null +++ b/app/avo/resources/oidc_provider.rb @@ -0,0 +1,23 @@ +class Avo::Resources::OIDCProvider < Avo::BaseResource + self.title = :issuer + self.includes = [] + self.model_class = ::OIDC::Provider + + def actions + action Avo::Actions::RefreshOIDCProvider + end + + def fields + field :issuer, as: :text, link_to_resource: true + field :configuration, as: :nested do + visible_on = %i[edit new] + OIDC::Provider::Configuration.then { (_1.required_attributes + _1.optional_attributes) - fields.map(&:id) }.each do |k| + field k, as: (k.to_s.end_with?("s_supported") ? :tags : :text), visible: ->(_) { visible_on.include?(view) || value.send(k).present? } + end + end + field :jwks, as: :array_of, field: :json_viewer, hide_on: :index + field :api_key_roles, as: :has_many + + field :id, as: :id + end +end diff --git a/app/avo/resources/oidc_provider_resource.rb b/app/avo/resources/oidc_provider_resource.rb deleted file mode 100644 index 8a2fa0fe6d4..00000000000 --- a/app/avo/resources/oidc_provider_resource.rb +++ /dev/null @@ -1,20 +0,0 @@ -class OIDCProviderResource < Avo::BaseResource - self.title = :issuer - self.includes = [] - self.model_class = ::OIDC::Provider - - action RefreshOIDCProvider - - # Fields generated from the model - field :issuer, as: :text, link_to_resource: true - field :configuration, as: :nested do - visible_on = %i[edit new] - OIDC::Provider::Configuration.then { (_1.required_attributes + _1.optional_attributes) - fields.map(&:id) }.each do |k| - field k, as: (k.to_s.end_with?("s_supported") ? :tags : :text), visible: ->(_) { visible_on.include?(view) || value.send(k).present? } - end - end - field :jwks, as: :array_of, field: :json_viewer, hide_on: :index - field :api_key_roles, as: :has_many - # add fields here - field :id, as: :id -end diff --git a/app/avo/resources/oidc_rubygem_trusted_publisher.rb b/app/avo/resources/oidc_rubygem_trusted_publisher.rb new file mode 100644 index 00000000000..e7e9d13f532 --- /dev/null +++ b/app/avo/resources/oidc_rubygem_trusted_publisher.rb @@ -0,0 +1,12 @@ +class Avo::Resources::OIDCRubygemTrustedPublisher < Avo::BaseResource + self.title = :id + self.includes = [:trusted_publisher] + self.model_class = ::OIDC::RubygemTrustedPublisher + + def fields + field :id, as: :id + + field :rubygem, as: :belongs_to + field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher + end +end diff --git a/app/avo/resources/oidc_rubygem_trusted_publisher_resource.rb b/app/avo/resources/oidc_rubygem_trusted_publisher_resource.rb deleted file mode 100644 index 96c63c43096..00000000000 --- a/app/avo/resources/oidc_rubygem_trusted_publisher_resource.rb +++ /dev/null @@ -1,11 +0,0 @@ -class OIDCRubygemTrustedPublisherResource < Avo::BaseResource - self.title = :id - self.includes = [:trusted_publisher] - self.model_class = ::OIDC::RubygemTrustedPublisher - - field :id, as: :id - # Fields generated from the model - field :rubygem, as: :belongs_to - field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher - # add fields here -end diff --git a/app/avo/resources/oidc_trusted_publisher_github_action.rb b/app/avo/resources/oidc_trusted_publisher_github_action.rb new file mode 100644 index 00000000000..0a850ed2e21 --- /dev/null +++ b/app/avo/resources/oidc_trusted_publisher_github_action.rb @@ -0,0 +1,20 @@ +class Avo::Resources::OIDCTrustedPublisherGitHubAction < Avo::BaseResource + self.title = :name + self.includes = [] + self.model_class = ::OIDC::TrustedPublisher::GitHubAction + + def fields + field :id, as: :id + + field :repository_owner, as: :text + field :repository_name, as: :text + field :repository_owner_id, as: :text + field :workflow_filename, as: :text + field :environment, as: :text + + field :rubygem_trusted_publishers, as: :has_many + field :pending_trusted_publishers, as: :has_many + field :rubygems, as: :has_many, through: :rubygem_trusted_publishers + field :api_keys, as: :has_many, inverse_of: :owner + end +end diff --git a/app/avo/resources/oidc_trusted_publisher_github_action_resource.rb b/app/avo/resources/oidc_trusted_publisher_github_action_resource.rb deleted file mode 100644 index 0ea00fd83e4..00000000000 --- a/app/avo/resources/oidc_trusted_publisher_github_action_resource.rb +++ /dev/null @@ -1,19 +0,0 @@ -class OIDCTrustedPublisherGitHubActionResource < Avo::BaseResource - self.title = :name - self.includes = [] - self.model_class = ::OIDC::TrustedPublisher::GitHubAction - - field :id, as: :id - # Fields generated from the model - field :repository_owner, as: :text - field :repository_name, as: :text - field :repository_owner_id, as: :text - field :workflow_filename, as: :text - field :environment, as: :text - # add fields here - # - field :rubygem_trusted_publishers, as: :has_many - field :pending_trusted_publishers, as: :has_many - field :rubygems, as: :has_many, through: :rubygem_trusted_publishers - field :api_keys, as: :has_many, inverse_of: :owner -end diff --git a/app/avo/resources/ownership.rb b/app/avo/resources/ownership.rb new file mode 100644 index 00000000000..3c45bf27da1 --- /dev/null +++ b/app/avo/resources/ownership.rb @@ -0,0 +1,34 @@ +class Avo::Resources::Ownership < Avo::BaseResource + self.title = :cache_key + self.includes = [] + + class ConfirmedFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter ConfirmedFilter, arguments: { default: { confirmed: true, unconfirmed: true } } + end + + def fields + field :id, as: :id, link_to_resource: true + + field :user, as: :belongs_to + field :rubygem, as: :belongs_to + + field :token, as: :heading + + field :token, as: :text, visible: -> { false } + field :token_expires_at, as: :date_time + field :api_key_rubygem_scopes, as: :has_many + + field :notifications, as: :heading + + field :push_notifier, as: :boolean + field :owner_notifier, as: :boolean + field :ownership_request_notifier, as: :boolean + + field :authorization, as: :heading + + field :authorizer, as: :belongs_to + field :confirmed_at, as: :date_time + end +end diff --git a/app/avo/resources/ownership_resource.rb b/app/avo/resources/ownership_resource.rb deleted file mode 100644 index cd51054bbd0..00000000000 --- a/app/avo/resources/ownership_resource.rb +++ /dev/null @@ -1,29 +0,0 @@ -class OwnershipResource < Avo::BaseResource - self.title = :cache_key - self.includes = [] - - class ConfirmedFilter < ScopeBooleanFilter; end - filter ConfirmedFilter, arguments: { default: { confirmed: true, unconfirmed: true } } - - field :id, as: :id, link_to_resource: true - - field :user, as: :belongs_to - field :rubygem, as: :belongs_to - - heading "Token" - - field :token, as: :text, visible: ->(_) { false } - field :token_expires_at, as: :date_time - field :api_key_rubygem_scopes, as: :has_many - - heading "Notifications" - - field :push_notifier, as: :boolean - field :owner_notifier, as: :boolean - field :ownership_request_notifier, as: :boolean - - heading "Authorization" - - field :authorizer, as: :belongs_to - field :confirmed_at, as: :date_time -end diff --git a/app/avo/resources/rubygem.rb b/app/avo/resources/rubygem.rb new file mode 100644 index 00000000000..5c470ef31a4 --- /dev/null +++ b/app/avo/resources/rubygem.rb @@ -0,0 +1,54 @@ +class Avo::Resources::Rubygem < Avo::BaseResource + self.title = :name + self.includes = [] + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("name LIKE ?", "%#{params[:q]}%") + } + end + + def actions + action Avo::Actions::ReleaseReservedNamespace + action Avo::Actions::AddOwner + action Avo::Actions::YankRubygem + action Avo::Actions::UploadInfoFile + action Avo::Actions::UploadNamesFile + action Avo::Actions::UploadVersionsFile + end + + class IndexedFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter IndexedFilter, arguments: { default: { with_versions: true, without_versions: true } } + end + + def fields + field :name, as: :text, link_to_resource: true + field :indexed, as: :boolean + field :slug, as: :text, hide_on: :index + field :id, as: :id, hide_on: :index + field :protected_days, as: :number, hide_on: :index + + tabs style: :pills do + field :versions, as: :has_many + field :latest_version, as: :has_one + + field :ownerships, as: :has_many + field :ownerships_including_unconfirmed, as: :has_many + field :ownership_calls, as: :has_many + field :ownership_requests, as: :has_many + + field :subscriptions, as: :has_many + field :subscribers, as: :has_many, through: :subscriptions + + field :web_hooks, as: :has_many + field :linkset, as: :has_one + field :gem_download, as: :has_one + + field :link_verifications, as: :has_many + field :oidc_rubygem_trusted_publishers, as: :has_many + + field :audits, as: :has_many + end + end +end diff --git a/app/avo/resources/rubygem_resource.rb b/app/avo/resources/rubygem_resource.rb deleted file mode 100644 index e942e207847..00000000000 --- a/app/avo/resources/rubygem_resource.rb +++ /dev/null @@ -1,46 +0,0 @@ -class RubygemResource < Avo::BaseResource - self.title = :name - self.includes = [] - self.search_query = lambda { - scope.where("name LIKE ?", "%#{params[:q]}%") - } - - action ReleaseReservedNamespace - action AddOwner - action YankRubygem - action UploadInfoFile - action UploadNamesFile - action UploadVersionsFile - - class IndexedFilter < ScopeBooleanFilter; end - filter IndexedFilter, arguments: { default: { with_versions: true, without_versions: true } } - - # Fields generated from the model - field :name, as: :text, link_to_resource: true - field :indexed, as: :boolean - field :slug, as: :text, hide_on: :index - field :id, as: :id, hide_on: :index - field :protected_days, as: :number, hide_on: :index - - tabs style: :pills do - field :versions, as: :has_many - field :latest_version, as: :has_one - - field :ownerships, as: :has_many - field :ownerships_including_unconfirmed, as: :has_many - field :ownership_calls, as: :has_many - field :ownership_requests, as: :has_many - - field :subscriptions, as: :has_many - field :subscribers, as: :has_many, through: :subscriptions - - field :web_hooks, as: :has_many - field :linkset, as: :has_one - field :gem_download, as: :has_one - - field :link_verifications, as: :has_many - field :oidc_rubygem_trusted_publishers, as: :has_many - - field :audits, as: :has_many - end -end diff --git a/app/avo/resources/sendgrid_event.rb b/app/avo/resources/sendgrid_event.rb new file mode 100644 index 00000000000..c9d57d8a636 --- /dev/null +++ b/app/avo/resources/sendgrid_event.rb @@ -0,0 +1,27 @@ +class Avo::Resources::SendgridEvent < Avo::BaseResource + self.title = :sendgrid_id + self.includes = [] + # self.search_query = -> do + # query.ransack(id_eq: params[:q], m: "or").result(distinct: false) + # end + + class StatusFilter < Avo::Filters::ScopeBooleanFilter; end + class EventTypeFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter StatusFilter, arguments: { default: SendgridEvent.statuses.transform_values { true } } + filter EventTypeFilter, arguments: { default: SendgridEvent.event_types.transform_values { true } } + filter Avo::Filters::EmailFilter + end + + def fields + field :id, as: :id, hide_on: :index + + field :sendgrid_id, as: :text, link_to_resource: true + field :email, as: :text + field :event_type, as: :text + field :occurred_at, as: :date_time, sortable: true + field :payload, as: :json_viewer + field :status, as: :select, enum: SendgridEvent.statuses + end +end diff --git a/app/avo/resources/sendgrid_event_resource.rb b/app/avo/resources/sendgrid_event_resource.rb deleted file mode 100644 index 9328ed102db..00000000000 --- a/app/avo/resources/sendgrid_event_resource.rb +++ /dev/null @@ -1,25 +0,0 @@ -class SendgridEventResource < Avo::BaseResource - self.title = :sendgrid_id - self.includes = [] - # self.search_query = -> do - # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) - # end - - class StatusFilter < ScopeBooleanFilter; end - filter StatusFilter, arguments: { default: SendgridEvent.statuses.transform_values { true } } - - class EventTypeFilter < ScopeBooleanFilter; end - filter EventTypeFilter, arguments: { default: SendgridEvent.event_types.transform_values { true } } - - filter EmailFilter - - field :id, as: :id, hide_on: :index - # Fields generated from the model - field :sendgrid_id, as: :text, link_to_resource: true - field :email, as: :text - field :event_type, as: :text - field :occurred_at, as: :date_time, sortable: true - field :payload, as: :json_viewer - field :status, as: :select, enum: SendgridEvent.statuses - # add fields here -end diff --git a/app/avo/resources/user.rb b/app/avo/resources/user.rb new file mode 100644 index 00000000000..4c55562a940 --- /dev/null +++ b/app/avo/resources/user.rb @@ -0,0 +1,77 @@ +class Avo::Resources::User < Avo::BaseResource + self.title = :name + self.includes = [] + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("email LIKE ? OR handle LIKE ?", "%#{params[:q]}%", "%#{params[:q]}%") + } + end + + def actions + action Avo::Actions::BlockUser + action Avo::Actions::CreateUser + action Avo::Actions::ChangeUserEmail + action Avo::Actions::ResetApiKey + action Avo::Actions::ResetUser2fa + action Avo::Actions::YankRubygemsForUser + action Avo::Actions::YankUser + end + + def fields + field :id, as: :id + + field :email, as: :text + field :gravatar, + as: :gravatar, + rounded: true, + size: 48 do |_, _, _| + record.email + end + + field :email_confirmed, as: :boolean + + field :email_reset, as: :boolean + field :handle, as: :text + field :public_email, as: :boolean + field :twitter_username, as: :text, as_html: true, format_using: -> { link_to value, "https://twitter.com/#{value}", target: :_blank, rel: :noopener if value.present? } + field :unconfirmed_email, as: :text + + field :mail_fails, as: :number + field :blocked_email, as: :text + + tabs style: :pills do + tab "Auth" do + field :encrypted_password, as: :password, visible: -> { false } + field :totp_seed, as: :text, visible: -> { false } + field :mfa_seed, as: :text, visible: -> { false } # legacy field + field :mfa_level, as: :select, enum: ::User.mfa_levels + field :mfa_recovery_codes, as: :text, visible: -> { false } + field :mfa_hashed_recovery_codes, as: :text, visible: -> { false } + field :webauthn_id, as: :text + field :remember_token_expires_at, as: :date_time + field :api_key, as: :text, visible: -> { false } + field :confirmation_token, as: :text, visible: -> { false } + field :remember_token, as: :text, visible: -> { false } + field :salt, as: :text, visible: -> { false } + field :token, as: :text, visible: -> { false } + field :token_expires_at, as: :date_time + end + field :ownerships, as: :has_many + field :rubygems, as: :has_many, through: :ownerships + field :subscriptions, as: :has_many + field :subscribed_gems, as: :has_many, through: :subscriptions + field :deletions, as: :has_many + field :web_hooks, as: :has_many + field :unconfirmed_ownerships, as: :has_many + field :api_keys, as: :has_many, name: "API Keys" + field :ownership_calls, as: :has_many + field :ownership_requests, as: :has_many + field :pushed_versions, as: :has_many + field :oidc_api_key_roles, as: :has_many + field :webauthn_credentials, as: :has_many + field :webauthn_verification, as: :has_one + + field :audits, as: :has_many + end + end +end diff --git a/app/avo/resources/user_resource.rb b/app/avo/resources/user_resource.rb deleted file mode 100644 index 71c93636dc0..00000000000 --- a/app/avo/resources/user_resource.rb +++ /dev/null @@ -1,71 +0,0 @@ -class UserResource < Avo::BaseResource - self.title = :name - self.includes = [] - self.search_query = lambda { - scope.where("email LIKE ? OR handle LIKE ?", "%#{params[:q]}%", "%#{params[:q]}%") - } - - action BlockUser - action CreateUser - action ChangeUserEmail - action ResetApiKey - action ResetUser2fa - action YankRubygemsForUser - action YankUser - - field :id, as: :id - # Fields generated from the model - field :email, as: :text - field :gravatar, - as: :gravatar, - rounded: true, - size: 48 do |_, _, _| - model.email - end - - field :email_confirmed, as: :boolean - - field :email_reset, as: :boolean - field :handle, as: :text - field :public_email, as: :boolean - field :twitter_username, as: :text, as_html: true, format_using: -> { link_to value, "https://twitter.com/#{value}", target: :_blank, rel: :noopener if value.present? } - field :unconfirmed_email, as: :text - - field :mail_fails, as: :number - field :blocked_email, as: :text - - tabs style: :pills do - tab "Auth" do - field :encrypted_password, as: :password, visible: ->(_) { false } - field :totp_seed, as: :text, visible: ->(_) { false } - field :mfa_seed, as: :text, visible: ->(_) { false } # legacy field - field :mfa_level, as: :select, enum: ::User.mfa_levels - field :mfa_recovery_codes, as: :text, visible: ->(_) { false } - field :mfa_hashed_recovery_codes, as: :text, visible: ->(_) { false } - field :webauthn_id, as: :text - field :remember_token_expires_at, as: :date_time - field :api_key, as: :text, visible: ->(_) { false } - field :confirmation_token, as: :text, visible: ->(_) { false } - field :remember_token, as: :text, visible: ->(_) { false } - field :salt, as: :text, visible: ->(_) { false } - field :token, as: :text, visible: ->(_) { false } - field :token_expires_at, as: :date_time - end - field :ownerships, as: :has_many - field :rubygems, as: :has_many, through: :ownerships - field :subscriptions, as: :has_many - field :subscribed_gems, as: :has_many, through: :subscriptions - field :deletions, as: :has_many - field :web_hooks, as: :has_many - field :unconfirmed_ownerships, as: :has_many - field :api_keys, as: :has_many, name: "API Keys" - field :ownership_calls, as: :has_many - field :ownership_requests, as: :has_many - field :pushed_versions, as: :has_many - field :oidc_api_key_roles, as: :has_many - field :webauthn_credentials, as: :has_many - field :webauthn_verification, as: :has_one - - field :audits, as: :has_many - end -end diff --git a/app/avo/resources/version.rb b/app/avo/resources/version.rb new file mode 100644 index 00000000000..e3bc36bf860 --- /dev/null +++ b/app/avo/resources/version.rb @@ -0,0 +1,78 @@ +class Avo::Resources::Version < Avo::BaseResource + self.title = :full_name + self.includes = [:rubygem] + if Gem.loaded_specs["avo-pro"] + self.search_query = lambda { + query.where("full_name LIKE ?", "#{params[:q]}%") + } + end + + def actions + action Avo::Actions::RestoreVersion + end + + class IndexedFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter IndexedFilter, arguments: { default: { indexed: true, yanked: true } } + end + + def fields + field :full_name, as: :text, link_to_resource: true + field :id, as: :id, hide_on: :index, as_html: true do |_id, *_args| + link_to record.id, main_app.rubygem_version_url(record.rubygem.slug, record.slug) + end + + field :rubygem, as: :belongs_to + field :slug, as: :text, hide_on: :index + field :number, as: :text + field :platform, as: :text + + field :canonical_number, as: :text + + field :indexed, as: :boolean + field :prerelease, as: :boolean + field :position, as: :number + field :latest, as: :boolean + + field :yanked_at, as: :date_time, sortable: true + + field :pusher, as: :belongs_to, class: "User" + field :pusher_api_key, as: :belongs_to, class: "ApiKey" + + tabs do + tab "Metadata", description: "Metadata that comes from the gemspec" do + panel do + field :summary, as: :textarea + field :description, as: :textarea + field :authors, as: :textarea + field :licenses, as: :textarea + field :cert_chain, as: :textarea + field :built_at, as: :date_time, sortable: true + field :metadata, as: :key_value, stacked: true + end + end + + tab "Runtime information" do + panel do + field :size, as: :number, sortable: true + field :requirements, as: :textarea + field :required_ruby_version, as: :text + field :sha256, as: :text + field :required_rubygems_version, as: :text + end + end + + tab "API" do + panel do + field :info_checksum, as: :text + field :yanked_info_checksum, as: :text + end + end + + field :dependencies, as: :has_many + field :gem_download, as: :has_one, name: "Downloads" + field :deletion, as: :has_one + end + end +end diff --git a/app/avo/resources/version_resource.rb b/app/avo/resources/version_resource.rb deleted file mode 100644 index 4334c6f1c89..00000000000 --- a/app/avo/resources/version_resource.rb +++ /dev/null @@ -1,69 +0,0 @@ -class VersionResource < Avo::BaseResource - self.title = :full_name - self.includes = [:rubygem] - self.search_query = lambda { - scope.where("full_name LIKE ?", "#{params[:q]}%") - } - - action RestoreVersion - - class IndexedFilter < ScopeBooleanFilter; end - filter IndexedFilter, arguments: { default: { indexed: true, yanked: true } } - - field :full_name, as: :text, link_to_resource: true - field :id, as: :id, hide_on: :index, as_html: true do |_id, *_args| - link_to model.id, main_app.rubygem_version_url(model.rubygem.slug, model.slug) - end - - field :rubygem, as: :belongs_to - field :slug, as: :text, hide_on: :index - field :number, as: :text - field :platform, as: :text - - field :canonical_number, as: :text - - field :indexed, as: :boolean - field :prerelease, as: :boolean - field :position, as: :number - field :latest, as: :boolean - - field :yanked_at, as: :date_time, sortable: true - - field :pusher, as: :belongs_to, class: "User" - field :pusher_api_key, as: :belongs_to, class: "ApiKey" - - tabs do - tab "Metadata", description: "Metadata that comes from the gemspec" do - panel do - field :summary, as: :textarea - field :description, as: :textarea - field :authors, as: :textarea - field :licenses, as: :textarea - field :cert_chain, as: :textarea - field :built_at, as: :date_time, sortable: true - field :metadata, as: :key_value, stacked: true - end - end - - tab "Runtime information" do - panel do - field :size, as: :number, sortable: true - field :requirements, as: :textarea - field :required_ruby_version, as: :text - field :sha256, as: :text - field :required_rubygems_version, as: :text - end - end - - tab "API" do - panel do - field :info_checksum, as: :text - field :yanked_info_checksum, as: :text - end - end - - field :dependencies, as: :has_many - field :gem_download, as: :has_one, name: "Downloads" - field :deletion, as: :has_one - end -end diff --git a/app/avo/resources/web_hook.rb b/app/avo/resources/web_hook.rb new file mode 100644 index 00000000000..98ef03cdbef --- /dev/null +++ b/app/avo/resources/web_hook.rb @@ -0,0 +1,43 @@ +class Avo::Resources::WebHook < Avo::BaseResource + self.title = :id + self.includes = %i[user rubygem] + + def actions + action Avo::Actions::DeleteWebhook + end + + class EnabledFilter < Avo::Filters::ScopeBooleanFilter; end + class GlobalFilter < Avo::Filters::ScopeBooleanFilter; end + + def filters + filter EnabledFilter, arguments: { default: { enabled: true, disabled: false } } + filter GlobalFilter, arguments: { default: { global: true, specific: true } } + end + + def fields + field :id, as: :id, link_to_resource: true + + field :url, as: :text + field :enabled?, as: :boolean + field :failure_count, as: :number, sortable: true, index_text_align: :right + field :user, as: :belongs_to + field :rubygem, as: :belongs_to + field :global?, as: :boolean + + field :hook_relay_stream, as: :text do + stream_name = "webhook_id-#{record.id}" + link_to stream_name, "https://app.hookrelay.dev/hooks/#{ENV['HOOK_RELAY_STREAM_ID']}?started_at=P1W&stream=#{stream_name}" + end + + field :disabled_reason, as: :text + field :disabled_at, as: :date_time, sortable: true + field :last_success, as: :date_time, sortable: true + field :last_failure, as: :date_time, sortable: true + field :successes_since_last_failure, as: :number, sortable: true + field :failures_since_last_success, as: :number, sortable: true + + tabs style: :pills do + field :audits, as: :has_many + end + end +end diff --git a/app/avo/resources/web_hook_resource.rb b/app/avo/resources/web_hook_resource.rb deleted file mode 100644 index ee2c22d59f9..00000000000 --- a/app/avo/resources/web_hook_resource.rb +++ /dev/null @@ -1,35 +0,0 @@ -class WebHookResource < Avo::BaseResource - self.title = :id - self.includes = %i[user rubygem] - - action DeleteWebhook - class EnabledFilter < ScopeBooleanFilter; end - filter EnabledFilter, arguments: { default: { enabled: true, disabled: false } } - class GlobalFilter < ScopeBooleanFilter; end - filter GlobalFilter, arguments: { default: { global: true, specific: true } } - - field :id, as: :id, link_to_resource: true - - field :url, as: :text - field :enabled?, as: :boolean - field :failure_count, as: :number, sortable: true, index_text_align: :right - field :user, as: :belongs_to - field :rubygem, as: :belongs_to - field :global?, as: :boolean - - field :hook_relay_stream, as: :text do - stream_name = "webhook_id-#{model.id}" - link_to stream_name, "https://app.hookrelay.dev/hooks/#{ENV['HOOK_RELAY_STREAM_ID']}?started_at=P1W&stream=#{stream_name}" - end - - field :disabled_reason, as: :text - field :disabled_at, as: :date_time, sortable: true - field :last_success, as: :date_time, sortable: true - field :last_failure, as: :date_time, sortable: true - field :successes_since_last_failure, as: :number, sortable: true - field :failures_since_last_success, as: :number, sortable: true - - tabs style: :pills do - field :audits, as: :has_many - end -end diff --git a/app/avo/resources/webauthn_credential.rb b/app/avo/resources/webauthn_credential.rb new file mode 100644 index 00000000000..def6a1bcb20 --- /dev/null +++ b/app/avo/resources/webauthn_credential.rb @@ -0,0 +1,14 @@ +class Avo::Resources::WebauthnCredential < Avo::BaseResource + self.title = :id + self.includes = [] + + def fields + field :id, as: :id + + field :external_id, as: :text + field :public_key, as: :text + field :nickname, as: :text + field :sign_count, as: :number + field :user, as: :belongs_to + end +end diff --git a/app/avo/resources/webauthn_credential_resource.rb b/app/avo/resources/webauthn_credential_resource.rb deleted file mode 100644 index b6711b63eab..00000000000 --- a/app/avo/resources/webauthn_credential_resource.rb +++ /dev/null @@ -1,13 +0,0 @@ -class WebauthnCredentialResource < Avo::BaseResource - self.title = :id - self.includes = [] - - field :id, as: :id - # Fields generated from the model - field :external_id, as: :text - field :public_key, as: :text - field :nickname, as: :text - field :sign_count, as: :number - field :user, as: :belongs_to - # add fields here -end diff --git a/app/avo/resources/webauthn_verification.rb b/app/avo/resources/webauthn_verification.rb new file mode 100644 index 00000000000..48e509a1b76 --- /dev/null +++ b/app/avo/resources/webauthn_verification.rb @@ -0,0 +1,14 @@ +class Avo::Resources::WebauthnVerification < Avo::BaseResource + self.title = :id + self.includes = [] + + def fields + field :id, as: :id + + field :path_token, as: :text + field :path_token_expires_at, as: :date_time + field :otp, as: :text + field :otp_expires_at, as: :date_time + field :user, as: :belongs_to + end +end diff --git a/app/avo/resources/webauthn_verification_resource.rb b/app/avo/resources/webauthn_verification_resource.rb deleted file mode 100644 index 5834540ac89..00000000000 --- a/app/avo/resources/webauthn_verification_resource.rb +++ /dev/null @@ -1,13 +0,0 @@ -class WebauthnVerificationResource < Avo::BaseResource - self.title = :id - self.includes = [] - - field :id, as: :id - # Fields generated from the model - field :path_token, as: :text - field :path_token_expires_at, as: :date_time - field :otp, as: :text - field :otp_expires_at, as: :date_time - field :user, as: :belongs_to - # add fields here -end diff --git a/config/initializers/avo.rb b/config/initializers/avo.rb index 552309a8dca..fd05c1e42cc 100644 --- a/config/initializers/avo.rb +++ b/config/initializers/avo.rb @@ -118,7 +118,7 @@ Rails.configuration.to_prepare do Avo::ApplicationController.include GitHubOAuthable Avo::BaseController.prepend AvoAuditable - Avo::BaseResource.include Concerns::AvoAuditableResource + Avo::BaseResource.include Avo::Resources::Concerns::AvoAuditableResource Avo::ApplicationController.content_security_policy do |policy| policy.style_src :self, "https://fonts.googleapis.com", :unsafe_inline