trusty-cms 7.0.2 → 7.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +89 -102
  5. data/INSTALL.md +8 -6
  6. data/README.md +123 -15
  7. data/app/assets/javascripts/admin/validations/scheduled_status_validation.js +60 -0
  8. data/app/assets/stylesheets/admin/main.scss +2 -1
  9. data/app/assets/stylesheets/admin/partials/_datetime_input.scss +5 -0
  10. data/app/assets/stylesheets/admin/partials/_forms.scss +13 -0
  11. data/app/assets/stylesheets/admin/partials/_messages.scss +4 -0
  12. data/app/controllers/admin/configuration_controller.rb +1 -1
  13. data/app/controllers/admin/extensions_controller.rb +1 -0
  14. data/app/controllers/admin/layouts_controller.rb +2 -1
  15. data/app/controllers/admin/resource_controller.rb +10 -1
  16. data/app/controllers/admin/sites_controller.rb +1 -0
  17. data/app/controllers/admin/snippets_controller.rb +2 -1
  18. data/app/controllers/admin/users_controller.rb +2 -1
  19. data/app/controllers/page_status_controller.rb +61 -0
  20. data/app/controllers/site_controller.rb +0 -15
  21. data/app/helpers/admin/pages_helper.rb +0 -5
  22. data/app/helpers/admin/users_helper.rb +2 -1
  23. data/app/helpers/application_helper.rb +2 -1
  24. data/app/models/admins_site.rb +6 -0
  25. data/app/models/page.rb +3 -10
  26. data/app/models/site.rb +2 -0
  27. data/app/models/status.rb +1 -5
  28. data/app/models/trusty_cms/config.rb +2 -1
  29. data/app/models/user.rb +15 -4
  30. data/app/views/admin/layouts/_choose_site.html.haml +5 -3
  31. data/app/views/admin/layouts/_site_chooser.html.haml +2 -2
  32. data/app/views/admin/pages/_fields.html.haml +15 -6
  33. data/app/views/admin/pages/_node.html.haml +1 -1
  34. data/app/views/admin/snippets/_choose_site.html.haml +2 -1
  35. data/app/views/admin/users/_choose_site.html.haml +2 -1
  36. data/app/views/admin/users/_form.html.haml +3 -1
  37. data/bin/rails +2 -2
  38. data/config/application.rb +1 -0
  39. data/config/initializers/devise.rb +1 -1
  40. data/config/locales/en.yml +11 -9
  41. data/config/routes.rb +1 -0
  42. data/db/migrate/20241108172942_create_site_users.rb +8 -0
  43. data/lib/login_system.rb +15 -15
  44. data/lib/trusty_cms/version.rb +1 -1
  45. data/spec/dummy/config/application.rb +2 -0
  46. data/spec/dummy/db/schema.rb +8 -1
  47. data/spec/factories/snippet.rb +10 -0
  48. data/spec/factories/user.rb +11 -11
  49. data/spec/models/snippets_spec.rb +29 -0
  50. data/spec/models/user_spec.rb +46 -0
  51. data/trusty_cms.gemspec +1 -1
  52. data/vendor/extensions/multi-site-extension/lib/multi_site/scoped_model.rb +17 -11
  53. data/vendor/extensions/multi-site-extension/lib/multi_site/site_chooser_helper.rb +10 -10
  54. metadata +16 -6
  55. data/app/users/_choose_site.html.haml +0 -4
  56. /data/app/assets/stylesheets/admin/partials/{_dateinput.scss → _date_input.scss} +0 -0
@@ -0,0 +1,60 @@
1
+ $(document).ready(function() {
2
+ function isValidDateTime(value) {
3
+ return !isNaN(new Date(value).getTime());
4
+ }
5
+
6
+ function showError(message) {
7
+ $('#published-at-error').text(message);
8
+ $('.error').removeClass('hidden');
9
+ }
10
+
11
+ function hideError() {
12
+ $('.error').addClass('hidden');
13
+ }
14
+
15
+ function validateScheduledStatus(publishedTime, currentTime) {
16
+ if (!isValidDateTime(publishedTime)) {
17
+ showError('Select a valid Date & Time.');
18
+ return false;
19
+ }
20
+ if (publishedTime < currentTime) {
21
+ showError('Scheduled Date & Time cannot be in the past.');
22
+ return false;
23
+ }
24
+
25
+ hideError();
26
+ return true;
27
+ }
28
+
29
+ function validatePublishedStatus(publishedTime, currentTime) {
30
+ if (publishedTime > currentTime) {
31
+ showError('Published Date & Time cannot be in the future. Clear the date and time to publish now, or set the status to Scheduled.');
32
+ return false;
33
+ }
34
+
35
+ hideError();
36
+ return true;
37
+ }
38
+
39
+ function validateDateTime() {
40
+ const publishedAt = $('#page_published_at').val();
41
+ const status = $('#page_status_id').val();
42
+ const publishedTime = new Date(publishedAt);
43
+ const currentTime = new Date();
44
+
45
+ if (status === '90') {
46
+ return validateScheduledStatus(publishedTime, currentTime);
47
+ }
48
+
49
+ if (status === '100') {
50
+ return validatePublishedStatus(publishedTime, currentTime);
51
+ }
52
+ }
53
+
54
+ $('#save-button, #save-and-continue-button').on('click', function(event) {
55
+ if (!validateDateTime()) {
56
+ event.preventDefault();
57
+ event.stopImmediatePropagation();
58
+ }
59
+ });
60
+ });
@@ -20,7 +20,8 @@
20
20
  @import "partials/footer";
21
21
  @import "partials/popup";
22
22
  @import "partials/tabcontrol";
23
- @import "partials/dateinput";
23
+ @import "partials/date_input";
24
+ @import "partials/datetime_input";
24
25
  @import "partials/toolbar";
25
26
  @import "partials/validations";
26
27
  @import "partials/preferences";
@@ -0,0 +1,5 @@
1
+ .datetime {
2
+ border: 1px solid #919191;
3
+ margin: 0.5em;
4
+ padding: 0.5em 1em;
5
+ }
@@ -60,6 +60,19 @@ select {
60
60
  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
61
61
  }
62
62
 
63
+ select[multiple] {
64
+ height: auto;
65
+
66
+ option {
67
+ padding: 0.5em;
68
+
69
+ &:checked {
70
+ background-color: #e5e6e7;
71
+ font-weight: 700;
72
+ }
73
+ }
74
+ }
75
+
63
76
  label {
64
77
  display: block;
65
78
  }
@@ -10,6 +10,10 @@
10
10
  .error {
11
11
  background-color: #f3c2c2;
12
12
  color: $alt-link-color;
13
+
14
+ &.hidden {
15
+ display: none;
16
+ }
13
17
  }
14
18
 
15
19
  .warning {
@@ -5,7 +5,7 @@ class Admin::ConfigurationController < ApplicationController
5
5
  # and the show and edit views determine what set of config values is shown and made editable.
6
6
 
7
7
  before_action :initialize_config
8
-
8
+ before_action :authorize_role
9
9
  only_allow_access_to :edit, :update,
10
10
  when: [:admin],
11
11
  denied_url: { controller: 'admin/configuration', action: 'show' },
@@ -1,4 +1,5 @@
1
1
  class Admin::ExtensionsController < ApplicationController
2
+ before_action :authorize_role
2
3
  only_allow_access_to :index,
3
4
  when: :admin,
4
5
  denied_url: { controller: 'pages', action: 'index' },
@@ -1,7 +1,8 @@
1
1
  class Admin::LayoutsController < Admin::ResourceController
2
2
  paginate_models
3
+ before_action :authorize_role
3
4
  only_allow_access_to :index, :show, :new, :create, :edit, :update, :remove, :destroy,
4
5
  when: %i[designer admin],
5
6
  denied_url: { controller: 'admin/pages', action: 'index' },
6
- denied_message: 'You must have designer privileges to perform this action.'
7
+ denied_message: 'You must have at least editor privileges to perform this action.'
7
8
  end
@@ -1,4 +1,5 @@
1
1
  require 'trusty_cms/resource_responses'
2
+
2
3
  class Admin::ResourceController < ApplicationController
3
4
  extend TrustyCms::ResourceResponses
4
5
 
@@ -95,6 +96,7 @@ class Admin::ResourceController < ApplicationController
95
96
  def will_paginate_options
96
97
  self.class.will_paginate_options || {}
97
98
  end
99
+
98
100
  helper_method :will_paginate_options
99
101
 
100
102
  # a convenience method that returns true if paginate_models has been called on this controller class
@@ -102,6 +104,7 @@ class Admin::ResourceController < ApplicationController
102
104
  def paginated?
103
105
  self.class.paginated == true && params[:pp] != 'all'
104
106
  end
107
+
105
108
  helper_method :paginated?
106
109
 
107
110
  # return a hash of page and per_page that can be used to build a will_paginate collection
@@ -145,7 +148,9 @@ class Admin::ResourceController < ApplicationController
145
148
  def model
146
149
  instance_variable_get("@#{model_symbol}") || load_model
147
150
  end
151
+
148
152
  alias :current_object :model
153
+
149
154
  def model=(object)
150
155
  instance_variable_set("@#{model_symbol}", object)
151
156
  end
@@ -155,13 +160,15 @@ class Admin::ResourceController < ApplicationController
155
160
  model_class.find(params[:id])
156
161
  else
157
162
  model_class.new
158
- end
163
+ end
159
164
  end
160
165
 
161
166
  def models
162
167
  instance_variable_get("@#{plural_model_symbol}") || load_models
163
168
  end
169
+
164
170
  alias :current_objects :models
171
+
165
172
  def models=(objects)
166
173
  instance_variable_set("@#{plural_model_symbol}", objects)
167
174
  end
@@ -177,6 +184,7 @@ class Admin::ResourceController < ApplicationController
177
184
  def plural_model_name
178
185
  model_name.pluralize
179
186
  end
187
+
180
188
  alias :models_name :plural_model_name
181
189
 
182
190
  def model_symbol
@@ -186,6 +194,7 @@ class Admin::ResourceController < ApplicationController
186
194
  def plural_model_symbol
187
195
  model_name.pluralize.underscore.intern
188
196
  end
197
+
189
198
  alias :models_symbol :plural_model_symbol
190
199
 
191
200
  def humanized_model_name
@@ -1,5 +1,6 @@
1
1
  class Admin::SitesController < Admin::ResourceController
2
2
  helper :sites
3
+ before_action :authorize_role
3
4
  only_allow_access_to :index, :show, :new, :create, :edit, :update, :remove, :destroy,
4
5
  when: :admin,
5
6
  denied_url: { controller: 'pages', action: 'index' },
@@ -1,7 +1,8 @@
1
1
  class Admin::SnippetsController < Admin::ResourceController
2
2
  paginate_models
3
+ before_action :authorize_role
3
4
  only_allow_access_to :index, :show, :new, :create, :edit, :update, :remove, :destroy,
4
5
  when: %i[designer admin],
5
6
  denied_url: { controller: 'admin/pages', action: 'index' },
6
- denied_message: 'You must have designer privileges to perform this action.'
7
+ denied_message: 'You must have at least editor privileges to perform this action.'
7
8
  end
@@ -1,5 +1,6 @@
1
1
  class Admin::UsersController < Admin::ResourceController
2
2
  paginate_models
3
+ before_action :authorize_role
3
4
  only_allow_access_to :index, :show, :new, :create, :edit, :update, :remove, :destroy,
4
5
  when: :admin,
5
6
  denied_url: { controller: 'pages', action: 'index' },
@@ -48,7 +49,7 @@ class Admin::UsersController < Admin::ResourceController
48
49
 
49
50
  def user_params
50
51
  params.require(:user).permit(:first_name, :last_name, :admin, :designer,
51
- :password, :password_confirmation, :email, :site_id, :notes)
52
+ :password, :password_confirmation, :email, :site_id, :notes, site_ids: [])
52
53
  end
53
54
 
54
55
  def announce_cannot_delete_self
