aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb
blob: fa6584eae578039f23a39f6e07fd506f4070e1ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
require "cases/helper"

class SchemaThing < ActiveRecord::Base
end

class SchemaAuthorizationTest < ActiveRecord::PostgreSQLTestCase
  self.use_transactional_tests = false

  TABLE_NAME = 'schema_things'
  COLUMNS = [
    'id serial primary key',
    'name character varying(50)'
  ]
  USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2']

  def setup
    @connection = ActiveRecord::Base.connection
    @connection.execute "SET search_path TO '$user',public"
    set_session_auth
    USERS.each do |u|
      @connection.execute "CREATE USER #{u}" rescue nil
      @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" rescue nil
      set_session_auth u
      @connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
      @connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')"
      set_session_auth
    end
  end

  teardown do
    set_session_auth
    @connection.execute "RESET search_path"
    USERS.each do |u|
      @connection.execute "DROP SCHEMA #{u} CASCADE"
      @connection.execute "DROP USER #{u}"
    end
  end

  def test_schema_invisible
    assert_raise(ActiveRecord::StatementInvalid) do
      set_session_auth
      @connection.execute "SELECT * FROM #{TABLE_NAME}"
    end
  end

  def test_session_auth=
    assert_raise(ActiveRecord::StatementInvalid) do
      @connection.session_auth = 'DEFAULT'
      @connection.execute "SELECT * FROM #{TABLE_NAME}"
    end
  end

  def test_setting_auth_clears_stmt_cache
    assert_nothing_raised do
      set_session_auth
      USERS.each do |u|
        set_session_auth u
        assert_equal u, @connection.exec_query("SELECT name FROM #{TABLE_NAME} WHERE id = $1", 'SQL', [bind_param(1)]).first['name']
        set_session_auth
      end
    end
  end

  def test_auth_with_bind
    assert_nothing_raised do
      set_session_auth
      USERS.each do |u|
        @connection.clear_cache!
        set_session_auth u
        assert_equal u, @connection.exec_query("SELECT name FROM #{TABLE_NAME} WHERE id = $1", 'SQL', [bind_param(1)]).first['name']
        set_session_auth
      end
    end
  end

  def test_schema_uniqueness
    assert_nothing_raised do
      set_session_auth
      USERS.each do |u|
        set_session_auth u
        assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1")
        set_session_auth
      end
    end
  end

  def test_sequence_schema_caching
    assert_nothing_raised do
      USERS.each do |u|
        set_session_auth u
        st = SchemaThing.new :name => 'TEST1'
        st.save!
        st = SchemaThing.new :id => 5, :name => 'TEST2'
        st.save!
        set_session_auth
      end
    end
  end

  def test_tables_in_current_schemas
    assert !@connection.tables.include?(TABLE_NAME)
    USERS.each do |u|
      set_session_auth u
      assert @connection.tables.include?(TABLE_NAME)
      set_session_auth
    end
  end

  private
    def set_session_auth auth = nil
       @connection.session_auth =  auth || 'default'
    end

    def bind_param(value)
      ActiveRecord::Relation::QueryAttribute.new(nil, value, ActiveRecord::Type::Value.new)
    end
end