Compare commits

..

9 Commits

Author SHA1 Message Date
anph d76d85b8fb change 2023-10-07 15:09:30 +08:00
anph 82907e001f update 2023-09-22 21:10:33 +08:00
anph b8f9deb1ed GLCC 2023-08-15 00:15:10 +08:00
jasder 4fa10a3683 Merge pull request 'fix mege develop' (#248) from develop into master 2021-11-14 20:39:31 +08:00
jasder cb11a5c8e9 发布v3.1.1版本
* FIX 修复pulls、issues 搜索数量统计问题
* FIX 解决在线创建文件错误提示信息不准确的问题
* FIX table name bug
* FIX 解决applied_projects相关表操作的问题
* FIX 解决排序参数的判断预防SQL注入
* FIX 项目导航栏数量改为开启中的数量
* FIX 解决项目邀请码的索引查询问题
* FIX FIX get readme file bug
* FIX sql attack
* FIX projects load by invite code slowly
2021-06-18 17:09:57 +08:00
jasder c5d73b7cf8 v3.1.0
* 改版升级个人主页
* 修复bug
* 更改license
2021-06-09 09:52:57 +08:00
jasder 8a10a183e0 Merge branch 'develop' 2021-05-24 10:18:03 +08:00
jasder 6d1bcabd51 Merge branch 'master' of https://git.trustie.net/jasder/forgeplus 2021-05-24 10:10:24 +08:00
jasder 86f03ffafc Merge OK 2021-05-08 17:46:22 +08:00
576 changed files with 7035 additions and 23692 deletions

View File

@ -23,7 +23,7 @@
* Fix 版本库中附件下载400(#51625) * Fix 版本库中附件下载400(#51625)
* Fix loading页面优化(#51588) * Fix loading页面优化(#51588)
* Fix 提交详情页面优化(#51577) * Fix 提交详情页面优化(#51577)
* Fix 修复修复制功能(#51569) * Fix 修复修复制功能(#51569)
* Fix 修复新建发行版用户信息显示错误的问题(#51665) * Fix 修复新建发行版用户信息显示错误的问题(#51665)
* Fix 修复查看文件详细信息报错的问题(#51561) * Fix 修复查看文件详细信息报错的问题(#51561)
* Fix 修复提交记录中时间显示格式问题(#51526) * Fix 修复提交记录中时间显示格式问题(#51526)
@ -62,7 +62,7 @@
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08 ## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
* BUGFIXES * BUGFIXES
* Fix 解决修标题过长导致的排版问题(45469) * Fix 解决修标题过长导致的排版问题(45469)
* Fix 解决合并请求详情页面排版错误的问题(45457) * Fix 解决合并请求详情页面排版错误的问题(45457)
* FIX 解决转移仓库界面专有名词描述错误的问题(45455) * FIX 解决转移仓库界面专有名词描述错误的问题(45455)
* Fix 解决markdown格式文件自动生成数字排序的问题(45454) * Fix 解决markdown格式文件自动生成数字排序的问题(45454)

274
Gemfile
View File

@ -1,144 +1,130 @@
#source 'https://gems.ruby-china.com' source 'https://gems.ruby-china.com'
source 'https://mirrors.cloud.tencent.com/rubygems/' git_source(:github) { |repo| "https://github.com/#{repo}.git" }
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '~> 5.2.0'
gem 'rails', '~> 5.2.0' gem 'mysql2', '>= 0.4.4', '< 0.6.0'
gem 'mysql2', '>= 0.4.4', '< 0.6.0' gem 'puma', '~> 3.11'
gem 'puma', '~> 3.11' gem 'sass-rails', '~> 5.0'
gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0'
gem 'uglifier', '>= 1.3.0'
# gem 'coffee-rails', '~> 4.2'
# gem 'coffee-rails', '~> 4.2' gem 'turbolinks', '~> 5'
gem 'turbolinks', '~> 5' gem 'jbuilder', '~> 2.5'
gem 'jbuilder', '~> 2.5' gem 'groupdate', '~> 4.1.0'
gem 'groupdate', '~> 4.1.0' gem 'chartkick'
gem 'chartkick' gem 'grape-entity', '~> 0.7.1'
gem 'grape-entity', '~> 0.7.1' gem 'kaminari', '~> 1.1', '>= 1.1.1'
gem 'kaminari', '~> 1.1', '>= 1.1.1'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'bootsnap', '>= 1.1.0', require: false
gem 'chinese_pinyin'
gem 'chinese_pinyin'
gem 'rack-cors'
gem 'rack-cors' gem 'redis-rails'
gem 'redis-rails' gem 'roo-xls'
gem 'roo-xls' gem 'simple_xlsx_reader'
gem 'simple_xlsx_reader'
gem 'rubyzip'
gem 'rubyzip'
gem 'spreadsheet'
gem 'spreadsheet' gem 'ruby-ole'
gem 'ruby-ole' # 导出为xlsx
# 导出为xlsx gem 'axlsx', '~> 3.0.0.pre'
gem 'axlsx', '~> 3.0.0.pre' gem 'axlsx_rails', '~> 0.5.2'
gem 'axlsx_rails', '~> 0.5.2'
gem 'oauth2'
gem 'oauth2' #导出为pdf
#导出为pdf gem 'pdfkit'
gem 'pdfkit' gem 'wkhtmltopdf-binary'
gem 'wkhtmltopdf-binary' # gem 'request_store'
# gem 'request_store' #gem 'iconv'
#gem 'iconv' # markdown 转html
# markdown 转html gem 'redcarpet', '~> 3.4'
gem 'redcarpet', '~> 3.4'
gem 'rqrcode', '~> 0.10.1'
gem 'rqrcode', '~> 0.10.1' gem 'rqrcode_png'
gem 'rqrcode_png'
gem 'acts-as-taggable-on', '~> 6.0'
gem 'acts-as-taggable-on', '~> 6.0'
# a tree structure
# a tree structure gem 'ancestry'
gem 'ancestry' gem 'acts_as_list'
gem 'acts_as_list' gem 'omniauth-cas'
gem 'omniauth-cas'
# profiler Middleware
# profiler Middleware gem 'rack-mini-profiler'
gem 'rack-mini-profiler'
# object-based searching
# object-based searching gem 'ransack'
gem 'ransack'
group :development, :test do
group :development, :test do gem 'rspec-rails', '~> 3.8'
gem 'rspec-rails', '~> 3.8' end
end
group :development do
group :development do gem 'prettier'
gem 'prettier' gem 'rubocop', '~> 0.52.0'
gem 'rubocop', '~> 0.52.0' gem 'solargraph', '~> 0.38.0'
gem 'solargraph', '~> 0.38.0' gem 'awesome_print'
gem 'awesome_print' gem 'web-console', '>= 3.3.0'
gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2'
gem 'listen', '>= 3.0.5', '< 3.2' gem 'spring'
gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0'
gem 'spring-watcher-listen', '~> 2.0.0' gem "annotate", "~> 2.6.0"
gem "annotate", "~> 2.6.0" end
end
group :test do
group :test do gem 'capybara', '>= 2.15', '< 4.0'
gem 'capybara', '>= 2.15', '< 4.0' gem 'selenium-webdriver'
gem 'selenium-webdriver' gem 'chromedriver-helper'
gem 'chromedriver-helper' end
end
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
#编码检测
#编码检测 gem 'rchardet', '~> 1.8'
gem 'rchardet', '~> 1.8'
# http client
# http client gem 'faraday', '~> 0.15.4'
gem 'faraday', '~> 0.15.4'
# view
# view gem 'active_decorator'
gem 'active_decorator' gem 'bootstrap', '~> 4.3.1'
gem 'bootstrap', '~> 4.3.1' gem 'jquery-rails'
gem 'jquery-rails' gem 'simple_form'
gem 'simple_form' gem 'font-awesome-sass', '4.7.0'
gem 'font-awesome-sass', '4.7.0'
# i18n
# i18n gem 'rails-i18n', '~> 5.1'
gem 'rails-i18n', '~> 5.1'
# job
# job gem 'sidekiq'
gem 'sidekiq' gem 'sinatra'
gem 'sinatra' gem "sidekiq-cron", "~> 1.1"
gem "sidekiq-cron", "~> 1.1"
gem 'sidekiq-failures' # batch insert
gem 'bulk_insert'
# batch insert
gem 'bulk_insert' # elasticsearch
gem 'searchkick'
# elasticsearch
gem 'searchkick' gem 'aasm'
gem 'enumerize'
gem 'aasm'
gem 'enumerize' gem 'diffy'
gem 'diffy' gem 'deep_cloneable', '~> 3.0.0'
gem 'deep_cloneable', '~> 3.0.0' # oauth2
gem 'omniauth', '~> 1.9.0'
# oauth2 gem 'omniauth-oauth2', '~> 1.6.0'
gem 'omniauth', '~> 1.9.0'
gem 'omniauth-oauth2', '~> 1.6.0' # global var
gem "omniauth-github" gem 'request_store'
gem "omniauth-rails_csrf_protection"
gem 'omniauth-gitee', '~> 1.0.0' # 敏感词汇
gem "omniauth-wechat-oauth2" gem 'harmonious_dictionary', '~> 0.0.1'
# global var gem 'parallel', '~> 1.19', '>= 1.19.1'
gem 'request_store'
gem 'letter_avatar'
# 敏感词汇
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.6'

View File

@ -106,10 +106,6 @@ GEM
activerecord (>= 3.1.0, < 7) activerecord (>= 3.1.0, < 7)
diff-lcs (1.3) diff-lcs (1.3)
diffy (3.3.0) diffy (3.3.0)
doorkeeper (5.5.1)
railties (>= 5)
doorkeeper-jwt (0.4.1)
jwt (>= 2.1)
e2mmap (0.1.0) e2mmap (0.1.0)
elasticsearch (7.5.0) elasticsearch (7.5.0)
elasticsearch-api (= 7.5.0) elasticsearch-api (= 7.5.0)
@ -454,8 +450,6 @@ DEPENDENCIES
chromedriver-helper chromedriver-helper
deep_cloneable (~> 3.0.0) deep_cloneable (~> 3.0.0)
diffy diffy
doorkeeper
doorkeeper-jwt
enumerize enumerize
faraday (~> 0.15.4) faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0) font-awesome-sass (= 4.7.0)
@ -464,7 +458,6 @@ DEPENDENCIES
harmonious_dictionary (~> 0.0.1) harmonious_dictionary (~> 0.0.1)
jbuilder (~> 2.5) jbuilder (~> 2.5)
jquery-rails jquery-rails
jwt
kaminari (~> 1.1, >= 1.1.1) kaminari (~> 1.1, >= 1.1.1)
letter_avatar letter_avatar
listen (>= 3.0.5, < 3.2) listen (>= 3.0.5, < 3.2)

View File

@ -1,137 +1,136 @@
//= require rails-ujs //= require rails-ujs
//= require activestorage //= require activestorage
//= require turbolinks //= require turbolinks
//= require jquery3 //= require jquery3
//= require popper //= require popper
//= require bootstrap-sprockets //= require bootstrap-sprockets
//= require jquery.validate.min //= require jquery.validate.min
//= require additional-methods.min //= require additional-methods.min
//= require bootstrap-notify //= require bootstrap-notify
//= require jquery.cookie.min //= require jquery.cookie.min
//= require select2 //= require select2
//= require moment.min //= require moment.min
//= require jquery.cxselect //= require jquery.cxselect
//= require bootstrap-datepicker //= require bootstrap-datepicker
//= require bootstrap-datetimepicker //= require bootstrap-datetimepicker
//= require bootstrap.viewer //= require bootstrap.viewer
//= require bootstrap/bootstrap-toggle //= require jquery.mloading
//= require jquery.mloading //= require jquery-confirm.min
//= require jquery-confirm.min //= require common
//= require common
//= require echarts
//= require echarts //= require codemirror/lib/codemirror
//= require codemirror/lib/codemirror //= require codemirror/mode/shell/shell
//= require codemirror/mode/shell/shell //= require editormd/editormd
//= require editormd/editormd //= require editormd/languages/zh-tw
//= require editormd/languages/zh-tw //= require dragula/dragula
//= require dragula/dragula
//= require_tree ./i18n
//= require_tree ./i18n //= require_tree ./admins
//= require_tree ./admins
$.ajaxSetup({
$.ajaxSetup({ beforeSend: function(xhr) {
beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); }
} });
});
// ******** select2 global config ********
// ******** select2 global config ******** $.fn.select2.defaults.set('theme', 'bootstrap4');
$.fn.select2.defaults.set('theme', 'bootstrap4'); $.fn.select2.defaults.set('language', 'zh-CN');
$.fn.select2.defaults.set('language', 'zh-CN');
Turbolinks.setProgressBarDelay(200);
Turbolinks.setProgressBarDelay(200);
$.notifyDefaults({
$.notifyDefaults({ type: 'success',
type: 'success', z_index: 9999,
z_index: 9999, delay: 2000
delay: 2000 });
});
function show_success_flash(){
function show_success_flash(){ $.notify({
$.notify({ message: '操作成功'
message: '操作成功' },{
},{ type: 'success'
type: 'success' });
}); }
}
$(document).on('turbolinks:load', function(){
$(document).on('turbolinks:load', function(){ $('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' });
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' }); $('[data-toggle="popover"]').popover();
$('[data-toggle="popover"]').popover();
// 图片查看大图
// 图片查看大图 $('img.preview-image').bootstrapViewer();
$('img.preview-image').bootstrapViewer();
// flash alert提示框自动关闭
// flash alert提示框自动关闭 if($('.admin-alert-container .alert').length > 0){
if($('.admin-alert-container .alert').length > 0){ setTimeout(function(){
setTimeout(function(){ $('.admin-alert-container .alert:not(.alert-danger)').alert('close');
$('.admin-alert-container .alert:not(.alert-danger)').alert('close'); }, 2000);
}, 2000); setTimeout(function(){
setTimeout(function(){ $('.admin-alert-container .alert.alert-danger').alert('close');
$('.admin-alert-container .alert.alert-danger').alert('close'); }, 5000);
}, 5000); }
} });
});
$(document).on("turbolinks:before-cache", function () {
$(document).on("turbolinks:before-cache", function () { $('[data-toggle="tooltip"]').tooltip('hide');
$('[data-toggle="tooltip"]').tooltip('hide'); $('[data-toggle="popover"]').popover('hide');
$('[data-toggle="popover"]').popover('hide'); });
}); // var progressBar = new Turbolinks.ProgressBar();
// var progressBar = new Turbolinks.ProgressBar();
// $(document).on('ajax:send', function(event){
// $(document).on('ajax:send', function(event){ // console.log('ajax send', event);
// console.log('ajax send', event); // progressBar.setValue(0)
// progressBar.setValue(0) // progressBar.show()
// progressBar.show() // });
// }); //
// // $(document).on('ajax:complete', function(event){
// $(document).on('ajax:complete', function(event){ // console.log('ajax complete', event);
// console.log('ajax complete', event); // progressBar.setValue(1)
// progressBar.setValue(1) // progressBar.hide() // 分页时不触发,奇怪
// progressBar.hide() // 分页时不触发,奇怪 // });
// }); // $(document).on('ajax:success', function(event){
// $(document).on('ajax:success', function(event){ // console.log('ajax success', event);
// console.log('ajax success', event); // });
// }); // $(document).on('ajax:error', function(event){
// $(document).on('ajax:error', function(event){ // console.log('ajax error', event);
// console.log('ajax error', event); // });
// });
$(function () {
$(function () { });
});
$(document).on('turbolinks:load', function() {
$(document).on('turbolinks:load', function() {
$('.logo-item-left').on("change", 'input[type="file"]', function () {
$('.logo-item-left').on("change", 'input[type="file"]', function () { var $fileInput = $(this);
var $fileInput = $(this); var file = this.files[0];
var file = this.files[0]; var imageType = /image.*/;
var imageType = /image.*/; if (file && file.type.match(imageType)) {
if (file && file.type.match(imageType)) { var reader = new FileReader();
var reader = new FileReader(); reader.onload = function () {
reader.onload = function () { var $box = $fileInput.parent();
var $box = $fileInput.parent(); $box.find('img').attr('src', reader.result).css('display', 'block');
$box.find('img').attr('src', reader.result).css('display', 'block'); $box.addClass('has-img');
$box.addClass('has-img'); };
}; reader.readAsDataURL(file);
reader.readAsDataURL(file); } else {
} else { }
} });
});
$('.attachment-item-left').on("change", 'input[type="file"]', function () {
$('.attachment-item-left').on("change", 'input[type="file"]', function () { var $fileInput = $(this);
var $fileInput = $(this); var file = this.files[0];
var file = this.files[0]; var imageType = /image.*/;
var imageType = /image.*/; if (file && file.type.match(imageType)) {
if (file && file.type.match(imageType)) { var reader = new FileReader();
var reader = new FileReader(); reader.onload = function () {
reader.onload = function () { var $box = $fileInput.parent();
var $box = $fileInput.parent(); $box.find('img').attr('src', reader.result).css('display', 'block');
$box.find('img').attr('src', reader.result).css('display', 'block'); $box.addClass('has-img');
$box.addClass('has-img'); };
}; reader.readAsDataURL(file);
reader.readAsDataURL(file); } else {
} else { }
} });
});
}) })

View File

@ -1,180 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
+function ($) {
'use strict';
// TOGGLE PUBLIC CLASS DEFINITION
// ==============================
var Toggle = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, this.defaults(), options)
this.render()
}
Toggle.VERSION = '2.2.0'
Toggle.DEFAULTS = {
on: 'On',
off: 'Off',
onstyle: 'primary',
offstyle: 'default',
size: 'normal',
style: '',
width: null,
height: null
}
Toggle.prototype.defaults = function() {
return {
on: this.$element.attr('data-on') || Toggle.DEFAULTS.on,
off: this.$element.attr('data-off') || Toggle.DEFAULTS.off,
onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle,
offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle,
size: this.$element.attr('data-size') || Toggle.DEFAULTS.size,
style: this.$element.attr('data-style') || Toggle.DEFAULTS.style,
width: this.$element.attr('data-width') || Toggle.DEFAULTS.width,
height: this.$element.attr('data-height') || Toggle.DEFAULTS.height
}
}
Toggle.prototype.render = function () {
this._onstyle = 'btn-' + this.options.onstyle
this._offstyle = 'btn-' + this.options.offstyle
var size = this.options.size === 'large' ? 'btn-lg'
: this.options.size === 'small' ? 'btn-sm'
: this.options.size === 'mini' ? 'btn-xs'
: ''
var $toggleOn = $('<label class="btn">').html(this.options.on)
.addClass(this._onstyle + ' ' + size)
var $toggleOff = $('<label class="btn">').html(this.options.off)
.addClass(this._offstyle + ' ' + size + ' active')
var $toggleHandle = $('<span class="toggle-handle btn btn-default">')
.addClass(size)
var $toggleGroup = $('<div class="toggle-group">')
.append($toggleOn, $toggleOff, $toggleHandle)
var $toggle = $('<div class="toggle btn" data-toggle="toggle">')
.addClass( this.$element.prop('checked') ? this._onstyle : this._offstyle+' off' )
.addClass(size).addClass(this.options.style)
this.$element.wrap($toggle)
$.extend(this, {
$toggle: this.$element.parent(),
$toggleOn: $toggleOn,
$toggleOff: $toggleOff,
$toggleGroup: $toggleGroup
})
this.$toggle.append($toggleGroup)
var width = this.options.width || Math.max($toggleOn.outerWidth(), $toggleOff.outerWidth())+($toggleHandle.outerWidth()/2)
var height = this.options.height || Math.max($toggleOn.outerHeight(), $toggleOff.outerHeight())
$toggleOn.addClass('toggle-on')
$toggleOff.addClass('toggle-off')
this.$toggle.css({ width: width, height: height })
if (this.options.height) {
$toggleOn.css('line-height', $toggleOn.height() + 'px')
$toggleOff.css('line-height', $toggleOff.height() + 'px')
}
this.update(true)
this.trigger(true)
}
Toggle.prototype.toggle = function () {
if (this.$element.prop('checked')) this.off()
else this.on()
}
Toggle.prototype.on = function (silent) {
if (this.$element.prop('disabled')) return false
this.$toggle.removeClass(this._offstyle + ' off').addClass(this._onstyle)
this.$element.prop('checked', true)
if (!silent) this.trigger()
}
Toggle.prototype.off = function (silent) {
if (this.$element.prop('disabled')) return false
this.$toggle.removeClass(this._onstyle).addClass(this._offstyle + ' off')
this.$element.prop('checked', false)
if (!silent) this.trigger()
}
Toggle.prototype.enable = function () {
this.$toggle.removeAttr('disabled')
this.$element.prop('disabled', false)
}
Toggle.prototype.disable = function () {
this.$toggle.attr('disabled', 'disabled')
this.$element.prop('disabled', true)
}
Toggle.prototype.update = function (silent) {
if (this.$element.prop('disabled')) this.disable()
else this.enable()
if (this.$element.prop('checked')) this.on(silent)
else this.off(silent)
}
Toggle.prototype.trigger = function (silent) {
this.$element.off('change.bs.toggle')
if (!silent) this.$element.change()
this.$element.on('change.bs.toggle', $.proxy(function() {
this.update()
}, this))
}
Toggle.prototype.destroy = function() {
this.$element.off('change.bs.toggle')
this.$toggleGroup.remove()
this.$element.removeData('bs.toggle')
this.$element.unwrap()
}
// TOGGLE PLUGIN DEFINITION
// ========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.toggle')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.toggle', (data = new Toggle(this, options)))
if (typeof option == 'string' && data[option]) data[option]()
})
}
var old = $.fn.bootstrapToggle
$.fn.bootstrapToggle = Plugin
$.fn.bootstrapToggle.Constructor = Toggle
// TOGGLE NO CONFLICT
// ==================
$.fn.toggle.noConflict = function () {
$.fn.bootstrapToggle = old
return this
}
// TOGGLE DATA-API
// ===============
$(function() {
$('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle()
})
$(document).on('click.bs.toggle', 'div[data-toggle^=toggle]', function(e) {
var $checkbox = $(this).find('input[type=checkbox]')
$checkbox.bootstrapToggle('toggle')
e.preventDefault()
})
}(jQuery);

View File

