Project

General

Profile

Feature #13919 » feature_13919_v1.patch

Mizuki ISHIKAWA, 2019-03-07 05:34

View differences:

app/helpers/application_helper.rb
54 54
      name = h(user.name(options[:format]))
55 55
      if user.active? || (User.current.admin? && user.logged?)
56 56
        only_path = options[:only_path].nil? ? true : options[:only_path]
57
        link_to name, user_url(user, :only_path => only_path), :class => user.css_classes
57
        css_classes = options[:class] ? "#{user.css_classes} #{options[:class]}" : user.css_classes
58
        link_to name, user_url(user, :only_path => only_path), :class => css_classes
58 59
      else
59 60
        name
60 61
      end
......
974 975
              if p = Project.visible.find_by_id(oid)
975 976
                link = link_to_project(p, {:only_path => only_path}, :class => 'project')
976 977
              end
977
            when 'user'
978
              u = User.visible.find_by(:id => oid, :type => 'User')
979
              link = link_to_user(u, :only_path => only_path) if u
980 978
            end
981 979
          elsif sep == ':'
982 980
            name = remove_double_quotes(identifier)
......
1035 1033
              if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
1036 1034
                link = link_to_project(p, {:only_path => only_path}, :class => 'project')
1037 1035
              end
1038
            when 'user'
1039
              u = User.visible.find_by("LOWER(login) = :s AND type = 'User'", :s => name.downcase)
1040
              link = link_to_user(u, :only_path => only_path) if u
1041 1036
            end
1042
          elsif sep == "@"
1043
            name = remove_double_quotes(identifier)
1044
            u = User.visible.find_by("LOWER(login) = :s AND type = 'User'", :s => name.downcase)
1045
            link = link_to_user(u, :only_path => only_path) if u
1037
          end
1038
          if link.nil? && $~
1039
            user = User.mentioned_user($~.named_captures.symbolize_keys)
1040
            if user
1041
              css_classes = (user.notify_mentioned_user?(obj) ? 'notified' : nil)
1042
              link = link_to_user(user, :only_path => only_path, :class => css_classes)
1043
            end
1046 1044
          end
1047 1045
        end
1048 1046
        (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
app/models/document.rb
61 61
  end
62 62

  
63 63
  def notified_users
64
    project.notified_users.reject {|user| !visible?(user)}
64
    project.notified_users.select {|user| user.allowed_to_view_notify_target?(self) }
65 65
  end
66 66

  
67 67
  private
app/models/issue.rb
1038 1038
    notified += project.notified_users
1039 1039
    notified.uniq!
1040 1040
    # Remove users that can not view the issue
1041
    notified.reject! {|user| !visible?(user)}
1042
    notified
1041
    notified.select {|user| user.allowed_to_view_notify_target?(self)}
1043 1042
  end
1044 1043

  
1045 1044
  # Returns the email addresses that should be notified
app/models/journal.rb
141 141

  
142 142
  def notified_users
143 143
    notified = journalized.notified_users
144
    if private_notes?
145
      notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
146
    end
147
    notified
144
    notified.select{ |u| u.allowed_to_view_notify_target?(self) }
148 145
  end
149 146

  
150 147
  def recipients
app/models/mailer.rb
90 90
  #   Mailer.deliver_issue_add(issue)
91 91
  def self.deliver_issue_add(issue)
92 92
    users = issue.notified_users | issue.notified_watchers
93
    users |= mentioned_users(issue.description, issue)
93 94
    users.each do |user|
94 95
      issue_add(user, issue).deliver_later
95 96
    end
......
124 125
  #   Mailer.deliver_issue_edit(journal)
125 126
  def self.deliver_issue_edit(journal)
126 127
    users  = journal.notified_users | journal.notified_watchers
128
    users |= mentioned_users(journal.notes, journal)
127 129
    users.select! do |user|
128 130
      journal.notes? || journal.visible_details(user).any?
129 131
    end
......
149 151
  #   Mailer.deliver_document_added(document, author)
150 152
  def self.deliver_document_added(document, author)
151 153
    users = document.notified_users
154
    users |= mentioned_users(document.description, document)
152 155
    users.each do |user|
153 156
      document_added(user, document, author).deliver_later
154 157
    end
......
217 220
  #   Mailer.deliver_news_added(news)
218 221
  def self.deliver_news_added(news)
219 222
    users = news.notified_users | news.notified_watchers_for_added_news
223
    users |= mentioned_users(news.description, news)
220 224
    users.each do |user|
221 225
      news_added(user, news).deliver_later
222 226
    end
......
244 248
  def self.deliver_news_comment_added(comment)
245 249
    news = comment.commented
246 250
    users = news.notified_users | news.notified_watchers
251
    users |= mentioned_users(comment.content, news)
247 252
    users.each do |user|
248 253
      news_comment_added(user, comment).deliver_later
249 254
    end
......
271 276
    users  = message.notified_users
272 277
    users |= message.root.notified_watchers
273 278
    users |= message.board.notified_watchers
279
    users |= mentioned_users(message.content, message)
274 280

  
275 281
    users.each do |user|
276 282
      message_posted(user, message).deliver_later
......
329 335
    users  = wiki_content.notified_users
330 336
    users |= wiki_content.page.notified_watchers
331 337
    users |= wiki_content.page.wiki.notified_watchers
338
    users |= mentioned_users(wiki_content.text, wiki_content)
332 339

  
333 340
    users.each do |user|
334 341
      wiki_content_updated(user, wiki_content).deliver_later
......
758 765
    @references_objects ||= []
759 766
    @references_objects << object
760 767
  end
768

  
769
  def self.mentioned_users(text, obj)
770
    users = []
771
    return users if text.blank?
772
    text.scan(ApplicationHelper::LINKS_RE) do |_|
773
      target = User.mentioned_user($~.named_captures.symbolize_keys)
774
      next if target.blank? || users.include?(target)
775
      users << target if target.notify_mentioned_user?(obj)
776
    end
777
    users
778
  end
761 779
end
762 780

  
app/models/message.rb
103 103
  end
104 104

  
105 105
  def notified_users
106
    project.notified_users.reject {|user| !visible?(user)}
106
    project.notified_users.select {|user| user.allowed_to_view_notify_target?(self) }
107 107
  end
108 108

  
109 109
  private
app/models/news.rb
54 54
  end
55 55

  
56 56
  def notified_users
57
    project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}
