Compare commits

..

5 Commits

Author SHA1 Message Date
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
231 changed files with 2942 additions and 10272 deletions

2
.gitignore vendored
View File

@ -74,7 +74,6 @@ vendor/bundle/
/log
/public/admin
/mysql_data
/public/repo/
.generators
@ -86,4 +85,3 @@ redis_data/
Dockerfile
dump.rdb
.tags*
ceshi_user.xlsx

529
.merge_file_a17580 Normal file
View File

@ -0,0 +1,529 @@
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import {LocaleProvider} from 'antd'
import zhCN from 'antd/lib/locale-provider/zh_CN';
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';
import axios from 'axios';
import '@icedesign/base/dist/ICEDesignBase.css';
import '@icedesign/base/index.scss';
import LoginDialog from './modules/login/LoginDialog';
import Notcompletedysl from './modules/user/Notcompletedysl';
import Trialapplicationysl from './modules/login/Trialapplicationysl';
import Trialapplicationreview from './modules/user/Trialapplicationreview';
import Addcourses from "./modules/courses/coursesPublic/Addcourses";
import AccountProfile from"./modules/user/AccountProfile";
import Trialapplication from './modules/login/Trialapplication'
import NotFoundPage from './NotFoundPage'
import Loading from './Loading'
import Loadable from 'react-loadable';
import moment from 'moment'
import {MuiThemeProvider, createMuiTheme} from 'material-ui/styles';
// import './AppConfig'
import history from './history';
import {SnackbarHOC} from 'educoder'
import {initAxiosInterceptors} from './AppConfig'
// tpi需要这个来加载css
import {TPMIndexHOC} from './modules/tpm/TPMIndexHOC';
const theme = createMuiTheme({
palette: {
primary: {
main: '#4CACFF',
contrastText: 'rgba(255, 255, 255, 0.87)'
},
secondary: {main: '#4CACFF'}, // #11cb5f This is just green.A700 as hex.
},
});
//
// const Trialapplication= Loadable({
// loader: () =>import('./modules/login/Trialapplication'),
// loading:Loading,
// })
//登入
const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'),
loading: Loading,
})
const TestIndex = Loadable({
loader: () => import('./modules/test'),
loading: Loading,
})
const IndexWrapperComponent = Loadable({
loader: () => import('./modules/page/IndexWrapper'),
loading: Loading,
})
const CommentComponent = Loadable({
loader: () => import('./modules/comment/CommentContainer'),
loading: Loading,
})
const TestMaterialDesignComponent = Loadable({
loader: () => import('./modules/test/md/TestMaterialDesign'),
loading: Loading,
})
const TestCodeMirrorComponent = Loadable({
loader: () => import('./modules/test/codemirror/TestCodeMirror'),
loading: Loading,
})
const TestComponent = Loadable({
loader: () => import('./modules/test/TestRC'),
loading: Loading,
})
const TestUrlQueryComponent = Loadable({
loader: () => import('./modules/test/urlquery/TestUrlQuery'),
loading: Loading,
})
const TPMIndexComponent = Loadable({
loader: () => import('./modules/tpm/TPMIndex'),
loading: Loading,
})
const TPMShixunsIndexComponent = Loadable({
loader: () => import('./modules/tpm/shixuns/ShixunsIndex'),
loading: Loading,
})
//实训课程(原实训路径)
const ShixunPaths = Loadable({
loader: () => import('./modules/paths/Index'),
loading: Loading,
})
//在线课堂
const CoursesIndex = Loadable({
loader: () => import('./modules/courses/Index'),
loading: Loading,
})
const SearchPage = Loadable({
loader: () => import('./search/SearchPage'),
loading: Loading,
})
//教学案例
const MoopCases = Loadable({
loader: () => import('./modules/moop_cases/index'),
loading: Loading,
})
// 课堂讨论
// const BoardIndex = Loadable({
// loader: () => import('./modules/courses/boards/BoardIndex'),
// loading:Loading,
// })
// //课堂普通作业&分组作业
// const CoursesWorkIndex = Loadable({
// loader: () => import('./modules/courses/busyWork/Index'),
// loading:Loading,
// })
//
// const TPMShixunchildIndexComponent = Loadable({
// loader: () => import('./modules/tpm/shixunchild/ShixunChildIndex'),
// loading: Loading,
// })
// const TPMshixunfork_listIndexComponent = Loadable({
// loader: () => import('./modules/tpm/shixunchild/Shixunfork_list'),
// loading: Loading,
// })
const ForumsIndexComponent = Loadable({
loader: () => import('./modules/forums/ForumsIndex'),
loading: Loading,
})
// trustie plus forum
// const TPForumsIndexComponent = Loadable({
// loader: () => import('./modules/tp-forums/TPForumsIndex'),
// loading: Loading,
// })
// const TestPageComponent = Loadable({
// loader: () => import('./modules/page/Index'),
// loading: Loading,
// })
//新建实训
const Newshixuns = Loadable({
loader: () => import('./modules/tpm/newshixuns/Newshixuns'),
loading: Loading,
})
//实训首页
const ShixunsHome = Loadable({
loader: () => import('./modules/home/shixunsHome'),
loading: Loading,
})
const CompatibilityPageLoadable = Loadable({
loader: () => import('./modules/common/CompatibilityPage'),
loading: Loading,
})
//403页面
const Shixunauthority = Loadable({
loader: () => import('./modules/403/Shixunauthority'),
loading: Loading,
})
//404页面
const Shixunnopage = Loadable({
loader: () => import('./modules/404/Shixunnopage'),
loading: Loading,
})
//500页面
const http500 = Loadable({
loader: () => import('./modules/500/http500'),
loading: Loading,
})
// 登录注册
const LoginRegisterPage = Loadable({
loader: () => import('./modules/user/LoginRegisterPage'),
loading: Loading,
})
const AccountPage = Loadable({
loader: () => import('./modules/user/AccountPage'),
loading: Loading,
})
// 个人主页
const UsersInfo = Loadable({
loader: () => import('./modules/user/usersInfo/Infos'),
loading: Loading,
})
// 兴趣页面
const Interestpage = Loadable({
loader: () => import('./modules/login/EducoderInteresse'),
loading: Loading,
})
//众包创新
const ProjectPackages=Loadable({
loader: () => import('./modules/projectPackages/ProjectPackageIndex'),
loading: Loading,
})
class App extends Component {
constructor(props) {
super(props)
// this.state = {
// isRenders:false,
// }
}
componentDidMount() {
// force an update if the URL changes
history.listen(() => {
this.forceUpdate()
const $ = window.$
// https://www.trustie.net/issues/21919 可能会有问题
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props)
//
// axios.interceptors.response.use((response) => {
// // console.log("response"+response);
// if(response!=undefined)
// // console.log("response"+response.data.statu);
// if (response&&response.data.status === 407) {
// this.setState({
// isRenders: true,
// })
// }
// return response;
// }, (error) => {
// //TODO 这里如果样式变了会出现css不加载的情况
// });
}
//修改登录方法
Modifyloginvalue=()=>{
this.setState({
isRender:false,
})
}
render() {
return (
<LocaleProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
<Addcourses {...this.props} {...this.state}/>
<AccountProfile {...this.props} {...this.state}/>
{/*{*/}
{/* isRender === true?*/}
{/* <LoginDialog></LoginDialog> : ""*/}
{/*}*/}
{/*{*/}
{/* isRenders === true?*/}
{/*<Trialapplication></Trialapplication>*/}
{/*:""*/}
{/*}*/}
<Router>
<Switch>
{/*<Route path="/login" component={LoginRegisterPage}/>*/}
{/*众包创新*/}
<Route path={"/crowdsourcings"} component={ProjectPackages}/>
{/*认证*/}
<Route path="/account" component={AccountPage}/>
{/*403*/}
<Route path="/403" component={Shixunauthority}/>
<Route path="/500" component={http500}/>
{/*404*/}
<Route path="/nopage" component={Shixunnopage}/>
<Route path="/compatibility" component={CompatibilityPageLoadable}/>
<Route
path="/login" component={EducoderLogin}
/>
<Route
path="/register" component={EducoderLogin}
/>
<Route path="/users/:username"
render={
(props) => (<UsersInfo {...this.props} {...props} {...this.state} />)
}></Route>
{/*<Route*/}
{/* path="/trialapplication" component={Trialapplication}*/}
{/*/>*/}
<Route
path="/changepassword" component={EducoderLogin}
/>
<Route
path="/interesse" component={Interestpage}
/>
<Route path="/shixuns/new" component={Newshixuns}>
</Route>
<Route path="/tasks/:stageId" component={IndexWrapperComponent}/>
<Route path="/shixuns/:shixunId" component={TPMIndexComponent}>
</Route>
{/*列表页*/}
<Route path="/shixuns" component={TPMShixunsIndexComponent}/>
{/* <Route path="/shixunchild" component={TPMShixunchildIndexComponent}>
</Route>
<Route path="/fork_list" component={TPMshixunfork_listIndexComponent}>
</Route> */}
{/*<Route path="/forums" component={ForumsIndexComponent}>*/}
{/*</Route>*/}
{/*实训课程(原实训路径)*/}
<Route path="/paths" component={ShixunPaths}></Route>
<Route path="/search"
render={
(props)=>(<SearchPage {...this.props} {...props} {...this.state}></SearchPage>)
}
></Route>
{/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props}></Route>
{/* 课堂讨论 */}
{/* <Route path="/board" component = {BoardIndex} {...this.props}></Route> */}
{/* <Route path="/tpforums" component={TPForumsIndexComponent}>
</Route> */}
{/* <Route path="/myshixuns/:shixunId/stages/:stageId" component={Index}/> */}
{/* 兴趣页面*/}
{/*<Route path="/interest" component={Interestpage}/>*/}
<Route path="/comment" component={CommentComponent}/>
<Route path="/testMaterial" component={TestMaterialDesignComponent}/>
<Route path="/test" component={TestIndex}/>
<Route path="/testCodeMirror" component={TestCodeMirrorComponent}/>
<Route path="/testRCComponent" component={TestComponent}/>
<Route path="/testUrlQuery" component={TestUrlQueryComponent}/>
{/* 教学案例 */}
<Route path="/moop_cases"render={
(props) => (<MoopCases {...this.props} {...props} {...this.state} />)
}/>
{/* <Route component={NotFoundPage}/> */}
{/*列表页*/}
{/*<Route component={TPMShixunsIndexComponent}/>*/}
{/*首页*/}
<Route exact path="/" component={ShixunsHome}/>
<Route component={Shixunnopage}/>
{/*<Route component={ShixunsHome}/>*/}
</Switch>
</Router>
</MuiThemeProvider>
</LocaleProvider>
);
}
}
// moment国际化设置为中文
moment.defineLocale('zh-cn', {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
longDateFormat: {
LT: 'Ah点mm分',
LTS: 'Ah点m分s秒',
L: 'YYYY-MM-DD',
LL: 'YYYY年MMMD日',
LLL: 'YYYY年MMMD日Ah点mm分',
LLLL: 'YYYY年MMMD日ddddAh点mm分',
l: 'YYYY-MM-DD',
ll: 'YYYY年MMMD日',
lll: 'YYYY年MMMD日Ah点mm分',
llll: 'YYYY年MMMD日ddddAh点mm分'
},
meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
meridiemHour: function (hour, meridiem) {
if (hour === 12) {
hour = 0;
}
if (meridiem === '凌晨' || meridiem === '早上' ||
meridiem === '上午') {
return hour;
} else if (meridiem === '下午' || meridiem === '晚上') {
return hour + 12;
} else {
// '中午'
return hour >= 11 ? hour : hour + 12;
}
},
meridiem: function (hour, minute, isLower) {
var hm = hour * 100 + minute;
if (hm < 600) {
return '凌晨';
} else if (hm < 900) {
return '早上';
} else if (hm < 1130) {
return '上午';
} else if (hm < 1230) {
return '中午';
} else if (hm < 1800) {
return '下午';
} else {
return '晚上';
}
},
calendar: {
sameDay: function () {
return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
},
nextDay: function () {
return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
},
lastDay: function () {
return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
},
nextWeek: function () {
var startOfWeek, prefix;
startOfWeek = moment().startOf('week');
prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
},
lastWeek: function () {
var startOfWeek, prefix;
startOfWeek = moment().startOf('week');
prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]';
return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
},
sameElse: 'LL'
},
ordinalParse: /\d{1,2}(日|月|周)/,
ordinal: function (number, period) {
switch (period) {
case 'd':
case 'D':
case 'DDD':
return number + '日';
case 'M':
return number + '月';
case 'w':
case 'W':
return number + '周';
default:
return number;
}
},
relativeTime: {
future: '%s内',
past: '%s前',
s: '几秒',
m: '1分钟',
mm: '%d分钟',
h: '1小时',
hh: '%d小时',
d: '1天',
dd: '%d天',
M: '1个月',
MM: '%d个月',
y: '1年',
yy: '%d年'
},
week: {
// GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
dow: 1, // Monday is the first day of the week.
doy: 4 // The week that contains Jan 4th is the first week of the year.
}
});
export default SnackbarHOC()(App);

View File

@ -338,10 +338,10 @@ http://localhost:3000/api/projects/ | jq
|-|-|-|-|
|user_id |是|int |用户id或者组织id |
|name |是|string |项目名称 |
|description ||string |项目描述 |
|description ||string |项目描述 |
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|ignore_id |否|int |gitignore相关id |
|license_id |否|int |开源许可证id |
|private |否|boolean|项目是否私有, true为私有false: 公开,默认为公开 |
@ -374,7 +374,9 @@ curl -X POST \
-d "user_id=36408" \
-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
-d "name=golden_mirror1" \
-d "repository_name=golden_mirror1" \
-d "description=golden_mirror" \
-d "project_category_id=1" \
-d "project_language_id=2" \
http://localhost:3000/api/projects/migrate.json | jq
```
*请求参数说明:*
@ -386,8 +388,8 @@ http://localhost:3000/api/projects/migrate.json | jq
|clone_addr |是|string |镜像项目clone地址 |
|description |否|string |项目描述 |
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|is_mirror |否|boolean|是否设置为镜像, true false默认为否 |
|auth_username |否|string|镜像源仓库的登录用户名 |
|auth_password |否|string|镜像源仓库的登录秘密 |

View File

@ -1,7 +1,7 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-courses-index-page').length > 0) {
var searchContainer = $(".course-list-form");
var searchForm = $("form.search-form",searchContainer);
let searchContainer = $(".course-list-form");
let searchForm = $("form.search-form",searchContainer);
searchContainer.on('change', '.course-homepage-show', function(){
searchForm.find('input[type="submit"]').trigger('click');

View File

@ -1,76 +0,0 @@
/*
* @Description: Do not edit
* @Date: 2021-08-31 11:16:45
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-08-31 14:19:46
* @FilePath: /forgeplus/app/assets/javascripts/admins/reversed_keywords/index.js
*/
$(document).on('turbolinks:load', function(){
var showSuccessNotify = function() {
$.notify({
message: '操作成功'
},{
type: 'success'
});
}
// close user
$('.reversed-keyword-list-container').on('click', '.close-action', function(){
var $closeAction = $(this);
var $uncloseAction = $closeAction.siblings('.unclose-action');
var keywordID = $closeAction.data('id');
customConfirm({
content: '确认关闭限制吗?',
ok: function(){
$.ajax({
url: '/admins/reversed_keywords/' + keywordID,
method: 'PUT',
dataType: 'json',
data: {
reversed_keyword: {
closed: true
}
},
success: function() {
showSuccessNotify();
$closeAction.hide();
$uncloseAction.show();
$(".reversed-keyword-item-"+keywordID).children('td').eq(3).text("")
}
});
}
});
});
// unclose user
$('.reversed-keyword-list-container').on('click', '.unclose-action', function(){
var $uncloseAction = $(this);
var $closeAction = $uncloseAction.siblings('.close-action');
var keywordID = $uncloseAction.data('id');
customConfirm({
content: '确认开启限制吗?',
ok: function () {
$.ajax({
url: '/admins/reversed_keywords/' + keywordID,
method: 'PUT',
dataType: 'json',
data: {
reversed_keyword: {
closed: false
}
},
success: function() {
showSuccessNotify();
$closeAction.show();
$uncloseAction.hide();
$(".reversed-keyword-item-"+keywordID).children('td').eq(3).text("√")
}
});
}
})
});
})

View File

@ -1,15 +1,7 @@
/*
* @Description: Do not edit
* @Date: 2021-07-16 11:58:16
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-08-31 14:48:59
* @FilePath: /forgeplus/app/assets/javascripts/admins/shixun_settings/index.js
*/
$(document).on('turbolinks:load', function() {
if ($('body.admins-shixun-settings-index-page').length > 0) {
var searchContainer = $(".shixun-settings-list-form");
var searchForm = $("form.search-form",searchContainer);
let searchContainer = $(".shixun-settings-list-form");
let searchForm = $("form.search-form",searchContainer);
searchContainer.on('change', '.shixun-settings-select', function(){
searchForm.find('input[type="submit"]').trigger('click');

View File

@ -9,7 +9,6 @@ class AccountsController < ApplicationController
# 其他平台同步注册的用户
def remote_register
username = params[:username]&.gsub(/\s+/, "")
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.is_reversed(username).present?
email = params[:email]&.gsub(/\s+/, "")
password = params[:password]
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")

View File

@ -1,55 +0,0 @@
class Admins::EduSettingsController < Admins::BaseController
before_action :find_setting, only: [:edit,:update, :destroy]
def index
default_sort('id', 'desc')
edu_settings = Admins::EduSettingQuery.call(params)
@edu_settings = paginate edu_settings
end
def new
@edu_setting = EduSetting.new
end
def edit
end
def create
@edu_setting = EduSetting.new(edu_setting_params)
if @edu_setting.save
redirect_to admins_edu_settings_path
flash[:success] = '创建成功'
else
redirect_to admins_edu_settings_path
flash[:danger] = @edu_setting.errors.full_messages.join(",")
end
end
def update
if @edu_setting.update!(edu_setting_params)
flash[:success] = '更新成功'
else
flash[:danger] = @edu_setting.errors.full_messages.join(",")
end
redirect_to admins_edu_settings_path
end
def destroy
if @edu_setting.destroy!
flash[:success] = '删除成功'
else
lash[:danger] = '删除失败'
end
redirect_to admins_edu_settings_path
end
private
def find_setting
@edu_setting ||= EduSetting.find(params[:id])
end
def edu_setting_params
params.require(:edu_setting).permit(:name, :value, :description)
end
end

View File

@ -1,84 +0,0 @@
class Admins::ReversedKeywordsController < Admins::BaseController
before_action :get_keyword, only: [:edit,:update, :destroy]
# before_action :validate_identifer, only: [:create, :update]
def index
sort_by = ReversedKeyword.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = ReversedKeyword.ransack(identifier_cont: params[:search])
keywords = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@keywords = paginate(keywords)
end
def new
@keyword = ReversedKeyword.new
end
def edit
end
def create
@keyword = ReversedKeyword.new(keyword_params)
if @keyword.save
redirect_to admins_reversed_keywords_path
flash[:success] = '系统保留关键词创建成功'
else
redirect_to admins_reversed_keywords_path
flash[:danger] = @keyword.errors.full_messages.join(",")
end
end
def update
respond_to do |format|
if @keyword.update_attributes(keyword_params)
format.html do
redirect_to admins_reversed_keywords_path
flash[:success] = '系统保留关键词更新成功'
end
format.js {render_ok}
else
format.html do
redirect_to admins_reversed_keywords_path
flash[:danger] = @keyword.errors.full_messages.join(",")
end
format.js {render_js_error}
end
end
end
def destroy
if @keyword.destroy
redirect_to admins_reversed_keywords_path
flash[:success] = "系统保留关键词删除成功"
else
redirect_to admins_reversed_keywords_path
flash[:danger] = "系统保留关键词删除失败"
end
end
private
def keyword_params
params.require(:reversed_keyword).permit!
end
def get_keyword
@keyword = ReversedKeyword.find_by(id: params[:id])
unless @keyword.present?
redirect_to admins_reversed_keywords_path
flash[:danger] = "系统保留关键词不存在"
end
end
def validate_identifer
identifer = keyword_params[:identifier].to_s.downcase
if identifer.blank?
redirect_to admins_reversed_keywords_path
flash[:danger] = '系统保留关键词标识不能为空'
elsif ProjectLanguage.exists?(name: identifer)
redirect_to admins_reversed_keywords_path
flash[:danger] = '系统保留关键词已存在'
end
end
end

View File

@ -1,56 +0,0 @@
class Admins::SitesController < Admins::BaseController
before_action :find_site, only: [:edit,:update, :destroy]
def index
default_sort('id', 'desc')
sites = Admins::SiteQuery.call(params)
@sites = paginate sites
end
def new
@site = Site.new
end
def edit
end
def create
@site = Site.new(site_params)
if @site.save
redirect_to admins_sites_path
flash[:success] = '创建成功'
else
redirect_to admins_sites_path
flash[:danger] = @site.errors.full_messages.join(",")
end
end
def update
if @site.update!(site_params)
flash[:success] = '更新成功'
else
flash[:danger] = @site.errors.full_messages.join(",")
end
redirect_to admins_sites_path
end
def destroy
if @site.destroy!
flash[:success] = '删除成功'
else
lash[:danger] = '删除失败'
end
redirect_to admins_sites_path
end
private
def find_site
@site ||= Site.find(params[:id])
end
def site_params
params.require(:site).permit(:name, :url, :key, :site_type)
end
end

View File

@ -246,14 +246,6 @@ class ApplicationController < ActionController::Base
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
def require_profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_completed
end
def require_user_profile_completed(user)
tip_exception(412, "请用户完善资料后再操作") unless user.profile_completed
end
# 异常提醒
def tip_exception(status = -1, message)
raise Educoder::TipException.new(status, message)
@ -337,6 +329,7 @@ class ApplicationController < ActionController::Base
User.current = user
end
end
# if !User.current.logged? && Rails.env.development?
# User.current = User.find 1
# end
@ -761,10 +754,10 @@ class ApplicationController < ActionController::Base
if @project and current_user.can_read_project?(@project)
logger.info "########### has project and can read project"
@project
# elsif @project && current_user.is_a?(AnonymousUser)
# logger.info "###########This is AnonymousUser"
# @project = nil if !@project.is_public?
# render_forbidden and return
elsif @project && current_user.is_a?(AnonymousUser)
logger.info "###########This is AnonymousUser"
@project = nil if !@project.is_public?
render_forbidden and return
else
logger.info "###########project not found"
@project = nil
@ -778,12 +771,11 @@ class ApplicationController < ActionController::Base
end
def base_url
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
request.base_url
end
def convert_image!
@image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
@image = params[:image] || user_params[:image]
return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile

View File

@ -32,17 +32,8 @@ class AttachmentsController < ApplicationController
def get_file
normal_status(-1, "参数缺失") if params[:download_url].blank?
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
if url.starts_with?(base_url)
domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
response = Faraday.get(request_url)
filename = url.to_s.split("/").pop()
else
response = Faraday.get(url)
filename = params[:download_url].to_s.split("/").pop()
end
response = Faraday.get(url)
filename = params[:download_url].to_s.split("/").pop()
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
end

View File

@ -6,48 +6,26 @@ class CompareController < ApplicationController
end
def show
load_compare_params
compare
@merge_status, @merge_message = get_merge_message
end
private
def get_merge_message
if @base.blank? || @head.blank?
return -2, "请选择分支"
else
if @head.include?(":")
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
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
else
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
end
if @exist_pullrequest.present?
return -2, "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}/Messagecount'>#{@exist_pullrequest.try(:title)}</a>"
else
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
return -2, "分支内容相同,无需创建合并请求"
end
end
end
return 0, "可以合并"
end
def compare
base, head = compare_params
# TODO: 处理fork的项目向源项目发送PR的base、head参数问题
@compare_result ||=
@head.include?(":") ? gitea_compare(@base, @head) : gitea_compare(@head, @base)
head.include?(":") ? gitea_compare(base, head) : gitea_compare(head, base)
end
def load_compare_params
@base = Addressable::URI.unescape(params[:base])
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
def compare_params
base = Addressable::URI.unescape(params[:base])
head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
[base, head]
end
def gitea_compare(base, head)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head)
end
end

View File

@ -41,7 +41,7 @@ module LaboratoryHelper
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
my_projects: "/users/#{current_user.try(:login)}/projects",
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
default_url: Rails.application.config_for(:configuration)['platform_url'],
default_url: "https://www.trustie.net/",
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
register_url: "https://www.trustie.net/login?login=false"
}

View File

@ -1,17 +1,13 @@
module RegisterHelper
extend ActiveSupport::Concern
def autologin_register(username, email, password, platform= 'forge', need_edit_info = false)
def autologin_register(username, email, password, platform= 'forge')
result = {message: nil, user: nil}
user = User.new(admin: false, login: username, mail: email, type: "User")
user.password = password
user.platform = platform
if need_edit_info
user.need_edit_info
else
user.activate
end
user.activate
return unless user.valid?
@ -31,31 +27,4 @@ module RegisterHelper
result
end
def autosync_register_trustie(username, password, email, lastname="")
config = Rails.application.config_for(:configuration).symbolize_keys!
api_host = config[:sync_url]
return if api_host.blank?
url = "#{api_host}/api/v1/users/common"
sync_json = {
"mail": email,
"password": password,
"login": username,
"lastname": lastname
}.compact
uri = URI.parse(url)
if api_host
http = Net::HTTP.new(uri.hostname, uri.port)
if api_host.include?("https://")
http.use_ssl = true
end
http.send_request('POST', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'})
end
end
end

View File

@ -29,8 +29,10 @@ class EduSettingsController < ApplicationController
respond_to do |format|
if @edu_setting.save
format.html { redirect_to @edu_setting, notice: 'Edu setting was successfully created.' }
format.json { render :show, status: :created, location: @edu_setting }
else
format.html { render :new }
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
end
end
@ -41,8 +43,10 @@ class EduSettingsController < ApplicationController
def update
respond_to do |format|
if @edu_setting.update(edu_setting_params)
format.html { redirect_to @edu_setting, notice: 'Edu setting was successfully updated.' }
format.json { render :show, status: :ok, location: @edu_setting }
else
format.html { render :edit }
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
end
end
@ -53,6 +57,7 @@ class EduSettingsController < ApplicationController
def destroy
@edu_setting.destroy
respond_to do |format|
format.html { redirect_to edu_settings_url, notice: 'Edu setting was successfully destroyed.' }
format.json { head :no_content }
end
end

View File

@ -1,6 +1,5 @@
class ForksController < ApplicationController
before_action :require_login
before_action :require_profile_completed, only: [:create]
before_action :load_project
before_action :authenticate_project!, :authenticate_user!

View File

@ -7,7 +7,7 @@ class IssueTagsController < ApplicationController
def index
issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}")
issue_tags = @project.issue_tags.order("#{order_name} #{order_type}")
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
@page = params[:page] || 1
@limit = params[:limit] || 15

View File

@ -1,11 +1,8 @@
class IssuesController < ApplicationController
before_action :require_login, except: [:index, :show, :index_chosen]
before_action :require_profile_completed, only: [:create]
before_action :load_project
before_action :set_user
before_action :check_menu_authorize, except: [:index_chosen]
before_action :check_issue_permission
before_action :operate_issue_permission, only:[:create, :update, :destroy, :clean, :series_update, :copy]
before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue]
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
@ -15,6 +12,7 @@ class IssuesController < ApplicationController
include TagChosenHelper
def index
return render_not_found unless @project.has_menu_permission("issues")
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member
@ -220,7 +218,7 @@ class IssuesController < ApplicationController
change_type = change_token > 0 ? "add" : "minus"
post_to_chain(change_type, change_token.abs, current_user.try(:login))
end
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) if @issue.previous_changes.present?
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")
@ -232,7 +230,7 @@ class IssuesController < ApplicationController
end
def show
@user_permission = current_user.present? && current_user.logged? && (@project.member?(current_user) || current_user.admin? || @issue.user == current_user)
@user_permission = current_user.present? && current_user.logged? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user)
@issue_attachments = @issue.attachments
@issue_user = @issue.user
@issue_assign_to = @issue.get_assign_user
@ -303,11 +301,9 @@ class IssuesController < ApplicationController
# update_hash = params[:issue]
issue_ids = params[:ids]
if issue_ids.present?
issues = Issue.where(id: issue_ids)
if update_hash.blank?
normal_status(-1, "请选择批量更新内容")
elsif issues&.update(update_hash)
issues.map{|i| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?}
elsif Issue.where(id: issue_ids).update_all(update_hash)
normal_status(0, "批量更新成功")
else
normal_status(-1, "批量更新失败")
@ -319,7 +315,6 @@ class IssuesController < ApplicationController
def copy
@new_issue = @issue.dup
@new_issue.author_id = current_user.id
if @new_issue.save
issue_tags = @issue.issue_tags.pluck(:id)
if issue_tags.present?
@ -417,10 +412,6 @@ class IssuesController < ApplicationController
end
end
def operate_issue_permission
return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.member?(current_user)
end
def export_issues(issues)
@table_columns = %w(ID 类型 标题 描述 状态 指派给 优先级 标签 发布人 创建时间 里程碑 开始时间 截止时间 完成度 分类 金额 属于)
@export_issues = []
@ -500,8 +491,4 @@ class IssuesController < ApplicationController
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
end
end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("issues")
end
end

View File

@ -1,6 +1,5 @@
class JournalsController < ApplicationController
before_action :require_login, except: [:index, :get_children_journals]
before_action :require_profile_completed, only: [:create]
before_action :set_issue
before_action :check_issue_permission
before_action :set_journal, only: [:destroy, :edit, :update]

View File

@ -2,7 +2,6 @@ class MembersController < ApplicationController
before_action :require_login
before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role]
before_action :check_user_profile_completed, only: [:create]
before_action :operate!, except: %i[index]
before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role]
@ -48,7 +47,7 @@ class MembersController < ApplicationController
end
def member_exists?
@project.members.exists?(user_id: params[:user_id])
@project.members.exists?(params[:user_id])
end
def operate!
@ -56,14 +55,10 @@ class MembersController < ApplicationController
end
def check_member_exists!
return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
return render_result(1, "user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
end
def check_member_not_exists!
return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
end
def check_user_profile_completed
require_user_profile_completed(@user)
return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless @project.member?(params[:user_id])
end
end

View File

@ -2,7 +2,6 @@ class Oauth::BaseController < ActionController::Base
include RenderHelper
include LoginHelper
include ControllerRescueHandler
include LoggerHelper
# include LaboratoryHelper
skip_before_action :verify_authenticity_token
@ -12,18 +11,6 @@ class Oauth::BaseController < ActionController::Base
end
private
def tip_exception(status = -1, message)
raise Educoder::TipException.new(status, message)
end
def tip_show_exception(status = -2, message)
raise Educoder::TipException.new(status, message)
end
def tip_show(exception)
uid_logger("Tip show status is #{exception.status}, message is #{exception.message}")
render json: exception.tip_json
end
def session_user_id
# session[:user_id]
@ -61,13 +48,4 @@ class Oauth::BaseController < ActionController::Base
Rails.logger.info("[wechat] set session unionid: #{unionid}")
session[:unionid] = unionid
end
def session_edulogin
session[:edulogin]
end
def set_session_edulogin(login)
Rails.logger.info("[educoder] set sesstion edulogin: #{login}")
session[:edulogin] = login
end
end

View File

@ -1,6 +1,4 @@
class Oauth::EducoderController < Oauth::BaseController
include RegisterHelper
def bind
begin
login = params[:login]
@ -34,41 +32,4 @@ class Oauth::EducoderController < Oauth::BaseController
render_error(ex.message)
end
end
# 需要educoder那边设置回调地址
def create
begin
code = params['code'].to_s.strip
tip_exception("code不能为空") if code.blank?
new_user = false
result = EducoderOauth::Service.access_token(code)
result = EducoderOauth::Service.user_info(result[:access_token])
# 存在该用户
open_user = OpenUsers::Educoder.find_by(uid: result['login'])
if open_user.present? && open_user.user.present?
successful_authentication(open_user.user)
else
if current_user.blank? || !current_user.logged?
new_user = true
login = User.generate_login('E')
reg_result = autologin_register(login,"#{login}@forge.com", "Ec#{login}2021#", 'educoder', true)
if reg_result[:message].blank?
open_user = OpenUsers::Educoder.create!(user_id: reg_result[:user][:id], uid: result['login'], extra: result)
autosync_register_trustie(login, "Ec#{login}2021#", "#{login}@forge.com")
successful_authentication(open_user.user)
else
render_error(reg_result[:message])
end
else
OpenUsers::Educoder.create!(user: current_user, uid: result['login'], extra: result)
end
end
redirect_to root_path(new_user: new_user)
rescue Exception => ex
render_error(ex.message)
end
end
end

View File

@ -61,7 +61,6 @@ class OauthController < ApplicationController
login = params[:login]
email = params[:mail]
password = params[:password]
lastname = params[:lastname]
callback_url = params[:callback_url]
platform = params[:plathform] || 'educoder'
@ -73,11 +72,8 @@ class OauthController < ApplicationController
if result[:message].blank?
logger.info "[Oauth educoer] ====auto_register success"
user = User.find result[:user][:id]
user.update_column(:lastname, params[:lastname])
autosync_register_trustie(login, password, email, lastname)
OpenUsers::Educoder.create!(user: user, uid: user.login)
successful_authentication(user)
OpenUsers::Educoder.create!(user: user, uid: user.login)
render json: { callback_url: callback_url }
# redirect_to callback_url

View File

@ -1,6 +1,5 @@
class Organizations::OrganizationsController < Organizations::BaseController
before_action :require_login, except: [:index, :show, :recommend]
before_action :require_profile_completed, only: [:create]
before_action :convert_image!, only: [:create, :update]
before_action :load_organization, only: [:show, :update, :destroy]
before_action :check_user_can_edit_org, only: [:update, :destroy]
@ -26,7 +25,6 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create
ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.is_reversed(organization_params[:name]).present?
Organizations::CreateForm.new(organization_params).validate!
@organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
@ -43,8 +41,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
@organization.login = organization_params[:name] if organization_params[:name].present?
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
@organization.save!
sync_organization_extension!
@organization.organization_extension.update_attributes!(organization_params.except(:name, :nickname))
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
end
@ -98,18 +95,4 @@ class Organizations::OrganizationsController < Organizations::BaseController
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
end
def set_max_repo_creation
organization_params[:max_repo_creation].blank? ? -1 : organization_params[:max_repo_creation]
end
def organization_extension_params
organization_params
.except(:name, :nickname)
.merge(max_repo_creation: set_max_repo_creation)
end
def sync_organization_extension!
@organization.organization_extension.update_attributes!(organization_extension_params)
end
end

View File

@ -1,7 +1,6 @@
class Organizations::TeamUsersController < Organizations::BaseController
before_action :load_organization, :load_team
before_action :load_operate_user, only: [:create, :destroy]
before_action :check_user_profile_completed, only: [:create]
before_action :load_team_user, only: [:destroy]
before_action :check_user_can_edit_org, only: [:create, :destroy]
@ -30,11 +29,6 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do
@team_user.destroy!
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
unless org_team_users.present?
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!
Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, @operate_user.login)
end
render_ok
end
rescue Exception => e
@ -49,11 +43,6 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do
@team_user.destroy!
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, current_user.login)
org_team_users = @organization.team_users.where(user_id: current_user.id)
unless org_team_users.present?
@organization.organization_users.find_by(user_id: current_user.id).destroy!
Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, current_user.login)
end
render_ok
end
rescue Exception => e
@ -84,8 +73,4 @@ class Organizations::TeamUsersController < Organizations::BaseController
tip_exception("组织团队成员不存在") if @team_user.nil?
end
def check_user_profile_completed
require_user_profile_completed(@operate_user)
end
end

View File

@ -1,5 +1,5 @@
class OwnersController < ApplicationController
before_action :require_login, only: [:index]
before_action :require_login
def index
@owners = []
@ -9,53 +9,4 @@ class OwnersController < ApplicationController
teams: {can_create_org_project: true})
.distinct
end
def show
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
return render_not_found unless @owner.present?
# 组织
if @owner.is_a?(Organization)
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
@can_create_project = @owner.can_create_project?(current_user.id)
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
@is_member = @owner.is_member?(current_user.id)
# 用户
else
#待办事项,现在未做
if User.current.admin? || User.current.login == @owner.login
@waiting_applied_messages = @owner.applied_messages.waiting
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @owner.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @owner.id}, teams: {authorize: %w(admin owner)} )).common
@common_applied_projects = AppliedProject.where(project_id: @owner.full_admin_projects).common
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
else
@waiting_applied_messages = AppliedMessage.none
@common_applied_transfer_projects = AppliedTransferProject.none
@common_applied_projects = AppliedProject.none
@undo_events = 0
end
#用户的组织数量
# @user_composes_count = @user.composes.size
@user_composes_count = 0
user_organizations = User.current.logged? ? @owner.organizations.with_visibility(%w(common limited)) + @owner.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @owner.organizations.with_visibility("common")
@user_org_count = user_organizations.size
normal_projects = Project.members_projects(@owner.id).to_sql
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @owner.id}).to_sql
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @owner.login) ? projects : projects.visible
@projects_common_count = user_projects.common.size
@projects_mirrior_count = user_projects.mirror.size
@projects_sync_mirrior_count = user_projects.sync_mirror.size
puts @owner.as_json
end
end
private
def org_limited_condition
@owner.organization_extension.limited? && !current_user.logged?
end
def org_privacy_condition
return false if current_user.admin?
@owner.organization_extension.privacy? && @owner.organization_users.where(user_id: current_user.id).blank?
end
end
end

View File

@ -1,6 +1,5 @@
class PraiseTreadController < ApplicationController
before_action :require_login, except: %i[index]
before_action :require_profile_completed, only: [:like]
before_action :find_project_with_id
def index

View File

@ -1,6 +1,5 @@
class Projects::AppliedTransferProjectsController < Projects::BaseController
before_action :check_auth
before_action :check_user_profile_completed, only: [:create]
def organizations
@organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)})
@ -24,10 +23,4 @@ class Projects::AppliedTransferProjectsController < Projects::BaseController
def check_auth
return render_forbidden unless current_user.admin? ||@project.owner?(current_user)
end
def check_user_profile_completed
@owner = Owner.find_by(login: params[:owner_name])
return if @owner.is_a?(Organization)
require_user_profile_completed(@owner)
end
end

View File

@ -4,7 +4,4 @@ class Projects::BaseController < ApplicationController
before_action :load_project
before_action :load_repository
def require_manager!
return render_forbidden('你没有权限操作') unless current_user.admin? || @project.manager?(current_user)
end
end

View File

@ -1,5 +1,4 @@
class Projects::ProjectAppliesController < Projects::BaseController
before_action :require_profile_completed, only: [:create]
def create
project = Projects::ApplyJoinService.call(current_user, create_params)
render_ok(project_id: project.id)

View File

@ -14,7 +14,7 @@ class Projects::TeamsController < Projects::BaseController
def create
ActiveRecord::Base.transaction do
@team_project = TeamProject.build(@owner.id, @operate_team.id, @project.id)
Gitea::Organization::TeamProject::CreateService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
Gitea::Organization::TeamProject::CreateService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
render_ok
end
rescue Exception => e
@ -25,7 +25,7 @@ class Projects::TeamsController < Projects::BaseController
def destroy
ActiveRecord::Base.transaction do
@team_project.destroy!
Gitea::Organization::TeamProject::DeleteService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
Gitea::Organization::TeamProject::DeleteService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
render_ok
end
rescue Exception => e

View File

@ -1,116 +0,0 @@
class Projects::WebhooksController < Projects::BaseController
before_action :require_manager!
before_action :find_webhook, only:[:edit, :update, :destroy, :tasks, :test]
def index
@webhooks = @project.webhooks
@webhooks = kaminari_paginate(@webhooks)
end
def create
ActiveRecord::Base.transaction do
return render_error("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 19
return render_error("参数错误.") unless webhook_params.present?
form = Projects::Webhooks::CreateForm.new(webhook_params)
return render json: {status: -1, message: form.errors} unless form.validate!
response = Gitea::Repository::Webhooks::CreateService.new(operating_token, @project&.owner&.login, @project&.identifier, gitea_webhooks_params).call
if response[0] == 201
@webhook = response[2]
else
render_error("创建失败.")
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def edit
end
def update
return render_error("参数错误.") unless webhook_params.present?
form = Projects::Webhooks::CreateForm.new(webhook_params)
return render json: {status: -1, message: form.errors} unless form.validate!
response = Gitea::Repository::Webhooks::UpdateService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id, gitea_webhooks_params)
if response[0] == 200
@webhook = response[2]
render_ok
else
render_error("更新失败.")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def destroy
response = Gitea::Repository::Webhooks::DeleteService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id)
if response[0] == 204
@webhook = response[2]
render_ok
else
render_error("删除失败.")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def tasks
@tasks = @webhook.tasks.where(is_delivered: true).order("delivered desc")
@tasks = kaminari_paginate(@tasks)
end
def test
ActiveRecord::Base.transaction do
response = Gitea::Repository::Webhooks::TestService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id)
if response[0] == 204
render_ok
else
render_error("测试推送失败.")
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
private
def find_webhook
@webhook = @project.webhooks.find_by_id(params[:id])
return render_not_found if @webhook.nil?
end
def webhook_params
params.require(:webhook).permit(:url, :type, :http_method, :content_type, :secret, :active, :branch_filter, events: [])
end
def webhook_type
webhook_params.fetch(:type, "gitea")
end
def webhook_branch_filter
webhook_params.fetch(:branch_filter, "*")
end
def gitea_webhooks_params
{
active: webhook_params[:active],
branch_filter: webhook_branch_filter,
config: {
content_type: webhook_params[:content_type],
url: webhook_params[:url],
http_method: webhook_params[:http_method],
secret: webhook_params[:secret]
},
events: webhook_params[:events],
type: webhook_type,
}
end
def operating_token
@project.member?(current_user) ? current_user.gitea_token : @project&.owner&.gitea_token
end
end

View File

@ -5,8 +5,7 @@ class ProjectsController < ApplicationController
include Acceleratorable
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list]
before_action :require_profile_completed, only: [:create, :migrate]
before_action :load_repository, except: %i[index group_type_list migrate create recommend]
before_action :load_project, except: %i[index group_type_list migrate create recommend]
before_action :authorizate_user_can_edit_project!, only: %i[update]
before_action :project_public?, only: %i[fork_users praise_users watch_users]
@ -17,18 +16,17 @@ class ProjectsController < ApplicationController
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("pulls")) if @project.has_menu_permission("pulls")
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("resources")) if @project.has_menu_permission("resources")
menu.append(menu_hash_by_name("activity"))
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user)
render json: menu
end
def index
scope = current_user.logged? ? Projects::ListQuery.call(params, current_user.id) : Projects::ListQuery.call(params)
scope = Projects::ListQuery.call(params)
# @projects = kaminari_paginate(scope)
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
@ -110,25 +108,18 @@ class ProjectsController < ApplicationController
ActiveRecord::Base.transaction do
# TODO:
# 临时特殊处理修改website、lesson_url操作方法
if project_params.has_key?("website")
if project_params.has_key?("website")
@project.update(project_params)
elsif project_params.has_key?("default_branch")
@project.update(project_params)
gitea_params = {
default_branch: @project.default_branch
}
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
else
validate_params = project_params.slice(:name, :description,
:project_category_id, :project_language_id, :private)
Projects::UpdateForm.new(validate_params).validate!
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
private = params[:private] || false
new_project_params = project_params.except(:private).merge(is_public: !private)
@project.update_attributes!(new_project_params)
@project.forked_projects.update_all(is_public: @project.is_public)
gitea_params = {
private: private,
default_branch: @project.default_branch,
@ -153,7 +144,6 @@ class ProjectsController < ApplicationController
ActiveRecord::Base.transaction do
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
@project.destroy!
@project.forked_projects.update_all(forked_from_project_id: nil)
render_ok
end
else
@ -221,7 +211,7 @@ class ProjectsController < ApplicationController
private
def project_params
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch,
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url,
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
end

View File

@ -1,64 +0,0 @@
class PublicKeysController < ApplicationController
before_action :require_login
before_action :find_public_key, only: [:destroy]
def index
@public_keys = current_user.public_keys
@public_keys = kaminari_paginate(@public_keys)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def create
return render_error("参数错误") if public_key_params.blank?
return render_ok({status: 10002, message: "请输入密钥"}) if public_key_params[:key].blank?
return render_ok({status: 10001, message: "请输入标题"}) if public_key_params[:title].blank?
@gitea_response = Gitea::User::Keys::CreateService.call(current_user.gitea_token, public_key_params)
if @gitea_response[0] == 201
@public_key = @gitea_response[2]
else
return render_error("创建ssh key失败") if @gitea_response[2].blank?
return render_ok({status: 10002, message: "密钥格式不正确"}) if @gitea_response[2]["message"].starts_with?("Invalid key content")
exist_public_key = Gitea::PublicKey.find_by(content: public_key_params[:key])
return render_ok({status: 10002, message: "密钥已被占用"}) if @gitea_response[2]["message"].starts_with?("Key content has been used as non-deploy key") && exist_public_key.present? && exist_public_key&.owner_id != current_user.gitea_uid
return render_ok({status: 10002, message: "密钥已存在,请勿重复添加"}) if @gitea_response[2]["message"].starts_with?("Key content has been used as non-deploy key")
@public_key = nil
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def destroy
return render_not_found unless @public_key.present?
result = Gitea::User::Keys::DeleteService.call(current_user.gitea_token, @public_key.id)
if result[0] == 204
render_ok
else
render_error
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
private
def page
params[:page].to_i.zero? ? 1 : params[:page].to_i
end
def limit
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
end
def public_key_params
params.require(:public_key).permit(:key, :title)
end
def find_public_key
@public_key = current_user.public_keys.find_by_id(params[:id])
end
end

View File

@ -1,8 +1,6 @@
class PullRequestsController < ApplicationController
before_action :require_login, except: [:index, :show, :files, :commits]
before_action :require_profile_completed, only: [:create]
before_action :load_repository
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 :load_pull_request, only: [:files, :commits]
include TagChosenHelper
@ -10,6 +8,7 @@ class PullRequestsController < ApplicationController
def index
return render_not_found unless @project.has_menu_permission("pulls")
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user)
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@ -20,7 +19,6 @@ class PullRequestsController < ApplicationController
@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})
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
@user_admin_or_developer = current_user.present? && (current_user.admin || @project.all_developers.include?(current_user))
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "PullRequest")
@issues_size = scopes.size
@ -58,7 +56,7 @@ class PullRequestsController < ApplicationController
ActiveRecord::Base.transaction do
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
if @gitea_pull_request[:status] == :success
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"])
render_ok
else
render_error("create pull request error: #{@gitea_pull_request[:status]}")
@ -93,7 +91,7 @@ class PullRequestsController < ApplicationController
if @issue.update_attributes(@issue_params)
if @pull_request.update_attributes(@local_params.compact)
gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier,
@pull_request.gitea_number, @requests_params, current_user.gitea_token)
@pull_request.gpid, @requests_params, current_user.gitea_token)
if gitea_pull[:status] === :success
if params[:issue_tag_ids].present?
@ -141,7 +139,7 @@ class PullRequestsController < ApplicationController
@issue_user = @issue.user
@issue_assign_to = @issue.get_assign_user
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
@repository.identifier, @pull_request.gpid, current_user&.gitea_token)
end
def pr_merge
@ -152,16 +150,9 @@ class PullRequestsController < ApplicationController
else
ActiveRecord::Base.transaction do
begin
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login, @repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params)
if @gitea_pull["merged_by"].present?
success_condition = true
else
result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params)
success_condition = result.status == 200
end
if success_condition && @pull_request.merge!
if result.status == 200 && @pull_request.merge!
@pull_request.project_trend_status!
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
normal_status(1, "合并成功")
@ -200,12 +191,12 @@ class PullRequestsController < ApplicationController
def files
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token)
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token)
# render json: @files_result
end
def commits
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token)
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token)
# render json: @commits_result
end
@ -261,8 +252,4 @@ class PullRequestsController < ApplicationController
status_id: 1,
}
end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("pulls")
end
end

View File

@ -4,11 +4,10 @@ class RepositoriesController < ApplicationController
include Repository::LanguagesPercentagable
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 :load_repository
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
before_action :authorizate!, except: [:sync_mirror, :tags, :commit]
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
before_action :get_ref, only: %i[entries sub_entries top_counts file]
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts]
@ -193,30 +192,6 @@ class RepositoriesController < ApplicationController
render json: languages_precentagable
end
def archive
domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
file_path = [domain, api_url, archive_url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
return render_not_found if !request.format.zip? && !request.format.gzip?
redirect_to file_path
end
def raw
domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
file_path = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden?
redirect_to file_path
end
private
def find_project
@ -291,7 +266,7 @@ class RepositoriesController < ApplicationController
# uploadPushInfo
end
def create_new_pr(params)
if params[:new_branch].present? && params[:new_branch] != params[:branch]
local_params = {
@ -328,7 +303,7 @@ class RepositoriesController < ApplicationController
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
if local_requests.save
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
if gitea_request[:status] == :success && local_requests.update_attributes(gitea_number: gitea_request["body"]["number"])
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
end
end

View File

@ -4,7 +4,7 @@ class SettingsController < ApplicationController
get_add_menu
get_common_menu
get_personal_menu
get_third_party
end
private
@ -40,14 +40,6 @@ class SettingsController < ApplicationController
end
end
def get_third_party
@third_party = []
@third_party << {
name: 'educoder',
url: EducoderOauth.oauth_url
}
end
def get_site_url(key, value)
key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value)
end

View File

@ -5,7 +5,7 @@ class Users::BaseController < ApplicationController
helper_method :observed_logged_user?, :observed_user
def observed_user
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
@_observed_user ||= (User.find_by_id(params[:user_id]) || User.find_by_login(params[:user_id]))
end
def observed_logged_user?

View File

@ -1,7 +1,7 @@
class Users::HeadmapsController < Users::BaseController
def index
result = Gitea::User::HeadmapService.call(observed_user.login, start_stamp, end_stamp)
@headmaps = result[2].blank? ? [] : result[2]
@headmaps = result[2]
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)

View File

@ -14,7 +14,7 @@ class Users::StatisticsController < Users::BaseController
@date_data << date.strftime("%Y.%m.%d")
@issue_data << observed_user.issues.where("DATE(created_on) = ?", 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.select{|item| item["timestamp"] == date.to_time.to_i}
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
end
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}

View File

@ -74,7 +74,7 @@ class UsersController < ApplicationController
end
def update
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id])
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
@user.attributes = user_params.except(:image)
@ -267,7 +267,7 @@ class UsersController < ApplicationController
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
if interactor.success?
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO)
render_ok
else
render_error(interactor.error)

View File

@ -7,7 +7,7 @@ class VersionReleasesController < ApplicationController
def index
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
@version_releases = version_releases
@user_permission = current_user.present? && (@repository.project.all_developers.include?(current_user) || current_user.admin?)
@user_permission = current_user.present? && (current_user == @user || current_user.admin?)
@forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments)
end

View File

@ -1,12 +1,11 @@
class VersionsController < ApplicationController
before_action :require_login, except: [:index, :show]
before_action :require_profile_completed, only: [:create]
before_action :load_repository
before_action :check_menu_authorize
before_action :check_issue_permission, except: [:show, :index]
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
def index
return render_not_found unless @project.has_menu_permission("versions")
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
status = params[:status]
versions = @project.versions.version_includes
@ -26,13 +25,17 @@ class VersionsController < ApplicationController
end
def show
version_issues = @version.issues.issue_issue.issue_includes
version_issues = @version.issues.issue_includes
status_type = params[:status_type] || "1"
# @close_issues_size = version_issues.where(status_id: 5).size
# @open_issues_size = version_issues.size - @close_issues_size
if status_type.to_s == "1" #表示开启中的
version_issues = version_issues.where.not(status_id: 5)
else
version_issues = version_issues.where(status_id: 5)
end
version_issues = version_issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all"
version_issues = version_issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all"
version_issues = version_issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present? && params[:tracker_id].to_s != "all"
@ -44,26 +47,10 @@ class VersionsController < ApplicationController
version_issues = version_issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present? && params[:issue_tag_id].to_s != "all"
version_issues = version_issues.reorder("#{order_name} #{order_type}")
has_filter_params = (params[:author_id].present? && params[:author_id].to_s != "all") ||
(params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all") ||
(params[:tracker_id].present? && params[:tracker_id].to_s != "all") ||
(params[:status_id].present? && params[:status_id].to_s != "all") ||
(params[:priority_id].present? && params[:priority_id].to_s != "all") ||
(params[:fixed_version_id].present? && params[:fixed_version_id].to_s != "all") ||
(params[:done_ratio].present? && params[:done_ratio].to_s != "all") ||
(params[:issue_type].present? && params[:issue_type].to_s != "all") ||
(params[:issue_tag_id].present? && params[:issue_tag_id].to_s != "all")
@version_close_issues_size = has_filter_params ? version_issues.closed.size : @version.issues.issue_issue.issue_includes.closed.size
@version_issues_size = has_filter_params ? version_issues.size : @version.issues.issue_issue.issue_includes.size
if status_type.to_s == "1" #表示开启中的
version_issues = version_issues.where.not(status_id: 5)
else
version_issues = version_issues.where(status_id: 5)
end
@page = params[:page] || 1
@limit = params[:limit] || 15
# @version_issues_size = version_issues.size
@version_issues_size = version_issues.size
@version_issues = version_issues.page(@page).per(@limit)
end
@ -183,8 +170,4 @@ class VersionsController < ApplicationController
%w(desc asc).include?(params[:order_type]) ? params[:order_type] : 'desc'
end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("versions")
end
end

View File

@ -1,6 +1,5 @@
class WatchersController < ApplicationController
before_action :require_login, except: %i[index]
before_action :require_profile_completed, only: [:follow]
# before_action :find_project_with_id
before_action :get_target

View File

@ -12,7 +12,6 @@ toc_footers:
includes:
- licenses
- gitignores
- public_keys
- users
- projects
- repositories

View File

@ -1,158 +0,0 @@
<!--
* @Date: 2021-07-14 15:10:29
* @LastEditors: viletyy
* @LastEditTime: 2021-07-14 15:37:23
* @FilePath: /forgeplus/app/docs/slate/source/includes/_public_keys.md
-->
# PublicKeys
## public_keys列表
获取public_keys列表支持分页
> 示例:
```shell
curl -X GET \
http://localhost:3000/api/public_keys.json
```
```javascript
await octokit.request('GET /api/public_keys.json')
```
### HTTP 请求
`GET api/public_keys.json`
### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
page |否| 1 | int | 页码 |
limit |否| 15 | int | 每页数量 |
### 返回字段说明
参数 | 类型 | 字段说明
--------- | ----------- | -----------
total_count |int |总数 |
public_keys.id |int |ID|
public_keys.name |string|密钥标题|
public_keys.content |string|密钥内容|
public_keys.fingerprint |string|密钥标识|
public_keys.created_time |string|密钥创建时间|
> 返回的JSON示例:
```json
{
"total_count": 1,
"public_keys": [
{
"id": 16,
"name": "xxx",
"content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com",
"fingerprint": "SHA256:cU8AK/+roqUUyiaYXIdS2Nj4+Rb2p6rqWSeRDc+aqKM",
"created_unix": 1626246596,
"created_time": "2021/07/14 15:09"
}
]
}
```
<aside class="success">
Success — a happy kitten is an authenticated kitten!
</aside>
## 创建public_key
创建public_key
> 示例:
```shell
curl -X POST \
http://localhost:3000/api/public_keys.json
```
```javascript
await octokit.request('POST /api/public_keys.json')
```
### HTTP 请求
`POST api/public_keys.json`
### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
key |是 | 否 | string | 密钥 |
title |是 | 否 | string | 密钥标题 |
> 请求的JSON示例
```json
{
"public_key": {
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com",
"title": "xxx"
}
}
```
### 返回字段说明
参数 | 类型 | 字段说明
--------- | ----------- | -----------
total_count |int |总数 |
id |int |ID|
name |string|密钥标题|
content |string|密钥内容|
fingerprint |string|密钥标识|
created_time |string|密钥创建时间|
> 返回的JSON示例:
```json
{
"id": 17,
"name": "xxx",
"content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com",
"fingerprint": "SHA256:cU8AK/+roqUUyiaYXIdS2Nj4+Rb2p6rqWSeRDc+aqKM",
"created_time": "2021/07/14 15:26"
}
```
<aside class="success">
Success — a happy kitten is an authenticated kitten!
</aside>
## 删除public_key
删除public_key
> 示例:
```shell
curl -X DELETE \
http://localhost:3000/api/public_keys/:id.json
```
```javascript
await octokit.request('DELETE /api/public_keys/:id.json')
```
### HTTP 请求
`DELETE api/public_keys/:id.json`
### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
id |是 | 否 | int | 密钥ID |
> 返回的JSON示例:
```json
{
"status": 0,
"message": "success"
}
```
<aside class="success">
Success — a happy kitten is an authenticated kitten!
</aside>

View File

@ -867,674 +867,3 @@ await octokit.request('GET /api/jasder/jasder_test/sub_entries.json')
<aside class="success">
Success Data.
</aside>
## 获取仓库webhooks列表
获取仓库webhooks列表
> 示例:
```shell
curl -X GET \
http://localhost:3000/api/yystopf/ceshi/webhooks.json
```
```javascript
await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
```
### HTTP 请求
`GET /api/:owner/:repo/webhooks.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| |string |用户登录名 |
|repo |是| |string |项目标识identifier |
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
|id |int |id |
|url |string|地址|
|http_method |string|请求方式|
|is_active |bool |是否激活|
|type |string|类型|
|last_status |string|最后一次推送的状态|
|create_time |string|创建时间|
> 返回的JSON示例:
```json
{
"total_count": 4,
"webhooks": [
{
"id": 2,
"url": "https://oapi.dingtalk.com/robot/send?access_token=7e1e19d0eddb6a5e33c5c2c4e66f4c88f9437184b9ed2c2653194c6374c7d513",
"http_method": "",
"is_active": true,
"type": "dingtalk",
"last_status": "succeed",
"create_time": "2021-07-12 10:50:07"
},
{
"id": 3,
"url": "http://localhost:3000",
"http_method": "GET",
"is_active": true,
"type": "gitea",
"last_status": "succeed",
"create_time": "2021-07-26 10:03:45"
},
{
"id": 4,
"url": "http://localhost:10081",
"http_method": "POST",
"is_active": true,
"type": "gitea",
"last_status": "waiting",
"create_time": "2021-07-26 16:56:53"
},
{
"id": 5,
"url": "http://localhost:3001",
"http_method": "POST",
"is_active": true,
"type": "gitea",
"last_status": "fail",
"create_time": "2021-07-26 16:58:23"
}
]
}
```
<aside class="success">
Success Data.
</aside>
## 获取仓库单个webhook
获取仓库单个webhook
> 示例:
```shell
curl -X GET \
http://localhost:3000/api/yystopf/ceshi/webhooks/3/edit.json
```
```javascript
await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
```
### HTTP 请求
`GET /api/:owner/:repo/webhooks/:id/edit.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| |string |用户登录名 |
|repo |是| |string |项目标识identifier |
|id |是||integer|webhook ID|
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
|id |int |id |
|url |string|地址|
|content_type |string|POST Content Type|
|http_method |string|请求方式|
|secret| |string|密钥|
|is_active |bool |是否激活|
|type |string|类型|
|last_status |string|最后一次推送的状态, waiting 等待,fail 失败,succeed 成功|
|branch_filter |string|分支过滤|
|events |string|触发条件|
|create_time |string|创建时间|
参数| 含义|
--------- | ------- | ------- |
|create|创建分支或标签|
|delete|分支或标签删除|
|fork|仓库被fork|
|push|git仓库推送|
|issue|易修已打开、已关闭、已重新打开或编辑|
|issue_assign|易修被指派|
|issue_label|易修标签被更新或删除|
|issue_milestone|易修被收入里程碑|
|issue_comment|易修评论|
|pull_request|合并请求|
|pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签|
|pull_request_milestone|合并请求被记录于里程碑中|
|pull_request_comment|合并请求被评论|
|pull_request_review_approved|合并请求被批准|
|pull_request_review_rejected|合并请求被拒绝|
|pull_request_review_comment|合并请求被提出审查意见|
|pull_request_sync|合并请求被同步|
|repository|创建或删除仓库|
|release|版本发布|
> 返回的JSON示例:
```json
{
"id": 3,
"http_method": "GET",
"content_type": "form",
"url": "http://localhost:3000",
"secret": "123456",
"last_status": "succeed",
"is_active": true,
"type": "gitea",
"create_time": "2021-07-26 10:03:45",
"branch_filter": "*",
"events": [
"create",
"delete",
"fork",
"issues",
"issue_assign",
"issue_label",
"issue_milestone",
"issue_comment",
"push",
"pull_request",
"pull_request_assign",
"pull_request_label",
"pull_request_milestone",
"pull_request_comment",
"pull_request_review",
"pull_request_sync",
"repository",
"release"
]
}
```
<aside class="success">
Success Data.
</aside>
## 添加仓库webhook
添加仓库webhook
> 示例:
```shell
curl -X POST \
http://localhost:3000/api/yystopf/ceshi/webhooks.json
```
```javascript
await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
```
### HTTP 请求
`POST /api/:owner/:repo/webhooks.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| | string |用户登录名 |
|repo |是| | string |项目标识identifier |
|webhook.url |是| | string |目标url |
|webhook.type |否| | string |类型|
|webhook.http_method |是| | string | http方法, POST和GET |
|webhook.content_type |是| | string | POST Content Type |
|webhook.secret |否| | string |密钥文本|
|webhook.active |是| | bool | 是否激活|
|webhook.branch_filter|否| |string|分支过滤|
|webhook.events |否| |array|触发事件|
触发事件字段说明
参数| 含义|
--------- | ------- | ------- |
|create|创建分支或标签|
|delete|分支或标签删除|
|fork|仓库被fork|
|push|git仓库推送|
|issue|易修已打开、已关闭、已重新打开或编辑|
|issue_assign|易修被指派|
|issue_label|易修标签被更新或删除|
|issue_milestone|易修被收入里程碑|
|issue_comment|易修评论|
|pull_request|合并请求|
|pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签|
|pull_request_milestone|合并请求被记录于里程碑中|
|pull_request_comment|合并请求被评论|
|pull_request_review_approved|合并请求被批准|
|pull_request_review_rejected|合并请求被拒绝|
|pull_request_review_comment|合并请求被提出审查意见|
|pull_request_sync|合并请求被同步|
|repository|创建或删除仓库|
|release|版本发布|
> 请求的JSON示例:
```json
{
"active": true,
"content_type": "json",
"http_method": "GET",
"secret": "123456",
"url": "http://localhost:10000",
"branch_filter": "*",
"events": ["push"]
}
```
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
|id |int |id |
|url |string|地址|
|content_type |string|POST Content Type|
|is_active |bool |是否激活|
|type |string|类型|
|events | array|触发事件 |
|create_time |string|创建时间|
> 返回的JSON示例:
```json
{
"id": 18,
"type": "gitea",
"content_type": "json",
"url": "http://localhost:10000",
"events": [
"push"
],
"active": true,
"create_time": "2021-07-26 18:53:43"
}
```
<aside class="success">
Success Data.
</aside>
## 更新仓库webhook
更新仓库webhook
> 示例:
```shell
curl -X PATCH \
http://localhost:3000/api/yystopf/ceshi/webhooks/7.json
```
```javascript
await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
```
### HTTP 请求
`PATCH /api/:owner/:repo/webhooks/:id.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| | string |用户登录名 |
|repo |是| | string |项目标识identifier |
|id |是| | string |webhook id |
|webhook.url |是| | string |目标url |
|webhook.type |否| | string |类型|
|webhook.http_method |是| | string | http方法, POST和GET |
|webhook.content_type |是| | string | POST Content Type |
|webhook.secret |否| | string |密钥文本|
|webhook.active |是| | bool | 是否激活|
|webhook.branch_filter|否| |string|分支过滤|
|webhook.events |否| |array|触发事件|
触发事件字段说明
参数| 含义|
--------- | ------- | ------- |
|create|创建分支或标签|
|delete|分支或标签删除|
|fork|仓库被fork|
|push|git仓库推送|
|issue|易修已打开、已关闭、已重新打开或编辑|
|issue_assign|易修被指派|
|issue_label|易修标签被更新或删除|
|issue_milestone|易修被收入里程碑|
|issue_comment|易修评论|
|pull_request|合并请求|
|pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签|
|pull_request_milestone|合并请求被记录于里程碑中|
|pull_request_comment|合并请求被评论|
|pull_request_review_approved|合并请求被批准|
|pull_request_review_rejected|合并请求被拒绝|
|pull_request_review_comment|合并请求被提出审查意见|
|pull_request_sync|合并请求被同步|
|repository|创建或删除仓库|
|release|版本发布|
> 请求的JSON示例:
```json
{
"active": true,
"content_type": "json",
"http_method": "GET",
"secret": "123456",
"url": "http://localhost:10000",
"branch_filter": "*",
"events": ["push"]
}
```
### 返回字段说明:
> 返回的JSON示例:
```json
{
"status": 0,
"message": "success"
}
```
<aside class="success">
Success Data.
</aside>
## 删除仓库webhook
删除仓库webhook
> 示例:
```shell
curl -X DELETE \
http://localhost:3000/api/yystopf/ceshi/webhooks/7.json
```
```javascript
await octokit.request('DELETE /api/yystopf/ceshi/webhooks/7.json')
```
### HTTP 请求
`DELETE /api/:owner/:repo/webhooks/:id.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| | string |用户登录名 |
|repo |是| | string |项目标识identifier |
|id |是| | string |webhook id |
### 返回字段说明:
> 返回的JSON示例:
```json
{
"status": 0,
"message": "success"
}
```
<aside class="success">
Success Data.
</aside>
## 获取仓库webhook的历史推送列表
获取仓库webhook的历史推送列表
> 示例:
```shell
curl -X GET \
http://localhost:3000/api/yystopf/ceshi/webhooks/3/tasks.json
```
```javascript
await octokit.request('GET /api/yystopf/ceshi/webhooks/3/tasks.json')
```
### HTTP 请求
`GET /api/:owner/:repo/webhooks/:id/tasks.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| |string |用户登录名 |
|repo |是| |string |项目标识identifier |
|id |是| |integer |webhook ID|
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
|id |int |id |
|uuid |string|推送uuid|
|type |string|类型|
|is_succeed |bool|是否推送成功|
|is_delivered |bool|是否完成推送|
|payload_content |json|请求主体内容|
|request_content |json|请求内容,头部等等|
|reponse_content |json|响应内容,状态,头部,主体等等|
|delivered_time |string|推送时间|
> 返回的JSON示例:
```json
{
"total_count": 6,
"tasks": [
{
"id": 20,
"type": "gitea",
"uuid": "99aa2c23-6884-4c44-9020-5469320aa408",
"is_succeed": true,
"is_delivered": true,
"payload_content": {
"secret": "123456",
"ref": "refs/heads/master",
"before": "feb48e31362787a7620b53d4df3c4effddbb6f0b",
"after": "feb48e31362787a7620b53d4df3c4effddbb6f0b",
"compare_url": "",
"commits": [
{
"id": "feb48e31362787a7620b53d4df3c4effddbb6f0b",
"message": "fix\n",
"url": "http://localhost:10081/yystopf/ceshi/commit/feb48e31362787a7620b53d4df3c4effddbb6f0b",
"author": {
"name": "viletyy",
"email": "yystopf@163.com",
"username": "root"
},
"committer": {
"name": "viletyy",
"email": "yystopf@163.com",
"username": "root"
},
"verification": {
"verified": false,
"reason": "gpg.error.not_signed_commit",
"signature": "",
"signer": null,
"payload": ""
},
"timestamp": "2021-07-26T13:52:13+08:00",
"added": null,
"removed": null,
"modified": null
}
],
"head_commit": null,
"repository": {
"id": 2,
"owner": {
"id": 3,
"login": "yystopf",
"full_name": "",
"email": "yystopf@forge.com",
"avatar_url": "http://localhost:10081/user/avatar/yystopf/-1",
"language": "zh-CN",
"is_admin": true,
"last_login": "2021-07-21T18:38:21+08:00",
"created": "2021-06-03T14:50:25+08:00",
"username": "yystopf"
},
"name": "ceshi",
"full_name": "yystopf/ceshi",
"description": "",
"empty": false,
"private": false,
"fork": false,
"template": false,
"parent": null,
"mirror": false,
"size": 3846,
"html_url": "http://localhost:10081/yystopf/ceshi",
"ssh_url": "virus@localhost:10081:yystopf/ceshi.git",
"clone_url": "http://localhost:10081/yystopf/ceshi.git",
"original_url": "",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 1,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "master",
"archived": false,
"created_at": "2021-06-03T15:15:30+08:00",
"updated_at": "2021-07-26T13:52:16+08:00",
"permissions": {
"admin": false,
"push": false,
"pull": false
},
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": true,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_squash_merge": true,
"avatar_url": "",
"internal": false
},
"pusher": {
"id": 0,
"login": "yystopf",
"full_name": "",
"email": "yystopf@forge.com",
"avatar_url": "http://localhost:10081/user/avatar/yystopf/-1",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2021-06-03T14:50:25+08:00",
"username": "yystopf"
},
"sender": {
"id": 0,
"login": "yystopf",
"full_name": "",
"email": "yystopf@forge.com",
"avatar_url": "http://localhost:10081/user/avatar/yystopf/-1",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2021-06-03T14:50:25+08:00",
"username": "yystopf"
}
},
"request_content": {
"headers": {
"X-GitHub-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408",
"X-GitHub-Event": "push",
"X-Gitea-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408",
"X-Gitea-Event": "push",
"X-Gitea-Signature": "34a01edcd952ff6410ff6ebc946471161bde74aff86171f21621d2c2c4130f66",
"X-Gogs-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408",
"X-Gogs-Event": "push",
"X-Gogs-Signature": "34a01edcd952ff6410ff6ebc946471161bde74aff86171f21621d2c2c4130f66"
}
},
"response_content": {
"status": 200,
"headers": {
"Cache-Control": "no-store, must-revalidate, private, max-age=0",
"Content-Length": "2556",
"Content-Type": "text/html; charset=utf-8",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Set-Cookie": "__profilin=p%3Dt; path=/; HttpOnly",
"Vary": "Origin",
"X-Content-Type-Options": "nosniff",
"X-Download-Options": "noopen",
"X-Frame-Options": "SAMEORIGIN",
"X-Miniprofiler-Ids": "9ynvpncz5xm0rpgorb5y,hgggd9mv6lr4a9drcrlr,j7zqlx2vy5aji2vtgoba,f1ktsmh3jxvq0z2hf612,mih3dvgvlqhi3zy8lf2x,5k1qbkvbnru8mye9cest,tj6ern8w6awqf2zsimbr,9isaehvubivd52wo5p9v,1rzfhtq1nhuwbgy9p76g,z0xzidzyywna0y7a69m0,hzoklky92ycjqt42gi0s,y0ai7y0t28mcn8x0py2x,322il7nadinp51mw2r5m,m6dukftfsh6tjcxzp1gq,667wlqbytfwbrirnmma1,jcehj3dl8lkw8gk510cr",
"X-Miniprofiler-Original-Cache-Control": "max-age=0, private, must-revalidate",
"X-Permitted-Cross-Domain-Policies": "none",
"X-Request-Id": "08bff080-bbb5-4183-b845-81de3d47120a",
"X-Runtime": "0.394766",
"X-Xss-Protection": "1; mode=block"
},
"body": "<!doctype html><html lang=\"zh-CN\" class=\"notranslate translated-ltr\" translate=\"no\"><head><meta charset=\"utf-8\"><meta name=\"”Keywords”\" content=\"”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″\"><meta name=\"”Keywords”\" content=\"”TrustieOpenSourceProject″\"><meta name=\"”Keywords”\" content=\"”issue,bug,tracker,软件工程,课程实践″\"><meta name=\"”Description”\" content=\"”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”\"><meta name=\"theme-color\" content=\"#000000\"><link rel=\"manifest\" href=\"/react/build//manifest.json\"><link rel=\"stylesheet\" href=\"/react/build/css/iconfont.css\"><link rel=\"stylesheet\" href=\"/react/build/css/edu-purge.css\"><link rel=\"stylesheet\" href=\"/react/build/css/editormd.min.css\"><link rel=\"stylesheet\" href=\"/react/build/css/merge.css\"><link href=\"/react/build/static/css/main.07f7e90c.chunk.css\" rel=\"stylesheet\"></head><body><div id=\"md_div\" style=\"display:none\"></div><div id=\"root\" class=\"page -layout-v -fit widthunit\"></div><div id=\"picture_display\" style=\"display:none\"></div><script src=\"/react/build/js/jquery-1.8.3.min.js\"></script><script src=\"/react/build/js/js_min_all.js\"></script><script src=\"/react/build/js/codemirror/codemirror.js\"></script><script src=\"/react/build/js/editormd/editormd.min.js\"></script><script src=\"/react/build/js/codemirror/merge/merge.js\"></script><script src=\"/react/build/./static/js/runtime~main.3d644966.js\"></script><script src=\"/react/build/./static/js/main.e46872e3.chunk.js\"></script><script async type=\"text/javascript\" id=\"mini-profiler\" src=\"/mini-profiler-resources/includes.js?v=67dd1c2571ced7fc74ae7f1813e47bdf\" data-version=\"67dd1c2571ced7fc74ae7f1813e47bdf\" data-path=\"/mini-profiler-resources/\" data-current-id=\"9ynvpncz5xm0rpgorb5y\" data-ids=\"9ynvpncz5xm0rpgorb5y,hgggd9mv6lr4a9drcrlr,j7zqlx2vy5aji2vtgoba,f1ktsmh3jxvq0z2hf612,mih3dvgvlqhi3zy8lf2x,5k1qbkvbnru8mye9cest,tj6ern8w6awqf2zsimbr,9isaehvubivd52wo5p9v,1rzfhtq1nhuwbgy9p76g,z0xzidzyywna0y7a69m0,hzoklky92ycjqt42gi0s,y0ai7y0t28mcn8x0py2x,322il7nadinp51mw2r5m,m6dukftfsh6tjcxzp1gq,667wlqbytfwbrirnmma1,jcehj3dl8lkw8gk510cr\" data-horizontal-position=\"left\" data-vertical-position=\"top\" data-trivial=\"false\" data-children=\"false\" data-max-traces=\"20\" data-controls=\"false\" data-total-sql-count=\"false\" data-authorized=\"true\" data-toggle-shortcut=\"alt+p\" data-start-hidden=\"false\" data-collapse-results=\"true\" data-html-container=\"body\"></script>\n</body></html>"
},
"delivered_time": "2021-07-28 11:47:29"
}
]
}
```
<aside class="success">
Success Data.
</aside>
## 仓库webhook测试推送
仓库webhook测试推送
> 示例:
```shell
curl -X POST \
http://localhost:3000/api/yystopf/ceshi/webhooks/3/test.json
```
```javascript
await octokit.request('POST /api/yystopf/ceshi/webhooks/3/test.json')
```
### HTTP 请求
`POST /api/:owner/:repo/webhooks/:id/test.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| | string |用户登录名 |
|repo |是| | string |项目标识identifier |
|id |是| | integer|webhook ID|
### 返回字段说明:
> 返回的JSON示例:
```json
{
"status": 0,
"message": "success"
}
```
<aside class="success">
Success Data.
</aside>