@@ -0,0 +1,61 @@
1
+ class PageStatusController < ApplicationController
2
+ skip_before_action :verify_authenticity_token, only: [:refresh]
3
+ skip_before_action :authenticate_user!, only: [:refresh]
4
+ before_action :authenticate_bearer_token
5
+
6
+ def refresh
7
+ pages = Page.where(status_id: Status[:scheduled].id)
8
+
9
+ updated_pages, remaining_pages = process_pages(pages)
10
+
11
+ render json: refresh_response(updated_pages, remaining_pages), status: :ok
12
+ end
13
+
14
+ private
15
+
16
+ def authenticate_bearer_token
17
+ provided_token = request.headers['Authorization']&.split(' ')&.last
18
+ expected_token = Rails.application.credentials[:trusty_cms][:page_status_bearer_token]
19
+
20
+ if provided_token.blank?
21
+ render json: { error: 'Missing Bearer Token' }, status: :unauthorized and return
22
+ end
23
+
24
+ unless ActiveSupport::SecurityUtils.secure_compare(provided_token, expected_token)
25
+ render json: { error: 'Invalid Bearer Token' }, status: :unauthorized
26
+ end
27
+ end
28
+
29
+ def process_pages(pages)
30
+ updated_pages = []
31
+ remaining_pages = []
32
+
33
+ pages.each do |page|
34
+ page_id = page.id
35
+ if page.published_at <= Time.now
36
+ page.update(status_id: Status[:published].id)
37
+ updated_pages << page_id
38
+ else
39
+ remaining_pages << page_id
40
+ end
41
+ end
42
+
43
+ [updated_pages, remaining_pages]
44
+ end
45
+
46
+ def refresh_response(updated_pages, remaining_pages)
47
+ if updated_pages.any?
48
+ updated_pages_count = updated_pages.count
49
+ {
50
+ message: "Successfully updated status of #{updated_pages_count} #{'page'.pluralize(updated_pages_count)}.",
51
+ updated_page_ids: updated_pages,
52
+ remaining_scheduled_page_ids: remaining_pages,
53
+ }
54
+ else
55
+ {
56
+ message: 'No scheduled pages matched the criteria for status refresh.',
57
+ remaining_scheduled_page_ids: remaining_pages,
58
+ }
59
+ end
60
+ end
61
+ end
@@ -23,7 +23,6 @@ class SiteController < ApplicationController
23
23
  url.to_s
24
24
  end
25
25
  if @page = find_page(url)
26
- batch_page_status_refresh if url == '/' || url == ''
27
26
  # This is a bit of a hack to get Vanity URL pages working in another extension
28
27
  # In Rails 2, redirect_to halted execution, so process_page could be aliased and
29
28
  # a redirect could be used. This no longer works. There's a better fix for this,
@@ -61,20 +60,6 @@ class SiteController < ApplicationController
61
60
 
62
61
  private
63
62
 
64
- def batch_page_status_refresh
65
- @changed_pages = []
66
- @pages = Page.where({ status_id: Status[:scheduled].id })
67
- @pages.each do |page|
68
- if page.published_at <= Time.now
69
- page.status_id = Status[:published].id
70
- page.save
71
- @changed_pages << page.id
72
- end
73
- end
74
-
75
- expires_in nil, :private => true, 'no-cache' => true if @changed_pages.length > 0
76
- end
77
-
78
63
  def set_cache_control
79
64
  response_cache_director(@page).set_cache_control
80
65
  end
@@ -14,11 +14,6 @@ module Admin::PagesHelper
14
14
  !!(@page.errors[:slug] or @page.errors[:breadcrumb])
15
15
  end
16
16
 
17
- def status_to_display
18
- @page.status_id = 100 if @page.status_id == 90
19
- @display_status = Status.selectable.map { |s| [I18n.translate(s.name.downcase), s.id] }
20
- end
21
-
22
17
  def clean_page_description(page)
23
18
  page.description.to_s.strip.gsub(/\t/, '').gsub(/\s+/, ' ')
24
19
  end
@@ -2,7 +2,8 @@ module Admin::UsersHelper
2
2
  def roles(user)
3
3
  roles = []
