Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorJames Edwards-Jones <jedwardsjones@gitlab.com>2017-03-16 01:29:07 +0300
committerJames Edwards-Jones <jedwardsjones@gitlab.com>2017-03-31 21:37:01 +0300
commit91ed8ed687ee9edbda0098475e66ad41f886d7a5 (patch)
tree7a446fa1048484d2ccb25a37e7ce650884b7d76f /app
parent1a416a42f1c1b876ecd96687e41696bc915cc2c2 (diff)
Protected tags copy/paste from protected branches
Should provide basic CRUD backend for frontend to work from. Doesn’t include frontend, API, or the internal API used from gitlab-shell
Diffstat (limited to 'app')
-rw-r--r--app/controllers/projects/protected_tags_controller.rb58
-rw-r--r--app/models/concerns/protected_ref_access.rb21
-rw-r--r--app/models/concerns/protected_tag_access.rb21
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/protected_branch.rb39
-rw-r--r--app/models/protected_ref_matcher.rb52
-rw-r--r--app/models/protected_tag.rb39
-rw-r--r--app/models/protected_tag/push_access_level.rb21
-rw-r--r--app/services/protected_tags/create_service.rb11
-rw-r--r--app/services/protected_tags/update_service.rb13
10 files changed, 244 insertions, 32 deletions
diff --git a/app/controllers/projects/protected_tags_controller.rb b/app/controllers/projects/protected_tags_controller.rb
new file mode 100644
index 00000000000..5ab5d1d997b
--- /dev/null
+++ b/app/controllers/projects/protected_tags_controller.rb
@@ -0,0 +1,58 @@
+class Projects::ProtectedTagsController < Projects::ApplicationController
+ include RepositorySettingsRedirect
+ # Authorize
+ before_action :require_non_empty_project
+ before_action :authorize_admin_project!
+ before_action :load_protected_tag, only: [:show, :update, :destroy]
+
+ layout "project_settings"
+
+ def index
+ redirect_to_repository_settings(@project)
+ end
+
+ def create
+ @protected_tag = ::ProtectedTags::CreateService.new(@project, current_user, protected_tag_params).execute
+ unless @protected_tag.persisted?
+ flash[:alert] = @protected_tags.errors.full_messages.join(', ').html_safe
+ end
+ redirect_to_repository_settings(@project)
+ end
+
+ def show
+ @matching_tags = @protected_tag.matching(@project.repository.tags)
+ end
+
+ def update
+ @protected_tag = ::ProtectedTags::UpdateService.new(@project, current_user, protected_tag_params).execute(@protected_tag)
+
+ if @protected_tag.valid?
+ respond_to do |format|
+ format.json { render json: @protected_tag, status: :ok }
+ end
+ else
+ respond_to do |format|
+ format.json { render json: @protected_tag.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ def destroy
+ @protected_tag.destroy
+
+ respond_to do |format|
+ format.html { redirect_to_repository_settings(@project) }
+ format.js { head :ok }
+ end
+ end
+
+ private
+
+ def load_protected_tag
+ @protected_tag = @project.protected_tags.find(params[:id])
+ end
+
+ def protected_tag_params
+ params.require(:protected_tag).permit(:name, push_access_levels_attributes: [:access_level, :id])
+ end
+end
diff --git a/app/models/concerns/protected_ref_access.rb b/app/models/concerns/protected_ref_access.rb
new file mode 100644
index 00000000000..9dd4d9c6f24
--- /dev/null
+++ b/app/models/concerns/protected_ref_access.rb
@@ -0,0 +1,21 @@
+module ProtectedBranchAccess
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :protected_branch
+ delegate :project, to: :protected_branch
+
+ scope :master, -> { where(access_level: Gitlab::Access::MASTER) }
+ scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
+ end
+
+ def humanize
+ self.class.human_access_levels[self.access_level]
+ end
+
+ def check_access(user)
+ return true if user.is_admin?
+
+ project.team.max_member_access(user.id) >= access_level
+ end
+end
diff --git a/app/models/concerns/protected_tag_access.rb b/app/models/concerns/protected_tag_access.rb
new file mode 100644
index 00000000000..cf66a6434b5
--- /dev/null
+++ b/app/models/concerns/protected_tag_access.rb
@@ -0,0 +1,21 @@
+module ProtectedTagAccess
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :protected_tag
+ delegate :project, to: :protected_tag
+
+ scope :master, -> { where(access_level: Gitlab::Access::MASTER) }
+ scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
+ end
+
+ def humanize
+ self.class.human_access_levels[self.access_level]
+ end
+
+ def check_access(user)
+ return true if user.is_admin?
+
+ project.team.max_member_access(user.id) >= access_level
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 4a3faff7d5b..3f1a8a1a1e1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -132,6 +132,7 @@ 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 :protected_tags, dependent: :destroy
has_many :project_authorizations
has_many :authorized_users, through: :project_authorizations, source: :user, class_name: 'User'
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 39e979ef15b..7681d5b5112 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -18,50 +18,25 @@ class ProtectedBranch < ActiveRecord::Base
project.commit(self.name)
end
- # Returns all protected branches that match the given branch name.
- # This realizes all records from the scope built up so far, and does
- # _not_ return a relation.
- #
- # This method optionally takes in a list of `protected_branches` to search
- # through, to avoid calling out to the database.
def self.matching(branch_name, protected_branches: nil)
- (protected_branches || all).select { |protected_branch| protected_branch.matches?(branch_name) }
+ ProtectedRefMatcher.matching(ProtectedBranch, branch_name, protected_refs: protected_branches)
end
- # Returns all branches (among the given list of branches [`Gitlab::Git::Branch`])
- # that match the current protected branch.
def matching(branches)
- branches.select { |branch| self.matches?(branch.name) }
+ ref_matcher.matching(branches)
end
- # Checks if the protected branch matches the given branch name.
def matches?(branch_name)
- return false if self.name.blank?
-
- exact_match?(branch_name) || wildcard_match?(branch_name)
+ ref_matcher.matches?(branch_name)
end
- # Checks if this protected branch contains a wildcard
def wildcard?
- self.name && self.name.include?('*')
+ ref_matcher.wildcard?
end
- protected
-
- def exact_match?(branch_name)
- self.name == branch_name
- end
-
- def wildcard_match?(branch_name)
- wildcard_regex === branch_name
- end
+ private
- def wildcard_regex
- @wildcard_regex ||= begin
- name = self.name.gsub('*', 'STAR_DONT_ESCAPE')
- quoted_name = Regexp.quote(name)
- regex_string = quoted_name.gsub('STAR_DONT_ESCAPE', '.*?')
- /\A#{regex_string}\z/
- end
+ def ref_matcher
+ @ref_matcher ||= ProtectedRefMatcher.new(self)
end
end
diff --git a/app/models/protected_ref_matcher.rb b/app/models/protected_ref_matcher.rb
new file mode 100644
index 00000000000..83f44240259
--- /dev/null
+++ b/app/models/protected_ref_matcher.rb
@@ -0,0 +1,52 @@
+class ProtectedRefMatcher
+ def initialize(protected_ref)
+ @protected_ref = protected_ref
+ end
+
+ # Returns all protected refs that match the given ref name.
+ # This realizes all records from the scope built up so far, and does
+ # _not_ return a relation.
+ #
+ # This method optionally takes in a list of `protected_refs` to search
+ # through, to avoid calling out to the database.
+ def self.matching(type, ref_name, protected_refs: nil)
+ (protected_refs || type.all).select { |protected_ref| protected_ref.matches?(ref_name) }
+ end
+
+ # Returns all branches/tags (among the given list of refs [`Gitlab::Git::Branch`])
+ # that match the current protected ref.
+ def matching(refs)
+ refs.select { |ref| @protected_ref.matches?(ref.name) }
+ end
+
+ # Checks if the protected ref matches the given ref name.
+ def matches?(ref_name)
+ return false if @protected_ref.name.blank?
+
+ exact_match?(ref_name) || wildcard_match?(ref_name)
+ end
+
+ # Checks if this protected ref contains a wildcard
+ def wildcard?
+ @protected_ref.name && @protected_ref.name.include?('*')
+ end
+
+ protected
+
+ def exact_match?(ref_name)
+ @protected_ref.name == ref_name
+ end
+
+ def wildcard_match?(ref_name)
+ wildcard_regex === ref_name
+ end
+
+ def wildcard_regex
+ @wildcard_regex ||= begin
+ name = @protected_ref.name.gsub('*', 'STAR_DONT_ESCAPE')
+ quoted_name = Regexp.quote(name)
+ regex_string = quoted_name.gsub('STAR_DONT_ESCAPE', '.*?')
+ /\A#{regex_string}\z/
+ end
+ end
+end
diff --git a/app/models/protected_tag.rb b/app/models/protected_tag.rb
new file mode 100644
index 00000000000..d307549aa49
--- /dev/null
+++ b/app/models/protected_tag.rb
@@ -0,0 +1,39 @@
+class ProtectedTag < ActiveRecord::Base
+ include Gitlab::ShellAdapter
+
+ belongs_to :project
+ validates :name, presence: true
+ validates :project, presence: true
+
+ has_many :push_access_levels, dependent: :destroy
+
+ validates :push_access_levels, length: { is: 1, message: "are restricted to a single instance per protected tag." }
+
+ accepts_nested_attributes_for :push_access_levels
+
+ def commit
+ project.commit(self.name)
+ end
+
+ def self.matching(tag_name, protected_tags: nil)
+ ProtectedRefMatcher.matching(ProtectedTag, tag_name, protected_refs: protected_tags)
+ end
+
+ def matching(branches)
+ ref_matcher.matching(branches)
+ end
+
+ def matches?(tag_name)
+ ref_matcher.matches?(tag_name)
+ end
+
+ def wildcard?
+ ref_matcher.wildcard?
+ end
+
+ private
+
+ def ref_matcher
+ @ref_matcher ||= ProtectedRefMatcher.new(self)
+ end
+end
diff --git a/app/models/protected_tag/push_access_level.rb b/app/models/protected_tag/push_access_level.rb
new file mode 100644
index 00000000000..9282af841ce
--- /dev/null
+++ b/app/models/protected_tag/push_access_level.rb
@@ -0,0 +1,21 @@
+class ProtectedTag::PushAccessLevel < ActiveRecord::Base
+ include ProtectedTagAccess
+
+ validates :access_level, presence: true, inclusion: { in: [Gitlab::Access::MASTER,
+ Gitlab::Access::DEVELOPER,
+ Gitlab::Access::NO_ACCESS] }
+
+ def self.human_access_levels
+ {
+ Gitlab::Access::MASTER => "Masters",
+ Gitlab::Access::DEVELOPER => "Developers + Masters",
+ Gitlab::Access::NO_ACCESS => "No one"
+ }.with_indifferent_access
+ end
+
+ def check_access(user)
+ return false if access_level == Gitlab::Access::NO_ACCESS
+
+ super
+ end
+end
diff --git a/app/services/protected_tags/create_service.rb b/app/services/protected_tags/create_service.rb
new file mode 100644
index 00000000000..faba7865a17
--- /dev/null
+++ b/app/services/protected_tags/create_service.rb
@@ -0,0 +1,11 @@
+module ProtectedTags
+ class CreateService < BaseService
+ attr_reader :protected_tag
+
+ def execute
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
+
+ project.protected_tags.create(params)
+ end
+ end
+end
diff --git a/app/services/protected_tags/update_service.rb b/app/services/protected_tags/update_service.rb
new file mode 100644
index 00000000000..8a2419efd7b
--- /dev/null
+++ b/app/services/protected_tags/update_service.rb
@@ -0,0 +1,13 @@
+module ProtectedTags
+ class UpdateService < BaseService
+ attr_reader :protected_tag
+
+ def execute(protected_tag)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
+
+ @protected_tag = protected_tag
+ @protected_tag.update(params)
+ @protected_tag
+ end
+ end
+end