@ -1,9 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
//# sourceMappingURL=bootstrap-toggle.min.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"bootstrap-toggle.min.js","sources":["bootstrap-toggle.js"],"names":["$","Plugin","option","this","each","$this","data","options","Toggle","element","$element","extend","defaults","render","VERSION","DEFAULTS","on","off","onstyle","offstyle","size","style","width","height","prototype","attr","_onstyle","_offstyle","$toggleOn","html","addClass","$toggleOff","$toggleHandle","$toggleGroup","append","$toggle","prop","wrap","parent","Math","max","outerWidth","outerHeight","css","update","trigger","toggle","silent","removeClass","enable","removeAttr","disable","change","proxy","destroy","remove","removeData","unwrap","old","fn","bootstrapToggle","Constructor","noConflict","document","e","$checkbox","find","preventDefault","jQuery"],"mappings":";;;;;;;CASE,SAAUA,GACV,YAoID,SAASC,GAAOC,GACf,MAAOC,MAAKC,KAAK,WAChB,GAAIC,GAAUL,EAAEG,MACZG,EAAUD,EAAMC,KAAK,aACrBC,EAA2B,gBAAVL,IAAsBA,CAEtCI,IAAMD,EAAMC,KAAK,YAAcA,EAAO,GAAIE,GAAOL,KAAMI,IACvC,gBAAVL,IAAsBI,EAAKJ,IAASI,EAAKJ,OAtItD,GAAIM,GAAS,SAAUC,EAASF,GAC/BJ,KAAKO,SAAYV,EAAES,GACnBN,KAAKI,QAAYP,EAAEW,UAAWR,KAAKS,WAAYL,GAC/CJ,KAAKU,SAGNL,GAAOM,QAAW,QAElBN,EAAOO,UACNC,GAAI,KACJC,IAAK,MACLC,QAAS,UACTC,SAAU,UACVC,KAAM,SACNC,MAAO,GACPC,MAAO,KACPC,OAAQ,MAGTf,EAAOgB,UAAUZ,SAAW,WAC3B,OACCI,GAAIb,KAAKO,SAASe,KAAK,YAAcjB,EAAOO,SAASC,GACrDC,IAAKd,KAAKO,SAASe,KAAK,aAAejB,EAAOO,SAASE,IACvDC,QAASf,KAAKO,SAASe,KAAK,iBAAmBjB,EAAOO,SAASG,QAC/DC,SAAUhB,KAAKO,SAASe,KAAK,kBAAoBjB,EAAOO,SAASI,SACjEC,KAAMjB,KAAKO,SAASe,KAAK,cAAgBjB,EAAOO,SAASK,KACzDC,MAAOlB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASM,MAC3DC,MAAOnB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASO,MAC3DC,OAAQpB,KAAKO,SAASe,KAAK,gBAAkBjB,EAAOO,SAASQ,SAI/Df,EAAOgB,UAAUX,OAAS,WACzBV,KAAKuB,SAAW,OAASvB,KAAKI,QAAQW,QACtCf,KAAKwB,UAAY,OAASxB,KAAKI,QAAQY,QACvC,IAAIC,GAA6B,UAAtBjB,KAAKI,QAAQa,KAAmB,SAClB,UAAtBjB,KAAKI,QAAQa,KAAmB,SACV,SAAtBjB,KAAKI,QAAQa,KAAkB,SAC/B,GACCQ,EAAY5B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQS,IACzDc,SAAS3B,KAAKuB,SAAW,IAAMN,GAC7BW,EAAa/B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQU,KAC1Da,SAAS3B,KAAKwB,UAAY,IAAMP,EAAO,WACrCY,EAAgBhC,EAAE,gDACpB8B,SAASV,GACPa,EAAejC,EAAE,8BACnBkC,OAAON,EAAWG,EAAYC,GAC5BG,EAAUnC,EAAE,iDACd8B,SAAU3B,KAAKO,SAAS0B,KAAK,WAAajC,KAAKuB,SAAWvB,KAAKwB,UAAU,QACzEG,SAASV,GAAMU,SAAS3B,KAAKI,QAAQc,MAEvClB,MAAKO,SAAS2B,KAAKF,GACnBnC,EAAEW,OAAOR,MACRgC,QAAShC,KAAKO,SAAS4B,SACvBV,UAAWA,EACXG,WAAYA,EACZE,aAAcA,IAEf9B,KAAKgC,QAAQD,OAAOD,EAEpB,IAAIX,GAAQnB,KAAKI,QAAQe,OAASiB,KAAKC,IAAIZ,EAAUa,aAAcV,EAAWU,cAAeT,EAAcS,aAAa,EACpHlB,EAASpB,KAAKI,QAAQgB,QAAUgB,KAAKC,IAAIZ,EAAUc,cAAeX,EAAWW,cACjFd,GAAUE,SAAS,aACnBC,EAAWD,SAAS,cACpB3B,KAAKgC,QAAQQ,KAAMrB,MAAOA,EAAOC,OAAQA,IACrCpB,KAAKI,QAAQgB,SAChBK,EAAUe,IAAI,cAAef,EAAUL,SAAW,MAClDQ,EAAWY,IAAI,cAAeZ,EAAWR,SAAW,OAErDpB,KAAKyC,QAAO,GACZzC,KAAK0C,SAAQ,IAGdrC,EAAOgB,UAAUsB,OAAS,WACrB3C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKc,MACnCd,KAAKa,MAGXR,EAAOgB,UAAUR,GAAK,SAAU+B,GAC/B,MAAI5C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQa,YAAY7C,KAAKwB,UAAY,QAAQG,SAAS3B,KAAKuB,UAChEvB,KAAKO,SAAS0B,KAAK,WAAW,QACzBW,GAAQ5C,KAAK0C,aAGnBrC,EAAOgB,UAAUP,IAAM,SAAU8B,GAChC,MAAI5C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQa,YAAY7C,KAAKuB,UAAUI,SAAS3B,KAAKwB,UAAY,QAClExB,KAAKO,SAAS0B,KAAK,WAAW,QACzBW,GAAQ5C,KAAK0C,aAGnBrC,EAAOgB,UAAUyB,OAAS,WACzB9C,KAAKgC,QAAQe,WAAW,YACxB/C,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAU2B,QAAU,WAC1BhD,KAAKgC,QAAQV,KAAK,WAAY,YAC9BtB,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAUoB,OAAS,SAAUG,GAC/B5C,KAAKO,SAAS0B,KAAK,YAAajC,KAAKgD,UACpChD,KAAK8C,SACN9C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKa,GAAG+B,GACtC5C,KAAKc,IAAI8B,IAGfvC,EAAOgB,UAAUqB,QAAU,SAAUE,GACpC5C,KAAKO,SAASO,IAAI,oBACb8B,GAAQ5C,KAAKO,SAAS0C,SAC3BjD,KAAKO,SAASM,GAAG,mBAAoBhB,EAAEqD,MAAM,WAC5ClD,KAAKyC,UACHzC,QAGJK,EAAOgB,UAAU8B,QAAU,WAC1BnD,KAAKO,SAASO,IAAI,oBAClBd,KAAK8B,aAAasB,SAClBpD,KAAKO,SAAS8C,WAAW,aACzBrD,KAAKO,SAAS+C,SAiBf,IAAIC,GAAM1D,EAAE2D,GAAGC,eAEf5D,GAAE2D,GAAGC,gBAA8B3D,EACnCD,EAAE2D,GAAGC,gBAAgBC,YAAcrD,EAKnCR,EAAE2D,GAAGb,OAAOgB,WAAa,WAExB,MADA9D,GAAE2D,GAAGC,gBAAkBF,EAChBvD,MAMRH,EAAE,WACDA,EAAE,6CAA6C4D,oBAGhD5D,EAAE+D,UAAU/C,GAAG,kBAAmB,2BAA4B,SAASgD,GACtE,GAAIC,GAAYjE,EAAEG,MAAM+D,KAAK,uBAC7BD,GAAUL,gBAAgB,UAC1BI,EAAEG,oBAGFC"}

View File

@ -1,180 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap2-toggle.js v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
+function ($) {
'use strict';
// TOGGLE PUBLIC CLASS DEFINITION
// ==============================
var Toggle = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, this.defaults(), options)
this.render()
}
Toggle.VERSION = '2.2.0'
Toggle.DEFAULTS = {
on: 'On',
off: 'Off',
onstyle: 'primary',
offstyle: 'default',
size: 'normal',
style: '',
width: null,
height: null
}
Toggle.prototype.defaults = function() {
return {
on: this.$element.attr('data-on') || Toggle.DEFAULTS.on,
off: this.$element.attr('data-off') || Toggle.DEFAULTS.off,
onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle,
offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle,
size: this.$element.attr('data-size') || Toggle.DEFAULTS.size,
style: this.$element.attr('data-style') || Toggle.DEFAULTS.style,
width: this.$element.attr('data-width') || Toggle.DEFAULTS.width,
height: this.$element.attr('data-height') || Toggle.DEFAULTS.height
}
}
Toggle.prototype.render = function () {
this._onstyle = 'btn-' + this.options.onstyle
this._offstyle = 'btn-' + this.options.offstyle
var size = this.options.size === 'large' ? 'btn-large'
: this.options.size === 'small' ? 'btn-small'
: this.options.size === 'mini' ? 'btn-mini'
: ''
var $toggleOn = $('<label class="btn">').html(this.options.on)
.addClass(this._onstyle + ' ' + size)
var $toggleOff = $('<label class="btn">').html(this.options.off)
.addClass(this._offstyle + ' ' + size + ' active')
var $toggleHandle = $('<span class="toggle-handle btn btn-default">')
.addClass(size)
var $toggleGroup = $('<div class="toggle-group">')
.append($toggleOn, $toggleOff, $toggleHandle)
var $toggle = $('<div class="toggle btn" data-toggle="toggle">')
.addClass( this.$element.prop('checked') ? this._onstyle : this._offstyle+' off' )
.addClass(size).addClass(this.options.style)
this.$element.wrap($toggle)
$.extend(this, {
$toggle: this.$element.parent(),
$toggleOn: $toggleOn,
$toggleOff: $toggleOff,
$toggleGroup: $toggleGroup
})
this.$toggle.append($toggleGroup)
var width = this.options.width || Math.max($toggleOn.width(), $toggleOff.width())+($toggleHandle.outerWidth()/2)
var height = this.options.height || Math.max($toggleOn.height(), $toggleOff.height())
$toggleOn.addClass('toggle-on')
$toggleOff.addClass('toggle-off')
this.$toggle.css({ width: width, height: height })
if (this.options.height) {
$toggleOn.css('line-height', $toggleOn.height() + 'px')
$toggleOff.css('line-height', $toggleOff.height() + 'px')
}
this.update(true)
this.trigger(true)
}
Toggle.prototype.toggle = function () {
if (this.$element.prop('checked')) this.off()
else this.on()
}
Toggle.prototype.on = function (silent) {
if (this.$element.prop('disabled')) return false
this.$toggle.removeClass(this._offstyle + ' off').addClass(this._onstyle)
this.$element.prop('checked', true)
if (!silent) this.trigger()
}
Toggle.prototype.off = function (silent) {
if (this.$element.prop('disabled')) return false
this.$toggle.removeClass(this._onstyle).addClass(this._offstyle + ' off')
this.$element.prop('checked', false)
if (!silent) this.trigger()
}
Toggle.prototype.enable = function () {
this.$toggle.removeAttr('disabled')
this.$element.prop('disabled', false)
}
Toggle.prototype.disable = function () {
this.$toggle.attr('disabled', 'disabled')
this.$element.prop('disabled', true)
}
Toggle.prototype.update = function (silent) {
if (this.$element.prop('disabled')) this.disable()
else this.enable()
if (this.$element.prop('checked')) this.on(silent)
else this.off(silent)
}
Toggle.prototype.trigger = function (silent) {
this.$element.off('change.bs.toggle')
if (!silent) this.$element.change()
this.$element.on('change.bs.toggle', $.proxy(function() {
this.update()
}, this))
}
Toggle.prototype.destroy = function() {
this.$element.off('change.bs.toggle')
this.$toggleGroup.remove()
this.$element.removeData('bs.toggle')
this.$element.unwrap()
}
// TOGGLE PLUGIN DEFINITION
// ========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.toggle')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.toggle', (data = new Toggle(this, options)))
if (typeof option == 'string' && data[option]) data[option]()
})
}
var old = $.fn.bootstrapToggle
$.fn.bootstrapToggle = Plugin
$.fn.bootstrapToggle.Constructor = Toggle
// TOGGLE NO CONFLICT
// ==================
$.fn.toggle.noConflict = function () {
$.fn.bootstrapToggle = old
return this
}
// TOGGLE DATA-API
// ===============
$(function() {
$('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle()
})
$(document).on('click.bs.toggle', 'div[data-toggle^=toggle]', function(e) {
var $checkbox = $(this).find('input[type=checkbox]')
$checkbox.bootstrapToggle('toggle')
e.preventDefault()
})
}(jQuery);

View File

@ -1,9 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap2-toggle.js v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-large":"small"===this.options.size?"btn-small":"mini"===this.options.size?"btn-mini":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.width(),d.width())+e.outerWidth()/2,i=this.options.height||Math.max(c.height(),d.height());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
//# sourceMappingURL=bootstrap2-toggle.min.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"bootstrap2-toggle.min.js","sources":["bootstrap2-toggle.js"],"names":["$","Plugin","option","this","each","$this","data","options","Toggle","element","$element","extend","defaults","render","VERSION","DEFAULTS","on","off","onstyle","offstyle","size","style","width","height","prototype","attr","_onstyle","_offstyle","$toggleOn","html","addClass","$toggleOff","$toggleHandle","$toggleGroup","append","$toggle","prop","wrap","parent","Math","max","outerWidth","css","update","trigger","toggle","silent","removeClass","enable","removeAttr","disable","change","proxy","destroy","remove","removeData","unwrap","old","fn","bootstrapToggle","Constructor","noConflict","document","e","$checkbox","find","preventDefault","jQuery"],"mappings":";;;;;;;CASE,SAAUA,GACV,YAoID,SAASC,GAAOC,GACf,MAAOC,MAAKC,KAAK,WAChB,GAAIC,GAAUL,EAAEG,MACZG,EAAUD,EAAMC,KAAK,aACrBC,EAA2B,gBAAVL,IAAsBA,CAEtCI,IAAMD,EAAMC,KAAK,YAAcA,EAAO,GAAIE,GAAOL,KAAMI,IACvC,gBAAVL,IAAsBI,EAAKJ,IAASI,EAAKJ,OAtItD,GAAIM,GAAS,SAAUC,EAASF,GAC/BJ,KAAKO,SAAYV,EAAES,GACnBN,KAAKI,QAAYP,EAAEW,UAAWR,KAAKS,WAAYL,GAC/CJ,KAAKU,SAGNL,GAAOM,QAAW,QAElBN,EAAOO,UACNC,GAAI,KACJC,IAAK,MACLC,QAAS,UACTC,SAAU,UACVC,KAAM,SACNC,MAAO,GACPC,MAAO,KACPC,OAAQ,MAGTf,EAAOgB,UAAUZ,SAAW,WAC3B,OACCI,GAAIb,KAAKO,SAASe,KAAK,YAAcjB,EAAOO,SAASC,GACrDC,IAAKd,KAAKO,SAASe,KAAK,aAAejB,EAAOO,SAASE,IACvDC,QAASf,KAAKO,SAASe,KAAK,iBAAmBjB,EAAOO,SAASG,QAC/DC,SAAUhB,KAAKO,SAASe,KAAK,kBAAoBjB,EAAOO,SAASI,SACjEC,KAAMjB,KAAKO,SAASe,KAAK,cAAgBjB,EAAOO,SAASK,KACzDC,MAAOlB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASM,MAC3DC,MAAOnB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASO,MAC3DC,OAAQpB,KAAKO,SAASe,KAAK,gBAAkBjB,EAAOO,SAASQ,SAI/Df,EAAOgB,UAAUX,OAAS,WACzBV,KAAKuB,SAAW,OAASvB,KAAKI,QAAQW,QACtCf,KAAKwB,UAAY,OAASxB,KAAKI,QAAQY,QACvC,IAAIC,GAA6B,UAAtBjB,KAAKI,QAAQa,KAAmB,YAClB,UAAtBjB,KAAKI,QAAQa,KAAmB,YACV,SAAtBjB,KAAKI,QAAQa,KAAkB,WAC/B,GACCQ,EAAY5B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQS,IACzDc,SAAS3B,KAAKuB,SAAW,IAAMN,GAC7BW,EAAa/B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQU,KAC1Da,SAAS3B,KAAKwB,UAAY,IAAMP,EAAO,WACrCY,EAAgBhC,EAAE,gDACpB8B,SAASV,GACPa,EAAejC,EAAE,8BACnBkC,OAAON,EAAWG,EAAYC,GAC5BG,EAAUnC,EAAE,iDACd8B,SAAU3B,KAAKO,SAAS0B,KAAK,WAAajC,KAAKuB,SAAWvB,KAAKwB,UAAU,QACzEG,SAASV,GAAMU,SAAS3B,KAAKI,QAAQc,MAEvClB,MAAKO,SAAS2B,KAAKF,GACnBnC,EAAEW,OAAOR,MACRgC,QAAShC,KAAKO,SAAS4B,SACvBV,UAAWA,EACXG,WAAYA,EACZE,aAAcA,IAEf9B,KAAKgC,QAAQD,OAAOD,EAEpB,IAAIX,GAAQnB,KAAKI,QAAQe,OAASiB,KAAKC,IAAIZ,EAAUN,QAASS,EAAWT,SAAUU,EAAcS,aAAa,EAC1GlB,EAASpB,KAAKI,QAAQgB,QAAUgB,KAAKC,IAAIZ,EAAUL,SAAUQ,EAAWR,SAC5EK,GAAUE,SAAS,aACnBC,EAAWD,SAAS,cACpB3B,KAAKgC,QAAQO,KAAMpB,MAAOA,EAAOC,OAAQA,IACrCpB,KAAKI,QAAQgB,SAChBK,EAAUc,IAAI,cAAed,EAAUL,SAAW,MAClDQ,EAAWW,IAAI,cAAeX,EAAWR,SAAW,OAErDpB,KAAKwC,QAAO,GACZxC,KAAKyC,SAAQ,IAGdpC,EAAOgB,UAAUqB,OAAS,WACrB1C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKc,MACnCd,KAAKa,MAGXR,EAAOgB,UAAUR,GAAK,SAAU8B,GAC/B,MAAI3C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQY,YAAY5C,KAAKwB,UAAY,QAAQG,SAAS3B,KAAKuB,UAChEvB,KAAKO,SAAS0B,KAAK,WAAW,QACzBU,GAAQ3C,KAAKyC,aAGnBpC,EAAOgB,UAAUP,IAAM,SAAU6B,GAChC,MAAI3C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQY,YAAY5C,KAAKuB,UAAUI,SAAS3B,KAAKwB,UAAY,QAClExB,KAAKO,SAAS0B,KAAK,WAAW,QACzBU,GAAQ3C,KAAKyC,aAGnBpC,EAAOgB,UAAUwB,OAAS,WACzB7C,KAAKgC,QAAQc,WAAW,YACxB9C,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAU0B,QAAU,WAC1B/C,KAAKgC,QAAQV,KAAK,WAAY,YAC9BtB,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAUmB,OAAS,SAAUG,GAC/B3C,KAAKO,SAAS0B,KAAK,YAAajC,KAAK+C,UACpC/C,KAAK6C,SACN7C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKa,GAAG8B,GACtC3C,KAAKc,IAAI6B,IAGftC,EAAOgB,UAAUoB,QAAU,SAAUE,GACpC3C,KAAKO,SAASO,IAAI,oBACb6B,GAAQ3C,KAAKO,SAASyC,SAC3BhD,KAAKO,SAASM,GAAG,mBAAoBhB,EAAEoD,MAAM,WAC5CjD,KAAKwC,UACHxC,QAGJK,EAAOgB,UAAU6B,QAAU,WAC1BlD,KAAKO,SAASO,IAAI,oBAClBd,KAAK8B,aAAaqB,SAClBnD,KAAKO,SAAS6C,WAAW,aACzBpD,KAAKO,SAAS8C,SAiBf,IAAIC,GAAMzD,EAAE0D,GAAGC,eAEf3D,GAAE0D,GAAGC,gBAA8B1D,EACnCD,EAAE0D,GAAGC,gBAAgBC,YAAcpD,EAKnCR,EAAE0D,GAAGb,OAAOgB,WAAa,WAExB,MADA7D,GAAE0D,GAAGC,gBAAkBF,EAChBtD,MAMRH,EAAE,WACDA,EAAE,6CAA6C2D,oBAGhD3D,EAAE8D,UAAU9C,GAAG,kBAAmB,2BAA4B,SAAS+C,GACtE,GAAIC,GAAYhE,EAAEG,MAAM8D,KAAK,uBAC7BD,GAAUL,gBAAgB,UAC1BI,EAAEG,oBAGFC"}

View File

@ -8,7 +8,6 @@
@import "jquery.mloading"; @import "jquery.mloading";
@import "jquery-confirm.min"; @import "jquery-confirm.min";
@import "bootstrap-datetimepicker.min"; @import "bootstrap-datetimepicker.min";
@import "bootstrap/bootstrap-toggle.min";
@import "codemirror/lib/codemirror"; @import "codemirror/lib/codemirror";
@import "editormd/css/editormd.min"; @import "editormd/css/editormd.min";
@ -204,14 +203,4 @@ input.form-control {
color: #23272B; color: #23272B;
font-size: 1rem; font-size: 1rem;
} }
}
.table th, .table td {
padding: 0.75rem 0.1rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
.table .thead-light th{
white-space: nowrap;
} }

View File

@ -1,83 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
.checkbox label .toggle,
.checkbox-inline .toggle {
margin-left: -20px;
margin-right: 5px;
}
.toggle {
position: relative;
overflow: hidden;
}
.toggle input[type="checkbox"] {
display: none;
}
.toggle-group {
position: absolute;
width: 200%;
top: 0;
bottom: 0;
left: 0;
transition: left 0.35s;
-webkit-transition: left 0.35s;
-moz-user-select: none;
-webkit-user-select: none;
}
.toggle.off .toggle-group {
left: -100%;
}
.toggle-on {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 50%;
margin: 0;
border: 0;
border-radius: 0;
}
.toggle-off {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
right: 0;
margin: 0;
border: 0;
border-radius: 0;
}
.toggle-handle {
position: relative;
margin: 0 auto;
padding-top: 0px;
padding-bottom: 0px;
height: 100%;
width: 0px;
border-width: 0 1px;
}
.toggle.btn { min-width: 59px; min-height: 34px; }
.toggle-on.btn { padding-right: 24px; }
.toggle-off.btn { padding-left: 24px; }
.toggle.btn-lg { min-width: 79px; min-height: 45px; }
.toggle-on.btn-lg { padding-right: 31px; }
.toggle-off.btn-lg { padding-left: 31px; }
.toggle-handle.btn-lg { width: 40px; }
.toggle.btn-sm { min-width: 50px; min-height: 30px;}
.toggle-on.btn-sm { padding-right: 20px; }
.toggle-off.btn-sm { padding-left: 20px; }
.toggle.btn-xs { min-width: 35px; min-height: 22px;}
.toggle-on.btn-xs { padding-right: 12px; }
.toggle-off.btn-xs { padding-left: 12px; }

View File

@ -1,28 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}
.toggle{position:relative;overflow:hidden}
.toggle input[type=checkbox]{display:none}
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
.toggle.off .toggle-group{left:-100%}
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
.toggle.btn{min-width:59px;min-height:34px}
.toggle-on.btn{padding-right:24px}
.toggle-off.btn{padding-left:24px}
.toggle.btn-lg{min-width:79px;min-height:45px}
.toggle-on.btn-lg{padding-right:31px}
.toggle-off.btn-lg{padding-left:31px}
.toggle-handle.btn-lg{width:40px}
.toggle.btn-sm{min-width:50px;min-height:30px}
.toggle-on.btn-sm{padding-right:20px}
.toggle-off.btn-sm{padding-left:20px}
.toggle.btn-xs{min-width:35px;min-height:22px}
.toggle-on.btn-xs{padding-right:12px}
.toggle-off.btn-xs{padding-left:12px}

View File

@ -1,85 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap2-toggle.css v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
label.checkbox .toggle,
label.checkbox.inline .toggle {
margin-left: -20px;
margin-right: 5px;
}
.toggle {
min-width: 40px;
height: 20px;
position: relative;
overflow: hidden;
}
.toggle input[type="checkbox"] {
display: none;
}
.toggle-group {
position: absolute;
width: 200%;
top: 0;
bottom: 0;
left: 0;
transition: left 0.35s;
-webkit-transition: left 0.35s;
-moz-user-select: none;
-webkit-user-select: none;
}
.toggle.off .toggle-group {
left: -100%;
}
.toggle-on {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 50%;
margin: 0;
border: 0;
border-radius: 0;
}
.toggle-off {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
right: 0;
margin: 0;
border: 0;
border-radius: 0;
}
.toggle-handle {
position: relative;
margin: 0 auto;
padding-top: 0px;
padding-bottom: 0px;
height: 100%;
width: 0px;
border-width: 0 1px;
}
.toggle-handle.btn-mini {
top: -1px;
}
.toggle.btn { min-width: 30px; }
.toggle-on.btn { padding-right: 24px; }
.toggle-off.btn { padding-left: 24px; }
.toggle.btn-large { min-width: 40px; }
.toggle-on.btn-large { padding-right: 35px; }
.toggle-off.btn-large { padding-left: 35px; }
.toggle.btn-small { min-width: 25px; }
.toggle-on.btn-small { padding-right: 20px; }
.toggle-off.btn-small { padding-left: 20px; }
.toggle.btn-mini { min-width: 20px; }
.toggle-on.btn-mini { padding-right: 12px; }
.toggle-off.btn-mini { padding-left: 12px; }

View File

@ -1,28 +0,0 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap2-toggle.css v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
label.checkbox .toggle,label.checkbox.inline .toggle{margin-left:-20px;margin-right:5px}
.toggle{min-width:40px;height:20px;position:relative;overflow:hidden}
.toggle input[type=checkbox]{display:none}
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
.toggle.off .toggle-group{left:-100%}
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
.toggle-handle.btn-mini{top:-1px}
.toggle.btn{min-width:30px}
.toggle-on.btn{padding-right:24px}
.toggle-off.btn{padding-left:24px}
.toggle.btn-large{min-width:40px}
.toggle-on.btn-large{padding-right:35px}
.toggle-off.btn-large{padding-left:35px}
.toggle.btn-small{min-width:25px}
.toggle-on.btn-small{padding-right:20px}
.toggle-off.btn-small{padding-left:20px}
.toggle.btn-mini{min-width:20px}
.toggle-on.btn-mini{padding-right:12px}
.toggle-off.btn-mini{padding-left:12px}

View File