View File

@ -2,24 +2,18 @@ class BaseForm
include ActiveModel::Model
def check_project_category(project_category_id)
raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id)
raise "project_category_id参数值无效." if (ProjectCategory.find_by_id project_category_id).blank?
end
def check_project_language(project_language_id)
raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id)
raise "project_language_id参数值无效." if (ProjectLanguage.find_by_id project_language_id).blank?
end
def check_repository_name(user_id, repository_name)
check_reversed_keyword(repository_name)
raise "项目标识已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists?
raise "仓库名称已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists?
end
def check_project_name(user_id, project_name)
raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists?
end
def check_reversed_keyword(repository_name)
raise "项目标识已被占用." if ReversedKeyword.is_reversed(repository_name).exists?
end
end

View File

@ -1,9 +1,11 @@
class Projects::CreateForm < BaseForm
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
:project_language_id, :ignore_id, :license_id, :private, :owner
validates :user_id, :name, :repository_name, presence: true
validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validates :user_id, :name, :description,:repository_name,
:project_category_id, :project_language_id, presence: true
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validates :name, length: { maximum: 50 }
validates :repository_name, length: { maximum: 100 }
@ -13,8 +15,6 @@ class Projects::CreateForm < BaseForm
validate do
check_project_category(project_category_id)
check_project_language(project_language_id)
check_project_name(user_id, name) unless name.blank?
check_repository_name(user_id, repository_name) unless repository_name.blank?
end
def check_license
@ -26,14 +26,13 @@ class Projects::CreateForm < BaseForm
end
def check_owner
@project_owner = Owner.find_by(id: user_id)
raise "user_id值无效." if user_id && @project_owner.blank?
@owner = Owner.find_by(id: user_id)
raise "user_id值无效." if user_id && owner.blank?
end
def check_max_repo_creation
return unless @project_owner.is_a?(Organization)
return if @project_owner.max_repo_creation <= -1
raise "已超过组织设置最大仓库数" if @project_owner.max_repo_creation == @project_owner.num_projects
return unless owner.is_a?(Organization)
return if owner.max_repo_creation <= -1
raise "已超过组织设置最大仓库数" if owner.max_repo_creation == owner.num_projects
end
end

