Browse Source

Merge branch 'develop'

tags/v3.0.0
Jasder 5 years ago
parent
commit
a357ea3ecd
46 changed files with 1622 additions and 124 deletions
  1. +13
    -0
      README.md
  2. +527
    -112
      api_document.md
  3. +43
    -0
      app/controllers/protected_branches_controller.rb
  4. +19
    -0
      app/forms/protected_branches/create_form.rb
  5. +2
    -0
      app/helpers/protected_branches_helper.rb
  6. +44
    -0
      app/interactors/repositories/protected_branches/delete_interactor.rb
  7. +1
    -0
      app/models/concerns/project_operable.rb
  8. +65
    -0
      app/models/protected_branch.rb
  9. +1
    -0
      app/models/repository.rb
  10. +5
    -1
      app/services/application_service.rb
  11. +99
    -2
      app/services/gitea/client_service.rb
  12. +2
    -1
      app/services/gitea/hooks/create_service.rb
  13. +2
    -1
      app/services/gitea/oauth2/create_service.rb
  14. +1
    -1
      app/services/gitea/repository/branches/get_service.rb
  15. +1
    -1
      app/services/gitea/repository/branches/list_service.rb
  16. +2
    -1
      app/services/gitea/repository/create_service.rb
  17. +3
    -1
      app/services/gitea/repository/entries/create_service.rb
  18. +3
    -1
      app/services/gitea/repository/fork_service.rb
  19. +3
    -1
      app/services/gitea/repository/migrate_service.rb
  20. +76
    -0
      app/services/gitea/repository/protected_branches/create_service.rb
  21. +39
    -0
      app/services/gitea/repository/protected_branches/destroy_service.rb
  22. +78
    -0
      app/services/gitea/repository/protected_branches/update_service.rb
  23. +3
    -1
      app/services/gitea/repository/sync_mirrored_service.rb
  24. +276
    -0
      app/services/protected_branches/base_service.rb
  25. +23
    -0
      app/services/protected_branches/create_service.rb
  26. +26
    -0
      app/services/protected_branches/destroy_service.rb
  27. +35
    -0
      app/services/protected_branches/edit_service.rb
  28. +23
    -0
      app/services/protected_branches/get_service.rb
  29. +31
    -0
      app/services/protected_branches/update_service.rb
  30. +16
    -0
      app/views/protected_branches/_protected_branch.json.jbuilder
  31. +1
    -0
      app/views/protected_branches/create.json.jbuilder
  32. +9
    -0
      app/views/protected_branches/edit.json.jbuilder
  33. +2
    -0
      app/views/protected_branches/index.json.jbuilder
  34. +1
    -0
      app/views/protected_branches/show.json.jbuilder
  35. +1
    -0
      app/views/protected_branches/update.json.jbuilder
  36. +2
    -0
      config/application.rb
  37. +28
    -0
      config/routes.rb
  38. +31
    -0
      db/migrate/20201130081039_create_protected_branches.rb
  39. +40
    -0
      spec/controllers/protected_branches_controller_spec.rb
  40. +15
    -0
      spec/helpers/protected_branches_helper_spec.rb
  41. +5
    -0
      spec/models/protected_branch_spec.rb
  42. +5
    -0
      spec/views/protected_branches/create.html.erb_spec.rb
  43. +5
    -0
      spec/views/protected_branches/destroy.html.erb_spec.rb
  44. +5
    -0
      spec/views/protected_branches/edit.html.erb_spec.rb
  45. +5
    -0
      spec/views/protected_branches/index.html.erb_spec.rb
  46. +5
    -0
      spec/views/protected_branches/update.html.erb_spec.rb

+ 13
- 0
README.md View File

@@ -110,3 +110,16 @@ http://localhost:3000/
- 里程碑

![](docs/figs/milestone.png)

### API
- [API](api_document.md)

## 贡献代码

1. Fork 项目
2. 创建本地分支(git checkout -b my-new-feature)
3. 提交更改 (git commit -am 'Add some feature')
4. 推送到分支 (git push origin my-new-feature)
5. 向源项目的 **develop** 分支发起 Pull Request

## License

+ 527
- 112
api_document.md
File diff suppressed because it is too large
View File


+ 43
- 0
app/controllers/protected_branches_controller.rb View File

@@ -0,0 +1,43 @@
class ProtectedBranchesController < ApplicationController
include OperateProjectAbilityAble

before_action :require_login
before_action :load_repository
before_action :authorizate_user_can_edit_project!

def index
scope = ProtectedBranch.all
@total_count = scope.size
@protected_branches = paginate(scope)
end

def create
@protected_branch = ProtectedBranches::CreateService.call(@repository, @owner, params)

render_protected_branch_json
end

def update
@protected_branch = ProtectedBranches::UpdateService.call(@repository, @owner, params)
end

def destroy
ProtectedBranches::DestroyService.call(@repository, @owner, params[:branch_name])

render_ok
end

def show
@protected_branch = ProtectedBranches::GetService.call(@repository, @owner, params)
end

def edit
@branch, @protected_branch = ProtectedBranches::EditService.call(@repository, @owner, params[:branch_name])
end

private
def render_protected_branch_json
@protected_branch.persisted? ? @protected_branch : render_error('创建失败!')
end

end

+ 19
- 0
app/forms/protected_branches/create_form.rb View File

@@ -0,0 +1,19 @@
class ProtectedBranches::CreateForm < BaseForm
attr_accessor :repository, :branch_name, :can_push, :enable_whitelist, :whitelist_user_i_ds,
:whitelist_team_i_ds, :enable_merge_whitelist, :whitelist_deploy_keys, :merge_whitelist_user_i_ds,
:merge_whitelist_team_i_ds, :enable_status_check, :status_check_contexts, :approvals_whitelist_user_i_ds,
:approvals_whitelist_team_i_ds, :required_approvals, :enable_approvals_whitelist, :block_on_rejected_reviews,
:dismiss_stale_approvals, :require_signed_commits, :protected_file_patterns, :block_on_outdated_branch

validates :repo_id, :branch_name, presence: true

validate do
check_branch_name!
end


def check_branch_name!
protected_branch_exists = repository.protected_branches.exists?(branch_name)
raise "Protected branch '#{branch_name}' already exists" if protected_branch_exists
end
end

+ 2
- 0
app/helpers/protected_branches_helper.rb View File

@@ -0,0 +1,2 @@
module ProtectedBranchesHelper
end

+ 44
- 0
app/interactors/repositories/protected_branches/delete_interactor.rb View File

@@ -0,0 +1,44 @@
module Repositories::ProtectedBranches
class DeleteInteractor
def self.call(user, identifier, filepath, **args)
interactor = new(user, identifier, filepath, **args)
interactor.run
interactor
end

attr_reader :error, :result

def initialize(user, identifier, filepath, **args)
@user = user
@identifier = identifier
@filepath = filepath
@args = args
end

def success?
@error.nil?
end

def result
end

def run

rescue Exception => exception
fail!(exception.message)
end


private

attr_reader :user, :identifier, :filepath, :args

def fail!(error)
@error = error
end

def render_result(response)
@result = response
end
end
end

+ 1
- 0
app/models/concerns/project_operable.rb View File

@@ -7,6 +7,7 @@ module ProjectOperable
has_many :managers, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
has_many :developers, -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member'
has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member'
has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member'
end

def add_member!(user_id, role_name='Developer')


+ 65
- 0
app/models/protected_branch.rb View File

@@ -0,0 +1,65 @@
# == Schema Information
#
# Table name: protected_branches
#
# id :integer not null, primary key
# repo_id :integer
# branch_name :string(255) default("")
# can_push :boolean default("0"), not null
# enable_whitelist :boolean default("0")
# whitelist_user_i_ds :text(65535)
# whitelist_team_i_ds :text(65535)
# enable_merge_whitelist :boolean default("0"), not null
# whitelist_deploy_keys :boolean default("0"), not null
# merge_whitelist_user_i_ds :text(65535)
# merge_whitelist_team_i_ds :text(65535)
# enable_status_check :boolean default("0"), not null
# status_check_contexts :text(65535)
# approvals_whitelist_user_i_ds :text(65535)
# approvals_whitelist_team_i_ds :text(65535)
# required_approvals :integer default("0")
# enable_approvals_whitelist :boolean default("0"), not null
# block_on_rejected_reviews :boolean default("0"), not null
# dismiss_stale_approvals :boolean default("0"), not null
# require_signed_commits :boolean default("0"), not null
# protected_file_patterns :text(65535)
# block_on_outdated_branch :boolean default("0"), not null
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_protected_branches_on_repo_id (repo_id)
#

class ProtectedBranch < ApplicationRecord
serialize :whitelist_user_i_ds, Array
serialize :merge_whitelist_user_i_ds, Array
serialize :approvals_whitelist_user_i_ds, Array

belongs_to :repo, class_name: 'Repository', foreign_key: :repo_id
validates :branch_name, presence: true
validates :repo, presence: true

def to_param
self.branch_name.parameterize
end


def push_whitelist_usernames
get_logins_by_ids(whitelist_user_i_ds)
end

def merge_whitelist_usernames
get_logins_by_ids(merge_whitelist_user_i_ds)
end

def approvals_whitelist_usernames
get_logins_by_ids(approvals_whitelist_user_i_ds)
end

def get_logins_by_ids(ids)
User.where(id: ids).map(&:login)
end

end

+ 1
- 0
app/models/repository.rb View File

@@ -37,6 +37,7 @@ class Repository < ApplicationRecord
has_one :mirror, foreign_key: :repo_id
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :repo_id
has_many :version_releases, dependent: :destroy
has_many :protected_branches, class_name: 'ProtectedBranch', foreign_key: :repo_id, dependent: :destroy

validates :identifier, presence: true



+ 5
- 1
app/services/application_service.rb View File

@@ -14,4 +14,8 @@ class ApplicationService
def strip(str)
str.to_s.strip.presence
end
end
def str_to_boolean str
ActiveModel::Type::Boolean.new.cast str
end
end

+ 99
- 2
app/services/gitea/client_service.rb View File

@@ -21,11 +21,10 @@ class Gitea::ClientService < ApplicationService
def post(url, params={})
puts "[gitea] request params: #{params}"
auth_token = authen_params(params[:token])
response = conn(auth_token).post do |req|
conn(auth_token).post do |req|
req.url full_url(url)
req.body = params[:data].to_json
end
render_status(response)
end

def get(url, params={})
@@ -164,4 +163,102 @@ class Gitea::ClientService < ApplicationService
nil
end
end

def render_response(response)
status = response.status
body = response&.body

log_error(status, body)

body, message = get_body_by_status(status, body)

[status, message, body]
end

def get_body_by_status(status, body)
body, message =
case status
when 404 then [nil, "404"]
when 403 then [nil, "403"]
else
if body.present?
body = JSON.parse(body)
fix_body(body)
else
nil
end
end

[body, message]
end

def log_error(status, body)
puts "[gitea] status: #{status}"
puts "[gitea] body: #{body}"
end

def fix_body(body)
return [body, nil] if body.is_a? Array

body['message'].blank? ? [body, nil] : [nil, body['message']]
end

def render_json_data(status, message, body, success=true)
if success
success(body)
else
error(message, status)
end
end

def error(message, http_status = nil)
result = {
message: message,
status: :error
}

result[:http_status] = http_status if http_status
result
end

def success(body=nil)
{
status: :success,
body: body
}
end

def render_body(body)
success(body)[:body]
end

def render_200_response(response)
extract_statuses(response)
end

def render_200_no_body(response)
response.status
case response.status
when 200
{status: 200}
else
end
end

def render_201_response(response)
extract_statuses(response)
end

def render_202_response(response)
extract_statuses(response)
end

def extract_statuses(response)
success_statuses = [200, 201, 202, 204]
status, message, body = render_response(response)

return error(message, status) unless success_statuses.include? status

render_body(body)
end
end

+ 2
- 1
app/services/gitea/hooks/create_service.rb View File

@@ -24,7 +24,8 @@ class Gitea::Hooks::CreateService < Gitea::ClientService
end

def call
post(url, params)
response = post(url, params)
render_201_response(response)
end

private


+ 2
- 1
app/services/gitea/oauth2/create_service.rb View File

@@ -27,7 +27,8 @@ class Gitea::Oauth2::CreateService < Gitea::ClientService
end

def call
post(url, request_params)
response = post(url, request_params)
render_201_response(response)
end

private


+ 1
- 1
app/services/gitea/repository/branches/get_service.rb View File

@@ -13,7 +13,7 @@ class Gitea::Repository::Branches::GetService < Gitea::ClientService

def call
response = get(url, params)
render_data(response)
render_200_response(response)
end

private


+ 1
- 1
app/services/gitea/repository/branches/list_service.rb View File

@@ -8,7 +8,7 @@ class Gitea::Repository::Branches::ListService < Gitea::ClientService

def call
response = get(url, params)
render_data(response)
render_200_response(response)
end

private


+ 2
- 1
app/services/gitea/repository/create_service.rb View File

@@ -18,7 +18,8 @@ class Gitea::Repository::CreateService < Gitea::ClientService
end

def call
post(url, request_params)
response = post(url, request_params)
render_201_response(response)
end

private


+ 3
- 1
app/services/gitea/repository/entries/create_service.rb View File

@@ -29,7 +29,9 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
end

def call
post(url, params)
response = post(url, params)

render_201_response(response)
end

private


+ 3
- 1
app/services/gitea/repository/fork_service.rb View File

@@ -14,7 +14,9 @@ class Gitea::Repository::ForkService < Gitea::ClientService
end

def call
post(url, request_params)
response = post(url, request_params)
render_202_response(response)
end

private


+ 3
- 1
app/services/gitea/repository/migrate_service.rb View File

@@ -31,7 +31,9 @@ class Gitea::Repository::MigrateService < Gitea::ClientService
end