@ -1,422 +1,373 @@
class AccountsController < ApplicationController class AccountsController < ApplicationController
before_action :require_login, only: [:login_check, :simple_update] include ApplicationHelper
include ApplicationHelper
#skip_before_action :check_account, :only => [:logout]
#skip_before_action :check_account, :only => [:logout]
def index
def simple_update render json: session
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, "")) end
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, "")) # 其他平台同步注册的用户
Register::RemoteForm.new(simple_update_params).validate! def remote_register
username = params[:username]&.gsub(/\s+/, "")
ActiveRecord::Base.transaction do tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
result = auto_update(current_user, simple_update_params) email = params[:email]&.gsub(/\s+/, "")
if result[:message].blank? password = params[:password]
render_ok platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
else
render_error(result[:message]) ActiveRecord::Base.transaction do
end result = autologin_register(username, email, password, platform)
end if result[:message].blank?
end render_ok({user: result[:user]})
else
def index render_error(result[:message])
render json: session end
end end
rescue Exception => e
# 为了同步平台上未注册gitea的用户 uid_logger_error(e.message)
def gitea_register tip_exception(-1, e.message)
user = User.find_by(login: sync_gitea_params[:login]) end
Users::SyncGiteaForm.new(sync_gitea_params.merge(user: user)).validate!
return render_error("该用户已同步协作平台") if user.gitea_token.present? && user.gitea_uid.present? # 其他平台修改用户的信息,这边同步修改
def remote_update
result = create_gitea_user!(user, sync_gitea_params[:login], sync_gitea_params[:email], sync_gitea_params[:password]) ActiveRecord::Base.transaction do
result[:user] ? render_ok : render_error(result[:message]) user_params = params[:user_params]
rescue Exception => e user_extension_params = params[:user_extension_params]
uid_logger_error(e.message)
tip_exception(-1, e.message) u = User.find_by(login: params[:old_user_login])
end user_mail = u.try(:mail)
# 其他平台同步注册的用户 if u.present?
def remote_register ue = u.user_extension
Register::RemoteForm.new(remote_register_params).validate! u.login = user_params["login"] if user_params["login"]
username = params[:username]&.gsub(/\s+/, "") u.mail = user_params["mail"] if user_params["mail"]
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username) u.lastname = user_params["lastname"] if user_params["lastname"]
email = params[:email]&.gsub(/\s+/, "")
password = params[:password] ue.gender = user_extension_params["gender"]
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") ue.school_id = user_extension_params["school_id"]
ue.location = user_extension_params["location"]
ActiveRecord::Base.transaction do ue.location_city = user_extension_params["location_city"]
result = autologin_register(username, email, password, platform) ue.identity = user_extension_params["identity"]
if result[:message].blank? ue.technical_title = user_extension_params["technical_title"]
render_ok({user: result[:user]}) ue.student_id = user_extension_params["student_id"]
else ue.description = user_extension_params["description"]
render_error(result[:message]) ue.save!
end u.save!
end
rescue Exception => e sync_params = {}
uid_logger_error(e.message)
tip_exception(-1, e.message) if (user_params["mail"] && user_params["mail"] != user_mail)
end sync_params = sync_params.merge(email: user_params["mail"])
end
# 其他平台修改用户的信息,这边同步修改
def remote_update if sync_params.present?
ActiveRecord::Base.transaction do interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
user_params = params[:user_params] if interactor.success?
user_extension_params = params[:user_extension_params] render_ok
else
u = User.find_by(login: params[:old_user_login]) render_error(interactor.error)
user_mail = u.try(:mail) end
end
if u.present? end
ue = u.user_extension end
u.login = user_params["login"] if user_params["login"] rescue Exception => e
u.mail = user_params["mail"] if user_params["mail"] uid_logger_error(e.message)
u.lastname = user_params["lastname"] if user_params["lastname"] tip_exception(-1, e.message)
end
ue.gender = user_extension_params["gender"]
ue.school_id = user_extension_params["school_id"] # 其他平台同步登录
ue.location = user_extension_params["location"] def remote_login
ue.location_city = user_extension_params["location_city"] @user = User.try_to_login(params[:login], params[:password])
ue.identity = user_extension_params["identity"] if @user
ue.technical_title = user_extension_params["technical_title"] successful_authentication(@user)
ue.student_id = user_extension_params["student_id"] render_ok({user: {id: @user.id, token: @user.gitea_token}})
ue.description = user_extension_params["description"] else
ue.save! render_error("用户不存在")
u.save! end
end
sync_params = {}
#修改密码
if (user_params["mail"] && user_params["mail"] != user_mail) def remote_password
sync_params = sync_params.merge(email: user_params["mail"]) @user = User.find_by(login: params[:login])
end return render_error("未找到相关用户!") if @user.blank?
if sync_params.present? sync_params = {
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params) password: params[:password].to_s,
if interactor.success? email: @user.mail
render_ok }
else
render_error(interactor.error) interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
end if interactor.success?
end @user.update_attribute(:password, params[:password])
end render_ok
end else
rescue Exception => e render_error(interactor.error)
uid_logger_error(e.message) end
tip_exception(-1, e.message) end
end
# 其他平台同步登录
def remote_login # 用户注册
@user = User.try_to_login(params[:login], params[:password]) # 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
if @user # params[:login] 邮箱或者手机号
successful_authentication(@user) # params[:namespace] 登录名
render_ok({user: {id: @user.id, token: @user.gitea_token}}) # params[:code] 验证码
else # code_type 1注册手机验证码 8邮箱注册验证码
render_error("用户不存在") # 本地forge注册入口需要重新更改逻辑
end def register
end # type只可能是1或者8
user = nil
#修改密码 begin
def remote_password Register::Form.new(register_params).validate!
@user = User.find_by(login: params[:login])
return render_error("未找到相关用户!") if @user.blank? user = Users::RegisterService.call(register_params)
password = register_params[:password].strip
sync_params = {
password: params[:password].to_s, # gitea用户注册, email, username, password
email: @user.mail,
login_name: @user.login, interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
source_id: 0 if interactor.success?
} gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.call(user.login, password)
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params) user.gitea_token = result['sha1']
if interactor.success? user.gitea_uid = gitea_user[:body]['id']
@user.update_attribute(:password, params[:password]) if user.save!
render_ok UserExtension.create!(user_id: user.id)
else successful_authentication(user)
render_error(interactor.error) render_ok
end end
end else
tip_exception(-1, interactor.error)
end
# 用户注册 rescue Register::BaseForm::EmailError => e
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用 render_error(-2, e.message)
# params[:login] 邮箱或者手机号 rescue Register::BaseForm::LoginError => e
# params[:namespace] 登录名 render_error(-3, e.message)
# params[:code] 验证码 rescue Register::BaseForm::PhoneError => e
# code_type 1注册手机验证码 8邮箱注册验证码 render_error(-4, e.message)
# 本地forge注册入口需要重新更改逻辑 rescue Register::BaseForm::PasswordFormatError => e
def register render_error(-5, e.message)
# type只可能是1或者8 rescue Register::BaseForm::VerifiCodeError => e
user = nil render_error(-6, e.message)
begin rescue Exception => e
Register::Form.new(register_params).validate! Gitea::User::DeleteService.call(user.login) unless user.nil?
uid_logger_error(e.message)
user = Users::RegisterService.call(register_params) tip_exception(-1, e.message)
password = register_params[:password].strip end
end
# gitea用户注册, email, username, password
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password}) # 用户登录
if interactor.success? def login
gitea_user = interactor.result Users::LoginForm.new(account_params).validate!
result = Gitea::User::GenerateTokenService.call(user.login, password) @user = User.try_to_login(params[:login], params[:password])
user.gitea_token = result['sha1']
user.gitea_uid = gitea_user[:body]['id'] return normal_status(-2, "错误的账号或密码") if @user.blank?
if user.save! # user is already in local database
UserExtension.create!(user_id: user.id) return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
successful_authentication(user)
render_ok login_control = LimitForbidControl::UserLogin.new(@user)
end return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
else
tip_exception(-1, interactor.error) password_ok = @user.check_password?(params[:password].to_s)
end unless password_ok
rescue Register::BaseForm::EmailError => e if login_control.remain_times-1 == 0
render_error(-2, e.message) normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
rescue Register::BaseForm::LoginError => e else
render_error(-3, e.message) normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
rescue Register::BaseForm::PhoneError => e end
render_error(-4, e.message) login_control.increment!
rescue Register::BaseForm::PasswordFormatError => e return
render_error(-5, e.message) end
rescue Register::BaseForm::VerifiCodeError => e
render_error(-6, e.message) successful_authentication(@user)
rescue Exception => e sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
Gitea::User::DeleteService.call(user.login) unless user.nil?
uid_logger_error(e.message) # session[:user_id] = @user.id
tip_exception(-1, e.message) end
end
end def change_password
@user = User.find_by(login: params[:login])
# 用户登录 return render_error("未找到相关用户!") if @user.blank?
def login return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
Users::LoginForm.new(account_params).validate!
@user = User.try_to_login(params[:login], params[:password]) sync_params = {
password: params[:password].to_s,
return normal_status(-2, "错误的账号或密码") if @user.blank? email: @user.mail
# user is already in local database }
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
login_control = LimitForbidControl::UserLogin.new(@user) if interactor.success?
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid? @user.update_attribute(:password, params[:password])
render_ok
password_ok = @user.check_password?(params[:password].to_s) else
unless password_ok render_error(interactor.error)
if login_control.remain_times-1 == 0 end
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") end
else
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会") # 忘记密码
end def reset_password
login_control.increment! begin
return code = params[:code]
end login_type = phone_mail_type(params[:login].strip)
# 获取验证码
successful_authentication(@user) if login_type == 1
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步 phone = params[:login]
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last
# session[:user_id] = @user.id user = User.find_by_phone(phone)
end else
email = params[:login]
def change_password verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
@user = User.find_by(login: params[:login]) user = User.find_by_mail(email) #这里有问题应该是为email,而不是mail 6.13-hs
return render_error("未找到相关用户!") if @user.blank? end
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password]) return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
sync_params = { return normal_status(-1, "8~16位密码支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
password: params[:password].to_s,
email: @user.mail, user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
login_name: @user.login, ActiveRecord::Base.transaction do
source_id: 0 user.save!
} LimitForbidControl::UserLogin.new(user).clear
end
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params) sucess_status
if interactor.success? rescue Exception => e
@user.update_attribute(:password, params[:password]) uid_logger_error(e.message)
render_ok tip_exception(e.message)
else end
render_error(interactor.error) end
end
end def successful_authentication(user)
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
# 忘记密码 # Valid user
def reset_password self.logged_user = user
begin # generate a key and set cookie if autologin
code = params[:code]
login_type = phone_mail_type(params[:login].strip) set_autologin_cookie(user)
# 获取验证码 UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
if login_type == 1 user.update_column(:last_login_on, Time.now)
phone = params[:login] session[:"#{default_yun_session}"] = user.id
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
user = User.find_by_phone(phone) # 注册完成后有一天的试用申请(先去掉)
else # UserDayCertification.create(user_id: user.id, status: 1)
email = params[:login] end
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
user = User.find_by_mail(email) #这里有问题应该是为email,而不是mail 6.13-hs def set_autologin_cookie(user)
end token = Token.get_or_create_permanent_login_token(user, "autologin")
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip sync_user_token_to_trustie(user.login, token.value)
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
return normal_status(-1, "8~16位密码支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD cookie_options = {
:value => token.value,
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation] :expires => 1.month.from_now,
ActiveRecord::Base.transaction do :path => '/',
user.save! :secure => false,
LimitForbidControl::UserLogin.new(user).clear :httponly => true
end }
sucess_status if edu_setting('cookie_domain').present?
rescue Exception => e cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
uid_logger_error(e.message) end
tip_exception(e.message) cookies[autologin_cookie_name] = cookie_options
end cookies.signed[:user_id] ||= user.id
end
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
def successful_authentication(user) end
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
# Valid user def logout
self.logged_user = user Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
# generate a key and set cookie if autologin UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
logout_user
set_autologin_cookie(user) render :json => {status: 1, message: "退出成功!"}
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip) end
user.update_column(:last_login_on, Time.now)
session[:"#{default_yun_session}"] = user.id # 检验邮箱是否已被注册及邮箱或者手机号是否合法
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}") # 参数type为事件类型 1注册2忘记密码3绑定
# 注册完成后有一天的试用申请(先去掉) def valid_email_and_phone
# UserDayCertification.create(user_id: user.id, status: 1) check_mail_and_phone_valid(params[:login], params[:type])
end end
def set_autologin_cookie(user) # 发送验证码
token = Token.get_or_create_permanent_login_token(user, "autologin") # params[:login] 手机号或者邮箱号
sync_user_token_to_trustie(user.login, token.value) # params[:type]为事件通知类型 1用户注册 2忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
# 发送验证码send_type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱
cookie_options = { # 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 9: 验收手机号有效
:value => token.value, def get_verification_code
:expires => 1.month.from_now, code = %W(0 1 2 3 4 5 6 7 8 9)
:path => '/', value = params[:login]
:secure => false, type = params[:type].strip.to_i
:httponly => true login_type = phone_mail_type(value)
} send_type = verify_type(login_type, type)
if edu_setting('cookie_domain').present? verification_code = code.sample(6).join
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
end sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
cookies[autologin_cookie_name] = cookie_options tip_exception(501, "请求不合理") if sign != params[:smscode]
cookies.signed[:user_id] ||= user.id
logger.info "########### 验证码:#{verification_code}"
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}") logger.info("########get_verification_code: login_type #{login_type} send_type#{send_type}, ")
end
# 记录验证码
def logout check_verification_code(verification_code, send_type, value)
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}") render_ok
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip) end
logout_user
render :json => {status: 1, message: "退出成功!"} # check user's login or email or phone is used
end # params[:value] 手机号或者邮箱号或者登录名
# params[:type] 为事件类型 1登录名(login) 2email(邮箱) 3phone(手机号)
# 检验邮箱是否已被注册及邮箱或者手机号是否合法 def check
# 参数type为事件类型 1注册2忘记密码3绑定 Register::CheckColumnsForm.new(check_params).validate!
def valid_email_and_phone render_ok
check_mail_and_phone_valid(params[:login], params[:type]) end
end
private
# 发送验证码
# params[:login] 手机号或者邮箱号 # type 事件类型 1用户注册 2忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
# params[:type]为事件通知类型 1用户注册 2忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加 # login_type 1手机类型 2邮箱类型
# 发送验证码send_type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱 def verify_type login_type, type
# 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 9: 验收手机号有效 case type
def get_verification_code when 1
code = %W(0 1 2 3 4 5 6 7 8 9) login_type == 1 ? 1 : 8
value = params[:login] when 2
type = params[:type].strip.to_i login_type == 1 ? 2 : 3
login_type = phone_mail_type(value) when 3
send_type = verify_type(login_type, type) login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
verification_code = code.sample(6).join when 4
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}") when 5
tip_exception(501, "请求不合理") if sign != params[:smscode] login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
end
logger.info "########### 验证码:#{verification_code}" end
logger.info("########get_verification_code: login_type #{login_type} send_type#{send_type}, ")
def generate_login(login)
# 记录验证码 type = phone_mail_type(login.strip)
check_verification_code(verification_code, send_type, value)
render_ok if type == 1
end uid_logger("start register by phone: type is #{type}")
pre = 'p'
# check user's login or email or phone is used email = nil
# params[:value] 手机号或者邮箱号或者登录名 phone = login
# params[:type] 为事件类型 1登录名(login) 2email(邮箱) 3phone(手机号) else
def check uid_logger("start register by email: type is #{type}")
Register::CheckColumnsForm.new(check_params).validate! pre = 'm'
render_ok email = login
end phone = nil
end
def login_check code = generate_identifier User, 8, pre
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
render_ok { login: pre + code, email: email, phone: phone }
end end
private def user_params
params.require(:user).permit(:login, :email, :phone)
# type 事件类型 1用户注册 2忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加 end
# login_type 1手机类型 2邮箱类型
def verify_type login_type, type def account_params
case type params.require(:account).permit(:login, :password)
when 1 end
login_type == 1 ? 1 : 8
when 2 def check_params
login_type == 1 ? 2 : 3 params.permit(:type, :value)
when 3 end
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
when 4 def register_params
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5 params.permit(:login, :namespace, :password, :code)
when 5 end
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
end end
end
def generate_login(login)
type = phone_mail_type(login.strip)
if type == 1
uid_logger("start register by phone: type is #{type}")
pre = 'p'
email = nil
phone = login
else
uid_logger("start register by email: type is #{type}")
pre = 'm'
email = login
phone = nil
end
code = generate_identifier User, 8, pre
{ login: pre + code, email: email, phone: phone }
end
def sync_gitea_params
params.permit(:login, :email, :password)
end
def user_params
params.require(:user).permit(:login, :email, :phone)
end
def account_params
params.require(:account).permit(:login, :password)
end
def check_params
params.permit(:type, :value)
end
def register_params
params.permit(:login, :namespace, :password, :code)
end
def remote_register_params
params.permit(:username, :email, :password, :platform)
end
def simple_update_params
params.permit(:username, :email, :password, :platform)
end
end

View File

@ -1,33 +1,10 @@
class Admins::DashboardsController < Admins::BaseController class Admins::DashboardsController < Admins::BaseController
def index def index
# 用户活跃数 @active_user_count = User.where(last_login_on: today).count
day_user_ids = CommitLog.where(created_at: today).pluck(:user_id).uniq @weekly_active_user_count = User.where(last_login_on: current_week).count
weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:user_id).uniq @month_active_user_count = User.where(last_login_on: current_month).count
month_user_ids = CommitLog.where(created_at: current_month).pluck(:user_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 end
def month_active_user def month_active_user
@ -65,14 +42,10 @@ class Admins::DashboardsController < Admins::BaseController
end end
def current_week def current_week
7.days.ago.end_of_day..Time.now.end_of_day 7.days.ago.beginning_of_day..Time.now.end_of_day
end end
def current_month def current_month
30.days.ago.end_of_day..Time.now.end_of_day 30.days.ago.beginning_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
end end

View File

@ -1,49 +0,0 @@
class Admins::FeedbacksController < Admins::BaseController
before_action :get_feedback, only: [:new_history, :create_history, :destroy]
def index
sort_by = Feedback.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
feedbacks = Feedback.order("#{sort_by} #{sort_direction}")
@feedbacks = paginate(feedbacks)
end
def destroy
if @feedback.destroy
redirect_to admins_feedbacks_path
flash[:success] = "反馈意见删除成功"
else
redirect_to admins_feedbacks_path
flash[:danger] = "反馈意见删除失败"
end
end
def new_history
@feedback_message_history = FeedbackMessageHistory.new
end
def create_history
@feedback_message_history = @feedback.feedback_message_histories.new(feedback_message_history_params)
@feedback_message_history.user = current_user
if @feedback_message_history.save
redirect_to admins_feedbacks_path
flash[:success] = "发送通知成功"
else
redirect_to admins_feedbacks_path
flash[:danger] = @feedback_message_history.errors.full_messages.join(", ")
end
end
private
def feedback_params
params.require(:feedback).permit!
end
def feedback_message_history_params
params.require(:feedback_message_history).permit(:title, :content)
end
def get_feedback
@feedback = Feedback.find_by_id(params[:id])
end
end

View File

@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
def create def create
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile) return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
result = Admins::ImportUserFromExcelService.call(params[:file].to_io) result = Admins::ImportUserService.call(params[:file].to_io)
render_ok(result) render_ok(result)
rescue Admins::ImportUserService::Error => ex rescue Admins::ImportUserService::Error => ex
render_error(ex) render_error(ex)

View File

@ -2,24 +2,8 @@ class Admins::MessageTemplatesController < Admins::BaseController
before_action :get_template, only: [:edit, :update, :destroy] before_action :get_template, only: [:edit, :update, :destroy]
def index def index
message_templates = MessageTemplate.ransack(sys_notice_or_email_or_email_title_cont: params[:search]).result message_templates = MessageTemplate.group(:type).count.keys
@message_templates = kaminari_paginate(message_templates) @message_templates = kaminari_array_paginate(message_templates)
end
def new
@message_template = MessageTemplate.new
end
def create
@message_template = MessageTemplate::CustomTip.new(message_template_params)
@message_template.type = "MessageTemplate::CustomTip"
if @message_template.save!
redirect_to admins_message_templates_path
flash[:success] = "创建消息模板成功"
else
render :new
flash[:danger] = "创建消息模板失败"
end
end end
def edit def edit
@ -47,9 +31,7 @@ class Admins::MessageTemplatesController < Admins::BaseController
private private
def message_template_params def message_template_params
# type = @message_template.present? ? @message_template.type : "MessageTemplate::CustomTip" params.require(@message_template.type.split("::").join("_").underscore.to_sym).permit!
# params.require(type.split("::").join("_").underscore.to_sym).permit!
params.require(:message_template).permit!
end end
def get_template def get_template

View File

@ -1,26 +0,0 @@
class Admins::NpsController < Admins::BaseController
def index
@on_off_switch = EduSetting.get("nps-on-off-switch").to_s == 'true'
@user_nps = UserNp.joins(:user).order(created_at: :desc)
keyword = params[:keyword].to_s.strip.presence
if keyword
sql = 'CONCAT(users.lastname, users.firstname) LIKE :keyword OR users.nickname LIKE :keyword OR users.login LIKE :keyword OR users.mail LIKE :keyword OR users.phone LIKE :keyword'
@user_nps = @user_nps.where(sql, keyword: "%#{keyword}%")
end
@user_nps = @user_nps.where("action_type != 'close'") if params[:done_score].present?
@min_score = @user_nps.where("action_type != 'close'").minimum("score")
@max_score = @user_nps.where("action_type != 'close'").maximum("score")
@score_total_count = UserNp.where("action_type !='close'").count
@user_nps = paginate @user_nps.includes(:user)
end
def switch_change
edu_setting = EduSetting.find_by(name: "nps-on-off-switch")
if edu_setting.blank?
edu_setting = EduSetting.new(name: "nps-on-off-switch")
end
edu_setting.value = params[:switch].to_s
edu_setting.save
render_ok
end
end

View File

@ -1,6 +1,6 @@
class Admins::ProjectIgnoresController < Admins::BaseController class Admins::ProjectIgnoresController < Admins::BaseController
before_action :set_ignore, only: [:edit,:update, :destroy,:show] before_action :set_ignore, only: [:edit,:update, :destroy,:show]
# before_action :validate_params, only: [:create, :update] before_action :validate_params, only: [:create, :update]
def index def index
sort_by = Ignore.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at' sort_by = Ignore.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
@ -31,12 +31,12 @@ class Admins::ProjectIgnoresController < Admins::BaseController
# } # }
@project_ignore = Ignore.new(ignore_params) @project_ignore = Ignore.new(ignore_params)
if @project_ignore.save if @project_ignore.save!
redirect_to admins_project_ignores_path redirect_to admins_project_ignores_path
flash[:success] = "创建成功" flash[:success] = "创建成功"
else else
redirect_to admins_project_ignores_path render :new
flash[:danger] = @project_ignore.errors.full_messages.join(",") flash[:danger] = "创建失败"
end end
end end
@ -58,8 +58,8 @@ class Admins::ProjectIgnoresController < Admins::BaseController
redirect_to admins_project_ignores_path redirect_to admins_project_ignores_path
flash[:success] = "更新成功" flash[:success] = "更新成功"
else else
redirect_to admins_project_ignores_path render :edit
flash[:danger] = @project_ignore.errors.full_messages.join(",") flash[:danger] = "更新失败"
end end
end end
@ -98,23 +98,23 @@ class Admins::ProjectIgnoresController < Admins::BaseController
params.require(:ignore).permit(:name,:content) params.require(:ignore).permit(:name,:content)
end end
# def validate_params def validate_params
# name = params[:ignore][:name] name = params[:ignore][:name]
# if name.blank? if name.blank?
# flash[:danger] = "名称不允许为空" flash[:danger] = "名称不允许为空"
# redirect_to admins_project_ignores_path redirect_to admins_project_ignores_path
# elsif check_ignore_present?(name) && @project_ignore.blank? elsif check_ignore_present?(name) && @project_ignore.blank?
# flash[:danger] = "创建失败:名称已存在" flash[:danger] = "创建失败:名称已存在"
# redirect_to admins_project_ignores_path redirect_to admins_project_ignores_path
# end end
# end end
# def check_ignore_present?(name) def check_ignore_present?(name)
# return true if name.blank? return true if name.blank?
# name_downcase = name.downcase name_downcase = name.downcase
# name_upcase = name.upcase name_upcase = name.upcase
# name_first_big = name.capitalize name_first_big = name.capitalize
# Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big) Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
# end end
end end

View File

@ -27,18 +27,17 @@ class Admins::ProjectLanguagesController < Admins::BaseController
flash[:success] = '创建成功' flash[:success] = '创建成功'
else else
redirect_to admins_project_languages_path redirect_to admins_project_languages_path
flash[:danger] = @project_language.errors.full_messages.join(",") flash[:danger] = '创建失败'
end end
end end
def update def update
@project_language.attributes = {name: @name} if @project_language.update_attribute(:name, @name)
if @project_language.save
redirect_to admins_project_languages_path redirect_to admins_project_languages_path
flash[:success] = '更新成功' flash[:success] = '更新成功'
else else
redirect_to admins_project_languages_path redirect_to admins_project_languages_path
flash[:danger] = @project_language.errors.full_messages.join(",") flash[:success] = '更新失败'
end end
end end

View File

@ -1,6 +1,6 @@
class Admins::ProjectLicensesController < Admins::BaseController class Admins::ProjectLicensesController < Admins::BaseController
before_action :set_license, only: [:edit,:update, :destroy,:show] before_action :set_license, only: [:edit,:update, :destroy,:show]
# before_action :validate_params, only: [:create, :update] before_action :validate_params, only: [:create, :update]
def index def index
sort_by = License.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at' sort_by = License.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
@ -30,12 +30,13 @@ class Admins::ProjectLicensesController < Admins::BaseController
# position: max_position # position: max_position
# } # }
@project_license = License.new(license_params) @project_license = License.new(license_params)
if @project_license.save
if @project_license.save!
redirect_to admins_project_licenses_path redirect_to admins_project_licenses_path
flash[:success] = "创建成功" flash[:success] = "创建成功"
else else
redirect_to admins_project_licenses_path render :new
flash[:danger] = @project_license.errors.full_messages.join(",") flash[:danger] = "创建失败"
end end
end end
@ -53,13 +54,12 @@ class Admins::ProjectLicensesController < Admins::BaseController
# permissions: permissions.to_s, # permissions: permissions.to_s,
# limitations: limitations.to_s # limitations: limitations.to_s
# } # }
@project_license.attributes = license_params if @project_license.update_attributes(license_params)
if @project_license.save
redirect_to admins_project_licenses_path redirect_to admins_project_licenses_path
flash[:success] = "更新成功" flash[:success] = "更新成功"
else else
render admins_project_licenses_path render :edit
flash[:danger] = @project_license.errors.full_messages.join(",") flash[:danger] = "更新失败"
end end
end end
@ -98,23 +98,23 @@ class Admins::ProjectLicensesController < Admins::BaseController
params.require(:license).permit(:name,:content) params.require(:license).permit(:name,:content)
end end
# def validate_params def validate_params
# name = params[:license][:name] name = params[:license][:name]
# if name.blank? if name.blank?
# flash[:danger] = "名称不允许为空" flash[:danger] = "名称不允许为空"
# redirect_to admins_project_licenses_path redirect_to admins_project_licenses_path
# elsif check_license_present?(name) && @project_license.blank? elsif check_license_present?(name) && @project_license.blank?
# flash[:danger] = "创建失败:名称已存在" flash[:danger] = "创建失败:名称已存在"
# redirect_to admins_project_licenses_path redirect_to admins_project_licenses_path
# end end
# end end
# def check_license_present?(name) def check_license_present?(name)
# return true if name.blank? return true if name.blank?
# name_downcase = name.downcase name_downcase = name.downcase
# name_upcase = name.upcase name_upcase = name.upcase
# name_first_big = name.capitalize name_first_big = name.capitalize
# License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big) License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
# end end
end end

