forked from Gitlink/forgeplus
FIX Merge master branch
This commit is contained in:
commit
837aa1ea9e
|
@ -0,0 +1,22 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- name: install
|
||||
image: ruby:2.4.5
|
||||
commands:
|
||||
- gem install bundler
|
||||
- bundle -v
|
||||
- bundle install --jobs=1 --retry=1
|
||||
|
||||
- name: test
|
||||
image: ruby:2.4.5
|
||||
volumes:
|
||||
- name: bundle
|
||||
path: /usr/local/bundle
|
||||
commands:
|
||||
- rake
|
5
Gemfile
5
Gemfile
|
@ -1,8 +1,6 @@
|
|||
source 'https://gems.ruby-china.com'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
ruby '2.3.7'
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
|
||||
gem 'puma', '~> 3.11'
|
||||
|
@ -19,8 +17,6 @@ gem 'kaminari', '~> 1.1', '>= 1.1.1'
|
|||
|
||||
gem 'bootsnap', '>= 1.1.0', require: false
|
||||
|
||||
gem 'gitlab', path: 'lib/gitlab-cli'
|
||||
|
||||
gem 'chinese_pinyin'
|
||||
|
||||
gem 'rack-cors'
|
||||
|
@ -74,6 +70,7 @@ group :development do
|
|||
gem 'listen', '>= 3.0.5', '< 3.2'
|
||||
gem 'spring'
|
||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
||||
gem "annotate", "~> 2.6.0"
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
23
Gemfile.lock
23
Gemfile.lock
|
@ -1,10 +1,3 @@
|
|||
PATH
|
||||
remote: lib/gitlab-cli
|
||||
specs:
|
||||
gitlab (3.2.0)
|
||||
httparty
|
||||
terminal-table
|
||||
|
||||
GEM
|
||||
remote: https://gems.ruby-china.com/
|
||||
specs:
|
||||
|
@ -61,6 +54,9 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 5.0)
|
||||
ancestry (3.0.7)
|
||||
activerecord (>= 3.2.0)
|
||||
annotate (2.6.5)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
archive-zip (0.12.0)
|
||||
io-like (~> 0.3.0)
|
||||
arel (9.0.0)
|
||||
|
@ -138,9 +134,6 @@ GEM
|
|||
harmonious_dictionary (0.0.1)
|
||||
hashie (3.6.0)
|
||||
htmlentities (4.3.4)
|
||||
httparty (0.18.0)
|
||||
mime-types (~> 3.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (1.8.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
io-like (0.3.1)
|
||||
|
@ -177,9 +170,6 @@ GEM
|
|||
mimemagic (~> 0.3.2)
|
||||
maruku (0.7.3)
|
||||
method_source (0.9.2)
|
||||
mime-types (3.3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2019.1009)
|
||||
mimemagic (0.3.4)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
|
@ -402,8 +392,6 @@ GEM
|
|||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thor (1.0.1)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.10)
|
||||
|
@ -437,6 +425,7 @@ DEPENDENCIES
|
|||
acts-as-taggable-on (~> 6.0)
|
||||
acts_as_list
|
||||
ancestry
|
||||
annotate (~> 2.6.0)
|
||||
awesome_print
|
||||
axlsx (~> 3.0.0.pre)
|
||||
axlsx_rails (~> 0.5.2)
|
||||
|
@ -452,7 +441,6 @@ DEPENDENCIES
|
|||
enumerize
|
||||
faraday (~> 0.15.4)
|
||||
font-awesome-sass (= 4.7.0)
|
||||
gitlab!
|
||||
grape-entity (~> 0.7.1)
|
||||
groupdate (~> 4.1.0)
|
||||
harmonious_dictionary (~> 0.0.1)
|
||||
|
@ -502,8 +490,5 @@ DEPENDENCIES
|
|||
web-console (>= 3.3.0)
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.3.7p456
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -110,33 +110,33 @@ class AccountsController < ApplicationController
|
|||
# params[:login] 邮箱或者手机号
|
||||
# params[:code] 验证码
|
||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||
# 本地forge注册入口
|
||||
def register
|
||||
begin
|
||||
# 查询验证码是否正确;type只可能是1或者8
|
||||
type = phone_mail_type(params[:login].strip)
|
||||
code = params[:code].strip
|
||||
# code = params[:code].strip
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = params[:login]
|
||||
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
||||
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
||||
# TODO: 暂时限定邮箱注册
|
||||
return normal_status(-1, '只支持邮箱注册')
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = params[:login]
|
||||
phone = nil
|
||||
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
||||
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
|
||||
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
|
||||
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
||||
end
|
||||
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
||||
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
||||
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
|
||||
# todo 上线前请删除万能验证码"513231"
|
||||
unless code == "513231" && request.subdomain == "test-newweb"
|
||||
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
|
||||
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
|
||||
end
|
||||
|
||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
|
||||
|
||||
code = generate_identifier User, 8, pre
|
||||
|
@ -146,23 +146,20 @@ class AccountsController < ApplicationController
|
|||
# 现在因为是验证码,所以在注册的时候就可以激活
|
||||
@user.activate
|
||||
# 必须要用save操作,密码的保存是在users中
|
||||
if @user.save!
|
||||
# todo user_extension
|
||||
UserExtension.create!(user_id: @user.id)
|
||||
# 注册完成,手机号或邮箱想可以奖励500金币
|
||||
# RewardGradeService.call(
|
||||
# @user,
|
||||
# container_id: @user.id,
|
||||
# container_type: pre == 'p' ? 'Phone' : 'Mail',
|
||||
# score: 500
|
||||
# )
|
||||
# 注册时,记录是否是引流用户
|
||||
ip = request.remote_ip
|
||||
ua = UserAgent.find_by_ip(ip)
|
||||
ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua
|
||||
successful_authentication(@user)
|
||||
# session[:user_id] = @user.id
|
||||
normal_status("注册成功")
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
|
||||
@user.gitea_token = result['sha1']
|
||||
@user.gitea_uid = gitea_user['id']
|
||||
if @user.save!
|
||||
UserExtension.create!(user_id: @user.id)
|
||||
successful_authentication(@user)
|
||||
normal_status("注册成功")
|
||||
end
|
||||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
@ -6,6 +6,12 @@ class Admins::LaboratoriesController < Admins::BaseController
|
|||
@laboratories = paginate laboratories.preload(:laboratory_users)
|
||||
end
|
||||
|
||||
def new
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
Admins::CreateLaboratoryService.call(create_params)
|
||||
render_ok
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
class Admins::LaboratorySettingsController < Admins::BaseController
|
||||
|
||||
def new
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@laboratory = current_laboratory
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ class ApplicationController < ActionController::Base
|
|||
include LoggerHelper
|
||||
include LoginHelper
|
||||
include RegisterHelper
|
||||
|
||||
|
||||
protect_from_forgery prepend: true, unless: -> { request.format.json? }
|
||||
|
||||
before_action :check_sign
|
||||
|
@ -343,7 +343,8 @@ class ApplicationController < ActionController::Base
|
|||
elsif params[:debug] == 'student'
|
||||
User.current = User.find 8686
|
||||
elsif params[:debug] == 'admin'
|
||||
user = User.find 1
|
||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
user = User.find 36480
|
||||
User.current = user
|
||||
cookies.signed[:user_id] = user.id
|
||||
end
|
||||
|
@ -384,11 +385,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def current_user
|
||||
if Rails.env.development?
|
||||
User.current = User.find 1
|
||||
else
|
||||
User.current
|
||||
end
|
||||
User.current
|
||||
end
|
||||
|
||||
## 默认输出json
|
||||
|
@ -744,12 +741,12 @@ class ApplicationController < ActionController::Base
|
|||
namespace = params[:owner]
|
||||
id = params[:repo] || params[:id]
|
||||
|
||||
@project = Project.find_with_namespace(namespace, id)
|
||||
@project, @owner = Project.find_with_namespace(namespace, id)
|
||||
|
||||
if @project and current_user.can_read_project?(@project)
|
||||
logger.info "###########: has project and can read project"
|
||||
@project
|
||||
elsif current_user.is_a?(AnonymousUser)
|
||||
elsif @project && current_user.is_a?(AnonymousUser)
|
||||
logger.info "###########:This is AnonymousUser"
|
||||
@project = nil if !@project.is_public?
|
||||
render_forbidden and return
|
||||
|
@ -762,7 +759,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def load_repository
|
||||
@repository ||= load_project.repository
|
||||
@repository ||= load_project&.repository
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# 文件上传
|
||||
class AttachmentsController < ApplicationController
|
||||
before_action :require_login, :check_auth, except: [:show]
|
||||
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
||||
before_action :find_file, only: %i[show destroy]
|
||||
before_action :attachment_candown, only: [:show]
|
||||
skip_before_action :check_sign, only: [:show, :create]
|
||||
|
@ -28,6 +28,15 @@ class AttachmentsController < ApplicationController
|
|||
update_downloads(@file)
|
||||
end
|
||||
|
||||
|
||||
def get_file
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||
response = Faraday.get(url)
|
||||
filename = params[:download_url].to_s.split("/").pop()
|
||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||
end
|
||||
|
||||
def create
|
||||
# 1. 本地存储
|
||||
# 2. 上传到云
|
||||
|
@ -107,6 +116,26 @@ class AttachmentsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# 附件为视频时,点击播放
|
||||
def preview_attachment
|
||||
attachment = Attachment.find_by(id: params[:id])
|
||||
dir_path = "#{Rails.root}/public/preview"
|
||||
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
||||
if params[:status] == "preview"
|
||||
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
||||
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
else
|
||||
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
||||
normal_status(1, "操作成功")
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_file
|
||||
@file =
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
class Ci::BaseController < ApplicationController
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :require_login
|
||||
before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? }
|
||||
before_action :connect_to_ci_database, only: :load_repo
|
||||
|
||||
def load_repo
|
||||
namespace = params[:owner]
|
||||
id = params[:repo] || params[:id]
|
||||
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
|
||||
end
|
||||
|
||||
private
|
||||
def authorize_access_project!
|
||||
unless @project.manager?(current_user)
|
||||
return render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_manager!
|
||||
unless @project.manager?(current_user)
|
||||
return render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_admin!
|
||||
return render_forbidden unless current_user.admin?
|
||||
end
|
||||
|
||||
def authorize_owner!
|
||||
unless @project.owner?(current_user)
|
||||
return render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
def find_cloud_account
|
||||
@cloud_account ||= current_user.ci_cloud_account
|
||||
@cloud_account.blank? ? nil : @cloud_account
|
||||
end
|
||||
|
||||
def load_ci_user
|
||||
@ci_user ||= Ci::User.find_by(user_login: params[:owner])
|
||||
@ci_user.blank? ? raise("未找到相关的记录") : @ci_user
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
class Ci::BuildsController < Ci::BaseController
|
||||
include RepositoriesHelper
|
||||
|
||||
before_action :load_project
|
||||
before_action :authorize_owner!, only: [:restart, :stop]
|
||||
before_action :load_repo
|
||||
before_action :find_cloud_account, except: [:index, :show]
|
||||
|
||||
def index
|
||||
@user = current_user
|
||||
scope = @repo.builds
|
||||
|
||||
scope = Ci::Builds::ListQuery.call(@repo, params)
|
||||
|
||||
@total_count = scope.map(&:build_id).size
|
||||
@builds = paginate scope
|
||||
end
|
||||
|
||||
def show
|
||||
@build = @repo.builds.includes(stages: [:steps]).find_by(build_number: params[:build])
|
||||
end
|
||||
|
||||
def restart
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).restart
|
||||
|
||||
render json: result
|
||||
end
|
||||
|
||||
def stop
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).stop
|
||||
render json: result
|
||||
end
|
||||
|
||||
def logs
|
||||
# TODO **待优化**
|
||||
# 因直接操作ci库,如下查询待优化,可直接根据log id查询即可
|
||||
build = @repo.builds.find_by(build_number: params[:build])
|
||||
return render_not_found("Couldn't found build with 'number'= #{params[:build]}") if build.blank?
|
||||
|
||||
stage = build.stages.includes(steps: [:log]).find_by(stage_number: params[:stage])
|
||||
return render_not_found("Couldn't found build with 'number'= #{params[:stage]}") if stage.blank?
|
||||
|
||||
step = stage.steps.find_by(step_number: params[:step])
|
||||
return render_not_found("Couldn't found build with 'number'= #{params[:step]}") if step.blank?
|
||||
|
||||
log = step.log
|
||||
|
||||
result = log.blank? ? nil : (log.log_data[0..5].include?('null') ? nil : JSON.parse(log.log_data))
|
||||
|
||||
# result = Ci::Drone::API.new(@user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, build: params[:build], stage: params[:stage], step: params[:step]).logs
|
||||
|
||||
render json: result
|
||||
end
|
||||
end
|
|
@ -0,0 +1,101 @@
|
|||
class Ci::CloudAccountsController < Ci::BaseController
|
||||
include Ci::CloudAccountManageable
|
||||
|
||||
skip_before_action :connect_to_ci_database, only: %i[create bind]
|
||||
before_action :load_project, only: %i[create activate]
|
||||
before_action :authorize_owner!, only: %i[create activate]
|
||||
before_action :load_repo, only: %i[activate]
|
||||
before_action :find_cloud_account, only: %i[show oauth_grant]
|
||||
before_action :validate_params!, only: %i[create bind]
|
||||
before_action only: %i[create bind] do
|
||||
connect_to_ci_database(master_db: true)
|
||||
end
|
||||
|
||||
def create
|
||||
flag, msg = check_bind_cloud_account!
|
||||
return render_error(msg) if flag === true
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@cloud_account = bind_account!
|
||||
if @cloud_account.blank?
|
||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||
render_ok(redirect_url: @cloud_account.authenticate_url)
|
||||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def activate
|
||||
return render_error('请先认证') unless current_user.ci_certification?
|
||||
|
||||
begin
|
||||
@cloud_account = Ci::CloudAccount.find params[:id]
|
||||
ActiveRecord::Base.transaction do
|
||||
if @repo
|
||||
return render_error('该项目已经激活') if @repo.repo_active?
|
||||
@repo.activate!(@ci_user.user_id)
|
||||
else
|
||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||
@user.update_column(:user_syncing, false)
|
||||
end
|
||||
|
||||
result = bind_hook!(current_user, @cloud_account, @repo)
|
||||
@project.update_columns(open_devops: true, gitea_webhook_id: result['id'])
|
||||
@cloud_account.update_column(:ci_user_id, @ci_user.user_id)
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def bind
|
||||
flag, msg = check_bind_cloud_account!
|
||||
return render_error(msg) if flag === true
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@cloud_account = bind_account!
|
||||
if @cloud_account.blank?
|
||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def unbind
|
||||
ActiveRecord::Base.transaction do
|
||||
unbind_account!
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def oauth_grant
|
||||
password = params[:password].to_s
|
||||
return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
|
||||
|
||||
oauth = current_user.oauths.last
|
||||
return render_error("服务器出小差了.") if oauth.blank?
|
||||
|
||||
result = gitea_oauth_grant!(password, oauth)
|
||||
return render_error('授权失败.') unless result === true
|
||||
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
||||
end
|
||||
|
||||
private
|
||||
def validate_params!
|
||||
Ci::CreateCloudAccountForm.new(devops_params).validate!
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
class Ci::LanguagesController < Ci::BaseController
|
||||
# TODO 需要开启权限认证,只有该项目devops初始化成功后才能获取语言列表
|
||||
before_action :find_langugae, only: :show
|
||||
|
||||
def index
|
||||
@languages = Ci::Language.by_usage_amount_desc
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def common
|
||||
@languages = Ci::Language.six_common
|
||||
end
|
||||
|
||||
private
|
||||
def find_langugae
|
||||
@language = Ci::Language.find params[:id]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
class Ci::ProjectsController < Ci::BaseController
|
||||
include RepositoriesHelper
|
||||
include Ci::CloudAccountManageable
|
||||
|
||||
before_action :load_project
|
||||
before_action :load_repo, only: [:update_trustie_pipeline, :activate, :deactivate]
|
||||
before_action :authorize_owner!, only: [:authorize]
|
||||
before_action :find_cloud_account, only: [:authorize, :activate, :deactivate]
|
||||
|
||||
def authorize
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# get .trustie-pipeline.yml file
|
||||
def get_trustie_pipeline
|
||||
file_path_uri = URI.parse('.trustie-pipeline.yml')
|
||||
interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master")
|
||||
if interactor.success?
|
||||
file = interactor.result
|
||||
return render json: {} if file[:status]
|
||||
|
||||
json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])}
|
||||
render json: json
|
||||
end
|
||||
end
|
||||
|
||||
def update_trustie_pipeline
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, params[:owner], params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def activate
|
||||
return render_error('你还未认证') unless current_user.ci_certification?
|
||||
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
if @repo
|
||||
return render_error('该项目已经激活') if @repo.repo_active?
|
||||
if @project.ci_reactivate?
|
||||
@project.ci_reactivate!(@repo)
|
||||
return render_ok
|
||||
end
|
||||
@repo.activate!(@ci_user.user_id)
|
||||
else
|
||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||
@ci_user.update_column(:user_syncing, false)
|
||||
end
|
||||
|
||||
result = bind_hook!(current_user, @cloud_account, @repo)
|
||||
@project.update_columns(open_devops: true, gitea_webhook_id: result['id'])
|
||||
@project.increment!(:open_devops_count)
|
||||
@cloud_account.update_column(:ci_user_id, @ci_user.user_id)
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
def deactivate
|
||||
return render_error('该项目已经取消激活') if !@repo.repo_active?
|
||||
|
||||
@project.update_column(:open_devops, false)
|
||||
@repo.deactivate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
class CompareController < ApplicationController
|
||||
# skip_before_action :require_login
|
||||
before_action :load_repository
|
||||
|
||||
def index
|
||||
end
|
||||
|
||||
def show
|
||||
base_ref = Addressable::URI.unescape(params[:base])
|
||||
@ref = head_ref = Addressable::URI.unescape(params[:head]&.split('.json')[0])
|
||||
@compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base_ref, head_ref)
|
||||
|
||||
# render json: @compare_result
|
||||
end
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
module Ci::CloudAccountManageable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
end
|
||||
|
||||
def bind_account!
|
||||
# 1. 保存华为云服务器帐号
|
||||
create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num].strip).to_i, secret: Ci::CloudAccount.encrypted_secret(devops_params[:secret]))
|
||||
|
||||
cloud_account = Ci::CloudAccount.new(create_params)
|
||||
cloud_account.user = current_user
|
||||
cloud_account.save!
|
||||
|
||||
# 2. 生成oauth2应用程序的client_id和client_secrete
|
||||
gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline-#{SecureRandom.hex(8)}", redirect_uris: ["#{cloud_account.drone_url}/login"]})
|
||||
logger.info "######### gitea_oauth: #{gitea_oauth}"
|
||||
oauth = Oauth.new(client_id: gitea_oauth['client_id'],
|
||||
client_secret: gitea_oauth['client_secret'],
|
||||
redirect_uri: gitea_oauth['redirect_uris'],
|
||||
gitea_oauth_id: gitea_oauth['id'],
|
||||
user_id: current_user.id)
|
||||
oauth.save!
|
||||
|
||||
# 创建数据ci端数据库
|
||||
database_result = auto_create_database!(@connection, "#{current_user.login}_drone")
|
||||
logger.info "[CI::DbConnectable] auto_create_database's result: #{database_result}"
|
||||
|
||||
# 初始化表结构
|
||||
sub_connection = connect_to_ci_database
|
||||
auto_create_table_structure!(sub_connection)
|
||||
|
||||
rpc_secret = SecureRandom.hex 16
|
||||
logger.info "######### rpc_secret: #{rpc_secret}"
|
||||
|
||||
# 3. 创建drone server
|
||||
drone_server_cmd = Ci::Drone::Server.new(current_user.login, oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd
|
||||
logger.info "######### drone_server_cmd: #{drone_server_cmd}"
|
||||
|
||||
# 4. 创建drone client
|
||||
drone_client_cmd = Ci::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd
|
||||
logger.info "######### drone_client_cmd: #{drone_client_cmd}"
|
||||
|
||||
# 5. 登录远程服务器,启动drone服务
|
||||
result = Ci::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run
|
||||
logger.info "######### result: #{result}"
|
||||
|
||||
|
||||
redirect_url = "#{cloud_account.drone_url}/login"
|
||||
logger.info "######### redirect_url: #{redirect_url}"
|
||||
|
||||
return nil unless result.present?
|
||||
result && !result.blank? ? cloud_account : nil
|
||||
end
|
||||
|
||||
def unbind_account!
|
||||
cloud_account = current_user.ci_cloud_account
|
||||
return render_error('你未绑定CI服务器') if current_user.devops_step == User::DEVOPS_UNINIT || cloud_account.blank?
|
||||
|
||||
cloud_account.destroy! unless cloud_account.blank?
|
||||
@connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database
|
||||
|
||||
current_user.unbind_account!
|
||||
end
|
||||
|
||||
def bind_hook!(user, cloud_account, repo)
|
||||
hook_params = {
|
||||
active: true,
|
||||
config: {
|
||||
content_type: "json",
|
||||
url: cloud_account.drone_url + "/hook?secret=#{repo.repo_signer}"
|
||||
},
|
||||
type: "gitea"
|
||||
}
|
||||
result = Gitea::Hooks::CreateService.call(user.gitea_token, user.login, repo.repo_name, hook_params)
|
||||
|
||||
result[:status].present? ? nil : result
|
||||
end
|
||||
|
||||
def check_bind_cloud_account!
|
||||
return [true, "你已经绑定了云帐号."] unless current_user.ci_cloud_account.blank?
|
||||
|
||||
ip_num = IPAddr.new(devops_params[:ip_num]).to_i
|
||||
Ci::CloudAccount.exists?(ip_num: ip_num) ? [true, "#{devops_params[:ip_num]}服务器已被使用."] : [false, nil]
|
||||
end
|
||||
|
||||
def gitea_auto_create_auth_grant!(gitea_oauth_id)
|
||||
connection = Gitea::Database.set_connection.connection
|
||||
unix_time = Time.now.to_i
|
||||
|
||||
# 目前直接操作db,可以建立对应的model进行操作
|
||||
sql = "INSERT INTO oauth2_grant ( user_id, application_id, counter, created_unix, updated_unix ) VALUES ( #{current_user.gitea_uid}, #{gitea_oauth_id}, 0, #{unix_time}, #{unix_time} );"
|
||||
connection.execute(sql)
|
||||
end
|
||||
|
||||
def gitea_oauth_grant!(password, oauth)
|
||||
gitea_auto_create_auth_grant!(oauth&.gitea_oauth_id)
|
||||
|
||||
state = SecureRandom.hex(8)
|
||||
|
||||
# redirect_uri eg:
|
||||
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
||||
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
||||
grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{oauth&.client_id}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
|
||||
logger.info "[gitea] grant_url: #{grant_url}"
|
||||
|
||||
conn = Faraday.new(url: grant_url) do |req|
|
||||
req.request :url_encoded
|
||||
req.adapter Faraday.default_adapter
|
||||
req.basic_auth(current_user.login, password)
|
||||
end
|
||||
|
||||
response = conn.get
|
||||
logger.info "[gitea] response headers: #{response.headers}"
|
||||
|
||||
drone_oauth_user!(response.headers.to_h['location'], state)
|
||||
end
|
||||
|
||||
def drone_oauth_user!(url, state)
|
||||
logger.info "[drone] drone_oauth_user url: #{url}"
|
||||
conn = Faraday.new(url: url) do |req|
|
||||
req.request :url_encoded
|
||||
req.adapter Faraday.default_adapter
|
||||
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
||||
end
|
||||
|
||||
response = conn.get
|
||||
logger.info "[drone] response headers: #{response.headers}"
|
||||
|
||||
response.headers['location'].include?('error') ? false : true
|
||||
end
|
||||
|
||||
private
|
||||
def devops_params
|
||||
params.permit(:account, :secret, :ip_num)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
module Ci::DbConnectable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
end
|
||||
|
||||
# Dynamically sets the database connection.
|
||||
def connect_to_ci_database(options={})
|
||||
master_db = options[:master_db] || false
|
||||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
db_config = config[:ci_db_server].symbolize_keys!
|
||||
raise 'ci database config missing' if db_config.blank?
|
||||
|
||||
req_params = {
|
||||
host: db_config[:host],
|
||||
username: db_config[:username],
|
||||
password: db_config[:password],
|
||||
port: db_config[:port]
|
||||
}
|
||||
req_params = req_params.merge(database: "#{current_user.login}_#{db_config[:database]}") unless master_db === true
|
||||
|
||||
db_params = Ci::Database.get_connection_params(req_params)
|
||||
@connection = Ci::Database.set_connection(db_params).connection
|
||||
end
|
||||
|
||||
def auto_create_database!(connection, database)
|
||||
Rails.logger.info "[CI::DbConnectable] auto_create_database's connection: #{connection}"
|
||||
connection.execute("CREATE DATABASE IF NOT EXISTS #{database}")
|
||||
end
|
||||
|
||||
def auto_create_table_structure!(connection)
|
||||
Rails.logger.info "[CI::DbConnectable] auto_create_table_structure's connection: #{connection}"
|
||||
|
||||
sqls = Ci::Schema.statement.split(';').map(&:strip).reject { |e| e.to_s.empty? }
|
||||
sqls.each do |sql|
|
||||
con_result = connection.execute(sql)
|
||||
Rails.logger.info "=============> ci create tabels result: #{con_result}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -17,7 +17,7 @@ module LoginHelper
|
|||
:expires => 1.month.from_now,
|
||||
:path => '/',
|
||||
:secure => false,
|
||||
:httponly => false
|
||||
:httponly => true
|
||||
}
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||
|
@ -51,11 +51,16 @@ module LoginHelper
|
|||
Rails.logger.info("####################__User.current_id______######{current_user.try(:id)}###___#{current_user&.logged?}")
|
||||
|
||||
if User.current.logged?
|
||||
if autologin = cookies.delete(autologin_cookie_name)
|
||||
user = User.current
|
||||
autologin =
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookies.delete(autologin_cookie_name, domain: edu_setting('cookie_domain'))
|
||||
else
|
||||
cookies.delete(autologin_cookie_name)
|
||||
end
|
||||
|
||||
User.current.delete_autologin_token(autologin)
|
||||
end
|
||||
User.current.delete_session_token(session[:tk])
|
||||
user.delete_autologin_token(autologin)
|
||||
user.delete_session_token(session[:tk])
|
||||
self.logged_user = nil
|
||||
end
|
||||
|
||||
|
@ -68,7 +73,7 @@ module LoginHelper
|
|||
|
||||
# Sets the logged in user
|
||||
def logged_user=(user)
|
||||
# reset_session
|
||||
reset_session
|
||||
if user && user.is_a?(User)
|
||||
Rails.logger.info("########________logged_user___________###########{user.id}")
|
||||
|
||||
|
@ -111,4 +116,34 @@ module LoginHelper
|
|||
false
|
||||
end
|
||||
end
|
||||
|
||||
# TODO 同步token到trustie平台,保持同步登录状态
|
||||
def sync_user_token_to_trustie(login, token_value)
|
||||
|
||||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
|
||||
token = config[:sync_token]
|
||||
api_host = config[:sync_url]
|
||||
|
||||
return if api_host.blank?
|
||||
|
||||
url = "#{api_host}/api/v1/users/sync_user_token"
|
||||
sync_json = {
|
||||
"token": token,
|
||||
"login": login,
|
||||
"user_token": token_value
|
||||
}
|
||||
uri = URI.parse(url)
|
||||
|
||||
if api_host
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
|
||||
if api_host.include?("https://")
|
||||
http.use_ssl = true
|
||||
end
|
||||
|
||||
http.send_request('POST', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module RegisterHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def autologin_register(username, email, password, platform= '')
|
||||
def autologin_register(username, email, password, platform= 'forge')
|
||||
result = {message: nil, user: nil}
|
||||
email ||= "#{username@example.org}"
|
||||
|
||||
|
|
|
@ -4,18 +4,18 @@ class HooksController < ApplicationController
|
|||
before_action :check_user
|
||||
before_action :set_repository
|
||||
|
||||
def index
|
||||
hooks_response = Gitea::Hooks::ListService.new(@user, @repository.try(:identifier)).call
|
||||
if hooks_response.status == 200
|
||||
def index
|
||||
hooks_response = Gitea::Hooks::ListService.new(@user.gitea_token, @user.login, @repository.try(:identifier)).call
|
||||
if hooks_response.status == 200
|
||||
lists = JSON.parse(hooks_response.body)
|
||||
@hooks_size = lists.size
|
||||
@hooks = paginate(lists)
|
||||
else
|
||||
else
|
||||
normal_status(-1, "出现错误")
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
def create
|
||||
#根据gitea的api
|
||||
# hook_params = {
|
||||
# active: true,
|
||||
|
@ -36,17 +36,17 @@ class HooksController < ApplicationController
|
|||
# content_type: params[:content_type].to_i,
|
||||
# secret: params[:secret],
|
||||
# events: {
|
||||
# push_only: params[:push_only] || false, # 是否为推送事件
|
||||
# send_everything: params[:send_everything] || false, #是否为所有事件
|
||||
# push_only: params[:push_only] || false, # 是否为推送事件
|
||||
# send_everything: params[:send_everything] || false, #是否为所有事件
|
||||
# choose_events: params[:choose_events] || false, #是否为自定义事件
|
||||
# branch_filter: params[:branch_filter] || "*",
|
||||
# events: {
|
||||
# create: params[:create] || false, #创建分支/标签
|
||||
# delete: params[:delete] || false, #删除分支/标签
|
||||
# fork: params[:fork] || false, #仓库被派生
|
||||
# delete: params[:delete] || false, #删除分支/标签
|
||||
# fork: params[:fork] || false, #仓库被派生
|
||||
# issues: params[:issues] || false, #工单
|
||||
# issue_comment: params[:issue_comment] || false, #评论
|
||||
# push: params[:push] || false # 推送
|
||||
# issue_comment: params[:issue_comment] || false, #评论
|
||||
# push: params[:push] || false # 推送
|
||||
# pull_request: params[:pull_request] || false #合并请求
|
||||
# repository: params[:repository] || false #仓库
|
||||
# release: params[:release] || false #版本发布
|
||||
|
@ -58,28 +58,28 @@ class HooksController < ApplicationController
|
|||
Gitea::Hooks::CreateService.new(@user, @repository.try(:identifier), hook_params).call #创建gitea的hook功能
|
||||
Gitea::Hooks::CreateService.new(user, p.try(:identifier), hook_params).call #创建gitea的hook功能
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
def update
|
||||
hook_params = params[:hook_params]
|
||||
response = Gitea::Hooks::UpdateService.new(@user, @repository.try(:identifier), hook_params, params[:id]).call
|
||||
if response.status == 200
|
||||
if response.status == 200
|
||||
normal_status(1, "更新成功")
|
||||
else
|
||||
else
|
||||
normal_status(-1, "更新失败")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
def destroy
|
||||
response = Gitea::Hooks::DestroyService.new(@user, @repository.try(:identifier), params[:id]).call
|
||||
if response.status == 204
|
||||
normal_status(1, "删除成功")
|
||||
else
|
||||
else
|
||||
normal_status(-1, "删除失败")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def set_repository
|
||||
@repository = @project.repository
|
||||
|
@ -88,9 +88,9 @@ class HooksController < ApplicationController
|
|||
normal_status(-1, "用户不存在") unless @user.present?
|
||||
end
|
||||
|
||||
def check_user
|
||||
unless @project.user_id == current_user.id
|
||||
tip_exception(403, "您没有权限进入")
|
||||
def check_user
|
||||
unless @project.user_id == current_user.id
|
||||
tip_exception(403, "您没有权限进入")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,9 +105,6 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "标题不能为空")
|
||||
elsif params[:subject].to_s.size > 255
|
||||
normal_status(-1, "标题不能超过255个字符")
|
||||
elsif (params[:issue_type].to_s == "2")
|
||||
return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0
|
||||
|
||||
else
|
||||
issue_params = issue_send_params(params)
|
||||
|
||||
|
@ -137,17 +134,16 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
# normal_status(0, "创建成功",)
|
||||
render :json => { status: 0, message: "创建成功", id: @issue.id}
|
||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||
else
|
||||
normal_status(-1, @issue.errors.messages.values[0][0])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def edit
|
||||
# @all_branches = get_branches
|
||||
# @issue_chosen = issue_left_chosen(@project, @issue.id)
|
||||
@issue_attachments = @issue.attachments
|
||||
end
|
||||
|
@ -204,7 +200,6 @@ class IssuesController < ApplicationController
|
|||
else
|
||||
normal_status(-1, @issue.errors.messages.values[0][0])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -306,6 +301,9 @@ class IssuesController < ApplicationController
|
|||
if type == 5
|
||||
@issue&.project_trends&.update_all(action_type: "close")
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
if @issue.issue_type.to_s == "2"
|
||||
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
||||
end
|
||||
if @issue.issue_classify.to_s == "pull_request"
|
||||
@issue&.pull_request&.update_attribute(:status, 2)
|
||||
end
|
||||
|
@ -399,17 +397,6 @@ class IssuesController < ApplicationController
|
|||
tracker_array
|
||||
end
|
||||
|
||||
def get_branches
|
||||
all_branches = []
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @project&.repository.try(:identifier)).call
|
||||
if get_all_branches && get_all_branches.size > 0
|
||||
get_all_branches.each do |b|
|
||||
all_branches.push(b["name"])
|
||||
end
|
||||
end
|
||||
all_branches
|
||||
end
|
||||
|
||||
def issue_send_params(params)
|
||||
{
|
||||
subject: params[:subject],
|
||||
|
|
|
@ -2,7 +2,7 @@ class MainController < ApplicationController
|
|||
protect_from_forgery except: :index
|
||||
skip_before_action :check_sign
|
||||
skip_before_action :user_setup
|
||||
# skip_before_action :setup_laboratory
|
||||
skip_before_action :setup_laboratory
|
||||
|
||||
def first_stamp
|
||||
render :json => { status: 0, message: Time.now.to_i }
|
||||
|
|
|
@ -7,7 +7,7 @@ class Oauth::EducoderController < Oauth::BaseController
|
|||
token = params[:token]
|
||||
|
||||
::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate!
|
||||
|
||||
|
||||
open_user= OpenUsers::Educoder.find_by(uid: login)
|
||||
|
||||
if open_user.present? && open_user.user.present? && open_user.user.email_binded?
|
||||
|
@ -17,15 +17,15 @@ class Oauth::EducoderController < Oauth::BaseController
|
|||
redirect_to callback_url
|
||||
else
|
||||
Rails.logger.info "######## open user not exits"
|
||||
user = User.find_by('login = ? or mail = ?', login, mail)
|
||||
user = User.find_by(login: login) || User.find_by(mail: mail)
|
||||
|
||||
if user.is_a?(User)
|
||||
if user.is_a?(User) && !user.is_a?(AnonymousUser)
|
||||
OpenUsers::Educoder.create!(user: user, uid: login)
|
||||
successful_authentication(user)
|
||||
|
||||
redirect_to callback_url
|
||||
else
|
||||
redirect_to oauth_register_path(login: login, callback_url: callback_url)
|
||||
redirect_to oauth_register_path(login: login, mail: mail, callback_url: callback_url)
|
||||
end
|
||||
end
|
||||
rescue WechatOauth::Error => ex
|
||||
|
|
|
@ -40,8 +40,5 @@ class PraiseTreadController < ApplicationController
|
|||
end
|
||||
|
||||
private
|
||||
def render_result
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -6,16 +6,6 @@ class ProjectCategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def group_list
|
||||
# if current_user&.logged?
|
||||
# projects = Project.list_user_projects(current_user.id)
|
||||
# else
|
||||
# projects = Project.visible
|
||||
# end
|
||||
@project_children_categories = ProjectCategory.descendants
|
||||
projects = Project.no_anomory_projects.visible
|
||||
categories = projects.joins(:project_category).where(project_categories: {ancestry: nil}).group("project_categories.name", "project_categories.id").size.keys.to_h
|
||||
extra_category_id = categories.delete("其他")
|
||||
categories = categories.merge({"其他": extra_category_id}) if extra_category_id.present? #其他的放在最后面
|
||||
@category_group_list = categories
|
||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,16 +2,26 @@ class ProjectsController < ApplicationController
|
|||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include ProjectsHelper
|
||||
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users]
|
||||
before_action :load_project, except: %i[index group_type_list migrate create]
|
||||
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about]
|
||||
before_action :load_project, except: %i[index group_type_list migrate create recommend]
|
||||
before_action :authorizate_user_can_edit_project!, only: %i[update]
|
||||
before_action :project_public?, only: %i[fork_users praise_users watch_users]
|
||||
|
||||
def index
|
||||
scope = Projects::ListQuery.call(params)
|
||||
|
||||
@projects = kaminari_paginate(scope)
|
||||
@total_count = @projects.total_count
|
||||
# @projects = kaminari_paginate(scope)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, owner: :user_extension)
|
||||
|
||||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
if category_id.blank?
|
||||
ps = ProjectStatistic.first
|
||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
else
|
||||
cate = ProjectCategory.find_by(id: category_id)
|
||||
cate&.projects_count || 0
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -34,7 +44,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def branches
|
||||
@branches = Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call
|
||||
@branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : []
|
||||
end
|
||||
|
||||
def group_type_list
|
||||
|
@ -52,9 +62,13 @@ class ProjectsController < ApplicationController
|
|||
ActiveRecord::Base.transaction do
|
||||
# Projects::CreateForm.new(project_params).validate!
|
||||
private = params[:private]
|
||||
gitea_params = {
|
||||
private: private,
|
||||
default_branch: params[:default_branch]
|
||||
}
|
||||
if [true, false].include? private
|
||||
new_project_params = project_params.merge(is_public: !private)
|
||||
Gitea::Repository::UpdateService.new(@project.owner, @project.repository.identifier, {private: private}).call
|
||||
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
|
||||
@project.repository.update_column(:hidden, private)
|
||||
end
|
||||
@project.update_attributes!(new_project_params)
|
||||
|
@ -95,13 +109,44 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def fork_users
|
||||
fork_users = @project.fork_users.includes(:user, :project).order("fork_users.created_at desc").distinct
|
||||
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
@forks_count = fork_users.size
|
||||
@fork_users = paginate(fork_users)
|
||||
end
|
||||
|
||||
def simple
|
||||
json_response(@project)
|
||||
json_response(@project, current_user)
|
||||
end
|
||||
|
||||
def recommend
|
||||
@projects = Project.recommend.includes(:repository, :project_category, owner: :user_extension).limit(5)
|
||||
end
|
||||
|
||||
def about
|
||||
@project_detail = @project.project_detail
|
||||
@attachments = Array(@project_detail&.attachments) if request.get?
|
||||
ActiveRecord::Base.transaction do
|
||||
if request.post?
|
||||
require_login
|
||||
authorizate_user_can_edit_project!
|
||||
unless @project_detail.present?
|
||||
@project_detail = ProjectDetail.new(
|
||||
content: params[:content],
|
||||
project_id: @project.id)
|
||||
else
|
||||
@project_detail.content = params[:content]
|
||||
end
|
||||
if @project_detail.save!
|
||||
attachment_ids = Array(params[:attachment_ids])
|
||||
@attachments = Attachment.where(id: attachment_ids)
|
||||
@attachments.update_all(
|
||||
container_id: @project_detail.id,
|
||||
container_type: @project_detail.model_name.name,
|
||||
author_id: current_user.id,
|
||||
description: "")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -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 = @repository.protected_branches
|
||||
@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
|
|
@ -1,9 +1,8 @@
|
|||
class PullRequestsController < ApplicationController
|
||||
before_action :require_login, except: [:index, :show]
|
||||
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||
before_action :load_repository
|
||||
before_action :set_user, only: [:new, :get_branches]
|
||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos]
|
||||
# before_action :get_relatived, only: [:edit]
|
||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||
before_action :load_pull_request, only: [:files, :commits]
|
||||
include TagChosenHelper
|
||||
include ApplicationHelper
|
||||
|
||||
|
@ -24,11 +23,11 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@all_branches = PullRequests::BranchesService.new(@user, @project).call
|
||||
@all_branches = Branches::ListService.call(@owner, @project)
|
||||
@is_fork = @project.forked_from_project_id.present?
|
||||
@projects_names = [{
|
||||
project_user_login: @user.try(:login),
|
||||
project_name: "#{@user.try(:show_real_name)}/#{@repository.try(:identifier)}",
|
||||
project_user_login: @owner.try(:login),
|
||||
project_name: "#{@owner.try(:show_real_name)}/#{@repository.try(:identifier)}",
|
||||
project_id: @project.identifier,
|
||||
id: @project.id
|
||||
}]
|
||||
|
@ -45,66 +44,20 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def get_branches
|
||||
branch_result = PullRequests::BranchesService.new(@user, @project).call
|
||||
branch_result = Branches::ListService.call(@owner, @project)
|
||||
render json: branch_result
|
||||
# return json: branch_result
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:title].nil?
|
||||
normal_status(-1, "名称不能为空")
|
||||
elsif params[:issue_tag_ids].nil?
|
||||
normal_status(-1, "标签不能为空")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
merge_params
|
||||
pull_issue = Issue.new(@issue_params)
|
||||
if pull_issue.save!
|
||||
pr_params = {
|
||||
user_id: current_user.try(:id),
|
||||
project_id: @project.id,
|
||||
issue_id: pull_issue.id,
|
||||
fork_project_id: params[:fork_project_id],
|
||||
is_original: params[:is_original]
|
||||
}
|
||||
local_requests = PullRequest.new(@local_params.merge(pr_params))
|
||||
if local_requests.save
|
||||
remote_pr_params = @local_params
|
||||
remote_pr_params = remote_pr_params.merge(head: "#{params[:merge_user_login]}:#{params[:head]}").compact if local_requests.is_original && params[:merge_user_login]
|
||||
gitea_request = Gitea::PullRequest::CreateService.call(current_user.try(:gitea_token), @project.owner, @repository.try(:identifier), remote_pr_params.except(:milestone))
|
||||
if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"])
|
||||
if params[:issue_tag_ids].present?
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag)
|
||||
end
|
||||
end
|
||||
|
||||
if params[:assigned_to_id].present?
|
||||
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
|
||||
container_id: local_requests.id, container_type: 'PullRequest',
|
||||
parent_container_id: @project.id, parent_container_type: "Project",
|
||||
tiding_type: 'pull_request', status: 0)
|
||||
end
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
if params[:title].to_s.include?("WIP:")
|
||||
pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。", current_user&.id)
|
||||
end
|
||||
# render :json => { status: 0, message: "PullRequest创建成功", id: pull_issue.id}
|
||||
normal_status(0, "PullRequest创建成功")
|
||||
else
|
||||
normal_status(-1, "PullRequest创建失败")
|
||||
end
|
||||
else
|
||||
normal_status(-1, local_requests.errors.messages.values[0][0])
|
||||
end
|
||||
else
|
||||
normal_status(-1, pull_issue.errors.messages.values[0][0])
|
||||
end
|
||||
rescue => e
|
||||
normal_status(-1, e.message)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
ActiveRecord::Base.transaction do
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
if @gitea_pull_request[:status] == :success
|
||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"])
|
||||
render_ok
|
||||
else
|
||||
render_error("create pull request error: #{@gitea_pull_request[:status]}")
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -226,11 +179,11 @@ class PullRequestsController < ApplicationController
|
|||
elsif target_head === target_base && !is_original
|
||||
normal_status(-2, "分支内容相同,无需创建合并请求")
|
||||
else
|
||||
can_merge = @project&.pull_requests.where(user_id: current_user&.id, head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id])
|
||||
can_merge = @project&.pull_requests.where(head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id])
|
||||
if can_merge.present?
|
||||
render json: {
|
||||
status: -2,
|
||||
message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@project.id}/merge/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>",
|
||||
message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>",
|
||||
}
|
||||
else
|
||||
normal_status(0, "可以合并")
|
||||
|
@ -239,9 +192,19 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
|
||||
def files
|
||||
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid)
|
||||
# render json: @files_result
|
||||
end
|
||||
|
||||
def commits
|
||||
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid)
|
||||
# render json: @commits_result
|
||||
end
|
||||
|
||||
private
|
||||
def set_user
|
||||
@user = @project.owner
|
||||
def load_pull_request
|
||||
@pull_request = PullRequest.find params[:id]
|
||||
end
|
||||
|
||||
def find_pull_request
|
||||
|
|
|
@ -13,7 +13,7 @@ class RepositoriesController < ApplicationController
|
|||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
@result = Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
|
@ -26,60 +26,85 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
@project_owner = @project.owner
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@project_owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
def top_counts
|
||||
@result = Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
@sub_entries = interactor.result
|
||||
@sub_entries = [] << @sub_entries unless @sub_entries.is_a? Array
|
||||
@sub_entries = @sub_entries.sort_by{ |hash| hash['type'] }
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = [{
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}]
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
end
|
||||
else
|
||||
render_error(interactor.error)
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits
|
||||
@project_owner = @project.owner
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@project_owner.login, @project.identifier,
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
end
|
||||
|
||||
def commit
|
||||
@commit = Gitea::Repository::Commits::GetService.new(@repository.user.login, @repository.identifier, params[:sha], current_user.gitea_token).call
|
||||
@sha = params[:sha]
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
end
|
||||
|
||||
def tags
|
||||
@tags = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}).call
|
||||
@tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def create_file
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @project.owner.login, content_params)
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
create_new_pr(params)
|
||||
# create_new_pr(params)
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def update_file
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier))
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
create_new_pr(params)
|
||||
# TODO: 是否创建pr
|
||||
# create_new_pr(params)
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
|
@ -87,7 +112,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def delete_file
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier))
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "文件删除成功")
|
||||
|
@ -133,8 +158,8 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
|
@ -142,9 +167,9 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def get_latest_commit
|
||||
latest_commit = project_commits
|
||||
@latest_commit = latest_commit[:body][0] if latest_commit.present?
|
||||
@commits_count = latest_commit[:total_count] if latest_commit.present?
|
||||
latest_commit = @project.educoder? ? nil : project_commits
|
||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||
end
|
||||
|
||||
def content_params
|
||||
|
@ -154,6 +179,10 @@ class RepositoriesController < ApplicationController
|
|||
new_branch: params[:new_branch],
|
||||
content: params[:content],
|
||||
message: params[:message],
|
||||
committer: {
|
||||
email: current_user.mail,
|
||||
name: current_user.login
|
||||
},
|
||||
identifier: @project.identifier
|
||||
}
|
||||
end
|
||||
|
@ -208,14 +237,14 @@ class RepositoriesController < ApplicationController
|
|||
issue_type: "1",
|
||||
tracker_id: 2,
|
||||
status_id: 1,
|
||||
priority_id: 1
|
||||
priority_id: params[:priority_id] || "2"
|
||||
}
|
||||
@pull_issue = Issue.new(issue_params)
|
||||
if @pull_issue.save!
|
||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @project.owner, @project.try(:identifier), requests_params).call
|
||||
if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"])
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
class UsersController < ApplicationController
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users]
|
||||
before_action :require_login, only: %i[me list]
|
||||
before_action :connect_to_ci_database, only: :get_user_info, if: -> { current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification? }
|
||||
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
||||
def list
|
||||
|
|
|
@ -139,7 +139,7 @@ class VersionReleasesController < ApplicationController
|
|||
body: params[:body],
|
||||
draft: params[:draft] || false,
|
||||
name: params[:name],
|
||||
prerelease: params[:prerelease],
|
||||
prerelease: params[:prerelease] || false,
|
||||
tag_name: params[:tag_name],
|
||||
target_commitish: params[:target_commitish] || "master" #分支
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
class Ci::CreateCloudAccountForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :ip_num, :account, :secret
|
||||
|
||||
# validates :project_id, :account, :secret, presence: true
|
||||
validates :account, :secret, presence: true
|
||||
validates :ip_num, presence: true, format: { with: CustomRegexp::IP, multiline: true, message: 'IP 地址格式不对' }
|
||||
|
||||
end
|
|
@ -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
|
|
@ -436,4 +436,9 @@ module ApplicationHelper
|
|||
def find_user_by_login(login)
|
||||
User.find_by_login login
|
||||
end
|
||||
|
||||
def render_base64_decoded(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64 str
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
module Ci::BuildsHelper
|
||||
def format_utc_time(unix_time)
|
||||
return nil if unix_time == 0
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
def render_duartion_time(end_time, start_time)
|
||||
return nil if end_time == 0 || start_time == 0
|
||||
game_spend_time(end_time - start_time)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module Ci::LanguagesHelper
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module CompareHelper
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module DevOpsHelper
|
||||
end
|
|
@ -1,2 +1,18 @@
|
|||
module MembersHelper
|
||||
def get_user_token(user_login,reponame)
|
||||
query_params = {
|
||||
type: "query",
|
||||
chain_params: {
|
||||
reponame: reponame,
|
||||
username: user_login
|
||||
}
|
||||
}
|
||||
response = Gitea::Chain::ChainGetService.new(query_params).call
|
||||
|
||||
if response.status == 200
|
||||
return JSON.parse(response.body)["balance"].to_i
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,8 +28,10 @@ module ProjectsHelper
|
|||
(User.find_by_login identifier) || (User.find_by_mail identifier)
|
||||
end
|
||||
|
||||
def json_response(project)
|
||||
repo = project.repository
|
||||
def json_response(project, user)
|
||||
# repo = project.repository
|
||||
repo = Repository.includes(:mirror).select(:id, :mirror_url).find_by(project: project)
|
||||
|
||||
tmp_json = {}
|
||||
unless project.common?
|
||||
tmp_json = tmp_json.merge({
|
||||
|
@ -41,16 +43,48 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
tmp_json = tmp_json.merge({
|
||||
identifier: project.identifier,
|
||||
identifier: render_identifier(project),
|
||||
name: project.name,
|
||||
platform: project.platform,
|
||||
id: project.id,
|
||||
repo_id: repo.id,
|
||||
open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?,
|
||||
type: project.numerical_for_project_type,
|
||||
author: {
|
||||
login: project.owner.login,
|
||||
name: project.owner.real_name,
|
||||
image_url: url_to_avatar(project.owner)
|
||||
}
|
||||
author: render_owner(project)
|
||||
}).compact
|
||||
|
||||
render json: tmp_json
|
||||
end
|
||||
|
||||
def render_owner(project)
|
||||
if project.educoder?
|
||||
{
|
||||
login: project.project_educoder.owner,
|
||||
name: project.project_educoder.owner,
|
||||
image_url: project.project_educoder.image_url
|
||||
}
|
||||
else
|
||||
{
|
||||
login: @owner.login,
|
||||
name: @owner.real_name,
|
||||
image_url: url_to_avatar(@owner)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def render_identifier(project)
|
||||
project.educoder? ? project.project_educoder&.repo_name&.split('/')[1] : project.identifier
|
||||
end
|
||||
|
||||
def render_author(project)
|
||||
project.educoder? ? project.project_educoder&.repo_name&.split('/')[0] : project.owner.login
|
||||
end
|
||||
|
||||
def render_educoder_avatar_url(project_educoder)
|
||||
[Rails.application.config_for(:configuration)['educoder']['cdn_url'], project_educoder&.image_url].join('/')
|
||||
end
|
||||
|
||||
def render_avatar_url(owner)
|
||||
['images', url_to_avatar(owner)].join('/')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
module ProtectedBranchesHelper
|
||||
end
|
|
@ -1,11 +1,17 @@
|
|||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
return "Owner" if user === project.owner
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
def render_decode64_content(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64(str).force_encoding('UTF-8')
|
||||
Base64.decode64(str).force_encoding("UTF-8")
|
||||
end
|
||||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
|
@ -44,7 +50,7 @@ module RepositoriesHelper
|
|||
end
|
||||
if r_content.include?("?")
|
||||
new_r_content = r_content + "&raw=true"
|
||||
else
|
||||
else
|
||||
new_r_content = r_content + "?raw=true"
|
||||
end
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
|
@ -56,4 +62,14 @@ module RepositoriesHelper
|
|||
|
||||
return content
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
def render_format_time_with_unix(unix_time)
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
# date for example: 2020-11-01T19:57:27+08:00
|
||||
def render_format_time_with_date(date)
|
||||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,143 @@
|
|||
module TagChosenHelper
|
||||
def get_associated_data(project)
|
||||
issue_comment_users_array = []
|
||||
cost_time_array = []
|
||||
all_issues = []
|
||||
{
|
||||
"assign_user": render_cache_collaborators(project),
|
||||
"tracker": render_cache_trackers,
|
||||
"issue_status": render_cache_issue_statuses,
|
||||
"priority": render_cache_issue_priorities,
|
||||
"issue_version": render_cache_milestones(project),
|
||||
"start_date": "",
|
||||
"due_date": "",
|
||||
"joins_users": issue_comment_users_array,
|
||||
"cost_time_users": cost_time_array,
|
||||
# "total_cost_time": Time.at(all_cost_time).utc.strftime('%H h %M min %S s'),
|
||||
# "be_depended_issues": be_depended_issues_array,
|
||||
# "depended_issues":depended_issues_array,
|
||||
# "estimated_hours": issue_info[7],
|
||||
"done_ratio": render_complete_percentage,
|
||||
"issue_tag": render_issue_tags(project),
|
||||
"issue_type": render_issue_species,
|
||||
"all_issues": all_issues
|
||||
}
|
||||
end
|
||||
|
||||
def render_cache_trackers
|
||||
cache_key = "all_trackers/#{Tracker.maximum('id')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
Tracker.select(:id, :name, :position).collect do |event|
|
||||
{
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
position: event.position,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_issue_statuses
|
||||
cache_key = "all_issue_statuses/#{IssueStatus.maximum('id')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
IssueStatus.select(:id, :name, :position).collect do |event|
|
||||
{
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
position: event.position,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_issue_priorities
|
||||
cache_key = "all_issue_priorities/#{IssuePriority.maximum('id')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
IssuePriority.select(:id, :name, :position).collect do |event|
|
||||
{
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
position: event.position,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_complete_percentage
|
||||
completion_nums = %w(0 10 20 30 40 50 60 70 80 90 100)
|
||||
completion_nums.collect do |event|
|
||||
{
|
||||
id: event.to_i,
|
||||
name: event + "%",
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def render_issue_species
|
||||
species = %W(普通 悬赏)
|
||||
|
||||
species.collect do |event|
|
||||
{
|
||||
id: event.to_i + 1,
|
||||
token: nil,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def render_issue_tags(project)
|
||||
# project.issue_tags.last&.cache_key
|
||||
cache_key = "all_issue_tags/#{project.issue_tags.maximum('updated_at')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
project.issue_tags.select(:id, :name, :color).collect do |event|
|
||||
{
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
color: event.color,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_milestones(project)
|
||||
cache_key = "all_milestones/#{project.versions.maximum('updated_on')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
project.versions.select(:id, :name, :status).collect do |event|
|
||||
{
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
status: event.status,
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_collaborators(project)
|
||||
cache_key = "all_collaborators/#{project.members.maximum('created_on')}"
|
||||
|
||||
Rails.cache.fetch(cache_key) do
|
||||
project.members.includes(:user).collect do |event|
|
||||
{
|
||||
id: event.user&.id,
|
||||
name: event.user&.show_real_name,
|
||||
avatar_url: url_to_avatar(event.user),
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def issue_left_chosen(project,issue_id)
|
||||
issue_info = Array.new(11)
|
||||
|
@ -205,4 +344,4 @@ module TagChosenHelper
|
|||
# be_depended_issues_array
|
||||
# end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,8 @@ module Gitea
|
|||
attr_reader :error, :result
|
||||
|
||||
def initialize(token, owner, params)
|
||||
@owner = owner
|
||||
@token = token
|
||||
@owner = owner
|
||||
@params = params
|
||||
end
|
||||
|
||||
|
@ -58,6 +59,7 @@ module Gitea
|
|||
file_params = file_params.merge(new_branch: @params[:new_branch]) unless @params[:new_branch].blank?
|
||||
file_params = file_params.merge(content: Base64.encode64(@params[:content]))
|
||||
file_params = file_params.merge(message: @params[:message]) unless @params[:message].blank?
|
||||
file_params = file_params.merge(committer: @params[:committer])
|
||||
file_params
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ module Gitea
|
|||
|
||||
def run
|
||||
Gitea::UserForm.new(params).validate!
|
||||
response = Gitea::User::RegisterService.new(params).call
|
||||
response = Gitea::User::RegisterService.call(params.merge(token: token))
|
||||
render_result(response)
|
||||
rescue Exception => exception
|
||||
Rails.logger.info "Exception ===========> #{exception.message}"
|
||||
|
@ -41,5 +41,12 @@ module Gitea
|
|||
def render_result(response)
|
||||
@result = response
|
||||
end
|
||||
|
||||
def token
|
||||
{
|
||||
username: Gitea.gitea_config[:access_key_id],
|
||||
password: Gitea.gitea_config[:access_key_secret]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,24 @@
|
|||
class PostChainJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(chain_params)
|
||||
status = false
|
||||
chain_type = chain_params[:type].to_s
|
||||
reponame = chain_params[:chain_params][:reponame]
|
||||
5.times do |i|
|
||||
if status
|
||||
break
|
||||
else
|
||||
response = Gitea::Chain::ChainPostService.new(chain_params).call
|
||||
if response.status == 200
|
||||
reponse_body = response&.body
|
||||
messages = reponse_body.present? ? JSON.parse(reponse_body) : "success"
|
||||
status = true
|
||||
Rails.logger.info("################_repository__#{reponame}______create_chain_success_try:_#{i+1}_message__:#{messages}__")
|
||||
else
|
||||
Rails.logger.info("########_repository__#{reponame}______create_chain_failed__try:_#{i+1}_")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
class SyncEducoderShixunJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(url, private_token, page, per_page)
|
||||
uri = URI("#{url}?page=#{page}&per_page=#{per_page}&private_token=#{private_token}")
|
||||
puts "-------url: #{uri}"
|
||||
response = Net::HTTP.get_response(uri)
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
if result['status'] != 0
|
||||
puts "======= 接口请求失败!"
|
||||
return
|
||||
end
|
||||
|
||||
result['data']['repositories'].each do |re|
|
||||
next if re['repo_name'].blank?
|
||||
next if ProjectEducoder.exists?(repo_name: re['repo_name'])
|
||||
|
||||
language = ProjectLanguage.find_by_name re['language']
|
||||
language = ProjectLanguage.create!(name: re['language']) if language.blank?
|
||||
|
||||
category = ProjectCategory.find_by_name re['category']
|
||||
category = ProjectCategory.create!(name: re['category']) if category.blank?
|
||||
|
||||
project_params =
|
||||
{
|
||||
name: re['name'],
|
||||
# user_id: params[:user_id],
|
||||
description: re['description'],
|
||||
project_category_id: category.id,
|
||||
project_language_id: language.id,
|
||||
is_public: true,
|
||||
# ignore_id: params[:ignore_id],
|
||||
# license_id: params[:license_id],
|
||||
identifier: re['repo_name'],
|
||||
platform: Project.platforms[:educoder]
|
||||
}
|
||||
|
||||
project = Project.new(project_params)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
if project.save!
|
||||
repo_params =
|
||||
{
|
||||
hidden: false,
|
||||
project_id: project.id,
|
||||
identifier: re['repo_name']
|
||||
}
|
||||
|
||||
ProjectEducoder.create!(
|
||||
project_id: project.id,
|
||||
owner: re['username'],
|
||||
repo_name: re['repo_name'],
|
||||
forked_count: re['forked_count'],
|
||||
commit_count: re['commit_count'],
|
||||
image_url: re['image_url'])
|
||||
|
||||
repo = Repository.new(repo_params)
|
||||
repo.save!
|
||||
|
||||
puts "项目: #{re['name']} 同步成功"
|
||||
else
|
||||
puts "项目: #{re['name']} 同步失败"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -8,7 +8,7 @@ class SyncProjectsJob < ApplicationJob
|
|||
SyncLog.sync_log("==========begin to sync #{sync_params[:type]} to forge============")
|
||||
SyncLog.sync_log("==========sync_params:#{sync_params}============")
|
||||
|
||||
begin
|
||||
begin
|
||||
url = "#{gitea_main}/sync_forges" #trustie上的相关路由
|
||||
uri = URI.parse(url)
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
|
@ -85,7 +85,7 @@ class SyncProjectsJob < ApplicationJob
|
|||
new_target = target_type.constantize.new(re[:target_params].merge(user_id: u_id))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if !is_exists && new_target.save!
|
||||
SyncLog.sync_log("***【#{target_type}】. create_success---------------")
|
||||
if re[:journals].present?
|
||||
|
@ -112,10 +112,8 @@ class SyncProjectsJob < ApplicationJob
|
|||
SyncLog.sync_log("=========***【#{target_type}】creat_had_erros:#{e}===================")
|
||||
next
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def create_journals(target_jsons, target_type,issue_id)
|
||||
|
@ -127,7 +125,7 @@ class SyncProjectsJob < ApplicationJob
|
|||
if re[:target_params].present?
|
||||
u_id = User.select(:id, :login).where(login: re[:user_login]).pluck(:id).first
|
||||
is_exists = Journal.exists?(user_id: u_id, journalized_id: re[:target_params][:journalized_id], created_on: re[:target_params][:created_on].to_s.to_time)
|
||||
|
||||
|
||||
if is_exists
|
||||
SyncLog.sync_log("***00000. Journal:#{re[:target_params][:id]}-is exists--------------")
|
||||
else
|
||||
|
@ -142,7 +140,7 @@ class SyncProjectsJob < ApplicationJob
|
|||
end
|
||||
else
|
||||
SyncLog.sync_log("***111222. journal_create failed---------------")
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -181,4 +179,4 @@ class SyncProjectsJob < ApplicationJob
|
|||
SyncLog.sync_log("***111222. end_to_create_target---------------")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
module Ci
|
||||
class Database < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
|
||||
# Dynamically sets the database connection.
|
||||
def self.set_connection(params)
|
||||
puts "[Ci::Database] set db connection params: #{params}"
|
||||
establish_connection(
|
||||
adapter: params[:adapter],
|
||||
database: params[:database],
|
||||
port: params[:port].to_i,
|
||||
host: params[:host],
|
||||
username: params[:username],
|
||||
password: params[:password],
|
||||
encoding: "utf8"
|
||||
)
|
||||
end
|
||||
|
||||
def self.get_connection_params(connect_to)
|
||||
params = Hash.new
|
||||
params[:adapter] = "mysql2"
|
||||
params[:host] = connect_to[:host].to_s
|
||||
params[:username] = connect_to[:username].to_s
|
||||
params[:password] = connect_to[:password].to_s
|
||||
params[:database] = connect_to[:database].to_s
|
||||
params[:port] = connect_to[:port] || "43306"
|
||||
params[:encoding] = "utf8"
|
||||
return params
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
class Ci::Drone::API < Ci::Drone::Request
|
||||
attr_reader :drone_token, :endpoint, :owner, :repo, :options
|
||||
|
||||
# drone_token:
|
||||
# owner: repo's owner name or login
|
||||
# repo: repo's identifier
|
||||
def initialize(drone_token, endpoint, owner, repo, options={})
|
||||
@drone_token = drone_token
|
||||
@endpoint = endpoint
|
||||
@owner = owner
|
||||
@repo = repo
|
||||
@options = options
|
||||
end
|
||||
|
||||
# Build List
|
||||
# GET api/repos/{owner}/{name}/builds
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier)
|
||||
def builds
|
||||
get(endpoint, "api/repos/#{owner}/#{repo}/builds", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Build Info
|
||||
# GET api/repos/{owner}/{name}/builds/{number}
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier, number: number).build
|
||||
def build
|
||||
get(endpoint, "api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Update .trustie-pipeline.yml file
|
||||
# PATCH api/repos/{owner}/{name}\
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier, config_path: config_path).config_yml
|
||||
def config_yml
|
||||
patch(endpoint, "/api/repos/#{owner}/#{repo}", drone_token: drone_token, config_path: options[:config_path])
|
||||
end
|
||||
|
||||
# Activate user's project with Drone CI
|
||||
# POST api/repos/{owner}/{name}
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier).activate
|
||||
def activate
|
||||
post(endpoint, "/api/repos/#{owner}/#{repo}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Build Restart
|
||||
# POST api/repos/{owner}/{name}/builds/{number}
|
||||
# Restart the specified build. Please note this api requires read and write access to the repository and the request parameter {build} is not the build id but the build number.
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).restart
|
||||
def restart
|
||||
post(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Build Stop
|
||||
# DELETE api/repos/{owner}/{name}/builds/{number}
|
||||
# Stop the specified build. Please note this api requires administrative privileges and the request parameter {build} is not the build id but the build number.
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).stop
|
||||
def stop
|
||||
delete(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Build Logs
|
||||
# GET /api/repos/{owner}/{repo}/builds/{build}/logs/{stage}/{step}
|
||||
# Please note this api requires read access to the repository.
|
||||
# eq:
|
||||
# Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, build: build, stage: stage, step: step).logs
|
||||
def logs
|
||||
get(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:build]}/logs/#{options[:stage]}/#{options[:step]}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# Synchronize the currently authenticated user’s repository list.
|
||||
# POST /api/user/repos
|
||||
# eq:
|
||||
# Ci::Drone::API.new(drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).sync
|
||||
def sync_repos
|
||||
post(endpoint, "/api/users/repos", drone_token: drone_token)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
class Ci::Drone::Ci
|
||||
attr_reader :host, :username, :password, :gitea_username
|
||||
|
||||
# host: drone server's ip
|
||||
# username: drone server's account
|
||||
# password: drone server's password
|
||||
# eq:
|
||||
# DevOps::Drone::Ci.new(@cloud_account.drone_ip, @cloud_account.account, @cloud_account.visible_secret, current_user.login).get_token
|
||||
def initialize(host, username, password, gitea_username)
|
||||
@host = host
|
||||
@username = username
|
||||
@password = password
|
||||
@gitea_username = gitea_username
|
||||
end
|
||||
|
||||
def get_token
|
||||
puts "--------- sshpass -p #{password} ssh -o 'StrictHostKeyChecking no' #{username}@#{host} '#{cmd}'"
|
||||
`sshpass -p #{password} ssh -o "StrictHostKeyChecking no" #{username}@#{host} "#{cmd}"`
|
||||
end
|
||||
|
||||
private
|
||||
def cmd
|
||||
"cd ..; cd var/lib/drone/; sqlite3 database.sqlite; .dump; select user_hash from users where user_login=#{gitea_username};"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
class Ci::Drone::Client
|
||||
attr_reader :client_id, :drone_ip, :rpc_secret
|
||||
|
||||
# client_id: user's client_id from oauth
|
||||
# drone_ip: 云服务器IP地址, eq: 173.65.32.21
|
||||
# eq:
|
||||
# DevOps::Drone::Client.new(current_user.oauth.client_id, 'drone_ip').generate_cmd
|
||||
def initialize(client_id, drone_ip, rpc_secret)
|
||||
@client_id = client_id
|
||||
@drone_ip = drone_ip
|
||||
@rpc_secret = rpc_secret
|
||||
end
|
||||
|
||||
def generate_cmd
|
||||
"docker run -d \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_RPC_HOST=#{drone_ip}:80 \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_RUNNER_NAME=#{drone_ip} \
|
||||
--restart always \
|
||||
--name drone-agent--#{client_id} \
|
||||
--net='bridge' \
|
||||
drone/drone-runner-docker:1"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
class Ci::Drone::Error < StandardError
|
||||
attr_reader :code
|
||||
|
||||
def initialize(code, message)
|
||||
super message
|
||||
@code = code
|
||||
end
|
||||
|
||||
class << self
|
||||
def parse(result)
|
||||
new(result['errcode'], result['errmsg'])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,108 @@
|
|||
class Ci::Drone::Request
|
||||
# Converts the response body to an ObjectifiedHash.
|
||||
def self.parse(body)
|
||||
body = decode(body)
|
||||
|
||||
if body.is_a? Hash
|
||||
ObjectifiedHash.new body
|
||||
elsif body.is_a? Array
|
||||
body.collect! { |e| ObjectifiedHash.new(e) }
|
||||
elsif body == true
|
||||
body
|
||||
else
|
||||
raise Error::Parsing.new "Couldn't parse a response body"
|
||||
end
|
||||
end
|
||||
|
||||
# Decodes a JSON response into Ruby object.
|
||||
def self.decode(response)
|
||||
begin
|
||||
JSON.load response
|
||||
rescue JSON::ParserError
|
||||
raise Error::Parsing.new "The response is not a valid JSON"
|
||||
end
|
||||
end
|
||||
|
||||
def get(endpoint, path, options={})
|
||||
validate_request_params!(endpoint)
|
||||
request(:get, endpoint, path, options)
|
||||
end
|
||||
|
||||
def post(endpoint, path, options={})
|
||||
validate_request_params!(endpoint)
|
||||
request(:post, endpoint, path, options)
|
||||
end
|
||||
|
||||
def put(endpoint, path, options={})
|
||||
validate_request_params!(endpoint)
|
||||
request(:put, endpoint, path, options)
|
||||
end
|
||||
|
||||
def patch(endpoint, path, options={})
|
||||
validate_request_params!(endpoint)
|
||||
request(:patch, endpoint, path, options)
|
||||
end
|
||||
|
||||
def delete(endpoint, path, options={})
|
||||
validate_request_params!(endpoint)
|
||||
request(:delete, endpoint, path, options)
|
||||
end
|
||||
|
||||
private
|
||||
def request(method, endpoint, path, **params)
|
||||
Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:drone_token).inspect}")
|
||||
|
||||
client ||= begin
|
||||
Faraday.new(url: endpoint) do |req|
|
||||
req.request :url_encoded
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.response :logger # 显示日志
|
||||
req.adapter Faraday.default_adapter
|
||||
req.authorization :Bearer, params[:drone_token]
|
||||
req.headers['Authorization']
|
||||
end
|
||||
end
|
||||
response = client.public_send(method, path) do |req|
|
||||
req.body = params.except(:drone_token).to_json
|
||||
end
|
||||
|
||||
json_response(response)
|
||||
end
|
||||
|
||||
# Checks the response code for common errors.
|
||||
# Returns parsed response for successful requests.
|
||||
def validate(response)
|
||||
# case response.code
|
||||
# when 400; raise Error::BadRequest.new error_message(response)
|
||||
# when 401; raise Error::Unauthorized.new error_message(response)
|
||||
# when 403; raise Error::Forbidden.new error_message(response)
|
||||
# when 404; raise Error::NotFound.new error_message(response)
|
||||
# when 405; raise Error::MethodNotAllowed.new error_message(response)
|
||||
# when 406; raise Error::DataNotAccepted.new error_message(response)
|
||||
# when 409; raise Error::Conflict.new error_message(response)
|
||||
# when 500; raise Error::InternalServerError.new error_message(response)
|
||||
# when 502; raise Error::BadGateway.new error_message(response)
|
||||
# when 503; raise Error::ServiceUnavailable.new error_message(response)
|
||||
# end
|
||||
|
||||
response.parsed_response
|
||||
end
|
||||
|
||||
# Checks a base_uri and params for requests.
|
||||
def validate_request_params!(endpoint)
|
||||
raise "Please set an endpoint to API" unless endpoint
|
||||
end
|
||||
|
||||
def error_message(response)
|
||||
"Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \
|
||||
"Request URI: #{response.request.base_uri}#{response.request.path}"
|
||||
end
|
||||
|
||||
def json_response(response)
|
||||
result = JSON.parse(response.body)
|
||||
status = response.status
|
||||
Rails.logger.info("[drone] response:#{status} #{result.inspect}")
|
||||
|
||||
response.status != 200 ? result.merge!(status: response.status) : result
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
class Ci::Drone::Server
|
||||
attr_reader :user_login, :client_id, :client_secret, :drone_host, :rpc_secret
|
||||
|
||||
# client_id: user's client_id from oauth
|
||||
# client_secret: user's client_id from oauth
|
||||
# drone_host: 云服务器地址,eq: 173.53.21.31:80
|
||||
# eg:
|
||||
# DevOps::Drone::Server.new(current_user.login, current_user.oauth.client_id, current_user.oauth.client_secret, 'drone_host').generate_cmd
|
||||
def initialize(user_login, client_id, client_secret, drone_host, rpc_secret)
|
||||
@user_login = user_login
|
||||
@client_id = client_id
|
||||
@drone_host = drone_host
|
||||
@rpc_secret = rpc_secret
|
||||
@client_secret = client_secret
|
||||
end
|
||||
|
||||
# TODO 一下代码方便测试,正式环境请移除
|
||||
# docker rm -f `docker ps -qa`
|
||||
def generate_cmd
|
||||
"service docker start; docker run \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_DATABASE_DRIVER=mysql \
|
||||
-e DRONE_DATABASE_DATASOURCE=#{database_username}:'#{database_password}'@tcp\\(#{database_host}:#{database_port}\\)/#{user_login}_drone?parseTime=true \
|
||||
-e DRONE_GITEA_SERVER=#{gitea_url} \
|
||||
-e DRONE_GITEA_CLIENT_ID=#{client_id} \
|
||||
-e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_SERVER_HOST=#{drone_host} \
|
||||
-e DRONE_SERVER_PROTO=http \
|
||||
-p '80:80' \
|
||||
--restart=always \
|
||||
--detach=true \
|
||||
--name=drone-server-#{client_id} \
|
||||
--net='bridge' \
|
||||
drone/drone:1"
|
||||
end
|
||||
|
||||
private
|
||||
def gitea_url
|
||||
Gitea.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def database_username
|
||||
database_config[Rails.env]["ci_server_db"]["username"]
|
||||
end
|
||||
|
||||
def database_password
|
||||
database_config[Rails.env]["ci_server_db"]["password"]
|
||||
end
|
||||
|
||||
def database_host
|
||||
database_config[Rails.env]["ci_server_db"]["host"]
|
||||
end
|
||||
|
||||
def database_port
|
||||
database_config[Rails.env]["ci_server_db"]["port"] || 3306
|
||||
end
|
||||
|
||||
def database_config
|
||||
Rails.configuration.database_configuration
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
class Ci::Drone::Start
|
||||
attr_reader :drone_username, :drone_password, :drone_host, :drone_server_cmd, :drone_client_cmd
|
||||
|
||||
# drone_username="XXXX" 云服务器登录用户名
|
||||
# drone_password="XXXXX" 云服务器用户密码
|
||||
# drone_host="" 云服务器地址
|
||||
# eq:
|
||||
# drone_server_cmd = DevOps::Drone::Server.new('client_id', 'client_secret', 'drone_url').generate_cmd
|
||||
# drone_client_cmd = DevOps::Drone::Client.new('client_id', 'server_url').generate_cmd
|
||||
# DevOps::Drone::Start.new(drone_username, drone_password, 'drone_host', drone_server_cmd, drone_client_cmd).run
|
||||
def initialize(drone_username, drone_password, drone_host, drone_server_cmd, drone_client_cmd)
|
||||
@drone_username = drone_username
|
||||
@drone_password = drone_password
|
||||
@drone_host = drone_host
|
||||
@drone_server_cmd = drone_server_cmd
|
||||
@drone_client_cmd = drone_client_cmd
|
||||
end
|
||||
|
||||
def run
|
||||
`sshpass -p #{drone_password} ssh -o "StrictHostKeyChecking no" #{drone_username}@#{drone_host} "#{drone_server_cmd} && #{drone_client_cmd}"`
|
||||
end
|
||||
end
|
|
@ -0,0 +1,260 @@
|
|||
module Ci::Schema
|
||||
class << self
|
||||
def statement
|
||||
sqls = <<-SQL
|
||||
CREATE TABLE IF NOT EXISTS `repos` (
|
||||
`repo_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`repo_uid` varchar(250) DEFAULT NULL,
|
||||
`repo_user_id` int(11) DEFAULT NULL,
|
||||
`repo_namespace` varchar(250) DEFAULT NULL,
|
||||
`repo_name` varchar(250) DEFAULT NULL,
|
||||
`repo_slug` varchar(250) DEFAULT NULL,
|
||||
`repo_scm` varchar(50) DEFAULT NULL,
|
||||
`repo_clone_url` varchar(2000) DEFAULT NULL,
|
||||
`repo_ssh_url` varchar(2000) DEFAULT NULL,
|
||||
`repo_html_url` varchar(2000) DEFAULT NULL,
|
||||
`repo_active` tinyint(1) DEFAULT NULL,
|
||||
`repo_private` tinyint(1) DEFAULT NULL,
|
||||
`repo_visibility` varchar(50) DEFAULT NULL,
|
||||
`repo_branch` varchar(250) DEFAULT NULL,
|
||||
`repo_counter` int(11) DEFAULT NULL,
|
||||
`repo_config` varchar(500) DEFAULT NULL,
|
||||
`repo_timeout` int(11) DEFAULT NULL,
|
||||
`repo_trusted` tinyint(1) DEFAULT NULL,
|
||||
`repo_protected` tinyint(1) DEFAULT NULL,
|
||||
`repo_synced` int(11) DEFAULT NULL,
|
||||
`repo_created` int(11) DEFAULT NULL,
|
||||
`repo_updated` int(11) DEFAULT NULL,
|
||||
`repo_version` int(11) DEFAULT NULL,
|
||||
`repo_signer` varchar(50) DEFAULT NULL,
|
||||
`repo_secret` varchar(50) DEFAULT NULL,
|
||||
PRIMARY KEY (`repo_id`),
|
||||
UNIQUE KEY `repo_slug` (`repo_slug`),
|
||||
UNIQUE KEY `repo_uid` (`repo_uid`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=137 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `builds` (
|
||||
`build_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`build_repo_id` int(11) DEFAULT NULL,
|
||||
`build_config_id` int(11) DEFAULT NULL,
|
||||
`build_trigger` varchar(250) DEFAULT NULL,
|
||||
`build_number` int(11) DEFAULT NULL,
|
||||
`build_parent` int(11) DEFAULT NULL,
|
||||
`build_status` varchar(50) DEFAULT NULL,
|
||||
`build_error` varchar(500) DEFAULT NULL,
|
||||
`build_event` varchar(50) DEFAULT NULL,
|
||||
`build_action` varchar(50) DEFAULT NULL,
|
||||
`build_link` varchar(1000) DEFAULT NULL,
|
||||
`build_timestamp` int(11) DEFAULT NULL,
|
||||
`build_title` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`build_message` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`build_before` varchar(50) DEFAULT NULL,
|
||||
`build_after` varchar(50) DEFAULT NULL,
|
||||
`build_ref` varchar(500) DEFAULT NULL,
|
||||
`build_source_repo` varchar(250) DEFAULT NULL,
|
||||
`build_source` varchar(500) DEFAULT NULL,
|
||||
`build_target` varchar(500) DEFAULT NULL,
|
||||
`build_author` varchar(500) DEFAULT NULL,
|
||||
`build_author_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`build_author_email` varchar(500) DEFAULT NULL,
|
||||
`build_author_avatar` varchar(1000) DEFAULT NULL,
|
||||
`build_sender` varchar(500) DEFAULT NULL,
|
||||
`build_deploy` varchar(500) DEFAULT NULL,
|
||||
`build_params` varchar(2000) DEFAULT NULL,
|
||||
`build_started` int(11) DEFAULT NULL,
|
||||
`build_finished` int(11) DEFAULT NULL,
|
||||
`build_created` int(11) DEFAULT NULL,
|
||||
`build_updated` int(11) DEFAULT NULL,
|
||||
`build_version` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`build_id`),
|
||||
UNIQUE KEY `build_repo_id` (`build_repo_id`,`build_number`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cron` (
|
||||
`cron_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`cron_repo_id` int(11) DEFAULT NULL,
|
||||
`cron_name` varchar(50) DEFAULT NULL,
|
||||
`cron_expr` varchar(50) DEFAULT NULL,
|
||||
`cron_next` int(11) DEFAULT NULL,
|
||||
`cron_prev` int(11) DEFAULT NULL,
|
||||
`cron_event` varchar(50) DEFAULT NULL,
|
||||
`cron_branch` varchar(250) DEFAULT NULL,
|
||||
`cron_target` varchar(250) DEFAULT NULL,
|
||||
`cron_disabled` tinyint(1) DEFAULT NULL,
|
||||
`cron_created` int(11) DEFAULT NULL,
|
||||
`cron_updated` int(11) DEFAULT NULL,
|
||||
`cron_version` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`cron_id`),
|
||||
UNIQUE KEY `cron_repo_id` (`cron_repo_id`,`cron_name`),
|
||||
CONSTRAINT `cron_ibfk_1` FOREIGN KEY (`cron_repo_id`) REFERENCES `repos` (`repo_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `latest` (
|
||||
`latest_repo_id` int(11) NOT NULL DEFAULT '0',
|
||||
`latest_build_id` int(11) DEFAULT NULL,
|
||||
`latest_type` varchar(50) NOT NULL DEFAULT '',
|
||||
`latest_name` varchar(500) NOT NULL DEFAULT '',
|
||||
`latest_created` int(11) DEFAULT NULL,
|
||||
`latest_updated` int(11) DEFAULT NULL,
|
||||
`latest_deleted` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`latest_repo_id`,`latest_type`,`latest_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `logs` (
|
||||
`log_id` int(11) NOT NULL,
|
||||
`log_data` mediumblob,
|
||||
PRIMARY KEY (`log_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `migrations` (
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nodes` (
|
||||
`node_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`node_uid` varchar(500) DEFAULT NULL,
|
||||
`node_provider` varchar(50) DEFAULT NULL,
|
||||
`node_state` varchar(50) DEFAULT NULL,
|
||||
`node_name` varchar(50) DEFAULT NULL,
|
||||
`node_image` varchar(500) DEFAULT NULL,
|
||||
`node_region` varchar(100) DEFAULT NULL,
|
||||
`node_size` varchar(100) DEFAULT NULL,
|
||||
`node_os` varchar(50) DEFAULT NULL,
|
||||
`node_arch` varchar(50) DEFAULT NULL,
|
||||
`node_kernel` varchar(50) DEFAULT NULL,
|
||||
`node_variant` varchar(50) DEFAULT NULL,
|
||||
`node_address` varchar(500) DEFAULT NULL,
|
||||
`node_capacity` int(11) DEFAULT NULL,
|
||||
`node_filter` varchar(2000) DEFAULT NULL,
|
||||
`node_labels` varchar(2000) DEFAULT NULL,
|
||||
`node_error` varchar(2000) DEFAULT NULL,
|
||||
`node_ca_key` blob,
|
||||
`node_ca_cert` blob,
|
||||
`node_tls_key` blob,
|
||||
`node_tls_cert` blob,
|
||||
`node_tls_name` varchar(500) DEFAULT NULL,
|
||||
`node_paused` tinyint(1) DEFAULT NULL,
|
||||
`node_protected` tinyint(1) DEFAULT NULL,
|
||||
`node_created` int(11) DEFAULT NULL,
|
||||
`node_updated` int(11) DEFAULT NULL,
|
||||
`node_pulled` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`node_id`),
|
||||
UNIQUE KEY `node_name` (`node_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `orgsecrets` (
|
||||
`secret_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`secret_namespace` varchar(50) DEFAULT NULL,
|
||||
`secret_name` varchar(200) DEFAULT NULL,
|
||||
`secret_type` varchar(50) DEFAULT NULL,
|
||||
`secret_data` blob,
|
||||
`secret_pull_request` tinyint(1) DEFAULT NULL,
|
||||
`secret_pull_request_push` tinyint(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`secret_id`),
|
||||
UNIQUE KEY `secret_namespace` (`secret_namespace`,`secret_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `perms` (
|
||||
`perm_user_id` int(11) NOT NULL DEFAULT '0',
|
||||
`perm_repo_uid` varchar(250) NOT NULL DEFAULT '',
|
||||
`perm_read` tinyint(1) DEFAULT NULL,
|
||||
`perm_write` tinyint(1) DEFAULT NULL,
|
||||
`perm_admin` tinyint(1) DEFAULT NULL,
|
||||
`perm_synced` int(11) DEFAULT NULL,
|
||||
`perm_created` int(11) DEFAULT NULL,
|
||||
`perm_updated` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`perm_user_id`,`perm_repo_uid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `secrets` (
|
||||
`secret_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`secret_repo_id` int(11) DEFAULT NULL,
|
||||
`secret_name` varchar(500) DEFAULT NULL,
|
||||
`secret_data` blob,
|
||||
`secret_pull_request` tinyint(1) DEFAULT NULL,
|
||||
`secret_pull_request_push` tinyint(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`secret_id`),
|
||||
UNIQUE KEY `secret_repo_id` (`secret_repo_id`,`secret_name`),
|
||||
CONSTRAINT `secrets_ibfk_1` FOREIGN KEY (`secret_repo_id`) REFERENCES `repos` (`repo_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `stages` (
|
||||
`stage_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`stage_repo_id` int(11) DEFAULT NULL,
|
||||
`stage_build_id` int(11) DEFAULT NULL,
|
||||
`stage_number` int(11) DEFAULT NULL,
|
||||
`stage_name` varchar(100) DEFAULT NULL,
|
||||
`stage_kind` varchar(50) DEFAULT NULL,
|
||||
`stage_type` varchar(50) DEFAULT NULL,
|
||||
`stage_status` varchar(50) DEFAULT NULL,
|
||||
`stage_error` varchar(500) DEFAULT NULL,
|
||||
`stage_errignore` tinyint(1) DEFAULT NULL,
|
||||
`stage_exit_code` int(11) DEFAULT NULL,
|
||||
`stage_limit` int(11) DEFAULT NULL,
|
||||
`stage_os` varchar(50) DEFAULT NULL,
|
||||
`stage_arch` varchar(50) DEFAULT NULL,
|
||||
`stage_variant` varchar(10) DEFAULT NULL,
|
||||
`stage_kernel` varchar(50) DEFAULT NULL,
|
||||
`stage_machine` varchar(500) DEFAULT NULL,
|
||||
`stage_started` int(11) DEFAULT NULL,
|
||||
`stage_stopped` int(11) DEFAULT NULL,
|
||||
`stage_created` int(11) DEFAULT NULL,
|
||||
`stage_updated` int(11) DEFAULT NULL,
|
||||
`stage_version` int(11) DEFAULT NULL,
|
||||
`stage_on_success` tinyint(1) DEFAULT NULL,
|
||||
`stage_on_failure` tinyint(1) DEFAULT NULL,
|
||||
`stage_depends_on` text,
|
||||
`stage_labels` text,
|
||||
PRIMARY KEY (`stage_id`),
|
||||
UNIQUE KEY `stage_build_id` (`stage_build_id`,`stage_number`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `stages_unfinished` (
|
||||
`stage_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`stage_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `steps` (
|
||||
`step_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`step_stage_id` int(11) DEFAULT NULL,
|
||||
`step_number` int(11) DEFAULT NULL,
|
||||
`step_name` varchar(100) DEFAULT NULL,
|
||||
`step_status` varchar(50) DEFAULT NULL,
|
||||
`step_error` varchar(500) DEFAULT NULL,
|
||||
`step_errignore` tinyint(1) DEFAULT NULL,
|
||||
`step_exit_code` int(11) DEFAULT NULL,
|
||||
`step_started` int(11) DEFAULT NULL,
|
||||
`step_stopped` int(11) DEFAULT NULL,
|
||||
`step_version` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`step_id`),
|
||||
UNIQUE KEY `step_stage_id` (`step_stage_id`,`step_number`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`user_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_login` varchar(250) DEFAULT NULL,
|
||||
`user_email` varchar(500) DEFAULT NULL,
|
||||
`user_admin` tinyint(1) DEFAULT NULL,
|
||||
`user_machine` tinyint(1) DEFAULT NULL,
|
||||
`user_active` tinyint(1) DEFAULT NULL,
|
||||
`user_avatar` varchar(2000) DEFAULT NULL,
|
||||
`user_syncing` tinyint(1) DEFAULT NULL,
|
||||
`user_synced` int(11) DEFAULT NULL,
|
||||
`user_created` int(11) DEFAULT NULL,
|
||||
`user_updated` int(11) DEFAULT NULL,
|
||||
`user_last_login` int(11) DEFAULT NULL,
|
||||
`user_oauth_token` varchar(500) DEFAULT NULL,
|
||||
`user_oauth_refresh` varchar(500) DEFAULT NULL,
|
||||
`user_oauth_expiry` int(11) DEFAULT NULL,
|
||||
`user_hash` varchar(500) DEFAULT NULL,
|
||||
PRIMARY KEY (`user_id`),
|
||||
UNIQUE KEY `user_login` (`user_login`),
|
||||
UNIQUE KEY `user_hash` (`user_hash`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
SQL
|
||||
|
||||
sqls
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,4 +5,5 @@ module CustomRegexp
|
|||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
|
||||
end
|
||||
IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
|
||||
end
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
module Gitea
|
||||
class Database < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
|
||||
def self.set_connection
|
||||
gitea_server_config = Rails.configuration.database_configuration[Rails.env]["gitea_server"]
|
||||
raise 'gitea database config missing' if gitea_server_config.blank?
|
||||
|
||||
establish_connection gitea_server_config
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,23 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: applied_messages
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# applied_id :integer
|
||||
# applied_type :string(255)
|
||||
# viewed :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# name :string(255)
|
||||
# applied_user_id :integer
|
||||
# role :integer
|
||||
# project_id :integer
|
||||
#
|
||||
|
||||
class AppliedMessage < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :applied, polymorphic: true
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: applied_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer not null
|
||||
# user_id :integer not null
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
#
|
||||
|
||||
class AppliedProject < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: apply_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# reason :string(255)
|
||||
# container_id :integer
|
||||
# container_type :string(255)
|
||||
# dealer_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# status :integer default("0")
|
||||
# apply_reason :text(65535)
|
||||
# noticed :boolean default("0")
|
||||
# ip_addr :string(255)
|
||||
# reject_description :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_apply_actions_on_user_id (user_id)
|
||||
#
|
||||
|
||||
# 申请消息
|
||||
class ApplyAction < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
@ -27,4 +50,4 @@ class ApplyAction < ApplicationRecord
|
|||
belong_container_id: container_id, belong_container_type: belong_container_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: apply_user_authentications
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# status :integer
|
||||
# auth_type :integer
|
||||
# remarks :string(255)
|
||||
# dealer :integer
|
||||
# deal_time :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# is_delete :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_apply_user_authentications_on_user_id (user_id)
|
||||
#
|
||||
|
||||
# status:0 审核中 1 同意 2 拒绝 3 撤销
|
||||
# auth_type:1 实名认证, 2 职业认证
|
||||
class ApplyUserAuthentication < ApplicationRecord
|
||||
|
|
|
@ -1,3 +1,42 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: attachments
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(30)
|
||||
# filename :string(255) default(""), not null
|
||||
# disk_filename :string(255) default(""), not null
|
||||
# filesize :integer default("0"), not null
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default(""), not null
|
||||
# downloads :integer default("0"), not null
|
||||
# author_id :integer default("0"), not null
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer default("1")
|
||||
# is_public :integer default("1")
|
||||
# copy_from :integer
|
||||
# quotes :integer default("0")
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :datetime
|
||||
# resource_bank_id :integer
|
||||
# unified_setting :boolean default("1")
|
||||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachments_on_author_id (author_id)
|
||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
#
|
||||
|
||||
class Attachment < ApplicationRecord
|
||||
include BaseModel
|
||||
include Publicable
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: attachment_group_settings
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# attachment_id :integer
|
||||
# course_group_id :integer
|
||||
# course_id :integer
|
||||
# publish_time :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachment_group_settings_on_attachment_id (attachment_id)
|
||||
# index_attachment_group_settings_on_course_group_id (course_group_id)
|
||||
# index_attachment_group_settings_on_course_id (course_id)
|
||||
#
|
||||
|
||||
class AttachmentGroupSetting < ActiveRecord::Base
|
||||
belongs_to :attachment
|
||||
# belongs_to :course_group
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: attachment_histories
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(255)
|
||||
# filename :string(255) default("")
|
||||
# disk_filename :string(255) default("")
|
||||
# filesize :integer default("0")
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default("")
|
||||
# downloads :integer default("0")
|
||||
# author_id :integer
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer
|
||||
# is_public :integer
|
||||
# copy_from :integer
|
||||
# quotes :integer
|
||||
# version :integer
|
||||
# attachment_id :integer
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :date
|
||||
# cloud_url :string(255) default("")
|
||||
#
|
||||
|
||||
class AttachmentHistory < ApplicationRecord
|
||||
include Publishable
|
||||
include Publicable
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: bidding_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_package_id :integer
|
||||
# user_id :integer
|
||||
# status :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_bidding_users_on_project_package_id (project_package_id)
|
||||
# index_bidding_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class BiddingUser < ApplicationRecord
|
||||
include AASM
|
||||
|
||||
|
@ -21,4 +38,4 @@ class BiddingUser < ApplicationRecord
|
|||
def status_text
|
||||
I18n.t("bidding_user.status.#{status}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module Ci
|
||||
# def self.table_name_prefix
|
||||
# 'ci_'
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
class Ci::Build < Ci::RemoteBase
|
||||
self.primary_key = 'build_id'
|
||||
|
||||
belongs_to :repo, foreign_key: :build_repo_id
|
||||
has_many :stages, foreign_key: "stage_build_id", dependent: :destroy
|
||||
|
||||
scope :successed, ->{ by_status('success') }
|
||||
scope :failed, -> { by_status('failure') }
|
||||
scope :running, -> { by_status('running') }
|
||||
scope :errored, -> { by_status('error') }
|
||||
scope :pending, -> { by_status('pending') }
|
||||
scope :killed, -> { by_status('killed') }
|
||||
scope :by_status, ->(status) { where(build_status: status) }
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: ci_cloud_accounts
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# ip_num :integer
|
||||
# account :string(255)
|
||||
# secret :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ci_user_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# dev_ops_cloud_accounts_p_u_ip (user_id,ip_num)
|
||||
#
|
||||
|
||||
class Ci::CloudAccount < Ci::LocalBase
|
||||
belongs_to :user
|
||||
belongs_to :ci_user, class_name: 'Ci::User', foreign_key: :ci_user_id, optional: true
|
||||
|
||||
def drone_host
|
||||
[drone_ip, ":80"].join
|
||||
end
|
||||
|
||||
def drone_ip
|
||||
IPAddr.new(self.ip_num, Socket::AF_INET).to_s
|
||||
end
|
||||
|
||||
def drone_url
|
||||
["http://", self.drone_host].join
|
||||
end
|
||||
|
||||
def visible_secret
|
||||
Base64.decode64(secret)
|
||||
end
|
||||
|
||||
def self.encrypted_secret(str)
|
||||
Base64.encode64(str.strip).gsub(/\n/, '')
|
||||
end
|
||||
|
||||
def authenticate_url
|
||||
[drone_url, '/login'].join
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: ci_languages
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) not null
|
||||
# content :text(65535) not null
|
||||
# usage_amount :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# cover_id :integer
|
||||
#
|
||||
|
||||
class Ci::Language < Ci::LocalBase
|
||||
# before_save :encode_content
|
||||
|
||||
belongs_to :cover, class_name: "Attachment", foreign_key: :cover_id, optional: true
|
||||
|
||||
scope :six_common, -> { limit(6).by_usage_amount_desc }
|
||||
scope :without_content, -> { select(column_names - ['content']) }
|
||||
scope :by_usage_amount_desc, -> { order(usage_amount: :desc) }
|
||||
|
||||
|
||||
private
|
||||
def encode_content
|
||||
self.content = Base64.encode64 content
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
class Ci::LocalBase < ApplicationRecord
|
||||
self.abstract_class = true
|
||||
|
||||
def self.table_name_prefix
|
||||
"ci_"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class Ci::Log < Ci::RemoteBase
|
||||
self.primary_key = nil
|
||||
|
||||
belongs_to :step, class_name: 'Ci::Step', foreign_key: :log_id
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
class Ci::Perm < Ci::RemoteBase
|
||||
self.primary_key = nil
|
||||
|
||||
belongs_to :user, class_name: 'Ci::User', foreign_key: :perm_user_id
|
||||
belongs_to :repo, class_name: 'Ci::Repo', foreign_key: :perm_repo_uid
|
||||
|
||||
def self.auto_create!(user, repo)
|
||||
perm = new(
|
||||
perm_user_id: user.user_id,
|
||||
perm_repo_uid: repo.repo_id,
|
||||
perm_read: true,
|
||||
perm_write: true,
|
||||
perm_admin: true,
|
||||
perm_synced: 0,
|
||||
perm_created: Time.now.to_i,
|
||||
perm_updated: Time.now.to_i
|
||||
)
|
||||
perm.save!
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class Ci::RemoteBase < Ci::Database
|
||||
self.abstract_class = true
|
||||
|
||||
def generate_code
|
||||
[*'a'..'z',*'0'..'9',*'A'..'Z'].sample(32).join
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,64 @@
|
|||
class Ci::Repo < Ci::RemoteBase
|
||||
self.primary_key = 'repo_id'
|
||||
|
||||
belongs_to :user, foreign_key: :repo_user_id
|
||||
has_one :perm, foreign_key: :perm_repo_uid
|
||||
has_many :builds, foreign_key: :build_repo_id, dependent: :destroy
|
||||
|
||||
def self.find_with_namespace(namespace_path, identifier)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Ci::User.find_by_user_login namespace_path
|
||||
repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first
|
||||
|
||||
[user, repo]
|
||||
end
|
||||
|
||||
def activate!(ci_user_id)
|
||||
update(repo_active: 1,
|
||||
repo_signer: generate_code,
|
||||
repo_secret: generate_code,
|
||||
repo_user_id: ci_user_id,
|
||||
repo_timeout: 60,
|
||||
repo_config: '.trustie-pipeline.yml',
|
||||
repo_updated: Time.now.to_i)
|
||||
end
|
||||
|
||||
def self.auto_create!(user, project)
|
||||
repo = new(
|
||||
repo_user_id: user.user_id,
|
||||
repo_namespace: project.owner.login,
|
||||
repo_name: project.identifier,
|
||||
repo_slug: "#{project.owner.login}/#{project.identifier}",
|
||||
repo_scm: "git",
|
||||
repo_ssh_url: "",
|
||||
repo_html_url: "",
|
||||
repo_clone_url: project.repository.url,
|
||||
repo_active: 1,
|
||||
repo_private: true,
|
||||
repo_visibility: 'private',
|
||||
repo_branch: 'master',
|
||||
repo_counter: 0,
|
||||
repo_trusted: false,
|
||||
repo_protected: false,
|
||||
repo_synced: 0,
|
||||
repo_version: 1,
|
||||
repo_timeout: 60,
|
||||
repo_config: '.trustie-pipeline.yml',
|
||||
repo_created: Time.now.to_i,
|
||||
repo_updated: Time.now.to_i
|
||||
)
|
||||
|
||||
repo.repo_signer = repo.generate_code
|
||||
repo.repo_secret = repo.generate_code
|
||||
if repo.save!
|
||||
Ci::Perm.auto_create!(user, repo)
|
||||
repo.update_column(:repo_uid, repo.id)
|
||||
repo
|
||||
end
|
||||
end
|
||||
|
||||
def deactivate!
|
||||
update_column(:repo_active, 0)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class Ci::Stage < Ci::RemoteBase
|
||||
self.primary_key = 'stage_id'
|
||||
|
||||
belongs_to :build, foreign_key: :stage_build_id
|
||||
has_many :steps, foreign_key: "step_stage_id", dependent: :destroy
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class Ci::Step < Ci::RemoteBase
|
||||
self.primary_key = 'step_id'
|
||||
|
||||
belongs_to :stage, foreign_key: :step_stage_id
|
||||
has_one :log, class_name: 'Ci::Log', foreign_key: :log_id
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: users
|
||||
#
|
||||
# id :integer not null
|
||||
# login :string(255) default(""), not null
|
||||
# hashed_password :string(40) default(""), not null
|
||||
# firstname :string(30) default(""), not null
|
||||
# lastname :string(255) default(""), not null
|
||||
# mail :string(60)
|
||||
# admin :boolean default("0"), not null
|
||||
# status :integer default("1"), not null
|
||||
# last_login_on :datetime
|
||||
# language :string(5) default("")
|
||||
# auth_source_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# type :string(255)
|
||||
# identity_url :string(255)
|
||||
# mail_notification :string(255) default(""), not null
|
||||
# salt :string(64)
|
||||
# gid :integer
|
||||
# visits :integer default("0")
|
||||
# excellent_teacher :integer default("0")
|
||||
# excellent_student :integer default("0")
|
||||
# phone :string(255)
|
||||
# authentication :boolean default("0")
|
||||
# grade :integer default("0")
|
||||
# experience :integer default("0")
|
||||
# nickname :string(255)
|
||||
# show_realname :boolean default("1")
|
||||
# professional_certification :boolean default("0")
|
||||
# ID_number :string(255)
|
||||
# certification :integer default("0")
|
||||
# homepage_teacher :boolean default("0")
|
||||
# homepage_engineer :boolean default("0")
|
||||
# is_test :integer default("0")
|
||||
# ecoder_user_id :integer default("0")
|
||||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_users_on_ecoder_user_id (ecoder_user_id)
|
||||
# index_users_on_homepage_engineer (homepage_engineer)
|
||||
# index_users_on_homepage_teacher (homepage_teacher)
|
||||
# index_users_on_laboratory_id (laboratory_id)
|
||||
# index_users_on_login (login)
|
||||
# index_users_on_mail (mail)
|
||||
# index_users_on_type (type)
|
||||
#
|
||||
|
||||
class Ci::User < Ci::RemoteBase
|
||||
self.primary_key = 'user_id'
|
||||
|
||||
has_many :repos, foreign_key: :repo_user_id, dependent: :destroy
|
||||
has_many :perms, foreign_key: :perm_user_id, dependent: :delete_all
|
||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :ci_user_id
|
||||
|
||||
end
|
|
@ -1,3 +1,23 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: composes
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# title :string(255)
|
||||
# description :text(65535)
|
||||
# show_mode :integer default("0")
|
||||
# compose_mode :boolean default("0")
|
||||
# compose_users_count :integer default("0")
|
||||
# compose_projects_count :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_composes_on_user_id_and_show_mode_and_compose_mode (user_id,show_mode,compose_mode)
|
||||
#
|
||||
|
||||
class Compose < ApplicationRecord
|
||||
#组织
|
||||
belongs_to :user
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: compose_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# compose_id :integer
|
||||
# position :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_compose_projects_on_user_id_and_project_id_and_compose_id (user_id,project_id,compose_id)
|
||||
#
|
||||
|
||||
class ComposeProject < ApplicationRecord
|
||||
#组织的项目记录表
|
||||
belongs_to :compose
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: compose_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# compose_id :integer
|
||||
# is_manager :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_compose_users_on_user_id_and_compose_id (user_id,compose_id)
|
||||
#
|
||||
|
||||
class ComposeUser < ApplicationRecord
|
||||
belongs_to :compose
|
||||
belongs_to :user
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
module Droneable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
end
|
||||
|
||||
def devops_uninit?
|
||||
self.devops_step === User::DEVOPS_UNINIT
|
||||
end
|
||||
|
||||
def devops_unverified?
|
||||
self.devops_step === User::DEVOPS_UNVERIFIED
|
||||
end
|
||||
|
||||
def devops_certification?
|
||||
self.devops_step === User::DEVOPS_CERTIFICATION
|
||||
end
|
||||
|
||||
def set_drone_step!(step)
|
||||
self.update_column(:devops_step, step)
|
||||
end
|
||||
|
||||
def ci_certification?
|
||||
return false if self.is_a?(AnonymousUser)
|
||||
devops_certification? && Ci::User.exists?(user_login: self.login)
|
||||
end
|
||||
|
||||
def unbind_account!
|
||||
user_projects = self.projects
|
||||
|
||||
user_projects.update_all(open_devops: false, open_devops_count: 0)
|
||||
set_drone_step!(User::DEVOPS_UNINIT)
|
||||
|
||||
# TODO
|
||||
# 删除用户项目下的与ci相关的所有webhook
|
||||
user_projects.select(:id, :identifier, :gitea_webhook_id).each do |project|
|
||||
if project.gitea_webhook_id
|
||||
result = Gitea::Hooks::DestroyService.call(self.gitea_token, self.login, project.identifier, project.gitea_webhook_id)
|
||||
project.update_column(:gitea_webhook_id, nil) if result.status == 204
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
end
|
||||
end
|
|
@ -5,6 +5,7 @@ module Matchable
|
|||
scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? }
|
||||
scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? }
|
||||
scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) }
|
||||
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: coo_imgs
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# src_states :string(255)
|
||||
# url_states :string(255)
|
||||
# img_type :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# position :integer
|
||||
#
|
||||
|
||||
class CooImg < ApplicationRecord
|
||||
extend Enumerize
|
||||
|
||||
enumerize :img_type, in: %i[com_coop edu_coop alliance_coop]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: diff_records
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# container_type :string(255)
|
||||
# container_id :integer
|
||||
# column_name :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_diff_records_on_container_type_and_container_id (container_type,container_id)
|
||||
# index_diff_records_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class DiffRecord < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :container, polymorphic: true
|
||||
|
@ -5,4 +23,4 @@ class DiffRecord < ApplicationRecord
|
|||
has_one :diff_record_content, dependent: :destroy
|
||||
|
||||
delegate :content, to: :diff_record_content
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: diff_record_contents
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# diff_record_id :integer
|
||||
# content :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_diff_record_contents_on_diff_record_id (diff_record_id)
|
||||
#
|
||||
|
||||
class DiffRecordContent < ApplicationRecord
|
||||
belongs_to :diff_record
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: edu_settings
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# value :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# description :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_edu_settings_on_name (name) UNIQUE
|
||||
#
|
||||
|
||||
class EduSetting < ApplicationRecord
|
||||
after_commit :expire_value_cache
|
||||
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: fork_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# fork_project_id :integer
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_fork_users_on_project_id (project_id)
|
||||
# index_fork_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class ForkUser < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
class Gitea::Base < Gitea::Database
|
||||
self.abstract_class = true
|
||||
|
||||
end
|
|
@ -1,3 +1,14 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: ignores
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class Ignore < ApplicationRecord
|
||||
include Projectable
|
||||
end
|
||||
|
|
|
@ -1,3 +1,53 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issues
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# tracker_id :integer not null
|
||||
# project_id :integer not null
|
||||
# subject :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# due_date :date
|
||||
# category_id :integer
|
||||
# status_id :integer not null
|
||||
# assigned_to_id :integer
|
||||
# priority_id :integer not null
|
||||
# fixed_version_id :integer
|
||||
# author_id :integer not null
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# start_date :date
|
||||
# done_ratio :integer default("0"), not null
|
||||
# estimated_hours :float(24)
|
||||
# parent_id :integer
|
||||
# root_id :integer
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# is_private :boolean default("0"), not null
|
||||
# closed_on :datetime
|
||||
# project_issues_index :integer
|
||||
# issue_type :string(255)
|
||||
# token :integer default("0")
|
||||
# issue_tags_value :string(255)
|
||||
# is_lock :boolean default("0")
|
||||
# issue_classify :string(255)
|
||||
# ref_name :string(255)
|
||||
# branch_name :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issues_on_assigned_to_id (assigned_to_id)
|
||||
# index_issues_on_author_id (author_id)
|
||||
# index_issues_on_category_id (category_id)
|
||||
# index_issues_on_created_on (created_on)
|
||||
# index_issues_on_fixed_version_id (fixed_version_id)
|
||||
# index_issues_on_priority_id (priority_id)
|
||||
# index_issues_on_root_id_and_lft_and_rgt (root_id,lft,rgt)
|
||||
# index_issues_on_status_id (status_id)
|
||||
# index_issues_on_tracker_id (tracker_id)
|
||||
# issues_project_id (project_id)
|
||||
#
|
||||
|
||||
class Issue < ApplicationRecord
|
||||
#issue_type 1为普通,2为悬赏
|
||||
include DunCheckAble
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issue_depends
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# issue_id :integer
|
||||
# depend_issue_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_depends_on_user_id_and_issue_id_and_depend_issue_id (user_id,issue_id,depend_issue_id)
|
||||
#
|
||||
|
||||
class IssueDepend < ApplicationRecord
|
||||
belongs_to :issue
|
||||
end
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issue_priorities
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# position :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_priorities_on_name (name)
|
||||
#
|
||||
|
||||
class IssuePriority < ApplicationRecord
|
||||
has_many :issues
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issue_statuses
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(30) default(""), not null
|
||||
# is_closed :boolean default("0"), not null
|
||||
# is_default :boolean default("0"), not null
|
||||
# position :integer default("1")
|
||||
# default_done_ratio :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_statuses_on_is_closed (is_closed)
|
||||
# index_issue_statuses_on_is_default (is_default)
|
||||
# index_issue_statuses_on_position (position)
|
||||
#
|
||||
|
||||
class IssueStatus < ApplicationRecord
|
||||
has_many :issues
|
||||
belongs_to :project, optional: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issue_tags
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# description :string(255)
|
||||
# color :string(255)
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# issues_count :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# gid :integer
|
||||
# gitea_url :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_tags_on_user_id_and_name_and_project_id (user_id,name,project_id)
|
||||
#
|
||||
|
||||
class IssueTag < ApplicationRecord
|
||||
|
||||
has_many :issue_tags_relates, dependent: :destroy
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: issue_tags_relates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# issue_id :integer
|
||||
# issue_tag_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_tags_relates_on_issue_id_and_issue_tag_id (issue_id,issue_tag_id)
|
||||
#
|
||||
|
||||
class IssueTagsRelate < ApplicationRecord
|
||||
belongs_to :issue
|
||||
belongs_to :issue_tag, counter_cache: :issues_count
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue