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.
- checksums.yaml +4 -4
- data/Gemfile.lock +100 -92
- data/app/assets/images/admin/default_forgot_password.svg +1 -0
- data/app/assets/images/admin/default_reset_password.svg +1 -0
- data/app/assets/images/admin/default_safe_login.svg +1 -0
- data/app/assets/javascripts/admin.js +0 -1
- data/app/assets/javascripts/admin/modernizr.js +3 -409
- data/app/assets/stylesheets/admin/partials/_forms.scss +39 -0
- data/app/assets/stylesheets/admin/partials/_layout.scss +8 -0
- data/app/assets/stylesheets/admin/partials/_validations.scss +6 -13
- data/app/controllers/admin/assets_controller.rb +7 -0
- data/app/controllers/admin/preferences_controller.rb +1 -1
- data/app/controllers/admin/resource_controller.rb +6 -0
- data/app/controllers/admin/users_controller.rb +3 -2
- data/app/controllers/application_controller.rb +5 -7
- data/app/controllers/site_controller.rb +2 -1
- data/app/controllers/social_mailer_controller.rb +2 -1
- data/app/models/legacy_user.rb +6 -0
- data/app/models/user.rb +39 -68
- data/app/models/user_action_observer.rb +4 -2
- data/app/views/admin/configuration/show.html.haml +2 -7
- data/app/views/admin/layouts/_site_chooser.html.haml +1 -1
- data/app/views/admin/pages/_node.html.haml +2 -2
- data/app/views/admin/preferences/edit.html.haml +9 -14
- data/app/views/admin/users/_form.html.haml +8 -15
- data/app/views/admin/users/index.html.haml +0 -1
- data/app/views/devise/passwords/edit.html.haml +23 -0
- data/app/views/devise/passwords/new.html.haml +14 -0
- data/app/views/devise/sessions/new.html.haml +25 -0
- data/app/views/devise/shared/_links.html.haml +16 -0
- data/app/views/layouts/application.html.haml +1 -1
- data/config/application.rb +1 -0
- data/config/initializers/devise.rb +310 -0
- data/config/routes.rb +6 -10
- data/db/migrate/20200117141251_create_admin_users.rb +51 -0
- data/lib/generators/extension_controller/templates/controller.rb +1 -1
- data/lib/login_system.rb +40 -44
- data/lib/tasks/upgrade_to_devise.rake +22 -0
- data/lib/trusty_cms.rb +1 -1
- data/lib/trusty_cms/admin_ui.rb +3 -3
- data/lib/trusty_cms/engine.rb +2 -0
- data/lib/trusty_cms/setup.rb +0 -1
- data/trusty_cms.gemspec +1 -0
- data/vendor/extensions/clipped-extension/clipped_extension.rb +0 -2
- data/vendor/extensions/multi-site-extension/lib/multi_site/site_chooser_helper.rb +1 -1
- data/vendor/extensions/snippets-extension/snippets_extension.rb +0 -2
- metadata +27 -8
- data/app/assets/javascripts/admin/cookie.js +0 -80
- data/app/controllers/admin/password_resets_controller.rb +0 -31
- data/app/controllers/admin/welcome_controller.rb +0 -47
- data/app/views/admin/password_resets/edit.html.haml +0 -27
- data/app/views/admin/password_resets/new.html.haml +0 -12
- 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 {
|
@@ -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
|
-
|
9
|
-
|
10
|
-
color:
|
11
|
-
|
12
|
-
|
13
|
-
|
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(:
|
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
|
-
|
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
|
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
|
|
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
|
-
#
|
7
|
-
|
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
|
-
|
9
|
+
alias_attribute :created_by_id, :id
|
17
10
|
|
18
|
-
|
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
|
-
|
23
|
-
|
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
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
51
|
-
|
35
|
+
def admin?
|
36
|
+
self.admin
|
52
37
|
end
|
53
38
|
|
54
|
-
def
|
55
|
-
|
39
|
+
def designer?
|
40
|
+
self.designer
|
56
41
|
end
|
57
42
|
|
58
|
-
def
|
59
|
-
|
43
|
+
def content_editor?
|
44
|
+
self.content_editor
|
60
45
|
end
|
61
46
|
|
62
|
-
def
|
63
|
-
|
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
|
-
|
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
|
75
|
-
|
55
|
+
def password_required?
|
56
|
+
return false if skip_password_validation
|
57
|
+
super
|
76
58
|
end
|
77
59
|
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
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"),
|
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
|
@@ -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.
|
16
|
+
- form.edit_first_name do
|
17
17
|
%p
|
18
|
-
= f.label :name, t("
|
19
|
-
= f.text_field :
|
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'),
|
39
|
+
= link_to t('cancel'), admin_pages_url, class: 'alt'
|