View File

@ -1,55 +0,0 @@
class Api::V1::BaseController < ApplicationController
include Api::ProjectHelper
include Api::UserHelper
include Api::PullHelper
# 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 if !current_user.admin? && !@project.manager?(current_user)
end
# 具有对仓库的操作权限
def require_operate_above
@project = load_project
return render_forbidden if !current_user.admin? && !@project.operator?(current_user)
end
# 具有仓库的操作权限或者fork仓库的操作权限
def require_operate_above_or_fork_project
@project = load_project
puts !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
return render_forbidden if !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
end
# 具有对仓库的访问权限
def require_public_and_member_above
@project = load_project
return render_forbidden if !@project.is_public && !current_user.admin? && !@project.member?(current_user)
end
end

View File

@ -1,18 +0,0 @@
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

View File

@ -1,8 +0,0 @@
class Api::V1::Projects::CodeStatsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
def index
@result_object = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: params[:ref]}, @project.owner&.gitea_token)
# puts @result_object
end
end

View File

@ -1,12 +0,0 @@
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

View File

@ -1,17 +0,0 @@
class Api::V1::Projects::ContentsController < Api::V1::BaseController
before_action :require_operate_above_or_fork_project, only: [:batch]
def batch
@batch_content_params = batch_content_params
# 处理下author和committer信息如果没传则默认为当前用户信息
@batch_content_params.merge!(author_email: current_user.mail, author_name: current_user.login) if batch_content_params[:author_email].blank? && batch_content_params[:author_name].blank?
@batch_content_params.merge!(committer_email: current_user.mail, committer_name: current_user.login) if batch_content_params[:committer_email].blank? && batch_content_params[:committer_name].blank?
@result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, @batch_content_params, @project.owner.gitea_token)
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

View File

@ -1,12 +0,0 @@
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

View File

@ -1,5 +0,0 @@
class Api::V1::Projects::Pulls::BaseController < Api::V1::BaseController
before_action :require_public_and_member_above
before_action :load_pull_request
end

View File

@ -1,40 +0,0 @@
class Api::V1::Projects::Pulls::JournalsController < Api::V1::Projects::Pulls::BaseController
def index
@journals = Api::V1::Projects::Pulls::Journals::ListService.call(@project, @pull_request, params, current_user)
@journals = @journals.limit(200)
end
def create
@journal = Api::V1::Projects::Pulls::Journals::CreateService.call(@project, @pull_request, create_params, current_user)
end
before_action :find_journal, only: [:update, :destroy]
def update
@journal = Api::V1::Projects::Pulls::Journals::UpdateService.call(@project, @pull_request, @journal, update_params, current_user)
end
def destroy
if @journal.destroy
render_ok
else
render_error("删除评论失败!")
end
end
private
def create_params
params.permit(:parent_id, :line_code, :note, :commit_id, :path, :type, :review_id, :diff => {})
end
def update_params
params.permit(:note, :commit_id, :state)
end
def find_journal
@journal = @pull_request.journals.find_by_id(params[:id])
return render_not_found unless @journal.present?
end
end

View File

@ -1,20 +0,0 @@
class Api::V1::Projects::Pulls::PullsController < Api::V1::BaseController
before_action :require_public_and_member_above
def index
@pulls = Api::V1::Projects::Pulls::ListService.call(@project, query_params)
@pulls = kaminari_paginate(@pulls)
end
before_action :load_pull_request, only: [:show]
def show
@result_object = Api::V1::Projects::Pulls::GetService.call(@project, @pull_request, current_user&.gitea_token)
@last_review = @pull_request.reviews.order(created_at: :desc).take
end
private
def query_params
params.permit(:status, :keyword, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :sort_by, :sort_direction)
end
end

View File

@ -1,23 +0,0 @@
class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::BaseController
def index
@reviews = @pull_request.reviews
@reviews = @reviews.where(status: params[:status]) if params[:status].present?
# @reviews = kaminari_paginate(@reviews)
end
before_action :require_reviewer, only: [:create]
def create
@review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
end
private
def require_reviewer
return render_forbidden('您没有审查权限,请联系项目管理员') if !current_user.admin? && !@pull_request.reviewers.exists?(current_user.id) && !@project.manager?(current_user)
end
def review_params
params.require(:review).permit(:content, :commit_id, :status)
end
end

View File

@ -1,10 +0,0 @@
class Api::V1::Projects::Pulls::VersionsController < Api::V1::Projects::Pulls::BaseController
def index
@result_object = Api::V1::Projects::Pulls::Versions::ListService.call(@project, @pull_request, {page: page, limit: limit}, current_user&.gitea_token)
end
def diff
@result_object = Api::V1::Projects::Pulls::Versions::GetDiffService.call(@project, @pull_request, params[:id], {filepath: params[:filepath]}, current_user&.gitea_token)
end
end

View File

@ -1,61 +0,0 @@
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 = @webhooks.where(type: params[:type]) if params[:type].present?
@webhooks = kaminari_paginate(@webhooks)
end
def create
return render_error("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49
@result_object = Api::V1::Projects::Webhooks::CreateService.call(@project, create_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 create_webhook_params
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, :type, events: [])
end
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

View File

@ -1,19 +0,0 @@
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)
end
end

View File

@ -1,16 +0,0 @@
class Api::V1::Users::FeedbacksController < Api::V1::BaseController
before_action :load_observe_user
before_action :check_auth_for_observe_user
def create
@result = Api::V1::Users::Feedbacks::CreateService.call(@observe_user, feedback_params)
return render_error("反馈意见创建失败.") if @result.nil?
return render_ok
end
private
def feedback_params
params.permit(:content)
end
end

View File

@ -1,13 +0,0 @@
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

View File

@ -1,81 +0,0 @@
class Api::V1::UsersController < Api::V1::BaseController
before_action :load_observe_user
before_action :check_auth_for_observe_user
def send_email_vefify_code
code = %W(0 1 2 3 4 5 6 7 8 9)
verification_code = code.sample(6).join
mail = params[:email]
code_type = params[:code_type]
sign = Digest::MD5.hexdigest("#{OPENKEY}#{mail}")
Rails.logger.info sign
tip_exception(501, "请求不合理") if sign != params[:smscode]
# 60s内不能重复发送
send_email_limit_cache_key = "send_email_60_second_limit:#{mail}"
tip_exception(-2, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key)
send_email_control = LimitForbidControl::SendEmailCode.new(mail)
tip_exception(-2, '邮件发送太频繁,请稍后再试') if send_email_control.forbid?
begin
UserMailer.update_email(mail, verification_code).deliver_now
Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute)
send_email_control.increment!
rescue Exception => e
logger_error(e)
tip_exception(-2,"邮件发送失败,请稍后重试")
end
ver_params = {code_type: code_type, code: verification_code, email: mail}
last_code = VerificationCode.where(code_type: code_type, email: mail).last
last_code.update_attributes!({created_at: Time.current - 10.minute}) if last_code.present?
data = VerificationCode.new(ver_params)
if data.save!
render_ok
else
tip_exception(-1, "创建数据失败")
end
end
def check_password
password = params[:password]
return tip_exception(-5, "8~16位密码支持字母数字和符号") unless password =~ CustomRegexp::PASSWORD
return tip_exception(-5, "密码错误") unless @observe_user.check_password?(password)
render_ok
end
def check_email
mail = strip(params[:email])
return tip_exception(-2, "邮件格式有误") unless mail =~ CustomRegexp::EMAIL
exist_owner = Owner.find_by(mail: mail)
return tip_exception(-2, '邮箱已被使用') if exist_owner
render_ok
end
def check_email_verify_code
code = strip(params[:code])
mail = strip(params[:email])
code_type = params[:code_type]
return tip_exception(-2, "邮件格式有误") unless mail =~ CustomRegexp::EMAIL
verifi_code = VerificationCode.where(email: mail, code: code, code_type: code_type).last
return render_ok if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
return tip_exception(-6, "验证码不正确") if verifi_code&.code != code
return tip_exception(-6, "验证码已失效") if !verifi_code&.effective?
render_ok
end
def update_email
@result_object = Api::V1::Users::UpdateEmailService.call(@observe_user, params, current_user.gitea_token)
if @result_object
return render_ok
else
return render_error('更改邮箱失败!')
end
end
end

View File

@ -174,11 +174,11 @@ class ApplicationController < ActionController::Base
end end
def require_profile_completed def require_profile_completed
# tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed? tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
end end
def require_user_profile_completed(user) def require_user_profile_completed(user)
# tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed? tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
end end
# 异常提醒 # 异常提醒
@ -248,57 +248,42 @@ class ApplicationController < ActionController::Base
#return if params[:controller] == "main" #return if params[:controller] == "main"
# Find the current user # Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}") #Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer') User.current = find_current_user
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token? uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
if @doorkeeper_token.present?
# client方法对接需要一直带着用户标识uid # 开放课程通过链接访问的用户
if @doorkeeper_token.resource_owner_id.blank? if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
tip_exception(-1, "缺少用户标识!") if params[:uid].nil? content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
User.current = User.find(params[:uid])
else if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id) user = open_class_user
if user
start_user_session(user)
set_autologin_cookie(user)
end end
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 User.current = user
start_user_session(user)
end 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
# end
# end
end end
if !User.current.logged? && Rails.env.development?
User.current = User.find 104
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
# end
# end
# User.current = User.find 81403 # User.current = User.find 81403
end end
@ -701,7 +686,7 @@ class ApplicationController < ActionController::Base
@project, @owner = Project.find_with_namespace(namespace, id) @project, @owner = Project.find_with_namespace(namespace, id)
if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links") if @project and current_user.can_read_project?(@project)
logger.info "########### has project and can read project" logger.info "########### has project and can read project"
@project @project
# elsif @project && current_user.is_a?(AnonymousUser) # elsif @project && current_user.is_a?(AnonymousUser)
@ -709,15 +694,9 @@ class ApplicationController < ActionController::Base
# @project = nil if !@project.is_public? # @project = nil if !@project.is_public?
# render_forbidden and return # render_forbidden and return
else else
if @project.present? logger.info "###########project not found"
logger.info "########### has project and but can't read project" @project = nil
@project = nil render_not_found and return
render_forbidden and return
else
logger.info "###########project not found"
@project = nil
render_not_found and return
end
end end
@project @project
end end
@ -730,20 +709,14 @@ class ApplicationController < ActionController::Base
Rails.application.config_for(:configuration)['platform_url'] || request.base_url Rails.application.config_for(:configuration)['platform_url'] || request.base_url
end 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 convert_image! def convert_image!
@image = params[:image] @image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image @image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
return unless @image.present? return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile if @image.class == ActionDispatch::Http::UploadedFile
return render_error('请上传文件') if @image.size.zero? render_error('请上传文件') if @image.size.zero?
return render_error('文件大小超过限制') if @image.size > max_size.to_i render_error('文件大小超过限制') if @image.size > max_size.to_i
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
else else
image = @image.to_s.strip image = @image.to_s.strip
return render_error('请上传正确的图片') if image.blank? return render_error('请上传正确的图片') if image.blank?

View File

@ -1,258 +1,261 @@
#coding=utf-8 #coding=utf-8
# #
# 文件上传 # 文件上传
class AttachmentsController < ApplicationController class AttachmentsController < ApplicationController
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file] before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
before_action :find_file, only: %i[show destroy] before_action :find_file, only: %i[show destroy]
before_action :attachment_candown, only: [:show] before_action :attachment_candown, only: [:show]
skip_before_action :check_sign, only: [:show, :create] skip_before_action :check_sign, only: [:show, :create]
include ApplicationHelper include ApplicationHelper
def show def show
# 1. 优先跳到cdn # 1. 优先跳到cdn
# 2. 如果没有cdnsend_file # 2. 如果没有cdnsend_file
if @file.cloud_url.present? if @file.cloud_url.present?
update_downloads(@file) update_downloads(@file)
redirect_to @file.cloud_url and return redirect_to @file.cloud_url and return
end end
type_attachment = params[:disposition] || "attachment" type_attachment = params[:disposition] || "attachment"
if type_attachment == "inline" if type_attachment == "inline"
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf' send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
elsif type_attachment == "MP4" elsif type_attachment == "MP4"
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
else else
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream') send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
end end
update_downloads(@file) update_downloads(@file)
end end
def get_file def get_file
normal_status(-1, "参数缺失") if params[:download_url].blank? normal_status(-1, "参数缺失") if params[:download_url].blank?
url = base_url.starts_with?("https:") ? URI.encode(params[:download_url].to_s.gsub("http:", "https:")) : URI.encode(params[:download_url].to_s) url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
if url.starts_with?(base_url) && !url.starts_with?("#{base_url}/repo") if url.starts_with?(base_url)
domain = GiteaService.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = GiteaService.gitea_config[:base_url] api_url = Gitea.gitea_config[:base_url]
url = ("/repos"+url.split(base_url + "/api")[1]).gsub('?filepath=', '/').gsub('&', '?') 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 request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
response = Faraday.get(request_url) response = Faraday.get(request_url)
filename = url.to_s.split("/").pop() filename = url.to_s.split("/").pop()
else else
response = Faraday.get(url) response = Faraday.get(url)
filename = params[:download_url].to_s.split("/").pop() filename = params[:download_url].to_s.split("/").pop()
end end
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment') send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
end end
def create def create
# 1. 本地存储 # 1. 本地存储
# 2. 上传到云 # 2. 上传到云
begin begin
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称 upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
raise "未上传文件" unless upload_file raise "未上传文件" unless upload_file
folder = file_storage_directory folder = file_storage_directory
raise "存储目录未定义" unless folder.present? raise "存储目录未定义" unless folder.present?
month_folder = current_month_folder month_folder = current_month_folder
save_path = File.join(folder, month_folder) save_path = File.join(folder, month_folder)
ext = file_ext(upload_file.original_filename) ext = file_ext(upload_file.original_filename)
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext) local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
content_type = upload_file.content_type.presence || 'application/octet-stream' content_type = upload_file.content_type.presence || 'application/octet-stream'
# remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type) # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端 remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
logger.info "local_path: #{local_path}" logger.info "local_path: #{local_path}"
logger.info "remote_path: #{remote_path}" logger.info "remote_path: #{remote_path}"
disk_filename = local_path[save_path.size + 1, local_path.size] disk_filename = local_path[save_path.size + 1, local_path.size]
#存数据库 #存数据库
# #
@attachment = Attachment.where(disk_filename: disk_filename, @attachment = Attachment.where(disk_filename: disk_filename,
author_id: current_user.id, author_id: current_user.id,
cloud_url: remote_path).first cloud_url: remote_path).first
if @attachment.blank? if @attachment.blank?
@attachment = Attachment.new @attachment = Attachment.new
@attachment.filename = upload_file.original_filename @attachment.filename = upload_file.original_filename
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size] @attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
@attachment.filesize = upload_file.tempfile.size @attachment.filesize = upload_file.tempfile.size
@attachment.content_type = content_type @attachment.content_type = content_type
@attachment.digest = digest @attachment.digest = digest
@attachment.author_id = current_user.id @attachment.author_id = current_user.id
@attachment.disk_directory = month_folder @attachment.disk_directory = month_folder
@attachment.cloud_url = remote_path @attachment.cloud_url = remote_path
@attachment.save! @attachment.save!
else else
logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}" logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}"
end end
render_json render_json
rescue => e rescue => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
end end
end end
def destroy def destroy
begin begin
@file_path = absolute_path(local_path(@file)) @file_path = absolute_path(local_path(@file))
#return normal_status(403, "") unless @file.author == current_user #return normal_status(403, "") unless @file.author == current_user
@file.destroy! @file.destroy!
delete_file(@file_path) delete_file(@file_path)
normal_status("删除成功") normal_status("删除成功")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
# 附件为视频时,点击播放 # 附件为视频时,点击播放
def preview_attachment def preview_attachment
attachment = Attachment.find_by(id: params[:id]) attachment = Attachment.find_by(id: params[:id])
dir_path = "#{Rails.root}/public/preview" dir_path = "#{Rails.root}/public/preview"
Dir.mkdir(dir_path) unless Dir.exist?(dir_path) Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
if params[:status] == "preview" if params[:status] == "preview"
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/") if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"} render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
else else
normal_status(-1, "出现错误,请稍后重试") normal_status(-1, "出现错误,请稍后重试")
end end
else else
if system("rm -rf #{dir_path}/#{attachment.disk_filename}") if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
normal_status(1, "操作成功") normal_status(1, "操作成功")
else else
normal_status(-1, "出现错误,请稍后重试") normal_status(-1, "出现错误,请稍后重试")
end end
end end
end end
private private
def find_file def find_file
@file = @file =
if params[:type] == 'history' if params[:type] == 'history'
AttachmentHistory.find params[:id] AttachmentHistory.find params[:id]
else else
Attachment.find params[:id] Attachment.find params[:id]
end end
end end
def delete_file(file_path) def delete_file(file_path)
File.delete(file_path) if File.exist?(file_path) File.delete(file_path) if File.exist?(file_path)
end end
def current_month_folder def current_month_folder
date = Time.now date = Time.now
"#{date.year}/#{date.month.to_s.rjust(2, '0')}" "#{date.year}/#{date.month.to_s.rjust(2, '0')}"
end end
def file_ext(file_name) def file_ext(file_name)
ext = '' ext = ''
exts = file_name.split(".") exts = file_name.split(".")
if exts.size > 1 if exts.size > 1
ext = ".#{exts.last}" ext = ".#{exts.last}"
end end
ext ext
end end
def file_save_to_local(save_path, temp_file, ext) def file_save_to_local(save_path, temp_file, ext)
unless Dir.exists?(save_path) unless Dir.exists?(save_path)
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常 FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
end end
digest = md5_file(temp_file) digest = md5_file(temp_file)
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}" digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
local_file_path = File.join(save_path, digest) + ext local_file_path = File.join(save_path, digest) + ext
save_temp_file(temp_file, local_file_path) save_temp_file(temp_file, local_file_path)
[local_file_path, digest] [local_file_path, digest]
end end
def save_temp_file(temp_file, save_file_path) def save_temp_file(temp_file, save_file_path)
File.open(save_file_path, 'wb') do |f| File.open(save_file_path, 'wb') do |f|
temp_file.rewind temp_file.rewind
while (buffer = temp_file.read(8192)) while (buffer = temp_file.read(8192))
f.write(buffer) f.write(buffer)
end end
end end
end end
def md5_file(temp_file) def md5_file(temp_file)
md5 = Digest::MD5.new md5 = Digest::MD5.new
temp_file.rewind temp_file.rewind
while (buffer = temp_file.read(8192)) while (buffer = temp_file.read(8192))
md5.update(buffer) md5.update(buffer)
end end
md5.hexdigest md5.hexdigest
end end
def file_save_to_ucloud(path, file, content_type) def file_save_to_ucloud(path, file, content_type)
ufile = Gitlink::Ufile.new( ufile = Gitlink::Ufile.new(
ucloud_public_key: edu_setting('public_key'), ucloud_public_key: edu_setting('public_key'),
ucloud_private_key: edu_setting('private_key'), ucloud_private_key: edu_setting('private_key'),
ucloud_public_read: true, ucloud_public_read: true,
ucloud_public_bucket: edu_setting('public_bucket'), ucloud_public_bucket: edu_setting('public_bucket'),
ucloud_public_bucket_host: edu_setting('public_bucket_host'), ucloud_public_bucket_host: edu_setting('public_bucket_host'),
ucloud_public_cdn_host: edu_setting('public_cdn_host'), ucloud_public_cdn_host: edu_setting('public_cdn_host'),
) )
File.open(file) do |f| File.open(file) do |f|
ufile.put(path, f, 'Content-Type' => content_type) ufile.put(path, f, 'Content-Type' => content_type)
end end
edu_setting('public_cdn_host') + "/" + path edu_setting('public_cdn_host') + "/" + path
end end
def attachment_candown def attachment_candown
unless current_user.admin? || current_user.business? unless current_user.admin? || current_user.business?
candown = true candown = true
if @file.container unless params[:type] == 'history'
if @file.container.is_a?(Issue) if @file.container && current_user.logged?
project = @file.container.project if @file.container.is_a?(Issue)
candown = project.is_public || (current_user.logged? && project.member?(current_user)) course = @file.container.project
elsif @file.container.is_a?(Journal) candown = course.member?(current_user)
project = @file.container.issue.project elsif @file.container.is_a?(Journal)
candown = project.is_public || (current_user.logged? && project.member?(current_user)) course = @file.container.issue.project
else candown = course.member?(current_user)
project = nil else
end course = nil
tip_exception(403, "您没有权限进入") if project.present? && !candown end
end tip_exception(403, "您没有权限进入") if course.present? && !candown
end tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
end end
end
def send_file_with_range(path, options = {}) end
logger.info("########request.headers: #{request.headers}") end
logger.info("########request.headers: #{File.exist?(path)}")
def send_file_with_range(path, options = {})
if File.exist?(path) logger.info("########request.headers: #{request.headers}")
size = File.size(path) logger.info("########request.headers: #{File.exist?(path)}")
logger.info("########request.headers: #{request.headers}")
if !request.headers["Range"] if File.exist?(path)
status_code = 200 # 200 OK size = File.size(path)
offset = 0 logger.info("########request.headers: #{request.headers}")
length = File.size(path) if !request.headers["Range"]
else status_code = 200 # 200 OK
status_code = 206 # 206 Partial Content offset = 0
bytes = Rack::Utils.byte_ranges(request.headers, size)[0] length = File.size(path)
offset = bytes.begin else
length = bytes.end - bytes.begin status_code = 206 # 206 Partial Content
end bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
response.header["Accept-Ranges"] = "bytes" offset = bytes.begin
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes length = bytes.end - bytes.begin
response.header["status"] = status_code end
response.header["Accept-Ranges"] = "bytes"
send_data IO.binread(path, length, offset), options response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
else response.header["status"] = status_code
raise ActionController::MissingFile, "Cannot read file #{path}."
end send_data IO.binread(path, length, offset), options
end else
raise ActionController::MissingFile, "Cannot read file #{path}."
end end
end
end

View File

@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
namespace = params[:owner] namespace = params[:owner]
id = params[:repo] || params[:id] id = params[:repo] || params[:id]
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id, current_user.login) @ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
end end
def load_all_repo def load_all_repo

View File

@ -14,12 +14,12 @@ class Ci::CloudAccountsController < Ci::BaseController
def create def create
flag, msg = check_bind_cloud_account! flag, msg = check_bind_cloud_account!
return tip_exception(msg) if flag === true return render_error(msg) if flag === true
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@cloud_account = bind_account! @cloud_account = bind_account!
if @cloud_account.blank? if @cloud_account.blank?
tip_exception('激活失败, 请检查你的云服务器信息是否正确.') render_error('激活失败, 请检查你的云服务器信息是否正确.')
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
else else
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
@ -27,17 +27,17 @@ class Ci::CloudAccountsController < Ci::BaseController
end end
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def activate def activate
return tip_exception('请先认证') unless current_user.ci_certification? return render_error('请先认证') unless current_user.ci_certification?
begin begin
@cloud_account = Ci::CloudAccount.find params[:id] @cloud_account = Ci::CloudAccount.find params[:id]
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @repo if @repo
return tip_exception('该项目已经激活') if @repo.repo_active? return render_error('该项目已经激活') if @repo.repo_active?
@repo.activate!(@project) @repo.activate!(@project)
else else
@repo = Ci::Repo.auto_create!(@ci_user, @project) @repo = Ci::Repo.auto_create!(@ci_user, @project)
@ -50,7 +50,7 @@ class Ci::CloudAccountsController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
end end
@ -59,39 +59,39 @@ class Ci::CloudAccountsController < Ci::BaseController
def bind def bind
flag, msg = check_bind_cloud_account! flag, msg = check_bind_cloud_account!
return tip_exception(msg) if flag === true return render_error(msg) if flag === true
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@cloud_account = bind_account! @cloud_account = bind_account!
if @cloud_account.blank? if @cloud_account.blank?
tip_exception('激活失败, 请检查你的云服务器信息是否正确.') render_error('激活失败, 请检查你的云服务器信息是否正确.')
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
else else
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
end end
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def trustie_bind def trustie_bind
account = params[:account].to_s account = params[:account].to_s
return tip_exception("account不能为空.") if account.blank? return render_error("account不能为空.") if account.blank?
flag, msg = check_trustie_bind_cloud_account! flag, msg = check_trustie_bind_cloud_account!
return tip_exception(msg) if flag === true return render_error(msg) if flag === true
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@cloud_account = trustie_bind_account! @cloud_account = trustie_bind_account!
if @cloud_account.blank? if @cloud_account.blank?
tip_exception('激活失败, 请检查你的云服务器信息是否正确.') render_error('激活失败, 请检查你的云服务器信息是否正确.')
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
else else
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
end end
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def unbind def unbind
@ -107,18 +107,18 @@ class Ci::CloudAccountsController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def oauth_grant def oauth_grant
password = params[:password].to_s password = params[:password].to_s
return tip_exception('你输入的密码不正确.') unless current_user.check_password?(password) return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
oauth = current_user.oauths.last oauth = current_user.oauths.last
return tip_exception("服务器出小差了.") if oauth.blank? return render_error("服务器出小差了.") if oauth.blank?
result = gitea_oauth_grant!(password, oauth) result = gitea_oauth_grant!(password, oauth)
return tip_exception('授权失败.') unless result === true return render_error('授权失败.') unless result === true
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION) current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
end end

View File

@ -30,7 +30,7 @@ class Ci::PipelinesController < Ci::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
if size > 0 if size > 0
tip_exception("#{params[:branch]}分支已经存在流水线!") render_error("#{params[:branch]}分支已经存在流水线!")
return return
end end
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner], pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
@ -53,7 +53,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok({id: pipeline.id}) render_ok({id: pipeline.id})
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
# 在代码库创建文件 # 在代码库创建文件
@ -81,7 +81,6 @@ class Ci::PipelinesController < Ci::BaseController
repo_branch: pipeline.branch, repo_branch: pipeline.branch,
repo_config: pipeline.file_name repo_config: pipeline.file_name
} }
Rails.logger.info("########create_params===#{create_params.to_json}")
repo = Ci::Repo.create_repo(create_params) repo = Ci::Repo.create_repo(create_params)
repo repo
end end
@ -119,7 +118,7 @@ class Ci::PipelinesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def destroy def destroy
@ -133,7 +132,7 @@ class Ci::PipelinesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def content def content
@ -183,7 +182,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def update_stage def update_stage
@ -193,7 +192,7 @@ class Ci::PipelinesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def delete_stage def delete_stage
@ -206,7 +205,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def update_stage_index(pipeline_id, show_index, diff) def update_stage_index(pipeline_id, show_index, diff)
@ -230,7 +229,7 @@ class Ci::PipelinesController < Ci::BaseController
unless steps.empty? unless steps.empty?
steps.each do |step| steps.each do |step|
unless step[:template_id] unless step[:template_id]
tip_exception('请选择模板!') render_error('请选择模板!')
return return
end end
if !step[:id] if !step[:id]
@ -247,7 +246,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def create_stage_step def create_stage_step
@ -263,7 +262,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def update_stage_step def update_stage_step
@ -280,7 +279,7 @@ class Ci::PipelinesController < Ci::BaseController
render_ok render_ok
end end
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def delete_stage_step def delete_stage_step
@ -290,6 +289,6 @@ class Ci::PipelinesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
end end

View File

@ -30,19 +30,19 @@ class Ci::ProjectsController < Ci::BaseController
@file = interactor.result @file = interactor.result
render_result(1, "更新成功") render_result(1, "更新成功")
else else
tip_exception(interactor.error) render_error(interactor.error)
end end
end end
def activate def activate
return tip_exception('你还未认证') unless current_user.ci_certification? return render_error('你还未认证') unless current_user.ci_certification?
begin begin
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @repo if @repo
@repo.destroy! if @repo&.repo_user_id == 0 return render_error('该项目已经激活') if @repo.repo_active?
return tip_exception('该项目已经激活') if @repo.repo_active?
@repo.activate!(@project) @repo.activate!(@project)
return render_ok
else else
@repo = Ci::Repo.auto_create!(@ci_user, @project) @repo = Ci::Repo.auto_create!(@ci_user, @project)
@ci_user.update_column(:user_syncing, false) @ci_user.update_column(:user_syncing, false)
@ -55,12 +55,12 @@ class Ci::ProjectsController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
end end
def deactivate def deactivate
return tip_exception('该项目已经取消激活') if !@repo.repo_active? return render_error('该项目已经取消激活') if !@repo.repo_active?
@project.update_column(:open_devops, false) @project.update_column(:open_devops, false)
@repo.deactivate_repos! @repo.deactivate_repos!

View File

@ -20,14 +20,14 @@ class Ci::SecretsController < Ci::BaseController
if result["id"] if result["id"]
render_ok render_ok
else else
tip_exception(result["message"]) render_error(result["message"])
end end
else else
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
if result["id"] if result["id"]
render_ok render_ok
else else
tip_exception(result["message"]) render_error(result["message"])
end end
end end
end end
@ -39,14 +39,14 @@ class Ci::SecretsController < Ci::BaseController
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
render_ok render_ok
else else
tip_exception("参数名不能为空") render_error("参数名不能为空")
end end
rescue Exception => ex rescue Exception => ex
render_ok render_ok
end end
def ci_drone_url def ci_drone_url
user = User.find_by(login: params[:owner]) || User.find_by(login: current_user.login) user = User.find_by(login: params[:owner])
user&.ci_cloud_account.drone_url user&.ci_cloud_account.drone_url
end end

View File

@ -50,7 +50,7 @@ class Ci::TemplatesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def update def update
@ -63,7 +63,7 @@ class Ci::TemplatesController < Ci::BaseController
) )
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
def destroy def destroy
@ -73,7 +73,7 @@ class Ci::TemplatesController < Ci::BaseController
end end
render_ok render_ok
rescue Exception => ex rescue Exception => ex
tip_exception(ex.message) render_error(ex.message)
end end
#======流水线模板查询=====# #======流水线模板查询=====#

View File

@ -1,30 +0,0 @@
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?
project.update_column(:updated_on, Time.now) if project.present?
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)
# 统计数据新增
CacheAsyncSetJob.perform_later("project_common_service", {commits: 1}, project.id)
end
end
end

View File

@ -6,37 +6,26 @@ class CompareController < ApplicationController
end end
def show def show
if params[:type] == "sha" load_compare_params
load_compare_params compare
@compare_result ||= gitea_compare(@base, @head) @merge_status, @merge_message = get_merge_message
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
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
end end
private private
def get_merge_message
def get_merge_message
if @base.blank? || @head.blank? if @base.blank? || @head.blank?
return -2, "请选择分支" return -2, "请选择分支"
else else
return -2, "目标仓库未开启合并请求PR功能" unless @project.has_menu_permission("pulls")
if @head.include?(":") if @head.include?(":")
fork_project = @project.forked_projects.joins(:owner).where(users: { login: @head.to_s.split("/")[0] }).take fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
return -2, "请选择正确的仓库" unless fork_project.present? return -2, "请选择正确的仓库" unless fork_project.present?
@exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take @exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take
else else
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).last @exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
end end
if @exist_pullrequest.present? if @exist_pullrequest.present?
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>" return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
else else
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank? if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
return -2, "分支内容相同,无需创建合并请求" return -2, "分支内容相同,无需创建合并请求"
end end
@ -53,22 +42,12 @@ class CompareController < ApplicationController
end end
def load_compare_params def load_compare_params
# @base = Addressable::URI.unescape(params[:base]) @base = Addressable::URI.unescape(params[:base])
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base]) @head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
# @head = Addressable::URI.unescape(@head)
@head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head)
end end
def gitea_compare(base, head) def gitea_compare(base, head)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token) Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
end
def page_size
params.fetch(:page, 1).to_i
end
def page_limit
params.fetch(:limit, 15).to_i
end end
end end

View File

@ -18,15 +18,15 @@ module Acceleratorable
end end
def accelerator_domain def accelerator_domain
GiteaService.gitea_config[:accelerator]["domain"] Gitea.gitea_config[:accelerator]["domain"]
end end
def accelerator_username def accelerator_username
GiteaService.gitea_config[:accelerator]["access_key_id"] Gitea.gitea_config[:accelerator]["access_key_id"]
end end
def config_accelerator? def config_accelerator?
GiteaService.gitea_config[:accelerator].present? Gitea.gitea_config[:accelerator].present?
end end
def is_foreign_url?(clone_addr) def is_foreign_url?(clone_addr)

View File

@ -1,20 +0,0 @@
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

View File

@ -1,19 +0,0 @@
module Api::PullHelper
extend ActiveSupport::Concern
def load_pull_request
pull_request_id = params[:pull_id] || params[:id]
@pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || PullRequest.find_by_id(pull_request_id)
@issue = @pull_request&.issue
if @pull_request
logger.info "###########pull_request founded"
@pull_request
else
logger.info "###########pull_request not found"
@pull_request = nil
render_not_found and return
end
@pull_request
end
end

View File

@ -1,28 +0,0 @@
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
# 是否具有查看用户或编辑用户的权限
def check_auth_for_observe_user
return render_forbidden unless current_user.admin? || @observe_user.id == current_user.id
end
def strip(str)
str.to_s.strip.presence
end
end

View File

@ -160,9 +160,9 @@ module Ci::CloudAccountManageable
state = SecureRandom.hex(8) state = SecureRandom.hex(8)
# redirect_uri eg: # redirect_uri eg:
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805 # https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
# redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login") redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
# clientId = client_id(oauth) clientId = client_id(oauth)
grant_url = "#{@cloud_account.drone_url}/login" grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{clientId}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
logger.info "[gitea] grant_url: #{grant_url}" logger.info "[gitea] grant_url: #{grant_url}"
conn = Faraday.new(url: grant_url) do |req| conn = Faraday.new(url: grant_url) do |req|
@ -188,7 +188,6 @@ module Ci::CloudAccountManageable
response = conn.get response = conn.get
logger.info "[drone] response headers: #{response.headers}" logger.info "[drone] response headers: #{response.headers}"
# true
response.headers['location'].include?('error') ? false : true response.headers['location'].include?('error') ? false : true
end end

View File

@ -35,15 +35,15 @@ module LaboratoryHelper
# my_projects: "/users/#{current_user.try(:login)}/projects", # my_projects: "/users/#{current_user.try(:login)}/projects",
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist", # my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
{ {
new_syllabuses: "https://forge.educoder.net/syllabuses/new", new_syllabuses: "https://www.trustie.net/syllabuses/new",
new_course: "https://forge.educoder.net/courses/new", new_course: "https://www.trustie.net/courses/new",
edit_account: "https://forge.educoder.net/my/account", edit_account: "https://www.trustie.net/my/account",
my_courses: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_courselist", my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
my_projects: "/users/#{current_user.try(:login)}/projects", my_projects: "/users/#{current_user.try(:login)}/projects",
my_organ: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_organizations", my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
default_url: "https://www.educoder.net/", default_url: Rails.application.config_for(:configuration)['platform_url'],
tiding_url: "https://www.educoder.net/users/#{current_user.try(:login)}/user_tidings", tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
register_url: "https://www.educoder.net/user/register" register_url: "https://www.trustie.net/login?login=false"
} }
end end
end end

View File

@ -11,7 +11,7 @@ module LoginHelper
def set_autologin_cookie(user) def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin") token = Token.get_or_create_permanent_login_token(user, "autologin")
# sync_user_token_to_trustie(user.login, token.value) sync_user_token_to_trustie(user.login, token.value)
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}" Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
cookie_options = { cookie_options = {
@ -108,15 +108,10 @@ module LoginHelper
def sync_pwd_to_gitea!(user, hash={}) def sync_pwd_to_gitea!(user, hash={})
return true if user.is_sync_pwd? return true if user.is_sync_pwd?
sync_params = { sync_params = { email: user.mail }
login_name: user.name,
source_id: 0,
email: user.mail
}
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash)) interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
if interactor.success? if interactor.success?
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########" Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
user.update_column(:is_sync_pwd, true)
true true
else else
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}" Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"

View File

@ -1,82 +1,30 @@
module RegisterHelper module RegisterHelper
extend ActiveSupport::Concern extend ActiveSupport::Concern
def autologin_register(username, email, password, platform = 'forge', phone = nil, nickname =nil, need_edit_info = false) def autologin_register(username, email, password, platform= 'forge')
result = {message: nil, user: nil} result = {message: nil, user: nil}
email = email.blank? ? "#{username}@example.org" : email
user = User.new(admin: false, login: username, mail: email, type: "User") user = User.new(admin: false, login: username, mail: email, type: "User")
user.password = password user.password = password
user.platform = platform user.platform = platform
user.phone = phone if phone.present? user.activate
user.nickname = nickname if nickname.present?
if need_edit_info
user.need_edit_info
else
user.activate
end
return unless user.valid? return unless user.valid?
create_gitea_user!(user, username, email, password)
end
def create_gitea_user!(forge_user, username, email, password=random_password)
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
result = {} if interactor.success?
if interactor.success? || interactor.result[:message].to_s.include?("已被注册") gitea_user = interactor.result
gitea_user = interactor.result[:message].to_s.include?("已被注册") ? Gitea::User::GetService.call(username, password) : interactor.result result = Gitea::User::GenerateTokenService.call(username, password)
Rails.logger.info "##### [gitea] create_gitea_user result: #{gitea_user}" user.gitea_token = result['sha1']
if gitea_user[:body].present? user.gitea_uid = gitea_user[:body]['id']
result = Gitea::User::GenerateTokenService.call(username, password) if user.save!
forge_user.gitea_token = result['sha1'] UserExtension.create!(user_id: user.id)
forge_user.gitea_uid = gitea_user[:body]['id'] if gitea_user[:body].present? && gitea_user[:body]['id'] !=0 result[:user] = {id: user.id, token: user.gitea_token}
forge_user.mail = email
if forge_user.save
UserExtension.create!(user_id: forge_user.id) if forge_user.user_extension.blank?
result[:user] = {id: forge_user.id, token: forge_user.gitea_token}
end
else
result[:message] = interactor.result[:message]
end end
else else
Rails.logger.info "##### [gitea] create_gitea_user result: #{interactor.result[:message]}" result[:message] = interactor.error
result[:message] = interactor.result[:message]
end end
result result
end end
def random_password
"#{Random.rand(11111111)}"
end
def auto_update(user, params={})
return if params.blank?
result = {message: nil, user: nil}
before_login = user.login
user.login = params[:username]
user.password = params[:password]
user.mail = params[:email]
if user.save!
sync_params = {
password: params[:password].to_s,
email: params[:email],
login_name: params[:username],
new_name: params[:username],
source_id: 0
}
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
if interactor.success?
result[:user] = user
else
result[:message] = '用户同步Gitea失败!'
end
else
result[:message] = user.errors.full_messages.join(",")
return
end
end
end end

View File

@ -3,7 +3,7 @@ module RenderHelper
render json: { status: 0, message: 'success' }.merge(data) render json: { status: 0, message: 'success' }.merge(data)
end end
def render_error(message = '', status=-1) def render_error(status = -1, message = '')
render json: { status: status, message: message } render json: { status: status, message: message }
end end

View File

@ -5,26 +5,7 @@ module Repository::LanguagesPercentagable
result = Gitea::Repository::Languages::ListService.call(@owner.login, result = Gitea::Repository::Languages::ListService.call(@owner.login,
@repository.identifier, current_user&.gitea_token) @repository.identifier, current_user&.gitea_token)
@transform_language = @transform_language = result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil 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)
return if @project.project_language.present?
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
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) if @project.project_language_id.nil?
rescue
return
end end
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781} # hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}

View File

@ -6,23 +6,14 @@ class ForksController < ApplicationController
def create def create
@new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call @new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call
# TODO: fix Educoder shixun
if @new_project.persisted?
ProjectScore.create(:project_id => @new_project.id, :score => 0) if @new_project.project_score.nil?
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @new_project.id)
@project.project_infos << project_info
end
end end
private private
def authenticate_project! def authenticate_project!
Rails.logger.info "authenticate_project1=======================#{current_user&.id},#{@project.user_id}"
Rails.logger.info "authenticate_project2=======================#{current_user&.id == @project.user_id}"
if current_user&.id == @project.user_id if current_user&.id == @project.user_id
render_result(-1, "自己不能fork自己的项目") render_result(-1, "自己不能fork自己的项目")
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier) elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
render_result(0, "fork失败你已拥有了这个项目") render_result(-1, "fork失败你已拥有了这个项目")
end end
# return if current_user != @project.owner # return if current_user != @project.owner
# render_result(-1, "自己不能fork自己的项目") # render_result(-1, "自己不能fork自己的项目")

View File

@ -2,12 +2,12 @@ class IssueTagsController < ApplicationController
before_action :require_login, except: [:index] before_action :require_login, except: [:index]
before_action :load_repository before_action :load_repository
before_action :set_user before_action :set_user
before_action :check_issue_tags_permission before_action :check_issue_permission, except: :index
before_action :set_issue_tag, only: [:edit, :update, :destroy] before_action :set_issue_tag, only: [:edit, :update, :destroy]
def index def index
issue_tags = @project.issue_tags.includes(:issues).reorder("issue_tags.#{order_name} #{order_type}") issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}")
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
@page = params[:page] || 1 @page = params[:page] || 1
@limit = params[:limit] || 15 @limit = params[:limit] || 15
@ -17,7 +17,7 @@ class IssueTagsController < ApplicationController
def create def create
title = params[:name].to_s.strip.first(15) title = params[:name].to_s.strip.first(10)
desc = params[:description].to_s.first(30) desc = params[:description].to_s.first(30)
color = params[:color] || "#ccc" color = params[:color] || "#ccc"
@ -29,7 +29,7 @@ class IssueTagsController < ApplicationController
if title.present? if title.present?
if IssueTag.exists?(name: title, project_id: @project.id) if IssueTag.exists?(name: title, project_id: @project.id)
normal_status(-1, "项目标记已存在") normal_status(-1, "标签已存在")
else else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@ -37,12 +37,12 @@ class IssueTagsController < ApplicationController
if issue_tag.save if issue_tag.save
# gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call # gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
# if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"]) # if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
normal_status(0, "项目标记创建成功!") # normal_status(0, "标签创建成功")
# else # else
# normal_status(-1, "项目标记创建失败") # normal_status(-1, "标签创建失败")
# end # end
else else
normal_status(-1, "项目标记创建失败") normal_status(-1, "标签创建失败")
end end
rescue => e rescue => e
puts "create version release error: #{e.message}" puts "create version release error: #{e.message}"
@ -51,7 +51,7 @@ class IssueTagsController < ApplicationController
end end
end end
else else
normal_status(-1, "项目标记名称不能为空") normal_status(-1, "标签名称不能为空")
end end
end end
@ -60,8 +60,8 @@ class IssueTagsController < ApplicationController
end end
def update def update
title = params[:name].to_s.strip.first(15) title = params[:name]
desc = params[:description].to_s.first(30) desc = params[:description]
color = params[:color] || "#ccc" color = params[:color] || "#ccc"
tag_params = { tag_params = {
@ -71,19 +71,19 @@ class IssueTagsController < ApplicationController
} }
if title.present? if title.present?
if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title) if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title)
normal_status(-1, "项目标记已存在") normal_status(-1, "标签已存在")
else else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
if @issue_tag.update_attributes(tag_params) if @issue_tag.update_attributes(tag_params)
# gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call # gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
# if gitea_tag # if gitea_tag
# normal_status(0, "项目标记更新成功") # normal_status(0, "标签更新成功")
# else # else
# normal_status(-1, "项目标记更新失败") # normal_status(-1, "标签更新失败")
# end # end
else else
normal_status(-1, "项目标记更新失败") normal_status(-1, "标签更新失败")
end end
rescue => e rescue => e
puts "create version release error: #{e.message}" puts "create version release error: #{e.message}"
@ -92,7 +92,7 @@ class IssueTagsController < ApplicationController
end end
end end
else else
normal_status(-1, "项目标记名称不能为空") normal_status(-1, "标签名称不能为空")
end end
end end
@ -102,12 +102,12 @@ class IssueTagsController < ApplicationController
if @issue_tag.destroy if @issue_tag.destroy
# issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call # issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
# if issue_tag # if issue_tag
# normal_status(0, "项目标记删除成功") # normal_status(0, "标签删除成功")
# else # else
# normal_status(-1, "项目标记删除失败") # normal_status(-1, "标签删除失败")
# end # end
else else
normal_status(-1, "项目标记删除失败") normal_status(-1, "标签删除失败")
end end
rescue => e rescue => e
puts "create version release error: #{e.message}" puts "create version release error: #{e.message}"
@ -122,16 +122,16 @@ class IssueTagsController < ApplicationController
@user = @project.owner @user = @project.owner
end end
def check_issue_tags_permission def check_issue_permission
unless @project.manager?(current_user) || current_user.admin? unless @project.member?(current_user) || current_user.admin?
return render_forbidden('你不是管理员,没有权限操作') normal_status(-1, "您没有权限")
end end
end end
def set_issue_tag def set_issue_tag
@issue_tag = IssueTag.find_by_id(params[:id]) @issue_tag = IssueTag.find_by_id(params[:id])
unless @issue_tag.present? unless @issue_tag.present?
normal_status(-1, "项目标记不存在") normal_status(-1, "标签不存在")
end end
end end

View File

@ -15,7 +15,6 @@ class IssuesController < ApplicationController
include TagChosenHelper include TagChosenHelper
def index def index
@user_operate_issue = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?) @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
issues = @project.issues.issue_issue.issue_index_includes issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member issues = issues.where(is_private: false) unless @user_admin_or_member
@ -24,13 +23,13 @@ class IssuesController < ApplicationController
@filter_issues = @all_issues @filter_issues = @all_issues
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD @filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING @filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present? @filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED) @open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED) @close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
@assign_to_me = @filter_issues.where(assigned_to_id: current_user&.id)
@my_published = @filter_issues.where(author_id: current_user&.id)
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue") scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
@issues_size = scopes.size @issues_size = scopes.size
@assign_to_me = scopes.where(assigned_to_id: current_user&.id)
@my_published = scopes.where(author_id: current_user&.id)
@issues = paginate(scopes) @issues = paginate(scopes)
respond_to do |format| respond_to do |format|
@ -109,7 +108,7 @@ class IssuesController < ApplicationController
def create def create
issue_params = issue_send_params(params) issue_params = issue_send_params(params)
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate! Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
@issue = Issue.new(issue_params) @issue = Issue.new(issue_params)
if @issue.save! if @issue.save!
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
@ -126,15 +125,9 @@ class IssuesController < ApplicationController
end end
end end
if params[:issue_tag_ids].present? if params[:issue_tag_ids].present?
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1 params[:issue_tag_ids].each do |tag|
return normal_status(-1, "最多只能创建一个标记。") IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1 end
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end end
if params[:assigned_to_id].present? if params[:assigned_to_id].present?
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
@ -149,13 +142,11 @@ class IssuesController < ApplicationController
end end
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}" Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0 AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
render json: {status: 0, message: "创建成", id: @issue.id} render json: {status: 0, message: "创建成", id: @issue.id}
else else
normal_status(-1, "创建失败") normal_status(-1, "创建失败")
end end
@ -174,18 +165,11 @@ class IssuesController < ApplicationController
last_token = @issue.token last_token = @issue.token
last_status_id = @issue.status_id last_status_id = @issue.status_id
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
if params[:issue_tag_ids].present? if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1 @issue&.issue_tags_relates&.destroy_all
return normal_status(-1, "最多只能创建一个标记。") params[:issue_tag_ids].each do |tag|
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1 IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
@issue&.issue_tags_relates&.destroy_all end
params[:issue_tag_ids].each do |tag|
next if tag == [""]
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end end
issue_files = params[:attachment_ids] issue_files = params[:attachment_ids]
@ -223,7 +207,7 @@ class IssuesController < ApplicationController
normal_status(-1, "不允许修改为关闭状态") normal_status(-1, "不允许修改为关闭状态")
else else
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate! Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
if @issue.update_attributes(issue_params) if @issue.update_attributes(issue_params)
if @issue&.pull_request.present? if @issue&.pull_request.present?
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
@ -247,7 +231,7 @@ class IssuesController < ApplicationController
end end
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
@issue.issue_times.update_all(end_time: Time.now) @issue.issue_times.update_all(end_time: Time.now)
# @issue.update_closed_issues_count_in_project! @issue.update_closed_issues_count_in_project!
if @issue.issue_type.to_s == "2" && last_status_id != 5 if @issue.issue_type.to_s == "2" && last_status_id != 5
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时才给token if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时才给token
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login)) post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
@ -489,8 +473,7 @@ class IssuesController < ApplicationController
end end
def operate_issue_permission def operate_issue_permission
@issue = Issue.find_by_id(params[:id]) unless @issue.present? return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
end end
def export_issues(issues) def export_issues(issues)

View File

