ooor 1.9.2 → 2.0.0
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/README.md +23 -71
- data/Rakefile +5 -0
- data/bin/ooor +1 -0
- data/lib/ooor.rb +87 -129
- data/lib/ooor/associations.rb +64 -0
- data/lib/ooor/base.rb +218 -0
- data/lib/{app/models → ooor}/base64.rb +0 -0
- data/lib/ooor/connection.rb +37 -0
- data/lib/ooor/errors.rb +120 -0
- data/lib/ooor/field_methods.rb +153 -0
- data/lib/{app → ooor}/helpers/core_helpers.rb +2 -2
- data/lib/ooor/locale.rb +13 -0
- data/lib/ooor/mini_active_resource.rb +94 -0
- data/lib/ooor/model_registry.rb +19 -0
- data/lib/ooor/naming.rb +73 -0
- data/lib/ooor/rack.rb +114 -0
- data/lib/ooor/railtie.rb +41 -0
- data/lib/ooor/reflection.rb +537 -0
- data/lib/ooor/reflection_ooor.rb +92 -0
- data/lib/{app/models → ooor}/relation.rb +61 -22
- data/lib/ooor/relation/finder_methods.rb +113 -0
- data/lib/ooor/report.rb +53 -0
- data/lib/{app/models → ooor}/serialization.rb +18 -6
- data/lib/ooor/services.rb +133 -0
- data/lib/ooor/session.rb +120 -0
- data/lib/ooor/session_handler.rb +63 -0
- data/lib/ooor/transport.rb +34 -0
- data/lib/ooor/transport/json_client.rb +53 -0
- data/lib/ooor/transport/xml_rpc_client.rb +15 -0
- data/lib/ooor/type_casting.rb +193 -0
- data/lib/ooor/version.rb +8 -0
- data/spec/helpers/test_helper.rb +11 -0
- data/spec/install_nightly.sh +17 -0
- data/spec/ooor_spec.rb +197 -79
- data/spec/requirements.txt +19 -0
- metadata +58 -20
- data/lib/app/models/client_xmlrpc.rb +0 -34
- data/lib/app/models/open_object_resource.rb +0 -486
- data/lib/app/models/services.rb +0 -47
- data/lib/app/models/type_casting.rb +0 -134
- data/lib/app/models/uml.rb +0 -210
- data/lib/app/ui/action_window.rb +0 -96
- data/lib/app/ui/client_base.rb +0 -36
- data/lib/app/ui/form_model.rb +0 -88
- data/ooor.yml +0 -27
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
require 'active_support/core_ext/object/inclusion'
|
3
|
+
|
4
|
+
module Ooor
|
5
|
+
# = Ooor Reflection
|
6
|
+
module ReflectionOoor # :nodoc:
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def set_columns_hash(view_fields={})
|
11
|
+
reload_fields_definition()
|
12
|
+
@t.columns_hash ||= {}
|
13
|
+
@t.fields.each do |k, field|
|
14
|
+
unless @t.associations_keys.index(k)
|
15
|
+
@t.columns_hash[k] = field.merge({type: to_rails_type(view_fields[k] && view_fields[k]['type'] || field['type'])})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@t.columns_hash
|
19
|
+
end
|
20
|
+
|
21
|
+
def column_for_attribute(name)
|
22
|
+
columns_hash[name.to_s]
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_reflection(name)
|
26
|
+
options = {}
|
27
|
+
if many2one_associations.keys.include?(name)
|
28
|
+
macro = :belongs_to
|
29
|
+
relation = many2one_associations[name]['relation'] #TODO prefix?
|
30
|
+
const_get(relation)
|
31
|
+
options[:class_name] = relation #TODO or pass it camelized already?
|
32
|
+
elsif many2many_associations.keys.include?(name)
|
33
|
+
macro = :has_and_belongs_to_many
|
34
|
+
elsif one2many_associations.keys.include?(name)
|
35
|
+
macro = :has_many
|
36
|
+
end
|
37
|
+
reflection = Reflection::AssociationReflection.new(macro, name, options, nil)#active_record) #TODO active_record?
|
38
|
+
# case macro
|
39
|
+
# when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many
|
40
|
+
# klass = options[:through] ? ThroughReflection : AssociationReflection
|
41
|
+
# reflection = klass.new(macro, name, options, active_record)
|
42
|
+
# when :composed_of
|
43
|
+
# reflection = AggregateReflection.new(macro, name, options, active_record)
|
44
|
+
# end
|
45
|
+
|
46
|
+
self.reflections = self.reflections.merge(name => reflection)
|
47
|
+
reflection
|
48
|
+
end
|
49
|
+
|
50
|
+
def reflect_on_association(association)
|
51
|
+
reflections[association] ||= create_reflection(association.to_s).tap do |reflection|
|
52
|
+
reflection.connection = connection
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
module Ooor
|
62
|
+
# = Active Record Reflection
|
63
|
+
module Reflection # :nodoc:
|
64
|
+
|
65
|
+
class MacroReflection
|
66
|
+
attr_accessor :connection
|
67
|
+
end
|
68
|
+
|
69
|
+
# Holds all the meta-data about an association as it was specified in the
|
70
|
+
# Active Record class.
|
71
|
+
class AssociationReflection < MacroReflection #:nodoc:
|
72
|
+
# Returns the target association's class.
|
73
|
+
#
|
74
|
+
# class Author < ActiveRecord::Base
|
75
|
+
# has_many :books
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# Author.reflect_on_association(:books).klass
|
79
|
+
# # => Book
|
80
|
+
#
|
81
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
82
|
+
# a new association object. Use +build_association+ or +create_association+
|
83
|
+
# instead. This allows plugins to hook into association object creation.
|
84
|
+
def klass
|
85
|
+
# @klass ||= active_record.send(:compute_type, class_name)
|
86
|
+
@klass ||= connection.class_name_from_model_key(class_name).constantize
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# OOOR: OpenObject On Ruby
|
2
|
-
# Copyright (C) 2009-
|
2
|
+
# Copyright (C) 2009-TODAY Akretion LTDA (<http://www.akretion.com>).
|
3
3
|
# Author: Raphaël Valyi
|
4
4
|
# Licensed under the MIT license, see MIT-LICENSE file
|
5
5
|
|
@@ -9,16 +9,15 @@
|
|
9
9
|
module Ooor
|
10
10
|
# = Similar to Active Record Relation
|
11
11
|
class Relation
|
12
|
-
|
13
12
|
attr_reader :klass, :loaded
|
14
|
-
attr_accessor :
|
13
|
+
attr_accessor :options, :count_field, :includes_values, :eager_load_values, :preload_values,
|
15
14
|
:select_values, :group_values, :order_values, :reorder_flag, :joins_values, :where_values, :having_values,
|
16
|
-
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value
|
15
|
+
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value, :page_value, :per_value
|
17
16
|
alias :loaded? :loaded
|
18
|
-
|
19
|
-
def build_where(opts, other = [])
|
17
|
+
|
18
|
+
def build_where(opts, other = [])#TODO OpenERP domain is more than just the intersection of restrictions
|
20
19
|
case opts
|
21
|
-
when Array
|
20
|
+
when Array || '|' || '&'
|
22
21
|
[opts]
|
23
22
|
when Hash
|
24
23
|
opts.keys.map {|key|["#{key}", "=", opts[key]]}
|
@@ -27,7 +26,11 @@ module Ooor
|
|
27
26
|
|
28
27
|
def where(opts, *rest)
|
29
28
|
relation = clone
|
30
|
-
|
29
|
+
if opts.is_a?(Array) && opts.any? {|e| e.is_a? Array}
|
30
|
+
relation.where_values = opts
|
31
|
+
else
|
32
|
+
relation.where_values += build_where(opts, rest) unless opts.blank?
|
33
|
+
end
|
31
34
|
relation
|
32
35
|
end
|
33
36
|
|
@@ -60,14 +63,13 @@ module Ooor
|
|
60
63
|
calculate(:count, column_name, options)
|
61
64
|
end
|
62
65
|
|
63
|
-
def initialize(klass)
|
66
|
+
def initialize(klass, options={})
|
64
67
|
@klass = klass
|
65
68
|
@where_values = []
|
66
69
|
@loaded = false
|
67
|
-
@
|
70
|
+
@options = options
|
68
71
|
@count_field = false
|
69
|
-
@
|
70
|
-
@offset_value = false
|
72
|
+
@offset_value = 0
|
71
73
|
@order_values = []
|
72
74
|
end
|
73
75
|
|
@@ -93,24 +95,61 @@ module Ooor
|
|
93
95
|
self
|
94
96
|
end
|
95
97
|
|
98
|
+
def apply_finder_options(options)
|
99
|
+
relation = clone
|
100
|
+
relation.options = options #TODO this may be too simplified for chainability, merge smartly instead?
|
101
|
+
relation
|
102
|
+
end
|
103
|
+
|
104
|
+
def where_values
|
105
|
+
if @options && @options[:domain]
|
106
|
+
@options[:domain]
|
107
|
+
else
|
108
|
+
@where_values
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
96
112
|
# A convenience wrapper for <tt>find(:all, *args)</tt>. You can pass in all the
|
97
113
|
# same arguments to this method as you can to <tt>find(:all)</tt>.
|
98
114
|
def all(*args)
|
99
|
-
|
100
|
-
to_a
|
115
|
+
args.any? ? apply_finder_options(args.first).to_a : to_a
|
101
116
|
end
|
102
117
|
|
103
118
|
def to_a
|
104
|
-
|
105
|
-
|
106
|
-
search_order = false
|
119
|
+
if loaded?
|
120
|
+
@records
|
107
121
|
else
|
108
|
-
|
122
|
+
if @order_values.empty?
|
123
|
+
search_order = false
|
124
|
+
else
|
125
|
+
search_order = @order_values.join(", ")
|
126
|
+
end
|
127
|
+
|
128
|
+
if @options && @options[:name_search]
|
129
|
+
name_search = @klass.name_search(@options[:name_search], where_values, 'ilike', @options[:context], @limit_value)
|
130
|
+
@records = name_search.map do |tuple|
|
131
|
+
r = @klass.new({name: tuple[1]}, [])
|
132
|
+
r.id = tuple[0]
|
133
|
+
r #TODO load the fields optionally
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if @per_value && @page_value
|
137
|
+
offset = @per_value * @page_value
|
138
|
+
limit = @per_value
|
139
|
+
else
|
140
|
+
offset = @offset_value
|
141
|
+
limit = @limit_value || false
|
142
|
+
end
|
143
|
+
@loaded = true
|
144
|
+
opts = @options.merge({
|
145
|
+
domain: where_values,
|
146
|
+
offset: offset,
|
147
|
+
limit: limit,
|
148
|
+
order: search_order,
|
149
|
+
})
|
150
|
+
@records = @klass.find(:all, opts)
|
151
|
+
end
|
109
152
|
end
|
110
|
-
ids = @klass.rpc_execute('search', @where_values, @offset_value, @limit_value, search_order, @context, @count_field)
|
111
|
-
@records = @klass.find(ids)
|
112
|
-
@loaded = true
|
113
|
-
@records
|
114
153
|
end
|
115
154
|
|
116
155
|
def eager_loading?
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Ooor
|
4
|
+
module FinderMethods
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def find(*arguments)
|
9
|
+
if arguments.size == 1 &&
|
10
|
+
arguments[0].is_a?(Hash) ||
|
11
|
+
(arguments[0].is_a?(Array) && !([arguments[0][1]] & Ooor::TypeCasting::OPERATORS).empty?)
|
12
|
+
find_single(nil, {domain: arguments[0]})
|
13
|
+
else
|
14
|
+
find_dispatch(*arguments)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def find_dispatch(*arguments)
|
20
|
+
scope = arguments.slice!(0)
|
21
|
+
options = arguments.slice!(0) || {}
|
22
|
+
if (!scope.is_a?(Array) && !options.is_a?(Hash))
|
23
|
+
scope = [scope] + [options] + arguments
|
24
|
+
options = {}
|
25
|
+
end
|
26
|
+
case scope
|
27
|
+
when :all then find_single(nil, options)
|
28
|
+
when :first then find_first_or_last(options)
|
29
|
+
when :last then find_first_or_last(options, "DESC")
|
30
|
+
when :one then find_one(options)
|
31
|
+
else find_single(scope, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_first_or_last(options, ordering = "ASC")
|
36
|
+
options[:order] ||= "id #{ordering}"
|
37
|
+
options[:limit] = 1
|
38
|
+
find_single(nil, options)[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
#actually finds many resources specified with scope = ids_array
|
42
|
+
def find_single(scope, options)
|
43
|
+
context = options[:context] || {}
|
44
|
+
reload_fields_definition(false, context)
|
45
|
+
fields = options[:fields] || options[:only] || fast_fields(options)
|
46
|
+
fields += options[:include] if options[:include]
|
47
|
+
|
48
|
+
if scope
|
49
|
+
is_collection, records = read_scope(context, fields, scope)
|
50
|
+
else
|
51
|
+
is_collection, records = read_domain(context, fields, options)
|
52
|
+
end
|
53
|
+
active_resources = []
|
54
|
+
records.each { |record| active_resources << new(record, [], context, true)}
|
55
|
+
if is_collection
|
56
|
+
active_resources
|
57
|
+
else
|
58
|
+
active_resources[0]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_scope(context, fields, scope)
|
63
|
+
if scope.is_a? Array
|
64
|
+
is_collection = true
|
65
|
+
else
|
66
|
+
scope = [scope]
|
67
|
+
is_collection = false
|
68
|
+
end
|
69
|
+
scope.map! { |item| item_to_id(item, context) }.reject! {|item| !item}
|
70
|
+
records = rpc_execute('read', scope, fields, context.dup)
|
71
|
+
records.sort_by! {|r| scope.index(r["id"])} if @connection.config[:force_xml_rpc]
|
72
|
+
return is_collection, records
|
73
|
+
end
|
74
|
+
|
75
|
+
def read_domain(context, fields, options)
|
76
|
+
if @connection.config[:force_xml_rpc]
|
77
|
+
domain = to_openerp_domain(options[:domain] || options[:conditions] || [])
|
78
|
+
ids = rpc_execute('search', domain, options[:offset] || 0, options[:limit] || false, options[:order] || false, context.dup)
|
79
|
+
records = rpc_execute('read', ids, fields, context.dup)
|
80
|
+
else
|
81
|
+
domain = to_openerp_domain(options[:domain] || options[:conditions] || [])
|
82
|
+
response = object_service(:search_read, openerp_model, 'search_read', {
|
83
|
+
fields: fields,
|
84
|
+
offset: options[:offset] || 0,
|
85
|
+
limit: options[:limit] || false,
|
86
|
+
domain: domain,
|
87
|
+
sort: options[:order] || false,
|
88
|
+
context: context
|
89
|
+
})
|
90
|
+
records = response["records"]
|
91
|
+
end
|
92
|
+
return true, records
|
93
|
+
end
|
94
|
+
|
95
|
+
def item_to_id(item, context)
|
96
|
+
if item.is_a?(String)
|
97
|
+
if item.to_i == 0#triggers ir_model_data absolute reference lookup
|
98
|
+
tab = item.split(".")
|
99
|
+
domain = [['name', '=', tab[-1]]]
|
100
|
+
domain << ['module', '=', tab[-2]] if tab[-2]
|
101
|
+
ir_model_data = const_get('ir.model.data').find(:first, domain: domain, context: context)
|
102
|
+
ir_model_data && ir_model_data.res_id && search([['id', '=', ir_model_data.res_id]], 0, false, false, context)[0]
|
103
|
+
else
|
104
|
+
item.to_i
|
105
|
+
end
|
106
|
+
else
|
107
|
+
item
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/ooor/report.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Ooor
|
4
|
+
module Report
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
#Added methods to obtain report data for a model
|
9
|
+
def report(report_name, ids, report_type='pdf', context={}) #TODO move to ReportService
|
10
|
+
context = connection.object.inject_session_context(:report, false, context)[0]
|
11
|
+
uid = @connection.config[:user_id]
|
12
|
+
pass = @connection.config[:password]
|
13
|
+
db = @connection.config[:database]
|
14
|
+
params = {model: openerp_model, id: ids[0], report_type: report_type}
|
15
|
+
connection.report.report(db, uid, pass, report_name, ids, params, context)
|
16
|
+
end
|
17
|
+
|
18
|
+
def report_get(report_id)
|
19
|
+
uid = @connection.config[:user_id]
|
20
|
+
pass = @connection.config[:password]
|
21
|
+
db = @connection.config[:database]
|
22
|
+
connection.report.report_get(db, uid, pass, report_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_report_data(report_name, ids, report_type='pdf', context={})
|
26
|
+
report_id = report(report_name, ids, report_type, context)
|
27
|
+
if report_id
|
28
|
+
state = false
|
29
|
+
attempt = 0
|
30
|
+
while not state
|
31
|
+
report = self.report_get(report_id)
|
32
|
+
state = report["state"]
|
33
|
+
attempt = 1
|
34
|
+
if not state
|
35
|
+
sleep(0.1)
|
36
|
+
attempt += 1
|
37
|
+
else
|
38
|
+
return [report["result"],report["format"]]
|
39
|
+
end
|
40
|
+
if attempt > 100
|
41
|
+
logger.debug "OOOR RPC: 'Printing Aborted!'"
|
42
|
+
break
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
logger.debug "OOOR RPC: 'report not found'"
|
47
|
+
end
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,25 +1,41 @@
|
|
1
1
|
# OOOR: OpenObject On Ruby
|
2
|
-
# Copyright (C) 2009-
|
2
|
+
# Copyright (C) 2009-TODAY Akretion LTDA (<http://www.akretion.com>).
|
3
3
|
# Author: Raphaël Valyi
|
4
4
|
# Licensed under the MIT license, see MIT-LICENSE file
|
5
5
|
|
6
6
|
module Ooor
|
7
7
|
module Serialization
|
8
8
|
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
self.include_root_in_json = false
|
13
|
+
end
|
14
|
+
|
9
15
|
def serializable_hash(options = nil)
|
10
16
|
options ||= {}
|
11
17
|
hash = super(options)
|
12
18
|
|
13
19
|
attribute_names = attributes.keys.sort
|
14
20
|
included_associations = {}
|
21
|
+
serialize_many2one(included_associations)
|
22
|
+
serialize_x_to_many(included_associations)
|
23
|
+
|
24
|
+
method_names = Array.wrap(options[:methods]).map { |n| n if respond_to?(n.to_s) }.compact
|
25
|
+
Hash[(attribute_names + method_names).map { |n| [n, send(n)] }].merge(included_associations)
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize_many2one(included_associations)
|
15
29
|
self.class.many2one_associations.keys.each do |k|
|
16
|
-
if loaded_associations[k].is_a?
|
30
|
+
if loaded_associations[k].is_a? Base
|
17
31
|
included_associations[k] = loaded_associations[k].as_json[loaded_associations[k].class.openerp_model.gsub('.', '_')]
|
18
32
|
elsif associations[k].is_a? Array
|
19
33
|
included_associations[k] = {"id" => associations[k][0], "name" => associations[k][1]}
|
20
34
|
end
|
21
35
|
end
|
36
|
+
end
|
22
37
|
|
38
|
+
def serialize_x_to_many(included_associations)
|
23
39
|
(self.class.one2many_associations.keys + self.class.many2many_associations.keys).each do |k|
|
24
40
|
if loaded_associations[k].is_a? Array
|
25
41
|
included_associations[k] = loaded_associations[k].map {|item| item.as_json[item.class.openerp_model.gsub('.', '_')]}
|
@@ -27,11 +43,7 @@ module Ooor
|
|
27
43
|
included_associations[k] = associations[k].map {|id| {"id" => id}} if associations[k]
|
28
44
|
end
|
29
45
|
end
|
30
|
-
|
31
|
-
method_names = Array.wrap(options[:methods]).map { |n| n if respond_to?(n.to_s) }.compact
|
32
|
-
Hash[(attribute_names + method_names).map { |n| [n, send(n)] }].merge(included_associations)
|
33
46
|
end
|
34
47
|
|
35
48
|
end
|
36
49
|
end
|
37
|
-
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# OOOR: OpenObject On Ruby
|
2
|
+
# Copyright (C) 2009-2013 Akretion LTDA (<http://www.akretion.com>).
|
3
|
+
# Author: Raphaël Valyi
|
4
|
+
# Licensed under the MIT license, see MIT-LICENSE file
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Ooor
|
9
|
+
autoload :InvalidSessionError, 'ooor/errors'
|
10
|
+
|
11
|
+
class Service
|
12
|
+
def initialize(session)
|
13
|
+
@session = session
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.define_service(service, methods)
|
17
|
+
methods.each do |meth|
|
18
|
+
self.instance_eval do
|
19
|
+
define_method meth do |*args|
|
20
|
+
endpoint = @session.get_client(:xml, "#{@session.base_url}/#{service.to_s.gsub('ooor_alias_', '')}") #TODO make that transport agnostic
|
21
|
+
endpoint.call(meth.gsub('ooor_alias_', ''), *args)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
class CommonService < Service
|
30
|
+
define_service(:common, %w[ir_get ir_set ir_del about ooor_alias_login logout timezone_get get_available_updates get_migration_scripts get_server_environment login_message check_connectivity about get_stats list_http_services version authenticate get_available_updates set_loglevel get_os_time get_sqlcount])
|
31
|
+
|
32
|
+
def login(db, username, password)
|
33
|
+
@session.logger.debug "OOOR login - db: #{db}, username: #{username}"
|
34
|
+
|
35
|
+
if @session.config[:force_xml_rpc]
|
36
|
+
send("ooor_alias_login", db, username, password)
|
37
|
+
else
|
38
|
+
conn = @session.get_client(:json, "#{@session.base_jsonrpc2_url}")
|
39
|
+
response = conn.post do |req|
|
40
|
+
req.url '/web/session/authenticate'
|
41
|
+
req.headers['Content-Type'] = 'application/json'
|
42
|
+
req.body = {method: 'call', params: { db: db, login: username, password: password}}.to_json
|
43
|
+
end
|
44
|
+
@session.web_session[:cookie] = response.headers["set-cookie"]
|
45
|
+
if response.status == 200
|
46
|
+
sid_part1 = @session.web_session[:cookie].split("sid=")[1]
|
47
|
+
if sid_part1
|
48
|
+
@session.web_session[:sid] = @session.web_session[:cookie].split("sid=")[1].split(";")[0] # NOTE side is required on v7 but not on v8, this enables to sniff if we are on v7
|
49
|
+
end
|
50
|
+
json_response = JSON.parse(response.body)
|
51
|
+
@session.web_session[:session_id] = json_response['result']['session_id']
|
52
|
+
user_id = json_response['result']['uid']
|
53
|
+
@session.config[:user_id] = user_id
|
54
|
+
Ooor.session_handler.register_session(@session)
|
55
|
+
user_id
|
56
|
+
else
|
57
|
+
raise Faraday::Error::ClientError.new(response.status, response)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
class DbService < Service
|
65
|
+
define_service(:db, %w[get_progress drop dump restore rename db_exist list change_admin_password list_lang server_version migrate_databases create_database duplicate_database])
|
66
|
+
|
67
|
+
def create(password=@session.config[:db_password], db_name='ooor_test', demo=true, lang='en_US', user_password=@session.config[:password] || 'admin')
|
68
|
+
@session.logger.info "creating database #{db_name} this may take a while..."
|
69
|
+
process_id = @session.get_client(:xml, @session.base_url + "/db").call("create", password, db_name, demo, lang, user_password)
|
70
|
+
sleep(2)
|
71
|
+
while get_progress(password, process_id)[0] != 1
|
72
|
+
@session.logger.info "..."
|
73
|
+
sleep(0.5)
|
74
|
+
end
|
75
|
+
@session.global_login(username: 'admin', password: user_password, database: db_name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
class ObjectService < Service
|
81
|
+
define_service(:object, %w[execute exec_workflow])
|
82
|
+
|
83
|
+
def object_service(service, obj, method, *args)
|
84
|
+
unless @session.config[:user_id]
|
85
|
+
@session.common.login(@session.config[:database], @session.config[:username], @session.config[:password])
|
86
|
+
end
|
87
|
+
args = inject_session_context(service, method, *args)
|
88
|
+
uid = @session.config[:user_id]
|
89
|
+
db = @session.config[:database]
|
90
|
+
@session.logger.debug "OOOR object service: rpc_method: #{service}, db: #{db}, uid: #{uid}, pass: #, obj: #{obj}, method: #{method}, *args: #{args.inspect}"
|
91
|
+
if @session.config[:force_xml_rpc]
|
92
|
+
pass = @session.config[:password]
|
93
|
+
send(service, db, uid, pass, obj, method, *args)
|
94
|
+
else
|
95
|
+
unless @session.web_session[:session_id]
|
96
|
+
@session.common.login(@session.config[:database], @session.config[:username], @session.config[:password])
|
97
|
+
end
|
98
|
+
json_conn = @session.get_client(:json, "#{@session.base_jsonrpc2_url}")
|
99
|
+
json_conn.oe_service(@session.web_session, service, obj, method, *args)
|
100
|
+
end
|
101
|
+
rescue InvalidSessionError
|
102
|
+
@session.config[:force_xml_rpc] = true #TODO set v6 version too
|
103
|
+
retry
|
104
|
+
rescue SessionExpiredError
|
105
|
+
@session.logger.debug "session for uid: #{uid} has expired, trying to login again"
|
106
|
+
@session.common.login(@session.config[:database], @session.config[:username], @session.config[:password])
|
107
|
+
retry
|
108
|
+
end
|
109
|
+
|
110
|
+
def inject_session_context(service, method, *args)
|
111
|
+
if service == :object && (i = Ooor.irregular_context_position(method)) && args.size >= i
|
112
|
+
c = HashWithIndifferentAccess.new(args[i])
|
113
|
+
args[i] = @session.session_context(c)
|
114
|
+
elsif args[-1].is_a? Hash #context
|
115
|
+
if args[-1][:context]
|
116
|
+
c = HashWithIndifferentAccess.new(args[-1][:context])
|
117
|
+
args[-1][:context] = @session.session_context(c)
|
118
|
+
else
|
119
|
+
c = HashWithIndifferentAccess.new(args[-1])
|
120
|
+
args[-1] = @session.session_context(c)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
args
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
class ReportService < Service
|
130
|
+
define_service(:report, %w[report report_get render_report]) #TODO make use json rpc transport too
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|