Revision 1297:0a574315af3e .svn/pristine/3f

View differences:

.svn/pristine/3f/3f96fdb167ef6475d848f64ee14b65e8b759b8e8.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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
class Watcher < ActiveRecord::Base
19
  belongs_to :watchable, :polymorphic => true
20
  belongs_to :user
21

  
22
  validates_presence_of :user
23
  validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]
24
  validate :validate_user
25

  
26
  # Unwatch things that users are no longer allowed to view
27
  def self.prune(options={})
28
    if options.has_key?(:user)
29
      prune_single_user(options[:user], options)
30
    else
31
      pruned = 0
32
      User.find(:all, :conditions => "id IN (SELECT DISTINCT user_id FROM #{table_name})").each do |user|
33
        pruned += prune_single_user(user, options)
34
      end
35
      pruned
36
    end
37
  end
38

  
39
  protected
40

  
41
  def validate_user
42
    errors.add :user_id, :invalid unless user.nil? || user.active?
43
  end
44

  
45
  private
46

  
47
  def self.prune_single_user(user, options={})
48
    return unless user.is_a?(User)
49
    pruned = 0
50
    find(:all, :conditions => {:user_id => user.id}).each do |watcher|
51
      next if watcher.watchable.nil?
52

  
53
      if options.has_key?(:project)
54
        next unless watcher.watchable.respond_to?(:project) && watcher.watchable.project == options[:project]
55
      end
56

  
57
      if watcher.watchable.respond_to?(:visible?)
58
        unless watcher.watchable.visible?(user)
59
          watcher.destroy
60
          pruned += 1
61
        end
62
      end
63
    end
64
    pruned
65
  end
66
end
.svn/pristine/3f/3fc44a4cc04ed1435106069e4fc48b4490b1b6a0.svn-base
1
<%= form_tag({:action => 'edit', :tab => 'repositories'}) do %>
2

  
3
<fieldset class="box settings enabled_scm">
4
<legend><%= l(:setting_enabled_scm) %></legend>
5
<%= hidden_field_tag 'settings[enabled_scm][]', '' %>
6
<table>
7
  <tr>
8
    <th></th>
9
    <th><%= l(:text_scm_command)         %></th>
10
    <th><%= l(:text_scm_command_version) %></th>
11
  </tr>
12
  <% Redmine::Scm::Base.all.collect do |choice| %>
13
    <% scm_class = "Repository::#{choice}".constantize %>
14
    <% text, value = (choice.is_a?(Array) ? choice : [choice, choice]) %>
15
    <% setting = :enabled_scm %>
16
		<% enabled = Setting.send(setting).include?(value) %>
17
    <tr>
18
      <td class="scm_name">
19
        <label>
20
        <%= check_box_tag("settings[#{setting}][]", value, enabled, :id => nil) %>
21
        <%= text.to_s %>
22
        </label>
23
      </td>
24
      <td>
25
         <% if enabled %>
26
         <%=
27
           image_tag(
28
              (scm_class.scm_available ? 'true.png' : 'exclamation.png'),
29
              :style => "vertical-align:bottom;"
30
           )
31
           %>
32
          <%= scm_class.scm_command %>
33
					<% end %>
34
       </td>
35
       <td>
36
          <%= scm_class.scm_version_string if enabled %>
37
       </td>
38
     </tr>
39
  <% end %>
40
</table>
41
<p><em class="info"><%= l(:text_scm_config) %></em></p>
42
</fieldset>
43

  
44
<div class="box tabular settings">
45
<p><%= setting_check_box :autofetch_changesets %></p>
46

  
47
<p><%= setting_check_box :sys_api_enabled,
48
                         :onclick =>
49
                             "if (this.checked) { $('#settings_sys_api_key').removeAttr('disabled'); } else { $('#settings_sys_api_key').attr('disabled', true); }" %></p>
50

  
51
<p><%= setting_text_field :sys_api_key,
52
                          :size     => 30,
53
                          :id       => 'settings_sys_api_key',
54
                          :disabled => !Setting.sys_api_enabled?,
55
                          :label    => :setting_mail_handler_api_key %>
56
  <%= link_to_function l(:label_generate_key),
57
                       "if (!$('#settings_sys_api_key').attr('disabled')) { $('#settings_sys_api_key').val(randomKey(20)) }" %>
