diff --git a/app/assets/javascripts/locomotive/views/roles/edit_view.js.coffee b/app/assets/javascripts/locomotive/views/roles/edit_view.js.coffee
new file mode 100644
index 0000000000..7ed118fc45
--- /dev/null
+++ b/app/assets/javascripts/locomotive/views/roles/edit_view.js.coffee
@@ -0,0 +1,17 @@
+#= require ../shared/form_view
+
+Locomotive.Views.Roles ||= {}
+
+class Locomotive.Views.Roles.EditView extends Locomotive.Views.Shared.FormView
+
+ el: '.main'
+
+ initialize: ->
+ tree = @$('.tree-view-div').tree(
+ primaryKey: 'id',
+ uiLibrary: 'bootstrap',
+ dataSource: JSON.parse(@$('.tree-view-div').attr('data-source')),
+ checkboxes: true)
+
+ @$('.edit_role').on 'submit', (e) ->
+ $('.role-pages-input').val(tree.getCheckedNodes())
\ No newline at end of file
diff --git a/app/assets/javascripts/locomotive/views/roles/new_view.js.coffee b/app/assets/javascripts/locomotive/views/roles/new_view.js.coffee
new file mode 100644
index 0000000000..f7f4b9e036
--- /dev/null
+++ b/app/assets/javascripts/locomotive/views/roles/new_view.js.coffee
@@ -0,0 +1,17 @@
+#= require ../shared/form_view
+
+Locomotive.Views.Roles ||= {}
+
+class Locomotive.Views.Roles.NewView extends Locomotive.Views.Shared.FormView
+
+ el: '.main'
+
+ initialize: ->
+ tree = @$('.tree-view-div').tree(
+ primaryKey: 'id',
+ uiLibrary: 'bootstrap',
+ dataSource: JSON.parse(@$('.tree-view-div').attr('data-source')),
+ checkboxes: true)
+
+ @$('.edit_role').on 'submit', (e) ->
+ $('.role-pages-input').val(tree.getCheckedNodes())
\ No newline at end of file
diff --git a/app/controllers/locomotive/accounts_controller.rb b/app/controllers/locomotive/accounts_controller.rb
index 101c1422a7..14344370ab 100644
--- a/app/controllers/locomotive/accounts_controller.rb
+++ b/app/controllers/locomotive/accounts_controller.rb
@@ -12,7 +12,7 @@ def new
def create
authorize Membership
@account = Account.create(account_params)
- service.create(@account) if @account.errors.empty?
+ service.create(@account,params[:account][:role_id]) if @account.errors.empty?
respond_with @account, location: edit_current_site_path(current_site)
end
diff --git a/app/controllers/locomotive/concerns/membership_controller.rb b/app/controllers/locomotive/concerns/membership_controller.rb
index 87edd782af..71dbacaccf 100644
--- a/app/controllers/locomotive/concerns/membership_controller.rb
+++ b/app/controllers/locomotive/concerns/membership_controller.rb
@@ -22,6 +22,11 @@ def current_membership
end
end
+ def current_role
+ return nil if current_membership.nil?
+ current_membership.role
+ end
+
def validate_site_membership
return true if current_membership.try(:site).present?
diff --git a/app/controllers/locomotive/editable_elements_controller.rb b/app/controllers/locomotive/editable_elements_controller.rb
index 2bfac12bac..d20bcb5711 100644
--- a/app/controllers/locomotive/editable_elements_controller.rb
+++ b/app/controllers/locomotive/editable_elements_controller.rb
@@ -8,6 +8,7 @@ class EditableElementsController < BaseController
before_action :load_page
after_action :store_location_if_content_entry
+ before_action :validate_pages_access, only: [:index]
layout :editable_elements_layout
@@ -72,5 +73,14 @@ def store_location_if_content_entry
store_location if @content_entry
end
+ protected
+ def validate_pages_access
+ return true if current_role.is_admin?
+ if current_role.role_pages.exclude? @page.id.to_s
+ flash[:alert] = "You have no access to #{ @page.title.to_s.titleize }"
+ redirect_to dashboard_url(current_site) and return false
+ end
+ end
+
end
end
diff --git a/app/controllers/locomotive/memberships_controller.rb b/app/controllers/locomotive/memberships_controller.rb
index a5d5d2eb0c..cc3c059d53 100644
--- a/app/controllers/locomotive/memberships_controller.rb
+++ b/app/controllers/locomotive/memberships_controller.rb
@@ -13,10 +13,10 @@ def new
def create
authorize Membership
- if @membership = service.create(membership_params[:email])
+ if @membership = service.create(membership_params[:email],membership_params[:role_id])
respond_with @membership, location: edit_current_site_path(current_site), flash: true
else
- redirect_to new_account_path(email: membership_params[:email])
+ redirect_to new_account_path(email: membership_params[:email],role_id: membership_params[:role_id])
end
end
@@ -26,7 +26,7 @@ def edit
def update
authorize @membership
- self.service.change_role(@membership, membership_params[:role])
+ self.service.change_role(@membership, membership_params[:role_id])
respond_with @membership, location: edit_current_site_path
end
diff --git a/app/controllers/locomotive/roles_controller.rb b/app/controllers/locomotive/roles_controller.rb
new file mode 100644
index 0000000000..9a5e0e72aa
--- /dev/null
+++ b/app/controllers/locomotive/roles_controller.rb
@@ -0,0 +1,62 @@
+module Locomotive
+ class RolesController < BaseController
+
+ account_required & within_site
+
+ before_action :load_role, only: [:edit, :update, :destroy]
+
+ def new
+ authorize Role
+ @role = current_site.roles.build
+ respond_with @role
+ end
+
+ def create
+ authorize Role
+ if @role = service.create(role_params)
+ respond_with @role, location: edit_current_site_path(:anchor => "role"), flash: true
+ else
+ redirect_to new_role_path(current_site)
+ end
+ end
+
+ def edit
+ respond_with @role
+ end
+
+ def update
+ authorize @role
+ self.service.update(@role, role_params)
+ respond_with @role, location: edit_current_site_path(:anchor => "role")
+ end
+
+ def destroy
+ authorize @role
+ @role.destroy
+ respond_with @role, location: edit_current_site_path(:anchor => "role")
+ end
+
+ def new_model
+ if params[:role_model].present?
+ render partial: 'role_models', locals: { role_model: params[:role_model] }
+ else
+ head :unprocessable_entity
+ end
+ end
+
+ protected
+
+ def service
+ @service ||= Locomotive::RoleService.new(current_site, current_locomotive_account)
+ end
+
+ def load_role
+ @role = current_site.roles.find(params[:id])
+ end
+
+ def role_params
+ params.require(:role).permit(*policy(@role || Role).permitted_attributes)
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/app/helpers/locomotive/accounts_helper.rb b/app/helpers/locomotive/accounts_helper.rb
index 80dd709e70..cd832c856b 100644
--- a/app/helpers/locomotive/accounts_helper.rb
+++ b/app/helpers/locomotive/accounts_helper.rb
@@ -5,5 +5,14 @@ def options_for_account
current_site.accounts.collect { |a| ["#{a.name} <#{a.email}>", a.id.to_s] }
end
+ def options_for_membership_roles
+ roles_arr = [].tap do |options|
+ current_site.roles.each do |role|
+ options << [role.name.capitalize, role.id.to_s]
+ end
+ end
+ roles_arr.sort!
+ end
+
end
end
diff --git a/app/helpers/locomotive/dashboard_helper.rb b/app/helpers/locomotive/dashboard_helper.rb
index a49ff1fd23..a40add43fa 100644
--- a/app/helpers/locomotive/dashboard_helper.rb
+++ b/app/helpers/locomotive/dashboard_helper.rb
@@ -21,6 +21,7 @@ def activity_to_icon(activity)
when 'content_entry' then activity.action == 'created_public' ? 'fa-comment' : 'fa-archive'
when 'content_asset' then 'fa-image'
when 'membership' then 'fa-user'
+ when 'role' then 'fa-user'
when 'site_metafields' then current_site_metafields_ui[:icon]
end
end
@@ -36,6 +37,8 @@ def render_activity_sentence(activity)
when 'content_asset.destroyed' then { name: activity_emphasize(params[:name]) }
when 'membership.created' then { name: activity_emphasize(params[:name]) }
when 'site_metafields.updated' then { label: current_site_metafields_ui[:label].downcase }
+ when 'role.created' then { name: activity_emphasize(params[:name]) }
+ when 'role.updated' then { name: activity_emphasize(params[:name]) }
end
activity_key_to_sentence(activity.key, options)
diff --git a/app/helpers/locomotive/memberships_helper.rb b/app/helpers/locomotive/memberships_helper.rb
index 19a28664b6..ee76ea9fcd 100644
--- a/app/helpers/locomotive/memberships_helper.rb
+++ b/app/helpers/locomotive/memberships_helper.rb
@@ -1,18 +1,13 @@
module Locomotive
module MembershipsHelper
- def options_for_membership_roles(membership)
- current_role = membership.role
-
- [].tap do |options|
- Locomotive::Membership::ROLES.each do |role|
- membership.role = role
- if policy(membership).change_role?
- options << [t("locomotive.memberships.roles.#{role}"), role.to_s]
- end
+ def options_for_membership_roles
+ roles_arr = [].tap do |options|
+ current_site.roles.each do |role|
+ options << [role.name.capitalize, role.id.to_s]
end
- membership.role = current_role
end
+ roles_arr.sort!
end
end
diff --git a/app/helpers/locomotive/roles_helper.rb b/app/helpers/locomotive/roles_helper.rb
new file mode 100644
index 0000000000..afcafde837
--- /dev/null
+++ b/app/helpers/locomotive/roles_helper.rb
@@ -0,0 +1,22 @@
+module Locomotive
+ module RolesHelper
+
+ def options_for_role_models
+ [].tap do |options|
+ Locomotive::ContentTypeService.new(current_site).list.each do |model|
+ options << [model.slug.titleize,model.slug]
+ end
+ end
+ end
+
+ def options_for_role_pages(role, pages)
+ collection = []
+ pages.each do |page|
+ children_page = page.children
+ collection << { id: page.id.to_s, text: page.title, checked: (role.role_pages.to_a.include? page.id.to_s) , hasChildren: children_page.present? , children: options_for_role_pages(role, children_page) }
+ end
+ collection
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/app/helpers/locomotive/shared/pages_helper.rb b/app/helpers/locomotive/shared/pages_helper.rb
index 907f393535..6316aab238 100644
--- a/app/helpers/locomotive/shared/pages_helper.rb
+++ b/app/helpers/locomotive/shared/pages_helper.rb
@@ -39,7 +39,7 @@ def render_pages
end
def build_page_tree
- @page_tree ||= Locomotive::PageTreeService.new(current_site).build_tree
+ @page_tree ||= Locomotive::PageTreeService.new(current_site,current_membership).build_tree
end
class Node < Struct.new(:page, :children, :controller)
diff --git a/app/inputs/locomotive/tree_view_input.rb b/app/inputs/locomotive/tree_view_input.rb
new file mode 100644
index 0000000000..75ab16a20e
--- /dev/null
+++ b/app/inputs/locomotive/tree_view_input.rb
@@ -0,0 +1,40 @@
+module Locomotive
+ class TreeViewInput < ::SimpleForm::Inputs::Base
+
+ include Locomotive::SimpleForm::BootstrapHelpers
+ include Locomotive::SimpleForm::HeaderLink
+ include Locomotive::SimpleForm::Inputs::FasterTranslate
+
+ def input(wrapper_options)
+ hidden_input + tree_view_wrapper
+ end
+
+ def hidden_input
+ _template = options[:template]
+ template_path = _template.respond_to?(:has_key?) ? _template[:path].to_s : _template.to_s
+ template.render(template_path).html_safe
+ end
+
+ def tree_view_wrapper
+ row_wrapping do
+ template.content_tag :div,
+ tree_view_html,
+ class: tree_view_wrapper_class
+ end
+ end
+
+ def tree_view_wrapper_class
+ %w(col-md-12).tap do |wrapper_class|
+ end.join(' ')
+ end
+
+ def tree_view_html
+ template.content_tag :div, '', class: 'tree-view-div', 'data-source': options[:source_options].to_json
+ end
+
+ def link(wrapper_options)
+
+ end
+
+ end
+end
diff --git a/app/models/locomotive/account.rb b/app/models/locomotive/account.rb
index 8c0ca5c39b..5949d3b0cd 100644
--- a/app/models/locomotive/account.rb
+++ b/app/models/locomotive/account.rb
@@ -26,6 +26,7 @@ class Account
field :name
field :locale, default: Locomotive.config.default_locale.to_s or 'en'
field :super_admin, type: Boolean, default: false
+ attr_reader :role_id
## validations ##
validates_presence_of :name
diff --git a/app/models/locomotive/concerns/membership/role.rb b/app/models/locomotive/concerns/membership/role.rb
new file mode 100644
index 0000000000..dab5c1cdcb
--- /dev/null
+++ b/app/models/locomotive/concerns/membership/role.rb
@@ -0,0 +1,27 @@
+module Locomotive
+ module Concerns
+ module Membership
+ module Role
+
+ extend ActiveSupport::Concern
+
+ included do
+
+ end
+
+ def to_role
+ role_name.to_sym
+ end
+
+ def role_name
+ self.role.try(:name).to_s
+ end
+
+ def role_name=(role)
+ self.role.name = role
+ end
+
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/models/locomotive/concerns/role/role_models.rb b/app/models/locomotive/concerns/role/role_models.rb
new file mode 100644
index 0000000000..499a83ee96
--- /dev/null
+++ b/app/models/locomotive/concerns/role/role_models.rb
@@ -0,0 +1,15 @@
+module Locomotive
+ module Concerns
+ module Role
+ module RoleModels
+
+ extend ActiveSupport::Concern
+
+ included do
+ field :role_models, type: ::RawArray, default: []
+ end
+
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/models/locomotive/concerns/role/role_pages.rb b/app/models/locomotive/concerns/role/role_pages.rb
new file mode 100644
index 0000000000..d954032624
--- /dev/null
+++ b/app/models/locomotive/concerns/role/role_pages.rb
@@ -0,0 +1,19 @@
+module Locomotive
+ module Concerns
+ module Role
+ module RolePages
+
+ extend ActiveSupport::Concern
+
+ included do
+ field :role_pages, type: ::RawArray, default: []
+ end
+
+ def role_pages_str=(pages_str)
+ self.role_pages = pages_str.split(',')
+ end
+
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/models/locomotive/membership.rb b/app/models/locomotive/membership.rb
index 95eb02d862..4e24e5d20d 100644
--- a/app/models/locomotive/membership.rb
+++ b/app/models/locomotive/membership.rb
@@ -2,34 +2,34 @@ module Locomotive
class Membership
include Locomotive::Mongoid::Document
+ include Concerns::Membership::Role
ROLES = %w(author designer admin)
- ## fields ##
- field :role, default: 'author'
-
## associations ##
belongs_to :account, class_name: 'Locomotive::Account', validate: false
embedded_in :site, class_name: 'Locomotive::Site', inverse_of: :memberships
+ belongs_to :role, class_name: 'Locomotive::Role', validate: false
## validations ##
validates_presence_of :account
validate :account_is_unique
-
+ validates_presence_of :role_id
## virtual attributes ##
attr_accessor :email
- ## callbacks ##
- before_save :define_role
-
## methods ##
ROLES.each do |_role|
define_method("#{_role}?") do
- self.role == _role
+ self.role_name == _role
end
end
+ def is_admin?
+ self.role.try(:name) == 'admin'
+ end
+
def to_role
self.role.to_sym
end
@@ -44,9 +44,5 @@ def account_is_unique
end
end
- def define_role
- self.role = ROLES.include?(role.downcase) ? role.downcase : ROLES.first
- end
-
end
end
diff --git a/app/models/locomotive/role.rb b/app/models/locomotive/role.rb
new file mode 100644
index 0000000000..eb7960b18d
--- /dev/null
+++ b/app/models/locomotive/role.rb
@@ -0,0 +1,22 @@
+module Locomotive
+ class Role
+
+ include Locomotive::Mongoid::Document
+
+ ## Extensions ##
+ include Concerns::Role::RoleModels
+ include Concerns::Role::RolePages
+
+ belongs_to :site, class_name: 'Locomotive::Site'
+
+ ## behaviours ##
+ #accepts_nested_attributes_for :role_models,:role_pages, allow_destroy: true
+
+ field :name , type: String, default: ''
+
+ def is_admin?
+ self.try(:name) == 'admin'
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/app/models/locomotive/site.rb b/app/models/locomotive/site.rb
index b456080d4a..ceb6ff0481 100644
--- a/app/models/locomotive/site.rb
+++ b/app/models/locomotive/site.rb
@@ -32,6 +32,7 @@ class Site
has_many :content_entries, class_name: 'Locomotive::ContentEntry', dependent: :destroy, validate: false, autosave: false
has_many :translations, class_name: 'Locomotive::Translation', dependent: :destroy, validate: false, autosave: false
has_many :activities, class_name: 'Locomotive::Activity', dependent: :destroy, validate: false, autosave: false
+ has_many :roles, class_name: 'Locomotive::Role', dependent: :destroy, validate: false, order: :name.asc
## validations ##
validates_presence_of :name
@@ -41,7 +42,7 @@ class Site
before_destroy :destroy_pages
## behaviours ##
- accepts_nested_attributes_for :memberships, allow_destroy: true
+ accepts_nested_attributes_for :memberships, :roles, allow_destroy: true
## methods ##
diff --git a/app/policies/locomotive/membership_policy.rb b/app/policies/locomotive/membership_policy.rb
index a7a2d117e5..824b481d43 100644
--- a/app/policies/locomotive/membership_policy.rb
+++ b/app/policies/locomotive/membership_policy.rb
@@ -17,16 +17,13 @@ def destroy?
site_admin? && change_role?
end
- # The role cannot be set higher than the current one (we use the index in
- # the roles array to check role presidence)
def change_role?
- roles = Locomotive::Membership::ROLES
- roles.index(resource.role.to_s) <= roles.index(membership.role.to_s)
+ site_admin?
end
def permitted_attributes
if site_admin?
- [:email, :role]
+ [:email, :role_id]
else
[]
end
diff --git a/app/policies/locomotive/role_policy.rb b/app/policies/locomotive/role_policy.rb
new file mode 100644
index 0000000000..2b92514214
--- /dev/null
+++ b/app/policies/locomotive/role_policy.rb
@@ -0,0 +1,37 @@
+module Locomotive
+ class RolePolicy < ApplicationPolicy
+
+ def index?
+ site_admin?
+ end
+
+ def new?
+ site_admin?
+ end
+
+ def create?
+ site_admin?
+ end
+
+ def edit?
+ site_admin? and !@resource.is_admin?
+ end
+
+ def update?
+ site_admin?
+ end
+
+ def destroy?
+ site_admin?
+ end
+
+ def permitted_attributes
+ if site_admin?
+ [ :name, :role_pages_str, :superior_id, role_models: [] ]
+ else
+ []
+ end
+ end
+
+ end
+end
diff --git a/app/policies/locomotive/site_policy.rb b/app/policies/locomotive/site_policy.rb
index 0909a1adaf..437c8b8fe3 100644
--- a/app/policies/locomotive/site_policy.rb
+++ b/app/policies/locomotive/site_policy.rb
@@ -41,6 +41,10 @@ def update_advanced?
super_admin? || site_admin?
end
+ def update_role?
+ super_admin? || site_admin?
+ end
+
def show_developers_documentation?
super_admin? || site_admin?
end
diff --git a/app/services/locomotive/membership_service.rb b/app/services/locomotive/membership_service.rb
index b176494c21..9107bbd913 100644
--- a/app/services/locomotive/membership_service.rb
+++ b/app/services/locomotive/membership_service.rb
@@ -12,7 +12,7 @@ class MembershipService < Struct.new(:site, :policy)
#
# @return [ Object ] A new membership (with errors or not) or nil (no account found)
#
- def create(email_or_account)
+ def create(email_or_account,role_id)
_account = if email_or_account.respond_to?(:email)
email_or_account
else
@@ -20,7 +20,7 @@ def create(email_or_account)
end
if _account
- site.memberships.create(account: _account, email: _account.email).tap do |success|
+ site.memberships.create(account: _account, email: _account.email,role_id: role_id).tap do |success|
if success
track_activity 'membership.created', parameters: { name: _account.name, email: _account.email }
end
@@ -42,15 +42,15 @@ def create(email_or_account)
#
# @return [ Boolean] True if everything went well
#
- def change_role(membership, role)
- membership.role = role if role.present?
-
- if role.present? && policy.change_role?
+ def change_role(membership, role_id)
+ if site.roles.where(id:role_id).present? && policy.change_role?
+ membership.role_id = role_id
membership.save
else
membership.errors.add(:role, :invalid)
false
end
+
end
def account
diff --git a/app/services/locomotive/page_tree_service.rb b/app/services/locomotive/page_tree_service.rb
index 488028243f..0704a9dd3c 100644
--- a/app/services/locomotive/page_tree_service.rb
+++ b/app/services/locomotive/page_tree_service.rb
@@ -1,6 +1,6 @@
module Locomotive
- class PageTreeService < Struct.new(:site)
+ class PageTreeService < Struct.new(:site,:membership)
# Returns the tree of pages from the site with the most minimal amount of queries.
# This method should only be used for read-only purpose since
@@ -10,7 +10,7 @@ class PageTreeService < Struct.new(:site)
# @return [ Array ] The first array of pages (index + page not found + pages with depth == 1)
#
def build_tree
- pages, page_not_found = pages_with_minimun_attributes, nil
+ pages, page_not_found = pages_with_minimun_attributes, site.pages.where(:title.in => ["Page not found"]).first
[].tap do |tree|
while page = pages.shift
@@ -33,10 +33,11 @@ def build_tree
#:nodoc:
def pages_with_minimun_attributes
- site.pages.unscoped.
- minimal_attributes.
- order_by_depth_and_position.
- to_a
+ if membership.role.is_admin?
+ site.pages.unscoped.minimal_attributes.order_by_depth_and_position.to_a
+ else
+ site.pages.unscoped.in(id:membership.role.role_pages).minimal_attributes.order_by_depth_and_position.to_a
+ end
end
#:nodoc:
diff --git a/app/services/locomotive/role_service.rb b/app/services/locomotive/role_service.rb
new file mode 100644
index 0000000000..30a43f3ba2
--- /dev/null
+++ b/app/services/locomotive/role_service.rb
@@ -0,0 +1,30 @@
+module Locomotive
+ class RoleService < Struct.new(:site, :account)
+
+ include Locomotive::Concerns::ActivityService
+
+ def create(attributes, raise_if_not_valid = false)
+ attributes[:name] = attributes[:name].to_s.downcase
+ site.roles.new(attributes).tap do |role|
+ success = raise_if_not_valid ? role.save! : role.save
+ track_activity 'role.created', parameters: { name: role.name.capitalize } if success
+ end
+ end
+
+ def create!(attributes)
+ create(attributes, true)
+ end
+
+ def update(role, attributes, raise_if_not_valid = false)
+ attributes[:name] = attributes[:name].to_s.downcase
+ role.attributes = attributes
+ success = raise_if_not_valid ? role.save! : role.save
+ track_activity 'role.updated', parameters: { name: role.name.capitalize } if success
+ end
+
+ def update!(role, attributes)
+ update(site, attributes, true)
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/app/services/locomotive/site_service.rb b/app/services/locomotive/site_service.rb
index 491698269d..e245fdbc07 100644
--- a/app/services/locomotive/site_service.rb
+++ b/app/services/locomotive/site_service.rb
@@ -31,8 +31,10 @@ def create(attributes, raise_if_not_valid = false)
Site.new(attributes).tap do |site|
site.created_by = account
- site.memberships.build account: account, role: 'admin'
-
+ admin_role = site.roles.build name: 'admin'
+ site.memberships.build account: account, role: admin_role
+ site.roles.build name: 'author'
+ site.roles.build name: 'designer'
success = raise_if_not_valid ? site.save! : site.save
ActiveSupport::Notifications.instrument 'locomotive.site.created', account: account, site: site
diff --git a/app/views/locomotive/accounts/new.html.slim b/app/views/locomotive/accounts/new.html.slim
index e3596f7fd6..3a7ec8eeb1 100644
--- a/app/views/locomotive/accounts/new.html.slim
+++ b/app/views/locomotive/accounts/new.html.slim
@@ -12,6 +12,7 @@
- if f.object.respond_to?(:password)
= f.input :email
+ = f.input :role_id, as: :select, collection: options_for_membership_roles, selected: params[:role_id] ,include_blank: false
= f.input :password, input_html: { autocomplete: 'off' }
= f.input :password_confirmation, input_html: { autocomplete: 'off' }
diff --git a/app/views/locomotive/current_site/_membership.html.slim b/app/views/locomotive/current_site/_membership.html.slim
index db6d4fab31..8a02d98ba7 100644
--- a/app/views/locomotive/current_site/_membership.html.slim
+++ b/app/views/locomotive/current_site/_membership.html.slim
@@ -11,7 +11,7 @@
|
small
span.label.label-default
- = t(membership.role, scope: 'locomotive.memberships.roles')
+ = membership.role.name.capitalize
br
small
= membership.account.email
diff --git a/app/views/locomotive/current_site/_role.html.slim b/app/views/locomotive/current_site/_role.html.slim
new file mode 100644
index 0000000000..8d7de6027d
--- /dev/null
+++ b/app/views/locomotive/current_site/_role.html.slim
@@ -0,0 +1,10 @@
+.item.row
+ .inner-row.col-md-12
+ .text
+ strong= role.name.to_s.titleize
+ .buttons
+ - if policy(role).edit?
+ = link_to t(:edit, scope: 'locomotive.inputs.array'), edit_role_path(current_site, role), class: 'choose btn btn-primary btn-sm'
+ |
+ = link_to role_path(current_site, role), class: 'delete', data: { confirm: t('locomotive.messages.confirm') }, method: :delete do
+ i.far.fa-trash-alt
\ No newline at end of file
diff --git a/app/views/locomotive/current_site/form/_panes.html.slim b/app/views/locomotive/current_site/form/_panes.html.slim
index c7cd525f3a..d9dc421ad4 100644
--- a/app/views/locomotive/current_site/form/_panes.html.slim
+++ b/app/views/locomotive/current_site/form/_panes.html.slim
@@ -1,4 +1,4 @@
.tab-content
- - %w(main access_points seo url_redirections advanced).each_with_index do |name, index|
+ - %w(main access_points seo url_redirections advanced role).each_with_index do |name, index|
= form_tab_pane name.to_sym, index == 0 do
= render "locomotive/current_site/form/#{name}", f: f
diff --git a/app/views/locomotive/current_site/form/_role.html.slim b/app/views/locomotive/current_site/form/_role.html.slim
new file mode 100644
index 0000000000..8492be5993
--- /dev/null
+++ b/app/views/locomotive/current_site/form/_role.html.slim
@@ -0,0 +1,4 @@
+= f.inputs :information do
+ = f.input :roles, as: :array, template: :role, new_item: policy(Locomotive::Role).create? ? { label: t('.new_role'), url: new_role_path(current_site) } : nil, wrapper_html: { class: 'roles' }
+= f.actions do
+ = f.action
diff --git a/app/views/locomotive/current_site/form/_tabs.html.slim b/app/views/locomotive/current_site/form/_tabs.html.slim
index dde0bc576c..6946560feb 100644
--- a/app/views/locomotive/current_site/form/_tabs.html.slim
+++ b/app/views/locomotive/current_site/form/_tabs.html.slim
@@ -15,3 +15,7 @@ ul.nav.nav-tabs role='tablist'
- if policy(@site).update_advanced?
= form_nav_tab :advanced do
= link_to t('simple_form.titles.locomotive.site.advanced'), '#advanced', role: 'tab', data: { toggle: 'tab' }
+
+ - if policy(@site).update_role?
+ = form_nav_tab :role do
+ = link_to t('simple_form.titles.locomotive.site.role'), '#role', role: 'tab', data: { toggle: 'tab' }
\ No newline at end of file
diff --git a/app/views/locomotive/memberships/edit.html.slim b/app/views/locomotive/memberships/edit.html.slim
index 2a58ac88ad..a903159e02 100644
--- a/app/views/locomotive/memberships/edit.html.slim
+++ b/app/views/locomotive/memberships/edit.html.slim
@@ -5,7 +5,7 @@
= locomotive_form_for @membership, url: membership_path(current_site, @membership) do |f|
= f.inputs :membership_email, class: 'inputs email' do
- = f.input :role, as: :select, collection: options_for_membership_roles(@membership), include_blank: false
+ = f.association :role, collection: options_for_membership_roles, include_blank: false
= f.actions do
.row
diff --git a/app/views/locomotive/memberships/new.html.slim b/app/views/locomotive/memberships/new.html.slim
index 00d38cb647..d45b6df998 100644
--- a/app/views/locomotive/memberships/new.html.slim
+++ b/app/views/locomotive/memberships/new.html.slim
@@ -6,6 +6,7 @@
= f.inputs :membership_email, class: 'inputs email' do
= f.input :email, input_html: { class: 'input-lg' }
+ = f.association :role, collection: options_for_membership_roles, include_blank: false
= f.actions do
.row
diff --git a/app/views/locomotive/roles/_role_models.html.slim b/app/views/locomotive/roles/_role_models.html.slim
new file mode 100644
index 0000000000..f2a5c51664
--- /dev/null
+++ b/app/views/locomotive/roles/_role_models.html.slim
@@ -0,0 +1,11 @@
+.item.row data-id=role_model
+
+ = hidden_field_tag 'role[role_models][]', role_model
+
+ .inner-row.col-md-12
+
+ .text
+ = role_model.titleize
+ .buttons
+ = link_to '#', class: 'delete' do
+ i.fa.fa-trash-o
\ No newline at end of file
diff --git a/app/views/locomotive/roles/_role_pages.html.slim b/app/views/locomotive/roles/_role_pages.html.slim
new file mode 100644
index 0000000000..256e2506fa
--- /dev/null
+++ b/app/views/locomotive/roles/_role_pages.html.slim
@@ -0,0 +1 @@
+= hidden_field_tag 'role[role_pages_str]', '', class: 'role-pages-input'
\ No newline at end of file
diff --git a/app/views/locomotive/roles/edit.html.slim b/app/views/locomotive/roles/edit.html.slim
new file mode 100644
index 0000000000..f12a8ba58c
--- /dev/null
+++ b/app/views/locomotive/roles/edit.html.slim
@@ -0,0 +1,20 @@
+link rel="stylesheet" media="screen, projection" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
+link rel="stylesheet" media="screen, projection" href="https://cdn.jsdelivr.net/npm/gijgo@1.9.10/css/gijgo.min.css"
+script src='https://cdnjs.cloudflare.com/ajax/libs/gijgo/1.9.6/combined/js/gijgo.min.js'
+
+- title t('.title', name: @role.name.titleize)
+
+= help t('.help', default: '')
+
+= locomotive_form_for @role, url: role_path(current_site, @role) do |f|
+ = f.inputs :role, class: 'inputs' do
+ = f.input :name
+ = f.input :role_models, as: :array, label: t('.models_access'), template: :role_models, select_options: options_for_role_models, template_url: new_model_roles_path(current_site)
+ = f.input :role_pages, as: :tree_view, label: t('.pages_access'), source_options: options_for_role_pages(f.object,current_site.pages.where(depth:0).where(:title.nin => ["Page not found"]).order_by(name: 'asc')), template: :role_pages
+
+ = f.actions do
+ .row
+ .col-md-6.text-left
+ = link_to "← #{t('.back')}".html_safe, edit_current_site_path(current_site)
+ .col-md-6.text-right
+ = f.action
\ No newline at end of file
diff --git a/app/views/locomotive/roles/new.html.slim b/app/views/locomotive/roles/new.html.slim
new file mode 100644
index 0000000000..34aa1a5dc3
--- /dev/null
+++ b/app/views/locomotive/roles/new.html.slim
@@ -0,0 +1,19 @@
+link rel="stylesheet" media="screen, projection" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
+link rel="stylesheet" media="screen, projection" href="https://cdn.jsdelivr.net/npm/gijgo@1.9.10/css/gijgo.min.css"
+script src='https://cdnjs.cloudflare.com/ajax/libs/gijgo/1.9.6/combined/js/gijgo.min.js'
+
+- title t('.title')
+= help t('.help', default: '')
+
+= locomotive_form_for @role, url: roles_path(current_site) do |f|
+ = f.inputs :role, class: 'inputs' do
+ = f.input :name
+ = f.input :role_models, as: :array, label: 'Models Access', template: :role_models, select_options: options_for_role_models, template_url: new_model_roles_path(current_site)
+ = f.input :role_pages, as: :tree_view, label: 'Pagges Access', source_options: options_for_role_pages(f.object,current_site.pages.where(depth:0).where(:title.nin => ["Page not found"]).order_by(name: 'asc')), template: :role_pages
+
+ = f.actions do
+ .row
+ .col-md-6.text-left
+ = link_to "← #{t('.back')}".html_safe, edit_current_site_path(current_site)
+ .col-md-6.text-right
+ = f.action
\ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8ead90890c..d21a44fdae 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -117,6 +117,9 @@ en:
created: 'added %{name} to the site'
site_metafields:
updated: 'updated %{label}'
+ role:
+ created: 'created the %{name} role'
+ updated: 'updated the %{name} role'
pagination:
first: "«"
@@ -265,6 +268,8 @@ en:
advanced:
destroy: "Destroy this site"
confirm_destroy: "Please confirm by typing the site name in the following input"
+ role:
+ new_role: "Add role"
current_site_metafields:
index:
@@ -284,6 +289,14 @@ en:
title: "Edit membership for %{name}"
back: "Back to your site settings"
+ roles:
+ new:
+ title: 'Add a new role'
+ back: "Back to your site settings"
+ edit:
+ title: "Edit role for %{name}"
+ back: "Back to your site settings"
+
accounts:
new:
title: New account
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 1aefb404a8..f5824c7496 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -14,6 +14,7 @@ en:
seo: SEO
advanced: Advanced
url_redirections: URL redirections
+ role: Role
page:
content: Content
settings: Settings
@@ -22,6 +23,9 @@ en:
content: Content
advanced: Advanced
seo: SEO
+ role:
+ models_access: Models Access
+ pages_access: Pages Access
labels:
locomotive:
diff --git a/config/routes.rb b/config/routes.rb
index 678890896f..e1a540c3fe 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -52,6 +52,11 @@
resources :memberships
+ resources :roles, controller: 'roles' do
+ collection do
+ get :new_model
+ end
+ end
resources :translations
resources :search_for_resources, only: [:index]
diff --git a/spec/controllers/locomotive/roles_controller_spec.rb b/spec/controllers/locomotive/roles_controller_spec.rb
new file mode 100644
index 0000000000..c75120a6ae
--- /dev/null
+++ b/spec/controllers/locomotive/roles_controller_spec.rb
@@ -0,0 +1,5 @@
+describe Locomotive::RolesController do
+
+ routes { Locomotive::Engine.routes }
+
+end
\ No newline at end of file
diff --git a/spec/factories/role.rb b/spec/factories/role.rb
new file mode 100644
index 0000000000..faf3103196
--- /dev/null
+++ b/spec/factories/role.rb
@@ -0,0 +1,10 @@
+# encoding: utf-8
+
+FactoryBot.define do
+
+ ## Memberships ##
+ factory :role, class: Locomotive::Role do
+ site { build(:site) }
+ end
+
+end
diff --git a/spec/factories/site.rb b/spec/factories/site.rb
index c8feb2e68c..39c5eea6a0 100644
--- a/spec/factories/site.rb
+++ b/spec/factories/site.rb
@@ -15,6 +15,7 @@
after(:build) do |site_test|
site_test.memberships.build account: Locomotive::Account.where(name: 'Admin').first || create('admin user'), role: 'admin'
+
end
factory 'another site' do
diff --git a/spec/models/locomotive/role_spec.rb b/spec/models/locomotive/role_spec.rb
new file mode 100644
index 0000000000..687f2d1e80
--- /dev/null
+++ b/spec/models/locomotive/role_spec.rb
@@ -0,0 +1,12 @@
+# encoding: utf-8
+
+describe Locomotive::Role do
+
+ describe 'validation' do
+ it 'store pages in array' do
+ role = create(:role, role_pages_str: '1,2,3,4')
+ expect(role.role_pages).to eq(['1','2','3','4'])
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/spec/services/locomotive/site_service_spec.rb b/spec/services/locomotive/site_service_spec.rb
index f65dd1cda1..0751c039a7 100644
--- a/spec/services/locomotive/site_service_spec.rb
+++ b/spec/services/locomotive/site_service_spec.rb
@@ -28,7 +28,8 @@
it { expect { subject }.to change { Locomotive::Site.count }.by(1) }
it { expect(subject.handle).not_to eq nil }
it { expect(subject.created_by).not_to eq nil }
-
+ it { expect(subject.roles.size).to eq(3) }
+
end
describe '#create!' do