@ -23,7 +23,6 @@ class JournalsController < ApplicationController
normal_status(-1, "评论内容不能为空") normal_status(-1, "评论内容不能为空")
else else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
Journals::CreateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
journal_params = { journal_params = {
journalized_id: @issue.id , journalized_id: @issue.id ,
journalized_type: "Issue", journalized_type: "Issue",
@ -54,9 +53,6 @@ class JournalsController < ApplicationController
end end
end end
end end
rescue Exception => exception
puts exception.message
normal_status(-1, exception.message)
end end
def destroy def destroy
@ -74,8 +70,7 @@ class JournalsController < ApplicationController
def update def update
content = params[:content] content = params[:content]
if content.present? if content.present?
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
if @journal.update_attribute(:notes, content) if @journal.update_attribute(:notes, content)
normal_status(0, "更新成功") normal_status(0, "更新成功")
else else
@ -84,9 +79,7 @@ class JournalsController < ApplicationController
else else
normal_status(-1, "评论的内容不能为空") normal_status(-1, "评论的内容不能为空")
end end
rescue Exception => exception
puts exception.message
normal_status(-1, exception.message)
end end
def get_children_journals def get_children_journals

View File

@ -21,14 +21,6 @@ class MainController < ApplicationController
uid_logger("main start is #{cookies[:_educoder_session]}") uid_logger("main start is #{cookies[:_educoder_session]}")
end end
if params[:path] && params[:path].start_with?('projects/')
project_id = params[:path].split("/")[1]
project = Project.find_by_id(project_id)
if project.present?
return redirect_to("/projects/#{project.owner.login}/#{project.identifier}", status: 301)
end
end
# TODO: 这块之后需要整合者架构重新变化统一跳转到index后再路由分发 # TODO: 这块之后需要整合者架构重新变化统一跳转到index后再路由分发
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild" if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html' render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'

View File

@ -1,56 +0,0 @@
class MarkFilesController < ApplicationController
before_action :require_login
before_action :load_project
before_action :load_pull_request
def index
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token, { "only-file-name": true })
@mark_files = MarkFile.where(pull_request_id: @pull_request.id)
end
def create
# unless @pull_request.mark_files.present?
# MarkFile.bulk_insert(*%i[pull_request_id, file_path_sha file_path created_at updated_at]) do |worker|
# @files_result['Files'].each do |file|
# worker.add(pull_request_id: @pull_request.id, file_path_sha: SecureRandom.uuid.gsub("-", ""), file_path: file['Name'])
# end
# end
# end
end
def mark_file_as_unread
tip_exception "参数错误" if params[:file_path_sha].blank?
file_path = Base64.strict_decode64(params[:file_path_sha].to_s)
mark_file = @pull_request.mark_files.find_or_initialize_by(file_path_sha: params[:file_path_sha])
mark_file.file_path = file_path
mark_file.user_id = current_user.id
mark_file.mark_as_read = false
mark_file.save
render_ok
rescue Exception => e
tip_exception "参数解析错误"
end
def mark_file_as_read
tip_exception "参数错误" if params[:file_path_sha].blank?
file_path = Base64.strict_decode64(params[:file_path_sha].to_s)
mark_file = @pull_request.mark_files.find_or_initialize_by(file_path_sha: params[:file_path_sha])
mark_file.file_path = file_path
mark_file.user_id = current_user.id
mark_file.mark_as_read = true
mark_file.save
render_ok
rescue Exception => e
tip_exception "参数解析错误"
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

View File

@ -3,19 +3,11 @@ class MembersController < ApplicationController
before_action :load_project before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role] before_action :find_user_with_id, only: %i[create remove change_role]
before_action :check_user_profile_completed, only: [:create] before_action :check_user_profile_completed, only: [:create]
before_action :operate! before_action :operate!, except: %i[index]
before_action :check_member_exists!, only: %i[create] before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role] before_action :check_member_not_exists!, only: %i[remove change_role]
def create def create
if @user.gitea_token.blank?
result = Gitea::User::GetService.call(@user.login)
if result[:status] == :error
# gitea不存在用户@user,直接注册
user_result = create_gitea_user!(@user, @user.login, @user.mail)
return render_error(user_result[:message]) if user_result[:message]
end
end
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user) interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
@ -34,9 +26,6 @@ class MembersController < ApplicationController
@total_count = scope.size @total_count = scope.size
@members = paginate(scope) @members = paginate(scope)
if @project.owner.is_a?(Organization) && (params[:page].to_i == 1 || params[:page].blank?) && !@project.members.exists?(user_id: current_user.id)
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
end
end end
def remove def remove
@ -72,14 +61,11 @@ class MembersController < ApplicationController
end end
def check_member_exists! def check_member_exists!
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
return render_error("#{@user&.nickname}已经是项目成员") if member_exists? || (params[:user_id].to_i == current_user.id && @current_user_header_team.present?)
end end
def check_member_not_exists! def check_member_not_exists!
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
return render_error("用户为组织成员,请到组织下操作!") if (params[:user_id].to_i == current_user.id && @current_user_header_team.present?) && !member_exists?
return render_error("#{@user&.nickname}还不是项目成员") unless member_exists?
end end
def check_user_profile_completed def check_user_profile_completed

View File

@ -1,33 +0,0 @@
class NoticesController < ApplicationController
def create
return tip_exception("参数有误") if params["source"].blank?
user_id = params[:user_id]
if params["source"] == "CompetitionBegin"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionBegin', user_id, competition_id)
elsif params["source"] == "CompetitionResult"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionResult', user_id, competition_id)
elsif params["source"] == "CompetitionReview"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
elsif params["source"] == "CustomTip"
users_id = params[:users_id]
props = params[:props].to_unsafe_hash
return tip_exception("参数有误") unless props.is_a?(Hash) && users_id.is_a?(Array)
template_id = params[:template_id]
SendTemplateMessageJob.perform_later('CustomTip', users_id, template_id, props)
else
tip_exception("#{params["source"]}未配置")
end
render_ok
end
private
def params_props
params.require(:notice).permit(:props)
end
end

View File

@ -1,17 +0,0 @@
class NpsController < ApplicationController
before_action :require_login
# close,关闭
# createIssue,创建issue
# createPullRequest,创建PR
# auditPullRequest,审核PR
# indexProject,项目主页
# createProject,创建项目
# createOrganization,创建组织
def create
tip_exception "缺少参数" if params[:action_id].blank? || params[:action_type].blank?
UserNp.create(:action_id => params[:action_id].to_i, :action_type => params[:action_type], :user_id => User.current.id, :score => params[:score].to_f, memo: params[:memo])
render_ok
end
end

View File

@ -2,7 +2,6 @@ class Oauth::BaseController < ActionController::Base
include RenderHelper include RenderHelper
include LoginHelper include LoginHelper
include ControllerRescueHandler include ControllerRescueHandler
include RegisterHelper
# include LaboratoryHelper # include LaboratoryHelper
skip_before_action :verify_authenticity_token skip_before_action :verify_authenticity_token
@ -23,7 +22,7 @@ class Oauth::BaseController < ActionController::Base
end end
def auth_hash def auth_hash
# Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}") Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
request.env['omniauth.auth'] request.env['omniauth.auth']
end end

View File

@ -1,68 +0,0 @@
class Oauth::CallbacksController < Oauth::BaseController
def create
process_callback
rescue Exception => e
Rails.logger.info "授权失败:#{e}"
tip_exception("授权失败")
end
private
def config_providers
config = Rails.application.config_for(:configuration)
config.dig("oauth").keys
end
# QQ: {"ret":0,"msg":"","is_lost":0,"nickname":"颜值不算太高","gender":"男","gender_type":1,"province":"","city":"","year":"2013","constellation":"","figureurl":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/30","figureurl_1":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/50","figureurl_2":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/100","figureurl_qq_1":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=40\u0026t=1568887757","figureurl_qq_2":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=100\u0026t=1568887757","figureurl_qq":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=140\u0026t=1568887757","figureurl_type":"1","is_yellow_vip":"0","vip":"0","yellow_vip_level":"0","level":"0","is_yellow_year_vip":"0"}
def process_callback
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
if auth_hash.blank?
redirect_to("/login") && return
end
new_user = false
platform = auth_hash[:provider]
uid = auth_hash[:uid]
mail = auth_hash.info.email || nil
nickname = ["gitee", "github"].include?(platform) ? auth_hash.info.name : auth_hash.info.nickname
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid)
if open_user.present? && open_user.user.present?
successful_authentication(open_user.user)
else
if current_user.blank? || !current_user.logged?
has_user = User.find_by(mail: mail)
if has_user.present?
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: has_user.id, uid: uid, extra: auth_hash.extra)
successful_authentication(has_user)
else
new_user = true
login = build_login_name(platform, auth_hash.info.nickname)
mail = "#{login}@example.org" if mail.blank?
code = %W(0 1 2 3 4 5 6 7 8 9)
rand_password = code.sample(10).join
reg_result = autologin_register(login, mail, rand_password, platform, nil, nickname)
Rails.logger.info("[OAuth2] omniauth.auth [reg_result] #{reg_result} ")
if reg_result[:message].blank?
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: reg_result[:user][:id], uid: uid, extra: auth_hash.extra)
successful_authentication(open_user.user)
else
tip_exception(reg_result.present? ? reg_result[:message] : "授权失败")
end
end
else
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: login, extra: auth_hash.extra)
end
end
redirect_to root_path(new_user: new_user)
end
# gitee,github nickname=login,如果系统未占用保留原用户名
def build_login_name(provider, nickname)
if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank?
nickname
else
User.generate_user_login('p')
end
end
end

View File

@ -1,130 +0,0 @@
class ObRepositorySyncsController < ApplicationController
before_action :require_login
before_action :load_project
before_action :load_ob_repository_sync, except: [:create]
before_action :authenticate_user!
def index
render_ok(data: @ob_repository_sync)
end
def create
tip_exception "参数错误" if params[:github_address].blank? && params[:gitee_address].blank?
project_name ="#{@project.owner.name}:#{@project.identifier}"
service = ObRepositorySync::ApiService.new(project_name)
domain = GiteaService.gitea_config[:domain]
project_params = params.merge({ "gitlink_address": "#{domain}/#{@project.owner&.login}/#{@project.identifier}.git" })
res = service.create_projects(project_params)
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
sync_id = res["data"]["id"]
ob_repository_sync = ObRepositorySync.find_or_initialize_by(project_id: @project.id)
ob_repository_sync.project_id = @project.id
ob_repository_sync.user_id = current_user.id
ob_repository_sync.name = project_name
ob_repository_sync.github_address = "#{params[:github_address]}"
ob_repository_sync.gitee_address = "#{params[:gitee_address]}"
ob_repository_sync.github_token = "#{params[:github_token]}"
ob_repository_sync.gitee_token = "#{params[:gitee_token]}"
ob_repository_sync.sync_id = sync_id
ob_repository_sync.save!
render_ok
end
def delete
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.delete_project @ob_repository_sync.sync_id
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
if res["code"].to_s == "200"
@ob_repository_sync.destroy!
end
render_ok
end
def jobs
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
page = params[:page] || 1
limit = params[:limit] || 10
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
source = ""
if params[:type] && params[:type].to_s.downcase == "github"
source = "github_branch"
elsif params[:type] && params[:type].to_s.downcase == "gitee"
source = "gitee_branch"
end
res = service.get_projects_jobs(source, page, limit)
data = res["data"]["list"]
render_ok(count: res["data"]["total"], data: data)
end
def create_jobs
tip_exception "必须配置一个分支" if params[:github_branch].blank? && params[:gitee_branch].blank? && params[:gitlink_branch].blank?
ob_jobs = ObRepositorySyncJob.where(ob_repository_sync_id: @ob_repository_sync.id)
ob_jobs = ob_jobs.where(job_type: params[:job_type]) if params[:job_type].present?
ob_jobs = ob_jobs.where(github_branch: params[:github_branch]) if params[:github_branch].present?
ob_jobs = ob_jobs.where(gitee_branch: params[:gitee_branch]) if params[:gitee_branch].present?
ob_jobs = ob_jobs.where(gitlink_branch: params[:gitlink_branch]) if params[:gitlink_branch].present?
tip_exception "该分支组合已配置,不能重复!" if ob_jobs.count > 0
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.create_projects_jobs(params)
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
job_id = res["data"]["id"]
job = ObRepositorySyncJob.new
job.ob_repository_sync_id = @ob_repository_sync.id
job.github_branch = "#{params[:github_branch]}"
job.gitee_branch = "#{params[:gitee_branch]}"
job.gitlink_branch = "#{params[:gitlink_branch]}"
job.job_type = "#{params[:job_type]}"
job.base = "#{params[:base]}"
job.job_id = job_id
job.save
render_ok
end
def delete_job
tip_exception "缺少参数job_id" if params[:job_id].blank?
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.delete_job params[:job_id]
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
job = ObRepositorySyncJob.find_by(ob_repository_sync_id: @ob_repository_sync.id, job_id: params[:job_id])
job.destroy! if job.present?
render_ok
end
def start_job
tip_exception "缺少参数job_id" if params[:job_id].blank?
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.start_job params[:job_id]
tip_exception "启动错误: #{res["msg"]}" if res["code"].to_s != "200"
render_ok
end
def stop_job
tip_exception "缺少参数job_id" if params[:job_id].blank?
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.stop_job params[:job_id]
tip_exception "停止错误: #{res["msg"]}" if res["code"].to_s != "200"
render_ok
end
def job_logs
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
tip_exception "缺少参数job_id" if params[:job_id].blank?
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
res = service.job_logs params[:job_id]
tip_exception "请求错误: #{res["msg"]}" if res["code"].to_s != "200"
render_ok(count: res["data"]["total"], data: res["data"]["list"])
end
private
def load_ob_repository_sync
@ob_repository_sync = ObRepositorySync.find_by(project_id: @project.id)
end
def authenticate_user!
return if @project.member?(current_user) || current_user.admin?
render_forbidden('你没有权限操作')
end
end

View File

@ -4,14 +4,8 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
def index def index
@organization_users = @organization.organization_users.includes(:user) @organization_users = @organization.organization_users.includes(:user)
if params[:search].present? search = params[:search].to_s.downcase
search = params[:search].to_s.downcase @organization_users = @organization_users.joins(:user).merge(User.like(search))
user_condition_users = User.like(search).to_sql
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
@organization_users = @organization_users.where(user_id: users).distinct
end
@organization_users = kaminari_paginate(@organization_users) @organization_users = kaminari_paginate(@organization_users)
end end

View File

@ -28,10 +28,9 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name]) tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate! Organizations::CreateForm.new(organization_params).validate!
@organization = Organizations::CreateService.call(current_user, organization_params) @organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present? Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
Cache::V2::OwnerCommonService.new(@organization.id).reset
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -40,16 +39,15 @@ class Organizations::OrganizationsController < Organizations::BaseController
def update def update
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate! Organizations::CreateForm.new(organization_params).validate!
login = @organization.login login = @organization.login
@organization.login = organization_params[:name] if organization_params[:name].present? @organization.login = organization_params[:name] if organization_params[:name].present?
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present? @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
@organization.save! @organization.save!
sync_organization_extension! sync_organization_extension!
Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload) Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present? Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
Cache::V2::OwnerCommonService.new(@organization.id).reset
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -59,16 +57,10 @@ class Organizations::OrganizationsController < Organizations::BaseController
def destroy def destroy
tip_exception("密码不正确") unless current_user.check_password?(password) tip_exception("密码不正确") unless current_user.check_password?(password)
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
gitea_destroy = Gitea::Organization::DeleteService.call(current_user.gitea_token, @organization.login) Gitea::Organization::DeleteService.call(@organization.gitea_token, @organization.login)
if gitea_destroy[:status] == 204 @organization.destroy!
@organization.destroy!
render_ok
elsif gitea_destroy[:status] == 500
tip_exception("当组织内含有仓库时,无法删除此组织")
else
tip_exception("")
end
end end
render_ok
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)

View File

@ -14,6 +14,22 @@ class Organizations::ProjectsController < Organizations::BaseController
@projects = paginate(@projects) @projects = paginate(@projects)
end end
#######################change#################################
def organizationBadge
watchers_count = @organization.watchers_count
@watchered = judge_level(watchers_count, 10, 20, 100)
@badge = organizationBadge.find_or_create_by(organization_id: @organization.id)
if @watchered != @badge.watched
@badge.watched = @watchered
@badge.save
end
render :json => {list: [{watchered: @watchered}], count: 1}
end
#######################change#################################
def search def search
tip_exception("请输入搜索关键词") if params[:search].nil? tip_exception("请输入搜索关键词") if params[:search].nil?
public_projects_sql = @organization.projects.where(is_public: true).to_sql public_projects_sql = @organization.projects.where(is_public: true).to_sql
@ -42,4 +58,17 @@ class Organizations::ProjectsController < Organizations::BaseController
def sort_direction def sort_direction
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc' %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
end end
def judge_level(judged, low, mid, high)
if judged < low
return 0
elsif judged < mid
return 1
elsif judged < high
return 2
else
return 3
end
end
end end

View File

@ -6,7 +6,6 @@ class Organizations::TeamProjectsController < Organizations::BaseController
def index def index
@team_projects = @team.team_projects @team_projects = @team.team_projects
@team_projects = paginate(@team_projects) @team_projects = paginate(@team_projects)
end end
@ -21,17 +20,6 @@ class Organizations::TeamProjectsController < Organizations::BaseController
tip_exception(e.message) tip_exception(e.message)
end end
def create_all
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
ActiveRecord::Base.transaction do
@organization.projects.each do |project|
TeamProject.build(@organization.id, @team.id, project.id)
end
Gitea::Organization::TeamProject::CreateAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
render_ok
end
end
def destroy def destroy
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@ -44,17 +32,6 @@ class Organizations::TeamProjectsController < Organizations::BaseController
tip_exception(e.message) tip_exception(e.message)
end end
def destroy_all
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
ActiveRecord::Base.transaction do
@team.team_projects.each do |project|
project.destroy!
end
Gitea::Organization::TeamProject::DeleteAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
render_ok
end
end
private private
def load_organization def load_organization
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id]) @organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
@ -69,7 +46,7 @@ class Organizations::TeamProjectsController < Organizations::BaseController
end end
def load_operate_project def load_operate_project
@operate_project = @organization.projects.where(id: project_mark).take || @organization.projects.where(identifier: project_mark).take @operate_project = Project.find_by(id: project_mark) || Project.find_by(identifier: project_mark)
tip_exception("项目不存在") if @operate_project.nil? tip_exception("项目不存在") if @operate_project.nil?
end end

View File

@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id) @organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu?
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login) Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
end end
rescue Exception => e rescue Exception => e
@ -31,7 +31,6 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@team_user.destroy! @team_user.destroy!
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login) Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
org_team_users = @organization.team_users.where(user_id: @operate_user.id) org_team_users = @organization.team_users.where(user_id: @operate_user.id)
unless org_team_users.present? unless org_team_users.present?
@organization.organization_users.find_by(user_id: @operate_user.id).destroy! @organization.organization_users.find_by(user_id: @operate_user.id).destroy!

View File

@ -4,24 +4,15 @@ class Organizations::TeamsController < Organizations::BaseController
before_action :check_user_can_edit_org, only: [:create, :update, :destroy] before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
def index def index
#if @organization.is_owner?(current_user) || current_user.admin?
if params[:is_full].present?
if can_edit_org?
@teams = @organization.teams
else
@teams = []
end
else
#if @organization.is_owner?(current_user) || current_user.admin?
@teams = @organization.teams @teams = @organization.teams
#else #else
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id}) # @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
#end #end
@is_admin = can_edit_org? @is_admin = can_edit_org?
@teams = @teams.includes(:team_units, :team_users) @teams = @teams.includes(:team_units, :team_users)
@teams = kaminari_paginate(@teams) @teams = kaminari_paginate(@teams)
end
end end
def search def search
@ -43,12 +34,8 @@ class Organizations::TeamsController < Organizations::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
if @organization.teams.count >= 50 Organizations::CreateTeamForm.new(team_params).validate!
return tip_exception("组织的团队数量已超过限制!") @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
else
Organizations::CreateTeamForm.new(team_params).validate!
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
end
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)

View File

@ -20,7 +20,7 @@ class OwnersController < ApplicationController
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id) @is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
@is_member = @owner.is_member?(current_user.id) @is_member = @owner.is_member?(current_user.id)
# 用户 # 用户
elsif @owner.is_a?(User) else
#待办事项,现在未做 #待办事项,现在未做
if User.current.admin? || User.current.login == @owner.login if User.current.admin? || User.current.login == @owner.login
@waiting_applied_messages = @owner.applied_messages.waiting @waiting_applied_messages = @owner.applied_messages.waiting
@ -45,6 +45,7 @@ class OwnersController < ApplicationController
@projects_common_count = user_projects.common.size @projects_common_count = user_projects.common.size
@projects_mirrior_count = user_projects.mirror.size @projects_mirrior_count = user_projects.mirror.size
@projects_sync_mirrior_count = user_projects.sync_mirror.size @projects_sync_mirrior_count = user_projects.sync_mirror.size
puts @owner.as_json
end end
end end

View File

@ -12,7 +12,6 @@ class PraiseTreadController < ApplicationController
begin begin
return normal_status(2, "你已点过赞了") if current_user.liked?(@project) return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
current_user.like!(@project) current_user.like!(@project)
SendTemplateMessageJob.perform_later('ProjectPraised', current_user.id, @project.id) if Site.has_notice_menu?
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)}) render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)

View File

@ -10,7 +10,7 @@ class ProjectCategoriesController < ApplicationController
end end
def group_list def group_list
@project_categories = ProjectCategory.select("id, name, projects_count, private_projects_count, (projects_count - private_projects_count) as public_projects_count").having('public_projects_count > 0').order(public_projects_count: :desc) @project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
# projects = Project.no_anomory_projects.visible # projects = Project.no_anomory_projects.visible
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size # @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
end end

View File

@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
before_action :check_project_public before_action :check_project_public
def index def index
project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner) project_trends = @project.project_trends.preload(:user, trend: :user)
check_time = params[:time] #时间的筛选 check_time = params[:time] #时间的筛选
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version

View File

@ -1,42 +0,0 @@
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

View File

@ -9,7 +9,7 @@ class Projects::WebhooksController < Projects::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
return render_error("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49 return render_error("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 19
return render_error("参数错误.") unless webhook_params.present? return render_error("参数错误.") unless webhook_params.present?
form = Projects::Webhooks::CreateForm.new(webhook_params) form = Projects::Webhooks::CreateForm.new(webhook_params)
return render json: {status: -1, message: form.errors} unless form.validate! return render json: {status: -1, message: form.errors} unless form.validate!

View File

@ -13,20 +13,16 @@ class ProjectsController < ApplicationController
def menu_list def menu_list
menu = [] menu = []
user_is_admin = current_user.admin? || @project.manager?(current_user)
menu.append(menu_hash_by_name("home")) menu.append(menu_hash_by_name("home"))
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge? menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge? menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki")
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge? menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
menu.append(menu_hash_by_name("activity")) menu.append(menu_hash_by_name("activity"))
menu.append(menu_hash_by_name("sonar")) menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
render json: menu render json: menu
end end
@ -40,9 +36,8 @@ class ProjectsController < ApplicationController
category_id = params[:category_id] category_id = params[:category_id]
@total_count = @total_count =
if category_id.blank? if category_id.blank?
# ps = ProjectStatistic.first ps = ProjectStatistic.first
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank? ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
@projects.total_count
else else
cate = ProjectCategory.find_by(id: category_id) cate = ProjectCategory.find_by(id: category_id)
cate&.projects_count || 0 cate&.projects_count || 0
@ -54,13 +49,6 @@ class ProjectsController < ApplicationController
Projects::CreateForm.new(project_params).validate! Projects::CreateForm.new(project_params).validate!
@project = Projects::CreateService.new(current_user, project_params).call @project = Projects::CreateService.new(current_user, project_params).call
# TODO: fix Educoder shixun
if @project.persisted?
ProjectScore.create(:project_id => @project.id, :score => 0) if @project.project_score.nil?
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @project.id)
@project.project_infos << project_info
end
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -71,7 +59,7 @@ class ProjectsController < ApplicationController
Projects::MigrateForm.new(mirror_params).validate! Projects::MigrateForm.new(mirror_params).validate!
@project = @project =
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr]) if enable_accelerator?(mirror_params[:clone_addr])
source_clone_url = mirror_params[:clone_addr] source_clone_url = mirror_params[:clone_addr]
uid_logger("########## 已动加速器 ##########") uid_logger("########## 已动加速器 ##########")
result = Gitea::Accelerator::MigrateService.call(mirror_params) result = Gitea::Accelerator::MigrateService.call(mirror_params)
@ -83,11 +71,6 @@ class ProjectsController < ApplicationController
else else
Projects::MigrateService.call(current_user, mirror_params) Projects::MigrateService.call(current_user, mirror_params)
end end
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
source_clone_url = mirror_params[:clone_addr]
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
uid_logger("########## 更改clone_addr ##########")
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
else else
Projects::MigrateService.call(current_user, mirror_params) Projects::MigrateService.call(current_user, mirror_params)
end end
@ -99,9 +82,8 @@ class ProjectsController < ApplicationController
def branches def branches
return @branches = [] unless @project.forge? return @branches = [] unless @project.forge?
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name]) @branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
end end
def branches_slice def branches_slice
@ -112,18 +94,18 @@ class ProjectsController < ApplicationController
end end
def group_type_list def group_type_list
# project_statics = ProjectStatistic.first project_statics = ProjectStatistic.first
@project_statics_list = [ @project_statics_list = [
{ {
project_type: 'common', project_type: 'common',
name: '开源托管项目', name: '开源托管项目',
projects_count: Project.common.size || 0 projects_count: project_statics&.common_projects_count || 0
}, },
{ {
project_type: 'mirror', project_type: 'mirror',
name: '开源镜像项目', name: '开源镜像项目',
projects_count: Project.sync_mirror.size + Project.mirror.size || 0 projects_count: project_statics&.mirror_projects_count || 0
} }
] ]
@ -147,7 +129,7 @@ class ProjectsController < ApplicationController
validate_params = project_params.slice(:name, :description, validate_params = project_params.slice(:name, :description,
:project_category_id, :project_language_id, :private, :identifier) :project_category_id, :project_language_id, :private, :identifier)
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate! Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
@ -162,15 +144,6 @@ class ProjectsController < ApplicationController
} }
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params) gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]}) @project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
# 更新对应所属分类下的项目数量(私有)
before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public
after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public
before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id
after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id
before_pc = ProjectCategory.find_by_id(before_pc_id)
after_pc = ProjectCategory.find_by_id(after_pc_id)
before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public
after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public
end end
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
end end
@ -188,8 +161,6 @@ class ProjectsController < ApplicationController
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
@project.destroy! @project.destroy!
@project.forked_projects.update_all(forked_from_project_id: nil) @project.forked_projects.update_all(forked_from_project_id: nil)
# 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量
@project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public
render_ok render_ok
end end
else else
@ -200,22 +171,6 @@ class ProjectsController < ApplicationController
tip_exception(e.message) tip_exception(e.message)
end end
def quit
user_is_admin = current_user.admin? || @project.manager?(current_user)
if !user_is_admin && @project.member(current_user.id) && @project.forge?
ActiveRecord::Base.transaction do
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
render_ok
end
else
render_forbidden('你不能退出该仓库')
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def watch_users def watch_users
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
@watchers_count = watchers.size @watchers_count = watchers.size
@ -229,7 +184,7 @@ class ProjectsController < ApplicationController
end end
def fork_users def fork_users
fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
@forks_count = fork_users.size @forks_count = fork_users.size
@fork_users = paginate(fork_users) @fork_users = paginate(fork_users)
end end