58
</p>
59

  
60
<p><%= setting_text_field :repository_log_display_limit, :size => 6 %></p>
61
</div>
62

  
63
<fieldset class="box tabular settings">
64
<legend><%= l(:text_issues_ref_in_commit_messages) %></legend>
65
<p><%= setting_text_field :commit_ref_keywords, :size => 30 %>
66
<em class="info"><%= l(:text_comma_separated) %></em></p>
67

  
68
<p><%= setting_text_field :commit_fix_keywords, :size => 30 %>
69
&nbsp;<%= l(:label_applied_status) %>: <%= setting_select :commit_fix_status_id,
70
                                                          [["", 0]] +
71
                                                              IssueStatus.find(:all).collect{
72
                                                                 |status| [status.name, status.id.to_s]
73
                                                              },
74
                                                          :label => false %>
75
&nbsp;<%= l(:field_done_ratio) %>: <%= setting_select :commit_fix_done_ratio,
76
                                                       (0..10).to_a.collect {|r| ["#{r*10} %", "#{r*10}"] },
77
                                                       :blank => :label_no_change_option,
78
                                                       :label => false %>
79
<em class="info"><%= l(:text_comma_separated) %></em></p>
80

  
81
<p><%= setting_check_box :commit_cross_project_ref %></p>
82

  
83
<p><%= setting_check_box :commit_logtime_enabled,
84
                         :onclick =>
85
                            "if (this.checked) { $('#settings_commit_logtime_activity_id').removeAttr('disabled'); } else { $('#settings_commit_logtime_activity_id').attr('disabled', true); }"%></p>
86

  
87
<p><%= setting_select :commit_logtime_activity_id,
88
                      [[l(:label_default), 0]] +
89
                          TimeEntryActivity.shared.active.collect{|activity| [activity.name, activity.id.to_s]},
90
                      :disabled => !Setting.commit_logtime_enabled?%></p>
91
</fieldset>
92

  
93
<%= submit_tag l(:button_save) %>
94
<% end %>
.svn/pristine/3f/3feb470624b1737721fc273bdc7bfd57c3f458eb.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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
require File.expand_path('../../../../test_helper', __FILE__)
19

  
20
class Redmine::CipheringTest < ActiveSupport::TestCase
21

  
22
  def test_password_should_be_encrypted
23
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
24
      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
25
      assert_equal 'foo', r.password
26
      assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
27
    end
28
  end
29

  
30
  def test_password_should_be_clear_with_blank_key
31
    Redmine::Configuration.with 'database_cipher_key' => '' do
32
      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
33
      assert_equal 'foo', r.password
34
      assert_equal 'foo', r.read_attribute(:password)
35
    end
36
  end
37

  
38
  def test_password_should_be_clear_with_nil_key
39
    Redmine::Configuration.with 'database_cipher_key' => nil do
40
      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
41
      assert_equal 'foo', r.password
42
      assert_equal 'foo', r.read_attribute(:password)
43
    end
44
  end
45

  
46
  def test_blank_password_should_be_clear
47
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
48
      r = Repository::Subversion.create!(:password => '', :url => 'file:///tmp', :identifier => 'svn')
49
      assert_equal '', r.password
50
      assert_equal '', r.read_attribute(:password)
51
    end
52
  end
53

  
54
  def test_unciphered_password_should_be_readable
55
    Redmine::Configuration.with 'database_cipher_key' => nil do
56
      r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
57
    end
58

  
59
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
60
      r = Repository.first(:order => 'id DESC')
61
      assert_equal 'clear', r.password
62
    end
63
  end
64
  
65
  def test_ciphered_password_with_no_cipher_key_configured_should_be_returned_ciphered
66
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
67
      r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
68
    end
69

  
70
    Redmine::Configuration.with 'database_cipher_key' => '' do
71
      r = Repository.first(:order => 'id DESC')
72
      # password can not be deciphered
73
      assert_nothing_raised do
74
        assert r.password.match(/\Aaes-256-cbc:.+\Z/)
75
      end
76
    end
77
  end
78

  
79
  def test_encrypt_all
80
    Repository.delete_all
81
    Redmine::Configuration.with 'database_cipher_key' => nil do
82
      Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
83
      Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
84
    end
85

  
86
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
87
      assert Repository.encrypt_all(:password)
88
      r = Repository.first(:order => 'id DESC')
89
      assert_equal 'bar', r.password
90
      assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
91
    end
92
  end
93

  
94
  def test_decrypt_all
95
    Repository.delete_all
96
    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
97
      Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
98
      Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
99

  
100
      assert Repository.decrypt_all(:password)
101
      r = Repository.first(:order => 'id DESC')
102
      assert_equal 'bar', r.password
103
      assert_equal 'bar', r.read_attribute(:password)
104
    end
105
  end
