erp_tech_svcs 3.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/GPL-3-LICENSE +674 -0
- data/README.rdoc +2 -0
- data/Rakefile +30 -0
- data/app/assets/javascripts/erp_tech_svcs/application.js +9 -0
- data/app/assets/stylesheets/erp_tech_svcs/application.css +7 -0
- data/app/controllers/erp_tech_svcs/session_controller.rb +19 -0
- data/app/controllers/erp_tech_svcs/user_controller.rb +40 -0
- data/app/helpers/erp_tech_svcs/application_helper.rb +4 -0
- data/app/mailers/user_mailer.rb +16 -0
- data/app/models/audit_log.rb +60 -0
- data/app/models/audit_log_item.rb +4 -0
- data/app/models/audit_log_item_type.rb +6 -0
- data/app/models/audit_log_type.rb +24 -0
- data/app/models/capability.rb +8 -0
- data/app/models/capability_type.rb +3 -0
- data/app/models/capable_model.rb +4 -0
- data/app/models/encryption_key.rb +9 -0
- data/app/models/extensions/contact_purpose.rb +3 -0
- data/app/models/extensions/contact_type.rb +3 -0
- data/app/models/extensions/note.rb +6 -0
- data/app/models/extensions/note_type.rb +3 -0
- data/app/models/extensions/party.rb +3 -0
- data/app/models/extensions/relationship_type.rb +3 -0
- data/app/models/extensions/role_type.rb +3 -0
- data/app/models/file_asset.rb +178 -0
- data/app/models/role.rb +17 -0
- data/app/models/secured_model.rb +13 -0
- data/app/models/user.rb +33 -0
- data/app/views/layouts/application.html.erb +14 -0
- data/app/views/layouts/erp_tech_svcs/application.html.erb +14 -0
- data/app/views/user_mailer/activation_needed_email.html.erb +14 -0
- data/app/views/user_mailer/reset_password_email.html.erb +14 -0
- data/config/initializers/erp_tech_svcs.rb +7 -0
- data/config/initializers/file_support.rb +1 -0
- data/config/initializers/pdfkit.rb +18 -0
- data/config/initializers/sorcery.rb +199 -0
- data/config/routes.rb +9 -0
- data/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.rb +15 -0
- data/db/data_migrations/20111111144706_setup_audit_log_types.rb +21 -0
- data/db/migrate/20080805000010_base_tech_services.rb +247 -0
- data/db/migrate/20111109161549_add_capabilites.rb +56 -0
- data/db/migrate/upgrade/20111109161550_update_roles.rb +33 -0
- data/db/migrate/upgrade/20111109161551_update_user.rb +88 -0
- data/lib/erp_tech_svcs/application_installer.rb +102 -0
- data/lib/erp_tech_svcs/config.rb +27 -0
- data/lib/erp_tech_svcs/engine.rb +14 -0
- data/lib/erp_tech_svcs/extensions/active_record/acts_as_versioned.rb +494 -0
- data/lib/erp_tech_svcs/extensions/active_record/has_capabilities.rb +139 -0
- data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +40 -0
- data/lib/erp_tech_svcs/extensions/active_record/has_roles.rb +126 -0
- data/lib/erp_tech_svcs/extensions.rb +5 -0
- data/lib/erp_tech_svcs/file_support/aws_s3_patch.rb +3 -0
- data/lib/erp_tech_svcs/file_support/base.rb +30 -0
- data/lib/erp_tech_svcs/file_support/file_manipulator.rb +37 -0
- data/lib/erp_tech_svcs/file_support/file_system_manager.rb +167 -0
- data/lib/erp_tech_svcs/file_support/manager.rb +147 -0
- data/lib/erp_tech_svcs/file_support/paperclip_patch.rb +28 -0
- data/lib/erp_tech_svcs/file_support/railties/s3_resolver.rb +79 -0
- data/lib/erp_tech_svcs/file_support/s3_manager.rb +211 -0
- data/lib/erp_tech_svcs/file_support.rb +10 -0
- data/lib/erp_tech_svcs/sessions/delete_expired_sessions_job.rb +40 -0
- data/lib/erp_tech_svcs/sessions/delete_expired_sessions_service.rb +15 -0
- data/lib/erp_tech_svcs/utils/attachment_fu_patch.rb +15 -0
- data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +57 -0
- data/lib/erp_tech_svcs/utils/compass_logger.rb +94 -0
- data/lib/erp_tech_svcs/utils/compass_pdf.rb +72 -0
- data/lib/erp_tech_svcs/utils/default_nested_set_methods.rb +33 -0
- data/lib/erp_tech_svcs/utils/pdf_processor.rb +106 -0
- data/lib/erp_tech_svcs/version.rb +3 -0
- data/lib/erp_tech_svcs.rb +20 -0
- data/lib/tasks/erp_tech_svcs_tasks.rake +42 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +43 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +8 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/spec.rb +27 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +571 -0
- data/spec/dummy/db/spec.sqlite3 +0 -0
- data/spec/dummy/log/spec.log +2862 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/capability_type.rb +5 -0
- data/spec/factories/role.rb +5 -0
- data/spec/factories/users.rb +9 -0
- data/spec/lib/erp_tech_svcs/extensions/active_record/has_roles_spec.rb +68 -0
- data/spec/models/audit_log_spec.rb +48 -0
- data/spec/models/audit_log_type_spec.rb +9 -0
- data/spec/models/role_spec.rb +17 -0
- data/spec/models/user_spec.rb +27 -0
- data/spec/spec_helper.rb +61 -0
- metadata +273 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Paperclip
|
|
2
|
+
module Storage
|
|
3
|
+
module S3
|
|
4
|
+
def flush_writes #:nodoc:
|
|
5
|
+
@queued_for_write.each do |style, file|
|
|
6
|
+
begin
|
|
7
|
+
log("saving #{path(style)}")
|
|
8
|
+
AWS::S3::S3Object.store(path(style),
|
|
9
|
+
file,
|
|
10
|
+
bucket_name,
|
|
11
|
+
{:content_type => content_type,
|
|
12
|
+
:access => (@s3_permissions[style] || @s3_permissions[:default]),
|
|
13
|
+
}.merge(@s3_headers))
|
|
14
|
+
rescue AWS::S3::NoSuchBucket => e
|
|
15
|
+
create_bucket
|
|
16
|
+
retry
|
|
17
|
+
rescue AWS::S3::ResponseError => e
|
|
18
|
+
raise
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after_flush_writes # allows attachment to clean up temp files
|
|
23
|
+
|
|
24
|
+
@queued_for_write = {}
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module ActionView
|
|
2
|
+
class S3Resolver < PathResolver
|
|
3
|
+
def initialize(path, pattern=nil)
|
|
4
|
+
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
|
5
|
+
super(pattern)
|
|
6
|
+
@path = path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_s
|
|
10
|
+
@path.to_s
|
|
11
|
+
end
|
|
12
|
+
alias :to_path :to_s
|
|
13
|
+
|
|
14
|
+
def eql?(resolver)
|
|
15
|
+
self.class.equal?(resolver.class) && to_path == resolver.to_path
|
|
16
|
+
end
|
|
17
|
+
alias :== :eql?
|
|
18
|
+
|
|
19
|
+
def cached(key, path_info, details, locals) #:nodoc:
|
|
20
|
+
file_support = ErpTechSvcs::FileSupport::Base.new(:storage => :s3)
|
|
21
|
+
name, prefix, partial = path_info
|
|
22
|
+
locals = sort_locals(locals)
|
|
23
|
+
|
|
24
|
+
if key && caching?
|
|
25
|
+
if @cached[key][name][prefix][partial][locals].nil? or @cached[key][name][prefix][partial][locals].empty?
|
|
26
|
+
@cached[key][name][prefix][partial][locals] = decorate(yield, path_info, details, locals)
|
|
27
|
+
else
|
|
28
|
+
@cached[key][name][prefix][partial][locals].each do |template|
|
|
29
|
+
last_update = mtime(template.identifier, file_support)
|
|
30
|
+
if last_update > template.updated_at
|
|
31
|
+
@cached[key][name][prefix][partial][locals].delete_if{|item| item.identifier == template.identifier}
|
|
32
|
+
@cached[key][name][prefix][partial][locals] << build_template(template.identifier, template.virtual_path, (details[:formats] || [:html] if template.formats.empty?), file_support, template.locals)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
@cached[key][name][prefix][partial][locals]
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
fresh = decorate(yield, path_info, details, locals)
|
|
39
|
+
return fresh unless key
|
|
40
|
+
|
|
41
|
+
scope = @cached[key][name][prefix][partial]
|
|
42
|
+
cache = scope[locals]
|
|
43
|
+
mtime = cache && cache.map(&:updated_at).max
|
|
44
|
+
|
|
45
|
+
if !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime }
|
|
46
|
+
scope[locals] = fresh
|
|
47
|
+
else
|
|
48
|
+
cache
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def query(path, details, formats)
|
|
54
|
+
file_support = ErpTechSvcs::FileSupport::Base.new(:storage => :s3)
|
|
55
|
+
templates = []
|
|
56
|
+
get_dir_entries(path, file_support).each{|p|templates << build_template(p, path.virtual, formats, file_support)}
|
|
57
|
+
templates
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_dir_entries(path, file_support)
|
|
61
|
+
full_path = File.join(@path, path)
|
|
62
|
+
node = file_support.find_node(File.dirname(full_path))
|
|
63
|
+
node.nil? ? [] : node[:children].select{|child| child[:leaf]}.collect{|child| child[:id]}.select{|p|!p.scan(full_path).empty?}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def mtime(p, file_support)
|
|
67
|
+
node = file_support.find_node(p)
|
|
68
|
+
node[:last_modified]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
protected
|
|
72
|
+
|
|
73
|
+
def build_template(p, virtual_path, formats, file_support, locals=nil)
|
|
74
|
+
handler, format = extract_handler_and_format(p, formats)
|
|
75
|
+
contents, message = file_support.get_contents(p)
|
|
76
|
+
Template.new(contents, p, handler, :virtual_path => virtual_path, :format => format, :updated_at => mtime(p, file_support), :locals => locals)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'aws/s3'
|
|
3
|
+
|
|
4
|
+
module ErpTechSvcs
|
|
5
|
+
module FileSupport
|
|
6
|
+
class S3Manager < Manager
|
|
7
|
+
class << self
|
|
8
|
+
cattr_accessor :node_tree
|
|
9
|
+
|
|
10
|
+
def setup_connection
|
|
11
|
+
@@configuration = YAML::load_file(File.join(Rails.root,'config','s3.yml'))[Rails.env]
|
|
12
|
+
|
|
13
|
+
AWS::S3::Base.establish_connection!(
|
|
14
|
+
:access_key_id => @@configuration['access_key_id'],
|
|
15
|
+
:secret_access_key => @@configuration['secret_access_key']
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
@@s3_bucket = AWS::S3::Bucket.find(@@configuration['bucket'])
|
|
19
|
+
@@node_tree = build_node_tree
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reload
|
|
23
|
+
AWS::S3::Base.connected? ? (@@node_tree = build_node_tree(true)) : setup_connection
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def build_node_tree(reload=false)
|
|
27
|
+
tree_data = [{:text => @@s3_bucket.name, :leaf => false, :id => '', :children => []}]
|
|
28
|
+
objects = reload ? @@s3_bucket.objects(:reload) : @@s3_bucket.objects()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
nesting_depth = objects.collect{|object| object.key.split('/').count}.max
|
|
32
|
+
unless nesting_depth.nil?
|
|
33
|
+
levels = []
|
|
34
|
+
(1..nesting_depth).each do |i|
|
|
35
|
+
current_items = []
|
|
36
|
+
objects_this_depth = objects.collect{|object|
|
|
37
|
+
text = object.key.split('/')[i - 1]
|
|
38
|
+
path ='/' + (object.key.split('/')[0..(i-1)].join('/'))
|
|
39
|
+
if object.key.split('/').count >= i && current_items.select{|item| item[:text] == text and item[:path] == path}.empty?
|
|
40
|
+
item_hash = {:text => text, :path => path, :last_modified => object.last_modified}
|
|
41
|
+
current_items << item_hash
|
|
42
|
+
item_hash
|
|
43
|
+
end
|
|
44
|
+
}
|
|
45
|
+
objects_this_depth.delete_if{|item| (item.nil? or item[:text].nil?)}
|
|
46
|
+
levels << objects_this_depth
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
old_parents = []
|
|
50
|
+
new_parents = [tree_data[0]]
|
|
51
|
+
levels.each do |level|
|
|
52
|
+
old_parents = new_parents
|
|
53
|
+
new_parents = []
|
|
54
|
+
level.each do |item|
|
|
55
|
+
parent = old_parents.count == 1 ? old_parents.first : self.find_parent(item, old_parents)
|
|
56
|
+
path = File.join(parent[:id], item[:text])
|
|
57
|
+
child_hash = {:last_modified => item[:last_modified], :text => item[:text], :downloadPath => path, :leaf => !File.extname(item[:text]).blank?, :id => path, :children => []}
|
|
58
|
+
new_parents << child_hash
|
|
59
|
+
parent[:children] << child_hash
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
tree_data
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def buckets
|
|
69
|
+
AWS::S3::Service.buckets
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def bucket=(name)
|
|
73
|
+
@@s3_bucket = AWS::S3::Bucket.find(name)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def bucket
|
|
77
|
+
@@s3_bucket
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def root
|
|
81
|
+
''
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def update_file(path, content)
|
|
85
|
+
AWS::S3::S3Object.store(path, content, bucket.name, :access => :public_read)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def create_file(path, name, contents)
|
|
89
|
+
AWS::S3::S3Object.store(File.join(path,name), contents, @@s3_bucket.name, :access => :public_read)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def create_folder(path, name)
|
|
93
|
+
AWS::S3::S3Object.store(File.join(path,name) + "/", '', @@s3_bucket.name, :access => :public_read)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def save_move(path, new_parent_path)
|
|
97
|
+
result = nil
|
|
98
|
+
unless self.exists? path
|
|
99
|
+
message = 'File does not exists'
|
|
100
|
+
else
|
|
101
|
+
name = File.basename(path)
|
|
102
|
+
if AWS::S3::S3Object.rename path, File.join(new_parent_path,name), @@s3_bucket.name, :copy_acl => true
|
|
103
|
+
message = "#{name} was moved to #{new_parent_path} successfully"
|
|
104
|
+
result = true
|
|
105
|
+
else
|
|
106
|
+
message = "#Error renaming {old_name}"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return result, message
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def rename_file(path, name)
|
|
114
|
+
result = nil
|
|
115
|
+
old_name = File.basename(path)
|
|
116
|
+
path_pieces = path.split('/')
|
|
117
|
+
path_pieces.delete(path_pieces.last)
|
|
118
|
+
path_pieces.push(name)
|
|
119
|
+
new_path = path_pieces.join('/')
|
|
120
|
+
if AWS::S3::S3Object.rename path, new_path, @@s3_bucket.name, :copy_acl => true
|
|
121
|
+
message = "#{old_name} was renamed to #{name} successfully"
|
|
122
|
+
result = true
|
|
123
|
+
else
|
|
124
|
+
message = "#Error renaming {old_name}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
return result, message
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def delete_file(path, options={})
|
|
131
|
+
result = nil
|
|
132
|
+
message = nil
|
|
133
|
+
|
|
134
|
+
node = find_node(path)
|
|
135
|
+
|
|
136
|
+
if node[:children].empty?
|
|
137
|
+
is_directory = !node[:leaf]
|
|
138
|
+
path << '/' unless node[:leaf]
|
|
139
|
+
result = AWS::S3::S3Object.delete path, @@s3_bucket.name, :force => true
|
|
140
|
+
message = "File was deleted successfully"
|
|
141
|
+
result = true
|
|
142
|
+
elsif options[:force]
|
|
143
|
+
node[:children].each do |child|
|
|
144
|
+
delete_file(child[:id], options)
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
message = "Folder is not empty"
|
|
148
|
+
end unless node.nil?
|
|
149
|
+
|
|
150
|
+
return result, message, is_directory
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def exists?(path)
|
|
154
|
+
begin
|
|
155
|
+
path = path[1..path.length] if path.first == '/'
|
|
156
|
+
!AWS::S3::S3Object.find(path, @@s3_bucket.name).nil?
|
|
157
|
+
rescue AWS::S3::NoSuchKey
|
|
158
|
+
return false
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def get_contents(path)
|
|
163
|
+
contents = nil
|
|
164
|
+
message = nil
|
|
165
|
+
|
|
166
|
+
path = path[1..path.length]
|
|
167
|
+
begin
|
|
168
|
+
object = AWS::S3::S3Object.find path, @@s3_bucket.name
|
|
169
|
+
rescue AWS::S3::NoSuchKey => error
|
|
170
|
+
message = 'File does not exists'
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
contents = object.value.to_s if message.nil?
|
|
174
|
+
|
|
175
|
+
return contents, message
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def build_tree(starting_path, options={})
|
|
179
|
+
ErpTechSvcs::FileSupport::S3Manager.reload
|
|
180
|
+
node_tree = find_node(starting_path, options)
|
|
181
|
+
node_tree.nil? ? [] : node_tree
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def find_node(path, options={})
|
|
185
|
+
parent = if options[:file_asset_holder]
|
|
186
|
+
super
|
|
187
|
+
else
|
|
188
|
+
parent = @@node_tree.first
|
|
189
|
+
unless path.nil?
|
|
190
|
+
path_pieces = path.split('/')
|
|
191
|
+
path_pieces.each do |path_piece|
|
|
192
|
+
next if path_piece.blank?
|
|
193
|
+
parent[:children].each do |child_node|
|
|
194
|
+
if child_node[:text] == path_piece
|
|
195
|
+
parent = child_node
|
|
196
|
+
break
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
parent = nil if parent[:id] != path
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
parent
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
parent
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
end#S3Manager
|
|
210
|
+
end#FileSupport
|
|
211
|
+
end#ErpTechSvcs
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'erp_tech_svcs/file_support/base'
|
|
2
|
+
require 'erp_tech_svcs/file_support/manager'
|
|
3
|
+
require 'erp_tech_svcs/file_support/file_system_manager'
|
|
4
|
+
require 'erp_tech_svcs/file_support/s3_manager'
|
|
5
|
+
require 'erp_tech_svcs/file_support/aws_s3_patch'
|
|
6
|
+
require 'erp_tech_svcs/file_support/paperclip_patch'
|
|
7
|
+
require 'erp_tech_svcs/file_support/file_manipulator'
|
|
8
|
+
|
|
9
|
+
#path resolvers
|
|
10
|
+
require 'erp_tech_svcs/file_support/railties/s3_resolver'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module ErpTechSvcs
|
|
2
|
+
module Sessions
|
|
3
|
+
# Delayed Job to Reset Daily Assignments to Forecast
|
|
4
|
+
class DeleteExpiredSessionsJob
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@priority = 1
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def perform
|
|
11
|
+
begin
|
|
12
|
+
process_job
|
|
13
|
+
rescue => exception
|
|
14
|
+
ErpTechSvcs::Util::CompassLogger.delete_expired_sessions_job.error("An unrecoverable error has occured, the job will be rescheduled: #{exception.message} : #{exception.backtrace}")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Run once per day
|
|
18
|
+
date = Date.tomorrow
|
|
19
|
+
start_time = DateTime.civil(date.year, date.month, date.day, 2, 0, 1, -(5.0/24.0))
|
|
20
|
+
|
|
21
|
+
Delayed::Job.enqueue(DeleteExpiredSessionsJob.new(), @priority, start_time)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.schedule_job(schedule_dt)
|
|
25
|
+
Delayed::Job.enqueue(DeleteExpiredSessionsJob.new(), @priority, schedule_dt)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def process_job
|
|
29
|
+
start_time = Time.now
|
|
30
|
+
|
|
31
|
+
ErpTechSvcs::Sessions::DeleteExpiredSessionsService.new.execute
|
|
32
|
+
|
|
33
|
+
end_time = Time.now
|
|
34
|
+
|
|
35
|
+
return end_time - start_time
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end #Close DeleteExpiredSessionsJob
|
|
39
|
+
end #Close Sessions
|
|
40
|
+
end #Close ErpTechSvcs
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ErpTechSvcs
|
|
2
|
+
module Sessions
|
|
3
|
+
class DeleteExpiredSessionsService
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@session_age = 12.hours
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def execute
|
|
10
|
+
ActiveRecord::SessionStore::Session.delete_all ['updated_at < ?', @session_age.ago]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#This patch is to make the attachment_fu plugin work on Windows
|
|
2
|
+
#It is not necessary for 'nix operating systems, though it is not known
|
|
3
|
+
#to cause problems
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
class Tempfile
|
|
6
|
+
def size
|
|
7
|
+
if @tmpfile
|
|
8
|
+
@tmpfile.fsync # added this line
|
|
9
|
+
@tmpfile.flush
|
|
10
|
+
@tmpfile.stat.size
|
|
11
|
+
else
|
|
12
|
+
0
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ErpTechSvcs
|
|
2
|
+
module Utils
|
|
3
|
+
module CompassAccessNegotiator
|
|
4
|
+
|
|
5
|
+
def has_capability?(model, capability_type, resource)
|
|
6
|
+
model.user_has_capability?(capability_type.to_s, resource, self)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def with_capability(model, capability_type, resource, &block)
|
|
10
|
+
if model.user_has_capability?(capability_type.to_s, resource, self)
|
|
11
|
+
yield
|
|
12
|
+
else
|
|
13
|
+
raise ErpTechSvcs::Utils::CompassAccessNegotiator::Errors::UserDoesNotHaveCapability
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def has_access_to_widget?(widget)
|
|
18
|
+
widget.has_access?(self)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def valid_widgets(application)
|
|
22
|
+
widgets = []
|
|
23
|
+
application.widgets.each do |widget|
|
|
24
|
+
widgets << widget if self.has_access_to_widget?(widget)
|
|
25
|
+
end
|
|
26
|
+
widgets
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module Errors
|
|
30
|
+
class CapabilityDoesNotExist < StandardError
|
|
31
|
+
def to_s
|
|
32
|
+
"Capability does not exist."
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class CapabilityTypeDoesNotExist < StandardError
|
|
37
|
+
def to_s
|
|
38
|
+
"Capability type not exist."
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class CapabilityAlreadytExists < StandardError
|
|
43
|
+
def to_s
|
|
44
|
+
"Capability already exists."
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class UserDoesNotHaveCapability < StandardError
|
|
49
|
+
def to_s
|
|
50
|
+
"User does not have capability."
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end#CompassAccessNegotiator
|
|
56
|
+
end#Utils
|
|
57
|
+
end#ErpTechSvcs
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
module ErpTechSvcs
|
|
3
|
+
module Util
|
|
4
|
+
class CompassLogger
|
|
5
|
+
include Singleton
|
|
6
|
+
|
|
7
|
+
@@writers = {}
|
|
8
|
+
|
|
9
|
+
def CompassLogger.debug(msg)
|
|
10
|
+
if defined?(logger)
|
|
11
|
+
logger.debug(msg)
|
|
12
|
+
else
|
|
13
|
+
CompassLogger.app_logger()
|
|
14
|
+
@@writers["app_logger"].debug(msg)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def CompassLogger.info(msg)
|
|
19
|
+
if defined?(logger)
|
|
20
|
+
logger.info(msg)
|
|
21
|
+
else
|
|
22
|
+
CompassLogger.app_logger()
|
|
23
|
+
@@writers["app_logger"].info(msg)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def CompassLogger.warn(msg)
|
|
28
|
+
if defined?(logger)
|
|
29
|
+
logger.warn(msg)
|
|
30
|
+
else
|
|
31
|
+
CompassLogger.app_logger()
|
|
32
|
+
@@writers["app_logger"].warn(msg)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def CompassLogger.error(msg)
|
|
37
|
+
if defined?(logger)
|
|
38
|
+
logger.error(msg)
|
|
39
|
+
else
|
|
40
|
+
CompassLogger.app_logger()
|
|
41
|
+
@@writers["app_logger"].error(msg)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def CompassLogger.fatal(msg)
|
|
46
|
+
if defined?(logger)
|
|
47
|
+
logger.fatal(msg)
|
|
48
|
+
else
|
|
49
|
+
CompassLogger.app_logger()
|
|
50
|
+
@@writers["app_logger"].fatal(msg)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def CompassLogger.stdout(msg)
|
|
55
|
+
if CompassLogger.log_level() == 0
|
|
56
|
+
puts msg
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def CompassLogger.method_missing(method, *args, &block)
|
|
61
|
+
unless @@writers.has_key?(method)
|
|
62
|
+
logger = Logger.new(CompassLogger.log_path(method))
|
|
63
|
+
logger.level = CompassLogger.log_level()
|
|
64
|
+
@@writers[method] = logger
|
|
65
|
+
end
|
|
66
|
+
@@writers[method]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def CompassLogger.app_logger()
|
|
70
|
+
path = "#{Rails.root}/log/#{Rails.env rescue 'rake'}.log"
|
|
71
|
+
unless RUBY_PLATFORM =~ /(:?mswin|mingw|darwin)/
|
|
72
|
+
path = "/var/log/rails/#{Rails.env rescue 'rake'}.log"
|
|
73
|
+
end
|
|
74
|
+
unless @@writers.has_key?("app_logger")
|
|
75
|
+
logger = Logger.new(path)
|
|
76
|
+
logger.level = CompassLogger.log_level()
|
|
77
|
+
@@writers["app_logger"] = logger
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def CompassLogger.log_level()
|
|
82
|
+
ActiveRecord::Base.logger.level rescue Logger::DEBUG
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def CompassLogger.log_path(method)
|
|
86
|
+
if RUBY_PLATFORM =~ /(:?mswin|mingw|darwin)/
|
|
87
|
+
return "#{Rails.root}/log/#{Rails.env rescue ''}_#{method}.log"
|
|
88
|
+
else
|
|
89
|
+
return "/var/log/rails/#{Rails.env rescue ''}_#{method}.log"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module CompassPDF
|
|
2
|
+
|
|
3
|
+
class PDFXLate
|
|
4
|
+
|
|
5
|
+
# pdf xlator utility
|
|
6
|
+
attr_accessor :pdf_util
|
|
7
|
+
|
|
8
|
+
# options to the pdf xlator
|
|
9
|
+
attr_accessor :util_options
|
|
10
|
+
|
|
11
|
+
# temp file that contains the html to be xlated
|
|
12
|
+
attr_accessor :html_filename
|
|
13
|
+
|
|
14
|
+
# output option
|
|
15
|
+
attr_accessor :pdf_out_option
|
|
16
|
+
|
|
17
|
+
# pdf file generated
|
|
18
|
+
attr_accessor :pdf_filename
|
|
19
|
+
|
|
20
|
+
# shell command/s to invoke the xlation process and return the results
|
|
21
|
+
attr_accessor :command
|
|
22
|
+
|
|
23
|
+
def initialize(options={})
|
|
24
|
+
# lets default to using prince, we're big spenders
|
|
25
|
+
#options = {:pdf_util => "#{PDF_COMMAND}",:util_options => '--input=html --media=screen --baseurl=http://localhost:3000', :pdf_out_option => '-o '}.merge(options)
|
|
26
|
+
|
|
27
|
+
# lets use wkhtmltopdf, we're cheap
|
|
28
|
+
#options = {:pdf_util => "#{PDF_COMMAND}",:util_options => '', :pdf_out_option => ""}.merge(options)
|
|
29
|
+
options.each{ |k,v| self.send("#{k}=".to_sym, v) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def command
|
|
33
|
+
# TODO: send this to a background process to do the xlate
|
|
34
|
+
# TODO: add timeout
|
|
35
|
+
# Could bog down the rails process
|
|
36
|
+
# cmd = "#{@pdf_util} #{@util_options} #{self.html_filename} -o #{self.pdf_out} &>/dev/null;"
|
|
37
|
+
cmd = "#{@pdf_util} #{@util_options} #{self.html_filename} #{self.pdf_out_option} #{pdf_filename}"
|
|
38
|
+
# cmd << "cat #{self.pdf_filename}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def html_filename=(file_name)
|
|
42
|
+
@fname = file_name
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def html_filename
|
|
46
|
+
@fname ||= "tmp/html_output_#{Digest::MD5.hexdigest(Time.now.to_i.to_s)}.html"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def pdf_filename
|
|
50
|
+
html_filename.sub(/\.html/, '.pdf')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def write_html_response(body)
|
|
54
|
+
File.open("#{html_filename}", "w") { |f| f.puts(body) }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_pdf_generated
|
|
58
|
+
pdf_contents = nil
|
|
59
|
+
File.open("#{pdf_filename}",'rb') do |f|
|
|
60
|
+
pdf_contents = f.read
|
|
61
|
+
end
|
|
62
|
+
pdf_contents
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def invoke
|
|
66
|
+
puts "invoking command #{self.command}"
|
|
67
|
+
`#{self.command}`
|
|
68
|
+
#TODO: cleanup temp files, etc.
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ErpTechSvcs
|
|
2
|
+
module Utils
|
|
3
|
+
module DefaultNestedSetMethods
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.extend(ClassMethods)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def to_label
|
|
9
|
+
"#{description}"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def leaf
|
|
13
|
+
children.size == 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_json_with_leaf(options = {})
|
|
17
|
+
self.to_json_without_leaf(options.merge(:methods => :leaf))
|
|
18
|
+
end
|
|
19
|
+
alias_method_chain :to_json, :leaf
|
|
20
|
+
|
|
21
|
+
module ClassMethods
|
|
22
|
+
def find_roots
|
|
23
|
+
where("parent_id = nil")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def find_children(parent_id = nil)
|
|
27
|
+
parent_id.to_i == 0 ? self.roots : find(parent_id).children
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|