4
4
  roles << I18n.t('admin') if user.admin?
5
- roles << I18n.t('designer') if user.designer?
5
+ roles << I18n.t('editor') if user.editor?
6
+ roles << I18n.t('content_editor') if user.content_editor?
6
7
  roles.join(', ')
7
8
  end
8
9
  end
@@ -33,11 +33,12 @@ module ApplicationHelper
33
33
  t('buttons.save_changes', default: 'Save Changes')
34
34
  options[:class] ||= 'button'
35
35
  options[:accesskey] ||= 'S'
36
+ options[:id] ||= 'save-button'
36
37
  submit_tag options.delete(:label), options
37
38
  end
38
39
 
39
40
  def save_model_and_continue_editing_button(_model)
40
- submit_tag t('buttons.save_and_continue'), name: 'continue', class: 'button', accesskey: 's'
41
+ submit_tag t('buttons.save_and_continue'), name: 'continue', class: 'button', accesskey: 's', id: 'save-and-continue-button'
41
42
  end
42
43
 
43
44
  def current_item?(item)
@@ -0,0 +1,6 @@
1
+ class AdminsSite < ActiveRecord::Base
2
+ self.table_name = 'admins_sites'
3
+
4
+ belongs_to :admin, class_name: 'User'
5
+ belongs_to :site
6
+ end
data/app/models/page.rb CHANGED
@@ -8,7 +8,7 @@ class Page < ActiveRecord::Base
8
8
  end
9
9
 
10
10
  # Callbacks
11
- before_save :update_virtual, :update_status, :set_allowed_children_cache
11
+ before_save :update_virtual, :update_published_datetime, :set_allowed_children_cache
12
12
 
13
13
  # Associations
14
14
  acts_as_tree order: 'position ASC'
@@ -220,15 +220,8 @@ class Page < ActiveRecord::Base
220
220
  slug_child
221
221
  end
222
222
 
223
- def update_status
224
- self.published_at = Time.zone.now if published? && published_at == nil
225
-
226
- if !published_at.nil? && (published? || scheduled?)
227
- self[:status_id] = Status[:scheduled].id if published_at > Time.zone.now
228
- self[:status_id] = Status[:published].id if published_at <= Time.zone.now
229
- end
230
-
231
- true
223
+ def update_published_datetime
224
+ self.published_at = Time.zone.now if published? && published_at.blank?
232
225
  end
233
226
 
234
227
  def default_child
data/app/models/site.rb CHANGED
@@ -7,6 +7,8 @@ class Site < ActiveRecord::Base
7
7
  belongs_to :created_by, class_name: 'User'
8
8
  belongs_to :updated_by, class_name: 'User'
9
9
  belongs_to :production_homepage, class_name: 'ProductionPage'
10
+ has_many :admins_sites
11
+ has_many :admins, through: :admins_sites, class_name: 'User'
10
12
 
11
13
  default_scope { order('position ASC') }
12
14
 
data/app/models/status.rb CHANGED
@@ -19,12 +19,8 @@ class Status
19
19
  @@statuses.find { |status| status.id.to_s == id.to_s }
20
20
  end
21
21
 
22
- def self.find_all
23
- @@statuses.dup
24
- end
25
-
26
22
  def self.selectable
27
- find_all - [self['Scheduled']]
23
+ @@statuses
28
24
  end
29
25
 
30
26
  def self.selectable_values
@@ -81,7 +81,8 @@ module TrustyCms
81
81
  TrustyCms::Config.initialize_cache
82
82
  end
83
83
  TrustyCms::Config.initialize_cache if TrustyCms::Config.stale_cache?
84
- Rails.cache.read('TrustyCms::Config')[key]
84
+ config_cache = Rails.cache.read('TrustyCms::Config')
85
+ config_cache ? config_cache[key] : nil
85
86
  end
86
87
  end
87
88
  end
data/app/models/user.rb CHANGED
@@ -7,7 +7,6 @@ class User < ActiveRecord::Base
7
7
  :recoverable, :rememberable, :trackable, :validatable
8
8
 
9
9
  alias_attribute :created_by_id, :id