106
end
.svn/pristine/3f/3fecfd23ccdcab419a5392dfa395ed433f4bc031.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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 Acts
20
    module Searchable
21
      def self.included(base)
22
        base.extend ClassMethods
23
      end
24

  
25
      module ClassMethods
26
        # Options:
27
        # * :columns - a column or an array of columns to search
28
        # * :project_key - project foreign key (default to project_id)
29
        # * :date_column - name of the datetime column (default to created_on)
30
        # * :sort_order - name of the column used to sort results (default to :date_column or created_on)
31
        # * :permission - permission required to search the model (default to :view_"objects")
32
        def acts_as_searchable(options = {})
33
          return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
34

  
35
          cattr_accessor :searchable_options
36
          self.searchable_options = options
37

  
38
          if searchable_options[:columns].nil?
39
            raise 'No searchable column defined.'
40
          elsif !searchable_options[:columns].is_a?(Array)
41
            searchable_options[:columns] = [] << searchable_options[:columns]
42
          end
43

  
44
          searchable_options[:project_key] ||= "#{table_name}.project_id"
45
          searchable_options[:date_column] ||= "#{table_name}.created_on"
46
          searchable_options[:order_column] ||= searchable_options[:date_column]
47

  
48
          # Should we search custom fields on this model ?
49
          searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil?
50

  
51
          send :include, Redmine::Acts::Searchable::InstanceMethods
52
        end
53
      end
54

  
55
      module InstanceMethods
56
        def self.included(base)
57
          base.extend ClassMethods
58
        end
59

  
60
        module ClassMethods
61
          # Searches the model for the given tokens
62
          # projects argument can be either nil (will search all projects), a project or an array of projects
63
          # Returns the results and the results count
64
          def search(tokens, projects=nil, options={})
65
            if projects.is_a?(Array) && projects.empty?
66
              # no results
67
              return [[], 0]
68
            end
69

  
70
            # TODO: make user an argument
71
            user = User.current
72
            tokens = [] << tokens unless tokens.is_a?(Array)
73
            projects = [] << projects unless projects.nil? || projects.is_a?(Array)
74

  
75
            find_options = {:include => searchable_options[:include]}
76
            find_options[:order] = "#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')
77

  
78
            limit_options = {}
79
            limit_options[:limit] = options[:limit] if options[:limit]
80
            if options[:offset]
81
              limit_options[:conditions] = "(#{searchable_options[:date_column]} " + (options[:before] ? '<' : '>') + "'#{connection.quoted_date(options[:offset])}')"
82
            end
83

  
84
            columns = searchable_options[:columns]
85
            columns = columns[0..0] if options[:titles_only]
86

  
87
            token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"}
88

  
89
            if !options[:titles_only] && searchable_options[:search_custom_fields]
90
              searchable_custom_field_ids = CustomField.find(:all,
91
                                                             :select => 'id',
92
                                                             :conditions => { :type => "#{self.name}CustomField",
93
                                                                              :searchable => true }).collect(&:id)
94
              if searchable_custom_field_ids.any?
95
                custom_field_sql = "#{table_name}.id IN (SELECT customized_id FROM #{CustomValue.table_name}" +
96
                  " WHERE customized_type='#{self.name}' AND customized_id=#{table_name}.id AND LOWER(value) LIKE ?" +
97
                  " AND #{CustomValue.table_name}.custom_field_id IN (#{searchable_custom_field_ids.join(',')}))"
98
                token_clauses << custom_field_sql
99
              end
100
            end
101

  
102
            sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')
103

  
104
            find_options[:conditions] = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
105

  
106
            scope = self
107
            project_conditions = []
108
            if searchable_options.has_key?(:permission)
109
              project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project)
110
            elsif respond_to?(:visible)
111
              scope = scope.visible(user)
112
            else
113
              ActiveSupport::Deprecation.warn "acts_as_searchable with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
114
              project_conditions << Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym)
115
            end
116
            # TODO: use visible scope options instead
117
            project_conditions << "#{searchable_options[:project_key]} IN (#{projects.collect(&:id).join(',')})" unless projects.nil?
118
            project_conditions = project_conditions.empty? ? nil : project_conditions.join(' AND ')
119

  
120
            results = []
121
            results_count = 0
122

  
123
            scope = scope.scoped({:conditions => project_conditions}).scoped(find_options)
124
            results_count = scope.count(:all)
125
            results = scope.find(:all, limit_options)
126

  
127
            [results, results_count]
128
          end
129
        end
130
      end
131
    end
132
  end
133
end

Also available in: Unified diff