View File

@ -1,13 +1,12 @@
class Projects::MigrateForm < BaseForm
attr_accessor :user_id, :name, :repository_name, :project_category_id, :description,
:project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
validates :user_id, :name, :repository_name, :clone_addr, presence: true
validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validates :clone_addr, format: { with: CustomRegexp::URL_REGEX, multiline: true, message: "地址格式不正确" }
validates :name, length: { maximum: 50 }
validates :repository_name, length: { maximum: 100 }
validates :description, length: { maximum: 200 }
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner
validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validates :clone_addr, format: { with: URL_REGEX, multiline: true, message: "地址格式不正确" }
validate do
check_project_name(user_id, name) unless name.blank?
check_repository_name(user_id, repository_name) unless repository_name.blank?

View File

@ -1,8 +0,0 @@
class Projects::Webhooks::CreateForm < BaseForm
attr_accessor :type, :url, :http_method, :content_type, :secret, :events, :active, :branch_filter
validates :url, format: { with: URI::regexp(%w[http https]), message: "请输入正确的地址" }
validates :active, inclusion: {in: [true, false]}
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
end

View File

@ -434,10 +434,6 @@ module ApplicationHelper
User.find_by_login login
end
def find_user_by_gitea_uid(gitea_uid)
User.find_by(gitea_uid: gitea_uid)
end
def render_base64_decoded(str)
return nil if str.blank?
Base64.decode64 str

