diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/ability.rb | 22 | ||||
-rw-r--r-- | app/models/blob.rb | 2 | ||||
-rw-r--r-- | app/models/ci/build.rb | 51 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 10 | ||||
-rw-r--r-- | app/models/concerns/access_requestable.rb | 16 | ||||
-rw-r--r-- | app/models/concerns/awardable.rb | 8 | ||||
-rw-r--r-- | app/models/deployment.rb | 29 | ||||
-rw-r--r-- | app/models/environment.rb | 16 | ||||
-rw-r--r-- | app/models/group.rb | 17 | ||||
-rw-r--r-- | app/models/issue.rb | 12 | ||||
-rw-r--r-- | app/models/member.rb | 53 | ||||
-rw-r--r-- | app/models/members/group_member.rb | 20 | ||||
-rw-r--r-- | app/models/members/project_member.rb | 16 | ||||
-rw-r--r-- | app/models/note.rb | 23 | ||||
-rw-r--r-- | app/models/notification_setting.rb | 1 | ||||
-rw-r--r-- | app/models/project.rb | 26 | ||||
-rw-r--r-- | app/models/project_services/bamboo_service.rb | 44 | ||||
-rw-r--r-- | app/models/project_services/issue_tracker_service.rb | 18 | ||||
-rw-r--r-- | app/models/project_services/teamcity_service.rb | 37 | ||||
-rw-r--r-- | app/models/project_team.rb | 42 | ||||
-rw-r--r-- | app/models/repository.rb | 2 | ||||
-rw-r--r-- | app/models/service.rb | 2 | ||||
-rw-r--r-- | app/models/todo.rb | 1 | ||||
-rw-r--r-- | app/models/user.rb | 48 |
24 files changed, 172 insertions, 344 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb index 9c58b956007..44515550d9e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -9,6 +9,7 @@ class Ability when CommitStatus then commit_status_abilities(user, subject) when Project then project_abilities(user, subject) when Issue then issue_abilities(user, subject) + when ExternalIssue then external_issue_abilities(user, subject) when Note then note_abilities(user, subject) when ProjectSnippet then project_snippet_abilities(user, subject) when PersonalSnippet then personal_snippet_abilities(user, subject) @@ -18,7 +19,6 @@ class Ability when GroupMember then group_member_abilities(user, subject) when ProjectMember then project_member_abilities(user, subject) when User then user_abilities - when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project) else [] end.concat(global_abilities(user)) end @@ -187,8 +187,6 @@ class Ability project_report_rules elsif team.guest?(user) project_guest_rules - else - [] end end @@ -230,8 +228,6 @@ class Ability :read_build, :read_container_image, :read_pipeline, - :read_environment, - :read_deployment ] end @@ -250,8 +246,6 @@ class Ability :push_code, :create_container_image, :update_container_image, - :create_environment, - :create_deployment ] end @@ -269,8 +263,6 @@ class Ability @project_master_rules ||= project_dev_rules + [ :push_code_to_protected_branches, :update_project_snippet, - :update_environment, - :update_deployment, :admin_milestone, :admin_project_snippet, :admin_project_member, @@ -281,9 +273,7 @@ class Ability :admin_commit_status, :admin_build, :admin_container_image, - :admin_pipeline, - :admin_environment, - :admin_deployment + :admin_pipeline ] end @@ -327,8 +317,6 @@ class Ability unless project.builds_enabled rules += named_abilities('build') rules += named_abilities('pipeline') - rules += named_abilities('environment') - rules += named_abilities('deployment') end unless project.container_registry_enabled @@ -523,6 +511,10 @@ class Ability end end + def external_issue_abilities(user, subject) + project_abilities(user, subject.project) + end + private def restricted_public_level? @@ -541,7 +533,7 @@ class Ability def filter_confidential_issues_abilities(user, issue, rules) return rules if user.admin? || !issue.confidential? - unless issue.author == user || issue.assignee == user || issue.project.team.member?(user, Gitlab::Access::REPORTER) + unless issue.author == user || issue.assignee == user || issue.project.team.member?(user.id) rules.delete(:admin_issue) rules.delete(:read_issue) rules.delete(:update_issue) diff --git a/app/models/blob.rb b/app/models/blob.rb index 4279ea2ce57..0fea6b7f576 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -24,7 +24,7 @@ class Blob < SimpleDelegator end def only_display_raw? - size && truncated? + size && size > 5.megabytes end def svg? diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 764d8e4e136..6a64ca451f7 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -11,8 +11,6 @@ module Ci scope :unstarted, ->() { where(runner_id: nil) } scope :ignore_failures, ->() { where(allow_failure: false) } - scope :with_artifacts, ->() { where.not(artifacts_file: nil) } - scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader @@ -40,7 +38,7 @@ module Ci new_build.save end - def retry(build, user = nil) + def retry(build) new_build = Ci::Build.new(status: 'pending') new_build.ref = build.ref new_build.tag = build.tag @@ -54,7 +52,6 @@ module Ci new_build.stage = build.stage new_build.stage_idx = build.stage_idx new_build.trigger_request = build.trigger_request - new_build.user = user new_build.save MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) new_build @@ -76,17 +73,6 @@ module Ci build.update_coverage build.execute_hooks end - - after_transition any => [:success] do |build| - if build.environment.present? - service = CreateDeploymentService.new(build.project, build.user, - environment: build.environment, - sha: build.sha, - ref: build.ref, - tag: build.tag) - service.execute(build) - end - end end def retryable? @@ -97,6 +83,10 @@ module Ci !self.pipeline.statuses.latest.include?(self) end + def retry + Ci::Build.retry(self) + end + def depends_on_builds # Get builds of the same type latest_builds = self.pipeline.builds.latest @@ -327,7 +317,7 @@ module Ci end def artifacts? - !artifacts_expired? && artifacts_file.exists? + artifacts_file.exists? end def artifacts_metadata? @@ -338,15 +328,11 @@ module Ci Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry end - def erase_artifacts! - remove_artifacts_file! - remove_artifacts_metadata! - end - def erase(opts = {}) return false unless erasable? - erase_artifacts! + remove_artifacts_file! + remove_artifacts_metadata! erase_trace! update_erased!(opts[:erased_by]) end @@ -359,25 +345,6 @@ module Ci !self.erased_at.nil? end - def artifacts_expired? - artifacts_expire_at && artifacts_expire_at < Time.now - end - - def artifacts_expire_in - artifacts_expire_at - Time.now if artifacts_expire_at - end - - def artifacts_expire_in=(value) - self.artifacts_expire_at = - if value - Time.now + ChronicDuration.parse(value) - end - end - - def keep_artifacts! - self.update(artifacts_expire_at: nil) - end - private def erase_trace! @@ -385,7 +352,7 @@ module Ci end def update_erased!(user = nil) - self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil) + self.update(erased_by: user, erased_at: Time.now) end def yaml_variables diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 13be5b0fa5d..d780467034e 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -76,10 +76,8 @@ module Ci builds.running_or_pending.each(&:cancel) end - def retry_failed(user) - builds.latest.failed.select(&:retryable?).each do |build| - Ci::Build.retry(build, user) - end + def retry_failed + builds.latest.failed.select(&:retryable?).each(&:retry) end def latest? @@ -163,10 +161,6 @@ module Ci git_commit_message =~ /(\[ci skip\])/ if git_commit_message end - def environments - builds.where.not(environment: nil).success.pluck(:environment).uniq - end - def notes Note.for_commit_id(sha) end diff --git a/app/models/concerns/access_requestable.rb b/app/models/concerns/access_requestable.rb deleted file mode 100644 index eedd32a729f..00000000000 --- a/app/models/concerns/access_requestable.rb +++ /dev/null @@ -1,16 +0,0 @@ -# == AccessRequestable concern -# -# Contains functionality related to objects that can receive request for access. -# -# Used by Project, and Group. -# -module AccessRequestable - extend ActiveSupport::Concern - - def request_access(user) - members.create( - access_level: Gitlab::Access::DEVELOPER, - user: user, - requested_at: Time.now.utc) - end -end diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb index 539c7c31e30..aa4b4201250 100644 --- a/app/models/concerns/awardable.rb +++ b/app/models/concerns/awardable.rb @@ -5,7 +5,7 @@ module Awardable has_many :award_emoji, as: :awardable, dependent: :destroy if self < Participable - participant :award_emoji_with_associations + participant :award_emoji end end @@ -34,12 +34,8 @@ 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) + awards = award_emoji.group_by(&:name) if with_thumbs awards[AwardEmoji::UPVOTE_NAME] ||= [] diff --git a/app/models/deployment.rb b/app/models/deployment.rb deleted file mode 100644 index e498ca96e3c..00000000000 --- a/app/models/deployment.rb +++ /dev/null @@ -1,29 +0,0 @@ -class Deployment < ActiveRecord::Base - include InternalId - - belongs_to :project, required: true, validate: true - belongs_to :environment, required: true, validate: true - belongs_to :user - belongs_to :deployable, polymorphic: true - - validates :sha, presence: true - validates :ref, presence: true - - delegate :name, to: :environment, prefix: true - - def commit - project.commit(sha) - end - - def commit_title - commit.try(:title) - end - - def short_sha - Commit.truncate_sha(sha) - end - - def last? - self == environment.last_deployment - end -end diff --git a/app/models/environment.rb b/app/models/environment.rb deleted file mode 100644 index ac3a571a1f3..00000000000 --- a/app/models/environment.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Environment < ActiveRecord::Base - belongs_to :project, required: true, validate: true - - has_many :deployments - - validates :name, - presence: true, - uniqueness: { scope: :project_id }, - length: { within: 0..255 }, - format: { with: Gitlab::Regex.environment_name_regex, - message: Gitlab::Regex.environment_name_regex_message } - - def last_deployment - deployments.last - end -end diff --git a/app/models/group.rb b/app/models/group.rb index e66e04371b2..aec92e335e6 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -3,18 +3,11 @@ require 'carrierwave/orm/activerecord' class Group < Namespace include Gitlab::ConfigHelper include Gitlab::VisibilityLevel - include AccessRequestable include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' alias_method :members, :group_members - has_many :users, -> { where(members: { requested_at: nil }) }, through: :group_members - - has_many :owners, - -> { where(members: { access_level: Gitlab::Access::OWNER }) }, - through: :group_members, - source: :user - + has_many :users, through: :group_members has_many :project_group_links, dependent: :destroy has_many :shared_projects, through: :project_group_links, source: :project has_many :notification_settings, dependent: :destroy, as: :source @@ -65,10 +58,6 @@ class Group < Namespace "#{self.class.reference_prefix}#{name}" end - def web_url - Gitlab::Routing.url_helpers.group_url(self) - end - def human_name name end @@ -94,6 +83,10 @@ class Group < Namespace end end + def owners + @owners ||= group_members.owners.includes(:user).map(&:user) + end + def add_users(user_ids, access_level, current_user = nil) user_ids.each do |user_id| Member.add_user(self.group_members, user_id, access_level, current_user) diff --git a/app/models/issue.rb b/app/models/issue.rb index 1bdf9c011b2..235922710ad 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -51,18 +51,10 @@ class Issue < ActiveRecord::Base end def self.visible_to_user(user) - return where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? + return where(confidential: false) if user.blank? return all if user.admin? - where(' - issues.confidential IS NULL - OR issues.confidential IS FALSE - OR (issues.confidential = TRUE - AND (issues.author_id = :user_id - OR issues.assignee_id = :user_id - OR issues.project_id IN(:project_ids)))', - user_id: user.id, - project_ids: user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) + where('issues.confidential = false OR (issues.confidential = true AND (issues.author_id = :user_id OR issues.assignee_id = :user_id OR issues.project_id IN(:project_ids)))', user_id: user.id, project_ids: user.authorized_projects.select(:id)) end def self.reference_prefix diff --git a/app/models/member.rb b/app/models/member.rb index cea6d259760..d3060f07fc0 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -26,28 +26,20 @@ class Member < ActiveRecord::Base allow_nil: true } - scope :invite, -> { where.not(invite_token: nil) } - scope :non_invite, -> { where(invite_token: nil) } - scope :request, -> { where.not(requested_at: nil) } - scope :non_request, -> { where(requested_at: nil) } - scope :non_pending, -> { non_request.non_invite } - + scope :invite, -> { where(user_id: nil) } + scope :non_invite, -> { where("user_id IS NOT NULL") } scope :guests, -> { where(access_level: GUEST) } scope :reporters, -> { where(access_level: REPORTER) } scope :developers, -> { where(access_level: DEVELOPER) } scope :masters, -> { where(access_level: MASTER) } scope :owners, -> { where(access_level: OWNER) } - scope :owners_and_masters, -> { where(access_level: [OWNER, MASTER]) } before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } - after_create :send_invite, if: :invite? - after_create :send_request, if: :request? - after_create :create_notification_setting, unless: :pending? - after_create :post_create_hook, unless: :pending? - after_update :post_update_hook, unless: :pending? - after_destroy :post_destroy_hook, unless: :pending? - after_destroy :post_decline_request, if: :request? + after_create :create_notification_setting, unless: :invite? + after_create :post_create_hook, unless: :invite? + after_update :post_update_hook, unless: :invite? + after_destroy :post_destroy_hook, unless: :invite? delegate :name, :username, :email, to: :user, prefix: true @@ -104,31 +96,10 @@ class Member < ActiveRecord::Base end end - def real_source_type - source_type - end - def invite? self.invite_token.present? end - def request? - requested_at.present? - end - - def pending? - invite? || request? - end - - def accept_request - return false unless request? - - updated = self.update(requested_at: nil) - after_accept_request if updated - - updated - end - def accept_invite!(new_user) return false unless invite? @@ -186,10 +157,6 @@ class Member < ActiveRecord::Base # override in subclass end - def send_request - # override in subclass - end - def post_create_hook system_hook_service.execute_hooks_for(self, :create) end @@ -210,14 +177,6 @@ class Member < ActiveRecord::Base # override in subclass end - def after_accept_request - 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..f63a0debf1a 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -8,6 +8,9 @@ class GroupMember < Member validates_format_of :source_type, with: /\ANamespace\z/ default_scope { where(source_type: SOURCE_TYPE) } + scope :with_group, ->(group) { where(source_id: group.id) } + scope :with_user, ->(user) { where(user_id: user.id) } + def self.access_level_roles Gitlab::Access.options_with_owner end @@ -20,11 +23,6 @@ class GroupMember < Member access_level end - # Because source_type is `Namespace`... - def real_source_type - 'Group' - end - private def send_invite @@ -33,12 +31,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 +56,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..46955b430f3 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -11,6 +11,8 @@ class ProjectMember < Member default_scope { where(source_type: SOURCE_TYPE) } scope :in_project, ->(project) { where(source_id: project.id) } + scope :in_projects, ->(projects) { where(source_id: projects.pluck(:id)) } + scope :with_user, ->(user) { where(user_id: user.id) } before_destroy :delete_member_todos @@ -82,7 +84,7 @@ class ProjectMember < Member Gitlab::Access.sym_options end - def access_level_roles + def access_roles Gitlab::Access.options end end @@ -111,12 +113,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 +148,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/note.rb b/app/models/note.rb index 4b6748053ff..585d8c4ad84 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -88,9 +88,22 @@ class Note < ActiveRecord::Base table = arel_table pattern = "%#{query}%" - Note.joins('LEFT JOIN issues ON issues.id = noteable_id'). - where(table[:note].matches(pattern)). - merge(Issue.visible_to_user(as_user)) + found_notes = joins('LEFT JOIN issues ON issues.id = noteable_id'). + where(table[:note].matches(pattern)) + + if as_user + found_notes.where(' + issues.confidential IS NULL + OR issues.confidential IS FALSE + OR (issues.confidential IS TRUE + AND (issues.author_id = :user_id + OR issues.assignee_id = :user_id + OR issues.project_id IN(:project_ids)))', + user_id: as_user.id, + project_ids: as_user.authorized_projects.select(:id)) + else + found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE') + end end end @@ -187,10 +200,6 @@ class Note < ActiveRecord::Base award_emoji_supported? && contains_emoji_only? end - def emoji_awardable? - !system? - end - def clear_blank_line_code! self.line_code = nil if self.line_code.blank? end diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index 0ce87968e46..17fb15b08df 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -7,6 +7,7 @@ class NotificationSetting < ActiveRecord::Base belongs_to :source, polymorphic: true validates :user, presence: true + validates :source, presence: true validates :level, presence: true validates :user_id, uniqueness: { scope: [:source_type, :source_id], message: "already exists in source", diff --git a/app/models/project.rb b/app/models/project.rb index 0ede6c6b139..9dca63f124b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -5,7 +5,6 @@ class Project < ActiveRecord::Base include Gitlab::ShellAdapter include Gitlab::VisibilityLevel include Gitlab::CurrentSettings - include AccessRequestable include Referable include Sortable include AfterCommitQueue @@ -81,7 +80,7 @@ class Project < ActiveRecord::Base has_one :jira_service, dependent: :destroy has_one :redmine_service, dependent: :destroy has_one :custom_issue_tracker_service, dependent: :destroy - has_one :gitlab_issue_tracker_service, dependent: :destroy, inverse_of: :project + has_one :gitlab_issue_tracker_service, dependent: :destroy has_one :external_wiki_service, dependent: :destroy has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" @@ -103,9 +102,8 @@ class Project < ActiveRecord::Base has_many :snippets, dependent: :destroy, class_name: 'ProjectSnippet' has_many :hooks, dependent: :destroy, class_name: 'ProjectHook' has_many :protected_branches, dependent: :destroy - has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember' - alias_method :members, :project_members - has_many :users, -> { where(members: { requested_at: nil }) }, through: :project_members + has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember' + has_many :users, through: :project_members has_many :deploy_keys_projects, dependent: :destroy has_many :deploy_keys, through: :deploy_keys_projects has_many :users_star_projects, dependent: :destroy @@ -127,8 +125,6 @@ class Project < ActiveRecord::Base has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' has_many :variables, dependent: :destroy, class_name: 'Ci::Variable', foreign_key: :gl_project_id has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger', foreign_key: :gl_project_id - has_many :environments, dependent: :destroy - has_many :deployments, dependent: :destroy accepts_nested_attributes_for :variables, allow_destroy: true @@ -150,6 +146,7 @@ class Project < ActiveRecord::Base message: Gitlab::Regex.project_path_regex_message } validates :issues_enabled, :merge_requests_enabled, :wiki_enabled, inclusion: { in: [true, false] } + validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :namespace, presence: true validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id @@ -592,6 +589,10 @@ class Project < ActiveRecord::Base update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) end + def can_have_issues_tracker_id? + self.issues_enabled && !self.default_issues_tracker? + end + def build_missing_services services_templates = Service.where(template: true) @@ -684,6 +685,16 @@ class Project < ActiveRecord::Base end end + def project_member_by_name_or_email(name = nil, email = nil) + user = users.find_by('name like ? or email like ?', name, email) + project_members.where(user: user) if user + end + + # Get Team Member record by user id + def project_member_by_id(user_id) + project_members.find_by(user_id: user_id) + end + def name_with_namespace @name_with_namespace ||= begin if namespace @@ -693,7 +704,6 @@ class Project < ActiveRecord::Base end end end - alias_method :human_name, :name_with_namespace def path_with_namespace if namespace diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index b5c76e4d4fe..1d1780dcfbf 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -1,4 +1,6 @@ class BambooService < CiService + include HTTParty + prop_accessor :bamboo_url, :build_key, :username, :password validates :bamboo_url, presence: true, url: true, if: :activated? @@ -59,7 +61,18 @@ class BambooService < CiService end def build_info(sha) - @response = get_path("rest/api/latest/result?label=#{sha}") + url = URI.join(bamboo_url, "/rest/api/latest/result?label=#{sha}").to_s + + if username.blank? && password.blank? + @response = HTTParty.get(url, verify: false) + else + url << '&os_authType=basic' + auth = { + username: username, + password: password + } + @response = HTTParty.get(url, verify: false, basic_auth: auth) + end end def build_page(sha, ref) @@ -67,11 +80,11 @@ class BambooService < CiService if @response.code != 200 || @response['results']['results']['size'] == '0' # If actual build link can't be determined, send user to build summary page. - URI.join("#{bamboo_url}/", "browse/#{build_key}").to_s + URI.join(bamboo_url, "/browse/#{build_key}").to_s else # If actual build link is available, go to build result page. result_key = @response['results']['results']['result']['planResultKey']['key'] - URI.join("#{bamboo_url}/", "browse/#{result_key}").to_s + URI.join(bamboo_url, "/browse/#{result_key}").to_s end end @@ -99,27 +112,8 @@ class BambooService < CiService def execute(data) return unless supported_events.include?(data[:object_kind]) - get_path("updateAndBuild.action?buildKey=#{build_key}") - end - - private - - def build_url(path) - URI.join("#{bamboo_url}/", path).to_s - end - - def get_path(path) - url = build_url(path) - - if username.blank? && password.blank? - HTTParty.get(url, verify: false) - else - url << '&os_authType=basic' - HTTParty.get(url, verify: false, - basic_auth: { - username: username, - password: password - }) - end + # Bamboo requires a GET and does not take any data. + url = URI.join(bamboo_url, "/updateAndBuild.action?buildKey=#{build_key}").to_s + self.class.get(url, verify: false) end end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 87ecb3b8b86..6ae9b16d3ce 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -38,9 +38,9 @@ class IssueTrackerService < Service if enabled_in_gitlab_config self.properties = { title: issues_tracker['title'], - project_url: issues_tracker['project_url'], - issues_url: issues_tracker['issues_url'], - new_issue_url: issues_tracker['new_issue_url'] + project_url: add_issues_tracker_id(issues_tracker['project_url']), + issues_url: add_issues_tracker_id(issues_tracker['issues_url']), + new_issue_url: add_issues_tracker_id(issues_tracker['new_issue_url']) } else self.properties = {} @@ -83,4 +83,16 @@ class IssueTrackerService < Service def issues_tracker Gitlab.config.issues_tracker[to_param] end + + def add_issues_tracker_id(url) + if self.project + id = self.project.issues_tracker_id + + if id + url = url.gsub(":issues_tracker_id", id) + end + end + + url + end end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index a4a967c9bc9..b0dcb52eba1 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -1,4 +1,6 @@ class TeamcityService < CiService + include HTTParty + prop_accessor :teamcity_url, :build_type, :username, :password validates :teamcity_url, presence: true, url: true, if: :activated? @@ -62,7 +64,15 @@ class TeamcityService < CiService end def build_info(sha) - @response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,number:#{sha}") + url = URI.join( + teamcity_url, + "/httpAuth/app/rest/builds/branch:unspecified:any,number:#{sha}" + ).to_s + auth = { + username: username, + password: password + } + @response = HTTParty.get(url, verify: false, basic_auth: auth) end def build_page(sha, ref) @@ -71,11 +81,14 @@ class TeamcityService < CiService if @response.code != 200 # If actual build link can't be determined, # send user to build summary page. - build_url("viewLog.html?buildTypeId=#{build_type}") + URI.join(teamcity_url, "/viewLog.html?buildTypeId=#{build_type}").to_s else # If actual build link is available, go to build result page. built_id = @response['build']['id'] - build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}") + URI.join( + teamcity_url, + "/viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}" + ).to_s end end @@ -110,8 +123,8 @@ class TeamcityService < CiService branch = Gitlab::Git.ref_name(data[:ref]) - HTTParty.post( - build_url('httpAuth/app/rest/buildQueue'), + self.class.post( + URI.join(teamcity_url, '/httpAuth/app/rest/buildQueue').to_s, body: "<build branchName=\"#{branch}\">"\ "<buildType id=\"#{build_type}\"/>"\ '</build>', @@ -119,18 +132,4 @@ class TeamcityService < CiService basic_auth: auth ) end - - private - - def build_url(path) - URI.join("#{teamcity_url}/", path).to_s - end - - def get_path(path) - HTTParty.get(build_url(path), verify: false, - basic_auth: { - username: username, - password: password - }) - end end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 73e736820af..70a8bbaba65 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -21,13 +21,23 @@ class ProjectTeam end end + def find(user_id) + user = project.users.find_by(id: user_id) + + if group + user ||= group.users.find_by(id: user_id) + end + + user + end + def find_member(user_id) - member = project.members.non_request.find_by(user_id: user_id) + member = project.project_members.find_by(user_id: user_id) # If user is not in project members # we should check for group membership if group && !member - member = group.members.non_request.find_by(user_id: user_id) + member = group.group_members.find_by(user_id: user_id) end member @@ -51,10 +61,13 @@ class ProjectTeam ProjectMember.truncate_team(project) end + def users + members + end + def members @members ||= fetch_members end - alias_method :users, :members def guests @guests ||= fetch_members(:guests) @@ -118,14 +131,8 @@ class ProjectTeam max_member_access(user.id) == Gitlab::Access::MASTER end - def member?(user, min_member_access = nil) - member = !!find_member(user.id) - - if min_member_access - member && max_member_access(user.id) >= min_member_access - else - member - end + def member?(user_id) + !!find_member(user_id) end def human_max_access(user_id) @@ -137,7 +144,7 @@ class ProjectTeam def max_member_access(user_id) access = [] - project.members.non_request.each do |member| + project.project_members.each do |member| if member.user_id == user_id access << member.access_field if member.access_field break @@ -145,7 +152,7 @@ class ProjectTeam end if group - group.members.non_request.each do |member| + group.group_members.each do |member| if member.user_id == user_id access << member.access_field if member.access_field break @@ -160,7 +167,6 @@ class ProjectTeam access.compact.max end - private def max_invited_level(user_id) project.project_group_links.map do |group_link| @@ -177,15 +183,17 @@ class ProjectTeam end.compact.max end + private + def fetch_members(level = nil) - project_members = project.members.non_request - group_members = group ? group.members.non_request : [] + project_members = project.project_members + group_members = group ? group.group_members : [] invited_members = [] if project.invited_groups.any? && project.allowed_to_share_with_group? project.project_group_links.each do |group_link| invited_group = group_link.group - im = invited_group.members.non_request + im = invited_group.group_members if level int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize] diff --git a/app/models/repository.rb b/app/models/repository.rb index e5b277cb198..1ab163510bf 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -446,7 +446,7 @@ class Repository def blob_at(sha, path) unless Gitlab::Git.blank_ref?(sha) - Blob.decorate(Gitlab::Git::Blob.find(self, sha, path)) + Gitlab::Git::Blob.find(self, sha, path) end end diff --git a/app/models/service.rb b/app/models/service.rb index 40d39933ad8..bf352397509 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -18,7 +18,7 @@ class Service < ActiveRecord::Base after_commit :reset_updated_properties after_commit :cache_project_has_external_issue_tracker - belongs_to :project, inverse_of: :services + belongs_to :project has_one :service_hook validates :project_id, presence: true, unless: Proc.new { |service| service.template? } diff --git a/app/models/todo.rb b/app/models/todo.rb index 2792fa9b9a8..3a091373329 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -2,7 +2,6 @@ class Todo < ActiveRecord::Base ASSIGNED = 1 MENTIONED = 2 BUILD_FAILED = 3 - MARKED = 4 belongs_to :author, class_name: "User" belongs_to :note diff --git a/app/models/user.rb b/app/models/user.rb index 8d0427da5ab..e0987e07e1f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,8 +10,6 @@ class User < ActiveRecord::Base include CaseSensitivity include TokenAuthenticatable - DEFAULT_NOTIFICATION_LEVEL = :participating - add_authentication_token_field :authentication_token default_value_for :admin, false @@ -56,7 +54,8 @@ class User < ActiveRecord::Base # Groups has_many :members, dependent: :destroy - has_many :group_members, dependent: :destroy, source: 'GroupMember' + has_many :project_members, source: 'ProjectMember' + has_many :group_members, 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 @@ -64,13 +63,13 @@ 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 :projects, through: :project_members has_many :created_projects, foreign_key: :creator_id, class_name: 'Project' has_many :users_star_projects, dependent: :destroy has_many :starred_projects, through: :users_star_projects, source: :project has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet" + has_many :project_members, dependent: :destroy, class_name: 'ProjectMember' has_many :issues, dependent: :destroy, foreign_key: :author_id has_many :notes, dependent: :destroy, foreign_key: :author_id has_many :merge_requests, dependent: :destroy, foreign_key: :author_id @@ -100,6 +99,7 @@ class User < ActiveRecord::Base presence: true, uniqueness: { case_sensitive: false } + validates :notification_level, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :unique_email, if: ->(user) { user.email_changed? } @@ -133,6 +133,13 @@ class User < ActiveRecord::Base # Note: When adding an option, it MUST go on the end of the array. enum project_view: [:readme, :activity, :files] + # Notification level + # Note: When adding an option, it MUST go on the end of the array. + # + # TODO: Add '_prefix: :notification' to enum when update to Rails 5. https://github.com/rails/rails/pull/19813 + # Because user.notification_disabled? is much better than user.disabled? + enum notification_level: [:disabled, :participating, :watch, :global, :mention] + alias_attribute :private_token, :authentication_token delegate :path, to: :namespace, allow_nil: true, prefix: true @@ -404,8 +411,8 @@ class User < ActiveRecord::Base end # Returns projects user is authorized to access. - def authorized_projects(min_access_level = nil) - Project.where("projects.id IN (#{projects_union(min_access_level).to_sql})") + def authorized_projects + Project.where("projects.id IN (#{projects_union.to_sql})") end def viewable_starred_projects @@ -793,17 +800,6 @@ class User < ActiveRecord::Base notification_settings.find_or_initialize_by(source: source) end - # Lazy load global notification setting - # Initializes User setting with Participating level if setting not persisted - def global_notification_setting - return @global_notification_setting if defined?(@global_notification_setting) - - @global_notification_setting = notification_settings.find_or_initialize_by(source: nil) - @global_notification_setting.update_attributes(level: NotificationSetting.levels[DEFAULT_NOTIFICATION_LEVEL]) unless @global_notification_setting.persisted? - - @global_notification_setting - end - def assigned_open_merge_request_count(force: false) Rails.cache.fetch(['users', id, 'assigned_open_merge_request_count'], force: force) do assigned_merge_requests.opened.count @@ -823,19 +819,11 @@ class User < ActiveRecord::Base private - def projects_union(min_access_level = nil) - relations = [personal_projects.select(:id), - groups_projects.select(:id), - projects.select(:id), - groups.joins(:shared_projects).select(:project_id)] - - - if min_access_level - scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } - relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } - end - - Gitlab::SQL::Union.new(relations) + def projects_union + Gitlab::SQL::Union.new([personal_projects.select(:id), + groups_projects.select(:id), + projects.select(:id), + groups.joins(:shared_projects).select(:project_id)]) end def ci_projects_union |