def call
post(url, request_params)
response = post(url, request_params)

render_201_response(response)
end

private


+ 76
- 0
app/services/gitea/repository/protected_branches/create_service.rb View File

@@ -0,0 +1,76 @@
# Create a branch protections for a repository

class Gitea::Repository::ProtectedBranches::CreateService < Gitea::ClientService
attr_reader :owner, :repo, :body, :token

# owner: owner of the repo
# repo: name of the repo
# body:
# {
# "approvals_whitelist_teams": [
# "string"
# ],
# "approvals_whitelist_username": [
# "string"
# ],
# "block_on_outdated_branch": true,
# "block_on_rejected_reviews": true,
# "branch_name": "string",
# "dismiss_stale_approvals": true,
# "enable_approvals_whitelist": true,
# "enable_merge_whitelist": true,
# "enable_push": true,
# "enable_push_whitelist": true,
# "enable_status_check": true,
# "merge_whitelist_teams": [
# "string"
# ],
# "merge_whitelist_usernames": [
# "string"
# ],
# "protected_file_patterns": "string",
# "push_whitelist_deploy_keys": true,
# "push_whitelist_teams": [
# "string"
# ],
# "push_whitelist_usernames": [
# "string"
# ],
# "require_signed_commits": true,
# "required_approvals": 0,
# "status_check_contexts": [
# "string"
# ]
# }

def initialize(owner, repo, body={}, token=nil)
@owner = owner
@repo = repo
@body = body
@token = token
end

def call
response = post(url, params)
status, message, body = render_response(response)
json_format(status, message, body)
end

private
def params
Hash.new.merge(token: token, data: body)
end

def url
"/repos/#{owner}/#{repo}/branch_protections".freeze
end

def json_format(status, message, body)
case status
when 201 then success(body)
else
error(message, status)
end
end

end

+ 39
- 0
app/services/gitea/repository/protected_branches/destroy_service.rb View File

@@ -0,0 +1,39 @@
# Delete a specific branch protection for the repository

class Gitea::Repository::ProtectedBranches::DestroyService < Gitea::ClientService
attr_reader :owner, :repo, :name, :token

# owner: owner of the repo
# repo: name of the repo
# name: name of protected branch
# eg:
# Gitea::Repository::ProtectedBranches::DestroyService.call(user.login, repo.identifier, branch_name, user.gitea_token)
def initialize(owner, repo, name, token=nil)
@owner = owner
@repo = repo
@name = name
@token = token
end

def call
response = delete(url, params)
status, message = render_response(response)
json_format(status, message)
end

private
def params
Hash.new.merge(token: token, data: name)
end

def url
"/repos/#{owner}/#{repo}/branch_protections/#{name}".freeze
end

def json_format(status, message)
case status
when 204 then success
when 404 then error(message, 404)
end
end
end

+ 78
- 0
app/services/gitea/repository/protected_branches/update_service.rb View File

@@ -0,0 +1,78 @@
# Edit a branch protections for a repository. Only fields that are set will be changed

class Gitea::Repository::ProtectedBranches::UpdateService < Gitea::ClientService
attr_reader :owner, :repo, :name, :body, :token

# owner: owner of the repo
# repo: name of the repo
# nmae: name of protected branch
# body:
# {
# "approvals_whitelist_teams": [
# "string"
# ],
# "approvals_whitelist_username": [
# "string"
# ],
# "block_on_outdated_branch": true,
# "block_on_rejected_reviews": true,
# "branch_name": "string",
# "dismiss_stale_approvals": true,
# "enable_approvals_whitelist": true,
# "enable_merge_whitelist": true,
# "enable_push": true,
# "enable_push_whitelist": true,
# "enable_status_check": true,
# "merge_whitelist_teams": [
# "string"
# ],
# "merge_whitelist_usernames": [
# "string"
# ],
# "protected_file_patterns": "string",
# "push_whitelist_deploy_keys": true,
# "push_whitelist_teams": [
# "string"
# ],
# "push_whitelist_usernames": [
# "string"
# ],
# "require_signed_commits": true,
# "required_approvals": 0,
# "status_check_contexts": [
# "string"
# ]
# }
# eq:
# Gitea::Repository::ProtectedBranches::UpdateService.call(user.login, repo.identifier, branch_name, body, user.gitea_token)
def initialize(owner, repo, name, body, token=nil)
@owner = owner
@repo = repo
@name = name
@body = body
@token = token
end

def call
response = patch(url, params)
status, message, body = render_response(response)
json_format(status, message, body)
end

private
def params
Hash.new.merge(token: token, data: body)
end

def url
"/repos/#{owner}/#{repo}/branch_protections/#{name}".freeze
end