10
-
11
10
  attr_accessor :skip_password_validation
12
11
 
13
12
  validate :password_complexity
@@ -18,6 +17,13 @@ class User < ActiveRecord::Base
18
17
  # Associations
19
18
  belongs_to :created_by, class_name: 'User'
20
19
  belongs_to :updated_by, class_name: 'User'
20
+ has_many :admins_sites, foreign_key: 'admin_id', class_name: 'AdminsSite', dependent: :destroy
21
+ has_many :sites, through: :admins_sites
22
+
23
+ # Roles
24
+ # Admin - all permissions
25
+ # Editor - all permissions except for users, sites editing
26
+ # Content Editor - all permissions except for users, sites, publishing and deleting
21
27
 
22
28
  def role?(role)
23
29
  case role
@@ -40,12 +46,16 @@ class User < ActiveRecord::Base
40
46
  designer
41
47
  end
42
48
 
49
+ def editor?
50
+ designer
51
+ end
52
+
43
53
  def content_editor?
44
54
  content_editor
45
55
  end
46
56
 
47
- def scoped?
48
- site_id.present?
57
+ def scoped_site?
58
+ sites.present?
49
59
  end
50
60
 
51
61
  def locale
@@ -67,4 +77,5 @@ class User < ActiveRecord::Base
67
77
 
68
78
  errors.add :password, 'Complexity requirement not met. Length should be 12 characters and include: 1 uppercase, 1 lowercase, 1 digit and 1 special character.'
69
79
  end
70
- end
80
+
81
+ end
@@ -1,7 +1,9 @@
1
1
  - unless current_user.site
2
2
  %label{:for=>'layout_site_id', :class => 'admin_only'}
3
3
  Site
4
- - sites = Site.all.map { |s| [s.name, s.id] }
5
- - selection = {:include_blank => Layout.is_shareable?}
6
- - selection[:selected] = current_site.id if @layout.new_record? && ! Layout.is_shareable?
4
+ :ruby
5
+ user_sites = current_user.admins_sites.pluck(:site_id)
6
+ sites = Site.where(:id => user_sites).map { |s| [s.name, s.id] }
7
+ selection = {:include_blank => Layout.is_shareable?}
8
+ selection[:selected] = current_site.id if @layout.new_record? && ! Layout.is_shareable?
7
9
  = select :layout, :site_id, sites, selection
@@ -1,9 +1,9 @@
1
- - if current_user.admin? && !current_user.scoped? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
1
+ - if current_user.scoped_site? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
2
2
  .site_chooser
3
3
  %ul.nav
4
4
  %li
5
5
  = "Current Site: #{current_site.name}"
6
6
  %ul.expansion
7
- - Site.all.each do |site|
7
+ - current_user.sites.each do |site|
8
8
  %li
9
9
  = link_to( site.name, "#{request.path}?site_id=#{site.id}", :class => site == current_site ? 'fg site-link' : 'site-link')
@@ -1,3 +1,5 @@
1
+ = javascript_include_tag 'admin/validations/scheduled_status_validation'
2
+
1
3
  = fields.hidden_field :lock_version
2
4
  = fields.hidden_field :parent_id
3
5
  = fields.hidden_field :class_name
@@ -41,16 +43,23 @@
41
43
  = fields.label :class_name, t('page_type')
42
44
  = fields.select :class_name, [[t('select.normal'), '']] + Page.descendants.map { |p| [p.display_name, p.name] }.sort_by { |p| p.first }
43
45
  - layout.edit_status do
44
- .status
45
- = fields.label :status_id, t('status')
46
- = fields.select :status_id, status_to_display
46
+ - if current_user.admin? || current_user.editor?
47
+ .status
48
+ = fields.label :status_id, t('status')
49
+ = fields.select :status_id, Status.selectable.map { |s| [s.name, s.id] }
47
50
  - layout.edit_published_at do
48
51
  .published-date
