forked from Gitlink/forgeplus
Merge pull request '20220722版本' (#309) from Trustie/forgeplus:trustie_server into master
This commit is contained in:
commit
802568cf89
268
Gemfile
268
Gemfile
|
@ -1,130 +1,138 @@
|
|||
source 'https://gems.ruby-china.com'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
|
||||
gem 'puma', '~> 3.11'
|
||||
gem 'sass-rails', '~> 5.0'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
|
||||
# gem 'coffee-rails', '~> 4.2'
|
||||
gem 'turbolinks', '~> 5'
|
||||
gem 'jbuilder', '~> 2.5'
|
||||
gem 'groupdate', '~> 4.1.0'
|
||||
gem 'chartkick'
|
||||
gem 'grape-entity', '~> 0.7.1'
|
||||
gem 'kaminari', '~> 1.1', '>= 1.1.1'
|
||||
|
||||
gem 'bootsnap', '>= 1.1.0', require: false
|
||||
|
||||
gem 'chinese_pinyin'
|
||||
|
||||
gem 'rack-cors'
|
||||
gem 'redis-rails'
|
||||
gem 'roo-xls'
|
||||
gem 'simple_xlsx_reader'
|
||||
|
||||
gem 'rubyzip'
|
||||
|
||||
gem 'spreadsheet'
|
||||
gem 'ruby-ole'
|
||||
# 导出为xlsx
|
||||
gem 'axlsx', '~> 3.0.0.pre'
|
||||
gem 'axlsx_rails', '~> 0.5.2'
|
||||
|
||||
gem 'oauth2'
|
||||
#导出为pdf
|
||||
gem 'pdfkit'
|
||||
gem 'wkhtmltopdf-binary'
|
||||
# gem 'request_store'
|
||||
#gem 'iconv'
|
||||
# markdown 转html
|
||||
gem 'redcarpet', '~> 3.4'
|
||||
|
||||
gem 'rqrcode', '~> 0.10.1'
|
||||
gem 'rqrcode_png'
|
||||
|
||||
gem 'acts-as-taggable-on', '~> 6.0'
|
||||
|
||||
# a tree structure
|
||||
gem 'ancestry'
|
||||
gem 'acts_as_list'
|
||||
gem 'omniauth-cas'
|
||||
|
||||
# profiler Middleware
|
||||
gem 'rack-mini-profiler'
|
||||
|
||||
# object-based searching
|
||||
gem 'ransack'
|
||||
|
||||
group :development, :test do
|
||||
gem 'rspec-rails', '~> 3.8'
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'prettier'
|
||||
gem 'rubocop', '~> 0.52.0'
|
||||
gem 'solargraph', '~> 0.38.0'
|
||||
gem 'awesome_print'
|
||||
gem 'web-console', '>= 3.3.0'
|
||||
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
|
||||
gem 'capybara', '>= 2.15', '< 4.0'
|
||||
gem 'selenium-webdriver'
|
||||
gem 'chromedriver-helper'
|
||||
end
|
||||
|
||||
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
||||
|
||||
#编码检测
|
||||
gem 'rchardet', '~> 1.8'
|
||||
|
||||
# http client
|
||||
gem 'faraday', '~> 0.15.4'
|
||||
|
||||
# view
|
||||
gem 'active_decorator'
|
||||
gem 'bootstrap', '~> 4.3.1'
|
||||
gem 'jquery-rails'
|
||||
gem 'simple_form'
|
||||
gem 'font-awesome-sass', '4.7.0'
|
||||
|
||||
# i18n
|
||||
gem 'rails-i18n', '~> 5.1'
|
||||
|
||||
# job
|
||||
gem 'sidekiq'
|
||||
gem 'sinatra'
|
||||
gem "sidekiq-cron", "~> 1.1"
|
||||
|
||||
# batch insert
|
||||
gem 'bulk_insert'
|
||||
|
||||
# elasticsearch
|
||||
gem 'searchkick'
|
||||
|
||||
gem 'aasm'
|
||||
gem 'enumerize'
|
||||
|
||||
gem 'diffy'
|
||||
|
||||
gem 'deep_cloneable', '~> 3.0.0'
|
||||
|
||||
# oauth2
|
||||
gem 'omniauth', '~> 1.9.0'
|
||||
gem 'omniauth-oauth2', '~> 1.6.0'
|
||||
|
||||
# global var
|
||||
gem 'request_store'
|
||||
|
||||
# 敏感词汇
|
||||
gem 'harmonious_dictionary', '~> 0.0.1'
|
||||
|
||||
gem 'parallel', '~> 1.19', '>= 1.19.1'
|
||||
|
||||
gem 'letter_avatar'
|
||||
source 'https://gems.ruby-china.com'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
|
||||
gem 'puma', '~> 3.11'
|
||||
gem 'sass-rails', '~> 5.0'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
|
||||
# gem 'coffee-rails', '~> 4.2'
|
||||
gem 'turbolinks', '~> 5'
|
||||
gem 'jbuilder', '~> 2.5'
|
||||
gem 'groupdate', '~> 4.1.0'
|
||||
gem 'chartkick'
|
||||
gem 'grape-entity', '~> 0.7.1'
|
||||
gem 'kaminari', '~> 1.1', '>= 1.1.1'
|
||||
|
||||
gem 'bootsnap', '>= 1.1.0', require: false
|
||||
|
||||
gem 'chinese_pinyin'
|
||||
|
||||
gem 'rack-cors'
|
||||
gem 'redis-rails'
|
||||
gem 'roo-xls'
|
||||
gem 'simple_xlsx_reader'
|
||||
|
||||
gem 'rubyzip'
|
||||
|
||||
gem 'spreadsheet'
|
||||
gem 'ruby-ole'
|
||||
# 导出为xlsx
|
||||
gem 'axlsx', '~> 3.0.0.pre'
|
||||
gem 'axlsx_rails', '~> 0.5.2'
|
||||
|
||||
gem 'oauth2'
|
||||
#导出为pdf
|
||||
gem 'pdfkit'
|
||||
gem 'wkhtmltopdf-binary'
|
||||
# gem 'request_store'
|
||||
#gem 'iconv'
|
||||
# markdown 转html
|
||||
gem 'redcarpet', '~> 3.4'
|
||||
|
||||
gem 'rqrcode', '~> 0.10.1'
|
||||
gem 'rqrcode_png'
|
||||
|
||||
gem 'acts-as-taggable-on', '~> 6.0'
|
||||
|
||||
# a tree structure
|
||||
gem 'ancestry'
|
||||
gem 'acts_as_list'
|
||||
gem 'omniauth-cas'
|
||||
|
||||
# profiler Middleware
|
||||
gem 'rack-mini-profiler'
|
||||
|
||||
# object-based searching
|
||||
gem 'ransack'
|
||||
|
||||
group :development, :test do
|
||||
gem 'rspec-rails', '~> 3.8'
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'prettier'
|
||||
gem 'rubocop', '~> 0.52.0'
|
||||
gem 'solargraph', '~> 0.38.0'
|
||||
gem 'awesome_print'
|
||||
gem 'web-console', '>= 3.3.0'
|
||||
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
|
||||
gem 'capybara', '>= 2.15', '< 4.0'
|
||||
gem 'selenium-webdriver'
|
||||
gem 'chromedriver-helper'
|
||||
end
|
||||
|
||||
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
||||
|
||||
#编码检测
|
||||
gem 'rchardet', '~> 1.8'
|
||||
|
||||
# http client
|
||||
gem 'faraday', '~> 0.15.4'
|
||||
|
||||
# view
|
||||
gem 'active_decorator'
|
||||
gem 'bootstrap', '~> 4.3.1'
|
||||
gem 'jquery-rails'
|
||||
gem 'simple_form'
|
||||
gem 'font-awesome-sass', '4.7.0'
|
||||
|
||||
# i18n
|
||||
gem 'rails-i18n', '~> 5.1'
|
||||
|
||||
# job
|
||||
gem 'sidekiq'
|
||||
gem 'sinatra'
|
||||
gem "sidekiq-cron", "~> 1.1"
|
||||
|
||||
# batch insert
|
||||
gem 'bulk_insert'
|
||||
|
||||
# elasticsearch
|
||||
gem 'searchkick'
|
||||
|
||||
gem 'aasm'
|
||||
gem 'enumerize'
|
||||
|
||||
gem 'diffy'
|
||||
|
||||
gem 'deep_cloneable', '~> 3.0.0'
|
||||
|
||||
# oauth2
|
||||
gem 'omniauth', '~> 1.9.0'
|
||||
gem 'omniauth-oauth2', '~> 1.6.0'
|
||||
|
||||
# global var
|
||||
gem 'request_store'
|
||||
|
||||
# 敏感词汇
|
||||
gem 'harmonious_dictionary', '~> 0.0.1'
|
||||
|
||||
gem 'parallel', '~> 1.19', '>= 1.19.1'
|
||||
|
||||
gem 'letter_avatar'
|
||||
|
||||
gem 'jwt'
|
||||
|
||||
gem 'doorkeeper'
|
||||
|
||||
gem 'doorkeeper-jwt'
|
||||
|
||||
gem 'gitea-client', '~> 0.10.2'
|
|
@ -106,6 +106,10 @@ GEM
|
|||
activerecord (>= 3.1.0, < 7)
|
||||
diff-lcs (1.3)
|
||||
diffy (3.3.0)
|
||||
doorkeeper (5.5.1)
|
||||
railties (>= 5)
|
||||
doorkeeper-jwt (0.4.1)
|
||||
jwt (>= 2.1)
|
||||
e2mmap (0.1.0)
|
||||
elasticsearch (7.5.0)
|
||||
elasticsearch-api (= 7.5.0)
|
||||
|
@ -450,6 +454,8 @@ DEPENDENCIES
|
|||
chromedriver-helper
|
||||
deep_cloneable (~> 3.0.0)
|
||||
diffy
|
||||
doorkeeper
|
||||
doorkeeper-jwt
|
||||
enumerize
|
||||
faraday (~> 0.15.4)
|
||||
font-awesome-sass (= 4.7.0)
|
||||
|
@ -458,6 +464,7 @@ DEPENDENCIES
|
|||
harmonious_dictionary (~> 0.0.1)
|
||||
jbuilder (~> 2.5)
|
||||
jquery-rails
|
||||
jwt
|
||||
kaminari (~> 1.1, >= 1.1.1)
|
||||
letter_avatar
|
||||
listen (>= 3.0.5, < 3.2)
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
class Admins::DashboardsController < Admins::BaseController
|
||||
def index
|
||||
@active_user_count = User.where(last_login_on: today).count
|
||||
@weekly_active_user_count = User.where(last_login_on: current_week).count
|
||||
@month_active_user_count = User.where(last_login_on: current_month).count
|
||||
# 用户活跃数
|
||||
day_user_ids = CommitLog.where(created_at: today).pluck(:project_id).uniq
|
||||
weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:project_id).uniq
|
||||
month_user_ids = CommitLog.where(created_at: current_month).pluck(:project_id).uniq
|
||||
@active_user_count = User.where(last_login_on: today).or(User.where(id: day_user_ids)).count
|
||||
@weekly_active_user_count = User.where(last_login_on: current_week).or(User.where(id: weekly_user_ids)).count
|
||||
@month_active_user_count = User.where(last_login_on: current_month).or(User.where(id: month_user_ids)).count
|
||||
user_ids = User.where(created_on: pre_week).pluck(:id).uniq
|
||||
weekly_keep_user_count = User.where(id: user_ids).where(last_login_on: current_week).count
|
||||
@weekly_keep_rate = format("%.2f", user_ids.size > 0 ? weekly_keep_user_count.to_f / user_ids.size : 0)
|
||||
|
||||
@new_user_count = User.where(created_on: current_month).count
|
||||
# 新用户注册数
|
||||
@day_new_user_count = User.where(created_on: today).count
|
||||
@weekly_new_user_count = User.where(created_on: current_week).count
|
||||
@month_new_user_count = User.where(created_on: current_month).count
|
||||
|
||||
# 活跃项目数
|
||||
day_project_ids = (CommitLog.where(created_at: today).pluck(:project_id).uniq + Issue.where(created_on: today).pluck(:project_id).uniq).uniq
|
||||
weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq
|
||||
month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq
|
||||
@day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count
|
||||
@weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
|
||||
@month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
|
||||
|
||||
# 新增项目数
|
||||
@day_new_project_count = Project.where(created_on: today).count
|
||||
@weekly_new_project_count = Project.where(created_on: current_week).count
|
||||
@month_new_project_count = Project.where(created_on: current_month).count
|
||||
end
|
||||
|
||||
def month_active_user
|
||||
|
@ -16,7 +39,6 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
{ value: count['professional'].to_i, name: '专业人士' },
|
||||
{ value: count[nil].to_i, name: '未选职业' },
|
||||
]
|
||||
|
||||
render_ok(data: data)
|
||||
end
|
||||
|
||||
|
@ -42,10 +64,14 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
end
|
||||
|
||||
def current_week
|
||||
7.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
7.days.ago.end_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_month
|
||||
30.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
30.days.ago.end_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def pre_week
|
||||
14.days.ago.end_of_day..7.days.ago.end_of_day
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
class Api::V1::BaseController < ApplicationController
|
||||
|
||||
include Api::ProjectHelper
|
||||
include Api::UserHelper
|
||||
|
||||
# before_action :doorkeeper_authorize!
|
||||
# skip_before_action :user_setup
|
||||
|
||||
protected
|
||||
# def current_user
|
||||
# #client方法对接,需要一直带着用户标识uid
|
||||
# Rails.logger.info doorkeeper_token
|
||||
# if doorkeeper_token && doorkeeper_token.resource_owner_id.blank?
|
||||
# # return User.anonymous if params[:uid].nil?
|
||||
# # tip_exception("2222")
|
||||
# # return render_error('缺少用户标识!') if params[:uid].nil?
|
||||
# User.current = User.find(params[:uid])
|
||||
# else
|
||||
# User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
|
||||
# end
|
||||
# end
|
||||
|
||||
def limit
|
||||
params.fetch(:limit, 15)
|
||||
end
|
||||
def page
|
||||
params.fetch(:page, 1)
|
||||
end
|
||||
|
||||
# 具有对仓库的管理权限
|
||||
def require_manager_above
|
||||
@project = load_project
|
||||
return render_forbidden unless current_user.admin? && @project.manager?(current_user)
|
||||
end
|
||||
|
||||
# 具有对仓库的操作权限
|
||||
def require_operate_above
|
||||
@project = load_project
|
||||
return render_forbidden unless current_user.admin? && @project.operator?(current_user)
|
||||
end
|
||||
|
||||
# 具有对仓库的访问权限
|
||||
def require_public_and_member_above
|
||||
@project = load_project
|
||||
return render_forbidden unless @project.is_public || (current_user.admin? && @project.member?(current_user))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:all]
|
||||
|
||||
def all
|
||||
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
before_action :require_operate_above, only: [:create]
|
||||
|
||||
def create
|
||||
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
private
|
||||
def branch_params
|
||||
params.require(:branch).permit(:new_branch_name, :old_branch_name)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index, :diff]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
|
||||
def diff
|
||||
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class Api::V1::Projects::ContentsController < Api::V1::BaseController
|
||||
before_action :require_operate_above, only: [:batch]
|
||||
|
||||
def batch
|
||||
@result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, batch_content_params, current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
|
||||
private
|
||||
def batch_content_params
|
||||
params.require(:content).permit(:author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch, files: [ :action_type, :content, :encoding, :file_path])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class Api::V1::Projects::GitController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:trees, :blobs]
|
||||
|
||||
def trees
|
||||
@result_object = Api::V1::Projects::Git::TreesService.call(@project, params[:sha], {recursive: params[:recursive], page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def blobs
|
||||
@result_object = Api::V1::Projects::Git::BlobsService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
class Api::V1::Projects::WebhooksController < Api::V1::BaseController
|
||||
before_action :require_manager_above
|
||||
before_action :find_webhook, only: [:show, :update, :destroy, :tests, :hooktasks]
|
||||
|
||||
def index
|
||||
# @result_object = Api::V1::Projects::Webhooks::ListService.call(@project, current_user&.gitea_token)
|
||||
@webhooks = @project.webhooks
|
||||
@webhooks = kaminari_paginate(@webhooks)
|
||||
end
|
||||
|
||||
def create
|
||||
@result_object = Api::V1::Projects::Webhooks::CreateService.call(@project, webhook_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::Webhooks::GetService.call(@project, params[:id], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def update
|
||||
@result_object = Api::V1::Projects::Webhooks::UpdateService.call(@project, params[:id], webhook_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@result_object = Api::V1::Projects::Webhooks::DeleteService.call(@project, params[:id], current_user&.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('删除失败!')
|
||||
end
|
||||
end
|
||||
|
||||
def tests
|
||||
@result_object = Api::V1::Projects::Webhooks::TestsService.call(@project, params[:id], current_user&.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('推送失败!')
|
||||
end
|
||||
end
|
||||
|
||||
def hooktasks
|
||||
@hooktasks = @webhook.tasks.where(is_delivered: true).order("delivered desc")
|
||||
@hooktasks = kaminari_paginate(@hooktasks)
|
||||
end
|
||||
|
||||
private
|
||||
def webhook_params
|
||||
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, events: [])
|
||||
end
|
||||
|
||||
def find_webhook
|
||||
@webhook = Gitea::Webhook.find_by_id(params[:id])
|
||||
return render_not_found unless @webhook.present?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
class Api::V1::ProjectsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:show, :compare, :blame]
|
||||
|
||||
def index
|
||||
render_ok
|
||||
end
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token)
|
||||
end
|
||||
|
||||
def compare
|
||||
@result_object = Api::V1::Projects::CompareService.call(@project, params[:from], params[:to], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def blame
|
||||
@result_object = Api::V1::Projects::BlameService.call(@project, params[:sha], params[:filepath], current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class Api::V1::Users::ProjectsController < Api::V1::BaseController
|
||||
before_action :load_observe_user
|
||||
|
||||
def index
|
||||
@object_results = Api::V1::Users::Projects::ListService.call(@observe_user, query_params, current_user)
|
||||
@projects = kaminari_paginate(@object_results)
|
||||
end
|
||||
|
||||
private
|
||||
def query_params
|
||||
params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class Api::V1::UsersController < Api::V1::BaseController
|
||||
|
||||
def index
|
||||
render_ok
|
||||
end
|
||||
end
|
|
@ -170,7 +170,6 @@ class ApplicationController < ActionController::Base
|
|||
# 未授权的捕捉407,弹试用申请弹框
|
||||
def require_login
|
||||
#6.13 -hs
|
||||
|
||||
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
||||
end
|
||||
|
||||
|
@ -249,39 +248,55 @@ class ApplicationController < ActionController::Base
|
|||
#return if params[:controller] == "main"
|
||||
# Find the current user
|
||||
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
||||
User.current = find_current_user
|
||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||
|
||||
# 开放课程通过链接访问的用户
|
||||
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
||||
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
||||
|
||||
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
||||
user = open_class_user
|
||||
if user
|
||||
start_user_session(user)
|
||||
set_autologin_cookie(user)
|
||||
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
|
||||
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
|
||||
if @doorkeeper_token.present?
|
||||
# client方法对接,需要一直带着用户标识uid
|
||||
if @doorkeeper_token.resource_owner_id.blank?
|
||||
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
|
||||
User.current = User.find(params[:uid])
|
||||
else
|
||||
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
|
||||
end
|
||||
User.current = user
|
||||
end
|
||||
end
|
||||
# if !User.current.logged? && Rails.env.development?
|
||||
# User.current = User.find 1
|
||||
# end
|
||||
else
|
||||
User.current = find_current_user
|
||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||
|
||||
# 开放课程通过链接访问的用户
|
||||
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
||||
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
||||
|
||||
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
||||
user = open_class_user
|
||||
if user
|
||||
start_user_session(user)
|
||||
set_autologin_cookie(user)
|
||||
end
|
||||
User.current = user
|
||||
end
|
||||
end
|
||||
|
||||
# if !User.current.logged? && Rails.env.development?
|
||||
# user = User.find 1
|
||||
# User.current = user
|
||||
# start_user_session(user)
|
||||
# end
|
||||
|
||||
|
||||
# 测试版前端需求
|
||||
logger.info("subdomain:#{request.subdomain}")
|
||||
if request.subdomain != "www"
|
||||
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
User.current = User.find 81403
|
||||
elsif params[:debug] == 'student'
|
||||
User.current = User.find 8686
|
||||
elsif params[:debug] == 'admin'
|
||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
user = User.find 36480
|
||||
User.current = user
|
||||
cookies.signed[:user_id] = user.id
|
||||
# 测试版前端需求
|
||||
logger.info("subdomain:#{request.subdomain}")
|
||||
if request.subdomain != "www"
|
||||
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
User.current = User.find 81403
|
||||
elsif params[:debug] == 'student'
|
||||
User.current = User.find 8686
|
||||
elsif params[:debug] == 'admin'
|
||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
user = User.find 36480
|
||||
User.current = user
|
||||
cookies.signed[:user_id] = user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
# User.current = User.find 81403
|
||||
|
@ -681,7 +696,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
@project, @owner = Project.find_with_namespace(namespace, id)
|
||||
|
||||
if @project and current_user.can_read_project?(@project)
|
||||
if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
|
||||
logger.info "###########: has project and can read project"
|
||||
@project
|
||||
# elsif @project && current_user.is_a?(AnonymousUser)
|
||||
|
|
|
@ -33,8 +33,8 @@ class AttachmentsController < ApplicationController
|
|||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||
if url.starts_with?(base_url)
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
|
||||
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
|
||||
response = Faraday.get(request_url)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
class CommitLogsController < ApplicationController
|
||||
|
||||
def create
|
||||
tip_exception "未认证" unless params[:token].to_s == "7917908927b6f1b792f2027a08a8b24a2de42c1692c2fd45da0dee5cf90a5af5"
|
||||
ref = params[:ref]
|
||||
user_name = params[:pusher][:login]
|
||||
user_mail = params[:pusher][:email]
|
||||
user = User.find_by(mail: user_mail)
|
||||
user = User.find_by(login: user_name) if user.blank?
|
||||
|
||||
repository_id = params[:repository][:id]
|
||||
repository_name = params[:repository][:name]
|
||||
repository_full_name = params[:repository][:full_name]
|
||||
owner_name = repository_full_name.split("/")[0]
|
||||
owner = User.find_by(login: owner_name)
|
||||
project = Project.where(identifier: repository_name).where(user_id: owner&.id)&.first
|
||||
project = Project.where(identifier: repository_name).where(gpid: repository_id)&.first if project.blank?
|
||||
params[:commits].each do |commit|
|
||||
commit_id = commit[:id]
|
||||
message = commit[:message]
|
||||
CommitLog.create(user: user, project: project, repository_id: repository_id,
|
||||
name: repository_name, full_name: repository_full_name,
|
||||
ref: ref, commit_id: commit_id, message: message)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -6,9 +6,14 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
if params[:type] == "sha"
|
||||
load_compare_params
|
||||
@compare_result ||= gitea_compare(@base, @head)
|
||||
else
|
||||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
end
|
||||
@page_size = page_size <= 0 ? 1 : page_size
|
||||
@page_limit = page_limit <=0 ? 15 : page_limit
|
||||
@page_offset = (@page_size -1) * @page_limit
|
||||
|
|
|
@ -18,15 +18,15 @@ module Acceleratorable
|
|||
end
|
||||
|
||||
def accelerator_domain
|
||||
Gitea.gitea_config[:accelerator]["domain"]
|
||||
GiteaService.gitea_config[:accelerator]["domain"]
|
||||
end
|
||||
|
||||
def accelerator_username
|
||||
Gitea.gitea_config[:accelerator]["access_key_id"]
|
||||
GiteaService.gitea_config[:accelerator]["access_key_id"]
|
||||
end
|
||||
|
||||
def config_accelerator?
|
||||
Gitea.gitea_config[:accelerator].present?
|
||||
GiteaService.gitea_config[:accelerator].present?
|
||||
end
|
||||
|
||||
def is_foreign_url?(clone_addr)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
module Api::ProjectHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_project
|
||||
namespace = params[:owner]
|
||||
repo = params[:repo]
|
||||
|
||||
@project, @owner = Project.find_with_namespace(namespace, repo)
|
||||
|
||||
if @project
|
||||
logger.info "###########:project founded"
|
||||
@project
|
||||
else
|
||||
logger.info "###########:project not found"
|
||||
@project = nil
|
||||
render_not_found and return
|
||||
end
|
||||
@project
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
module Api::UserHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_observe_user
|
||||
username = params[:owner]
|
||||
|
||||
@observe_user = User.find_by(login: username)
|
||||
|
||||
if @observe_user
|
||||
logger.info "###########observe_user not founded"
|
||||
@observe_user
|
||||
else
|
||||
logger.info "###########observe_user not found"
|
||||
@observe_user = nil
|
||||
render_not_found and return
|
||||
end
|
||||
@observe_user
|
||||
end
|
||||
end
|
|
@ -116,6 +116,7 @@ module LoginHelper
|
|||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
||||
if interactor.success?
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
||||
user.update_column(:is_sync_pwd, true)
|
||||
true
|
||||
else
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
|
||||
|
|
|
@ -5,7 +5,16 @@ module Repository::LanguagesPercentagable
|
|||
result = Gitea::Repository::Languages::ListService.call(@owner.login,
|
||||
@repository.identifier, current_user&.gitea_token)
|
||||
|
||||
result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
||||
@transform_language = result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
||||
update_project_language(@transform_language) unless @transform_language.nil?
|
||||
@transform_language
|
||||
end
|
||||
|
||||
def update_project_language(language)
|
||||
db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
|
||||
@project.update_column(:project_language_id, db_language.id)
|
||||
rescue
|
||||
return
|
||||
end
|
||||
|
||||
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
class Oauth2Controller < ActionController::Base
|
||||
layout 'doorkeeper/application'
|
||||
include LoginHelper
|
||||
|
||||
def show
|
||||
client_id = params[:call_url].split("client_id=")[1].split("&redirect_uri")[0]
|
||||
@call_url = request.fullpath.split('call_url=').last
|
||||
@app = Doorkeeper::Application.find_by(uid: client_id)
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:login].blank?
|
||||
@error = {msg: '邮箱地址或用户名不能为空', id: 'login'}
|
||||
elsif params[:password].blank?
|
||||
@error = {msg: '请输入密码', id: 'password'}
|
||||
else
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return @error = {msg: '账号或密码错误', id: 'login'} if @user.blank?
|
||||
return @error = {msg: '违反平台使用规范,账号已被锁定', id: 'login'} if @user.locked?
|
||||
|
||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||
return @error = {msg: "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码", id: 'account'} if login_control.forbid?
|
||||
|
||||
password_ok = @user.check_password?(params[:password].to_s)
|
||||
unless password_ok
|
||||
if login_control.remain_times-1 == 0
|
||||
@error = {msg: "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码", id: 'account'}
|
||||
else
|
||||
@error = {msg: "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会", id: 'account'}
|
||||
end
|
||||
login_control.increment!
|
||||
return
|
||||
end
|
||||
login_control.clear
|
||||
redirect_to params[:call_url] + "&auth=" + @user.login
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
class Projects::ProjectInviteLinksController < Projects::BaseController
|
||||
before_action :require_manager!, except: [:show_link, :redirect_link]
|
||||
before_action :require_login
|
||||
|
||||
def current_link
|
||||
role = params[:role]
|
||||
is_apply = params[:is_apply]
|
||||
return render_error('请输入正确的参数!') unless role.present? && is_apply.present?
|
||||
@project_invite_link = ProjectInviteLink.find_by(user_id: current_user.id, project_id: @project.id, role: role, is_apply: is_apply)
|
||||
@project_invite_link = ProjectInviteLink.build!(@project, current_user, role, is_apply) unless @project_invite_link.present?
|
||||
end
|
||||
|
||||
def generate_link
|
||||
ActiveRecord::Base.transaction do
|
||||
params_data = link_params.merge({user_id: current_user.id, project_id: @project.id})
|
||||
Projects::ProjectInviteLinks::CreateForm.new(params_data).validate!
|
||||
@project_invite_link = ProjectInviteLink.build!(project, user, params_data[:role], params_data[:is_apply])
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show_link
|
||||
@project_invite_link = ProjectInviteLink.find_by(sign: params[:invite_sign])
|
||||
return render_not_found unless @project_invite_link.present?
|
||||
end
|
||||
|
||||
def redirect_link
|
||||
Projects::LinkJoinService.call(current_user, @project, params[:invite_sign])
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
normal_status(-1, e.message)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def link_params
|
||||
params.require(:project_invite_link).permit(:role, :is_apply)
|
||||
end
|
||||
end
|
|
@ -56,7 +56,12 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
if params[:fork_project_id].present?
|
||||
fork_project= Project.find_by(id: params[:fork_project_id])
|
||||
return normal_status(-1, "您不是源项目开发者,没有权限,请联系源项目管理员.") unless fork_project && fork_project.operator?(current_user)
|
||||
else
|
||||
return normal_status(-1, "您不是项目开发者,没有权限,请联系项目管理员.") unless @project.operator?(current_user)
|
||||
end
|
||||
ActiveRecord::Base.transaction do
|
||||
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
|
@ -176,6 +181,7 @@ class PullRequestsController < ApplicationController
|
|||
@issue_assign_to = @issue.get_assign_user
|
||||
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
||||
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||
@last_review = @pull_request.issue.reviews.take
|
||||
end
|
||||
|
||||
def pr_merge
|
||||
|
|
|
@ -9,7 +9,7 @@ class RepositoriesController < ApplicationController
|
|||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts files archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
|
@ -54,7 +54,7 @@ class RepositoriesController < ApplicationController
|
|||
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}/"
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -99,7 +99,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
else
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
|
@ -222,7 +222,7 @@ class RepositoriesController < ApplicationController
|
|||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
end
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
|
@ -240,8 +240,8 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
|
@ -253,8 +253,8 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
class ReviewsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :load_pull_request
|
||||
|
||||
def create
|
||||
return render_forbidden('您不是审查人员,无法进行审查!') if current_user&.id != @pull_request.issue.assigned_to_id
|
||||
@journal, @review = Api::V1::Projects::PullRequests::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
|
||||
end
|
||||
|
||||
private
|
||||
def review_params
|
||||
params.require(:review).permit(:content, :commit_id, :status)
|
||||
end
|
||||
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
end
|
|
@ -69,12 +69,18 @@ class Traces::ProjectsController < Traces::BaseController
|
|||
|
||||
|
||||
def task_pdf
|
||||
return render_error("task_id错误") if params[:task_id].blank?
|
||||
result = Trace::PdfReportService.call(current_user.trace_token, params[:task_id])
|
||||
if result.is_a?(Hash) && result[:code] == 200
|
||||
redirect_to result[:download_url]
|
||||
task_id = params[:task_id]
|
||||
return render_error("task_id错误") if task_id.blank?
|
||||
file_save_path = "public/trace_task_results/#{task_id}/report.pdf"
|
||||
if File.exists?(file_save_path)
|
||||
redirect_to "/trace_task_results/#{task_id}/report.pdf"
|
||||
else
|
||||
render_error("下载报告失败!")
|
||||
result = Trace::PdfReportService.call(current_user.trace_token, task_id)
|
||||
if result.is_a?(Hash) && result[:code] == 200
|
||||
redirect_to result[:download_url]
|
||||
else
|
||||
render_error("下载报告失败!")
|
||||
end
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
|
|
|
@ -100,7 +100,7 @@ class UsersController < ApplicationController
|
|||
|
||||
def get_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
# return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||
end
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Trustie API Reference
|
||||
title: GitLink API Reference
|
||||
|
||||
language_tabs: # must be one of https://git.io/vQNgJ
|
||||
- shell: Shell
|
||||
- javascript: JavaScript
|
||||
|
||||
toc_footers:
|
||||
- <a href='https://www.trustie.net/login?login=false'>Sign Up for a User</a>
|
||||
- <a href='https://www.trustie.net'>Powered by Trustie</a>
|
||||
- <a href='https://www.gitlink.org.cn/login'>Sign In for a User</a>
|
||||
- <a href='https://www.gitlink.org.cn'>Powered by GitLink</a>
|
||||
|
||||
includes:
|
||||
- licenses
|
||||
|
@ -31,8 +31,8 @@ code_clipboard: true
|
|||
|
||||
# Introduction
|
||||
|
||||
Welcome to the Trustie API! You can use our API to access Trustie API endpoints, which can get information on projects, repository, and users in our platform.
|
||||
Welcome to the GitLink API! You can use our API to access GitLink API endpoints, which can get information on projects, repository, and users in our platform.
|
||||
|
||||
We have language bindings in Shell,avaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
|
||||
|
||||
This example API documentation page was created with [Trustie](https://www.trustie.net). Feel free to edit it and use it as a base for your own API's documentation.
|
||||
This example API documentation page was created with [GitLink](https://www.gitlink.org.cn). Feel free to edit it and use it as a base for your own API's documentation.
|
||||
|
|
|
@ -1,4 +1,278 @@
|
|||
# Projects
|
||||
## 获取项目邀请链接(项目管理员)
|
||||
当前登录(管理员)用户获取项目邀请链接的接口(第一次请求会默认生成role类型为developer和is_apply为true的链接)
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/current_link.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/kellect/project_invite_links/current_link.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/project_invite_links/current_link.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||
|is_apply |是| |boolean |是否需要审核 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
## 生成项目邀请链接(项目管理员)
|
||||
当前登录(管理员)用户生成的项目邀请链接,可选role和is_apply参数
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/generate_link.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/generate_link.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/generate_link.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||
|is_apply |是| |boolean |是否需要审核 |
|
||||
|
||||
|
||||
> 请求的JSON示例
|
||||
|
||||
```json
|
||||
{
|
||||
"role": "developer",
|
||||
"is_apply": false
|
||||
}
|
||||
```
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 获取邀请链接信息(被邀请用户)
|
||||
用户请求邀请链接时,通过该接口来获取链接的信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/show_link.json?invite_sign=xxx`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 接受项目邀请链接(被邀请用户)
|
||||
当前登录(非项目)用户加入项目的接口,如果项目链接不需要审核,请求成功后即加入项目,如果需要审核,那么会提交一个申请,需要项目管理员审核
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/redirect_link.json?invite_sign=xxx`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
## 申请加入项目
|
||||
申请加入项目
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,6 +47,105 @@ await octokit.request('GET /api/users/me.json')
|
|||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 用户项目列表
|
||||
获取用户项目列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/v1/:login/projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/v1/:login/projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/v1/yystopf/projects.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login | string | 用户的用户名|
|
||||
|category | string | 归属项目,默认为全部项目, join: 参与项目, created: 创建项目, manage: 管理项目, watched: 关注项目, forked: 复刻项目 |
|
||||
|is_public | boolean | 公/私有项目,true为公开项目,false为私有项目|
|
||||
|project_type | string | 项目类型,common为托管项目, mirror为镜像项目, sync_mirror为同步镜像项目|
|
||||
|sort_by | string | 项目的排序字段,比如 created_on, updated_on等|
|
||||
|sort_direction | string | 排序的类型,desc 倒序,asc 正序|
|
||||
|limit | integer | 每页个数 |
|
||||
|page | integer | 页码 |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|total_count | integer | 项目总数 |
|
||||
|projects.owner.id | integer | 项目拥有者id |
|
||||
|projects.owner.type | string | 项目拥有者类型,User 用户,Organization 组织 |
|
||||
|projects.owner.name | string | 项目拥有者名称|
|
||||
|projects.owner.login | string | 项目拥有者用户名 |
|
||||
|projects.owner.image_url | string | 项目拥有者头像地址 |
|
||||
|type | string | 项目类型,common 托管项目,mirror 镜像项目, sync 同步镜像项目 |
|
||||
|description | string | 项目描述 |
|
||||
|forked_count | integer | 项目复刻数量 |
|
||||
|forked_from_project_id | integer | 项目复刻来源项目 |
|
||||
|identifier | string | 项目标识 |
|
||||
|issues_count | integer | 项目issues数量|
|
||||
|pull_requests_count | integer | 项目合并请求数量 |
|
||||
|invite_code | string | 项目邀请码|
|
||||
|website | string | 项目网址|
|
||||
|platform | string | 项目平台 |
|
||||
|name | string | 项目名称|
|
||||
|open_devops | boolean | 项目是否开启工作流 |
|
||||
|praises_count | integer | 项目点赞数量|
|
||||
|is_public | boolean | 项目是否公开|
|
||||
|status | integer | 项目状态|
|
||||
|watchers_count | integer | 项目关注数量|
|
||||
|ignore_id | integer | 项目ignoreID|
|
||||
|license_id | integer | 项目许可证ID|
|
||||
|project_category_id | integer | 项目分类ID|
|
||||
|project_language_id | integer | 项目语言ID|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
"total_count": 1,
|
||||
"projects": [
|
||||
{
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"type": "common",
|
||||
"description": null,
|
||||
"forked_count": 1,
|
||||
"forked_from_project_id": null,
|
||||
"identifier": "hahahah",
|
||||
"issues_count": 5,
|
||||
"pull_requests_count": 3,
|
||||
"invite_code": "8zfKtM",
|
||||
"website": null,
|
||||
"platform": "forge",
|
||||
"name": "hahahah",
|
||||
"open_devops": false,
|
||||
"praises_count": 0,
|
||||
"is_public": true,
|
||||
"status": 1,
|
||||
"watchers_count": 0,
|
||||
"ignore_id": null,
|
||||
"license_id": null,
|
||||
"project_category_id": null,
|
||||
"project_language_id": null
|
||||
}
|
||||
]
|
||||
```
|
||||
<aside class="success">
|
||||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 用户消息列表
|
||||
获取用户消息列表
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
class Projects::ProjectInviteLinks::CreateForm < BaseForm
|
||||
attr_accessor :user_id, :project_id, :role, :is_apply
|
||||
|
||||
validates :user_id, :project_id, :role, presence: true
|
||||
validates :role, inclusion: { in: %w(manager developer reporter), message: "请输入正确的权限." }
|
||||
validates :is_apply, inclusion: {in: [true, false], message: "请输入是否需要管理员审核."}
|
||||
end
|
||||
|
|
@ -30,7 +30,7 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def gitea_domain
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def find_user_by_login_or_mail(identifier)
|
||||
|
|
|
@ -1,218 +1,217 @@
|
|||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
def render_decode64_content(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
||||
end
|
||||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
||||
if author_json["id"].present?
|
||||
return find_user_by_gitea_uid author_json['id']
|
||||
end
|
||||
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
||||
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
if author_json["Name"].present? && author_json["Email"].present?
|
||||
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
||||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
|
||||
if image_type?(ext) || download_type(ext)
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub(s[0], "/#{s_content}")
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
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
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
||||
end
|
||||
if download_type(file_type)
|
||||
return entry['content']
|
||||
end
|
||||
render_decode64_content(entry['content'])
|
||||
end
|
||||
end
|
||||
|
||||
def base64_to_image(path, content)
|
||||
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
||||
content = Base64.decode64(content)
|
||||
File.open(path, 'wb') { |f| f.write(content) }
|
||||
end
|
||||
|
||||
def render_download_image_url(dir_path, file_path, content)
|
||||
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
||||
file_name = full_path.split("/")[-1]
|
||||
# 用户名/项目标识/文件路径
|
||||
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
||||
|
||||
file_path = [dir_path, file_name].join('/')
|
||||
|
||||
puts "##### render_download_image_url file_path: #{file_path}"
|
||||
base64_to_image(file_path, content)
|
||||
file_path = file_path[6..-1]
|
||||
File.join(base_url, file_path)
|
||||
end
|
||||
|
||||
def generate_dir_path(dir_path)
|
||||
# tmp_dir_path
|
||||
# eg: jasder/forgeplus/raw/branch/ref
|
||||
dir_path = ["public", tmp_dir, dir_path].join('/')
|
||||
puts "#### dir_path: #{dir_path}"
|
||||
unless Dir.exists?(dir_path)
|
||||
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
||||
end
|
||||
dir_path
|
||||
end
|
||||
|
||||
def tmp_dir
|
||||
"repo"
|
||||
end
|
||||
|
||||
end
|
||||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
def render_decode64_content(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
||||
end
|
||||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv apk)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
||||
if author_json["id"].present?
|
||||
return find_user_by_gitea_uid author_json['id']
|
||||
end
|
||||
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
||||
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
if author_json["Name"].present? && author_json["Email"].present?
|
||||
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
||||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
if (image_type?(ext) || download_type(ext)) && !ext.blank?
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub('('+s[0]+')', '('+"/#{s_content}"+')')
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
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
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
||||
end
|
||||
if download_type(file_type)
|
||||
return entry['content']
|
||||
end
|
||||
render_decode64_content(entry['content'])
|
||||
end
|
||||
end
|
||||
|
||||
def base64_to_image(path, content)
|
||||
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
||||
content = Base64.decode64(content)
|
||||
File.open(path, 'wb') { |f| f.write(content) }
|
||||
end
|
||||
|
||||
def render_download_image_url(dir_path, file_path, content)
|
||||
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
||||
file_name = full_path.split("/")[-1]
|
||||
# 用户名/项目标识/文件路径
|
||||
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
||||
|
||||
file_path = [dir_path, file_name].join('/')
|
||||
|
||||
puts "##### render_download_image_url file_path: #{file_path}"
|
||||
base64_to_image(file_path, content)
|
||||
file_path = file_path[6..-1]
|
||||
File.join(base_url, file_path)
|
||||
end
|
||||
|
||||
def generate_dir_path(dir_path)
|
||||
# tmp_dir_path
|
||||
# eg: jasder/forgeplus/raw/branch/ref
|
||||
dir_path = ["public", tmp_dir, dir_path].join('/')
|
||||
puts "#### dir_path: #{dir_path}"
|
||||
unless Dir.exists?(dir_path)
|
||||
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
||||
end
|
||||
dir_path
|
||||
end
|
||||
|
||||
def tmp_dir
|
||||
"repo"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -44,8 +44,8 @@ module Gitea
|
|||
|
||||
def token
|
||||
{
|
||||
username: Gitea.gitea_config[:access_key_id],
|
||||
password: Gitea.gitea_config[:access_key_secret]
|
||||
username: GiteaService.gitea_config[:access_key_id],
|
||||
password: GiteaService.gitea_config[:access_key_secret]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,7 +37,7 @@ class Ci::Drone::Server
|
|||
|
||||
private
|
||||
def gitea_url
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def database_username
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module Gitea
|
||||
module GiteaService
|
||||
class << self
|
||||
def gitea_config
|
||||
gitea_config = {}
|
|
@ -2,24 +2,27 @@
|
|||
#
|
||||
# Table name: forge_applied_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_invite_link_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_project_invite_link_id (project_invite_link_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class AppliedProject < ApplicationRecord
|
||||
self.table_name = "forge_applied_projects"
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :project_invite_link, optional: true
|
||||
|
||||
has_many :applied_messages, as: :applied, dependent: :destroy
|
||||
# has_many :forge_activities, as: :forge_act, dependent: :destroy
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class CommitLog < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :repository
|
||||
|
||||
end
|
|
@ -69,6 +69,7 @@ class Issue < ApplicationRecord
|
|||
has_many :issue_tags, through: :issue_tags_relates
|
||||
has_many :issue_times, dependent: :destroy
|
||||
has_many :issue_depends, dependent: :destroy
|
||||
has_many :reviews, dependent: :destroy
|
||||
scope :issue_includes, ->{includes(:user)}
|
||||
scope :issue_many_includes, ->{includes(journals: :user)}
|
||||
scope :issue_issue, ->{where(issue_classify: [nil,"issue"])}
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
# parent_id :integer
|
||||
# comments_count :integer default("0")
|
||||
# reply_id :integer
|
||||
# review_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_journals_on_created_on (created_on)
|
||||
# index_journals_on_journalized_id (journalized_id)
|
||||
# index_journals_on_review_id (review_id)
|
||||
# index_journals_on_user_id (user_id)
|
||||
# journals_journalized_id (journalized_id,journalized_type)
|
||||
#
|
||||
|
|
|
@ -61,6 +61,7 @@ class MessageTemplate::CustomTip < MessageTemplate
|
|||
end
|
||||
title.gsub!('{platform}', PLATFORM)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
|
||||
return title, content
|
||||
rescue => e
|
||||
|
|
|
@ -125,6 +125,7 @@ class Project < ApplicationRecord
|
|||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
has_many :project_invite_links, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
|
@ -138,7 +139,7 @@ class Project < ApplicationRecord
|
|||
delegate :content, to: :project_detail, allow_nil: true
|
||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||
|
||||
validate :validate_sensitive_string
|
||||
validate :validate_sensitive_string, on: [:create, :update]
|
||||
|
||||
def self.all_visible(user_id=nil)
|
||||
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
|
||||
|
@ -184,7 +185,7 @@ class Project < ApplicationRecord
|
|||
forked_project = self.forked_from_project
|
||||
if forked_project.present?
|
||||
forked_project.decrement(:forked_count, 1)
|
||||
forked_project.save
|
||||
forked_project.update_column(:forked_count, forked_project.forked_count)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -373,7 +374,7 @@ class Project < ApplicationRecord
|
|||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Owner.find_by_login namespace_path
|
||||
user = Owner.new(login: namespace_path) if user.nil?
|
||||
user = User.new(login: namespace_path) if user.nil?
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
return nil if project.blank?
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_invite_links
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("4")
|
||||
# is_apply :boolean default("1")
|
||||
# sign :string(255)
|
||||
# expired_at :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_invite_links_on_project_id (project_id)
|
||||
# index_project_invite_links_on_sign (sign)
|
||||
# index_project_invite_links_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class ProjectInviteLink < ApplicationRecord
|
||||
|
||||
default_scope { where("expired_at > ?", Time.now).or(where(expired_at: nil)) }
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
has_many :applied_projects
|
||||
|
||||
scope :with_project_id, -> (project_id) {where(project_id: project_id)}
|
||||
scope :with_user_id, -> (user_id) {where(user_id: user_id)}
|
||||
|
||||
enum role: {manager: 3, developer: 4, reporter: 5}
|
||||
|
||||
before_create :set_old_data_expired_at
|
||||
|
||||
def self.random_hex_sign
|
||||
hex = (SecureRandom.hex(32))
|
||||
return hex unless ProjectInviteLink.where(sign: hex).exists?
|
||||
end
|
||||
|
||||
def self.build!(project, user, role="developer", is_apply=true)
|
||||
self.create!(
|
||||
project_id: project&.id,
|
||||
user_id: user&.id,
|
||||
role: role,
|
||||
is_apply: is_apply,
|
||||
sign: random_hex_sign,
|
||||
expired_at: Time.now + 3.days
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def set_old_data_expired_at
|
||||
ProjectInviteLink.where(user_id: self.user_id, project_id: self.project, role: self.role, is_apply: self.is_apply).update_all(expired_at: Time.now)
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -14,6 +14,7 @@
|
|||
#
|
||||
|
||||
class ProjectUnit < ApplicationRecord
|
||||
|
||||
belongs_to :project
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: reviews
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# issue_id :integer
|
||||
# reviewer_id :integer
|
||||
# content :text(65535)
|
||||
# commit_id :string(255)
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_reviews_on_issue_id (issue_id)
|
||||
# index_reviews_on_reviewer_id (reviewer_id)
|
||||
#
|
||||
|
||||
class Review < ApplicationRecord
|
||||
|
||||
belongs_to :issue
|
||||
belongs_to :reviewer, class_name: 'User', foreign_key: :reviewer_id
|
||||
has_one :journal, dependent: :destroy
|
||||
|
||||
enum status: {common: 0, approved: 1, rejected: 2}
|
||||
end
|
|
@ -181,7 +181,7 @@ class User < Owner
|
|||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||
scope :like, lambda { |keywords|
|
||||
sql = "CONCAT(lastname, firstname) LIKE :search OR nickname LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search"
|
||||
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||
where(sql, :search => "%#{keywords.strip}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
scope :simple_select, -> {select(:id, :login, :lastname,:firstname, :nickname, :gitea_uid, :type)}
|
||||
|
@ -567,7 +567,8 @@ class User < Owner
|
|||
return '游客' unless logged?
|
||||
name = lastname + firstname
|
||||
name = name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
# name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
name.strip
|
||||
end
|
||||
|
||||
def only_real_name
|
||||
|
@ -684,6 +685,21 @@ class User < Owner
|
|||
raise text
|
||||
end
|
||||
|
||||
def self.authenticate!(login, password)
|
||||
user = self.where("login = ? or mail = ? or phone = ? ", login.to_s.gsub(" ",''),login.to_s.gsub(" ",''),login.downcase.to_s.gsub(" ",'')).limit(1).first
|
||||
return (user.check_password?(password) ? user : nil) unless user.nil?
|
||||
nil
|
||||
end
|
||||
|
||||
# Generate public/private keys
|
||||
def generate_keys
|
||||
key_size = (Rails.env == 'test' ? 512 : 2048)
|
||||
|
||||
serialized_private_key = OpenSSL::PKey::RSA::generate(key_size).to_s
|
||||
serialized_public_key = OpenSSL::PKey::RSA.new(serialized_private_key)
|
||||
[serialized_private_key, serialized_public_key]
|
||||
end
|
||||
|
||||
def show_real_name
|
||||
name = lastname + firstname
|
||||
if name.blank?
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
class Api::V1::Projects::BlameService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :sha, :filepath, :owner, :repo, :token
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :sha, :filepath, presence: true
|
||||
|
||||
def initialize(project, sha, filepath, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@sha = sha
|
||||
@filepath = filepath
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token,
|
||||
sha: sha,
|
||||
filepath: filepath
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_blame_by_owner_repo(owner, repo, {query: request_params})
|
||||
raise Error, '获取项目blame失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
class Api::V1::Projects::Branches::AllListService < ApplicationService
|
||||
|
||||
attr_accessor :project, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, '获取所有分支失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
class Api::V1::Projects::Branches::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project, :token, :owner, :repo, :old_branch_name, :new_branch_name
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :new_branch_name, :old_branch_name, presence: true
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@new_branch_name = params[:new_branch_name]
|
||||
@old_branch_name = params[:old_branch_name]
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
|
||||
check_new_branch_exist
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
new_branch_name: new_branch_name,
|
||||
old_branch_name: old_branch_name,
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_branches_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil
|
||||
raise Error, '创建分支失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
|
||||
def check_new_branch_exist
|
||||
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
||||
raise Error, '分支已存在!' if result['branch_name'].include?(@new_branch_name)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
class Api::V1::Projects::Commits::DiffService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project, :sha, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :sha, presence: true
|
||||
|
||||
def initialize(project, sha, token = nil)
|
||||
@project = project
|
||||
@sha = sha
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_commits_diff_by_owner_repo_sha(owner, repo, sha, {query: request_params}) rescue nil
|
||||
raise Error, '获取提交对比失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
class Api::V1::Projects::Commits::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :sha, :page, :limit, :owner, :repo, :token
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@sha = params[:sha]
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
param = {
|
||||
access_token: token,
|
||||
page: page,
|
||||
limit: limit
|
||||
}
|
||||
param.merge!(sha: sha) if sha.present?
|
||||
|
||||
param
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_commits_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, '获取提交列表失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
class Api::V1::Projects::CompareService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
attr_reader :project, :from, :to, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :from, :to, presence: true
|
||||
|
||||
def initialize(project, from, to, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@from = from
|
||||
@to = to
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
load_gitea_data
|
||||
raise Error, '获取对比信息失败!' unless gitea_data.is_a?(Hash)
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_compare_by_owner_repo_from_to(owner, repo, from, to, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
class Api::V1::Projects::Contents::BatchCreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :owner, :repo, :token
|
||||
attr_reader :files, :author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :author_email, :committer_email, presence: true, format: { with: CustomRegexp::EMAIL }
|
||||
validates :author_name, :committer_name, presence: true, format: { with: /\A(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ }
|
||||
validates :author_timeunix, :committer_timeunix, presence: true
|
||||
validates :branch, presence: true
|
||||
validates :message, presence: true
|
||||
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
puts params
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
@files = params[:files]
|
||||
@author_email = params[:author_email]
|
||||
@author_name = params[:author_name]
|
||||
@author_timeunix = params[:author_timeunix]
|
||||
@branch = params[:branch]
|
||||
@committer_email = params[:committer_email]
|
||||
@committer_name = params[:committer_name]
|
||||
@committer_timeunix = params[:committer_timeunix]
|
||||
@message = params[:message]
|
||||
@new_branch = params[:new_branch]
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, '请输入正确的文件参数Files' unless valid_files?
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
check_branch_exist
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
files: files,
|
||||
header: {
|
||||
author: {
|
||||
email: author_email,
|
||||
name: author_name
|
||||
},
|
||||
committer: {
|
||||
email: committer_email,
|
||||
name: committer_name
|
||||
},
|
||||
dates: {
|
||||
author: Time.at(author_timeunix.to_i),
|
||||
committer: Time.at(committer_timeunix.to_i)
|
||||
},
|
||||
message: message,
|
||||
new_branch: new_branch,
|
||||
signoff: false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def valid_files?
|
||||
return false unless files.is_a?(Array) && !files.blank?
|
||||
files.each do |file|
|
||||
return false unless file.has_key?(:action_type) && file.has_key?(:content) && file.has_key?(:encoding) && file.has_key?(:file_path)
|
||||
end
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_contents_batch_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil
|
||||
raise Error, '创建文件失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
|
||||
def check_branch_exist
|
||||
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params} ) rescue nil
|
||||
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
||||
raise Error, '分支不存在!' unless result['branch_name'].include?(branch)
|
||||
raise Error, '分支已存在!' if result['branch_name'].include?(new_branch) && new_branch.nil?
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
class Api::V1::Projects::GetService < ApplicationService
|
||||
|
||||
attr_reader :project, :token, :owner, :repo
|
||||
attr_accessor :gitea_data, :gitea_branch_tag_count
|
||||
|
||||
def initialize(project, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
load_gitea_branch_tag_count
|
||||
|
||||
result_object
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def result_object
|
||||
{
|
||||
full_name: "#{owner}/#{repo}",
|
||||
owner: project&.owner,
|
||||
ssh_url: gitea_data["ssh_url"],
|
||||
clone_url: gitea_data["clone_url"],
|
||||
size: gitea_data["size"],
|
||||
default_branch: gitea_data["default_branch"],
|
||||
empty: gitea_data["empty"],
|
||||
branch_count: gitea_branch_tag_count["branch_count"],
|
||||
tag_count: gitea_branch_tag_count["tag_count"],
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
end
|
||||
|
||||
def load_gitea_branch_tag_count
|
||||
@gitea_branch_tag_count = $gitea_client.get_repos_branch_tag_count_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
class Api::V1::Projects::Git::BlobsService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project, :sha, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :sha, presence: :true
|
||||
|
||||
|
||||
def initialize(project, sha, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@sha = sha
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_git_blobs_by_owner_repo_sha(owner, repo, sha, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
class Api::V1::Projects::Git::TreesService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project, :token, :sha, :recursive, :page, :limit, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :sha, presence: :true
|
||||
validates :recursive, inclusion: {in: [nil, '', true, false]}
|
||||
|
||||
def initialize(project, sha, params, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
@sha = sha
|
||||
@recursive = params[:recursive]
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_query
|
||||
if recursive.present?
|
||||
{
|
||||
recursive: recursive,
|
||||
page: page,
|
||||
per_page: limit,
|
||||
access_token: token
|
||||
}
|
||||
else
|
||||
{
|
||||
page: page,
|
||||
per_page: limit,
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_git_trees_by_owner_repo_sha(owner, repo, sha, {query: request_query}) rescue nil
|
||||
raise Error, '获取文件树列表失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
class Api::V1::Projects::PullRequests::Reviews::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :pull_request, :issue, :status, :commit_id, :content, :current_user
|
||||
attr_accessor :review, :journal
|
||||
|
||||
validates :status, inclusion: { in: %w(common approved rejected), message: '请输入正确的Type'}
|
||||
|
||||
def initialize(project, pull_request, params, current_user)
|
||||
@project = project
|
||||
@pull_request = pull_request
|
||||
@issue = pull_request&.issue
|
||||
@status = params[:status]
|
||||
@commit_id = params[:commit_id]
|
||||
@content = params[:content]
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
ActiveRecord::Base.transaction do
|
||||
create_review
|
||||
create_journal
|
||||
end
|
||||
|
||||
return @journal, @review
|
||||
rescue
|
||||
raise Error, '服务器错误,请联系系统管理员!'
|
||||
end
|
||||
|
||||
private
|
||||
def create_review
|
||||
@review = issue.reviews.create!(status: status, content: content, commit_id: commit_id, reviewer_id: @current_user.id)
|
||||
end
|
||||
|
||||
def create_journal
|
||||
@journal = issue.journals.create!(notes: content, user_id: @current_user.id, review_id: @review.id)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
class Api::V1::Projects::Webhooks::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :token, :owner, :repo, :active, :branch_filter, :content_type, :url, :http_method, :secret, :events
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :url, format: { with: URI::regexp(%w[http https]), message: "请输入正确的地址" }
|
||||
validates :active, inclusion: {in: [true, false]}
|
||||
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
|
||||
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@active = params[:active]
|
||||
@branch_filter = params[:branch_filter]
|
||||
@content_type = params[:content_type]
|
||||
@url = params[:url]
|
||||
@http_method = params[:http_method]
|
||||
@secret = params[:secret]
|
||||
@events = params[:events]
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
begin
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
active: active,
|
||||
branch_filter: branch_filter,
|
||||
config: {
|
||||
content_type: content_type,
|
||||
url: url,
|
||||
http_method: http_method,
|
||||
secret: secret
|
||||
},
|
||||
events: events || [],
|
||||
type: 'gitea',
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_hooks_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
class Api::V1::Projects::Webhooks::DeleteService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.delete_repos_hooks_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
class Api::V1::Projects::Webhooks::GetService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
class Api::V1::Projects::Webhooks::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_hooktasks_by_owner_repo(owner, repo, id, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
class Api::V1::Projects::Webhooks::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
class Api::V1::Projects::Webhooks::TestsService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_hooks_tests_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
class Api::V1::Projects::Webhooks::UpdateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo, :active, :branch_filter, :content_type, :url, :http_method, :secret, :events
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :url, format: { with: URI::regexp(%w[http https]), message: "请输入正确的地址" }
|
||||
validates :active, inclusion: {in: [true, false]}
|
||||
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
|
||||
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
|
||||
|
||||
def initialize(project, id, params, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@active = params[:active]
|
||||
@branch_filter = params[:branch_filter]
|
||||
@content_type = params[:content_type]
|
||||
@url = params[:url]
|
||||
@http_method = params[:http_method]
|
||||
@secret = params[:secret]
|
||||
@events = params[:events]
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
begin
|
||||
excute_data_to_gitea
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
{
|
||||
access_token: token
|
||||
}
|
||||
end
|
||||
|
||||
def request_body
|
||||
{
|
||||
active: active,
|
||||
branch_filter: branch_filter,
|
||||
config: {
|
||||
content_type: content_type,
|
||||
url: url,
|
||||
http_method: http_method,
|
||||
secret: secret
|
||||
},
|
||||
events: events || [],
|
||||
type: 'gitea',
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.patch_repos_hooks_by_owner_repo_id(owner, repo, id, {body: request_body.to_json, query: request_params}) rescue nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,86 @@
|
|||
class Api::V1::Users::Projects::ListService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :observe_user, :category, :is_public, :project_type, :sort_by, :sort_direction, :search, :current_user
|
||||
attr_accessor :queried_projects
|
||||
|
||||
validates :category, inclusion: {in: %w(all join created manage watched forked), message: "请输入正确的Category"}
|
||||
validates :is_public, inclusion: {in: [true, false], message: '请输入正确的IsPublic'}, allow_nil: true
|
||||
validates :project_type, inclusion: {in: %w(common mirror sync_mirror), message: '请输入正确的ProjectType'}, allow_nil: true
|
||||
validates :sort_by, inclusion: {in: Project.column_names, message: '请输入正确的SortBy'}
|
||||
validates :sort_direction, inclusion: {in: %w(asc desc), message: '请输入正确的SortDirection'}
|
||||
|
||||
def initialize(observe_user, params, current_user=nil)
|
||||
@observe_user = observe_user
|
||||
@category = params[:category] || 'all'
|
||||
@is_public = params[:is_public]
|
||||
@project_type = params[:project_type]
|
||||
@sort_by = params[:sort_by] || 'updated_on'
|
||||
@sort_direction = params[:sort_direction] || 'desc'
|
||||
@search = params[:search]
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
begin
|
||||
project_query_data
|
||||
|
||||
queried_projects
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def project_query_data
|
||||
if current_user.admin?
|
||||
projects = Project
|
||||
else
|
||||
projects = Project.visible
|
||||
end
|
||||
|
||||
case category
|
||||
when 'join'
|
||||
normal_projects = projects.where.not(user_id: observe_user.id).members_projects(observe_user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}).to_sql
|
||||
projects = Project.from("( #{normal_projects} UNION #{org_projects} ) AS projects").distinct
|
||||
when 'created'
|
||||
projects = projects.where(user_id: observe_user.id)
|
||||
when 'manage'
|
||||
normal_projects = projects.joins(members: :roles).where(members: {user_id: observe_user.id}, roles: {name: 'Manager'}).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}, teams: {authorize: %w(owner admin)}).to_sql
|
||||
projects = Project.from("( #{normal_projects} UNION #{org_projects} ) AS projects").distinct
|
||||
when 'watched'
|
||||
projects = projects.where.not(user_id: observe_user.id).joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observe_user.id})
|
||||
when 'forked'
|
||||
fork_ids = observe_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)
|
||||
projects = projects.where(id: fork_ids)
|
||||
else
|
||||
normal_projects = projects.members_projects(observe_user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
end
|
||||
|
||||
unless is_public.nil?
|
||||
if is_public
|
||||
projects = projects.visible
|
||||
else
|
||||
projects = projects.is_private
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
projects = projects.with_project_type(project_type)
|
||||
|
||||
q = projects.ransack(name_or_identifier_cont: search)
|
||||
|
||||
scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users)
|
||||
|
||||
|
||||
scope = scope.order("projects.#{sort_by} #{sort_direction}")
|
||||
|
||||
@queried_projects = scope
|
||||
end
|
||||
|
||||
end
|
|
@ -81,7 +81,7 @@ class Educoder::ClientService < ApplicationService
|
|||
end
|
||||
|
||||
def access_key_secret
|
||||
Gitea.gitea_config[:access_key_secret]
|
||||
GiteaService.gitea_config[:access_key_secret]
|
||||
end
|
||||
|
||||
def api_url(url)
|
||||
|
|
|
@ -56,7 +56,7 @@ class Gitea::Accelerator::BaseService < ApplicationService
|
|||
end
|
||||
|
||||
def accelerator
|
||||
Gitea.gitea_config[:accelerator]
|
||||
GiteaService.gitea_config[:accelerator]
|
||||
end
|
||||
|
||||
def render_status(response)
|
||||
|
|
|
@ -96,11 +96,11 @@ class Gitea::ClientService < ApplicationService
|
|||
end
|
||||
|
||||
def base_url
|
||||
Gitea.gitea_config[:base_url]
|
||||
GiteaService.gitea_config[:base_url]
|
||||
end
|
||||
|
||||
def domain
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def api_url
|
||||
|
|
|
@ -14,8 +14,8 @@ class Gitea::User::DeleteService < Gitea::ClientService
|
|||
private
|
||||
def token
|
||||
{
|
||||
username: Gitea.gitea_config[:access_key_id],
|
||||
password: Gitea.gitea_config[:access_key_secret]
|
||||
username: GiteaService.gitea_config[:access_key_id],
|
||||
password: GiteaService.gitea_config[:access_key_secret]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class Gitea::User::UpdateService < Gitea::ClientService
|
|||
# source_id integer($int64)
|
||||
# website string
|
||||
|
||||
def initialize(edit_username, params={}, token={username: Gitea.gitea_config[:access_key_id], password: Gitea.gitea_config[:access_key_secret]})
|
||||
def initialize(edit_username, params={}, token={username: GiteaService.gitea_config[:access_key_id], password: GiteaService.gitea_config[:access_key_secret]})
|
||||
@token = token
|
||||
@params = params
|
||||
@edit_username = edit_username
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
class Projects::LinkJoinService < ApplicationService
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
attr_reader :user, :project, :invite_sign, :params
|
||||
|
||||
def initialize(user, project, invite_sign, params={})
|
||||
@user = user
|
||||
@project = project
|
||||
@invite_sign = invite_sign
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
ActiveRecord::Base.transaction do
|
||||
validate!
|
||||
if invite_link.is_apply
|
||||
# 如果需要申请才能加入,创建一条申请记录
|
||||
create_applied_project!
|
||||
else
|
||||
# 如果不需要申请,直接为项目添加该成员
|
||||
create_member!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, 'invite_sign必须存在!' if invite_sign.blank?
|
||||
raise Error, '邀请链接不存在!' unless invite_link.present?
|
||||
raise Error, '邀请链接已失效!' unless invite_user_in_project
|
||||
raise Error, '您已是仓库成员' if project.member?(user.id)
|
||||
raise Error, '您的申请管理员正在审核中,请勿重复申请!' if user.applied_projects.exists?(applied_project_params)
|
||||
end
|
||||
|
||||
def applied_project_params
|
||||
{
|
||||
status: 'common',
|
||||
project: project,
|
||||
role: role_value,
|
||||
project_invite_link_id: invite_link&.id
|
||||
}
|
||||
end
|
||||
|
||||
def create_applied_project!
|
||||
user.applied_projects.find_or_create_by!(status: 'common', project: project, role: role_value, project_invite_link_id: invite_link&.id)
|
||||
end
|
||||
|
||||
def create_member!
|
||||
Projects::AddMemberInteractor.call(project.owner, project, user, permission)
|
||||
end
|
||||
|
||||
def invite_link
|
||||
ProjectInviteLink.find_by(project_id: project.id, sign: invite_sign)
|
||||
end
|
||||
|
||||
def invite_user_in_project
|
||||
in_project = project.member?(invite_link.user)
|
||||
invite_link.update_column(:expired_at, Time.now) unless in_project
|
||||
in_project
|
||||
end
|
||||
|
||||
def role_value
|
||||
@_role ||=
|
||||
case invite_link&.role
|
||||
when 'manager' then 3
|
||||
when 'developer' then 4
|
||||
when 'reporter' then 5
|
||||
else
|
||||
5
|
||||
end
|
||||
end
|
||||
|
||||
def permission
|
||||
case invite_link&.role
|
||||
when 'manager'
|
||||
'admin'
|
||||
when 'developer'
|
||||
'write'
|
||||
when 'reporter'
|
||||
'read'
|
||||
else
|
||||
'read'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -63,7 +63,7 @@ class Repositories::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def remote_repository_url
|
||||
[Gitea.gitea_config[:domain], '/', user.login, '/', params[:identifier], ".git"].join("")
|
||||
[GiteaService.gitea_config[:domain], '/', user.login, '/', params[:identifier], ".git"].join("")
|
||||
end
|
||||
|
||||
def repository_params
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# 代码溯源 导出pdf
|
||||
require 'open-uri'
|
||||
require 'fileutils'
|
||||
require 'zip'
|
||||
|
||||
class Trace::PdfReportService < Trace::ClientService
|
||||
|
||||
|
@ -15,8 +16,16 @@ class Trace::PdfReportService < Trace::ClientService
|
|||
content = open("#{domain}#{base_url}#{url}?task_id=#{task_id}", "Authorization" => token)
|
||||
if content.is_a?(Tempfile)
|
||||
check_file_path
|
||||
IO.copy_stream(content, "#{save_path}/#{task_id}.pdf")
|
||||
return {code: 200, download_url: "/trace_task_results/#{task_id}.pdf"}
|
||||
IO.copy_stream(content, "#{save_path}/report.zip")
|
||||
Zip::File.open("#{save_path}/report.zip") do |zip_file|
|
||||
zip_file.each do |f|
|
||||
name = f.name.force_encoding('utf-8')
|
||||
next unless name == '/report.pdf'
|
||||
fpath = File.join(save_path, name)
|
||||
zip_file.extract(f, fpath)
|
||||
end
|
||||
end
|
||||
return {code: 200, download_url: "/trace_task_results/#{task_id}/report.pdf"}
|
||||
else
|
||||
return {code: 404}
|
||||
end
|
||||
|
@ -28,7 +37,7 @@ class Trace::PdfReportService < Trace::ClientService
|
|||
end
|
||||
|
||||
def save_path
|
||||
"public/trace_task_results"
|
||||
"public/trace_task_results/#{task_id}"
|
||||
end
|
||||
|
||||
def url
|
||||
|
|
|
@ -2,217 +2,57 @@
|
|||
<% add_admin_breadcrumb('概览', admins_path) %>
|
||||
<% end %>
|
||||
|
||||
<div class="header bg-gradient-primary pb-8 pt-md-8">
|
||||
<div class="container-fluid">
|
||||
<div class="header-body">
|
||||
<!-- Card stats -->
|
||||
<div class="row">
|
||||
<div class="col-xl-3 col-lg-6">
|
||||
<div class="card card-stats mb-4 mb-xl-0">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="card-title text-uppercase text-muted mb-0">当日活跃用户</h5>
|
||||
<span class="h2 font-weight-bold mb-0"><%= @active_user_count %></span>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="icon icon-shape rounded-circle shadow">
|
||||
<i class="fa fa-users"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
|
||||
<!-- <span class="text-success mr-2"><i class="fa fa-arrow-up"></i> 3.48%</span>-->
|
||||
<!-- <span class="text-nowrap">Since last month</span>-->
|
||||
<!-- </p>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6">
|
||||
<div class="card card-stats mb-4 mb-xl-0">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="card-title text-uppercase text-muted mb-0">7天内活跃用户数</h5>
|
||||
<span class="h2 font-weight-bold mb-0"><%= @weekly_active_user_count %></span>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="icon icon-shape rounded-circle shadow">
|
||||
<i class="fa fa-users"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
|
||||
<!-- <span class="text-danger mr-2"><i class="fas fa-arrow-down"></i> 3.48%</span>-->
|
||||
<!-- <span class="text-nowrap">Since last week</span>-->
|
||||
<!-- </p>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6">
|
||||
<div class="card card-stats mb-4 mb-xl-0">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="card-title text-uppercase text-muted mb-0">30天内活跃用户数</h5>
|
||||
<span class="h2 font-weight-bold mb-0"><%= @month_active_user_count %></span>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="icon icon-shape rounded-circle shadow">
|
||||
<i class="fa fa-users"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
|
||||
<!-- <span class="text-warning mr-2"><i class="fas fa-arrow-down"></i> 1.10%</span>-->
|
||||
<!-- <span class="text-nowrap">Since yesterday</span>-->
|
||||
<!-- </p>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6">
|
||||
<div class="card card-stats mb-4 mb-xl-0">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="card-title text-uppercase text-muted mb-0">30天内新增用户数</h5>
|
||||
<span class="h2 font-weight-bold mb-0"><%= @new_user_count %></span>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="icon icon-shape rounded-circle shadow">
|
||||
<i class="fa fa-user-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <p class="mt-3 mb-0 text-muted text-sm">-->
|
||||
<!-- <span class="text-success mr-2"><i class="fas fa-arrow-up"></i> 12%</span>-->
|
||||
<!-- <span class="text-nowrap">Since last month</span>-->
|
||||
<!-- </p>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box admin-list-container project-language-list-container">
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">指标名称</th>
|
||||
<th width="20%">当日数</th>
|
||||
<th width="20%">七日内</th>
|
||||
<th width="20%">30日内</th>
|
||||
<th width="20%">周用户留存率</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="">
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" style="font-size:14px;width:85px;padding: 0; height:36px;background-color:#5475fb;border-radius:4px;border-color: #5475fb;">活跃用户</button>
|
||||
</td>
|
||||
<td><%=@active_user_count %></td>
|
||||
<td><%=@weekly_active_user_count %></td>
|
||||
<td><%=@month_active_user_count %></td>
|
||||
<td><%="#{@weekly_keep_rate.to_f * 100 }%" %></td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" style="font-size:14px;width:85px;padding: 0; height:36px;background-color:#36cfc9;border-radius:4px; border-color: #36cfc9;">新注册用户</button>
|
||||
</td>
|
||||
<td><%=@day_new_user_count %></td>
|
||||
<td><%=@weekly_new_user_count %></td>
|
||||
<td><%=@month_new_user_count %></td>
|
||||
<td><%="--" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" style="font-size:14px;width:85px;padding: 0; height:36px;background-color:#f89422;border-radius:4px; border-color: #f89422;">活跃项目</button>
|
||||
</td>
|
||||
<td><%=@day_active_project_count %></td>
|
||||
<td><%=@weekly_active_project_count %></td>
|
||||
<td><%=@month_active_project_count %></td>
|
||||
<td><%="--" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" style="font-size:14px;width:85px;padding: 0; height:36px;background-color:#9d74ff;border-radius:4px; border-color: #9d74ff;">新增项目</button>
|
||||
</td>
|
||||
<td><%=@day_new_project_count %></td>
|
||||
<td><%=@weekly_new_project_count %></td>
|
||||
<td><%=@month_new_project_count %></td>
|
||||
<td><%="--" %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid mt--7 pie-statistic">
|
||||
<div class="row mt-5">
|
||||
<div class="col-xl-8 mb-5 mb-xl-0">
|
||||
<div class="card shadow">
|
||||
<!-- <div class="card-header border-0">-->
|
||||
<!-- <div class="row align-items-center">-->
|
||||
<!-- <h5 class="mb-0">近7天评测次数</h5>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="table-responsive">-->
|
||||
<!-- <div id="evaluate-pie" class="pie"></div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header border-0">
|
||||
<div class="row align-items-center">
|
||||
<h5 class="mb-0">30天内新增用户</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<div id="month-active-user" class="pie"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--<div class="container-fluid mt--7">-->
|
||||
<!-- <div class="row mt-5">-->
|
||||
<!-- <div class="col-xl-8 mb-5 mb-xl-0">-->
|
||||
<!-- <div class="card shadow">-->
|
||||
<!-- <div class="card-header border-0">-->
|
||||
<!-- <div class="row align-items-center">-->
|
||||
<!-- <div class="col">-->
|
||||
<!-- <h3 class="mb-0">Page visits</h3>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col text-right">-->
|
||||
<!-- <a href="#!" class="btn btn-sm btn-primary">Test</a>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="table-responsive">-->
|
||||
<!-- <table class="table align-items-center table-flush">-->
|
||||
<!-- <thead class="thead-light">-->
|
||||
<!-- <tr>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- </tr>-->
|
||||
<!-- </thead>-->
|
||||
<!-- <tbody>-->
|
||||
<%# 5.times do %>
|
||||
<!-- <tr>-->
|
||||
<!-- <th scope="row">/test/</th>-->
|
||||
<!-- <td>4,569</td>-->
|
||||
<!-- <td>340</td>-->
|
||||
<!-- <td>-->
|
||||
<!-- <i class="fas fa-arrow-up text-success mr-3"></i> 46,53%-->
|
||||
<!-- </td>-->
|
||||
<!-- </tr>-->
|
||||
<%# end %>
|
||||
<!-- </tbody>-->
|
||||
<!-- </table>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col-xl-4">-->
|
||||
<!-- <div class="card shadow">-->
|
||||
<!-- <div class="card-header border-0">-->
|
||||
<!-- <div class="row align-items-center">-->
|
||||
<!-- <div class="col">-->
|
||||
<!-- <h3 class="mb-0">Test</h3>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col text-right">-->
|
||||
<!-- <a href="#!" class="btn btn-sm btn-primary">Test</a>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="table-responsive">-->
|
||||
<!-- <table class="table align-items-center table-flush">-->
|
||||
<!-- <thead class="thead-light">-->
|
||||
<!-- <tr>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- <th scope="col">Test</th>-->
|
||||
<!-- <th scope="col"></th>-->
|
||||
<!-- </tr>-->
|
||||
<!-- </thead>-->
|
||||
<!-- <tbody>-->
|
||||
<%# 5.times do %>
|
||||
<!-- <tr>-->
|
||||
<!-- <th scope="row">-->
|
||||
<!-- Test-->
|
||||
<!-- </th>-->
|
||||
<!-- <td>-->
|
||||
<!-- 1,480-->
|
||||
<!-- </td>-->
|
||||
<!-- <td>-->
|
||||
<!-- <div class="d-flex align-items-center">-->
|
||||
<!-- <span class="mr-2">60%</span>-->
|
||||
<!-- <div>-->
|
||||
<!-- <div class="progress">-->
|
||||
<!-- <div class="progress-bar bg-gradient-danger" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"></div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </td>-->
|
||||
<!-- </tr>-->
|
||||
<%# end %>
|
||||
<!-- </tbody>-->
|
||||
<!-- </table>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
<div id="project-language-modals">
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
if project.present?
|
||||
json.type project.project_type
|
||||
json.(project,
|
||||
:description, :forked_count, :forked_from_project_id, :identifier,
|
||||
:issues_count, :pull_requests_count, :invite_code, :website, :platform,
|
||||
:name, :open_devops, :praises_count, :is_public, :status, :watchers_count,
|
||||
:ignore_id, :license_id, :project_category_id, :project_language_id)
|
||||
else
|
||||
json.nil!
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
json.file_nums diff['NumFiles']
|
||||
json.total_addition diff['TotalAddition']
|
||||
json.total_deletion diff['TotalDeletion']
|
||||
json.files diff['Files'].each do |file|
|
||||
json.name file['Name']
|
||||
json.oldname file['OldName']
|
||||
json.addition file['Addition']
|
||||
json.deletion file['Deletion']
|
||||
json.type file['Type']
|
||||
json.is_created file['IsCreated']
|
||||
json.is_deleted file['IsDeleted']
|
||||
json.is_bin file['IsBin']
|
||||
json.is_lfs_file file['IsLFSFile']
|
||||
json.is_renamed file['IsRenamed']
|
||||
json.is_ambiguous file['IsAmbiguous']
|
||||
json.is_submodule file['IsSubmodule']
|
||||
json.sections file['Sections'] do |section|
|
||||
json.file_name section['FileName']
|
||||
json.name section['Name']
|
||||
json.lines section['Lines'] do |line|
|
||||
json.left_index line['LeftIdx']
|
||||
json.right_index line['RightIdx']
|
||||
json.match line['Match']
|
||||
json.type line['Type']
|
||||
json.content line['Content']
|
||||
unless line['SectionInfo'].blank?
|
||||
json.section_path line['SectionInfo']['Path']
|
||||
json.section_last_left_index line['SectionInfo']['LastLeftIdx']
|
||||
json.section_last_right_index line['SectionInfo']['LastRightIdx']
|
||||
json.section_left_index line['SectionInfo']['LeftIdx']
|
||||
json.section_right_index line['SectionInfo']['RightIdx']
|
||||
json.section_left_hunk_size line['SectionInfo']['LeftHunkSize']
|
||||
json.section_right_hunk_size line['SectionInfo']['RightHunkSize']
|
||||
end
|
||||
end
|
||||
end
|
||||
json.is_incomplete file['IsIncomplete']
|
||||
json.is_incomplete_line_too_long file['IsIncompleteLineTooLong']
|
||||
json.is_protected file['IsProtected']
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
json.file_size @result_object['file_size']
|
||||
json.file_name @result_object['file_name']
|
||||
json.num_lines @result_object['num_lines']
|
||||
json.blame_parts @result_object['blame_parts'] do |part|
|
||||
json.commit do
|
||||
json.sha part['commit']['id']
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(part['commit']['author']), name: part['commit']['author']['Name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(part['commit']['commiter']), name: part['commit']['commiter']['Name'] }
|
||||
end
|
||||
json.commit_message part['commit']['commit_message']
|
||||
json.authored_time render_unix_time(part['commit']['authored_time'])
|
||||
json.committed_time render_unix_time(part['commit']['committed_time'])
|
||||
json.created_time render_unix_time(part['commit']['created_time'])
|
||||
end
|
||||
json.current_number part['current_number']
|
||||
json.effect_line part['effect_line']
|
||||
json.lines part['lines']
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
json.name branch
|
||||
json.http_url render_http_url(@project)
|
||||
json.zip_url render_zip_url(@owner, @project.repository, branch)
|
||||
json.tar_url render_tar_url(@owner, @project.repository, branch)
|
|
@ -0,0 +1,26 @@
|
|||
json.name branch['name']
|
||||
json.commit do
|
||||
json.id branch['commit']['id']
|
||||
json.message branch['commit']['message']
|
||||
json.author do
|
||||
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name'] }
|
||||
end
|
||||
json.time_ago time_from_now(branch['commit']['timestamp'].to_time)
|
||||
json.timestamp branch['commit']['timestamp']
|
||||
end
|
||||
|
||||
json.protected branch['protected']
|
||||
json.user_can_push branch['user_can_push']
|
||||
json.user_can_merge branch['user_can_merge']
|
||||
json.commit_id branch['commit_id']
|
||||
json.commit_time_from_now time_from_now(branch['commit_time'].to_time)
|
||||
json.commit_time branch['commit_time']
|
||||
json.default_branch branch['default_branch']
|
||||
json.http_url render_http_url(@project)
|
||||
json.zip_url render_zip_url(@owner, @project.repository, branch['name'])
|
||||
json.tar_url render_tar_url(@owner, @project.repository, branch['name'])
|
|
@ -0,0 +1,3 @@
|
|||
json.array! @result_object["branch_name"] do |branch|
|
||||
json.partial! "api/v1/projects/branches/simple_detail", branch: branch
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
json.partial! "api/v1/projects/branches/simple_gitea_detail", branch: @result_object
|
|
@ -0,0 +1,10 @@
|
|||
json.sha commit['sha']
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['author']), name: commit['author']['name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['committer']), name: commit['committer']['name'] }
|
||||
end
|
||||
json.commit_message commit['message']
|
||||
json.parent_shas commit['parents'].map{|x|x['sha']}
|
|
@ -0,0 +1 @@
|
|||
json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object
|
|
@ -0,0 +1,17 @@
|
|||
json.total_count @result_object[:total_data].to_i
|
||||
json.commits @result_object[:data].each do |commit|
|
||||
json.sha commit['sha']
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] }
|
||||
end
|
||||
json.commit_message commit['commit']['message']
|
||||
json.parent_shas commit['parents'].map{|x|x['sha']}
|
||||
json.files commit['files'].map{|f|f['filename']}
|
||||
json.commit_date commit['commit_date']
|
||||
json.commit_time render_unix_time(commit['commit']['committer']['date'])
|
||||
json.branch commit['branch']
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
json.commits_count @result_object['CommitsCount']
|
||||
json.last_commit_sha @result_object['LatestSha']
|
||||
json.commits @result_object['Commits'] do |commit|
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] }
|
||||
end
|
||||
json.branch commit['Branch']
|
||||
json.commit_message commit['CommitMessage']
|
||||
json.sha commit['Sha']
|
||||
json.parent_shas commit['Sha']['ParentShas']
|
||||
end
|
||||
json.diff do
|
||||
json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff']
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
json.commit do
|
||||
json.partial! "api/v1/projects/commits/simple_gitea_detail", commit: @result_object['commit']
|
||||
json.authored_time render_unix_time(@result_object['commit']['author']['date'])
|
||||
json.commited_time render_unix_time(@result_object['commit']['committer']['date'])
|
||||
end
|
||||
json.contents @result_object['contents'].each do |content|
|
||||
json.name content['name']
|
||||
json.path content['path']
|
||||
json.sha content['sha']
|
||||
json.type content['type']
|
||||
json.size content['size']
|
||||
json.encoding content['encoding']
|
||||
json.content content['content']
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
json.sha @result_object['sha']
|
||||
json.size @result_object['size']
|
||||
json.encoding @result_object['encoding']
|
||||
json.content @result_object['content']
|
|
@ -0,0 +1,9 @@
|
|||
json.total_count @result_object['total_count']
|
||||
json.sha @result_object['sha']
|
||||
json.entries @result_object['tree'].each do |entry|
|
||||
json.name entry['path']
|
||||
json.mode entry['mode']
|
||||
json.type entry['type'] === 'blob' ? 'file' : 'dir'
|
||||
json.size entry['size']
|
||||
json.sha entry['sha']
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
json.owner do
|
||||
json.partial! "api/v1/users/simple_user", user: @result_object[:owner]
|
||||
end
|
||||
json.(@result_object, :full_name, :ssh_url, :clone_url, :default_branch, :empty, :branch_count, :tag_count)
|
||||
json.partial! "api/v1/projects/simple_detail", project: @project
|
|
@ -0,0 +1,3 @@
|
|||
json.(webhook, :id, :url, :http_method, :is_active)
|
||||
json.last_status webhook.last_status
|
||||
json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")
|
|
@ -0,0 +1,8 @@
|
|||
json.id webhook["id"]
|
||||
json.content_type webhook['config']['content_type']
|
||||
json.http_method webhook['config']['http_method']
|
||||
json.url webhook['config']['url']
|
||||
json.events webhook['events']
|
||||
json.active webhook['active']
|
||||
json.branch_filter webhook['branch_filter']
|
||||
json.created_at format_time(webhook['created_at'].to_time)
|
|
@ -0,0 +1 @@
|
|||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
|
@ -0,0 +1,6 @@
|
|||
json.total_count @hooktasks.total_count
|
||||
json.hooktasks @hooktasks.each do |task|
|
||||
json.(task, :id, :event_type, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content)
|
||||
json.response_content task.response_content_json
|
||||
json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S")
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @webhooks.total_count
|
||||
json.webhooks @webhooks do |webhook|
|
||||
json.partial! "api/v1/projects/webhooks/simple_detail", webhook: webhook
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
|
@ -0,0 +1 @@
|
|||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
|
@ -0,0 +1,21 @@
|
|||
if user.present?
|
||||
if user.is_a?(Hash)
|
||||
json.id user["id"]
|
||||
json.login user["login"]
|
||||
json.name user["name"]
|
||||
json.type user["type"]
|
||||
json.image_url user["avatar_url"]
|
||||
else
|
||||
json.id user.id
|
||||
json.login user.login
|
||||
json.name user.real_name
|
||||
json.type user&.type
|
||||
json.image_url url_to_avatar(user)
|
||||
end
|
||||
else
|
||||
json.id nil
|
||||
json.login name
|
||||
json.name name
|
||||
json.type nil
|
||||
json.image_url User::Avatar.get_letter_avatar_url(name)
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
if user.present?
|
||||
json.id user.id
|
||||
json.type user.type
|
||||
json.name user.real_name
|
||||
json.login user.login
|
||||
json.image_url url_to_avatar(user)
|
||||
else
|
||||
json.nil!
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue