Rails: выполнять тесты с пользователем только для чтения Postgres базы данных - PullRequest
0 голосов
/ 11 марта 2020

Допустим, у нас есть два приложения Rails (5/6):

  • library_management_system (Rails 5)
  • library_stats (Rails 6)

library_management_system имеет базу данных Postgres и, скажем, у нас есть:

  • суперпользователь PG (супермен)
  • пользователь PG только для чтения (кларк) (даже права на создание имеют был отозван)

library_stats имеет доступ только для чтения к базе данных library_management_system Postgres. Например, у library_stats database.yml есть

development:
  username: clark

Все в порядке в разработке. Так как нам никогда не нужно пересоздавать базу данных разработчика из library_stats.

Теперь я хотел бы проверить, что происходит с таким пользователем, доступным только для чтения, в моих тестах.

Я попытался просто использовать пользователь только для чтения:

test:
  username: clark

К сожалению, это не оставляет рельсам достаточных прав для настройки БД (как вы можете видеть в конце поста). В идеале я хотел бы, чтобы настройка теста выполнялась с superman, выполняющим взаимодействие с PG, а затем выполняла бы тесты с clark, выполняющим взаимодействие.

Каков (в идеале не слишком сложный) способ, которым я могу это сделать?

В общем, любое решение, которое позволило бы правильно проверить, что происходит с пользователем PG только для чтения. , хорошо.

Трассировка:

29: from railties-6.0.2.1/lib/rails/test_help.rb:17:in `<main>'
  28: from activerecord-6.0.2.1/lib/active_record/migration.rb:615:in `maintain_test_schema!'
  27: from activerecord-6.0.2.1/lib/active_record/migration.rb:620:in `method_missing'
  26: from activerecord-6.0.2.1/lib/active_record/migration.rb:867:in `suppress_messages'
  25: from activerecord-6.0.2.1/lib/active_record/migration.rb:615:in `block in maintain_test_schema!'
  24: from activerecord-6.0.2.1/lib/active_record/migration.rb:594:in `load_schema_if_pending!'
  23: from activerecord-6.0.2.1/lib/active_record/migration.rb:594:in `all?'
  22: from activerecord-6.0.2.1/lib/active_record/migration.rb:595:in `block in load_schema_if_pending!'
  21: from activerecord-6.0.2.1/lib/active_record/tasks/database_tasks.rb:348:in `schema_up_to_date?'
  20: from activerecord-6.0.2.1/lib/active_record/internal_metadata.rb:28:in `[]'
  19: from activerecord-6.0.2.1/lib/active_record/relation/calculations.rb:193:in `pluck'
  18: from activerecord-6.0.2.1/lib/active_record/relation.rb:828:in `skip_query_cache_if_necessary'
  17: from activerecord-6.0.2.1/lib/active_record/relation/calculations.rb:193:in `block in pluck'
  16: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract/query_cache.rb:107:in `select_all'
  15: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:70:in `select_all'
  14: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:487:in `select'
  13: from activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `exec_query'
  12: from activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:651:in `execute_and_clear'
  11: from activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:670:in `exec_no_cache'
  10: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:708:in `log'
   9: from activesupport-6.0.2.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
   8: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:717:in `block in log'
   7: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:717:in `synchronize'
   6: from activerecord-6.0.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:718:in `block (2 levels) in log'
   5: from activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:671:in `block in exec_no_cache'
   4: from activesupport-6.0.2.1/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
   3: from activesupport-6.0.2.1/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
   2: from activesupport-6.0.2.1/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
   1: from activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `block (2 levels) in exec_no_cache'
activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params': ERROR:  permission denied for relation ar_internal_metadata (PG::InsufficientPrivilege)

РЕДАКТИРОВАТЬ: я пошел со следующим решением

class LibraryManagementRecord < ApplicationRecord
  self.abstract_class = true

  if (Rails.env.test?)
    ActiveRecord::Base.establish_connection(:lms_test)
  end
end

и с двумя подключениями:

# database.yml
test:
  username: superman
lms test:
  username: clark

Теперь у нас ожидаемое поведение:

require 'test_helper'

class BookTest < ActiveSupport::TestCase
  test 'cannot create book' do
    error = assert_raises ActiveRecord::StatementInvalid do
      Book.create!
    end

    assert_equal(
      'PG::InsufficientPrivilege: ERROR:  permission denied for relation books',
      error.message.strip
    )
  end
end

Но оказывается, что есть еще одно ограничение: а именно, как вы вставляете, скажем, приборы. Вам, вероятно, придется явно получить соединение с разрешенной для записи ролью, чтобы вставить их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...