trusty-cms 3.8.0 → 3.8.1

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +100 -92
  3. data/app/assets/images/admin/default_forgot_password.svg +1 -0
  4. data/app/assets/images/admin/default_reset_password.svg +1 -0
  5. data/app/assets/images/admin/default_safe_login.svg +1 -0
  6. data/app/assets/javascripts/admin.js +0 -1
  7. data/app/assets/javascripts/admin/modernizr.js +3 -409
  8. data/app/assets/stylesheets/admin/partials/_forms.scss +39 -0
  9. data/app/assets/stylesheets/admin/partials/_layout.scss +8 -0
  10. data/app/assets/stylesheets/admin/partials/_validations.scss +6 -13
  11. data/app/controllers/admin/assets_controller.rb +7 -0
  12. data/app/controllers/admin/preferences_controller.rb +1 -1
  13. data/app/controllers/admin/resource_controller.rb +6 -0
  14. data/app/controllers/admin/users_controller.rb +3 -2
  15. data/app/controllers/application_controller.rb +5 -7
  16. data/app/controllers/site_controller.rb +2 -1
  17. data/app/controllers/social_mailer_controller.rb +2 -1
  18. data/app/models/legacy_user.rb +6 -0
  19. data/app/models/user.rb +39 -68
  20. data/app/models/user_action_observer.rb +4 -2
  21. data/app/views/admin/configuration/show.html.haml +2 -7
  22. data/app/views/admin/layouts/_site_chooser.html.haml +1 -1
  23. data/app/views/admin/pages/_node.html.haml +2 -2
  24. data/app/views/admin/preferences/edit.html.haml +9 -14
  25. data/app/views/admin/users/_form.html.haml +8 -15
  26. data/app/views/admin/users/index.html.haml +0 -1
  27. data/app/views/devise/passwords/edit.html.haml +23 -0
  28. data/app/views/devise/passwords/new.html.haml +14 -0
  29. data/app/views/devise/sessions/new.html.haml +25 -0
  30. data/app/views/devise/shared/_links.html.haml +16 -0
  31. data/app/views/layouts/application.html.haml +1 -1
  32. data/config/application.rb +1 -0
  33. data/config/initializers/devise.rb +310 -0
  34. data/config/routes.rb +6 -10
  35. data/db/migrate/20200117141251_create_admin_users.rb +51 -0
  36. data/lib/generators/extension_controller/templates/controller.rb +1 -1
  37. data/lib/login_system.rb +40 -44
  38. data/lib/tasks/upgrade_to_devise.rake +22 -0
  39. data/lib/trusty_cms.rb +1 -1
  40. data/lib/trusty_cms/admin_ui.rb +3 -3
  41. data/lib/trusty_cms/engine.rb +2 -0
  42. data/lib/trusty_cms/setup.rb +0 -1
  43. data/trusty_cms.gemspec +1 -0
  44. data/vendor/extensions/clipped-extension/clipped_extension.rb +0 -2
  45. data/vendor/extensions/multi-site-extension/lib/multi_site/site_chooser_helper.rb +1 -1
  46. data/vendor/extensions/snippets-extension/snippets_extension.rb +0 -2
  47. metadata +27 -8
  48. data/app/assets/javascripts/admin/cookie.js +0 -80
  49. data/app/controllers/admin/password_resets_controller.rb +0 -31
  50. data/app/controllers/admin/welcome_controller.rb +0 -47
  51. data/app/views/admin/password_resets/edit.html.haml +0 -27
  52. data/app/views/admin/password_resets/new.html.haml +0 -12
  53. data/app/views/password_mailer/password_reset.html.haml +0 -8
@@ -11,6 +11,45 @@
11
11
  }
12
12
  }
13
13
 
