summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/ability.rb3
-rw-r--r--app/models/ci/build.rb8
-rw-r--r--app/models/ci/pipeline.rb23
-rw-r--r--app/models/ci/runner.rb23
-rw-r--r--app/models/ci/variable.rb1
-rw-r--r--app/models/commit.rb26
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/models/concerns/awardable.rb12
-rw-r--r--app/models/concerns/issuable.rb39
-rw-r--r--app/models/concerns/participable.rb10
-rw-r--r--app/models/event.rb2
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/legacy_diff_note.rb2
-rw-r--r--app/models/member.rb7
-rw-r--r--app/models/members/group_member.rb12
-rw-r--r--app/models/members/project_member.rb12
-rw-r--r--app/models/merge_request.rb8
-rw-r--r--app/models/note.rb6
-rw-r--r--app/models/project.rb11
-rw-r--r--app/models/project_import_data.rb1
-rw-r--r--app/models/repository.rb17
-rw-r--r--app/models/snippet.rb17
-rw-r--r--app/models/user.rb10
24 files changed, 172 insertions, 84 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 9c58b956007..f5950879ccb 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -196,7 +196,8 @@ class Ability
@public_project_rules ||= project_guest_rules + [
:download_code,
:fork_project,
- :read_commit_status
+ :read_commit_status,
+ :read_pipeline
]
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index d618c84e983..2b0bec33131 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -300,18 +300,12 @@ module Ci
project.valid_runners_token? token
end
- def can_be_served?(runner)
- return false unless has_tags? || runner.run_untagged?
-
- (tag_list - runner.tag_list).empty?
- end
-
def has_tags?
tag_list.any?
end
def any_runners_online?
- project.any_runners? { |runner| runner.active? && runner.online? && can_be_served?(runner) }
+ project.any_runners? { |runner| runner.active? && runner.online? && runner.can_pick?(self) }
end
def stuck?
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 5b264ecffc5..10324bf2257 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -37,22 +37,22 @@ module Ci
end
def git_author_name
- commit_data.author_name if commit_data
+ commit.try(:author_name)
end
def git_author_email
- commit_data.author_email if commit_data
+ commit.try(:author_email)
end
def git_commit_message
- commit_data.message if commit_data
+ commit.try(:message)
end
def short_sha
Ci::Pipeline.truncate_sha(sha)
end
- def commit_data
+ def commit
@commit ||= project.commit(sha)
rescue
nil
@@ -163,13 +163,26 @@ module Ci
end
def skip_ci?
- git_commit_message =~ /(\[ci skip\])/ if git_commit_message
+ git_commit_message =~ /\[(ci skip|skip ci)\]/i if git_commit_message
end
def environments
builds.where.not(environment: nil).success.pluck(:environment).uniq
end
+ # Manually set the notes for a Ci::Pipeline
+ # There is no ActiveRecord relation between Ci::Pipeline and notes
+ # as they are related to a commit sha. This method helps importing
+ # them using the +Gitlab::ImportExport::RelationFactory+ class.
+ def notes=(notes)
+ notes.each do |note|
+ note[:id] = nil
+ note[:commit_id] = sha
+ note[:noteable_id] = self['id']
+ note.save!
+ end
+ end
+
def notes
Note.for_commit_id(sha)
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index adb65292208..b64ec79ec2b 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -4,7 +4,7 @@ module Ci
LAST_CONTACT_TIME = 5.minutes.ago
AVAILABLE_SCOPES = %w[specific shared active paused online]
- FORM_EDITABLE = %i[description tag_list active run_untagged]
+ FORM_EDITABLE = %i[description tag_list active run_untagged locked]
has_many :builds, class_name: 'Ci::Build'
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
@@ -26,6 +26,13 @@ module Ci
.where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
end
+ scope :assignable_for, ->(project) do
+ # FIXME: That `to_sql` is needed to workaround a weird Rails bug.
+ # Without that, placeholders would miss one and couldn't match.
+ where(locked: false).
+ where.not("id IN (#{project.runners.select(:id).to_sql})").specific
+ end
+
validate :tag_constraints
acts_as_taggable
@@ -56,7 +63,7 @@ module Ci
def assign_to(project, current_user = nil)
self.is_shared = false if shared?
self.save
- project.runner_projects.create!(runner_id: self.id)
+ project.runner_projects.create(runner_id: self.id)
end
def display_name
@@ -91,6 +98,10 @@ module Ci
!shared?
end
+ def can_pick?(build)
+ assignable_for?(build.project) && accepting_tags?(build)
+ end
+
def only_for?(project)
projects == [project]
end
@@ -111,5 +122,13 @@ module Ci
'can not be empty when runner is not allowed to pick untagged jobs')
end
end
+
+ def assignable_for?(project)
+ !locked? || projects.exists?(id: project.id)
+ end
+
+ def accepting_tags?(build)
+ (run_untagged? || build.has_tags?) && (build.tag_list - tag_list).empty?
+ end
end
end
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index f8d5d4486fd..c9c47ec7419 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -13,6 +13,7 @@ module Ci
attr_encrypted :value,
mode: :per_attribute_iv_and_salt,
+ insecure_mode: true,
key: Gitlab::Application.secrets.db_key_base,
algorithm: 'aes-256-cbc'
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index d69d518fadd..174ccbaea6c 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -271,6 +271,32 @@ class Commit
merged_merge_request ? 'merge request' : 'commit'
end
+ # Get the URI type of the given path
+ #
+ # Used to build URLs to files in the repository in GFM.
+ #
+ # path - String path to check
+ #
+ # Examples:
+ #
+ # uri_type('doc/README.md') # => :blob
+ # uri_type('doc/logo.png') # => :raw
+ # uri_type('doc/api') # => :tree
+ # uri_type('not/found') # => :nil
+ #
+ # Returns a symbol
+ def uri_type(path)
+ entry = @raw.tree.path(path)
+ if entry[:type] == :blob
+ blob = Gitlab::Git::Blob.new(name: entry[:name])
+ blob.image? ? :raw : :blob
+ else
+ entry[:type]
+ end
+ rescue Rugged::TreeError
+ nil
+ end
+
private
def repo_changes
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index ab13db4b297..e437e3417a8 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -8,6 +8,8 @@ class CommitStatus < ActiveRecord::Base
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id, touch: true
belongs_to :user
+ delegate :commit, to: :pipeline
+
validates :pipeline, presence: true, unless: :importing?
validates_presence_of :name
diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb
index 539c7c31e30..06beff177b1 100644
--- a/app/models/concerns/awardable.rb
+++ b/app/models/concerns/awardable.rb
@@ -2,10 +2,11 @@ module Awardable
extend ActiveSupport::Concern
included do
- has_many :award_emoji, as: :awardable, dependent: :destroy
+ has_many :award_emoji, -> { includes(:user) }, as: :awardable, dependent: :destroy
if self < Participable
- participant :award_emoji_with_associations
+ # By default we always load award_emoji user association
+ participant :award_emoji
end
end
@@ -34,12 +35,9 @@ module Awardable
end
end
- def award_emoji_with_associations
- award_emoji.includes(:user)
- end
-
def grouped_awards(with_thumbs: true)
- awards = award_emoji_with_associations.group_by(&:name)
+ # By default we always load award_emoji user association
+ awards = award_emoji.group_by(&:name)
if with_thumbs
awards[AwardEmoji::UPVOTE_NAME] ||= []
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 0ccd3474b81..d6f55885dd6 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -19,9 +19,14 @@ module Issuable
belongs_to :milestone
has_many :notes, as: :noteable, dependent: :destroy do
def authors_loaded?
- # We check first if we're loaded to not load unnecesarily.
+ # We check first if we're loaded to not load unnecessarily.
loaded? && to_a.all? { |note| note.association(:author).loaded? }
end
+
+ def award_emojis_loaded?
+ # We check first if we're loaded to not load unnecessarily.
+ loaded? && to_a.all? { |note| note.association(:award_emoji).loaded? }
+ end
end
has_many :label_links, as: :target, dependent: :destroy
has_many :labels, through: :label_links
@@ -49,7 +54,7 @@ module Issuable
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :join_project, -> { joins(:project) }
- scope :inc_notes_with_associations, -> { includes(notes: :author) }
+ scope :inc_notes_with_associations, -> { includes(notes: [ :project, :author, :award_emoji ]) }
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
@@ -112,15 +117,18 @@ module Issuable
end
def sort(method, excluded_labels: [])
- case method.to_s
- when 'milestone_due_asc' then order_milestone_due_asc
- when 'milestone_due_desc' then order_milestone_due_desc
- when 'downvotes_desc' then order_downvotes_desc
- when 'upvotes_desc' then order_upvotes_desc
- when 'priority' then order_labels_priority(excluded_labels: excluded_labels)
- else
- order_by(method)
- end
+ sorted = case method.to_s
+ when 'milestone_due_asc' then order_milestone_due_asc
+ when 'milestone_due_desc' then order_milestone_due_desc
+ when 'downvotes_desc' then order_downvotes_desc
+ when 'upvotes_desc' then order_upvotes_desc
+ when 'priority' then order_labels_priority(excluded_labels: excluded_labels)
+ else
+ order_by(method)
+ end
+
+ # Break ties with the ID column for pagination
+ sorted.order(id: :desc)
end
def order_labels_priority(excluded_labels: [])
@@ -257,7 +265,14 @@ module Issuable
# already have their authors loaded (possibly because the scope
# `inc_notes_with_associations` was used) and skip the inclusion if that's
# the case.
- notes.authors_loaded? ? notes : notes.includes(:author)
+ includes = []
+ includes << :author unless notes.authors_loaded?
+ includes << :award_emoji unless notes.award_emojis_loaded?
+ if includes.any?
+ notes.includes(includes)
+ else
+ notes
+ end
end
def updated_tasks
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 9056722f45e..9822844357d 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -53,6 +53,16 @@ module Participable
#
# Returns an Array of User instances.
def participants(current_user = nil)
+ @participants ||= Hash.new do |hash, user|
+ hash[user] = raw_participants(user)
+ end
+
+ @participants[current_user]
+ end
+
+ private
+
+ def raw_participants(current_user = nil)
current_user ||= author
ext = Gitlab::ReferenceExtractor.new(project, current_user)
participants = Set.new
diff --git a/app/models/event.rb b/app/models/event.rb
index 716039fb54b..d7d23c7ae6d 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -315,7 +315,7 @@ class Event < ActiveRecord::Base
def body?
if push?
- push_with_commits?
+ push_with_commits? || rm_ref?
elsif note?
true
else
diff --git a/app/models/group.rb b/app/models/group.rb
index e66e04371b2..c70c719e338 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -11,7 +11,7 @@ class Group < Namespace
has_many :users, -> { where(members: { requested_at: nil }) }, through: :group_members
has_many :owners,
- -> { where(members: { access_level: Gitlab::Access::OWNER }) },
+ -> { where(members: { requested_at: nil, access_level: Gitlab::Access::OWNER }) },
through: :group_members,
source: :user
diff --git a/app/models/key.rb b/app/models/key.rb
index 0532e84f47d..b9bc38a0436 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -9,7 +9,7 @@ class Key < ActiveRecord::Base
before_validation :strip_white_space, :generate_fingerprint
validates :title, presence: true, length: { within: 0..255 }
- validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
+ validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }
validates :key, format: { without: /\n|\r/, message: 'should be a single line' }
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
index 95fd510eb3a..33d2a69ebaf 100644
--- a/app/models/legacy_diff_note.rb
+++ b/app/models/legacy_diff_note.rb
@@ -20,7 +20,7 @@ class LegacyDiffNote < Note
end
def discussion_id
- @discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code, active?)
+ @discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code)
end
def diff_file_hash
diff --git a/app/models/member.rb b/app/models/member.rb
index 4ee3f1bb5c2..c74a16367db 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -48,7 +48,6 @@ class Member < ActiveRecord::Base
after_create :post_create_hook, unless: [:pending?, :importing?]
after_update :post_update_hook, unless: [:pending?, :importing?]
after_destroy :post_destroy_hook, unless: :pending?
- after_destroy :post_decline_request, if: :request?
delegate :name, :username, :email, to: :user, prefix: true
@@ -188,7 +187,7 @@ class Member < ActiveRecord::Base
end
def send_request
- # override in subclass
+ notification_service.new_access_request(self)
end
def post_create_hook
@@ -215,10 +214,6 @@ class Member < ActiveRecord::Base
post_create_hook
end
- def post_decline_request
- # override in subclass
- end
-
def system_hook_service
SystemHooksService.new
end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 363db877968..2f13d339c89 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -33,12 +33,6 @@ class GroupMember < Member
super
end
- def send_request
- notification_service.new_group_access_request(self)
-
- super
- end
-
def post_create_hook
notification_service.new_group_member(self)
@@ -64,10 +58,4 @@ class GroupMember < Member
super
end
-
- def post_decline_request
- notification_service.decline_group_access_request(self)
-
- super
- end
end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 250ee04fd1d..e9d3a82ba15 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -111,12 +111,6 @@ class ProjectMember < Member
super
end
- def send_request
- notification_service.new_project_access_request(self)
-
- super
- end
-
def post_create_hook
unless owner?
event_service.join_project(self.project, self.user)
@@ -152,12 +146,6 @@ class ProjectMember < Member
super
end
- def post_decline_request
- notification_service.decline_project_access_request(self)
-
- super
- end
-
def event_service
EventCreateService.new
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 36bc98bdb1e..f5c5b7c1306 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -264,19 +264,19 @@ class MergeRequest < ActiveRecord::Base
self.title.sub(WIP_REGEX, "")
end
- def mergeable?
- return false unless mergeable_state?
+ def mergeable?(skip_ci_check: false)
+ return false unless mergeable_state?(skip_ci_check: skip_ci_check)
check_if_can_be_merged
can_be_merged?
end
- def mergeable_state?
+ def mergeable_state?(skip_ci_check: false)
return false unless open?
return false if work_in_progress?
return false if broken?
- return false unless mergeable_ci_state?
+ return false unless skip_ci_check || mergeable_ci_state?
true
end
diff --git a/app/models/note.rb b/app/models/note.rb
index 8d164647550..8db500a5219 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -6,6 +6,10 @@ class Note < ActiveRecord::Base
include Awardable
include Importable
+ # Attribute containing rendered and redacted Markdown as generated by
+ # Banzai::ObjectRenderer.
+ attr_accessor :note_html
+
default_value_for :system, false
attr_mentionable :note, pipeline: :note
@@ -49,11 +53,13 @@ class Note < ActiveRecord::Base
scope :fresh, ->{ order(created_at: :asc, id: :asc) }
scope :inc_author_project, ->{ includes(:project, :author) }
scope :inc_author, ->{ includes(:author) }
+ scope :inc_author_project_award_emoji, ->{ includes(:project, :author, :award_emoji) }
scope :legacy_diff_notes, ->{ where(type: 'LegacyDiffNote') }
scope :non_diff_notes, ->{ where(type: ['Note', nil]) }
scope :with_associations, -> do
+ # FYI noteable cannot be loaded for LegacyDiffNote for commits
includes(:author, :noteable, :updated_by,
project: [:project_members, { group: [:group_members] }])
end
diff --git a/app/models/project.rb b/app/models/project.rb
index ca3bc04e2dd..96837364423 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -163,6 +163,7 @@ class Project < ActiveRecord::Base
validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
validate :visibility_level_allowed_by_group
validate :visibility_level_allowed_as_fork
+ validate :check_wiki_path_conflict
add_authentication_token_field :runners_token
before_save :ensure_runners_token
@@ -539,6 +540,16 @@ class Project < ActiveRecord::Base
self.errors.add(:visibility_level, "#{level_name} is not allowed since the fork source project has lower visibility.")
end
+ def check_wiki_path_conflict
+ return if path.blank?
+
+ path_to_check = path.ends_with?('.wiki') ? path.chomp('.wiki') : "#{path}.wiki"
+
+ if Project.where(namespace_id: namespace_id, path: path_to_check).exists?
+ errors.add(:name, 'has already been taken')
+ end
+ end
+
def to_param
path
end
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index ca8a9b4217b..331123a5a5b 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -7,6 +7,7 @@ class ProjectImportData < ActiveRecord::Base
marshal: true,
encode: true,
mode: :per_attribute_iv_and_salt,
+ insecure_mode: true,
algorithm: 'aes-256-cbc'
serialize :data, JSON
diff --git a/app/models/repository.rb b/app/models/repository.rb
index bbd7682d8e7..2a6a3b086c2 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -130,7 +130,7 @@ class Repository
end
def find_tag(name)
- raw_repository.tags.find { |tag| tag.name == name }
+ tags.find { |tag| tag.name == name }
end
def add_branch(user, branch_name, target)
@@ -191,8 +191,12 @@ class Repository
end
end
+ def ref_names
+ branch_names + tag_names
+ end
+
def branch_names
- cache.fetch(:branch_names) { branches.map(&:name) }
+ @branch_names ||= cache.fetch(:branch_names) { branches.map(&:name) }
end
def branch_exists?(branch_name)
@@ -267,6 +271,7 @@ class Repository
def expire_branches_cache
cache.expire(:branch_names)
+ @branch_names = nil
@local_branches = nil
end
@@ -332,10 +337,6 @@ class Repository
@lookup_cache ||= {}
end
- def expire_branch_names
- cache.expire(:branch_names)
- end
-
def expire_avatar_cache(branch_name = nil, revision = nil)
# Avatars are pulled from the default branch, thus if somebody pushes to a
# different branch there's no need to expire anything.
@@ -977,6 +978,10 @@ class Repository
raw_repository.ls_files(actual_ref)
end
+ def gitattribute(path, name)
+ raw_repository.attributes(path)[name]
+ end
+
def copy_gitattributes(ref)
actual_ref = ref || root_ref
begin
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index f8034cb5e6b..5ec933601ac 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -20,6 +20,7 @@ class Snippet < ActiveRecord::Base
length: { within: 0..255 },
format: { with: Gitlab::Regex.file_name_regex,
message: Gitlab::Regex.file_name_regex_message }
+
validates :content, presence: true
validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values }
@@ -81,6 +82,11 @@ class Snippet < ActiveRecord::Base
0
end
+ # alias for compatibility with blobs and highlighting
+ def path
+ file_name
+ end
+
def name
file_name
end
@@ -135,7 +141,16 @@ class Snippet < ActiveRecord::Base
end
def accessible_to(user)
- where('visibility_level IN (?) OR author_id = ?', [Snippet::INTERNAL, Snippet::PUBLIC], user)
+ return are_public unless user.present?
+ return all if user.admin?
+
+ where(
+ 'visibility_level IN (:visibility_levels)
+ OR author_id = :author_id
+ OR project_id IN (:project_ids)',
+ visibility_levels: [Snippet::PUBLIC, Snippet::INTERNAL],
+ author_id: user.id,
+ project_ids: user.authorized_projects.select(:id))
end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 2e458329cb9..767d6366c79 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -25,6 +25,7 @@ class User < ActiveRecord::Base
attr_encrypted :otp_secret,
key: Gitlab::Application.config.secret_key_base,
mode: :per_attribute_iv_and_salt,
+ insecure_mode: true,
algorithm: 'aes-256-cbc'
devise :two_factor_authenticatable,
@@ -57,7 +58,7 @@ class User < ActiveRecord::Base
# Groups
has_many :members, dependent: :destroy
- has_many :group_members, dependent: :destroy, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, source: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where members: { access_level: Gitlab::Access::OWNER } }, through: :group_members, source: :group
has_many :masters_groups, -> { where members: { access_level: Gitlab::Access::MASTER } }, through: :group_members, source: :group
@@ -65,7 +66,7 @@ class User < ActiveRecord::Base
# Projects
has_many :groups_projects, through: :groups, source: :projects
has_many :personal_projects, through: :namespace, source: :projects
- has_many :project_members, dependent: :destroy, class_name: 'ProjectMember'
+ has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, class_name: 'ProjectMember'
has_many :projects, through: :project_members
has_many :created_projects, foreign_key: :creator_id, class_name: 'Project'
has_many :users_star_projects, dependent: :destroy
@@ -308,7 +309,7 @@ class User < ActiveRecord::Base
def generate_password
if self.force_random_password
- self.password = self.password_confirmation = Devise.friendly_token.first(8)
+ self.password = self.password_confirmation = Devise.friendly_token.first(Devise.password_length.min)
end
end
@@ -487,9 +488,8 @@ class User < ActiveRecord::Base
events.recent.find do |event|
project = Project.find_by_id(event.project_id)
next unless project
- repo = project.repository
- if repo.branch_names.include?(event.branch_name)
+ if project.repository.branch_exists?(event.branch_name)
merge_requests = MergeRequest.where("created_at >= ?", event.created_at).
where(source_project_id: project.id,
source_branch: event.branch_name)