def json_format(status, message, body)
case status
when 200 then success(body)
else
error(message, status)
end
end
end

+ 3
- 1
app/services/gitea/repository/sync_mirrored_service.rb View File

@@ -15,7 +15,9 @@ class Gitea::Repository::SyncMirroredService < Gitea::ClientService
end

def call
post(url, request_params)
response = post(url, request_params)

render_200_no_body(response)
end

private


+ 276
- 0
app/services/protected_branches/base_service.rb View File

@@ -0,0 +1,276 @@
module ProtectedBranches
class BaseService < ApplicationService
Error = Class.new(StandardError)
attr_accessor :repository, :owner, :params

def initialize(repository, user = nil, params = {})
@repository, @owner, @params = repository, user, params.dup
end

# delegate :repository, to: :project

def protected_branch_params
# {
# "approvals_whitelist_teams": [
# "string"
# ], //批准团队(或审查团队)白名单
# "approvals_whitelist_username": [
# "string"
# ], // 批准用户(或审查者)白名单
# "block_on_outdated_branch": true, // 如果拉取过时,阻止合并
# "block_on_rejected_reviews": true, // 拒绝审核,阻止合并请求
# "branch_name": "string", //分支名称
# "dismiss_stale_approvals": true, // 取消过时的批准
# "enable_approvals_whitelist": true, //是否批准仅限列入白名单的用户或者团队, 主要用户pr的审核批准计数功能
# "enable_merge_whitelist": true, // 是否启用合并请求白名单
# "enable_push": true, //启用、禁止推送
# "enable_push_whitelist": true, // 是否启动推送白名单
# "enable_status_check": true, //是否启用状态检查
# "merge_whitelist_teams": [
# "string"
# ], // 合并请求团队白名单
# "merge_whitelist_usernames": [
# "string"
# ], // 合并请求用户白名单
# "protected_file_patterns": "string", //保护文件模式
# "push_whitelist_deploy_keys": true, // 具有推送权限的部署密钥白名单
# "push_whitelist_teams": [
# "string"
# ], //推送团队白名单
# "push_whitelist_usernames": [
# "string"
# ], //推送用户白名单
# "require_signed_commits": true, //是否需要签名提交
# "required_approvals": 0, // 所需批准数
# "status_check_contexts": [
# "string"
# ] // 状态检查规则
# }


# branch_name :string(255) default("")
# can_push :boolean default("0"), not null
# enable_whitelist :boolean default("0")
# whitelist_user_i_ds :text(65535)
# whitelist_team_i_ds :text(65535)
# enable_merge_whitelist :boolean default("0"), not null
# whitelist_deploy_keys :boolean default("0"), not null
# merge_whitelist_user_i_ds :text(65535)
# merge_whitelist_team_i_ds :text(65535)
# enable_status_check :boolean default("0"), not null
# status_check_contexts :text(65535)
# approvals_whitelist_user_i_ds :text(65535)
# approvals_whitelist_team_i_ds :text(65535)
# required_approvals :integer default("0")
# enable_approvals_whitelist :boolean default("0"), not null
# block_on_rejected_reviews :boolean default("0"), not null
# dismiss_stale_approvals :boolean default("0"), not null
# require_signed_commits :boolean default("0"), not null
# protected_file_patterns :text(65535)
# block_on_outdated_branch :boolean default("0"), not null

{
branch_name: params[:branch_name],
can_push: can_push_params,
enable_whitelist: enable_whitelist_params,
whitelist_user_i_ds: whitelist_user_i_ds_params,
# whitelist_team_i_ds: whitelist_team_i_ds_params,
enable_merge_whitelist: enable_merge_whitelist_params,
merge_whitelist_user_i_ds: merge_whitelist_user_i_ds_params,
# merge_whitelist_team_i_ds: merge_whitelist_team_i_ds_params,
enable_status_check: enable_status_check_params,
required_approvals: params[:required_approvals] || 0,
enable_approvals_whitelist: enable_approvals_whitelist_params,
approvals_whitelist_user_i_ds: approvals_whitelist_user_i_ds_params,
# approvals_whitelist_team_i_ds: approvals_whitelist_team_i_ds_params,
block_on_rejected_reviews: block_on_rejected_reviews_params,
dismiss_stale_approvals: dismiss_stale_approvals_params,
require_signed_commits: require_signed_commits_params,
block_on_outdated_branch: block_on_outdated_branch_params
}
end

def enable_status_check_params
str_to_boolean(params[:enable_status_check] || false)
end

def enable_approvals_whitelist_params
str_to_boolean(params[:enable_approvals_whitelist] || false)
end
def block_on_rejected_reviews_params
str_to_boolean(params[:block_on_rejected_reviews] || false)
end

def dismiss_stale_approvals_params
str_to_boolean(params[:dismiss_stale_approvals] || false)
end

def require_signed_commits_params
str_to_boolean(params[:require_signed_commits] || false)
end

def block_on_outdated_branch_params
str_to_boolean(params[:block_on_outdated_branch] || false)
end

def can_push_params
return false if !can_push?
return true if enable_whitelist?
str_to_boolean(params[:enable_push])
end

def enable_whitelist_params
return false if !can_push?
str_to_boolean(params[:enable_push_whitelist])
end

def whitelist_user_i_ds_params
return [] if !can_push?
user_ids(get_push_whitelist_usernames)
end

def whitelist_team_i_ds_params
# params[:push_whitelist_usernames]
end

def enable_merge_whitelist_params
str_to_boolean(params[:enable_merge_whitelist] || false)
end

def merge_whitelist_user_i_ds_params
returtn [] if !enable_merge_whitelist?
user_ids(get_merge_whitelist_usernames)
end

def merge_whitelist_team_i_ds_params
params[:merge_whitelist_teams]
end

def approvals_whitelist_user_i_ds_params
return [] if !enable_approvals_whitelist?
user_ids(get_approvals_whitelist_usernames)
end

def approvals_whitelist_team_i_ds_params
params[:approvals_whitelist_teams]
end

def user_ids(names)
member_ids & names_by_params(names)
end

def member_ids
@repository.project.writable_members.map(&:user_id)
end

def names_by_params(names)
User.where(login: names.to_a).ids
end

def get_push_whitelist_usernames
return [] if !can_push? || !enable_whitelist?
filter_empty_element Array(params[:push_whitelist_usernames])
end

def get_merge_whitelist_usernames
return [] if !enable_merge_whitelist?
filter_empty_element Array(params[:merge_whitelist_usernames])
end

def get_approvals_whitelist_usernames
return [] if !enable_approvals_whitelist?
filter_empty_element Array(params[:approvals_whitelist_usernames])
end

def check_users!(names)
names.each {|name|
check_user!(name)
break
}
end

def check_user!(name)
user_exist = User.exists?(login: name)
raise Error, "user '#{name}' does not exist" if !user_exist
end

def can_push?
str_to_boolean(params[:enable_push]) === true
end

def enable_whitelist?
str_to_boolean(params[:enable_push_whitelist]) === true
end

def enable_merge_whitelist?
str_to_boolean(params[:enable_merge_whitelist]) === true
end

def enable_approvals_whitelist?
str_to_boolean(params[:enable_approvals_whitelist]) === true
end

def filter_empty_element(array)
array.reject { |e| e.to_s.empty? }
end

def save_gitea_protected_branch!
@gitea_protected_branch ||= Gitea::Repository::ProtectedBranches::CreateService.call(@owner.login,
@repository.identifier,gitea_protected_branch_params, @owner.gitea_token)

raise Error, @gitea_protected_branch[:message] if @gitea_protected_branch[:status] != :success
end

def gitea_protected_branch_saved?
@gitea_protected_branch[:status] === success
end

def gitea_protected_branch
@gitea_protected_branch[:body]
end

def gitea_protected_branch_params
{
approvals_whitelist_username: get_approvals_whitelist_usernames,
branch_name: params[:branch_name],
enable_approvals_whitelist: enable_approvals_whitelist_params,
enable_merge_whitelist: enable_merge_whitelist_params,
enable_push: can_push_params,
enable_push_whitelist: enable_whitelist_params,
enable_status_check: enable_status_check_params,
# merge_whitelist_teams: [],
merge_whitelist_usernames: get_merge_whitelist_usernames,
# protected_file_patterns: string,
# push_whitelist_deploy_keys: true,
# push_whitelist_teams: [],
push_whitelist_usernames: get_push_whitelist_usernames,
block_on_rejected_reviews: block_on_rejected_reviews_params,
dismiss_stale_approvals: dismiss_stale_approvals_params,
require_signed_commits: require_signed_commits_params,
block_on_outdated_branch: block_on_outdated_branch_params

}
end

def validate!
protected_branch_exists = repository.protected_branches.exists?(params[:branch_name])
raise Error, "Protected branch '#{branch_name}' already exists" if protected_branch_exists

check_users!(get_push_whitelist_usernames) if get_push_whitelist_usernames.any?
check_users!(get_merge_whitelist_usernames) if get_merge_whitelist_usernames.any?
check_users!(get_approvals_whitelist_usernames) if get_approvals_whitelist_usernames.any?

raise Error, '分支名称不能为空' if params[:branch_name].blank?

end
end

def error(errors, award: nil, status: nil)
errors = Array.wrap(errors)

super(errors.to_sentence.presence, status).merge({
award: award,
errors: errors
})
end
end