View File

@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
before_action :require_login, except: [:index, :show, :files, :commits] before_action :require_login, except: [:index, :show, :files, :commits]
before_action :require_profile_completed, only: [:create] before_action :require_profile_completed, only: [:create]
before_action :load_repository before_action :load_repository
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge] before_action :check_menu_authorize
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
before_action :load_pull_request, only: [:files, :commits] before_action :load_pull_request, only: [:files, :commits]
before_action :find_atme_receivers, only: [:create, :update] before_action :find_atme_receivers, only: [:create, :update]
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues = issues.distinct @all_issues = issues.distinct
@filter_issues = @all_issues @filter_issues = @all_issues
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present? @filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN}) @open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED}) @close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED}) @merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
end end
def new def new
@all_branches = Branches::ListService.call(@owner, @project, params[:branch_name]) @all_branches = Branches::ListService.call(@owner, @project)
@is_fork = @project.forked_from_project_id.present? @is_fork = @project.forked_from_project_id.present?
@projects_names = [{ @projects_names = [{
project_user_login: @owner.try(:login), project_user_login: @owner.try(:login),
@ -50,20 +50,16 @@ class PullRequestsController < ApplicationController
end end
def get_branches def get_branches
branch_result = Branches::ListService.call(@owner, @project, params[:name]) branch_result = Branches::ListService.call(@owner, @project)
render json: branch_result render json: branch_result
# return json: branch_result # return json: branch_result
end end
def create def create
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
ActiveRecord::Base.transaction do 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) @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
if @gitea_pull_request[:status] == :success if @gitea_pull_request[:status] == :success
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"]) @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
reviewers = User.where(id: params[:reviewer_ids])
@pull_request.reviewers = reviewers
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}" Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
@ -73,8 +69,6 @@ class PullRequestsController < ApplicationController
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
rescue => e
normal_status(-1, e.message)
end end
def edit def edit
@ -84,7 +78,6 @@ class PullRequestsController < ApplicationController
end end
def update def update
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
if params[:title].nil? if params[:title].nil?
normal_status(-1, "名称不能为空") normal_status(-1, "名称不能为空")
elsif params[:issue_tag_ids].nil? elsif params[:issue_tag_ids].nil?
@ -92,11 +85,15 @@ class PullRequestsController < ApplicationController
else else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
merge_params merge_params
reviewers = User.where(id: params[:reviewer_ids]) @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
@pull_request.reviewers = reviewers if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
end
end
if @issue.update_attributes(@issue_params) if @issue.update_attributes(@issue_params)
if @pull_request.update_attributes(@local_params.compact) if @pull_request.update_attributes(@local_params.compact)
@ -105,16 +102,9 @@ class PullRequestsController < ApplicationController
if gitea_pull[:status] === :success if gitea_pull[:status] === :success
if params[:issue_tag_ids].present? if params[:issue_tag_ids].present?
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1 params[:issue_tag_ids].each do |tag|
return normal_status(-1, "最多只能创建一个标记。") IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1 end
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end end
if params[:status_id].to_i == 5 if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now) @issue.issue_times.update_all(end_time: Time.now)
@ -146,8 +136,6 @@ class PullRequestsController < ApplicationController
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user) colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
if colsed === true if colsed === true
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE) @pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
# 合并请求下issue处理为关闭
@issue&.update_attributes!({status_id:5})
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
normal_status(1, "已拒绝") normal_status(1, "已拒绝")
else else
@ -169,7 +157,6 @@ class PullRequestsController < ApplicationController
@issue_assign_to = @issue.get_assign_user @issue_assign_to = @issue.get_assign_user
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login, @gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token) @repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
# @last_review = @pull_request.reviews.take
end end
def pr_merge def pr_merge
@ -193,8 +180,6 @@ class PullRequestsController < ApplicationController
# @pull_request.project_trend_status! # @pull_request.project_trend_status!
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE) @pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
# 合并请求下issue处理为关闭
@issue&.update_attributes!({status_id:5})
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu? SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
normal_status(1, "合并成功") normal_status(1, "合并成功")
else else
@ -212,7 +197,7 @@ class PullRequestsController < ApplicationController
def check_can_merge def check_can_merge
target_head = params[:head] #源分支 target_head = params[:head] #源分支
target_base = params[:base] #目标分支 target_base = params[:base] #目标分支
is_original = params[:is_original] || false is_original = params[:is_original]
if target_head.blank? || target_base.blank? if target_head.blank? || target_base.blank?
normal_status(-2, "请选择分支") normal_status(-2, "请选择分支")
elsif target_head === target_base && !is_original elsif target_head === target_base && !is_original
@ -243,11 +228,11 @@ class PullRequestsController < ApplicationController
private private
def load_pull_request 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]) @pull_request = PullRequest.find params[:id]
end end
def find_pull_request def find_pull_request
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id]) @pull_request = PullRequest.find_by_id(params[:id])
@issue = @pull_request&.issue @issue = @pull_request&.issue
if @pull_request.blank? if @pull_request.blank?
normal_status(-1, "合并请求不存在") normal_status(-1, "合并请求不存在")
@ -258,7 +243,7 @@ class PullRequestsController < ApplicationController
def get_relatived def get_relatived
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json @project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
@project_versions = @project.versions.opening&.select(:id,:name, :status).as_json @project_versions = @project.versions&.select(:id,:name, :status).as_json
@project_members = @project.all_developers @project_members = @project.all_developers
@project_priories = IssuePriority&.select(:id,:name, :position).as_json @project_priories = IssuePriority&.select(:id,:name, :position).as_json
end end
@ -271,12 +256,12 @@ class PullRequestsController < ApplicationController
base: params[:base], #目标分支 base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联 milestone: 0, #里程碑,未与本地的里程碑关联
} }
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
@requests_params = @local_params.merge({ @requests_params = @local_params.merge({
assignee: current_user.try(:login),
# assignees: ["#{params[:assigned_login].to_s}"], # assignees: ["#{params[:assigned_login].to_s}"],
assignees: ["#{assignee_login.to_s}"], assignees: ["#{current_user.try(:login).to_s}"],
labels: params[:issue_tag_ids] labels: params[:issue_tag_ids],
# due_date: Time.now due_date: Time.now
}) })
@issue_params = { @issue_params = {
author_id: current_user.id, author_id: current_user.id,
@ -286,7 +271,7 @@ class PullRequestsController < ApplicationController
assigned_to_id: params[:assigned_to_id], assigned_to_id: params[:assigned_to_id],
fixed_version_id: params[:fixed_version_id], fixed_version_id: params[:fixed_version_id],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
priority_id: params[:priority_id], priority_id: params[:priority_id] || "2",
issue_classify: "pull_request", issue_classify: "pull_request",
issue_type: params[:issue_type] || "1", issue_type: params[:issue_type] || "1",
tracker_id: 2, tracker_id: 2,

View File

@ -1,407 +1,437 @@
class RepositoriesController < ApplicationController class RepositoriesController < ApplicationController
include RepositoriesHelper include RepositoriesHelper
include ApplicationHelper include ApplicationHelper
include OperateProjectAbilityAble include OperateProjectAbilityAble
include Repository::LanguagesPercentagable include Repository::LanguagesPercentagable
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
before_action :require_profile_completed, only: [:create_file] before_action :require_profile_completed, only: [:create_file]
before_action :load_repository before_action :load_repository
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive] before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
before_action :get_ref, only: %i[entries sub_entries top_counts files archive] before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts] before_action :get_statistics, only: %i[top_counts]
before_action :preload_badge, only: [:badges]
def files
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token) def files
render json: result result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
end render json: result
end
# 新版项目详情
def detail
@user = current_user def preload_badge
@result = Repositories::DetailService.call(@owner, @repository, @user) @praised_cache = "praised"
@project_fork_id = @project.try(:forked_from_project_id) @forked_cache = "forked"
if @project_fork_id.present? @watchered_cache = "watchered"
@fork_project = Project.find_by(id: @project_fork_id) @badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
@fork_project_user = @fork_project.owner $redis_cache.hset(project_statistic_key, @many_projects_cache, @badge.many_projects)
end $redis_cache.hset(project_statistic_key, @manyParisesProject_cache, @badge.manyParisesProject)
rescue Exception => e $redis_cache.hset(project_statistic_key, @parises_project_cache, @badge.parises_project)
uid_logger_error(e.message) end
tip_exception(e.message)
end ####################change for repository############################
def show
@user = current_user def badges
@repo = @project.repository preload_badge
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil @badges_dic = Hash.new(0)
@project_fork_id = @project.try(:forked_from_project_id) praises_count = @project.praises_count.to_i
if @project_fork_id.present? forked_count = @project.forked_count.to_i
@fork_project = Project.find_by(id: @project_fork_id) watchers_count = @project.watchers_count.to_i
@fork_project_user = @fork_project.owner
end @praised = judge_level(praises_count, 10, 20,100)
rescue Exception => e redis_judge_reload @praised_cache, @praised
uid_logger_error(e.message) @badges_dic["praised_cache"] = $redis_cache.hget(project_statistic_key, @praised_cache).to_i
tip_exception(e.message)
end @forked = judge_level(forked_count, 5, 10,100)
redis_judge_reload @forked_cache, @forked
def entries @badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
@week_project_visit_record, @month_project_visit_record = TimeableVisitRecord.build(@project.id)
if @week_project_visit_record.visits < 300 && @month_project_visit_record.visits < 1000 @watchered = judge_level(watchers_count, 10, 20,100)
@week_project_visit_record.increment!(:visits) redis_judge_reload @watchered_cache, @watchered
@month_project_visit_record.increment!(:visits) @badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
@project.increment!(:visits)
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
end badges_visable = Array.new
if @project.educoder? @badges_dic.each do |key,value|
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name) if value > 0
else badges_visable.append({"#{key}":value})
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call end
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] end
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" render :json => {list: badges_visable, count: badges_visable.size}
end end
end
##########################################################
def top_counts
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call # 新版项目详情
end def detail
@user = current_user
def sub_entries @result = Repositories::DetailService.call(@owner, @repository, @user)
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip)) @project_fork_id = @project.try(:forked_from_project_id)
if @project_fork_id.present?
if @project.educoder? @fork_project = Project.find_by(id: @project_fork_id)
if params[:type] === 'file' @fork_project_user = @fork_project.owner
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) end
logger.info "######### sub_entries: #{@sub_entries}" rescue Exception => e
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 uid_logger_error(e.message)
tip_exception(e.message)
tmp_entries = { end
"content" => @sub_entries['data']['content'],
"type" => "blob" def show
} @user = current_user
@sub_entries = { @repo = @project.repository
"trees"=>tmp_entries, @result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
"commits" => [{}] @project_fork_id = @project.try(:forked_from_project_id)
} if @project_fork_id.present?
else @fork_project = Project.find_by(id: @project_fork_id)
begin @fork_project_user = @fork_project.owner
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri}) end
if @sub_entries.blank? || @sub_entries['status'].to_i === -1 rescue Exception => e
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) uid_logger_error(e.message)
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 tip_exception(e.message)
tmp_entries = { end
"content" => @sub_entries['data']['content'],
"type" => "blob" def entries
} @project.increment!(:visits)
@sub_entries = { CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
"trees"=>tmp_entries, if @project.educoder?
"commits" => [{}] @entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
} else
end @entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
rescue @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
return render_error('该文件暂未开放,敬请期待.') @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
end end
end end
else
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" def top_counts
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref) @result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
if interactor.success? end
result = interactor.result
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result def sub_entries
else file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
render_error(interactor.error) @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
end
end if @project.educoder?
end if params[:type] === 'file'
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
def commits logger.info "######### sub_entries: #{@sub_entries}"
if @project.educoder? return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
else tmp_entries = [{
if params[:filepath].present? "content" => @sub_entries['data']['content'],
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip)) "type" => "blob"
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri, }]
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call @sub_entries = {
else "trees"=>tmp_entries,
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, "commits" => [{}]
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call }
end else
end @sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
end end
else
def commits_slice interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier, if interactor.success?
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token) result = interactor.result
end @sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
else
def commit render_error(interactor.error)
@sha = params[:sha] end
if @project.educoder? end
return render_error('暂未开放,敬请期待.') end
else
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token) def commits
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token, {diff: true}) if params[:filepath].present?
render_error(@commit[:message], @commit[:status]) if @commit.has_key?(:status) || @commit_diff.has_key?(:status) file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
end @hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
end sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
else
def tags @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
if params[:only_name].present? sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name]) end
end
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
else def commits_slice
name_result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name]) @hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
@tag_names = result.is_a?(Hash) && result.key?(:status) ? [] : name_result end
result = Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) def commit
@sha = params[:sha]
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result @commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
end @commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
end end
def contributors def tags
if params[:filepath].present? || @project.educoder? result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
@contributors = []
else @tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) end
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
end def contributors
rescue if params[:filepath].present?
@contributors = [] @contributors = []
end else
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
def edit end
return render_forbidden if !@project.manager?(current_user) && !current_user.admin? end
end
def edit
def create_file return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) end
if interactor.success?
@file = interactor.result def create_file
# create_new_pr(params) interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
#如果是更新流水线文件 if interactor.success?
if params[:pipeline_id] @file = interactor.result
update_pipeline(params[:pipeline_id]) # create_new_pr(params)
end #如果是更新流水线文件
else if params[:pipeline_id]
render_error(interactor.error) update_pipeline(params[:pipeline_id])
end end
end else
render_error(interactor.error)
def update_pipeline(pipeline_id) end
pipeline = Ci::Pipeline.find(pipeline_id) end
if pipeline
pipeline.update!(sync: 1) def update_pipeline(pipeline_id)
end pipeline = Ci::Pipeline.find(pipeline_id)
end if pipeline
pipeline.update!(sync: 1)
def update_file end
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) end
if interactor.success?
@file = interactor.result def update_file
# TODO: 是否创建pr interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
# create_new_pr(params) if interactor.success?
render_result(1, "更新成功") @file = interactor.result
else # TODO: 是否创建pr
render_error(interactor.error) # create_new_pr(params)
end render_result(1, "更新成功")
end else
render_error(interactor.error)
def delete_file end
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) end
if interactor.success?
@file = interactor.result def delete_file
render_result(1, "文件删除成功") interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
else if interactor.success?
render_error(interactor.error) @file = interactor.result
end render_result(1, "文件删除成功")
end else
render_error(interactor.error)
def repo_hook end
end
end
def repo_hook
def sync_mirror
return render_error("正在镜像中..") if @repository.mirror.waiting? end
@repository.sync_mirror! def sync_mirror
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id) return render_error("正在镜像中..") if @repository.mirror.waiting?
render_ok
end @repository.sync_mirror!
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
def readme render_ok
if params[:filepath].present? end
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], @owner&.gitea_token)
else def readme
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], @owner&.gitea_token) if params[:filepath].present?
end result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
@path = GiteaService.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/" else
@readme = result[:status] === :success ? result[:body] : nil result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path) end
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path) @readme = result[:status] === :success ? result[:body] : nil
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content") @readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref])
rescue render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
render json: nil rescue
end render json: nil
end
def languages
if @project.educoder? def languages
render json: {} render json: languages_precentagable
else end
render json: languages_precentagable
end def archive
end domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
def archive archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
domain = GiteaService.gitea_config[:domain]
api_url = GiteaService.gitea_config[:base_url] file_path = [domain, api_url, archive_url].join
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}" file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
file_path = [domain, api_url, archive_url].join return render_not_found if !request.format.zip? && !request.format.gzip?
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("?")
redirect_to file_path
return render_not_found if !request.format.zip? && !request.format.gzip? end
redirect_to file_path def raw
end domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
def raw
domain = GiteaService.gitea_config[:domain] url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
api_url = GiteaService.gitea_config[:base_url] file_path = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden?
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
file_path = [domain, api_url, url].join redirect_to URI.escape(file_path)
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("&") end
redirect_to file_path private
end
def find_project
private @project = Project.find params[:id]
render_not_found("未找到相关的仓库") unless @project
def find_project end
@project = Project.find params[:id]
render_not_found("未找到相关的仓库") unless @project def find_project_with_includes
end @project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
end
def find_project_with_includes
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id] def authorizate!
end return if current_user && current_user.admin?
if @project.repository.hidden? && !@project.member?(current_user)
def authorizate! render_forbidden
return if current_user && current_user.admin? end
if @project.repository.hidden? && !@project.member?(current_user) end
render_forbidden
end # TODO 获取最新commit信息
end def project_commits
if params[:filepath].present?
# TODO 获取最新commit信息 file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
def project_commits Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
if params[:filepath].present? sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip)) else
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri, Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
else end
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, end
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call
end def get_statistics
end @branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
def get_statistics end
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(@project&.owner&.gitea_token, @project.owner.login, @project.identifier).call&.size def get_ref
end @ref = params[:ref] || @project&.default_branch
end
def get_ref
@ref = params[:ref] || @project&.default_branch def get_latest_commit
end latest_commit = @project.educoder? ? nil : project_commits
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
def get_latest_commit @commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
latest_commit = @project.educoder? ? nil : project_commits end
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0 def content_params
end {
filepath: params[:filepath],
def content_params branch: params[:branch],
{ new_branch: params[:new_branch],
filepath: params[:filepath], content: params[:content],
branch: params[:branch], message: params[:message],
new_branch: params[:new_branch], committer: {
content: params[:content], email: current_user.mail,
message: params[:message], name: current_user.login
committer: { },
email: current_user.mail, identifier: @project.identifier
name: current_user.login }
}, end
identifier: @project.identifier
} def hook_params(hook_type, params)
end # if hook_type == "push"
# # TODO hook返回的记录中暂时没有文件代码数量的增减暂时根据 commits数量来计算
def hook_params(hook_type, params) # uploadPushInfo = {
# if hook_type == "push" # "sha": params["commits"].present? ? params["commits"].last : "",
# # TODO hook返回的记录中暂时没有文件代码数量的增减暂时根据 commits数量来计算 # "branch": params["ref"].to_s.split("/").last,
# uploadPushInfo = { # "modification_lines": params["commits"].length
# "sha": params["commits"].present? ? params["commits"].last : "", # }
# "branch": params["ref"].to_s.split("/").last, # elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
# "modification_lines": params["commits"].length # uploadPushInfo = {
# } # "branch": params["base"]["ref"].to_s.split("/").last,
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作 # "sha": params["pull_request"]["merge_base"],
# uploadPushInfo = { # "modification_lines": 1 #pull_request中没有commits数量
# "branch": params["base"]["ref"].to_s.split("/").last, # }
# "sha": params["pull_request"]["merge_base"], # else
# "modification_lines": 1 #pull_request中没有commits数量 # uploadPushInfo = {}
# } # end
# else
# uploadPushInfo = {} # uploadPushInfo
# end end
# uploadPushInfo def create_new_pr(params)
end if params[:new_branch].present? && params[:new_branch] != params[:branch]
local_params = {
def create_new_pr(params) title: params[:message], #标题
if params[:new_branch].present? && params[:new_branch] != params[:branch] body: params[:content], #内容
local_params = { head: params[:new_branch], #源分支
title: params[:message], #标题 base: params[:branch], #目标分支
body: params[:content], #内容 milestone: 0 #里程碑,未与本地的里程碑关联
head: params[:new_branch], #源分支
base: params[:branch], #目标分支 }
milestone: 0 #里程碑,未与本地的里程碑关联 requests_params = local_params.merge({
assignee: current_user.try(:login),
} assignees: [],
requests_params = local_params.merge({ labels: [],
assignee: current_user.try(:login), due_date: Time.now
assignees: [], })
labels: [],
due_date: Time.now issue_params = {
}) author_id: current_user.id,
project_id: @project.id,
issue_params = { subject: params[:message],
author_id: current_user.id, description: params[:content],
project_id: @project.id, assigned_to_id: nil,
subject: params[:message], fixed_version_id: nil,
description: params[:content], issue_tags_value: nil,
assigned_to_id: nil, issue_classify: "pull_request",
fixed_version_id: nil, issue_type: "1",
issue_tags_value: nil, tracker_id: 2,
issue_classify: "pull_request", status_id: 1,
issue_type: "1", priority_id: params[:priority_id] || "2"
tracker_id: 2, }
status_id: 1, @pull_issue = Issue.new(issue_params)
priority_id: params[:priority_id] || "2" if @pull_issue.save!
} local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
@pull_issue = Issue.new(issue_params) if local_requests.save
if @pull_issue.save! gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id)) if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
if local_requests.save local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call end
if gitea_request[:status] == :success && local_requests.update_attributes(gitea_number: gitea_request["body"]["number"]) end
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") end
end end
end end
end
end
end def judge_level(judged, low, mid, high)
if judged < low
end return 0
elsif judged < mid
return 1
elsif judged < high
return 2
else
return 3
end
end
def redis_judge_reload(judge_cache, new_value)
if $redis_cache.hget(project_statistic_key, judge_cache).to_i != new_value
$redis_cache.del(project_statistic_key)
updateService judge_cache, new_value
load_redis
end
end
def project_statistic_key
"project:#{@project.id}"
end
def updateService(update_name, update_value)
@badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
@badge.update_attribute(update_name,update_value)
@badge.save
end
end

View File

@ -1,20 +0,0 @@
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
@review = Api::V1::Projects::Pulls::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

View File

@ -1,23 +1,13 @@
class SettingsController < ApplicationController class SettingsController < ApplicationController
def show def show
@old_projects_url = nil @old_projects_url = nil
get_navbar
get_add_menu get_add_menu
get_common_menu get_common_menu
get_personal_menu get_personal_menu
get_top_system_notification get_top_system_notification
get_banner
end end
private private
def get_navbar
@navbar = default_laboratory.navbar
if User.current.logged?
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
@navbar << pernal_index
end
end
def get_add_menu def get_add_menu
@add = [] @add = []
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
@ -68,14 +58,4 @@ class SettingsController < ApplicationController
def append_http(url) def append_http(url)
url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('') url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('')
end end
def get_banner
@banner = {
title: EduSetting.get("banner_title") || '大学开源',
sub_title: EduSetting.get("banner_sub_title") || '让大学绽放开源之花',
content: EduSetting.get("banner_content") || "Powered by Trustie and GitLink"
}
@banner
end
end end

View File

@ -1,41 +0,0 @@
class SonarTasksController < ApplicationController
before_action :require_login
before_action :load_project
before_action :authenticate_user!
def index
@sonar_task = SonarTask.find_by(project_id: @project.id)
tip_exception(-1, "代码未检测,请点击开始检测按钮检测!") if @sonar_task.blank?
if @sonar_task.complete_status == 0
service = Sonar::ApiService.new(@project.id)
service.task_result(@sonar_task.task_id)
end
end
def create
Sonar::ApiService.call(@project.id)
render_ok
end
def type_detail
service = Sonar::ApiService.new(@project.id)
@data = service.type_detail(params[:task_id], params[:type])
end
def code_source
service = Sonar::ApiService.new(@project.id)
@data = service.source_code(params[:task_id], params[:component])
Rails.logger.info "data=======#{@data}"
end
private
def authenticate_user!
return if @project.member?(current_user) || current_user.admin? || current_user.business? || educoder_auth_teacher?(current_user)
render_forbidden('你没有权限操作')
end
def educoder_auth_teacher?(user)
user.user_extension&.identity == 'teacher' && user.professional_certification?
end
end

View File

@ -2,24 +2,24 @@ class StatisticController < ApplicationController
# 平台概况 # 平台概况
def platform_profile def platform_profile
@platform_user_query = Statistic::PlatformUserQuery.new(params).call rescue [0, 0, 0] @platform_user_query = Statistic::PlatformUserQuery.new(params).call
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call rescue [0, 0, 0] @platform_project_query = Statistic::PlatformProjectQuery.new(params).call
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call rescue [0, 0, 0] @platform_course_query = Statistic::PlatformCourseQuery.new(params).call
end end
# 平台代码提交数据 # 平台代码提交数据
def platform_code def platform_code
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call rescue [0, 0] @platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call rescue [0, 0] @platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call
end end
# 项目案例活跃度排行榜 # 项目案例活跃度排行榜
def active_project_rank def active_project_rank
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call rescue [] @active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call
end end
# 开发者活跃度排行榜 # 开发者活跃度排行榜
def active_developer_rank def active_developer_rank
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call rescue [] @active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call
end end
end end

View File

@ -1,26 +0,0 @@
class Traces::BaseController < ApplicationController
helper_method :observed_logged_user?, :observed_user
before_action :check_trace_system
def observed_user
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
end
def observed_logged_user?
observed_user.id == User.current&.id
end
protected
def check_auth
return render_forbidden unless current_user.admin? || observed_logged_user?
end
def check_trace_system
code, data, error = Trace::SystemInfoService.call(current_user.trace_token)
return render_ok({code: 501, data: {operate_time: data['operate_time']}, message: '系统维护中'}) if data['status'] === 0
rescue
# 这里根据需求跳转到404
return render_not_found
end
end

View File