View File

@ -13,16 +13,12 @@ module ProjectsHelper
end
end
def render_zip_url(owner, repository, archive)
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.zip")].join
def render_zip_url(project, archive_name)
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.zip"].join('/')
end
def render_tar_url(owner, repository, archive)
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.tar.gz")].join
end
def render_download_file_url(owner, repository, filepath, ref)
[base_url, "/api/#{owner&.login}/#{repository.identifier}/raw?filepath=#{filepath}&ref=#{ref}"].join
def render_tar_url(project, archive_name)
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.tar.gz"].join('/')
end
def render_http_url(project)
@ -38,12 +34,11 @@ module ProjectsHelper
end
def json_response(project, user)
repo = Repository.includes(:mirror).select(:id, :is_mirror, :mirror_url, :source_clone_url).find_by(project: project)
repo = Repository.includes(:mirror).select(:id, :mirror_url, :source_clone_url).find_by(project: project)
tmp_json = {}
unless project.common?
tmp_json = tmp_json.merge({
is_mirror: repo.is_mirror ? true : false,
mirror_status: repo.mirror_status,
mirror_num: repo.mirror_num,
mirror_url: repo.remote_mirror_url,
@ -59,11 +54,7 @@ module ProjectsHelper
repo_id: repo.id,
open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?,
type: project.numerical_for_project_type,
author: render_owner(project),
project_category_id: project.project_category_id,
project_language_id: project.project_language_id,
license_id: project.license_id,
ignore_id: project.ignore_id
author: render_owner(project)
}).compact
render json: tmp_json