+ 23
- 0
app/services/protected_branches/create_service.rb View File

@@ -0,0 +1,23 @@
module ProtectedBranches
class CreateService < ProtectedBranches::BaseService
def call
validate!

ProtectedBranch.transaction do
save_gitea_protected_branch!
save_protected_branch!
end

protected_branch
end

private
def protected_branch
@protected_branch ||= repository.protected_branches.new(protected_branch_params)
end

def save_protected_branch!
protected_branch.save
end
end
end

+ 26
- 0
app/services/protected_branches/destroy_service.rb View File

@@ -0,0 +1,26 @@
module ProtectedBranches
class DestroyService < ProtectedBranches::BaseService
def call
protected_branch.destroy! if success?
rescue ActiveRecord::RecordNotFound
raise Error, '404'
rescue => ex
Rails.logger.info ex
raise Error, ex
end

private
def protected_branch
@protected_branch ||= @repository.protected_branches.find_by!(branch_name: @params)
end

def success?
result = Gitea::Repository::ProtectedBranches::DestroyService.call(@owner.login,
@repository.identifier, protected_branch.branch_name, @owner.gitea_token)

return true if result[:status] === :success
raise Error, result[:message]
end

end
end

+ 35
- 0
app/services/protected_branches/edit_service.rb View File

@@ -0,0 +1,35 @@
module ProtectedBranches
class EditService < ProtectedBranches::BaseService
def call
validate_branch_name!

protected_branch
rescue => ex
Rails.logger.info ex
raise Error, ex
end

private
def protected_branch
branch = get_common_branch
protected_branch ||= @repository.protected_branches.find_by(branch_name: branch_name)
[branch, protected_branch]
end

def get_common_branch
result = Gitea::Repository::Branches::GetService.call(@owner.login,
@repository.identifier, branch_name, @owner.gitea_token)

raise Error, '404' if result[:status] == :error
result
end

def validate_branch_name!
raise Error, '分支名称不能为空' if branch_name.blank?
end

def branch_name
params
end
end
end

+ 23
- 0
app/services/protected_branches/get_service.rb View File

@@ -0,0 +1,23 @@
module ProtectedBranches
class GetService < ProtectedBranches::BaseService
def call
validate_branch_name!

protected_branch
rescue ActiveRecord::RecordNotFound
raise Error, '404'
rescue => ex
Rails.logger.info ex
raise Error, ex
end

private
def protected_branch
@protected_branch ||= @repository.protected_branches.find_by!(branch_name: params[:branch_name])
end

def validate_branch_name!
raise Error, '分支名称不能为空' if params[:branch_name].blank?
end
end
end

+ 31
- 0
app/services/protected_branches/update_service.rb View File

@@ -0,0 +1,31 @@
module ProtectedBranches
class UpdateService < ProtectedBranches::BaseService
def call
validate!
protected_branch.update(protected_branch_params) if success?

protected_branch

rescue ActiveRecord::RecordNotFound
raise Error, '404'
rescue => ex
Rails.logger.info ex
raise Error, ex
end

private
def protected_branch
@protected_branch ||= @repository.protected_branches.find_by!(branch_name: params[:branch_name])
end

def success?
result = Gitea::Repository::ProtectedBranches::UpdateService.call(@owner.login, @repository.identifier,
protected_branch.branch_name, gitea_protected_branch_params, @owner.gitea_token)


return true if result[:status] === :success
raise Error, result[:message]
end

end
end

+ 16
- 0
app/views/protected_branches/_protected_branch.json.jbuilder View File

@@ -0,0 +1,16 @@
json.branch_name protected_branch.branch_name
json.enable_push protected_branch.can_push
json.required_approvals protected_branch.required_approvals
json.enable_status_check protected_branch.enable_status_check
json.enable_push_whitelist protected_branch.enable_whitelist
json.enable_merge_whitelist protected_branch.enable_merge_whitelist
json.enable_approvals_whitelist protected_branch.enable_approvals_whitelist
json.dismiss_stale_approvals protected_branch.dismiss_stale_approvals
json.block_on_rejected_reviews protected_branch.block_on_rejected_reviews
json.block_on_outdated_branch protected_branch.block_on_outdated_branch
json.require_signed_commits protected_branch.require_signed_commits
json.merge_whitelist_usernames protected_branch.merge_whitelist_usernames
json.push_whitelist_usernames protected_branch.push_whitelist_usernames
json.approvals_whitelist_usernames protected_branch.approvals_whitelist_usernames
json.created_at protected_branch.created_at.strftime("%Y-%m-%d %H:%M")
json.updated_at protected_branch.updated_at.strftime("%Y-%m-%d %H:%M")