@ -1,10 +1,7 @@
class Users::IsPinnedProjectsController < Users::BaseController class Users::IsPinnedProjectsController < Users::BaseController
before_action :private_user_resources!, only: [:pin] before_action :private_user_resources!, only: [:pin]
def index def index
@is_pinned_projects = observed_user.pinned_projects.left_joins(:project) @is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
.where("projects.is_public = TRUE")
.order(position: :desc, created_at: :asc)
.includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
@is_pinned_projects = kaminari_paginate(@is_pinned_projects) @is_pinned_projects = kaminari_paginate(@is_pinned_projects)
end end

View File

@ -1,5 +1,6 @@
class Users::StatisticsController < Users::BaseController class Users::StatisticsController < Users::BaseController
before_action :preload_develop_data, only: [:develop] before_action :preload_develop_data, only: [:develop]
before_action :preload_badge_data, only: [:badges]
# 近期活动统计 # 近期活动统计
def activity def activity
@ -12,7 +13,7 @@ class Users::StatisticsController < Users::BaseController
@commit_data = [] @commit_data = []
date_range.each do |date| date_range.each do |date|
@date_data << date.strftime("%Y.%m.%d") @date_data << date.strftime("%Y.%m.%d")
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size @issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size @pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i} date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
@ -20,6 +21,35 @@ class Users::StatisticsController < Users::BaseController
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data} render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}
end end
###############change###############
# 用户badges 接口 url 路径为/api/users/:user_id/statistic/badges
# 三类
# 第一类 贡献类
# 1. 用户累积获得高星
# 2. 用户关注数超过10人
# 3. 用户的累积获赞人数
# 4. 用户连续一周有commit
# 5. 用户累积pr数
# 第二类 活动类
# 第三类 特殊类
def badges
badges_visable = Array.new
@badges_dic.each do |key,value|
if value > 0
#与describe同理此处应该再增加一个 url字典
describe = @badges_describe_dic[key]
badges_visable.append({"#{key}":value, "describe":describe})
end
end
render :json => {list: badges_visable, count: badges_visable.size}
end
###############change###############
# 开发能力 # 开发能力
def develop def develop
if params[:start_time].present? && params[:end_time].present? if params[:start_time].present? && params[:end_time].present?
@ -216,4 +246,207 @@ class Users::StatisticsController < Users::BaseController
@platform_project_languages_count = JSON.parse(@platform_result["project-language"]) @platform_project_languages_count = JSON.parse(@platform_result["project-language"])
end end
end end
end end
def count_filter(collection, count_field, countf)
return collection.where("#{count_field} >= ?", countf)
end
# 判断是否拥有
def judge_have(judged, count)
return judged >= count ? 1 : 0
end
# 判断等级
def judge_level(judged, low, mid, high)
if judged < low
return 0
elsif judged < mid
return 1
elsif judged < high
return 2
else
return 3
end
end
###############change###############
# 用户badges 接口 url 路径为/api/users/:user_id/statistic/badges
# 三类
# 第一类 贡献类
# 2.用户有项目获得高星
# 3.用户有数个高星项目
# 4.用户拥有一个点赞数很高的项目
# 5.用户拥有数个点赞数很高的项目
# 6. 用户关注数超过10人
# 7. 用户的累积获赞人数
# 8. 用户累积pr数
# 第二类 活动类
# 第三类 活跃类
# 1. 用户拥有10个项目以上
# 2. 用户连续一周/月有commit
# 3. 用户涨粉迅速
def preload_badge_data
badge_describe
cache_describe
#加载缓存资源
load_redis
#存放用户获得的徽章字典
@badges_dic = Hash.new(0)
# 有些数据可以考虑直接从缓存中读取,由于题目要求不能破坏原本的函数,暂时缓存写了直接查询,
# 例如 Watcher.where(watchable: observed_user).count 可以用@user_result["follow-count"]来替代
#
@user_result = Cache::V2::UserStatisticService.new(observed_user.id).read
# 用户项目获得的徽章
#用户语言数量 y
# 用户项目数量 y
project_count = @user_result["project-count"].to_i
if project_count > 10
@badges_dic["project_count"] = project_count
end
# 用户点赞数量 y
# 用户项目被follow数量
praises_project_count = count_filter(Project.where(user_id:observed_user.id), 'praises_count' , 10).count
praises_project = Project.where(user_id:observed_user.id).maximum('praises_count')
watchers_project_count = count_filter(Project.where(user_id:observed_user.id), 'watchers_count' , 10).count
watchers_project = Project.where(user_id:observed_user.id).maximum('watchers_count')
# 项目数
@many_projects = judge_have(project_count, 5)
redis_judge_reload @many_projects_cache, @many_projects
@badges_dic["many_projects"] = $redis_cache.hget(user_statistic_key, @many_projects_cache).to_i
# 用户有超过五个以上的高点赞项目
@manyParisesProject = judge_have(praises_project_count, 5)
redis_judge_reload @manyParisesProject_cache, @manyParisesProject
@badges_dic["manyParisesProject"] = $redis_cache.hget(user_statistic_key, @manyParisesProject_cache).to_i
#用户有一个点赞数很高的项目 金/银/铜
@parises_project = judge_level(praises_project, 3, 5, 10)
redis_judge_reload @many_projects_cache, @parises_project
@badges_dic["parises_project"] = $redis_cache.hget(user_statistic_key, @parises_project_cache).to_i
# 用户有超过五个以上的高关注项目
@manyWatchersProject = judge_have(watchers_project_count, 5)
redis_judge_reload @manyWatchersProject_cache, @manyWatchersProject
@badges_dic["manyWatchersProject"] = $redis_cache.hget(user_statistic_key, @manyWatchersProject_cache).to_i
#用户有一个关注数很高的项目 金/银/铜
@watchers_project = judge_level(watchers_project, 3, 5, 10)
redis_judge_reload @watchers_project_cache, @watchers_project
@badges_dic["watchers_project"] = $redis_cache.hget(user_statistic_key, @watchers_project_cache).to_i
# 用户被follow数量 y
fans = Watcher.where(watchable: observed_user).count
# 用户pr数量 y
pr = PullRequest.where(user_id: observed_user.id).count
# 用户issue数量 y
issue = Issue.where(author_id: observed_user.id).count
#用户有关注数很多 金/银/铜
@many_fans = judge_level(fans, 5, 50, 100)
redis_judge_reload @many_fans_cache, @many_fans
@badges_dic["many_fans"] = $redis_cache.hget(user_statistic_key, @many_fans_cache).to_i
#用户pr很多 金/银/铜
@many_pr = judge_level(pr, 5, 50, 100)
redis_judge_reload @many_pr_cache, @many_pr
@badges_dic["many_pr"] = $redis_cache.hget(user_statistic_key, @many_pr_cache).to_i
#用户issue很多 金/银/铜
@many_issue = judge_level(issue, 5, 50, 100)
redis_judge_reload @many_issue_cache, @many_issue
@badges_dic["many_issue"] = $redis_cache.hget(user_statistic_key, @many_issue_cache).to_i
#一周内活跃
commit_request = Gitea::User::HeadmapService.call(observed_user.login, 1.week.ago.to_date.to_time.to_i, Date.today.to_time.to_i)
commit_data = commit_request[2]
active_commit = commit_data.select{|item| item["contributions"] >= 1}.size
@active_in_week = active_commit == 7 ? 1 : 0
@badges_dic["active_in_week"] = $redis_cache.hget(user_statistic_key, @active_in_week_cache).to_i
#TODO fans_raise_quickly
end
def user_statistic_key
"user:#{@user_id}"
end
def redis_judge_reload(judge_cache, new_value)
if $redis_cache.hget(user_statistic_key, judge_cache).to_i != new_value
$redis_cache.del(user_statistic_key)
updateService judge_cache, new_value
load_redis
end
end
def cache_describe
@many_projects_cache = "many_projects"
@manyParisesProject_cache = "manyParisesProject"
@parises_project_cache = "parises_project"
@manyWatchersProject_cache = "manyWatchersProject"
@watchers_project_cache = "watchers_project"
@many_fans_cache = "many_fans"
@many_pr_cache = "many_pr"
@many_issue_cache = "many_issue"
@active_in_week_cache = "active_in_week"
end
def badge_describe
@badges_describe_dic = Hash.new(0)
@badges_describe_dic["many_projects"] = "参与了多个project"
@badges_describe_dic["manyParisesProject"] = "有多个点赞数高的project"
@badges_describe_dic["parises_project"] = "有一个项目获得了很高的点赞数!"
@badges_describe_dic["manyWatchersProject"] = "有多个关注三诉讼诉讼诉讼诉讼诉讼诉讼数高的project"
@badges_describe_dic["watchers_project"] = "有一个项目获得了很高的关注数!"
@badges_describe_dic["watchers_project"] = "有一个项目获得了很高的关注数!"
@badges_describe_dic["many_fans"] = "粉丝数很多!"
@badges_describe_dic["many_fans"] = "贡献了很多pr"
@badges_describe_dic["many_pr"] = "贡献了很多issue"
@badges_describe_dic["many_issue"] = "粉丝数很多!"
@badges_describe_dic["active_in_week"] = "一周活跃打卡成就!"
end
def load_redis
@badge = Badge.find_or_create_by(user_id: observed_user.id)
$redis_cache.hset(user_statistic_key, @many_projects_cache, @badge.many_projects)
$redis_cache.hset(user_statistic_key, @manyParisesProject_cache, @badge.manyParisesProject)
$redis_cache.hset(user_statistic_key, @parises_project_cache, @badge.parises_project)
$redis_cache.hset(user_statistic_key, @manyWatchersProject_cache, @badge.manyWatchersProject)
$redis_cache.hset(user_statistic_key, @watchers_project_cache, @badge.watchers_project)
$redis_cache.hset(user_statistic_key, @many_fans_cache, @badge.many_fans)
$redis_cache.hset(user_statistic_key, @many_pr_cache, @badge.many_pr)
$redis_cache.hset(user_statistic_key, @many_issue_cache, @badge.many_issue)
$redis_cache.hset(user_statistic_key, @active_in_week_cache, @badge.active_in_week)
end
def updateService(update_name, update_value)
#添加事务,如果更新失败则回滚
ActiveRecord::Base.transaction do
@badge = Badge.find_or_create_by!(user_id: observed_user.id)
@badge.update_attributes!(update_name => update_value)
@badge.save!
end
end

View File

@ -23,8 +23,6 @@ class Users::TemplateMessageSettingsController < Users::BaseController
def get_current_setting def get_current_setting
@current_setting = @_observed_user.user_template_message_setting @current_setting = @_observed_user.user_template_message_setting
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil? @current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
end end
def setting_params def setting_params

View File

@ -1,373 +1,312 @@
class UsersController < ApplicationController class UsersController < ApplicationController
include ApplicationHelper include ApplicationHelper
include Ci::DbConnectable include Ci::DbConnectable
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard] before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
before_action :require_login, only: %i[me list] before_action :require_login, only: %i[me list sync_user_info]
before_action :connect_to_ci_db, only: [:get_user_info] before_action :connect_to_ci_db, only: [:get_user_info]
before_action :convert_image!, only: [:update] before_action :convert_image!, only: [:update]
skip_before_action :check_sign, only: [:attachment_show] skip_before_action :check_sign, only: [:attachment_show]
def connect_to_ci_db(options={}) def connect_to_ci_db(options={})
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?) if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
return return
end end
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
connect_to_trustie_ci_database(options) connect_to_trustie_ci_database(options)
else else
connect_to_ci_database(options) connect_to_ci_database(options)
end end
end end
def list def list
scope = User.active.recent.like(params[:search]).includes(:user_extension) scope = User.active.recent.like(params[:search]).includes(:user_extension)
@total_count = scope.size @total_count = scope.size
@users = paginate(scope) @users = paginate(scope)
end end
def show def show
#待办事项,现在未做 #待办事项,现在未做
if User.current.admin? || User.current.login == @user.login if User.current.admin? || User.current.login == @user.login
@waiting_applied_messages = @user.applied_messages.waiting @waiting_applied_messages = @user.applied_messages.waiting
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common @common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common @common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size @undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
else else
@waiting_applied_messages = AppliedMessage.none @waiting_applied_messages = AppliedMessage.none
@common_applied_transfer_projects = AppliedTransferProject.none @common_applied_transfer_projects = AppliedTransferProject.none
@common_applied_projects = AppliedProject.none @common_applied_projects = AppliedProject.none
@undo_events = 0 @undo_events = 0
end end
#用户的组织数量 #用户的组织数量
# @user_composes_count = @user.composes.size # @user_composes_count = @user.composes.size
@user_composes_count = 0 @user_composes_count = 0
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common") user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
@user_org_count = user_organizations.size @user_org_count = user_organizations.size
normal_projects = Project.members_projects(@user.id).to_sql normal_projects = Project.members_projects(@user.id).to_sql
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
@projects_common_count = user_projects.common.size @projects_common_count = user_projects.common.size
@projects_mirrior_count = user_projects.mirror.size @projects_mirrior_count = user_projects.mirror.size
@projects_sync_mirrior_count = user_projects.sync_mirror.size @projects_sync_mirrior_count = user_projects.sync_mirror.size
end # 为了缓存活跃用户的基本信息,后续删除
Cache::V2::OwnerCommonService.new(@user.id).read
def watch_users end
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
if params[:search].present? def watch_users
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id) watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
watchers = watchers.where(watchable_id: search_user_ids) if params[:search].present?
end search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
@watchers_count = watchers.size watchers = watchers.where(watchable_id: search_user_ids)
@watchers = paginate(watchers) end
end @watchers_count = watchers.size
@watchers = paginate(watchers)
def fan_users end
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
watchers = watchers.joins(:user).merge(User.like(params[:search])) def fan_users
@watchers_count = watchers.size watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
@watchers = paginate(watchers) watchers = watchers.joins(:user).merge(User.like(params[:search]))
end @watchers_count = watchers.size
@watchers = paginate(watchers)
def hovercard end
end
def hovercard
def update end
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) def update
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
@user.attributes = user_params.except(:image) return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
unless @user.save Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
render_error(@user.errors.full_messages.join(", ")) @user.attributes = user_params.except(:image)
end unless @user.save
end render_error(@user.errors.full_messages.join(", "))
end
def update_image end
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) def me
@user = current_user
Util.write_file(@image, avatar_path(@user)) end
return render_ok({message: '头像修改成功'})
rescue Exception => e # 贴吧获取用户信接口
uid_logger_error(e.message) def get_user_info
render_error(-1, '头像修改失败!') begin
end @user = current_user
begin
def get_image result = Notice::Read::CountService.call(current_user.id)
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id]) @message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) rescue
@message_unread_total = 0
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s end
end # TODO 等消息上线再打开注释
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
def me rescue Exception => e
@user = current_user uid_logger_error(e.message)
end missing_template
end
# 贴吧获取用户信接口
def get_user_info end
begin
@user = current_user def attachment_show
begin file_name = params[:file_name]
result = Notice::Read::CountService.call(current_user.id) path = params[:path] || file_storage_directory
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"] send_file "#{path}/#{file_name}", :filename => "#{file_name}",
rescue :type => 'game',
@message_unread_total = 0 :disposition => 'attachment' #inline can open in browser
end end
# TODO 等消息上线再打开注释
#@tidding_count = unviewed_tiddings(current_user) if current_user.present? def html_show
rescue Exception => e @contents = File.read("#{params[:path]}")
uid_logger_error(e.message) respond_to do |format|
missing_template format.html {render :layout => false}
end end
end
end
# Redo: 消息总数缓存
def attachment_show def get_navigation_info
file_name = params[:file_name] # @old_domain = edu_setting('old_edu_host')
path = params[:path] || file_storage_directory # @user = current_user
send_file "#{path}/#{file_name}", :filename => "#{file_name}", # # 新消息数
:type => 'game', # @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
:disposition => 'attachment' #inline can open in browser #
end # @user_url = "/users/#{@user.login}"
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
def html_show # @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
@contents = File.read("#{params[:path]}") end
respond_to do |format|
format.html {render :layout => false} # 用户回复功能
end def reply_message
end message = JournalsForMessage.new(reply_message_params)
message.user_id = current_user.id
# Redo: 消息总数缓存 message.save!
def get_navigation_info
# @old_domain = edu_setting('old_edu_host') render_ok(id: message.id)
# @user = current_user end
# # 新消息数
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0 # 搜索用户具有管理员角色的项目
# def search_user_projects
# @user_url = "/users/#{@user.login}" projects = Project.where.not(status: 9)
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
end projects = projects.where(members: { user_id: current_user.id })
# 用户回复功能 search = params[:search].to_s.strip
def reply_message projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
message = JournalsForMessage.new(reply_message_params)
message.user_id = current_user.id @projects = projects.select(:id, :name)
message.save! end
render_ok(id: message.id) #TODO 个人主页信息forge上弃用-hs, 0602
end def homepage_info
#待办事项,现在未做
# 搜索用户具有管理员角色的项目 @undo_events = 10
def search_user_projects #用户的组织数量
projects = Project.where.not(status: 9) # @user_composes_count = @user.composes.size
@user_composes_count = 10
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 }) end
projects = projects.where(members: { user_id: current_user.id })
def brief_introduction
search = params[:search].to_s.strip content = params[:content].to_s.strip
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
current_user.user_extension.update!(brief_introduction: content)
@projects = projects.select(:id, :name)
end render_ok
end
#TODO 个人主页信息forge上弃用-hs, 0602
def homepage_info def attendance
#待办事项,现在未做 attendance = Users::AttendanceService.call(current_user)
@undo_events = 10 render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
#用户的组织数量 rescue Users::AttendanceService::Error => ex
# @user_composes_count = @user.composes.size render_error(ex.message)
@user_composes_count = 10 end
end
# 其他平台登录后必须将token同步到forge平台实现sso登录功能
def brief_introduction def sync_token
content = params[:content].to_s.strip return render_error('未找相关用户!') unless @user
current_user.user_extension.update!(brief_introduction: content) token = Token.get_or_create_permanent_login_token(@user, 'autologin')
token.update_column(:value, params[:token])
render_ok render_ok
end end
def attendance def trustie_related_projects
attendance = Users::AttendanceService.call(current_user) projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
render_ok(grade: current_user.grade, next_gold: attendance.next_gold) projects_json = []
rescue Users::AttendanceService::Error => ex domain_url = EduSetting.get('host_name')
render_error(ex.message) if projects.present?
end projects.each do |p|
project_url = "/#{p.owner.login}/#{p.identifier}"
# 其他平台登录后必须将token同步到forge平台实现sso登录功能 pj = {
def sync_token id: p.id,
return render_error('未找相关用户!') unless @user name: p.name,
is_public: p.is_public,
token = Token.get_or_create_permanent_login_token(@user, 'autologin') updated_on: p.updated_on.strftime("%Y-%m-%d"),
token.update_column(:value, params[:token]) status: p.status,
render_ok is_member: p.member?(current_user.try(:id)),
end owner: {
name: p.owner.try(:show_real_name),
def trustie_related_projects login: p.owner.login
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc") },
projects_json = [] members_count: p&.members.size,
domain_url = EduSetting.get('host_name') + '/projects' issues_count: p.issues_count - p.pull_requests_count,
if projects.present? commits_count: p&.project_score&.changeset_num.to_i,
projects.each do |p| http_url: domain_url + project_url,
project_url = "/#{p.owner.login}/#{p.identifier}" http_collaborator_url: domain_url + project_url + "/setting/collaborator",
pj = { http_issues_url: domain_url + project_url + "/issues",
id: p.id, http_commits_url: domain_url + project_url + "/commits",
name: p.name, project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
is_public: p.is_public, }
updated_on: p.updated_on.strftime("%Y-%m-%d"), projects_json.push(pj)
status: p.status, end
is_member: p.member?(current_user.try(:id)), end
owner: { Rails.logger.info("==========projects_json========+########{projects_json}")
name: p.owner.try(:show_real_name), render json: { projects: projects_json.present? ? projects_json : {} }
login: p.owner.login end
},
members_count: p&.members.size, def trustie_projects
issues_count: p.issues_count - p.pull_requests_count, user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
commits_count: p&.project_score&.changeset_num.to_i, projects = Project.visible
http_url: domain_url + project_url,
http_collaborator_url: domain_url + project_url + "/setting/collaborator", projects = projects.joins(:members).where(members: { user_id: user_id })
http_issues_url: domain_url + project_url + "/issues",
http_commits_url: domain_url + project_url + "/commits", search = params[:search].to_s.strip
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {} projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
}
projects_json.push(pj) projects = projects.select(:id, :name).limit(10).as_json
end render json: { projects: projects }
end end
Rails.logger.info("==========projects_json========+########{projects_json}")
render json: { projects: projects_json.present? ? projects_json : {} } def projects
end is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
def trustie_projects @total_count = scope.size
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id @projects = paginate(scope)
projects = Project.visible end
projects = projects.joins(:members).where(members: { user_id: user_id }) # TODO 其他平台登录时同步修改gitea平台对应用户的密码
# 该方法主要用于别的平台初次部署对接forge平台同步用户后gitea平台对应的用户密码与forge平台用户密码不一致是问题
search = params[:search].to_s.strip def sync_gitea_pwd
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present? return render_error("未找到相关的用户") if @user.blank?
projects = projects.select(:id, :name).limit(10).as_json flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
render json: { projects: projects } flag ? render_ok : render_error('同步失败!')
end end
def projects # TODO
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id) # 同步trusite平台用户的salt信息只需同步一次同步完成后该方法可以删除
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user) def sync_salt
@total_count = scope.size user = User.find_by_login params[:login]
@projects = paginate(scope) return if user.blank?
end user.update_column(:salt, params[:salt])
render_ok
# TODO 其他平台登录时同步修改gitea平台对应用户的密码 end
# 该方法主要用于别的平台初次部署对接forge平台同步用户后gitea平台对应的用户密码与forge平台用户密码不一致是问题
def sync_gitea_pwd def sync_user_info
return render_error("未找到相关的用户") if @user.blank? user = User.find_by_login params[:login]
return render_forbidden unless user === current_user
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
flag ? render_ok : render_error('同步失败!') sync_params = {
end email: params[:email],
password: params[:password]
# TODO }
# 同步trusite平台用户的salt信息只需同步一次同步完成后该方法可以删除
def sync_salt Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
user = User.find_by_login params[:login]
return if user.blank? interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
user.update_column(:salt, params[:salt]) if interactor.success?
render_ok user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO)
end render_ok
else
# TODO: For Educoder render_error(interactor.error)
def change_password end
user = User.find_by_login params[:login] end
return render_error("用户 #{params[:login]} 不存在.") if user.nil?
private
form_params= { def load_user
login: params[:login], @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
email: user&.mail, end
password: params[:password],
user: user def user_params
} params.require(:user).permit(:nickname, :image,
Gitea::User::ChangePasswordForm.new(form_params).validate! user_extension_attributes: [
:gender, :location, :location_city,
sync_params = { :occupation, :technical_title,
password: params[:password].to_s, :school_id, :department_id, :province, :city,
email: user.mail, :custom_department, :identity, :student_id, :description,
login_name: user.login, :show_email, :show_location, :show_department]
source_id: 0 )
} end
if sync_params.present? def reply_message_params
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params) normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
if interactor.success? params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
user.update!(password: params[:password], is_sync_pwd: true) params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
render_ok end
else
render_error(interactor.error) def check_user_exist
end return if @user.present?
end render_not_found
end end
# TODO: For Educoder end
def change_email
user = User.find_by_login params[:login]
return render_error("用户 #{rq_params[:login]} 不存在.") if user.nil?
form_params= {
login: params[:login],
email: user&.mail,
user: user
}
Gitea::User::ChangeEmailForm.new(form_params).validate!
sync_params = {
email: params[:email]
}
if sync_params.present?
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
if interactor.success?
user.update!(mail: params[:email])
render_ok
else
render_error(interactor.error)
end
end
end
def email_search
return render_error('请输入email') if params[:email].blank?
@user = User.find_by(mail: params[:email])
end
private
def load_user
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
end
def user_params
params.require(:user).permit(:nickname, :image,
user_extension_attributes: [
:gender, :location, :location_city,
:occupation, :technical_title,
:school_id, :department_id, :province, :city,
:custom_department, :identity, :student_id, :description,
:show_super_description, :super_description,
:show_email, :show_location, :show_department]
)
end
def reply_message_params
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
end
def check_user_exist
return if @user.present?
render_not_found
end
end

View File

@ -14,7 +14,7 @@ class VersionReleasesController < ApplicationController
def new def new
#获取所有的分支 #获取所有的分支
@all_branches = [] @all_branches = []
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier), params[:branch_name]).call get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
if get_all_branches && get_all_branches.size > 0 if get_all_branches && get_all_branches.size > 0
get_all_branches.each do |b| get_all_branches.each do |b|
@all_branches.push(b["name"]) @all_branches.push(b["name"])

View File

@ -1,13 +1,13 @@
--- ---
title: GitLink API Reference title: Trustie API Reference
language_tabs: # must be one of https://git.io/vQNgJ language_tabs: # must be one of https://git.io/vQNgJ
- shell: Shell - shell: Shell
- javascript: JavaScript - javascript: JavaScript
toc_footers: toc_footers:
- <a href='https://www.gitlink.org.cn/login'>Sign In for a User</a> - <a href='https://www.trustie.net/login?login=false'>Sign Up for a User</a>
- <a href='https://www.gitlink.org.cn'>Powered by GitLink</a> - <a href='https://www.trustie.net'>Powered by Trustie</a>
includes: includes:
- licenses - licenses
@ -30,8 +30,8 @@ code_clipboard: true
# Introduction # Introduction
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. 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.
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. 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 [GitLink](https://www.gitlink.org.cn). 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 [Trustie](https://www.trustie.net). Feel free to edit it and use it as a base for your own API's documentation.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Some files were not shown because too many files have changed in this diff Show More