View File

@ -10,12 +10,12 @@ module RepositoriesHelper
end
def download_type(str)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot)
default_type.include?(str&.downcase)
end
def image_type?(str)
default_type = %w(png jpg gif tif psd svg gif bmp webp jpeg)
default_type = %w(png jpg gif tif psd svg)
default_type.include?(str&.downcase)
end
@ -26,9 +26,8 @@ module RepositoriesHelper
end
def render_commit_author(author_json)
return nil if author_json.blank? || author_json["id"].blank?
# find_user_by_login author_json['name']
find_user_by_gitea_uid author_json['id']
return nil if author_json.blank?
find_user_by_login author_json['name']
end
def readme_render_decode64_content(str, path)
@ -82,47 +81,9 @@ module RepositoriesHelper
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content']
readme_render_decode64_content(content, path)
else
file_type = File.extname(entry['name'].to_s)[1..-1]
if download_type(file_type)
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] : entry['content']
end
file_type = entry['name'].to_s.split(".").last
return entry['content'] if download_type(file_type)
render_decode64_content(entry['content'])
end
end
def base64_to_image(path, content)
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
content = Base64.decode64(content)
File.open(path, 'wb') { |f| f.write(content) }
end
def render_download_image_url(dir_path, file_path, content)
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
file_name = full_path.split("/")[-1]
# 用户名/项目标识/文件路径
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
file_path = [dir_path, file_name].join('/')
puts "##### render_download_image_url file_path: #{file_path}"
base64_to_image(file_path, content)
file_path = file_path[6..-1]
File.join(base_url, file_path)
end
def generate_dir_path(dir_path)
# tmp_dir_path
# eg: jasder/forgeplus/raw/branch/ref
dir_path = ["public", tmp_dir, dir_path].join('/')
puts "#### dir_path: #{dir_path}"
unless Dir.exists?(dir_path)
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
end
dir_path
end
def tmp_dir
"repo"
end
end

View File

@ -20,16 +20,10 @@ module TagChosenHelper
"done_ratio": render_complete_percentage,
"issue_tag": render_issue_tags(project),
"issue_type": render_issue_species,
"all_issues": all_issues,
"branches": render_branches(project)
"all_issues": all_issues
}
end
def render_branches(project)
branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier)
branches.collect{|i| i["name"] if i.is_a?(Hash)}
end
def render_cache_trackers
cache_key = "all_trackers/#{Tracker.maximum('id')}"
@ -182,7 +176,7 @@ module TagChosenHelper
real_name = user.try(:show_real_name)
user_id = user.id
is_chosen = ((user.id.to_s == issue_info[0].to_s) ? "1" : "0")
member_info = {id: user_id, name: real_name,avatar_url: url_to_avatar(user), permission: project.get_premission(user), is_chosen: is_chosen}
member_info = {id: user_id, name: real_name,avatar_url: url_to_avatar(user),is_chosen: is_chosen}
project_members_info.push(member_info)
end
end

View File

@ -24,14 +24,8 @@ module Gitea
def run
Contents::CreateForm.new(valid_params).validate!
result = Gitea::Repository::Entries::CreateService.call(token,
owner, @params[:identifier], @params[:filepath], file_params)
if result[:status] == :success
@result = result[:body]
else
fail!(result[:message])
end
response = Gitea::Repository::Entries::CreateService.new(token, owner, @params[:identifier], @params[:filepath], file_params).call
render_result(response)
rescue Exception => exception
Rails.logger.info "Exception ===========> #{exception.message}"
fail!(exception.message)
@ -62,7 +56,7 @@ module Gitea
file_params = {}
file_params = file_params.merge(branch: @params[:branch]) unless @params[:branch].blank?
file_params = file_params.merge(new_branch: @params[:new_branch]) unless @params[:new_branch].blank?
file_params = file_params.merge(content: Base64.encode64(@params[:content] || ""))
file_params = file_params.merge(content: Base64.encode64(@params[:content]))
file_params = file_params.merge(message: @params[:message]) unless @params[:message].blank?
file_params = file_params.merge(committer: @params[:committer])
file_params

View File

@ -8,13 +8,10 @@ class MigrateRemoteRepositoryJob < ApplicationJob
puts "############ MigrateRemoteRepositoryJob starting ... ############"
gitea_repository = Gitea::Repository::MigrateService.new(token, params).call
puts "#gitea_repository#{gitea_repository}"
if gitea_repository[0]==201
repo&.project&.update_columns(gpid: gitea_repository[2]["id"])
if gitea_repository
repo&.project&.update_columns(gpid: gitea_repository["id"])
repo&.mirror&.succeeded!
puts "############ mirror status: #{repo.mirror.status} ############"
else
repo&.mirror&.failed!
end
end
end