+ 1
- 0
app/views/protected_branches/create.json.jbuilder View File

@@ -0,0 +1 @@
json.partial! @protected_branch, as: :protected_branch

+ 9
- 0
app/views/protected_branches/edit.json.jbuilder View File

@@ -0,0 +1,9 @@
json.branch_name @branch['name']
json.protected @branch['protected']
json.protected_branch do
if @protected_branch
json.partial! @protected_branch, as: :protected_branch
else
json.nil!
end
end

+ 2
- 0
app/views/protected_branches/index.json.jbuilder View File

@@ -0,0 +1,2 @@
json.total_count @total_count
json.protected_branches @protected_branches, partial: 'protected_branches/protected_branch', as: :protected_branch

+ 1
- 0
app/views/protected_branches/show.json.jbuilder View File

@@ -0,0 +1 @@
json.partial! @protected_branch, as: :protected_branch

+ 1
- 0
app/views/protected_branches/update.json.jbuilder View File

@@ -0,0 +1 @@
json.partial! @protected_branch, as: :protected_branch

+ 2
- 0
config/application.rb View File

@@ -19,6 +19,8 @@ module Educoderplus
#
# config.educoder = config_for(:configuration)
# Custom directories with classes and modules you want to be autoloadable.
config.active_record.default_timezone = :utc
config.time_zone = 'Beijing'


+ 28
- 0
config/routes.rb View File

@@ -323,6 +323,34 @@ Rails.application.routes.draw do
end
end
# protected_branches
scope do
get(
'/protected_branches/',
to: 'protected_branches#index'
)
get(
'/protected_branches/:branch_name',
to: 'protected_branches#show'
)
get(
'/protected_branches/:branch_name/edit',
to: 'protected_branches#edit'
)
delete(
'/protected_branches/:branch_name',
to: 'protected_branches#destroy'
)
post(
'/protected_branches',
to: 'protected_branches#create'
)
patch(
'/protected_branches/:branch_name',
to: 'protected_branches#update'
)
end
resources :issues do
collection do
get :commit_issues


+ 31
- 0
db/migrate/20201130081039_create_protected_branches.rb View File

@@ -0,0 +1,31 @@
class CreateProtectedBranches < ActiveRecord::Migration[5.2]
def change
create_table :protected_branches do |t|
t.integer :repo_id
t.string :branch_name, default: ""
t.boolean :can_push, default: false, null: false
t.boolean :enable_whitelist, default: false
t.text :whitelist_user_i_ds
t.text :whitelist_team_i_ds
t.boolean :enable_merge_whitelist, default: false, null: false
t.boolean :whitelist_deploy_keys, default: false, null: false
t.text :merge_whitelist_user_i_ds
t.text :merge_whitelist_team_i_ds
t.boolean :enable_status_check, default: false, null: false
t.text :status_check_contexts
t.text :approvals_whitelist_user_i_ds
t.text :approvals_whitelist_team_i_ds
t.integer :required_approvals, default: 0
t.boolean :enable_approvals_whitelist, default: false, null: false
t.boolean :block_on_rejected_reviews, default: false, null: false
t.boolean :dismiss_stale_approvals, default: false, null: false
t.boolean :require_signed_commits, default: false, null: false
t.text :protected_file_patterns
t.boolean :block_on_outdated_branch, default: false, null: false

t.timestamps
end

add_index :protected_branches, :repo_id
end
end

+ 40
- 0
spec/controllers/protected_branches_controller_spec.rb View File

@@ -0,0 +1,40 @@
require 'rails_helper'

RSpec.describe ProtectedBranchesController, type: :controller do

describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end

describe "GET #create" do
it "returns http success" do
get :create
expect(response).to have_http_status(:success)
end
end

describe "GET #edit" do
it "returns http success" do
get :edit
expect(response).to have_http_status(:success)
end
end

describe "GET #update" do
it "returns http success" do
get :update
expect(response).to have_http_status(:success)
end
end

describe "GET #destroy" do
it "returns http success" do
get :destroy
expect(response).to have_http_status(:success)
end
end

end

+ 15
- 0
spec/helpers/protected_branches_helper_spec.rb View File

@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the ProtectedBranchesHelper. For example:
#
# describe ProtectedBranchesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe ProtectedBranchesHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/models/protected_branch_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe ProtectedBranch, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/views/protected_branches/create.html.erb_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "protected_branches/create.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/views/protected_branches/destroy.html.erb_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "protected_branches/destroy.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/views/protected_branches/edit.html.erb_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "protected_branches/edit.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/views/protected_branches/index.html.erb_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "protected_branches/index.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end

+ 5
- 0
spec/views/protected_branches/update.html.erb_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "protected_branches/update.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end

Loading…
Cancel
Save