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
Parent
Namespace
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