View File

@ -2,7 +2,6 @@ class ResetUserCacheJob < ApplicationJob
queue_as :cache
def perform(user)
return if user.nil?
Cache::UserFollowCountService.new(user).reset
Cache::UserIssueCountService.new(user).reset
Cache::UserProjectCountService.new(user).reset

View File

@ -6,8 +6,4 @@ module CustomRegexp
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
end

View File

@ -1,18 +0,0 @@
module EducoderOauth
class << self
attr_accessor :client_id, :client_secret, :base_url, :redirect_uri
def logger
@_logger ||= STDOUT
end
def logger=(l)
@_logger = l
end
def oauth_url
"#{base_url}/oauth2?call_url=/oauth/authorize?client_id=#{client_id}&redirect_uri=#{URI.encode_www_form_component(redirect_uri)}&response_type=code"
end
end
end

View File

@ -1,37 +0,0 @@
require 'oauth2'
module EducoderOauth::Service
module_function
def request(method, url, params)
begin
Rails.logger.info("[EducoderOauth] [#{method.to_s.upcase}] #{url} || #{params}")
client = Faraday.new(url: EducoderOauth.base_url)
response = client.public_send(method, url, params)
result = JSON.parse(response.body)
Rails.logger.info("[EducoderOauth] [#{response.status}] #{result}")
result
rescue Exception => e
raise Educoder::TipException.new(e.message)
end
end
def access_token(code)
begin
Rails.logger.info("[EducoderOauth] [code] #{code} ")
Rails.logger.info("[EducoderOauth] [redirect_uri] #{EducoderOauth.redirect_uri} ")
client = OAuth2::Client.new(EducoderOauth.client_id, EducoderOauth.client_secret, site: EducoderOauth.base_url)
result = client.auth_code.get_token(code, redirect_uri: EducoderOauth.redirect_uri).to_hash
return result
rescue Exception => e
raise Educoder::TipException.new(e.message)
end
end
def user_info(access_token)
request(:get, '/api/users/info.json', {access_token: access_token})
end
end

View File

@ -24,12 +24,4 @@ class ApplicationRecord < ActiveRecord::Base
def reset_platform_cache_async_job
ResetPlatformCacheJob.perform_later
end
def self.strip_param(key)
key.to_s.strip.presence
end
def strip_param(key)
key.to_s.strip.presence
end
end

View File

@ -1,26 +1,19 @@
# == Schema Information
#
# Table name: forge_applied_messages
# Table name: applied_messages
#
# id :integer not null, primary key
# user_id :integer
# applied_type :string(255)
# applied_id :integer
# applied_type :string(255)
# viewed :integer default("0")
# status :integer default("0")
# created_at :datetime not null
# updated_at :datetime not null
# name :string(255)
# applied_user_id :integer
# role :integer
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_forge_applied_messages_on_applied_type_and_applied_id (applied_type,applied_id)
# index_forge_applied_messages_on_applied_user_id (applied_user_id)
# index_forge_applied_messages_on_project_id (project_id)
# index_forge_applied_messages_on_user_id (user_id)
#
class AppliedMessage < ApplicationRecord

View File

@ -1,19 +1,14 @@
# == Schema Information
#
# Table name: forge_applied_projects
# Table name: applied_projects
#
# id :integer not null, primary key
# project_id :integer
# user_id :integer
# project_id :integer not null
# user_id :integer not null
# role :integer default("0")
# status :integer default("0")
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_forge_applied_projects_on_project_id (project_id)
# index_forge_applied_projects_on_user_id (user_id)
# created_at :datetime
# updated_at :datetime
#
class AppliedProject < ApplicationRecord

View File

@ -1,42 +1,41 @@
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :string(255)
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# link :string(255)
# clone_id :integer
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_clone_id (clone_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_created_on (created_on)
#
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#
class Attachment < ApplicationRecord

View File

@ -39,15 +39,17 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#
@ -55,9 +57,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#

View File

@ -65,7 +65,7 @@ module ProjectOperable
if owner.is_a?(User)
managers.exists?(user_id: user.id)
elsif owner.is_a?(Organization)
managers.exists?(user_id: user.id) || owner.is_owner?(user.id) || owner.is_only_admin?(user.id)
managers.exists?(user_id: user.id) || owner.is_only_admin?(user.id)
else
false
end
@ -94,7 +94,7 @@ module ProjectOperable
end
def operator?(user)
user.admin? || (member?(user.id) && !reporter?(user))
user.admin? || !reporter?(user)
end
def set_developer_role(member, role_name)

View File

@ -1,24 +1,22 @@
# == Schema Information
#
# Table name: edu_settings
#
# id :integer not null, primary key
# name :string(255)
# value :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255)
#
# Indexes
#
# index_edu_settings_on_name (name) UNIQUE
#
# == Schema Information
#
# Table name: edu_settings
#
# id :integer not null, primary key
# name :string(255)
# value :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255)
#
# Indexes
#
# index_edu_settings_on_name (name) UNIQUE
#
class EduSetting < ApplicationRecord
after_commit :expire_value_cache
scope :by_search, -> (keyword){ where("name LIKE :keyword OR value LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
def value_cache_key
self.class.value_cache_key(name)
end

View File

@ -1,6 +1,4 @@
class Gitea::Base < ApplicationRecord
db_config = Rails.configuration.database_configuration[Rails.env]["gitea_server"]
raise 'gitea database config missing' if db_config.blank?
establish_connection db_config
class Gitea::Base < Gitea::Database
self.abstract_class = true
end

View File

@ -1,9 +0,0 @@
class Gitea::PublicKey < Gitea::Base
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
# establish_connection :gitea_db
self.table_name = "public_key"
belongs_to :user, class_name: '::User', primary_key: :gitea_uid, foreign_key: :owner_id, optional: true
end

View File

@ -1,44 +0,0 @@
# == Schema Information
#
# Table name: pull_request
#
# id :integer not null, primary key
# type :integer
# status :integer
# conflicted_files :text(65535)
# commits_ahead :integer
# commits_behind :integer
# changed_protected_files :text(65535)
# issue_id :integer
# index :integer
# head_repo_id :integer
# base_repo_id :integer
# head_branch :string(255)
# base_branch :string(255)
# merge_base :string(40)
# has_merged :boolean
# merged_commit_id :string(40)
# merger_id :integer
# merged_unix :integer
#
# Indexes
#
# IDX_pull_request_base_repo_id (base_repo_id)
# IDX_pull_request_has_merged (has_merged)
# IDX_pull_request_head_repo_id (head_repo_id)
# IDX_pull_request_issue_id (issue_id)
# IDX_pull_request_merged_unix (merged_unix)
# IDX_pull_request_merger_id (merger_id)
#
class Gitea::Pull < Gitea::Base
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
# establish_connection :gitea_db
self.table_name = "pull_request"
serialize :conflicted_files, Array
belongs_to :pull_request, class_name: '::PullRequest', foreign_key: :id, primary_key: :gitea_id, optional: true
end

View File

@ -1,13 +0,0 @@
class Gitea::Webhook < Gitea::Base
serialize :events, JSON
self.inheritance_column = nil
self.table_name = 'webhook'
has_many :tasks, class_name: "Gitea::WebhookTask", foreign_key: :hook_id
belongs_to :project, class_name: "::Project", primary_key: :gpid, foreign_key: :repo_id, optional: true
enum hook_task_type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9}
enum last_status: {waiting: 0, succeed: 1, fail: 2}
enum content_type: {json: 1, form: 2}
end

View File

@ -1,13 +0,0 @@
class Gitea::WebhookTask < Gitea::Base
serialize :payload_content, JSON
serialize :request_content, JSON
serialize :response_content, JSON
self.inheritance_column = nil
self.table_name = 'hook_task'
belongs_to :webhook, class_name: "Gitea::Webhook", foreign_key: :hook_id
enum type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9}
end

View File

@ -10,7 +10,6 @@
# sync_course :boolean default("0")
# sync_subject :boolean default("0")
# sync_shixun :boolean default("0")
# is_local :boolean default("0")
#
# Indexes
#

View File

@ -7,6 +7,7 @@
# content :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# is_secret :boolean default("0")
#
class License < ApplicationRecord

View File

@ -11,6 +11,7 @@
# course_group_id :integer default("0")
# is_collect :integer default("1")
# graduation_group_id :integer default("0")
# is_apply_signature :boolean default("0")
#
# Indexes
#

View File

@ -39,15 +39,17 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#
@ -55,9 +57,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#

View File

@ -1,79 +1,79 @@
# == Schema Information
#
# Table name: projects
#
# id :integer not null, primary key
# name :string(255) default(""), not null
# description :text(4294967295)
# homepage :string(255) default("")
# is_public :boolean default("1"), not null
# parent_id :integer
# created_on :datetime
# updated_on :datetime
# identifier :string(255)
# status :integer default("1"), not null
# lft :integer
# rgt :integer
# inherit_members :boolean default("0"), not null
# project_type :integer default("0")
# hidden_repo :boolean default("0"), not null
# attachmenttype :integer default("1")
# user_id :integer
# dts_test :integer default("0")
# enterprise_name :string(255)
# organization_id :integer
# project_new_type :integer
# gpid :integer
# forked_from_project_id :integer
# forked_count :integer default("0")
# publish_resource :integer default("0")
# visits :integer default("0")
# hot :integer default("0")
# invite_code :string(255)
# qrcode :string(255)
# qrcode_expiretime :integer default("0")
# script :text(65535)
# training_status :integer default("0")
# rep_identifier :string(255)
# project_category_id :integer
# project_language_id :integer
# praises_count :integer default("0")
# watchers_count :integer default("0")
# issues_count :integer default("0")
# pull_requests_count :integer default("0")
# language :string(255)
# versions_count :integer default("0")
# issue_tags_count :integer default("0")
# closed_issues_count :integer default("0")
# open_devops :boolean default("0")
# gitea_webhook_id :integer
# open_devops_count :integer default("0")
# recommend :boolean default("0")
# platform :integer default("0")
# license_id :integer
# ignore_id :integer
# default_branch :string(255) default("master")
# website :string(255)
# lesson_url :string(255)
#
# Indexes
#
# index_projects_on_forked_from_project_id (forked_from_project_id)
# index_projects_on_identifier (identifier)
# index_projects_on_invite_code (invite_code)
# index_projects_on_is_public (is_public)
# index_projects_on_lft (lft)
# index_projects_on_license_id (license_id)
# index_projects_on_name (name)
# index_projects_on_platform (platform)
# index_projects_on_project_category_id (project_category_id)
# index_projects_on_project_language_id (project_language_id)
# index_projects_on_project_type (project_type)
# index_projects_on_recommend (recommend)
# index_projects_on_rgt (rgt)
# index_projects_on_status (status)
# index_projects_on_updated_on (updated_on)
#
# == Schema Information
#
# Table name: projects
#
# id :integer not null, primary key
# name :string(255) default(""), not null
# description :text(4294967295)
# homepage :string(255) default("")
# is_public :boolean default("1"), not null
# parent_id :integer
# created_on :datetime
# updated_on :datetime
# identifier :string(255)
# status :integer default("1"), not null
# lft :integer
# rgt :integer
# inherit_members :boolean default("0"), not null
# project_type :integer default("0")
# hidden_repo :boolean default("0"), not null
# attachmenttype :integer default("1")
# user_id :integer
# dts_test :integer default("0")
# enterprise_name :string(255)
# organization_id :integer
# project_new_type :integer
# gpid :integer
# forked_from_project_id :integer
# forked_count :integer default("0")
# publish_resource :integer default("0")
# visits :integer default("0")
# hot :integer default("0")
# invite_code :string(255)
# qrcode :string(255)
# qrcode_expiretime :integer default("0")
# script :text(65535)
# training_status :integer default("0")
# rep_identifier :string(255)
# project_category_id :integer
# project_language_id :integer
# license_id :integer
# ignore_id :integer
# praises_count :integer default("0")
# watchers_count :integer default("0")
# issues_count :integer default("0")
# pull_requests_count :integer default("0")
# language :string(255)
# versions_count :integer default("0")
# issue_tags_count :integer default("0")
# closed_issues_count :integer default("0")
# open_devops :boolean default("0")
# gitea_webhook_id :integer
# open_devops_count :integer default("0")
# recommend :boolean default("0")
# platform :integer default("0")
# default_branch :string(255) default("master")
# website :string(255)
# order_index :integer default("0")
# lesson_url :string(255)
#
# Indexes
#
# index_projects_on_forked_from_project_id (forked_from_project_id)
# index_projects_on_identifier (identifier)
# index_projects_on_invite_code (invite_code)
# index_projects_on_is_public (is_public)
# index_projects_on_lft (lft)
# index_projects_on_name (name)
# index_projects_on_platform (platform)
# index_projects_on_project_type (project_type)
# index_projects_on_recommend (recommend)
# index_projects_on_rgt (rgt)
# index_projects_on_status (status)
# index_projects_on_updated_on (updated_on)
#
class Project < ApplicationRecord
@ -98,12 +98,10 @@ class Project < ApplicationRecord
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
belongs_to :project_category, optional: true , :counter_cache => true
belongs_to :project_language, optional: true , :counter_cache => true
belongs_to :forked_from_project, class_name: 'Project', optional: true, foreign_key: :forked_from_project_id
has_many :project_trends, dependent: :destroy
has_many :watchers, as: :watchable, dependent: :destroy
has_many :fork_users, dependent: :destroy
has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy
has_many :forked_projects, class_name: 'Project', foreign_key: :forked_from_project_id
has_one :project_educoder, dependent: :destroy
has_one :project_score, dependent: :destroy
@ -122,10 +120,9 @@ class Project < ApplicationRecord
has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy
has_many :pinned_projects, dependent: :destroy
has_many :has_pinned_users, through: :pinned_projects, source: :user
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
after_save :check_project_members
before_save :set_invite_code, :reset_cache_data, :reset_unmember_followed
after_save :check_project_members, :reset_cache_data
before_save :set_invite_code
after_destroy :reset_cache_data
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
@ -134,18 +131,6 @@ class Project < ApplicationRecord
delegate :content, to: :project_detail, allow_nil: true
delegate :name, to: :license, prefix: true, allow_nil: true
def self.all_visible(user_id=nil)
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
org_public_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'common'})).to_sql
if user_id.present?
org_limit_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'limited'})).to_sql
org_privacy_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension, :organization_users).where(organization_extensions: {visibility: 'privacy'}, organization_users: {user_id: user_id})).to_sql
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } UNION #{ org_limit_projects_sql } UNION #{org_privacy_projects_sql} ) AS projects").visible
else
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } ) AS projects").visible
end
end
def reset_cache_data
if changes[:user_id].present?
first_owner = Owner.find_by_id(changes[:user_id].first)
@ -155,12 +140,6 @@ class Project < ApplicationRecord
self.reset_user_cache_async_job(self.owner)
end
def reset_unmember_followed
if changes[:is_public].present? && changes[:is_public] == [true, false]
self.watchers.where.not(user_id: self.all_collaborators).destroy_all
end
end
def set_invite_code
if self.invite_code.nil?
self.invite_code= self.generate_dcode('invite_code', 6)

