dohruby 0.2.1 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +8 -0
- data/bin/config.rb +61 -0
- data/bin/create_database.rb +13 -6
- data/bin/gendata.rb +37 -0
- data/bin/migrate.rb +66 -0
- data/bin/{rcov-preprocess-files.rb → rcov_preprocess_files.rb} +1 -1
- data/bin/run_tests.rb +15 -5
- data/bin/update_rdoc.rb +28 -0
- data/dohapp_home +0 -0
- data/lib/doh/app/activate_database.rb +5 -12
- data/lib/doh/app/activate_logger.rb +29 -13
- data/lib/doh/app/config.rb +18 -0
- data/lib/doh/app/home.rb +3 -8
- data/lib/doh/app/init_runnable.rb +39 -8
- data/lib/doh/app/init_script.rb +19 -0
- data/lib/doh/app/init_unit_test.rb +4 -1
- data/lib/doh/app_no_stdio.rb +1 -1
- data/lib/doh/boot/app.rb +2 -0
- data/lib/doh/boot/app_pwd.rb +2 -0
- data/lib/doh/boot/find_dohruby.rb +5 -0
- data/lib/doh/boot/find_dohruby_18.rb +37 -0
- data/lib/doh/boot/find_dohruby_19.rb +58 -0
- data/lib/doh/boot/init_runnable.rb +2 -0
- data/lib/doh/boot/options.rb +2 -0
- data/lib/doh/core/array.rb +10 -0
- data/lib/doh/core/bigdecimal.rb +15 -0
- data/lib/doh/core/date.rb +73 -0
- data/lib/doh/core/deep_dup.rb +12 -0
- data/lib/doh/core/hash.rb +21 -0
- data/lib/doh/core/object.rb +6 -0
- data/lib/doh/core/require_local.rb +5 -0
- data/lib/doh/core/socket.rb +25 -0
- data/lib/doh/core/string.rb +34 -4
- data/lib/doh/core.rb +4 -1
- data/lib/doh/data/basic.rb +24 -19
- data/lib/doh/data/bulk.rb +28 -88
- data/lib/doh/data/catalog.rb +44 -0
- data/lib/doh/data/human.rb +50 -42
- data/lib/doh/data/make_global.rb +3 -0
- data/lib/doh/data/require_datagen.rb +2 -1
- data/lib/doh/home.rb +16 -0
- data/lib/doh/logger/email_acceptor.rb +6 -3
- data/lib/doh/logger/event.rb +19 -6
- data/lib/doh/logger/formatter.rb +22 -16
- data/lib/doh/logger/interface.rb +13 -0
- data/lib/doh/logger/iostream_acceptor.rb +3 -2
- data/lib/doh/logger/null_interface.rb +1 -0
- data/lib/doh/logger/proxy.rb +53 -0
- data/lib/doh/logger/socket_acceptor.rb +53 -0
- data/lib/doh/logger/socket_viewer.rb +64 -0
- data/lib/doh/logger/standard_interface.rb +46 -17
- data/lib/doh/logger/util.rb +18 -0
- data/lib/doh/logger.rb +2 -1
- data/lib/doh/logger_configure.rb +1 -1
- data/lib/doh/merb/db_session.rb +136 -0
- data/lib/doh/merb/form_helpers.rb +16 -0
- data/lib/doh/merb/login.rb +27 -12
- data/lib/doh/merb/merb_dohsession.rb +4 -0
- data/lib/doh/merb/notify_on_exception.rb +1 -1
- data/lib/doh/merb/session.rb +7 -0
- data/lib/doh/merb/source_ip.rb +10 -0
- data/lib/doh/merb.rb +0 -1
- data/lib/doh/mysql/abstract_row.rb +81 -0
- data/lib/doh/mysql/cache_connector.rb +11 -8
- data/lib/doh/mysql/connector_instance.rb +32 -5
- data/lib/doh/mysql/connector_util.rb +1 -0
- data/lib/doh/mysql/convert.rb +18 -0
- data/lib/doh/mysql/database_creator.rb +18 -5
- data/lib/doh/mysql/db_date.rb +2 -2
- data/lib/doh/mysql/default_type_guesser.rb +21 -4
- data/lib/doh/mysql/error.rb +3 -2
- data/lib/doh/mysql/handle.rb +144 -18
- data/lib/doh/mysql/hash_row.rb +13 -0
- data/lib/doh/mysql/load_sql.rb +1 -0
- data/lib/doh/mysql/metadata_util.rb +60 -19
- data/lib/doh/mysql/migrate.rb +122 -0
- data/lib/doh/mysql/migrate_check.rb +139 -0
- data/lib/doh/mysql/parse.rb +2 -0
- data/lib/doh/mysql/readonly_row.rb +11 -48
- data/lib/doh/mysql/require_dbtypes.rb +8 -0
- data/lib/doh/mysql/smart_row.rb +156 -0
- data/lib/doh/mysql/to_sql.rb +12 -0
- data/lib/doh/mysql/typed_row_builder.rb +4 -3
- data/lib/doh/mysql/types.rb +33 -0
- data/lib/doh/mysql/unquoted.rb +8 -0
- data/lib/doh/mysql/version.rb +102 -0
- data/lib/doh/mysql/virtual.rb +17 -0
- data/lib/doh/mysql/writable_row.rb +58 -0
- data/lib/doh/mysql.rb +2 -1
- data/lib/doh/paypal/paypal.rb +20 -0
- data/lib/doh/paypal/pdt.rb +14 -0
- data/lib/doh/paypal.rb +1 -0
- data/lib/doh/rails/form_helpers.rb +53 -0
- data/lib/doh/rails/login.rb +143 -0
- data/lib/doh/test/error_acceptor.rb +1 -1
- data/lib/doh/test/run_tests.rb +48 -43
- data/lib/doh/test/setup_once.rb +15 -0
- data/lib/doh/test/test_result.rb +7 -0
- data/lib/doh/unit_test.rb +6 -0
- data/lib/doh/util/banking_workday.rb +16 -12
- data/lib/doh/util/class_basename.rb +10 -0
- data/lib/doh/util/current_date.rb +18 -41
- data/lib/doh/util/doh_socket.rb +56 -0
- data/lib/doh/util/email.rb +18 -0
- data/lib/doh/util/file_edit.rb +64 -0
- data/lib/doh/util/http_helper.rb +107 -0
- data/lib/doh/util/internal_ip.rb +1 -1
- data/lib/doh/util/jsval.rb +13 -0
- data/lib/doh/util/post_hash.rb +14 -0
- data/lib/doh/util/xml_util.rb +48 -0
- data/test/core/tc_array.rb +12 -0
- data/test/core/tc_date.rb +53 -0
- data/test/core/tc_deep_dup.rb +69 -0
- data/test/core/tc_hash.rb +28 -0
- data/test/core/tc_socket.rb +30 -0
- data/test/core/tc_string.rb +15 -22
- data/test/local_tests.rb +3 -0
- data/test/local_tests_including_slow.rb +4 -0
- data/test/logger/tc_acceptor.rb +23 -6
- data/test/logger/tc_event.rb +1 -1
- data/test/logger/tc_formatter.rb +3 -2
- data/test/logger/tc_socket_viewer_acceptor.rb +48 -0
- data/test/mysql/001_down.sql +1 -0
- data/test/mysql/001_up.sql +4 -0
- data/test/mysql/002_down.sql +1 -0
- data/test/mysql/002_up.sql +1 -0
- data/test/mysql/tc_connector_instance.rb +8 -8
- data/test/mysql/tc_convert.rb +45 -0
- data/test/mysql/tc_handle.rb +94 -2
- data/test/mysql/tc_metadata_util.rb +50 -0
- data/test/mysql/tc_migrate.rb +50 -0
- data/test/mysql/tc_parse.rb +3 -1
- data/test/mysql/tc_readonly_row.rb +14 -10
- data/test/mysql/tc_smart_row.rb +22 -0
- data/test/mysql/tc_to_sql.rb +20 -0
- data/test/mysql/tc_types.rb +32 -0
- data/test/mysql/tc_unquoted.rb +1 -0
- data/test/mysql/tc_writable_row.rb +22 -0
- data/test/ts_core.rb +4 -0
- data/test/ts_logger.rb +4 -0
- data/test/ts_mysql.rb +6 -0
- data/test/ts_util.rb +6 -0
- data/test/util/slow_doh_socket.rb +102 -0
- data/test/util/tc_banking_workday.rb +18 -0
- data/test/util/tc_file_edit.rb +54 -0
- data/test/util/tc_jsval.rb +12 -0
- data/test/util/tc_to_display.rb +14 -0
- data/test/util/tc_xml_util.rb +17 -0
- metadata +130 -39
- data/README +0 -4
- data/lib/doh/merb/post_hash.rb +0 -26
- data/lib/doh/mysql/db_null.rb +0 -24
- data/lib/doh/mysql/hash_util.rb +0 -56
- data/test/mysql/tc_hash_util.rb +0 -23
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
require 'doh/mysql/writable_row'
|
|
2
|
+
require 'doh/util/to_display'
|
|
3
|
+
require 'doh/mysql/virtual'
|
|
4
|
+
|
|
5
|
+
module DohDb
|
|
6
|
+
|
|
7
|
+
class RowDisplayProxy
|
|
8
|
+
def initialize(row)
|
|
9
|
+
@row = row
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def method_missing(sym, *ignore_args)
|
|
13
|
+
@row.send(sym.to_s).to_display
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class AbstractSmartRow < AbstractRow
|
|
18
|
+
attr_accessor :table
|
|
19
|
+
attr_reader :changed_keys
|
|
20
|
+
|
|
21
|
+
def initialize(keys, values)
|
|
22
|
+
@keys = keys.dup
|
|
23
|
+
@values = values.dup
|
|
24
|
+
@changed_keys = Set.new
|
|
25
|
+
@cached_virtuals = {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize_copy(orig)
|
|
29
|
+
@keys = @keys.dup
|
|
30
|
+
@values = @values.dup
|
|
31
|
+
@changed_keys = @changed_keys.dup
|
|
32
|
+
@cached_virtuals = @cached_virtuals.dup
|
|
33
|
+
@display_proxy = nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def display(key = nil)
|
|
37
|
+
if key.nil?
|
|
38
|
+
@display_proxy ||= RowDisplayProxy.new(self)
|
|
39
|
+
else
|
|
40
|
+
get(key).to_display
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def set(key, value, flag_changed = true)
|
|
45
|
+
index = @keys.index(key)
|
|
46
|
+
if index
|
|
47
|
+
if @values[index] != value
|
|
48
|
+
@values[index] = value
|
|
49
|
+
@changed_keys.add(key)
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
@keys.push(key)
|
|
53
|
+
@values.push(value)
|
|
54
|
+
@changed_keys.add(key)
|
|
55
|
+
end
|
|
56
|
+
value
|
|
57
|
+
end
|
|
58
|
+
alias []= set
|
|
59
|
+
|
|
60
|
+
def clear_changed_keys
|
|
61
|
+
@changed_keys.clear
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def method_missing(sym, *args)
|
|
65
|
+
name = sym.to_s
|
|
66
|
+
if name.end_with?('=')
|
|
67
|
+
guess_missing_set(name[0..-2], args.first)
|
|
68
|
+
else
|
|
69
|
+
guess_missing_get(name)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def merge!(hash)
|
|
74
|
+
hash.each_pair { |key, value| set(key, value) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def delete(key)
|
|
78
|
+
index = @keys.index(key)
|
|
79
|
+
return unless index
|
|
80
|
+
@keys.delete_at(index)
|
|
81
|
+
@values.delete_at(index)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def record_id=(value)
|
|
85
|
+
set(primary_key, value)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def db_insert
|
|
89
|
+
newid = DohDb::insert_hash(self, @table)
|
|
90
|
+
if newid != 0
|
|
91
|
+
set(primary_key, newid, false)
|
|
92
|
+
end
|
|
93
|
+
newid
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def db_update
|
|
97
|
+
return if @changed_keys.empty?
|
|
98
|
+
before_db_update
|
|
99
|
+
builder = BuildSQL::SimpleUpdateRow.new(@table, nil, get(primary_key), primary_key)
|
|
100
|
+
@changed_keys.each {|key| builder.setc(key, get(key).to_sql)}
|
|
101
|
+
DohDb::query(builder)
|
|
102
|
+
after_db_update
|
|
103
|
+
@changed_keys.clear
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
protected
|
|
107
|
+
def primary_key
|
|
108
|
+
DohDb::find_primary_key(@table)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def before_db_update
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def after_db_update
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def guess_missing_get(key)
|
|
118
|
+
return get(key) if key?(key)
|
|
119
|
+
retval = get_virtual_field(key)
|
|
120
|
+
raise "unknown field: #{key}" unless retval
|
|
121
|
+
retval
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def guess_missing_set(key, value)
|
|
125
|
+
set(key, value)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def get_virtual_field(name)
|
|
129
|
+
cached = @cached_virtuals[name]
|
|
130
|
+
return cached if cached
|
|
131
|
+
if idvalue = get(name + '_id')
|
|
132
|
+
@cached_virtuals[name] = DohDb::LinkedRow.build(name, idvalue.to_i)
|
|
133
|
+
else
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class SmartRow < AbstractSmartRow
|
|
140
|
+
def initialize(*args)
|
|
141
|
+
parsed_args = parse_initialize_args(*args)
|
|
142
|
+
if parsed_args.size == 3
|
|
143
|
+
@table = parsed_args.pop
|
|
144
|
+
end
|
|
145
|
+
super(*parsed_args)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
class CustomSmartRow < AbstractSmartRow
|
|
150
|
+
def initialize(*args)
|
|
151
|
+
super(*parse_initialize_args(*args))
|
|
152
|
+
@table = self.class.default_table
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
data/lib/doh/mysql/to_sql.rb
CHANGED
|
@@ -8,6 +8,12 @@ class Object
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
class NilClass
|
|
12
|
+
def to_sql
|
|
13
|
+
'NULL'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
11
17
|
class Numeric
|
|
12
18
|
def to_sql
|
|
13
19
|
to_s
|
|
@@ -37,3 +43,9 @@ class BigDecimal
|
|
|
37
43
|
to_s('F')
|
|
38
44
|
end
|
|
39
45
|
end
|
|
46
|
+
|
|
47
|
+
class Array
|
|
48
|
+
def to_sql
|
|
49
|
+
'(' + collect { |elem| elem.to_sql }.join(',') + ')'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -4,8 +4,9 @@ require 'doh/mysql/default_type_guesser'
|
|
|
4
4
|
module DohDb
|
|
5
5
|
|
|
6
6
|
class TypedRowBuilder
|
|
7
|
-
def initialize(guesser = nil)
|
|
8
|
-
@
|
|
7
|
+
def initialize(row_klass = nil, guesser = nil)
|
|
8
|
+
@row_klass = row_klass || ReadOnlyRow
|
|
9
|
+
@guesser = guesser || DefaultTypeGuesser
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def build_rows(result_set)
|
|
@@ -18,7 +19,7 @@ class TypedRowBuilder
|
|
|
18
19
|
row.each_with_index do |field, index|
|
|
19
20
|
typed_values[index] = @guesser.guess_type(field, meta_info[index])
|
|
20
21
|
end
|
|
21
|
-
retval.push(
|
|
22
|
+
retval.push(@row_klass.new(field_names, typed_values))
|
|
22
23
|
end
|
|
23
24
|
retval
|
|
24
25
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module DohDb
|
|
2
|
+
|
|
3
|
+
@@column_types = {}
|
|
4
|
+
def self.register_column_type(database, table, column, klass)
|
|
5
|
+
database = '__global__' # until database support is available
|
|
6
|
+
@@column_types[database] ||= {}
|
|
7
|
+
table = '__global__' if table.nil?
|
|
8
|
+
@@column_types[database][table] ||= {}
|
|
9
|
+
@@column_types[database][table][column] = klass
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.find_column_type(database, table, column)
|
|
13
|
+
database = '__global__' # until database support is available
|
|
14
|
+
db_hash = @@column_types[database]; return nil unless db_hash
|
|
15
|
+
table = '__global__' if table.nil?
|
|
16
|
+
table_hash = db_hash[table]; return nil unless table_hash
|
|
17
|
+
table_hash[column]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.link_database_types(dest_db, source_db)
|
|
21
|
+
@@column_types[dest_db] = @@column_types[source_db]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@@row_types = {}
|
|
25
|
+
def self.register_row_type(table, klass)
|
|
26
|
+
@@row_types[table] = klass
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.find_row_type(table)
|
|
30
|
+
@@row_types[table]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
data/lib/doh/mysql/unquoted.rb
CHANGED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'doh/mysql/connector_instance'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
module DohDb
|
|
5
|
+
|
|
6
|
+
def self.locked_filename(database)
|
|
7
|
+
File.join(DohApp::home, 'database', database, 'migrate/locked.yml')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.migration_filename(database, version, upordown = 'up')
|
|
11
|
+
version_str = version.to_s.rjust(3, '0')
|
|
12
|
+
File.join(DohApp::home, 'database', database, "migrate/#{version_str}_#{upordown}.sql")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.current_database_version(database = nil)
|
|
16
|
+
if database.nil?
|
|
17
|
+
table = 'version'
|
|
18
|
+
else
|
|
19
|
+
table = database + '.version'
|
|
20
|
+
end
|
|
21
|
+
DohDb::select_field("SELECT version FROM #{table}").to_i
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.latest_database_version(database = nil)
|
|
25
|
+
locked_version = locked_database_version(database)
|
|
26
|
+
unlocked_version = locked_version + 1
|
|
27
|
+
unlocked_migration_file = migration_filename(database, unlocked_version)
|
|
28
|
+
if File.exist?(unlocked_migration_file)
|
|
29
|
+
unlocked_version
|
|
30
|
+
else
|
|
31
|
+
locked_version
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.locked_version_info(database = nil)
|
|
36
|
+
database ||= (DohDb::connector_instance && DohDb::connector_instance.database) || DohApp::config['primary_database']
|
|
37
|
+
filename = locked_filename(database)
|
|
38
|
+
return [0, nil] unless File.exist?(filename)
|
|
39
|
+
YAML.load_file(filename)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.locked_database_version(database = nil)
|
|
43
|
+
locked_version_info(database).first
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.locked_svn_revision(database = nil)
|
|
47
|
+
locked_version_info(database).last
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.update_locked_file(database)
|
|
51
|
+
locked_file = locked_filename(database)
|
|
52
|
+
if File.exist?(locked_file)
|
|
53
|
+
new_version = YAML.load_file(locked_file).first + 1
|
|
54
|
+
else
|
|
55
|
+
new_version = 0
|
|
56
|
+
need_to_add = true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
file_to_check = ''
|
|
60
|
+
if need_to_add
|
|
61
|
+
file_to_check = File.join(DohApp::home, "database")
|
|
62
|
+
else
|
|
63
|
+
unlocked_migration_file = migration_filename(database, new_version)
|
|
64
|
+
return [true, "nothing to lock"] unless File.exist?(unlocked_migration_file)
|
|
65
|
+
|
|
66
|
+
svnout = `svn st #{unlocked_migration_file}`
|
|
67
|
+
unless svnout.strip.empty?
|
|
68
|
+
return [false, "svn status shows local changes to #{unlocked_migration_file} -- this needs to be resolved before updating the migration locked file"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
file_to_check = unlocked_migration_file
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
`svn update #{file_to_check}`
|
|
75
|
+
svnout = `svn st -v #{file_to_check}`.split("\n")
|
|
76
|
+
svnout =~ /(\d+)/
|
|
77
|
+
revision = svnout.collect {|elem| elem =~ /(\d+)/; $1.to_i}.max
|
|
78
|
+
if !revision
|
|
79
|
+
return [false, "unable to extract svn revision from: '#{svnout}'"]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
outfile = File.new(locked_file, 'w')
|
|
83
|
+
outfile.puts([new_version, revision.to_i].inspect)
|
|
84
|
+
outfile.close
|
|
85
|
+
|
|
86
|
+
if need_to_add
|
|
87
|
+
svnout = `svn add #{locked_file}`
|
|
88
|
+
if svnout[0,1] != 'A'
|
|
89
|
+
return [false, "failed to svn add #{locked_file}"]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
msg = "migrate lock for #{database} database, version #{new_version}"
|
|
94
|
+
svnout = `svn ci -m \"#{msg}\" #{locked_file}`
|
|
95
|
+
unless svnout.index("Committed revision")
|
|
96
|
+
return [false, "failed to svn ci #{locked_file}"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
[true, "#{locked_file} successfully updated"]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'doh/mysql/metadata_util'
|
|
2
|
+
require 'doh/mysql/readonly_row'
|
|
3
|
+
require 'doh/mysql/types'
|
|
4
|
+
|
|
5
|
+
module DohDb
|
|
6
|
+
|
|
7
|
+
class LinkedRow
|
|
8
|
+
def self.build(field, idvalue)
|
|
9
|
+
return ReadOnlyRow.new([], []) if idvalue.to_i == 0
|
|
10
|
+
table = field.sub(/_id/, '')
|
|
11
|
+
table = table.rafter('_') unless DohDb::table_exist?(table)
|
|
12
|
+
raise "unable to determine child table name for field #{field}" unless DohDb::table_exist?(table)
|
|
13
|
+
DohDb::select_row("SELECT * FROM #{table} WHERE #{DohDb::find_primary_key(table)} = #{idvalue}", DohDb::find_row_type(table) || :smart)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'doh/mysql/abstract_row'
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module DohDb
|
|
5
|
+
|
|
6
|
+
class WritableRow < AbstractRow
|
|
7
|
+
attr_reader :changed_keys
|
|
8
|
+
|
|
9
|
+
# can accept 2 arguments: keys array, values array
|
|
10
|
+
# or 1 argument: a hash
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
keys, values = parse_initialize_args(*args)
|
|
13
|
+
@keys = keys.dup
|
|
14
|
+
@values = values.dup
|
|
15
|
+
@changed_keys = Set.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize_copy(orig)
|
|
19
|
+
super(orig)
|
|
20
|
+
@changed_keys = Set.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def set(key, value)
|
|
24
|
+
index = @keys.index(key)
|
|
25
|
+
if index
|
|
26
|
+
@values[index] = value
|
|
27
|
+
else
|
|
28
|
+
@keys.push(key)
|
|
29
|
+
@values.push(value)
|
|
30
|
+
end
|
|
31
|
+
@changed_keys.add(key)
|
|
32
|
+
value
|
|
33
|
+
end
|
|
34
|
+
alias []= set
|
|
35
|
+
|
|
36
|
+
def clear_changed_keys
|
|
37
|
+
@changed_keys.clear
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def method_missing(sym, *args)
|
|
41
|
+
name = sym.to_s
|
|
42
|
+
if name.lastn(1) == '='
|
|
43
|
+
key = name[0..-2]
|
|
44
|
+
assign = true
|
|
45
|
+
else
|
|
46
|
+
key = name
|
|
47
|
+
end
|
|
48
|
+
raise RuntimeError.new("unknown field: " + name) unless key?(key)
|
|
49
|
+
|
|
50
|
+
if assign
|
|
51
|
+
set(key, args.first)
|
|
52
|
+
else
|
|
53
|
+
get(key)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
data/lib/doh/mysql.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'doh/util/http_helper'
|
|
2
|
+
module DohPaypal
|
|
3
|
+
|
|
4
|
+
# <form method=post action="https://www.sandbox.paypal.com/cgi-bin/webscr">
|
|
5
|
+
# <input type="hidden" name="cmd" value="_notify-synch">
|
|
6
|
+
# <input type="hidden" name="tx" value="5GW002680B422045J">
|
|
7
|
+
# <input type="hidden" name="at" value="cIPgiu5oHqqMBQmjXdlEozmRH5N1XwT0Bk2gaPeg_6S433QYY9Cj9REL3Hu">
|
|
8
|
+
# <input type="submit" value="PDT">
|
|
9
|
+
# </form>
|
|
10
|
+
|
|
11
|
+
#this downloads the payment data for a transaction, passing in the tx that paypal sends to us
|
|
12
|
+
def self.get_tx_info(tx_str)
|
|
13
|
+
hash = {'cmd' => '_notify-synch', 'tx' => tx_str, 'at' => DohApp::config['paypal_identity_string']}
|
|
14
|
+
http = Doh::HttpHelper.new("https://#{DohApp::config['paypal_url']}/cgi-bin/webscr")
|
|
15
|
+
http.post(hash)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module DohPaypal
|
|
2
|
+
# <form method=post action="https://www.sandbox.paypal.com/cgi-bin/webscr">
|
|
3
|
+
# <input type="hidden" name="cmd" value="_notify-synch">
|
|
4
|
+
# <input type="hidden" name="tx" value="5GW002680B422045J">
|
|
5
|
+
# <input type="hidden" name="at" value="cIPgiu5oHqqMBQmjXdlEozmRH5N1XwT0Bk2gaPeg_6S433QYY9Cj9REL3Hu">
|
|
6
|
+
# <input type="submit" value="PDT">
|
|
7
|
+
# </form>
|
|
8
|
+
|
|
9
|
+
def self.get_tx_info(tx_str)
|
|
10
|
+
hash = {'cmd' => '_notify-synch', 'tx' => tx_str, 'at' => DohApp::config['paypal_identity_string']}
|
|
11
|
+
http = Doh::HttpHelper.new("https://#{DohApp::config['paypal_url']}/cgi-bin/webscr")
|
|
12
|
+
http.post(hash)
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/doh/paypal.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'doh/paypal/paypal'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module DohRails
|
|
2
|
+
module FormHelpers
|
|
3
|
+
|
|
4
|
+
def self.get_label_html(options)
|
|
5
|
+
if options.key?(:label)
|
|
6
|
+
label_html = "<label for='#{DohRails::FormHelpers::get_id(options)}'>#{options[:label]}</label>"
|
|
7
|
+
options.delete(:label)
|
|
8
|
+
end
|
|
9
|
+
return label_html
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.get_id(options)
|
|
13
|
+
options[:name] ? options[:name] : "obj_#{options.hash}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.option_str(options)
|
|
17
|
+
options.to_a.collect{|key, value| "#{key}='#{value}'"}.join(' ')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def doh_field(type, options)
|
|
21
|
+
label_html = DohRails::FormHelpers::get_label_html(options)
|
|
22
|
+
"#{label_html}<input id='#{DohRails::FormHelpers::get_id(options)}' type='#{type}' #{DohRails::FormHelpers::option_str(options)}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def doh_text_field(options)
|
|
26
|
+
doh_field('text', options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def doh_hidden_field(options)
|
|
30
|
+
doh_field('hidden', options)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def doh_checkbox(options)
|
|
34
|
+
doh_field('checkbox', options)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#kjmtodo modify to set default value based on model / field name
|
|
38
|
+
def doh_select(select_array, options = {})
|
|
39
|
+
label_html = DohRails::FormHelpers::get_label_html(options)
|
|
40
|
+
result = ''
|
|
41
|
+
result += label_html
|
|
42
|
+
result += "<select id='#{DohRails::FormHelpers::get_id(options)}' #{DohRails::FormHelpers::option_str(options)}>\n"
|
|
43
|
+
select_list = select_array.collect do |elem|
|
|
44
|
+
"<option value=\"#{elem[0]}\">#{elem[1]}</option>"
|
|
45
|
+
end
|
|
46
|
+
result += select_list.join("\n")
|
|
47
|
+
result += "</select>"
|
|
48
|
+
result
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require 'doh/mysql'
|
|
2
|
+
require 'digest'
|
|
3
|
+
|
|
4
|
+
module DohRails
|
|
5
|
+
module Login
|
|
6
|
+
attr_accessor :login_model, :login_controller, :username_fieldname, :password_fieldname, :login_table, :login_db_name, :password_db_name, :index_page, :login_page
|
|
7
|
+
|
|
8
|
+
#set the attr_accessors or override them
|
|
9
|
+
|
|
10
|
+
def login_controller
|
|
11
|
+
@login_controller || 'application'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def login_model
|
|
15
|
+
@login_model || 'login_model'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def username_fieldname
|
|
19
|
+
@username_fieldname || 'username'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def password_fieldname
|
|
23
|
+
@password_fieldname || 'password'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def login_table
|
|
27
|
+
@login_table || 'login'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def login_db_name
|
|
31
|
+
@login_db_name || 'login'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def login_page
|
|
35
|
+
@login_page || 'login'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def index_page
|
|
39
|
+
@index_page || 'index'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def password_db_name
|
|
43
|
+
@password_db_name || 'password'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def login_page_hit
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def login_failed
|
|
50
|
+
flash[:notice] = 'Please enter a valid username / password'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def login_succeeded
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def login_redirect
|
|
57
|
+
flash[:notice] = 'Please log in'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def login_required
|
|
61
|
+
if !authenticated?
|
|
62
|
+
dohlog.debug "not authenticated, redirecting to #{login_page}"
|
|
63
|
+
session[:dohrails_original_uri] = request.request_uri
|
|
64
|
+
dohlog.debug("storing original uri #{request.request_uri.inspect}")
|
|
65
|
+
login_redirect
|
|
66
|
+
redirect_to :controller => login_controller, :action => login_page
|
|
67
|
+
return false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def authenticated?
|
|
72
|
+
if @authentication_checked
|
|
73
|
+
return @authenticated
|
|
74
|
+
end
|
|
75
|
+
dohlog.debug("authenticated? called -- session[:dohrails_login_username] = #{session[:dohrails_login_username]}")
|
|
76
|
+
@authenticated = authenticate_username_key(session[:dohrails_login_username], session[:dohrails_login_key]) if !session[:dohrails_login_username].to_s.strip.empty? && !session[:dohrails_login_key].to_s.strip.empty?
|
|
77
|
+
@authentication_checked = true
|
|
78
|
+
return @authenticated
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# override this to have custom behavior
|
|
82
|
+
def authenticate_username_key(username, key)
|
|
83
|
+
begin
|
|
84
|
+
row = DohDb::select_optional_row("SELECT * FROM #{login_table} WHERE #{login_db_name} = #{username.to_sql}")
|
|
85
|
+
if row
|
|
86
|
+
if key == get_session_key(username, row[password_db_name])
|
|
87
|
+
self.instance_variable_set("@#{login_table}_row", row)
|
|
88
|
+
dohlog.debug("authenticate_username returning true")
|
|
89
|
+
return true
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
rescue Exception => e
|
|
93
|
+
dohlog.warn("got error: #{e.inspect} (called from authenticate_username_key) -- are you missing the table: #{login_table.inspect}?")
|
|
94
|
+
end
|
|
95
|
+
dohlog.debug("authenticate_username returning nil")
|
|
96
|
+
return nil
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def get_session_key(username, password)
|
|
100
|
+
Digest::SHA1.hexdigest("#{username}**#{password}")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def logged_in?
|
|
104
|
+
authenticated?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def login
|
|
108
|
+
login_page_hit
|
|
109
|
+
if request.post?
|
|
110
|
+
login_params = params[login_model]
|
|
111
|
+
session[:dohrails_login_username] = login_params[username_fieldname]
|
|
112
|
+
session[:dohrails_login_key] = get_session_key(login_params[username_fieldname], login_params[password_fieldname])
|
|
113
|
+
if authenticated?
|
|
114
|
+
login_succeeded
|
|
115
|
+
if session[:dohrails_original_uri]
|
|
116
|
+
dohlog.debug("redirecting to original uri: #{session[:dohrails_original_uri].inspect}")
|
|
117
|
+
redirect_to session[:dohrails_original_uri]
|
|
118
|
+
session[:dohrails_original_uri] = nil
|
|
119
|
+
else
|
|
120
|
+
dohlog.debug("no original uri, redirecting to index")
|
|
121
|
+
redirect_to :controller => login_controller, :action => index_page
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
dohlog.debug("login_helper called, not authenticated -- redirecting to login page")
|
|
125
|
+
login_failed
|
|
126
|
+
redirect_to :controller => login_controller, :action => login_page
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def logged_out
|
|
132
|
+
flash[:notice] = 'You are now logged out'
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def logout
|
|
136
|
+
session[:dohrails_login_username] = ''
|
|
137
|
+
session[:dohrails_login_key] = ''
|
|
138
|
+
logged_out
|
|
139
|
+
redirect_to :controller => login_controller, :action => login_page
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -17,7 +17,7 @@ end
|
|
|
17
17
|
def self.check_for_unhandled_errors
|
|
18
18
|
errors = DohTest::error_acceptor.events
|
|
19
19
|
unless errors.empty?
|
|
20
|
-
STDERR.puts("#{errors.size} unhandled errors were written to the log file:")
|
|
20
|
+
STDERR.puts("#{errors.size} unhandled errors were written to the log file (call DohTest::pop_error after a test if the test is expected to generate an error):")
|
|
21
21
|
formatter = DohLogger::Formatter.new("[%severity] : %msg\nexception: %exception\nstack:\n%call_stack")
|
|
22
22
|
errors.each {|elem| STDERR.puts(formatter.replace(elem))}
|
|
23
23
|
exit 1
|