57
    project.users.select {|user| user.notify_about?(self) && user.allowed_to_view_notify_target?(self)}
58 58
  end
59 59

  
60 60
  def recipients
app/models/user.rb
787 787
    end
788 788
  end
789 789

  
790
  # Return true if the user is allowed to view the notify target.
791
  def allowed_to_view_notify_target?(object)
792
    case object
793
    when Journal
794
      self.allowed_to_view_notify_target?(object.journalized) &&
795
        (!object.private_notes? || self.allowed_to?(:view_private_notes, object.journalized.project))
796
    else
797
      object.try(:visible?, self)
798
    end
799
  end
800

  
790 801
  def self.current=(user)
791 802
    RequestStore.store[:current_user] = user
792 803
  end
......
795 806
    RequestStore.store[:current_user] ||= User.anonymous
796 807
  end
797 808

  
809
  # Return the mentioned user to based on the match data
810
  #  of ApplicationHelper::LINKS_RE.
811
  #     user:jsmith -> Link to user with login jsmith
812
  #     @jsmith -> Link to user with login jsmith
813
  #     user#2 -> Link to user with id 2
814
  def self.mentioned_user(match_data)
815
    return nil if match_data[:esc]
816
    sep = match_data[:sep1] || match_data[:sep2] || match_data[:sep3] || match_data[:sep4]
817
    identifier = match_data[:identifier1] || match_data[:identifier2] || match_data[:identifier3]
818
    prefix = match_data[:prefix]
819
    if (sep == '#' || sep == '##') && prefix == 'user'
820
      User.visible.find_by(:id => identifier.to_i, :type => 'User')
821
    elsif sep == '@' || (sep == ':' && prefix == 'user')
822
      name = identifier.gsub(%r{^"(.*)"$}, "\\1")
823
      User.find_by_login(CGI.unescapeHTML(name).downcase)
824
    end
825
  end
826

  
827
  # Return true if notify the mentioned user.
828
  def notify_mentioned_user?(object)
829
    self.active? &&
830
      self.mail.present? &&
831
      self.mail_notification.present? && self.mail_notification != 'none' &&
832
      self.allowed_to_view_notify_target?(object)
833
  end
834

  
798 835
  # Returns the anonymous user.  If the anonymous user does not exist, it is created.  There can be only
799 836
  # one anonymous user per database.
800 837
  def self.anonymous
app/models/wiki_content.rb
51 51
  end
52 52

  
53 53
  def notified_users
54
    project.notified_users.reject {|user| !visible?(user)}
54
    project.notified_users.select {|user| user.allowed_to_view_notify_target?(self) }
55 55
  end
56 56

  
57 57
  # Returns the mail addresses of users that should be notified
test/unit/mailer_test.rb
365 365
    assert_include 'dlopper@somenet.foo', recipients
366 366
  end
367 367

  
368
  def test_issue_added_should_notify_mentioned_users
369
    # issue with non-public project
370
    issue = Issue.find(4)
371
    # Developer
372
    user = User.find(8)
373

  
374
    # notify mentioned user
375
    ["user##{user.id}", "@#{user.login}", "user:#{user.login}"].each do |description|
376
      issue.update(description: description)
377
      ActionMailer::Base.deliveries.clear
378
      Mailer.deliver_issue_add(issue)
379
      assert_include user.mail, recipients
380
    end
381

  
382
    # Do not notify mentioned users without view_issues permission.
383
    Role.find(2).remove_permission!(:view_issues)
384
    issue.update(description: "user##{user.id}")
385
    ActionMailer::Base.deliveries.clear
386
    Mailer.deliver_issue_add(issue)
387
    assert_not_include user.mail, recipients
388
  end
389

  
368 390
  def test_issue_add_should_send_mail_to_all_user_email_address
369 391
    EmailAddress.create!(:user_id => 3, :address => 'otheremail@somenet.foo')
370 392
    issue = Issue.find(1)
(1-1/12)