File: lib/redmine/safe_attributes.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Redmine#18
  module: SafeAttributes#19
has properties
module method: included / 1 #20
method: safe_attribute_names / 1 #47
method: safe_attribute? / 2 #61
method: delete_unsafe_attributes / 2 #71
method: safe_attributes= / 2 #78
  module: ClassMethods#24
has properties
method: safe_attributes / 1 #31

Code

   1  # Redmine - project management software
   2  # Copyright (C) 2006-2011  Jean-Philippe Lang
   3  #
   4  # This program is free software; you can redistribute it and/or
   5  # modify it under the terms of the GNU General Public License
   6  # as published by the Free Software Foundation; either version 2
   7  # of the License, or (at your option) any later version.
   8  #
   9  # This program is distributed in the hope that it will be useful,
  10  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  # GNU General Public License for more details.
  13  #
  14  # You should have received a copy of the GNU General Public License
  15  # along with this program; if not, write to the Free Software
  16  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17 
  18  module Redmine
  19    module SafeAttributes
  20      def self.included(base)
  21        base.extend(ClassMethods)
  22      end
  23 
  24      module ClassMethods
  25        # Declares safe attributes
  26        # An optional Proc can be given for conditional inclusion
  27        #
  28        # Example:
  29        #   safe_attributes 'title', 'pages'
  30        #   safe_attributes 'isbn', :if => {|book, user| book.author == user}
  31        def safe_attributes(*args)
  32          @safe_attributes ||= []
  33          if args.empty?
  34            @safe_attributes
  35          else
  36            options = args.last.is_a?(Hash) ? args.pop : {}
  37            @safe_attributes << [args, options]
  38          end
  39        end
  40      end
  41 
  42      # Returns an array that can be safely set by user or current user
  43      #
  44      # Example:
  45      #   book.safe_attributes # => ['title', 'pages']
  46      #   book.safe_attributes(book.author) # => ['title', 'pages', 'isbn']
  47      def safe_attribute_names(user=nil)
  48        return @safe_attribute_names if @safe_attribute_names && user.nil?
  49        names = []
  50        self.class.safe_attributes.collect do |attrs, options|
  51          if options[:if].nil? || options[:if].call(self, user || User.current)
  52            names += attrs.collect(&:to_s)
  53          end
  54        end
  55        names.uniq!
  56        @safe_attribute_names = names if user.nil?
  57        names
  58      end
  59 
  60      # Returns true if attr can be set by user or the current user
  61      def safe_attribute?(attr, user=nil)
  62        safe_attribute_names(user).include?(attr.to_s)
  63      end
  64 
  65      # Returns a hash with unsafe attributes removed
  66      # from the given attrs hash
  67      #
  68      # Example:
  69      #   book.delete_unsafe_attributes({'title' => 'My book', 'foo' => 'bar'})
  70      #   # => {'title' => 'My book'}
  71      def delete_unsafe_attributes(attrs, user=User.current)
  72        safe = safe_attribute_names(user)
  73        attrs.dup.delete_if {|k,v| !safe.include?(k)}
  74      end
  75 
  76      # Sets attributes from attrs that are safe
  77      # attrs is a Hash with string keys
  78      def safe_attributes=(attrs, user=User.current)
  79        return unless attrs.is_a?(Hash)
  80        self.attributes = delete_unsafe_attributes(attrs, user)
  81      end
  82    end
  83  end