module Scrivito # @api beta class User < Struct.new(:id, :abilities, :description_proc, :suggest_users_proc, :restriction_set) class << self # Defines a new user. # @api beta # @param [String] id the unique, unalterable id of the user. # The user id is used to associate the user with the corresponding CMS resources. # It will be persisted in the CMS. # @raise [Scrivito::ScrivitoError] if id is blank # @raise [Scrivito::ScrivitoError] if id is more than 64 characters long # @yieldparam [Scrivito::UserDefinition] user object to define abilities on # @see Scrivito::UserDefinition#can # @see Scrivito::UserDefinition#description # @example # Scrivito::User.define('alice') do |user| # user.can(:publish_workspace) { true } # end # # Scrivito::User.define('bob') do |user| # user.description { 'Bob Doe' } # user.can(:publish_workspace) { true } # end def define(id, &block) assert_valid_id(id) user_definition = UserDefinition.new(id) yield user_definition user_definition.user end def anonymous_admin User.new( id: nil, abilities: Hash.new(-> {true}).with_indifferent_access, description_proc: nil, suggest_users_proc: nil ) end def find(id) if Configuration.find_user_proc user = Scrivito::Configuration.find_user_proc.call(id) assert_valid_user(user) user end end private def assert_valid_id(id) raise ScrivitoError.new('User id can not be blank') if id.blank? raise ScrivitoError.new('User id is too long (max length 64)') if id.length > 64 end def assert_valid_user(user) unless user.is_a?(User) || user.nil? raise ScrivitoError.new("Expected an instance of #{self} or nil, but got #{user.inspect}") end end end def initialize(options) super(*options.values_at(:id, :abilities, :description_proc, :suggest_users_proc, :restriction_set)) end def able_to?(ability_name) !!abilities[ability_name].call end # Verfies if the User is able to publish changes to a certain {BasicObj Obj} # # @api beta # @param [BasicObj] obj the obj that should be published # @return [Boolean] true if the user is allowed to publish otherwise false def can_publish?(obj) restriction_messages_for(obj).empty? end # Checks if the User is able to publish changes and returns the message # specified in a {UserDefinition#restrict_obj_publish} callback if they are not # If the user can publish the obj an empty array is returned # # @api beta # @param [BasicObj] obj the obj that should be published # @return [Array] Hints why the user can't publish def restriction_messages_for(obj) return [] if able_to?(UserDefinition::ADMINISTRATE_CMS_ABILITY) if obj.modification == Modification::EDITED base_revision_obj = obj.in_revision(obj.revision.workspace.base_revision) restriction_set.restriction_messages_for(obj) | restriction_set.restriction_messages_for(base_revision_obj) else restriction_set.restriction_messages_for(obj) end end def description @description ||= calculate_description end def suggest_users(input) suggest_users_proc ? suggest_users_proc.call(input) : [] end private def calculate_description description_proc ? description_proc.call : id end end end