erp_tech_svcs 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README.md +62 -0
  2. data/app/controllers/erp_tech_svcs/session_controller.rb +12 -7
  3. data/app/controllers/erp_tech_svcs/user_controller.rb +35 -14
  4. data/app/mailers/user_mailer.rb +8 -2
  5. data/app/models/attribute_type.rb +30 -0
  6. data/app/models/attribute_value.rb +41 -0
  7. data/app/models/file_asset.rb +58 -12
  8. data/app/models/secured_model.rb +4 -2
  9. data/app/models/user.rb +9 -7
  10. data/app/validators/password_strength_validator.rb +8 -0
  11. data/app/views/user_mailer/activation_needed_email.html.erb +1 -1
  12. data/config/initializers/erp_tech_svcs.rb +6 -1
  13. data/config/initializers/file_support.rb +9 -1
  14. data/config/initializers/sorcery.rb +3 -3
  15. data/config/routes.rb +2 -1
  16. data/db/data_migrations/20120109173616_create_download_capability_type.rb +13 -0
  17. data/db/migrate/20080805000010_base_tech_services.rb +12 -5
  18. data/db/migrate/20111117183144_create_has_attribute_tables.rb +38 -0
  19. data/db/migrate/{20111109161549_add_capabilites.rb → upgrade/20111109161549_add_capabilites.rb} +0 -0
  20. data/db/migrate/upgrade/20120329161641_add_file_asset_indexes.rb +22 -0
  21. data/lib/erp_tech_svcs/config.rb +20 -2
  22. data/lib/erp_tech_svcs/engine.rb +6 -0
  23. data/lib/erp_tech_svcs/extensions/active_record/has_capabilities.rb +18 -6
  24. data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +16 -3
  25. data/lib/erp_tech_svcs/extensions/active_record/has_relational_dynamic_attributes.rb +99 -0
  26. data/lib/erp_tech_svcs/extensions/active_record/has_roles.rb +3 -0
  27. data/lib/erp_tech_svcs/extensions/sorcery/user_activation.rb +13 -0
  28. data/lib/erp_tech_svcs/extensions.rb +5 -1
  29. data/lib/erp_tech_svcs/file_support/base.rb +1 -3
  30. data/lib/erp_tech_svcs/file_support/file_system_manager.rb +21 -19
  31. data/lib/erp_tech_svcs/file_support/manager.rb +29 -9
  32. data/lib/erp_tech_svcs/file_support/paperclip_patch.rb +13 -9
  33. data/lib/erp_tech_svcs/file_support/railties/s3_resolver.rb +24 -4
  34. data/lib/erp_tech_svcs/file_support/s3_manager.rb +133 -86
  35. data/lib/erp_tech_svcs/file_support.rb +5 -3
  36. data/lib/erp_tech_svcs/sms_wrapper/clickatell.rb +25 -0
  37. data/lib/erp_tech_svcs/sms_wrapper.rb +1 -0
  38. data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +12 -6
  39. data/lib/erp_tech_svcs/utils/default_nested_set_methods.rb +14 -1
  40. data/lib/erp_tech_svcs/version.rb +7 -1
  41. data/lib/erp_tech_svcs.rb +4 -2
  42. data/lib/tasks/erp_tech_svcs_tasks.rake +1 -1
  43. data/spec/controllers/erp_tech_svcs/user_controller_spec.rb +0 -0
  44. data/spec/lib/file_support/file_system_manager_spec.rb +82 -0
  45. data/spec/lib/file_support/s3_manager_spec.rb +92 -0
  46. data/spec/models/file_asset_spec.rb +78 -0
  47. data/spec/models/secured_model_spec.rb +22 -0
  48. data/spec/spec_helper.rb +9 -7
  49. metadata +146 -133
  50. data/README.rdoc +0 -2
  51. data/lib/erp_tech_svcs/file_support/aws_s3_patch.rb +0 -3
  52. data/spec/dummy/db/schema.rb +0 -571
  53. data/spec/dummy/db/spec.sqlite3 +0 -0
  54. data/spec/dummy/log/spec.log +0 -2862
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ #ErpTechSvcs
2
+
3
+ This engine is implemented with the premise that services like logging, tracing and encryption would likely already exist in many organizations, so they are factored here so they can easily be re-implemented. There are default implementations here, and we track several excellent Rails projects as potential implementations of services like security and content/digital asset mgt.
4
+
5
+ ##Initializer Options
6
+
7
+ - installation\_domain
8
+ - The domain that your Compass AE instance is installed at.
9
+ - Default : 'localhost:3000'
10
+ - login\_url
11
+ - Path to the login page.
12
+ - Default : '/erp_app/login'
13
+ - email\_notifications\_from
14
+ - From address for email notifications.
15
+ - Default : 'notifications@noreply.com'
16
+ - max\_file\_size\_in\_mb
17
+ - Max allowed file upload size in mega bytes.
18
+ - Default : 5
19
+ - file\_assets\_location
20
+ - Where you want file_assets to be saved to.
21
+ - Default : file_assets
22
+ - file\_storage
23
+ - File storage to use either s3 or filesystem.
24
+ - Default : :filesystem
25
+
26
+ ### Override Initializer
27
+
28
+ To override these settings simple create a erp_tech_svcs.rb file in your initializers and override the config options you want
29
+
30
+ Rails.application.config.erp_tech_svcs.configure do |config|
31
+ config.installation_domain = 'localhost:3000'
32
+ config.login_url = '/erp_app/login'
33
+ config.email_notifications_from = 'notifications@noreply.com'
34
+ config.max_file_size_in_mb = 5
35
+ config.file_assets_location = 'file_assets'
36
+ config.file_storage = :filesystem
37
+ end
38
+ Rails.application.config.erp_tech_svcs.configure!
39
+
40
+ ##Notes
41
+
42
+ We use [pdfkit](https://github.com/jdpace/PDFKit) and there is an initializer in erp\_tech\_svcs to set it up with some defaults. You will need to create your
43
+ own initializer to overwrite this if you have wkhtmltopdf in another location
44
+
45
+ # config/initializers/pdfkit.rb
46
+ PDFKit.configure do |config|
47
+ if RUBY_PLATFORM =~ /(:?mswin|mingw)/
48
+ # set path to wkhtmltopdf on windows here
49
+ config.wkhtmltopdf = '/opt/local/bin/wkhtmltopdf'
50
+ else
51
+ config.wkhtmltopdf = '/opt/local/bin/wkhtmltopdf'
52
+ end
53
+
54
+ config.default_options = {
55
+ :page_size => 'Letter',
56
+ :print_media_type => true,
57
+ :disable_smart_shrinking => true,
58
+ :dpi => 300,
59
+ :no_background => true
60
+ # :use_xserver => true
61
+ }
62
+ end
@@ -1,13 +1,18 @@
1
1
  module ErpTechSvcs
2
2
  class SessionController < ActionController::Base
3
3
  def create
4
- if login(params[:login],params[:password])
5
- request.xhr? ? (render :json => {:success => true}) : (redirect_to params[:login_to])
6
- else
7
- message = "Login failed. Try again"
8
- flash[:notice] = message
9
- request.xhr? ? (render :json => {:success => false, :errors => {:reason => message}}) : (render :text => message)
10
- end
4
+ last_login_at = nil
5
+ potential_user = User.where('username = ? or email = ?', params[:login], params[:login]).first
6
+ last_login_at = potential_user.last_login_at unless potential_user.nil?
7
+ if login(params[:login],params[:password])
8
+ login_to = last_login_at.nil? ? params[:first_login_to] : params[:login_to]
9
+ login_to = login_to || params[:login_to]
10
+ request.xhr? ? (render :json => {:success => true, :login_to => login_to}) : (redirect_to login_to)
11
+ else
12
+ message = "Login failed. Try again"
13
+ flash[:notice] = message
14
+ request.xhr? ? (render :json => {:success => false, :errors => {:reason => message}}) : (render :text => message)
15
+ end
11
16
  end
12
17
 
13
18
  def destroy
@@ -10,31 +10,52 @@ module ErpTechSvcs
10
10
  end
11
11
  end
12
12
 
13
- def reset_password
14
- begin
15
- login_url = params[:login_url].blank? ? ErpTechSvcs::Config.login_url : params[:login_url]
16
- if user = (User.find_by_email(params[:login]) || User.find_by_username(params[:login]))
17
- new_password = Sorcery::Model::TemporaryToken.generate_random_token
18
- user.password_confirmation = new_password
19
- if user.change_password!(new_password)
20
- user.add_instance_attribute(:login_url,login_url)
21
- user.deliver_reset_password_instructions!
22
- message = "Password has been reset. An email has been sent with further instructions to #{user.email}."
13
+ def update_password
14
+ if user = User.authenticate(current_user.username, params[:old_password])
15
+ user.password_confirmation = params[:password_confirmation]
16
+ if user.change_password!(params[:password])
23
17
  success = true
24
18
  else
25
- message = "Error re-setting password."
19
+ #### validation failed ####
20
+ message = user.errors.full_messages
26
21
  success = false
27
22
  end
28
23
  else
29
- message = "Invalid email address."
24
+ message = "Invalid current password."
30
25
  success = false
31
26
  end
32
- render :json => {:success => success,:message => message}
27
+
28
+ request.xhr? ? (render :json => {:success => success, :message => message}) : (render :text => message)
29
+ end
30
+
31
+ def reset_password
32
+ begin
33
+ login_url = params[:login_url].blank? ? ErpTechSvcs::Config.login_url : params[:login_url]
34
+ if user = (User.find_by_email(params[:login]) || User.find_by_username(params[:login]))
35
+ new_password = Sorcery::Model::TemporaryToken.generate_random_token
36
+ user.password_confirmation = new_password
37
+ if user.change_password!(new_password)
38
+ user.add_instance_attribute(:login_url,login_url)
39
+ user.add_instance_attribute(:domain, params[:domain])
40
+ user.deliver_reset_password_instructions!
41
+ message = "Password has been reset. An email has been sent with further instructions to #{user.email}."
42
+ success = true
43
+ else
44
+ message = "Error re-setting password."
45
+ success = false
46
+ end
47
+ else
48
+ message = "Invalid email address."
49
+ success = false
50
+ end
51
+ render :json => {:success => success,:message => message}
33
52
  rescue Exception=>ex
34
53
  logger.error ex.message
35
54
  logger.error ex.backtrace
36
55
  render :json => {:success => false,:message => 'Error sending email.'}
37
56
  end
38
57
  end
58
+
59
+
39
60
  end#UserController
40
- end#ErpTechSvcs
61
+ end#ErpTechSvcs
@@ -3,14 +3,20 @@ class UserMailer < ActionMailer::Base
3
3
 
4
4
  def activation_needed_email(user)
5
5
  @user = user
6
- @url = "#{ErpTechSvcs::Config.installation_domain}/users/activate/#{user.activation_token}"
6
+ @url = "#{get_domain(user.instance_attributes[:domain])}/users/activate/#{user.activation_token}"
7
7
  @url << "?login_url=#{@user.instance_attributes[:login_url]}" unless @user.instance_attributes[:login_url].nil?
8
8
  mail(:to => user.email, :subject => "An account has been created and needs activation")
9
9
  end
10
10
 
11
11
  def reset_password_email(user)
12
12
  @user = user
13
- @url = "#{ErpTechSvcs::Config.installation_domain}#{@user.instance_attributes[:login_url]}"
13
+ @url = "#{get_domain(user.instance_attributes[:domain])}#{@user.instance_attributes[:login_url]}"
14
14
  mail(:to => user.email, :subject => "Your password has been reset")
15
15
  end
16
+
17
+ def get_domain(domain)
18
+ domain = domain || ErpTechSvcs::Config.installation_domain
19
+ domain = "http://#{domain}" if domain.index('http').nil?
20
+ domain
21
+ end
16
22
  end
@@ -0,0 +1,30 @@
1
+ class AttributeType < ActiveRecord::Base
2
+ has_many :attribute_values, :dependent => :destroy
3
+
4
+ validates_uniqueness_of :internal_identifier
5
+ validates :description, :presence => true
6
+
7
+ before_save :update_iid
8
+
9
+ def values_by_date_range(start_date, end_date)
10
+ raise "attribute_type does not have a data_type of Date" unless self.data_type == "Date"
11
+
12
+ attribute_values = self.attribute_values
13
+ attribute_values.each do |attribute_value|
14
+ unless attribute_value.value_as_date >= start_date and attribute_value.value_as_date <= end_date
15
+ attribute_values.delete(attribute_value)
16
+ end
17
+ end
18
+
19
+ attribute_values
20
+ end
21
+
22
+ def self.find_by_iid_with_description(description)
23
+ iid = description.strip.underscore.gsub(/\s+/,"_")
24
+ AttributeType.find_by_internal_identifier iid
25
+ end
26
+
27
+ def update_iid
28
+ self.internal_identifier = self.description.strip.underscore.gsub(/\s+/,"_")
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ class AttributeValue < ActiveRecord::Base
2
+ belongs_to :attributed_record, :polymorphic => true
3
+ belongs_to :attribute_type
4
+
5
+ validates_format_of :value, :with => /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/, :if => :is_date?
6
+ before_destroy :destroy_attribute_types_without_values
7
+
8
+ def is_date?
9
+ self.attribute_type.data_type == 'Date' ? true : false
10
+ end
11
+
12
+ def value_as_data_type
13
+ data_type = self.attribute_type.data_type
14
+
15
+ case data_type
16
+ when "Date"
17
+ self.value.to_date
18
+ when "Boolean"
19
+ self.value == "true" ? true : false
20
+ when "Int"
21
+ self.value.to_i
22
+ when "Float"
23
+ self.value.to_f
24
+ else
25
+ self.value
26
+ end
27
+ end
28
+
29
+ def value_as_date
30
+ if self.is_date?
31
+ self.value.to_date
32
+ else
33
+ raise "value is not a Date or is not properly formated"
34
+ end
35
+ end
36
+
37
+ def destroy_attribute_types_without_values
38
+ self.attribute_type.destroy unless self.attribute_type.attribute_values.count > 1
39
+ end
40
+
41
+ end
@@ -1,15 +1,31 @@
1
1
  require 'fileutils'
2
2
 
3
3
  Paperclip.interpolates(:file_path){|data, style|
4
- case ErpTechSvcs::FileSupport.options[:storage]
4
+ case Rails.application.config.erp_tech_svcs.file_storage
5
5
  when :filesystem
6
- File.join(Rails.root,'public',data.instance.directory,data.instance.name)
6
+ file_support = ErpTechSvcs::FileSupport::Base.new
7
+ File.join(file_support.root,data.instance.directory,data.instance.name)
7
8
  when :s3
8
9
  File.join(data.instance.directory,data.instance.name)
9
10
  end
10
11
  }
11
12
 
12
- Paperclip.interpolates(:file_url){|data, style|File.join(data.instance.directory,data.instance.name)}
13
+ Paperclip.interpolates(:file_url){|data, style|
14
+ url = File.join(data.instance.directory, data.instance.name)
15
+ case Rails.application.config.erp_tech_svcs.file_storage
16
+ when :filesystem
17
+ #if public is at the front of this path and we are using file_system remove it
18
+ dir_pieces = url.split('/')
19
+ unless dir_pieces[1] == 'public'
20
+ "/download/#{data.instance.name}?path=#{dir_pieces.delete_if{|name| name == data.instance.name}.join('/')}"
21
+ else
22
+ dir_pieces.delete_at(1) if dir_pieces[1] == 'public'
23
+ dir_pieces.join('/')
24
+ end
25
+ when :s3
26
+ url
27
+ end
28
+ }
13
29
 
14
30
  class FileAsset < ActiveRecord::Base
15
31
  if respond_to?(:class_attribute)
@@ -28,9 +44,13 @@ class FileAsset < ActiveRecord::Base
28
44
  belongs_to :file_asset_holder, :polymorphic => true
29
45
  instantiates_with_sti
30
46
 
47
+ has_capabilities
48
+
31
49
  #paperclip
32
50
  has_attached_file :data,
33
- :storage => ErpTechSvcs::FileSupport.options[:storage],
51
+ :storage => Rails.application.config.erp_tech_svcs.file_storage,
52
+ :s3_protocol => Rails.application.config.erp_tech_svcs.s3_protocol,
53
+ :s3_permissions => :public_read,
34
54
  :s3_credentials => "#{Rails.root}/config/s3.yml",
35
55
  :path => ":file_path",
36
56
  :url => ":file_url",
@@ -59,11 +79,13 @@ class FileAsset < ActiveRecord::Base
59
79
  end
60
80
 
61
81
  def type_by_extension(extension)
62
- all_subclasses.detect{ |k| k.valid_extensions.include?(extension) }
82
+ klass = all_subclasses.detect{ |k| k.valid_extensions.include?(extension) }
83
+ klass = TextFile if klass.nil?
84
+ klass
63
85
  end
64
86
 
65
87
  def validate_extension(data, file)
66
- if file.name && !file.class.valid_extensions.include?(::File.extname(file.name))
88
+ if file.name && !file.class.valid_extensions.include?(File.extname(file.name))
67
89
  types = all_valid_extensions.map{ |type| type.gsub(/^\./, '') }.join(', ')
68
90
  "#{file.name} is not a valid file type. Valid file types are #{types}."
69
91
  end
@@ -92,9 +114,12 @@ class FileAsset < ActiveRecord::Base
92
114
  base_path ||= data.original_filename if data.respond_to?(:original_filename)
93
115
 
94
116
  directory, name = FileAsset.split_path(base_path) if base_path and name.blank?
95
- directory.gsub!(File.join(Rails.root,'public'),'')
117
+ directory.gsub!(Rails.root.to_s,'')
96
118
 
97
119
  @type ||= FileAsset.type_for(name) if name
120
+ @type = "TextFile" if @type.nil?
121
+ @name = name
122
+
98
123
  data = StringIO.new(data) if data.is_a?(String)
99
124
 
100
125
  super attributes.merge(:directory => directory, :name => name, :data => data)
@@ -115,7 +140,7 @@ class FileAsset < ActiveRecord::Base
115
140
  def set_content_type
116
141
  unless @type.nil?
117
142
  klass = @type.constantize
118
- content_type = klass == Image ? "image/#{self.extname.downcase}" : klass.content_type
143
+ content_type = klass == Image ? "image/#{File.extname(@name).gsub(/^\.+/, '')}" : klass.content_type
119
144
  self.data.instance_write(:content_type, content_type)
120
145
  end
121
146
  end
@@ -124,11 +149,20 @@ class FileAsset < ActiveRecord::Base
124
149
  update_attribute :data_file_name, name if data_file_name != name
125
150
  end
126
151
 
152
+ def get_contents
153
+ file_support = ErpTechSvcs::FileSupport::Base.new(:storage => Rails.application.config.erp_tech_svcs.file_storage)
154
+ file_support.get_contents(File.join(self.directory,self.data_file_name))
155
+ end
156
+
127
157
  def move(new_parent_path)
128
- file_support = ErpTechSvcs::FileSupport::Base.new(:storage => ErpTechSvcs::FileSupport.options[:storage])
129
- file_support.save_move(File.join(self.directory,self.name), new_parent_path)
130
- self.directory = new_parent_path
131
- self.save
158
+ file_support = ErpTechSvcs::FileSupport::Base.new(:storage => Rails.application.config.erp_tech_svcs.file_storage)
159
+ result, message = file_support.save_move(File.join(self.directory, self.name), new_parent_path)
160
+ if result
161
+ self.directory = new_parent_path.gsub(Regexp.new(Rails.root.to_s), '') # strip rails root from new_parent_path, we want relative path
162
+ self.save
163
+ end
164
+
165
+ return result, message
132
166
  end
133
167
 
134
168
  end
@@ -176,3 +210,15 @@ class HtmlFile < TextFile
176
210
  self.content_type = 'text/html'
177
211
  self.valid_extensions = %w(.html)
178
212
  end
213
+
214
+ class Pdf < TextFile
215
+ self.file_type = :pdf
216
+ self.content_type = 'application/pdf'
217
+ self.valid_extensions = %w(.pdf)
218
+ end
219
+
220
+ class Swf < TextFile
221
+ self.file_type = :swf
222
+ self.content_type = 'application/x-shockwave-flash'
223
+ self.valid_extensions = %w(.swf)
224
+ end
@@ -4,9 +4,11 @@ class SecuredModel < ActiveRecord::Base
4
4
 
5
5
  class << self
6
6
  def find_models_by_klass_and_role(model_klass, role)
7
- role = Role.iid(role) if role.is_a? String
7
+ role = Role.iid(role) if role.is_a? String
8
+ model_klass = model_klass.to_s unless model_klass.is_a? String
8
9
 
9
- SecuredModel.joins(['join roles_secured_models on roles_secured_models.secured_model_id = secured_models.id']).where('secured_record_type = ? and role_id = ?',model_klass, role.id).collect(&:secured_record)
10
+ SecuredModel.joins(['join roles_secured_models on roles_secured_models.secured_model_id = secured_models.id'])
11
+ .where('secured_record_type = ? and role_id = ?', model_klass, role.id).collect(&:secured_record)
10
12
  end
11
13
  end
12
14
 
data/app/models/user.rb CHANGED
@@ -1,24 +1,26 @@
1
1
  class User < ActiveRecord::Base
2
+ include ActiveModel::Validations
3
+
4
+ attr_accessor :password_validator
5
+
2
6
  has_roles
3
7
  include ErpTechSvcs::Utils::CompassAccessNegotiator
4
8
 
5
9
  belongs_to :party
6
-
10
+
7
11
  attr_accessible :email, :password, :password_confirmation
8
12
  authenticates_with_sorcery!
9
13
 
10
14
  #password validations
11
- validates_length_of :password, :minimum => 3, :message => "password must be at least 3 characters long", :if => :password
12
15
  validates_confirmation_of :password, :message => "should match confirmation", :if => :password
16
+ validates :password, :presence => true, :password_strength => true, :if => :password
13
17
 
14
18
  #email validations
15
- validates :email, :presence => {:message => 'Email cannot be blank'}
16
- validates_uniqueness_of :email
19
+ validates :email, :presence => {:message => 'Email cannot be blank'}, :uniqueness => true
17
20
  validates_format_of :email, :with => /\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/
18
21
 
19
22
  #username validations
20
- validates :email, :presence => {:message => 'Username cannot be blank'}
21
- validates_uniqueness_of :username
23
+ validates :username, :presence => {:message => 'Username cannot be blank'}, :uniqueness => true
22
24
 
23
25
  #these two methods allow us to assign instance level attributes that are not persisted. These are used for mailers
24
26
  def instance_attributes
@@ -29,5 +31,5 @@ class User < ActiveRecord::Base
29
31
  @instance_attrs = {} if @instance_attrs.nil?
30
32
  @instance_attrs[k] = v
31
33
  end
32
-
34
+
33
35
  end
@@ -0,0 +1,8 @@
1
+ class PasswordStrengthValidator < ActiveModel::EachValidator
2
+ # implement the method where the validation logic must reside
3
+ def validate_each(record, attribute, value)
4
+ password_validation_hash = record.password_validator || {:error_message => 'must be at least 8 characters long and start and end with a letter', :regex => '^[A-Za-z]\w{6,}[A-Za-z]$'}
5
+ record.errors[attribute] << password_validation_hash[:error_message] unless Regexp.new(password_validation_hash[:regex]) =~ value
6
+ end
7
+ end
8
+
@@ -8,7 +8,7 @@
8
8
  <p>
9
9
  You have successfully registered, to activate your account follow this link: <a href="<%= @url %>"><%= @url %></a>.
10
10
  </p>
11
- <p>Your username is <%=@user.username%> and your temporary password is <%=@user.instance_attributes[:temp_password]%></p>
11
+ <p>Your username is <%=@user.username%>, use the password you set during registration to login.</p>
12
12
  <p>Thanks for joining and have a great day!!</p>
13
13
  </body>
14
14
  </html>
@@ -3,5 +3,10 @@ Rails.application.config.erp_tech_svcs.configure do |config|
3
3
  config.login_url = '/erp_app/login'
4
4
  config.email_notifications_from = 'notifications@noreply.com'
5
5
  config.max_file_size_in_mb = 5
6
+ config.file_assets_location = 'file_assets' # relative to Rails.root/
7
+ config.s3_url_expires_in_seconds = 60
8
+ config.s3_protocol = 'https' # Can be either 'http' or 'https'
9
+ config.file_storage = :filesystem # Can be either :s3 or :filesystem
10
+ config.s3_cache_expires_in_minutes = 60
6
11
  end
7
- Rails.application.config.erp_tech_svcs.configure!
12
+ Rails.application.config.erp_tech_svcs.configure!
@@ -1 +1,9 @@
1
- ErpTechSvcs::FileSupport::S3Manager.setup_connection() if ErpTechSvcs::FileSupport.options[:storage] == :s3
1
+ # we need to_prepare so that this is checked multiple times during startup as erp_tech_svcs.file_storage can be overridden.
2
+ Rails.application.config.to_prepare do
3
+ # Rescue here, Compass should not die if it cannot connect to S3
4
+ begin
5
+ ErpTechSvcs::FileSupport::S3Manager.setup_connection() if Rails.application.config.erp_tech_svcs.file_storage == :s3
6
+ rescue Exception => e
7
+ Rails.logger.error "ERROR: Failed to connect to Amazon S3 #{e.inspect}"
8
+ end
9
+ end
@@ -125,7 +125,7 @@ Rails.application.config.sorcery.configure do |config|
125
125
  user.activation_success_email_method_name = nil # activation success email method
126
126
  # on your mailer class.
127
127
 
128
- # user.prevent_non_active_users_to_login = true # do you want to prevent or allow
128
+ user.prevent_non_active_users_to_login = true # do you want to prevent or allow
129
129
  # users that did not activate by
130
130
  # email to login?
131
131
 
@@ -164,9 +164,9 @@ Rails.application.config.sorcery.configure do |config|
164
164
  # user is banned and when it will
165
165
  # be active again.
166
166
 
167
- user.consecutive_login_retries_amount_limit = 5 # how many failed logins allowed.
167
+ user.consecutive_login_retries_amount_limit = 3 # how many failed logins allowed.
168
168
 
169
- # user.login_lock_time_period = 60 * 60 # how long the user should be
169
+ user.login_lock_time_period = 60 # how long the user should be
170
170
  # banned. in seconds. 0 for
171
171
  # permanent.
172
172
 
data/config/routes.rb CHANGED
@@ -6,4 +6,5 @@ Rails.application.routes.draw do
6
6
  #handle activation
7
7
  get "/users/activate/:activation_token" => 'erp_tech_svcs/user#activate'
8
8
  post "/users/reset_password" => 'erp_tech_svcs/user#reset_password'
9
- end
9
+ post "/users/update_password" => 'erp_tech_svcs/user#update_password'
10
+ end
@@ -0,0 +1,13 @@
1
+ class CreateDownloadCapabilityType
2
+
3
+ def self.up
4
+ CapabilityType.create(:internal_identifier => 'download', :description => 'Download')
5
+ Role.create(:description => 'File Downloader', :internal_identifier => 'file_downloader')
6
+ end
7
+
8
+ def self.down
9
+ CapabilityType.where("internal_identifier = 'download'").first.destroy unless Role.where("internal_identifier = 'download'").first.nil?
10
+ Role.where("internal_identifier = 'file_downloader'").first.destroy unless Role.where("internal_identifier = 'file_downloader'").first.nil?
11
+ end
12
+
13
+ end
@@ -32,15 +32,20 @@ class BaseTechServices < ActiveRecord::Migration
32
32
  t.string :activation_state, :default => nil
33
33
  t.string :activation_token, :default => nil
34
34
  t.datetime :activation_token_expires_at, :default => nil
35
-
35
+
36
+ t.string :security_question_1
37
+ t.string :security_answer_1
38
+ t.string :security_question_2
39
+ t.string :security_answer_2
40
+
36
41
  t.timestamps
37
42
  end
38
43
  add_index :users, :email, :unique => true
39
44
  add_index :users, :username, :unique => true
40
- add_index :users, [:last_logout_at, :last_activity_at], :name => 'activity_idx', :unique => true
41
- add_index :users, :remember_me_token, :unique => true
42
- add_index :users, :reset_password_token, :unique => true
43
- add_index :users, :activation_token, :unique => true
45
+ add_index :users, [:last_logout_at, :last_activity_at], :name => 'activity_idx'
46
+ add_index :users, :remember_me_token
47
+ add_index :users, :reset_password_token
48
+ add_index :users, :activation_token
44
49
 
45
50
  end
46
51
 
@@ -169,6 +174,8 @@ class BaseTechServices < ActiveRecord::Migration
169
174
  end
170
175
  add_index :file_assets, :type
171
176
  add_index :file_assets, [:file_asset_holder_id, :file_asset_holder_type], :name => 'file_asset_holder_idx'
177
+ add_index :file_assets, :name
178
+ add_index :file_assets, :directory
172
179
  end
173
180
 
174
181
  unless table_exists?(:delayed_jobs)
@@ -0,0 +1,38 @@
1
+ class CreateHasAttributeTables < ActiveRecord::Migration
2
+ def up
3
+ unless table_exists?(:attribute_types)
4
+ create_table :attribute_types do |t|
5
+ t.string :internal_identifier
6
+ t.string :description
7
+ t.string :data_type
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :attribute_types, :internal_identifier, :name => ':attribute_types_iid_idx'
13
+ end
14
+ unless table_exists?(:attribute_values)
15
+ create_table :attribute_values do |t|
16
+ t.integer :attributed_record_id
17
+ t.string :attributed_record_type
18
+ t.references :attribute_type
19
+ t.string :value
20
+
21
+ t.timestamps
22
+ end
23
+
24
+ add_index :attribute_values, [:attributed_record_id, :attributed_record_type], :name => 'attribute_values_attributed_record_idx'
25
+ add_index :attribute_values, :attribute_type_id, :name => 'attribute_values_attributed_type_idx'
26
+ add_index :attribute_values, :value, :name => 'attribute_values_value_idx'
27
+ end
28
+ end
29
+
30
+ def down
31
+ if table_exists?(:attribute_types)
32
+ drop_table :attribute_types
33
+ end
34
+ if table_exists?(:attribute_values)
35
+ drop_table :attribute_values
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ class AddFileAssetIndexes < ActiveRecord::Migration
2
+ def self.up
3
+ unless indexes(:file_assets).collect {|i| i.name}.include?('index_file_assets_on_type')
4
+ add_index :file_assets, :type
5
+ end
6
+
7
+ unless indexes(:file_assets).collect {|i| i.name}.include?('file_asset_holder_idx')
8
+ add_index :file_assets, [:file_asset_holder_id, :file_asset_holder_type], :name => 'file_asset_holder_idx'
9
+ end
10
+
11
+ unless indexes(:file_assets).collect {|i| i.name}.include?('index_file_assets_on_name')
12
+ add_index :file_assets, :name
13
+ end
14
+
15
+ unless indexes(:file_assets).collect {|i| i.name}.include?('index_file_assets_on_directory')
16
+ add_index :file_assets, :directory
17
+ end
18
+ end
19
+
20
+ def self.down
21
+ end
22
+ end
@@ -1,10 +1,28 @@
1
1
  module ErpTechSvcs
2
2
  module Config
3
3
  class << self
4
- attr_accessor :max_file_size_in_mb, :installation_domain, :login_url, :email_notifications_from
4
+ attr_accessor :max_file_size_in_mb,
5
+ :installation_domain,
6
+ :login_url,
7
+ :email_notifications_from,
8
+ :file_assets_location,
9
+ :s3_url_expires_in_seconds,
10
+ :s3_protocol,
11
+ :file_storage,
12
+ :s3_cache_expires_in_minutes
5
13
 
6
14
  def init!
7
- @defaults = {:@max_file_size_in_mb => nil, :@installation_domain => nil, :@login_url => nil, :@email_notifications_from => nil}
15
+ @defaults = {
16
+ :@max_file_size_in_mb => 5,
17
+ :@installation_domain => 'localhost:3000',
18
+ :@login_url => '/erp_app/login',
19
+ :@email_notifications_from => 'notifications@noreply.com',
20
+ :@file_assets_location => 'file_assets', # relative to Rails.root/
21
+ :@s3_url_expires_in_seconds => 60,
22
+ :@s3_protocol => 'https', # Can be either 'http' or 'https'
23
+ :@file_storage => :filesystem, # Can be either :s3 or :filesystem
24
+ :@s3_cache_expires_in_minutes => 60
25
+ }
8
26
  end
9
27
 
10
28
  def reset!