49
- #published_at{:class => (@page.published? ? nil : 'hidden')}
50
- = fields.label :published_at, t('published_on')
51
- = fields.text_field :published_at, :class=> 'date', :type=>'date', :value => (@page.published_at? ? I18n.localize(@page.published_at.to_date, :format =>:default) : nil)
52
+ #published_at{:class => (@page.published? ? '' : 'hidden')}
53
+ = fields.label :published_at, t('publish_datetime')
54
+ = fields.text_field :published_at,
55
+ class: 'datetime',
56
+ type: 'datetime-local',
57
+ value: (@page.published_at? ? @page.published_at.strftime('%Y-%m-%dT%H:%M') : nil)
52
58
  = render_region :layout_row, :locals => {:f => fields}
53
59
 
60
+ .error.hidden
61
+ %span#published-at-error
62
+
54
63
  - render_region :form_bottom, :locals => {:f => fields} do |form_bottom|
55
64
  - form_bottom.edit_buttons do
56
65
  - @buttons_partials.each do |partial|
@@ -18,5 +18,5 @@
18
18
  - unless simple
19
19
  %td.actions
20
20
  = page.add_child_option
21
- - if current_user.admin?
21
+ - if current_user.editor? || current_user.admin?
22
22
  = page.remove_option
@@ -1,5 +1,6 @@
1
1
  - unless current_user.site
2
2
  %label{:for=>'snippet_site_id', :Class => 'admin_only'}
3
3
  Site
4
- - sites = Site.all.map { |s| [s.name, s.id] }
4
+ - user_sites = current_user.admins_sites.pluck(:site_id)
5
+ - sites = Site.where(:id => user_sites).map { |s| [s.name, s.id] }
5
6
  = select :snippet, :site_id, sites, :include_blank => Snippet.is_shareable?, :selected => @snippet.site_id || current_site.id
@@ -1,4 +1,5 @@
1
1
  - if current_user.admin?
2
2
  %label{:for=>'user_admin'} Can edit site
3
- = select :user, :site_id, [['<any>', '']] + Site.all.map { |s| [s.name, s.id] }
3
+ .caption (hold ctrl or cmd to select multiple)
4
4
  .caption A user with no site is able to act (to whatever extent their status allows) on any site.
5
+ = select :user, :site_ids, options_for_select(Site.all.map { |s| [s.name, s.id] }, selected: @user.site_ids), {}, { multiple: true }
@@ -25,7 +25,9 @@
25
25
  = f.check_box 'admin', :class => 'checkbox'
26
26
  = f.label :admin, t('admin'), :class => 'checkbox'
27
27
  = f.check_box 'designer', :class => 'checkbox'
28
- = f.label :designer, t('designer'), :class => 'checkbox'
28
+ = f.label :designer, t('editor'), :class => 'checkbox'
29
+ = f.check_box 'content_editor', :class => 'checkbox'
30
+ = f.label :content_editor, t('content_editor'), :class => 'checkbox'
29
31
 
30
32
  - form.edit_notes do
31
33
  %fieldset
data/bin/rails CHANGED
@@ -3,8 +3,8 @@
3
3
  # installed from the root of your application.
4
4
 
5
5
  ENGINE_ROOT = File.expand_path('..', __dir__)
6
- ENGINE_PATH = File.expand_path('../lib/trusty/cms/engine', __dir__)
7
- APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/trusty_cms/engine', __dir__)
7
+ APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
8
8
 
9
9
  # Set up gems listed in the Gemfile.
10
10
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
@@ -20,6 +20,7 @@ module TrustyCms
20
20
  Rails.autoloaders.log!
21
21
  # Enable the asset pipeline
22
22
  config.assets.enabled = true
23
+ config.active_record.legacy_connection_handling = false
23
24
 
24
25
  # Version of your assets, change this if you want to expire all your assets
25
26
  config.assets.version = '1.0'
@@ -187,7 +187,7 @@ Devise.setup do |config|
187
187
  # ==> Configuration for :timeoutable
188
188
  # The time you want to timeout the user session without activity. After this
189
189
  # time the user will be asked for credentials again. Default is 30 minutes.
190
- # config.timeout_in = 30.minutes
190
+ config.timeout_in = 8.hours
191
191
 
192
192
  # ==> Configuration for :lockable
193
193
  # Defines which strategy will be used to lock an account.