Harbor Documentation

Harbor::Contrib::Session::DataObjects

This is a database backed session handle for DataObjects. You can use it instead of the builtin Harbor::Session::Cookie by doing:

  Harbor::Session.configure do |session|
    session[:store] = Harbor::Contrib::Session::DataObjects
    session[:connection_uri] = 'sqlite3://session.db'
  end

Public Class Methods

commit_session(data, request)

      # File lib/harbor/contrib/session/data_objects.rb, line 86
86:         def self.commit_session(data, request)
87:           session_id = data[:session_id]
88:         
89:           if data.dirty?
90:             user_id = data[:user_id]
91:             statement = "UPDATE sessions SET data = ?, user_id = ?, updated_at = ? WHERE id = ?;"
92:             execute(statement, self.dump(data.to_hash), user_id, Time.now, session_id)
93:           end
94:           
95:           session_id
96:         end

create_session(delegate, data = {}, request = nil)

       # File lib/harbor/contrib/session/data_objects.rb, line 124
124:         def self.create_session(delegate, data = {}, request = nil)
125:           session_id = `uuidgen`.chomp
126:           
127:           user_id = data.delete(:user_id)
128:           remote_ip = request ? request.remote_ip : nil
129:           user_agent_raw = request ? request.env["HTTP_USER_AGENT"] : nil
130:           
131:           data = self.dump(data)
132:           now = Time.now
133:           
134:           # We split in case X-Forwarded-For is a list, and rescue any errors
135:           # by setting the IP to 0.0.0.0 (which we'll treat as 'unknown').
136:           clean_ip = IPAddr.new(remote_ip.split(/,/, 2).first).to_s rescue '127.0.0.1'
137:           
138:           statement = "INSERT INTO sessions (id, data, user_id, remote_ip, user_agent_raw, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?);"
139:           execute(statement, session_id, data, user_id, clean_ip, user_agent_raw, now, now)
140:           delegate.session_created(session_id, remote_ip, user_agent_raw)
141:           
142:           {:session_id => session_id, :data => data, :user_id => user_id, :remote_ip => clean_ip, :user_agent_raw => user_agent_raw}
143:         end

create_session_table()

       # File lib/harbor/contrib/session/data_objects.rb, line 113
113:         def self.create_session_table
114:           return if (@table_exists == true)
115:           
116:           with_connection do |connection|
117:             cmd = connection.create_command(create_session_table_sql)
118:             cmd.execute_non_query
119:           end
120:           
121:           @table_exists = true
122:         end

dump(value)

       # File lib/harbor/contrib/session/data_objects.rb, line 176
176:         def self.dump(value)
177:           YAML::dump value
178:         end

execute(statement, *bind_values)

       # File lib/harbor/contrib/session/data_objects.rb, line 184
184:         def self.execute(statement, *bind_values)
185:           with_connection do |connection|
186:             command = connection.create_command(statement)
187:             command.execute_non_query(*bind_values)
188:           end
189:         end

get_raw_session(cookie, updated_at=nil)

       # File lib/harbor/contrib/session/data_objects.rb, line 145
145:         def self.get_raw_session(cookie, updated_at=nil)
146:           query = "SELECT id, data, user_id, remote_ip, user_agent_raw FROM sessions WHERE id = ? "
147:           params = [cookie]
148:           
149:           if updated_at
150:             query << ' AND updated_at >= ?'
151:             params << updated_at
152:           end
153:           query << ' LIMIT 1'
154:         
155:           raw = {}
156:           with_connection do |connection|
157:             cmd = connection.create_command(query)
158:             reader = cmd.execute_reader(*params)
159:             
160:             if reader.next!
161:               raw[:session_id] = reader.values[0]
162:               raw[:data] = reader.values[1]
163:               raw[:user_id] = reader.values[2]
164:               raw[:remote_ip] = reader.values[3]
165:               raw[:user_agent_raw] = reader.values[4]
166:             else
167:               raw = nil
168:             end
169:             
170:             reader.close
171:           end
172:           
173:           raw
174:         end

load(value)

       # File lib/harbor/contrib/session/data_objects.rb, line 180
180:         def self.load(value)
181:           YAML::load value
182:         end

load_session(delegate, cookie, request = nil)

      # File lib/harbor/contrib/session/data_objects.rb, line 70
70:         def self.load_session(delegate, cookie, request = nil)
71:           # create_session_table unless session_table_exists?
72:           
73:           if cookie && cookie.strip != ''
74:             raw_session = if expire_after = Harbor::Session.options[:expire_after]
75:               get_raw_session(cookie, Time.now - expire_after)
76:             else
77:               get_raw_session(cookie)
78:             end
79:           end
80:           
81:           raw_session ||= create_session(delegate, {}, request)
82: 
83:           SessionHash.new(raw_session)
84:         end

session_table_exists?()

       # File lib/harbor/contrib/session/data_objects.rb, line 98
 98:         def self.session_table_exists?        
 99:           return @table_exists unless @table_exists.nil?
100:           
101:           with_connection do |connection|
102:             cmd = connection.create_command(session_table_exists_sql)
103:             reader = cmd.execute_reader
104:             
105:             @table_exists = (reader.next! != false)
106:             
107:             reader.close
108:           end
109:           
110:           @table_exists
111:         end

with_connection()

       # File lib/harbor/contrib/session/data_objects.rb, line 191
191:         def self.with_connection
192:           conn = nil
193:           begin
194:             conn = ::DataObjects::Connection.new(Harbor::Session.options[:connection_uri])
195:             
196:             return yield(conn)
197: #          rescue => e
198: #            DataMapper.logger.error(e.to_s)
199: #            raise e
200:           ensure
201:             conn.close if conn
202:           end
203:         end

Private Class Methods

create_session_table_sql()

TODO we could create some kind of adapter when we get to add more supported DBs

       # File lib/harbor/contrib/session/data_objects.rb, line 208
208:         def self.create_session_table_sql
209:           case scheme
210:           when :sqlite3
211:             "CREATE TABLE sessions (id VARCHAR(50) NOT NULL, user_id INTEGER, remote_ip INET, user_agent_raw TEXT, data TEXT, created_at DATETIME, updated_at DATETIME, PRIMARY KEY(id))"
212:           when :postgres
213:             "CREATE TABLE sessions (id VARCHAR(50) NOT NULL, user_id INTEGER, remote_ip INET, user_agent_raw TEXT, data TEXT, created_at TIMESTAMP, updated_at TIMESTAMP, PRIMARY KEY(id))"
214:           else
215:             raise UnsupportedDatabaseError.new("Only SQLite3 and PostgreSQL are supported at the moment")
216:           end
217:         end

scheme()

       # File lib/harbor/contrib/session/data_objects.rb, line 230
230:         def self.scheme
231:           @scheme ||= ::DataObjects::URI::parse(Harbor::Session.options[:connection_uri]).scheme.to_sym
232:         end

session_table_exists_sql()

       # File lib/harbor/contrib/session/data_objects.rb, line 219
219:         def self.session_table_exists_sql
220:           case scheme
221:           when :sqlite3
222:             "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'sessions';"
223:           when :postgres
224:             "SELECT * FROM pg_tables WHERE schemaname = 'public' AND tablename = 'sessions';"
225:           else
226:             raise UnsupportedDatabaseError.new("Only SQLite3 and PostgreSQL are supported at the moment")
227:           end
228:         end