14
+ .login-form-content {
15
+ display: flex;
16
+ flex-flow: wrap;
17
+ justify-content: center;
18
+ margin-top: 5em;
19
+ .visual {
20
+ img {
21
+ height: 300px;
22
+ float: right;
23
+ }
24
+ }
25
+
26
+ .login {
27
+ form {
28
+ padding: 1em;
29
+ .field #user_email, .field #user_password, .field #user_password_confirmation {
30
+ padding: 1em;
31
+ margin-bottom: 1em;
32
+ width: 200px;
33
+ }
34
+
35
+ input[type='submit'] {
36
+ border-radius: 0;
37
+ background-color: #3c3a4b;
38
+
39
+ &:hover {
40
+ color: #fff;
41
+ cursor: pointer;
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ .error {
48
+ background-color: #f8d7da;
49
+ color: #721c24;
50
+ padding: 1em;
51
+ }
52
+
14
53
  #content {
15
54
  form {
16
55
  p {
@@ -11,3 +11,11 @@ body.single_form {
11
11
  }
12
12
  }
13
13
  }
14
+
15
+ body.reversed.login_form {
16
+ background-color: #fff;
17
+ }
18
+
19
+ body.reversed.password_form {
20
+ background-color: #fff;
21
+ }
@@ -1,18 +1,11 @@
1
1
  #content {
2
- span.error-with-field {
3
- input, select {
4
- background: #f3c2c2;
5
- }
6
- }
7
2
  span.error {
8
- line-height: 1.4;
9
- background-color: #cc0000;
10
- color: white;
11
- padding: 3px 6px;
12
- margin: 0 0 0 6px;
13
- background-color: #b30000;
14
- border-radius: 5px;
15
- box-shadow: 0 5px #333;
3
+ display: block;
4
+ margin: 1em 0;
5
+ background-color: #f8d7da;
6
+ color: #721c24;
7
+ padding: 1em;
8
+ font-size: 1em;
16
9
  a.closer {
17
10
  margin-left: 10px;
18
11
  color: #ffcccc;
@@ -38,6 +38,7 @@ class Admin::AssetsController < Admin::ResourceController
38
38
  else
39
39
  uploaded_asset = compress(uploaded_asset) if $kraken.api_key.present? && COMPRESS_FILE_TYPE.include?(uploaded_asset.content_type) && compress
40
40
  @asset = Asset.create(:asset => uploaded_asset, :caption => asset_params[:asset][:caption])
41
+ set_owner_or_editor
41
42
  if params[:for_attachment]
42
43
  @page = Page.find_by_id(params[:page_id]) || Page.new
43
44
  @page_attachments << @page_attachment = @asset.page_attachments.build(:page => @page)
@@ -81,6 +82,12 @@ private
81
82
  uploaded_asset
82
83
  end
83
84
 
85
+ def set_owner_or_editor
86
+ @asset.created_by_id = current_user.id
87
+ @asset.updated_by_id = current_user.id
88
+ @asset.save! if @asset.id.present?
89
+ end
90
+
84
91
  def asset_params
85
92
  params.permit(:id, :for_attachment, :asset => [:caption, :for_attachment, :asset => []])
86
93
  end
@@ -28,6 +28,6 @@ class Admin::PreferencesController < ApplicationController
28
28
  end
29
29
 
30
30
  def preferences_params
31
- params.require(:user).permit(:name, :email, :login, :password, :password_confirmation, :locale)
31
+ params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :locale)
32
32
  end
33
33
  end
@@ -7,6 +7,7 @@ class Admin::ResourceController < ApplicationController
7
7
  before_action :never_cache
8
8
  before_action :load_models, :only => :index
9
9
  before_action :load_model, :only => [:new, :create, :edit, :update, :remove, :destroy]
10
+ before_action :set_owner_or_editor, :only => [:new, :create, :update]
10
11
  after_action :clear_model_cache, :only => [:create, :update, :destroy]
11
12
 
12
13
  cattr_reader :paginated
@@ -134,6 +135,11 @@ class Admin::ResourceController < ApplicationController
134
135
  self.class.model_class
135
136
  end
136
137
 
138
+ def set_owner_or_editor
139
+ self.model.created_by_id = current_user.id if self.model.id == nil
140
+ self.model.updated_by_id = current_user.id
141
+ end
142
+
137
143
  def model
138
144
  instance_variable_get("@#{model_symbol}") || load_model
139
145
  end
@@ -15,8 +15,9 @@ class Admin::UsersController < Admin::ResourceController
15
15
  user_params = params[model_symbol].permit!
16
16
  if user_params && user_params['admin'] == false && model == current_user
17
17
  user_params.delete('admin')
18
- annouce_cannot_remove_self_from_admin_role
18
+ announce_cannot_remove_self_from_admin_role
19
19
  end
20
+ model.skip_password_validation = true unless user_params[:password_confirmation].present?
20
21
  model.update_attributes!(user_params)
21
22
  response_for :update
22
23
  end
@@ -34,7 +35,7 @@ class Admin::UsersController < Admin::ResourceController
34
35
  flash[:error] = t('users_controller.cannot_delete_self')
35
36
  end
36
37
 
37
- def annouce_cannot_remove_self_from_admin_role
38
+ def announce_cannot_remove_self_from_admin_role
38
39
  flash[:error] = 'You cannot remove yourself from the admin role.'
39
40
  end
40
41
  end
@@ -3,12 +3,10 @@ require 'login_system'
3
3
 
4
4
  class ApplicationController < ActionController::Base
5
5
  include LoginSystem
6
- # TODO: Add an ActionView::PathSet.new([paths]) for all extension view paths
7
6
  prepend_view_path("#{TRUSTY_CMS_ROOT}/app/views")
8
7
 
9
8
  protect_from_forgery with: :exception
10
-
11
- before_action :set_current_user
9
+ before_action :authenticate_user!
12
10
  before_action :set_timezone
13
11
  before_action :set_user_locale
14
12
  before_action :set_javascripts_and_stylesheets
@@ -25,6 +23,10 @@ class ApplicationController < ActionController::Base
25
23
  @trusty_config = TrustyCms::Config
26
24
  end
27
25
 
26
+ def after_sign_in_path_for(resource)
27
+ admin_pages_path
28
+ end
29
+
28
30
  def template_name
29
31
  case self.action_name
30
32
  when 'index'
@@ -48,10 +50,6 @@ class ApplicationController < ActionController::Base
48
50
  ActionMailer::Base.default_url_options[:host] = request.host_with_port
49
51
  end
50
52
 
51
- def set_current_user
52
- UserActionObserver.instance.current_user = current_user
53
- end
54
-
55
53
  def set_user_locale
56
54
  I18n.locale = current_user && !current_user.locale.blank? ? current_user.locale : TrustyCms::Config['default_locale']
57
55
  end
@@ -2,7 +2,8 @@ require 'trusty_cms/pagination/controller'
2
2
  class SiteController < ApplicationController
3
3
  include TrustyCms::Pagination::Controller
4
4
 
5
- no_login_required
5
+ # no_login_required
6
+ skip_before_action :authenticate_user!
6
7
 
7
8
  def self.cache_timeout=(val)
8
9
  TrustyCms::PageResponseCacheDirector.cache_timeout=(val)
@@ -1,7 +1,8 @@
1
1
  class SocialMailerController < ApplicationController
2
2
  include ShareLayouts::Controllers::ActionController
3
3
  trusty_layout "default", {:only => :create_social_mail}
4
- no_login_required
4
+ # no_login_required
5
+ skip_before_action :authenticate_user!
5
6
 
6
7
  def create_social_mail
7
8
 
@@ -0,0 +1,6 @@
1
+ class LegacyUser < ActiveRecord::Base
2
+ self.table_name = 'users'
3
+
4
+ # this is a legacy class
5
+ # this table formally held user information for when TrustyCMS had a handwritten authentication system
6
+ end
data/app/models/user.rb CHANGED
@@ -1,96 +1,67 @@
1
- require 'digest/sha1'
2
-
3
1
  class User < ActiveRecord::Base
4
2
  has_many :pages, :foreign_key => :created_by_id
3
+ self.table_name = 'admins'
5
4
 
6
- # Default Order
7
- default_scope {order("name")}
8
-
9
- # Associations
10
- belongs_to :created_by, :class_name => 'User'
11
- belongs_to :updated_by, :class_name => 'User'
12
-
13
- # Validations
14
- validates_uniqueness_of :login
5
+ # :confirmable, :lockable, :timeoutable and :omniauthable
6
+ devise :database_authenticatable, :registerable,
7
+ :recoverable, :rememberable, :trackable, :validatable
15
8
 
16
- validates_confirmation_of :password, :if => :confirm_password?
9
+ alias_attribute :created_by_id, :id
17
10
 
18
- validates_presence_of :name, :login
19
- validates_presence_of :password, :password_confirmation, :if => :new_record?
11
+ attr_accessor :skip_password_validation
20
12
 
13
+ validate :password_complexity
21
14
 
22
- validates_length_of :name, :maximum => 100, :allow_nil => true
23
- validates_length_of :login, :within => 3..40, :allow_nil => true
24
- validates_length_of :password, :within => 5..40, :allow_nil => true, :if => :validate_length_of_password?
25
- validates_length_of :email, :maximum => 255, :allow_nil => true
15
+ # Default Order
16
+ default_scope {order('last_name')}
26
17
 
27
- attr_writer :confirm_password
18
+ # Associations
19
+ belongs_to :created_by, :class_name => 'User'
20
+ belongs_to :updated_by, :class_name => 'User'
28
21
 
29
22
  def has_role?(role)
30
- respond_to?("#{role}?") && send("#{role}?")
31
- end
32
-
33
- def sha1(phrase)
34
- Digest::SHA1.hexdigest("--#{salt}--#{phrase}--")
35
- end
36
-
37
- def self.authenticate(login_or_email, password)
38
- user = where(["login = ? OR email = ?", login_or_email, login_or_email]).first
39
- user if user && user.authenticated?(password)
40
- end
41
-
42
- def authenticated?(password)
43
- self.password == sha1(password)
44
- end
45
-
46
- def after_initialize
47
- @confirm_password = true
23
+ case role
24
+ when :admin
25
+ self.admin?
26
+ when :designer
27
+ self.designer?
28
+ when :content_editor
29
+ self.content_editor?
30
+ else
31
+ false
32
+ end
48
33
  end
49
34
 
50
- def confirm_password?
51
- @confirm_password
35
+ def admin?
36
+ self.admin
52
37
  end
53
38
 
54
- def remember_me
55
- update_attribute(:session_token, sha1(Time.now + TrustyCms::Config['session_timeout'].to_i)) unless self.session_token?
39
+ def designer?
40
+ self.designer
56
41
  end
57
42
 
58
- def forget_me
59
- update_attribute(:session_token, nil)
43
+ def content_editor?
44
+ self.content_editor
60
45
  end
61
46
 
62
- def send_password_reset
63
- generate_token(:password_reset_token)
64
- update_attribute(:password_reset_sent_at, Time.zone.now)
65
- PasswordMailer.password_reset(self).deliver_now
47
+ def locale
48
+ 'en'
66
49
  end
67
50
 
68
- private
69
-
70
- def generate_token(column)
71
- self[column] = SecureRandom.urlsafe_base64 if User.exists?(column => self[column])
51
+ def name
52
+ "#{self.first_name} #{self.last_name}"
72
53
  end
73
54
 
74
- def validate_length_of_password?
75
- new_record? or not password.to_s.empty?
55
+ def password_required?
56
+ return false if skip_password_validation
57
+ super
76
58
  end
77
59
 
78
- before_create :encrypt_password
79
- def encrypt_password
80
- self.salt = Digest::SHA1.hexdigest("--#{Time.now}--#{login}--sweet harmonious biscuits--")
81
- self.password = sha1(password)
82
- end
60
+ def password_complexity
61
+ # Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a
62
+ return if password.blank? || password =~ /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,70}$/
83
63
 
84
- before_update :encrypt_password_unless_empty_or_unchanged
85
- def encrypt_password_unless_empty_or_unchanged
86
- user = self.class.find(self.id)
87
- case password
88
- when ''
89
- self.password = user.password
90
- when user.password
91
- else
92
- encrypt_password
93
- end
64
+ errors.add :password, 'Complexity requirement not met. Length should be 12 characters and include: 1 uppercase, 1 lowercase, 1 digit and 1 special character.'
94
65
  end
95
66
 
96
67
  end
@@ -4,6 +4,7 @@ class UserActionObserver < ActiveRecord::Observer
4
4
  def current_user=(user)
5
5
  self.class.current_user = user
6
6
  end
7
+
7
8
  def self.current_user=(user)
8
9
  Thread.current[:current_user] = user
9
10
  end
@@ -11,15 +12,16 @@ class UserActionObserver < ActiveRecord::Observer
11
12
  def current_user
12
13
  self.class.current_user
13
14
  end
15
+
14
16
  def self.current_user
15
17
  Thread.current[:current_user]
16
18
  end
17
19
 
18
20
  def before_create(model)
19
- model.created_by = self.current_user
21
+ #model.created_by = self.current_user
20
22
  end
21
23
 
22
24
  def before_update(model)
23
- model.updated_by = self.current_user
25
+ #model.updated_by = self.current_user
24
26
  end
25
27
  end
@@ -5,7 +5,7 @@
5
5
  - user.preferences do
6
6
  %h3
7
7
  .actions
8
- = button_to t("edit_preferences"), "/admin/preferences", :method => :get
8
+ = button_to t("edit_preferences"), edit_user_registration_path, :method => :get
9
9
  = t('personal_preferences')
10
10
  = image_tag(gravatar_url(@user.email, :size=>"64px"), :class=>"avatar", :width=>64, :height=>64, :alt=>"")
11
11
  %p.ruled
@@ -18,11 +18,6 @@
18
18
  = t('email_address')
19
19
  %span.uri
20
20
  = current_user.email
21
- %p.ruled
22
- %label
23
- = t('login')
24
- %span
25
- = current_user.login
26
21
  %p.ruled
27
22
  %label
28
23
  = t('password')
@@ -37,7 +32,7 @@
37
32
  - render_region :trusty_config do |config|
38
33
  - config.site do
39
34
  %h3
40
- - if admin?
35
+ - if current_user.admin?
41
36
  .actions
42
37
  = button_to t("edit_configuration"), edit_admin_configuration_path, :method => :get
43
38
  Configuration
@@ -1,4 +1,4 @@
1
- - if admin? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
1
+ - if current_user.admin? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
2
2
  %nav#site_chooser
3
3
  %ul#nav
4
4
  %li
@@ -18,5 +18,5 @@
18
18
  - unless simple
19
19
  %td.actions
20
20
  = page.add_child_option
21
- - if current_user.has_role?('admin')
22
- = page.remove_option
21
+ - if current_user.admin?
22
+ = page.remove_option
@@ -13,32 +13,27 @@
13
13
  = render_region :form_top, :locals => {:f => f}
14
14
 
15
15
  - render_region :form, :locals => {:f => f} do |form|
16
- - form.edit_name do
16
+ - form.edit_first_name do
17
17
  %p
18
- = f.label :name, t("name")
19
- = f.text_field :name, :class => "textbox", :size => 32, :maxlength => 100
18
+ = f.label :name, t("first_name")
19
+ = f.text_field :first_name, :class => "textbox", :size => 32, :maxlength => 100
20
+
21
+ - form.edit_last_name do
22
+ %p
23
+ = f.label :name, t("last_name")
24
+ = f.text_field :last_name, :class => "textbox", :size => 32, :maxlength => 100
20
25
 
21
26
  - form.edit_email do
22
27
  %p
23
28
  = f.label :email, t("email_address"), :class => "optional"
24
29
  = f.text_field "email", :class => 'textbox', :size => 32, :maxlength => 255
25
30
 
26
- - form.edit_username do
27
- %p
28
- = f.label :login, t("username")
29
- = f.text_field "login", :class => "textbox", :size => 32, :maxlength => 40, :required => true
30
-
31
31
  - form.edit_password do
32
32
  = render "admin/users/password_fields", :f => f
33
33
 
34
- - form.edit_locale do
35
- %p
36
- = f.label :locale, t('language')
37
- = f.select "locale", available_locales_select
38
-
39
34
  - render_region :form_bottom, :locals => {:f => f} do |form_bottom|
40
35
  - form_bottom.edit_buttons do
41
36
  .buttons
42
37
  = save_model_button @user
43
38
  = t('or')
44
- = link_to t('cancel'), admin_url, class: 'alt'
39
+ = link_to t('cancel'), admin_pages_url, class: 'alt'