View File

@ -8,6 +8,11 @@
# projects_count :integer default("0")
# created_at :datetime not null
# updated_at :datetime not null
# ancestry :string(255)
#
# Indexes
#
# index_project_categories_on_ancestry (ancestry)
#
class ProjectCategory < ApplicationRecord

View File

@ -16,7 +16,7 @@
class ProjectUnit < ApplicationRecord
belongs_to :project
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7}
enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5, resources: 6}
validates :unit_type, uniqueness: { scope: :project_id}

View File

@ -37,7 +37,6 @@ class PullRequest < ApplicationRecord
has_many :pull_request_tags, foreign_key: :pull_request_id
has_many :project_trends, as: :trend, dependent: :destroy
has_many :attachments, as: :container, dependent: :destroy
has_one :gitea_pull, foreign_key: :id, primary_key: :gitea_id, class_name: 'Gitea::Pull'
scope :merged_and_closed, ->{where.not(status: 0)}
scope :opening, -> {where(status: 0)}
@ -54,10 +53,8 @@ class PullRequest < ApplicationRecord
Project.find_by(id: self.fork_project_id)
end
def bind_gitea_pull_request!(gitea_pull_number, gitea_pull_id)
update_columns(
gitea_number: gitea_pull_number,
gitea_id: gitea_pull_id)
def bind_gitea_pull_request!(gitea_pull_number)
update_column(:gpid, gitea_pull_number)
end
def merge!
@ -70,26 +67,19 @@ class PullRequest < ApplicationRecord
# TODO: sync educoder platform repo's for update some statistics count
def self.update_some_count
PullRequest.includes(:user, :project).select(:id, :user_id, :gitea_number, :project_id, :fork_project_id).each do |pr|
PullRequest.includes(:user, :project).select(:id, :user_id, :gpid, :project_id, :fork_project_id).each do |pr|
puts pr.id
next if pr.gitea_number.blank?
next if pr.gpid.blank?
project = pr.project
next if project.blank?
user = project.owner
next if pr.gitea_number === 6 || pr.gitea_number === 7
files_result = Gitea::PullRequest::FilesService.call(user.login, project.identifier, pr.gitea_number)
next if pr.gpid === 6 || pr.gpid === 7
files_result = Gitea::PullRequest::FilesService.call(user.login, project.identifier, pr.gpid)
pr.update_column(:files_count, files_result['NumFiles']) unless files_result.blank?
commits_result = Gitea::PullRequest::CommitsService.call(user.login, project.identifier, pr.gitea_number)
commits_result = Gitea::PullRequest::CommitsService.call(user.login, project.identifier, pr.gpid)
pr.update_column(:commits_count, commits_result.size) unless commits_result.blank?
end
end
def conflict_files
file_names = self&.gitea_pull&.conflicted_files
return [] if file_names.blank?
JSON.parse file_names
end
end

View File

@ -27,6 +27,7 @@
#
# Indexes
#
# index_repositories_on_identifier (identifier)
# index_repositories_on_project_id (project_id)
# index_repositories_on_user_id (user_id)
#

View File

@ -1,26 +0,0 @@
# == Schema Information
#
# Table name: reversed_keywords
#
# id :integer not null, primary key
# identifier :string(255)
# description :text(65535)
# closed :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#
class ReversedKeyword < ApplicationRecord
scope :is_reversed, -> (identifier){where(identifier: identifier.downcase, closed: false) if identifier.present?}
validates :identifier, presence: true, uniqueness: true
before_validation :set_identifier
private
def set_identifier
self.identifier = self.identifier.downcase
end
end

View File

@ -17,9 +17,6 @@ class Site < ApplicationRecord
# common: 普通链接
enum site_type: { add: 0, personal: 1, common: 2 }
scope :by_search, -> (keyword){ where("name LIKE :keyword OR url LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
scope :by_site_type, -> (site_type){ where(site_type: strip_param(site_type)) unless strip_param(site_type).blank? }
def self.set_default_menu
set_add_menu!
set_personal_menu!
@ -29,8 +26,8 @@ class Site < ApplicationRecord
private
def self.set_add_menu!
adds= [
{name: '新建项目', key: 'add_mirror_project', url: '/projects/mirror/new'},
{name: '导入项目', key: 'add_common', url: '/projects/deposit/new'},
{name: '新建镜像项目', key: 'add_mirror_project', url: '/projects/mirror/new'},
{name: '新建托管项目', key: 'add_common', url: '/projects/deposit/new'},
{name: '新建组织', key: 'add_r', url: '/organize/new'}]
adds.each { |ele|

View File

@ -31,7 +31,7 @@ class Team < ApplicationRecord
validates :name, uniqueness: {scope: :organization_id}
enum authorize: {read: 1, write: 2, admin: 3, owner: 4}
enum authorize: {common: 0, read: 1, write: 2, admin: 3, owner: 4}
def self.build(organization_id, name, nickname, description, authorize, includes_all_project, can_create_org_project)
self.create!(organization_id: organization_id,

View File

@ -20,7 +20,7 @@ class TeamUnit < ApplicationRecord
belongs_to :organization
belongs_to :team
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki: 4, releases: 5}
enum unit_type: {code: 1, issues: 2, pulls: 3, releases: 4}
validates :unit_type, uniqueness: { scope: [:organization_id, :team_id]}

View File

@ -1,19 +1,19 @@
# == Schema Information
#
# Table name: tokens
#
# id :integer not null, primary key
# user_id :integer default("0"), not null
# action :string(30) default(""), not null
# value :string(40) default(""), not null
# created_on :datetime not null
#
# Indexes
#
# index_tokens_on_user_id (user_id)
# tokens_value (value) UNIQUE
#
# == Schema Information
#
# Table name: tokens
#
# id :integer not null, primary key
# user_id :integer default("0"), not null
# action :string(30) default(""), not null
# value :string(40) default(""), not null
# created_on :datetime not null
#
# Indexes
#
# index_tokens_on_user_id (user_id)
# tokens_value (value) UNIQUE
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -76,7 +76,7 @@ class Token < ActiveRecord::Base
# Returns the active user who owns the key for the given action
def self.find_active_user(action, key, validity_days=nil)
user = find_user(action, key, validity_days)
if user && (user.active? || user.need_edit_info?)
if user && user.active?
user
end
end

View File

@ -39,15 +39,17 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#
@ -55,9 +57,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#
@ -83,7 +84,6 @@ class User < Owner
STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
STATUS_LOCKED = 3
STATUS_EDIT_INFO = 4
# tpi tpm权限控制
EDU_ADMIN = 1 # 超级管理员
@ -170,10 +170,9 @@ class User < Owner
accepts_nested_attributes_for :is_pinned_projects
has_many :issues, dependent: :destroy, foreign_key: :author_id
has_many :pull_requests, dependent: :destroy
has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy
# Groups and active users
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
scope :active, lambda { where(status: STATUS_ACTIVE) }
scope :like, lambda { |keywords|
sql = "CONCAT(lastname, firstname) LIKE :search OR nickname LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search"
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
@ -187,7 +186,7 @@ class User < Owner
:show_email, :show_location, :show_department,
:technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true
before_save :update_hashed_password, :set_lastname, :set_profile_completed
before_save :update_hashed_password
after_create do
SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie?
end
@ -411,10 +410,6 @@ class User < Owner
status == STATUS_LOCKED
end
def need_edit_info?
status == STATUS_EDIT_INFO
end
def activate
self.status = STATUS_ACTIVE
end
@ -427,10 +422,6 @@ class User < Owner
self.status = STATUS_LOCKED
end
def need_edit_info
self.status = STATUS_EDIT_INFO
end
def activate!
update_attribute(:status, STATUS_ACTIVE)
end
@ -443,10 +434,6 @@ class User < Owner
update_attribute(:status, STATUS_LOCKED)
end
def need_edit_info!
update_attribute(:status, STATUS_EDIT_INFO)
end
# 课程用户身份
def course_identity(course)
if !logged?
@ -792,14 +779,6 @@ class User < Owner
self.laboratory = Laboratory.current if laboratory_id.blank?
end
def set_lastname
self.lastname = self.nickname if changes[:nickname].present?
end
def set_profile_completed
self.profile_completed = self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
end
end

View File

@ -12,9 +12,7 @@
#
# Indexes
#
# index_user_actions_on_ip (ip)
# index_user_actions_on_user_id (user_id)
# index_user_actions_on_user_id_and_action_type (user_id,action_type)
# index_user_actions_on_ip (ip)
#
class UserAction < ApplicationRecord

View File

@ -10,13 +10,10 @@
# updated_at :datetime not null
# register_status :integer default("0")
# action_status :integer default("0")
# is_delete :boolean default("0")
# user_id :integer
#
# Indexes
#
# index_user_agents_on_ip (ip)
# index_user_agents_on_user_id (user_id)
# index_user_agents_on_ip (ip) UNIQUE
#
class UserAgent < ApplicationRecord

View File

@ -22,9 +22,6 @@
# school_id :integer
# description :string(255) default("")
# department_id :integer
# honor :text(65535)
# edu_background :integer
# edu_entry_year :integer
# province :string(255)
# city :string(255)
# custom_department :string(255)

View File

@ -1,28 +0,0 @@
class Admins::EduSettingQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :id, default_by: :id, default_direction: :desc
def initialize(params)
@params = params
end
def call
collection = EduSetting.all
collection = filter_settings(collection)
custom_sort collection, params[:sort_by], params[:sort_direction]
end
def filter_settings(collection)
by_search(collection)
end
def by_search(collection)
keyword = strip_param(:search)
collection.by_search(keyword)
end
end

View File

@ -1,35 +0,0 @@
class Admins::SiteQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :id, default_by: :id, default_direction: :desc
def initialize(params)
@params = params
end
def call
collection = Site.all
collection = filter_sites(collection)
custom_sort collection, params[:sort_by], params[:sort_direction]
end
def filter_sites(collection)
collection = by_search(collection)
collection = by_stie_type(collection)
collection
end
def by_search(collection)
keyword = strip_param(:search)
collection.by_search(keyword)
end
def by_stie_type(collection)
site_type = strip_param(:site_type)
collection.by_site_type(site_type)
end
end

View File

@ -1,17 +1,16 @@
class Projects::ListQuery < ApplicationQuery
include CustomSortable
attr_reader :params, :current_user_id
attr_reader :params
sort_columns :updated_on, :created_on, :forked_count, :praises_count, default_by: :updated_on, default_direction: :desc
def initialize(params, current_user_id=nil)
def initialize(params)
@params = params
@current_user_id = current_user_id
end
def call
q = Project.all_visible(current_user_id).by_name_or_identifier(params[:search])
q = Project.visible.by_name_or_identifier(params[:search])
scope = q
.with_project_type(params[:project_type])

View File

@ -46,11 +46,11 @@ class Cache::PlatformProjectLanguagesCountService < ApplicationService
def reset_platform_project_language_count_by_key
return if key.nil?
$redis_cache.hset(platform_project_language_count_key, key, ProjectLanguage.where(name: key).projects_count)
$redis_cache.hset(platform_project_language_count_key, key, Project.joins(:project_language).where(project_languages: {name: key}).count)
end
def reset_platform_project_language_count
ProjectLanguage.where.not(projects_count: 0).group("project_languages.name").sum(:projects_count).each do |k, v|
Project.joins(:project_language).group("project_languages.name").count.each do |k, v|
$redis_cache.hset(platform_project_language_count_key, k, v)
end
end

View File

@ -44,7 +44,7 @@ class Gitea::Accelerator::MigrateService < Gitea::Accelerator::BaseService
clone_addr: params[:clone_addr],
repo_name: params[:repository_name],
auth_username: params[:auth_username],
auth_password: Base64.decode64(params[:auth_password]),
auth_password: params[:auth_password],
mirror: ActiveModel::Type::Boolean.new.cast(params[:is_mirror])
}
end

View File

@ -108,7 +108,6 @@ class Gitea::ClientService < ApplicationService
def full_url(api_rest, action='post')
url = [api_url, api_rest].join('').freeze
url = action === 'get' ? url : URI.escape(url)
url = URI.escape(url) unless url.ascii_only?
puts "[gitea] request url: #{url}"
return url
end
@ -215,14 +214,6 @@ class Gitea::ClientService < ApplicationService
[body, message]
end
def json_parse!(body)
return nil unless body.present?
body = JSON.parse(body)
body, message = fix_body(body)
body
end
def log_error(status, body)
puts "[gitea] status: #{status}"
puts "[gitea] body: #{body&.force_encoding('UTF-8')}"

View File

@ -15,8 +15,8 @@ class Gitea::Organization::Repository::CreateService < Gitea::ClientService
private
def request_params
# create_params = params.merge(readme: "readme")
Hash.new.merge(token: token, data: params)
create_params = params.merge(readme: "readme")
Hash.new.merge(token: token, data: create_params)
end
def url

View File

@ -8,7 +8,7 @@ class Gitea::PullRequest::CloseService < Gitea::PullRequest::UpdateService
# number: number of pull request
# token: token of gitea user
# eq:
# Gitea::PullRequest::CloseService.call(owner.login, repo.identifier, pull.gitea_number, pull.base, current_user.gitea_token)
# Gitea::PullRequest::CloseService.call(owner.login, repo.identifier, pull.gpid, pull.base, current_user.gitea_token)
def initialize(owner, repo, number, base,token=nil)
colse_pull_params = Hash.new.merge(base: base, state: 'closed').compact

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