forked from Trustie/forgeplus
Merge pull request 'fix mege develop' (#248) from develop into master
This commit is contained in:
commit
4fa10a3683
|
@ -74,6 +74,7 @@ vendor/bundle/
|
||||||
/log
|
/log
|
||||||
/public/admin
|
/public/admin
|
||||||
/mysql_data
|
/mysql_data
|
||||||
|
/public/repo/
|
||||||
|
|
||||||
|
|
||||||
.generators
|
.generators
|
||||||
|
@ -85,3 +86,4 @@ redis_data/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
dump.rdb
|
dump.rdb
|
||||||
.tags*
|
.tags*
|
||||||
|
ceshi_user.xlsx
|
|
@ -1,529 +0,0 @@
|
||||||
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);
|
|
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -1,4 +1,35 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
## [v3.2.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-06-09
|
||||||
|
|
||||||
|
### ENHANCEMENTS
|
||||||
|
* ADD 集成邮件和平台站内信等通知系统
|
||||||
|
* Fix 代码库二级页面-优化文件子目录浏览功能(#50388)
|
||||||
|
* Fix 代码库二级页面-优化commit提交详情页页面排版及数据显示(#50372)
|
||||||
|
* Fix 代码库二级页面-优化commit提交信息列表页加载方式和数据排序功能(#50348)
|
||||||
|
* Fix 代码库二级页面-优化创建发行版功能(#50346)
|
||||||
|
* Fix 代码库二级页面-优化标签列表页功能(#50344)
|
||||||
|
* Fix 代码库二级页面-优化发行版本列表页功能(#50345)
|
||||||
|
* Fix 代码库二级页面-优化分支列表页功能(#50343)
|
||||||
|
* Fix 其他问题优化(#51581) (#51343) (#51108)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### BUGFIXES
|
||||||
|
* Fix 发行版—标签跳转链接错误(#51666)
|
||||||
|
* Fix 文件预览报错(#51660)
|
||||||
|
* Fix 标签创建时间显示错误(#51658)
|
||||||
|
* Fix 分支列表中头像显示问题(#51656)
|
||||||
|
* Fix 文本信息过长(#51630) (#51626)
|
||||||
|
* Fix 版本库中附件下载400(#51625)
|
||||||
|
* Fix loading页面优化(#51588)
|
||||||
|
* Fix 提交详情页面优化(#51577)
|
||||||
|
* Fix 修复易修复制功能(#51569)
|
||||||
|
* Fix 修复新建发行版用户信息显示错误的问题(#51665)
|
||||||
|
* Fix 修复查看文件详细信息报错的问题(#51561)
|
||||||
|
* Fix 修复提交记录中时间显示格式问题(#51526)
|
||||||
|
* Fix 组织下项目更加更新时间倒序排序(#50833)
|
||||||
|
|
||||||
|
|
||||||
## [v3.1.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-06-09
|
## [v3.1.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-06-09
|
||||||
|
|
||||||
* ENHANCEMENTS
|
* ENHANCEMENTS
|
||||||
|
|
|
@ -51,6 +51,51 @@ http://localhost:3000/api/accounts/remote_register | jq
|
||||||
|-- token |string|用户token|
|
|-- token |string|用户token|
|
||||||
|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success",
|
||||||
|
"user": {
|
||||||
|
"id": 36400,
|
||||||
|
"token": "8c87a80d9cfacc92fcb2451845104f35119eda96"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 独立注册接口
|
||||||
|
```
|
||||||
|
POST accounts/register
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```bash
|
||||||
|
curl -X POST \
|
||||||
|
-d "login=2456233122@qq.com" \
|
||||||
|
-d "password=djs_D_00001" \
|
||||||
|
-d "namespace=16895620" \
|
||||||
|
-d "code=forge" \
|
||||||
|
http://localhost:3000/api/accounts/remote_register | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|login |是|string |邮箱或者手机号 |
|
||||||
|
|namespace |是|string |登录名 |
|
||||||
|
|password |是|string |密码 |
|
||||||
|
|code |是|string |验证码 |
|
||||||
|
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|user|json object |返回数据|
|
||||||
|
|-- id |int |用户id |
|
||||||
|
|-- token |string|用户token|
|
||||||
|
|
||||||
|
|
||||||
返回值
|
返回值
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -338,10 +383,10 @@ http://localhost:3000/api/projects/ | jq
|
||||||
|-|-|-|-|
|
|-|-|-|-|
|
||||||
|user_id |是|int |用户id或者组织id |
|
|user_id |是|int |用户id或者组织id |
|
||||||
|name |是|string |项目名称 |
|
|name |是|string |项目名称 |
|
||||||
|description |是|string |项目描述 |
|
|description |否|string |项目描述 |
|
||||||
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
||||||
|project_category_id|是|int |项目类别id |
|
|project_category_id|否|int |项目类别id |
|
||||||
|project_language_id|是|int |项目语言id |
|
|project_language_id|否|int |项目语言id |
|
||||||
|ignore_id |否|int |gitignore相关id |
|
|ignore_id |否|int |gitignore相关id |
|
||||||
|license_id |否|int |开源许可证id |
|
|license_id |否|int |开源许可证id |
|
||||||
|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 |
|
|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 |
|
||||||
|
@ -374,9 +419,7 @@ curl -X POST \
|
||||||
-d "user_id=36408" \
|
-d "user_id=36408" \
|
||||||
-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
|
-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
|
||||||
-d "name=golden_mirror1" \
|
-d "name=golden_mirror1" \
|
||||||
-d "description=golden_mirror" \
|
-d "repository_name=golden_mirror1" \
|
||||||
-d "project_category_id=1" \
|
|
||||||
-d "project_language_id=2" \
|
|
||||||
http://localhost:3000/api/projects/migrate.json | jq
|
http://localhost:3000/api/projects/migrate.json | jq
|
||||||
```
|
```
|
||||||
*请求参数说明:*
|
*请求参数说明:*
|
||||||
|
@ -388,8 +431,8 @@ http://localhost:3000/api/projects/migrate.json | jq
|
||||||
|clone_addr |是|string |镜像项目clone地址 |
|
|clone_addr |是|string |镜像项目clone地址 |
|
||||||
|description |否|string |项目描述 |
|
|description |否|string |项目描述 |
|
||||||
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
||||||
|project_category_id|是|int |项目类别id |
|
|project_category_id|否|int |项目类别id |
|
||||||
|project_language_id|是|int |项目语言id |
|
|project_language_id|否|int |项目语言id |
|
||||||
|is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 |
|
|is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 |
|
||||||
|auth_username |否|string|镜像源仓库的登录用户名 |
|
|auth_username |否|string|镜像源仓库的登录用户名 |
|
||||||
|auth_password |否|string|镜像源仓库的登录秘密 |
|
|auth_password |否|string|镜像源仓库的登录秘密 |
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
@ -99,3 +99,38 @@ $(document).on("turbolinks:before-cache", function () {
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('turbolinks:load', function() {
|
||||||
|
|
||||||
|
$('.logo-item-left').on("change", 'input[type="file"]', function () {
|
||||||
|
var $fileInput = $(this);
|
||||||
|
var file = this.files[0];
|
||||||
|
var imageType = /image.*/;
|
||||||
|
if (file && file.type.match(imageType)) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function () {
|
||||||
|
var $box = $fileInput.parent();
|
||||||
|
$box.find('img').attr('src', reader.result).css('display', 'block');
|
||||||
|
$box.addClass('has-img');
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.attachment-item-left').on("change", 'input[type="file"]', function () {
|
||||||
|
var $fileInput = $(this);
|
||||||
|
var file = this.files[0];
|
||||||
|
var imageType = /image.*/;
|
||||||
|
if (file && file.type.match(imageType)) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function () {
|
||||||
|
var $box = $fileInput.parent();
|
||||||
|
$box.find('img').attr('src', reader.result).css('display', 'block');
|
||||||
|
$box.addClass('has-img');
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
$(document).on('turbolinks:load', function() {
|
$(document).on('turbolinks:load', function() {
|
||||||
if ($('body.admins-courses-index-page').length > 0) {
|
if ($('body.admins-courses-index-page').length > 0) {
|
||||||
let searchContainer = $(".course-list-form");
|
var searchContainer = $(".course-list-form");
|
||||||
let searchForm = $("form.search-form",searchContainer);
|
var searchForm = $("form.search-form",searchContainer);
|
||||||
|
|
||||||
searchContainer.on('change', '.course-homepage-show', function(){
|
searchContainer.on('change', '.course-homepage-show', function(){
|
||||||
searchForm.find('input[type="submit"]').trigger('click');
|
searchForm.find('input[type="submit"]').trigger('click');
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* @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/system_notifications/index.js
|
||||||
|
*/
|
||||||
|
$(document).on('turbolinks:load', function(){
|
||||||
|
|
||||||
|
var showSuccessNotify = function() {
|
||||||
|
$.notify({
|
||||||
|
message: '操作成功'
|
||||||
|
},{
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// close user
|
||||||
|
$('.project-list-container').on('click', '.recommend-action', function(){
|
||||||
|
var $closeAction = $(this);
|
||||||
|
var $uncloseAction = $closeAction.siblings('.unrecommend-action');
|
||||||
|
var $editAction = $closeAction.siblings('.edit-recommend-action');
|
||||||
|
|
||||||
|
var keywordID = $closeAction.data('id');
|
||||||
|
customConfirm({
|
||||||
|
content: '确认将该项目设置为推荐项目吗?',
|
||||||
|
ok: function(){
|
||||||
|
$.ajax({
|
||||||
|
url: '/admins/projects/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
project: {
|
||||||
|
recommend: true,
|
||||||
|
recommend_index: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.hide();
|
||||||
|
$uncloseAction.show();
|
||||||
|
$editAction.show();
|
||||||
|
$(".project-item-"+keywordID).children('td').eq(5).text("√")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// unclose user
|
||||||
|
$('.project-list-container').on('click', '.unrecommend-action', function(){
|
||||||
|
var $uncloseAction = $(this);
|
||||||
|
var $closeAction = $uncloseAction.siblings('.recommend-action');
|
||||||
|
var $editAction = $closeAction.siblings('.edit-recommend-action');
|
||||||
|
|
||||||
|
var keywordID = $uncloseAction.data('id');
|
||||||
|
customConfirm({
|
||||||
|
content: '确认取消该推荐项目吗?',
|
||||||
|
ok: function () {
|
||||||
|
$.ajax({
|
||||||
|
url: '/admins/projects/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
project: {
|
||||||
|
recommend: false,
|
||||||
|
recommend_index: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.show();
|
||||||
|
$uncloseAction.hide();
|
||||||
|
$editAction.hide();
|
||||||
|
$(".project-item-"+keywordID).children('td').eq(5).text("")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// close user
|
||||||
|
$('.project-list-container').on('click', '.pinned-action', function(){
|
||||||
|
var $closeAction = $(this);
|
||||||
|
var $uncloseAction = $closeAction.siblings('.unpinned-action');
|
||||||
|
|
||||||
|
var keywordID = $closeAction.data('id');
|
||||||
|
customConfirm({
|
||||||
|
content: '确认将该项目设置为精选项目吗?',
|
||||||
|
ok: function(){
|
||||||
|
$.ajax({
|
||||||
|
url: '/admins/projects/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
project: {
|
||||||
|
is_pinned: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.hide();
|
||||||
|
$uncloseAction.show();
|
||||||
|
$(".project-item-"+keywordID).children('td').eq(4).text("√")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// unclose user
|
||||||
|
$('.project-list-container').on('click', '.unpinned-action', function(){
|
||||||
|
var $uncloseAction = $(this);
|
||||||
|
var $closeAction = $uncloseAction.siblings('.pinned-action');
|
||||||
|
|
||||||
|
var keywordID = $uncloseAction.data('id');
|
||||||
|
customConfirm({
|
||||||
|
content: '确认取消该精选项目吗?',
|
||||||
|
ok: function () {
|
||||||
|
$.ajax({
|
||||||
|
url: '/admins/projects/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
project: {
|
||||||
|
is_pinned: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.show();
|
||||||
|
$uncloseAction.hide();
|
||||||
|
$(".project-item-"+keywordID).children('td').eq(4).text("")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* @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("√")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
|
@ -1,7 +1,15 @@
|
||||||
|
/*
|
||||||
|
* @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() {
|
$(document).on('turbolinks:load', function() {
|
||||||
if ($('body.admins-shixun-settings-index-page').length > 0) {
|
if ($('body.admins-shixun-settings-index-page').length > 0) {
|
||||||
let searchContainer = $(".shixun-settings-list-form");
|
var searchContainer = $(".shixun-settings-list-form");
|
||||||
let searchForm = $("form.search-form",searchContainer);
|
var searchForm = $("form.search-form",searchContainer);
|
||||||
|
|
||||||
searchContainer.on('change', '.shixun-settings-select', function(){
|
searchContainer.on('change', '.shixun-settings-select', function(){
|
||||||
searchForm.find('input[type="submit"]').trigger('click');
|
searchForm.find('input[type="submit"]').trigger('click');
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* @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/system_notifications/index.js
|
||||||
|
*/
|
||||||
|
$(document).on('turbolinks:load', function(){
|
||||||
|
|
||||||
|
var showSuccessNotify = function() {
|
||||||
|
$.notify({
|
||||||
|
message: '操作成功'
|
||||||
|
},{
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// close user
|
||||||
|
$('.system-notification-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/system_notifications/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
system_notification: {
|
||||||
|
is_top: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.hide();
|
||||||
|
$uncloseAction.show();
|
||||||
|
$(".system-notification-item-"+keywordID).children('td').eq(3).text("")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// unclose user
|
||||||
|
$('.system-notification-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/system_notifications/' + keywordID,
|
||||||
|
method: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
system_notification: {
|
||||||
|
is_top: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
showSuccessNotify();
|
||||||
|
$closeAction.show();
|
||||||
|
$uncloseAction.hide();
|
||||||
|
$(".system-notification-item-"+keywordID).children('td').eq(3).text("√")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
|
@ -58,3 +58,149 @@ input.form-control {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo-item {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&-img {
|
||||||
|
display: block;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
background: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-upload {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
background: #e9ecef;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 27px;
|
||||||
|
left: 39px;
|
||||||
|
width: 2px;
|
||||||
|
height: 26px;
|
||||||
|
background: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 39px;
|
||||||
|
left: 27px;
|
||||||
|
width: 26px;
|
||||||
|
height: 2px;
|
||||||
|
background: #495057;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
|
||||||
|
&.has-img {
|
||||||
|
.logo-item-upload {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.logo-item-upload {
|
||||||
|
display: block;
|
||||||
|
background: rgba(145, 145, 145, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: #777777;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
color: #23272B;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-item {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&-img {
|
||||||
|
display: block;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
background: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-upload {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
background: #e9ecef;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 54px;
|
||||||
|
left: 78px;
|
||||||
|
width: 2px;
|
||||||
|
height: 52px;
|
||||||
|
background: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 78px;
|
||||||
|
left: 54px;
|
||||||
|
width: 52px;
|
||||||
|
height: 2px;
|
||||||
|
background: #495057;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
position: relative;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
|
||||||
|
&.has-img {
|
||||||
|
.attachment-item-upload {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.attachment-item-upload {
|
||||||
|
display: block;
|
||||||
|
background: rgba(145, 145, 145, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
padding-top: 100px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: #777777;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
color: #23272B;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
#skip_before_action :check_account, :only => [:logout]
|
#skip_before_action :check_account, :only => [:logout]
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ class AccountsController < ApplicationController
|
||||||
# 其他平台同步注册的用户
|
# 其他平台同步注册的用户
|
||||||
def remote_register
|
def remote_register
|
||||||
username = params[:username]&.gsub(/\s+/, "")
|
username = params[:username]&.gsub(/\s+/, "")
|
||||||
|
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||||
email = params[:email]&.gsub(/\s+/, "")
|
email = params[:email]&.gsub(/\s+/, "")
|
||||||
password = params[:password]
|
password = params[:password]
|
||||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||||
|
@ -108,60 +110,46 @@ class AccountsController < ApplicationController
|
||||||
# 用户注册
|
# 用户注册
|
||||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||||
# params[:login] 邮箱或者手机号
|
# params[:login] 邮箱或者手机号
|
||||||
|
# params[:namespace] 登录名
|
||||||
# params[:code] 验证码
|
# params[:code] 验证码
|
||||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||||
# 本地forge注册入口
|
# 本地forge注册入口需要重新更改逻辑
|
||||||
def register
|
def register
|
||||||
|
# type只可能是1或者8
|
||||||
|
user = nil
|
||||||
begin
|
begin
|
||||||
# 查询验证码是否正确;type只可能是1或者8
|
Register::Form.new(register_params).validate!
|
||||||
type = phone_mail_type(params[:login].strip)
|
|
||||||
# code = params[:code].strip
|
|
||||||
|
|
||||||
if type == 1
|
user = Users::RegisterService.call(register_params)
|
||||||
uid_logger("start register by phone: type is #{type}")
|
password = register_params[:password].strip
|
||||||
pre = 'p'
|
|
||||||
email = nil
|
|
||||||
phone = params[:login]
|
|
||||||
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
|
||||||
# TODO: 暂时限定邮箱注册
|
|
||||||
return normal_status(-1, '只支持邮箱注册')
|
|
||||||
else
|
|
||||||
uid_logger("start register by email: type is #{type}")
|
|
||||||
pre = 'm'
|
|
||||||
email = params[:login]
|
|
||||||
phone = nil
|
|
||||||
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
|
|
||||||
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
|
|
||||||
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
|
||||||
end
|
|
||||||
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
|
||||||
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
|
|
||||||
# todo 上线前请删除万能验证码"513231"
|
|
||||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
|
|
||||||
|
|
||||||
code = generate_identifier User, 8, pre
|
# gitea用户注册, email, username, password
|
||||||
login = pre + code
|
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||||
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User")
|
|
||||||
@user.password = params[:password]
|
|
||||||
# 现在因为是验证码,所以在注册的时候就可以激活
|
|
||||||
@user.activate
|
|
||||||
# 必须要用save操作,密码的保存是在users中
|
|
||||||
|
|
||||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
|
|
||||||
if interactor.success?
|
if interactor.success?
|
||||||
gitea_user = interactor.result
|
gitea_user = interactor.result
|
||||||
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
|
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
||||||
@user.gitea_token = result['sha1']
|
user.gitea_token = result['sha1']
|
||||||
@user.gitea_uid = gitea_user[:body]['id']
|
user.gitea_uid = gitea_user[:body]['id']
|
||||||
if @user.save!
|
if user.save!
|
||||||
UserExtension.create!(user_id: @user.id)
|
UserExtension.create!(user_id: user.id)
|
||||||
successful_authentication(@user)
|
successful_authentication(user)
|
||||||
normal_status("注册成功")
|
render_ok
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
tip_exception(-1, interactor.error)
|
tip_exception(-1, interactor.error)
|
||||||
end
|
end
|
||||||
|
rescue Register::BaseForm::EmailError => e
|
||||||
|
render_error(-2, e.message)
|
||||||
|
rescue Register::BaseForm::LoginError => e
|
||||||
|
render_error(-3, e.message)
|
||||||
|
rescue Register::BaseForm::PhoneError => e
|
||||||
|
render_error(-4, e.message)
|
||||||
|
rescue Register::BaseForm::PasswordFormatError => e
|
||||||
|
render_error(-5, e.message)
|
||||||
|
rescue Register::BaseForm::VerifiCodeError => e
|
||||||
|
render_error(-6, e.message)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(-1, e.message)
|
tip_exception(-1, e.message)
|
||||||
end
|
end
|
||||||
|
@ -296,7 +284,7 @@ class AccountsController < ApplicationController
|
||||||
|
|
||||||
# 发送验证码
|
# 发送验证码
|
||||||
# params[:login] 手机号或者邮箱号
|
# params[:login] 手机号或者邮箱号
|
||||||
# params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||||
def get_verification_code
|
def get_verification_code
|
||||||
|
@ -310,19 +298,22 @@ class AccountsController < ApplicationController
|
||||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||||
|
|
||||||
|
logger.info "########### 验证码:#{verification_code}"
|
||||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||||
|
|
||||||
# 记录验证码
|
# 记录验证码
|
||||||
check_verification_code(verification_code, send_type, value)
|
check_verification_code(verification_code, send_type, value)
|
||||||
sucess_status
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
# 1 手机类型;0 邮箱类型
|
# check user's login or email or phone is used
|
||||||
# 注意新版的login是自动名生成的
|
# params[:value] 手机号或者邮箱号或者登录名
|
||||||
def phone_mail_type value
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
value =~ /^1\d{10}$/ ? 1 : 0
|
def check
|
||||||
|
Register::CheckColumnsForm.new(check_params).validate!
|
||||||
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||||
|
@ -368,4 +359,13 @@ class AccountsController < ApplicationController
|
||||||
def account_params
|
def account_params
|
||||||
params.require(:account).permit(:login, :password)
|
params.require(:account).permit(:login, :password)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_params
|
||||||
|
params.permit(:type, :value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def register_params
|
||||||
|
params.permit(:login, :namespace, :password, :code)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
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
|
|
@ -0,0 +1,44 @@
|
||||||
|
class Admins::MessageTemplatesController < Admins::BaseController
|
||||||
|
before_action :get_template, only: [:edit, :update, :destroy]
|
||||||
|
|
||||||
|
def index
|
||||||
|
message_templates = MessageTemplate.group(:type).count.keys
|
||||||
|
@message_templates = kaminari_array_paginate(message_templates)
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if @message_template.update_attributes(message_template_params)
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:success] = '消息模版更新成功'
|
||||||
|
else
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:danger] = @message_template.errors.full_messages.join(",")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_data
|
||||||
|
if MessageTemplate.build_init_data
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:success] = '消息模版初始化成功'
|
||||||
|
else
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:danger] = '消息模版初始化失败'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def message_template_params
|
||||||
|
params.require(@message_template.type.split("::").join("_").underscore.to_sym).permit!
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_template
|
||||||
|
@message_template = MessageTemplate.find_by(id: params[:id])
|
||||||
|
unless @message_template.present?
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:danger] = "消息模版不存在"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -22,7 +22,7 @@ class Admins::ProjectCategoriesController < Admins::BaseController
|
||||||
max_position_items = ProjectCategory.select(:id, :position).pluck(:position).reject!(&:blank?)
|
max_position_items = ProjectCategory.select(:id, :position).pluck(:position).reject!(&:blank?)
|
||||||
max_position = max_position_items.present? ? max_position_items.max.to_i : 0
|
max_position = max_position_items.present? ? max_position_items.max.to_i : 0
|
||||||
|
|
||||||
@project_category = ProjectCategory.new(name: @name,position: max_position)
|
@project_category = ProjectCategory.new(name: @name,position: max_position, pinned_index: params[:project_category][:pinned_index].to_i)
|
||||||
if @project_category.save
|
if @project_category.save
|
||||||
redirect_to admins_project_categories_path
|
redirect_to admins_project_categories_path
|
||||||
flash[:success] = '创建成功'
|
flash[:success] = '创建成功'
|
||||||
|
@ -33,17 +33,18 @@ class Admins::ProjectCategoriesController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if @project_category.update_attribute(:name, @name)
|
if @project_category.update_attributes({name: @name, pinned_index: params[:project_category][:pinned_index].to_i})
|
||||||
|
save_image_file(params[:logo], 'logo')
|
||||||
redirect_to admins_project_categories_path
|
redirect_to admins_project_categories_path
|
||||||
flash[:success] = '更新成功'
|
flash[:success] = '更新成功'
|
||||||
else
|
else
|
||||||
redirect_to admins_project_categories_path
|
redirect_to admins_project_categories_path
|
||||||
flash[:success] = '更新失败'
|
flash[:danger] = '更新失败'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @project_language.destroy
|
if @project_category.destroy
|
||||||
redirect_to admins_project_categories_path
|
redirect_to admins_project_categories_path
|
||||||
flash[:success] = "删除成功"
|
flash[:success] = "删除成功"
|
||||||
else
|
else
|
||||||
|
@ -80,4 +81,12 @@ class Admins::ProjectCategoriesController < Admins::BaseController
|
||||||
flash[:danger] = '分类已存在'
|
flash[:danger] = '分类已存在'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def save_image_file(file, type)
|
||||||
|
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
|
file_path = Util::FileManage.source_disk_filename(@project_category, type)
|
||||||
|
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
|
||||||
|
Util.write_file(file, file_path)
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
class Admins::ProjectsController < Admins::BaseController
|
class Admins::ProjectsController < Admins::BaseController
|
||||||
|
before_action :find_project, only: [:edit, :update]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
|
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
|
||||||
|
@ -8,6 +9,26 @@ class Admins::ProjectsController < Admins::BaseController
|
||||||
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
|
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit ;end
|
||||||
|
|
||||||
|
def update
|
||||||
|
respond_to do |format|
|
||||||
|
if @project.update_attributes(project_update_params)
|
||||||
|
format.html do
|
||||||
|
redirect_to admins_projects_path
|
||||||
|
flash[:sucess] = "更新成功"
|
||||||
|
end
|
||||||
|
format.js {render_ok}
|
||||||
|
else
|
||||||
|
format.html do
|
||||||
|
redirect_to admins_projects_path
|
||||||
|
flash[:danger] = "更新失败"
|
||||||
|
end
|
||||||
|
format.js {render_js_error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
project = Project.find_by!(id: params[:id])
|
project = Project.find_by!(id: params[:id])
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
@ -21,4 +42,13 @@ class Admins::ProjectsController < Admins::BaseController
|
||||||
redirect_to admins_projects_path
|
redirect_to admins_projects_path
|
||||||
flash[:danger] = "删除失败"
|
flash[:danger] = "删除失败"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def find_project
|
||||||
|
@project = Project.find_by_id(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def project_update_params
|
||||||
|
params.require(:project).permit(:is_pinned, :recommend, :recommend_index)
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,84 @@
|
||||||
|
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
|
|
@ -0,0 +1,56 @@
|
||||||
|
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
|
|
@ -0,0 +1,75 @@
|
||||||
|
class Admins::SystemNotificationsController < Admins::BaseController
|
||||||
|
before_action :get_notification, only: [:history, :edit,:update, :destroy]
|
||||||
|
# before_action :validate_identifer, only: [:create, :update]
|
||||||
|
|
||||||
|
def index
|
||||||
|
sort_by = SystemNotification.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 = SystemNotification.ransack(subject_cont: params[:search])
|
||||||
|
notifications = q.result(distinct: true).reorder("#{sort_by} #{sort_direction},created_at desc")
|
||||||
|
@notifications = paginate(notifications)
|
||||||
|
end
|
||||||
|
|
||||||
|
def history
|
||||||
|
@users = @notification.users
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@notification = SystemNotification.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@notification = SystemNotification.new(notification_params)
|
||||||
|
if @notification.save
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:success] = '系统消息创建成功'
|
||||||
|
else
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:danger] = @notification.errors.full_messages.join(",")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
respond_to do |format|
|
||||||
|
if @notification.update_attributes(notification_params)
|
||||||
|
format.html do
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:success] = '系统消息更新成功'
|
||||||
|
end
|
||||||
|
format.js {render_ok}
|
||||||
|
else
|
||||||
|
format.html do
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:danger] = @notification.errors.full_messages.join(",")
|
||||||
|
end
|
||||||
|
format.js {render_js_error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if @notification.destroy
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:success] = "系统消息删除成功"
|
||||||
|
else
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:danger] = "系统消息删除失败"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def notification_params
|
||||||
|
params.require(:system_notification).permit!
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_notification
|
||||||
|
@notification = SystemNotification.find_by(id: params[:id])
|
||||||
|
unless @notification.present?
|
||||||
|
redirect_to admins_system_notifications_path
|
||||||
|
flash[:danger] = "系统消息不存在"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,6 @@
|
||||||
class Admins::UsersController < Admins::BaseController
|
class Admins::UsersController < Admins::BaseController
|
||||||
|
before_action :finder_user, except: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||||
|
@ -8,12 +10,9 @@ class Admins::UsersController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@user = User.find(params[:id])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@user = User.find(params[:id])
|
|
||||||
|
|
||||||
Admins::UpdateUserService.call(@user, update_params)
|
Admins::UpdateUserService.call(@user, update_params)
|
||||||
flash[:success] = '保存成功'
|
flash[:success] = '保存成功'
|
||||||
redirect_to edit_admins_user_path(@user)
|
redirect_to edit_admins_user_path(@user)
|
||||||
|
@ -26,43 +25,47 @@ class Admins::UsersController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
User.find(params[:id]).destroy!
|
@user.destroy!
|
||||||
|
Gitea::User::DeleteService.call(@user.login)
|
||||||
|
|
||||||
render_delete_success
|
render_delete_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def lock
|
def lock
|
||||||
User.find(params[:id]).lock!
|
@user.lock!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def unlock
|
def unlock
|
||||||
User.find(params[:id]).activate!
|
@user.activate!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def reward_grade
|
def reward_grade
|
||||||
user = User.find(params[:user_id])
|
|
||||||
return render_unprocessable_entity('金币数量必须大于0') if params[:grade].to_i <= 0
|
return render_unprocessable_entity('金币数量必须大于0') if params[:grade].to_i <= 0
|
||||||
|
|
||||||
RewardGradeService.call(user, container_id: user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
RewardGradeService.call(@user, container_id: @user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
||||||
|
|
||||||
render_ok(grade: user.grade)
|
render_ok(grade: @user.grade)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_login_times
|
def reset_login_times
|
||||||
User.find(params[:id]).reset_login_times!
|
@user.reset_login_times!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def finder_user
|
||||||
|
@user = User.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def update_params
|
def update_params
|
||||||
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
|
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
|
||||||
mail phone location location_city school_id department_id admin business is_test
|
mail phone location location_city school_id department_id admin business is_test
|
||||||
password professional_certification authentication])
|
password professional_certification authentication login])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,49 +70,11 @@ class ApplicationController < ActionController::Base
|
||||||
(current_user.professional_certification && (ue.teacher? || ue.professional?))
|
(current_user.professional_certification && (ue.teacher? || ue.professional?))
|
||||||
end
|
end
|
||||||
|
|
||||||
def shixun_marker
|
|
||||||
unless current_user.is_shixun_marker? || current_user.admin_or_business?
|
|
||||||
tip_exception(403, "..")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# 实训的访问权限
|
|
||||||
def shixun_access_allowed
|
|
||||||
if !current_user.shixun_permission(@shixun)
|
|
||||||
tip_exception(403, "..")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def admin_or_business?
|
def admin_or_business?
|
||||||
User.current.admin? || User.current.business?
|
User.current.admin? || User.current.business?
|
||||||
end
|
end
|
||||||
|
|
||||||
# 访问课堂时没权限直接弹加入课堂的弹框 :409
|
|
||||||
def user_course_identity
|
|
||||||
@user_course_identity = current_user.course_identity(@course)
|
|
||||||
if @user_course_identity > Course::STUDENT && @course.is_public == 0
|
|
||||||
tip_exception(401, "..") unless User.current.logged?
|
|
||||||
check_account
|
|
||||||
tip_exception(@course.excellent ? 410 : 409, "您没有权限进入")
|
|
||||||
end
|
|
||||||
if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT && @course.tea_id != current_user.id
|
|
||||||
# 实名认证和职业认证的身份判断
|
|
||||||
tip_exception(411, "你的实名认证和职业认证审核未通过") if @course.authentication &&
|
|
||||||
@course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
|
|
||||||
tip_exception(411, "你的实名认证审核未通过") if @course.authentication && !current_user.authentication
|
|
||||||
tip_exception(411, "你的职业认证审核未通过") if @course.professional_certification && !current_user.professional_certification
|
|
||||||
end
|
|
||||||
uid_logger("###############user_course_identity:#{@user_course_identity}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# 题库的访问权限
|
|
||||||
def bank_visit_auth
|
|
||||||
tip_exception(-2,"未通过职业认证") if current_user.is_teacher? && !current_user.certification_teacher? && !current_user.admin_or_business? && @bank.user_id != current_user.id && @bank.is_public
|
|
||||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin_or_business? ||
|
|
||||||
(current_user.certification_teacher? && @bank.is_public)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# 判断用户的邮箱或者手机是否可用
|
# 判断用户的邮箱或者手机是否可用
|
||||||
# params[:type] 1: 注册;2:忘记密码;3:绑定
|
# params[:type] 1: 注册;2:忘记密码;3:绑定
|
||||||
def check_mail_and_phone_valid login, type
|
def check_mail_and_phone_valid login, type
|
||||||
|
@ -120,16 +82,16 @@ class ApplicationController < ActionController::Base
|
||||||
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
|
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
|
||||||
tip_exception(-2, "请输入正确的手机号或邮箱")
|
tip_exception(-2, "请输入正确的手机号或邮箱")
|
||||||
end
|
end
|
||||||
# 考虑到安全参数问题,多一次查询,去掉Union
|
|
||||||
user = User.where(phone: login).first || User.where(mail: login).first
|
user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
|
||||||
if type.to_i == 1 && !user.nil?
|
if user_exist && type.to_i == 1
|
||||||
tip_exception(-2, "该手机号码或邮箱已被注册")
|
tip_exception(-2, "该手机号码或邮箱已被注册")
|
||||||
elsif type.to_i == 2 && user.nil?
|
elsif type.to_i == 2 && !user_exist
|
||||||
tip_exception(-2, "该手机号码或邮箱未注册")
|
tip_exception(-2, "该手机号码或邮箱未注册")
|
||||||
elsif type.to_i == 3 && user.present?
|
elsif type.to_i == 3 && user_exist
|
||||||
tip_exception(-2, "该手机号码或邮箱已绑定")
|
tip_exception(-2, "该手机号码或邮箱已绑定")
|
||||||
end
|
end
|
||||||
sucess_status
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
# 发送及记录激活码
|
# 发送及记录激活码
|
||||||
|
@ -140,7 +102,7 @@ class ApplicationController < ActionController::Base
|
||||||
when 1, 2, 4, 9
|
when 1, 2, 4, 9
|
||||||
# 手机类型的发送
|
# 手机类型的发送
|
||||||
sigle_para = {phone: value}
|
sigle_para = {phone: value}
|
||||||
status = Educoder::Sms.send(mobile: value, code: code)
|
status = Gitlink::Sms.send(mobile: value, code: code)
|
||||||
tip_exception(-2, code_msg(status)) if status != 0
|
tip_exception(-2, code_msg(status)) if status != 0
|
||||||
when 8, 3, 5
|
when 8, 3, 5
|
||||||
# 邮箱类型的发送
|
# 邮箱类型的发送
|
||||||
|
@ -186,26 +148,6 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_course
|
|
||||||
return normal_status(2, '缺少course_id参数!') if params[:course_id].blank?
|
|
||||||
@course = Course.find(params[:course_id])
|
|
||||||
tip_exception(404, "") if @course.is_delete == 1 && !current_user.admin_or_business?
|
|
||||||
rescue Exception => e
|
|
||||||
tip_exception(e.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def course_manager
|
|
||||||
return normal_status(403, '只有课堂管理员才有权限') if @user_course_identity > Course::CREATOR
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_board
|
|
||||||
return normal_status(2, "缺少board_id参数") if params[:board_id].blank?
|
|
||||||
@board = Board.find(params[:board_id])
|
|
||||||
rescue Exception => e
|
|
||||||
uid_logger_error(e.message)
|
|
||||||
tip_exception(e.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_type(object_type)
|
def validate_type(object_type)
|
||||||
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
|
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
|
||||||
end
|
end
|
||||||
|
@ -215,21 +157,6 @@ class ApplicationController < ActionController::Base
|
||||||
@page_size = params[:page_size] || 15
|
@page_size = params[:page_size] || 15
|
||||||
end
|
end
|
||||||
|
|
||||||
# 课堂教师权限
|
|
||||||
def teacher_allowed
|
|
||||||
logger.info("#####identity: #{current_user.course_identity(@course)}")
|
|
||||||
unless current_user.course_identity(@course) < Course::STUDENT
|
|
||||||
normal_status(403, "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# 课堂教师、课堂管理员、超级管理员的权限(不包含助教)
|
|
||||||
def teacher_or_admin_allowed
|
|
||||||
unless current_user.course_identity(@course) < Course::ASSISTANT_PROFESSOR
|
|
||||||
normal_status(403, "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_admin
|
def require_admin
|
||||||
normal_status(403, "") unless User.current.admin?
|
normal_status(403, "") unless User.current.admin?
|
||||||
end
|
end
|
||||||
|
@ -246,9 +173,17 @@ class ApplicationController < ActionController::Base
|
||||||
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def require_profile_completed
|
||||||
|
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_user_profile_completed(user)
|
||||||
|
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
|
||||||
|
end
|
||||||
|
|
||||||
# 异常提醒
|
# 异常提醒
|
||||||
def tip_exception(status = -1, message)
|
def tip_exception(status = -1, message)
|
||||||
raise Educoder::TipException.new(status, message)
|
raise Gitlink::TipException.new(status, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def missing_template
|
def missing_template
|
||||||
|
@ -257,7 +192,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
# 弹框提醒
|
# 弹框提醒
|
||||||
def tip_show_exception(status = -2, message)
|
def tip_show_exception(status = -2, message)
|
||||||
raise Educoder::TipException.new(status, message)
|
raise Gitlink::TipException.new(status, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def normal_status(status = 0, message)
|
def normal_status(status = 0, message)
|
||||||
|
@ -272,7 +207,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
# 资料是否完善
|
# 资料是否完善
|
||||||
def check_account
|
def check_account
|
||||||
if !current_user.profile_completed?
|
if !current_user. profile_is_completed?
|
||||||
#info_url = '/account/profile'
|
#info_url = '/account/profile'
|
||||||
tip_exception(402, nil)
|
tip_exception(402, nil)
|
||||||
end
|
end
|
||||||
|
@ -337,18 +272,18 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
# 测试版前端需求
|
# 测试版前端需求
|
||||||
logger.info("subdomain:#{request.subdomain}")
|
logger.info("subdomain:#{request.subdomain}")
|
||||||
if request.subdomain != "www"
|
# if request.subdomain != "www"
|
||||||
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||||
User.current = User.find 81403
|
# User.current = User.find 81403
|
||||||
elsif params[:debug] == 'student'
|
# elsif params[:debug] == 'student'
|
||||||
User.current = User.find 8686
|
# User.current = User.find 8686
|
||||||
elsif params[:debug] == 'admin'
|
# elsif params[:debug] == 'admin'
|
||||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||||
user = User.find 36480
|
# user = User.find 36480
|
||||||
User.current = user
|
# User.current = user
|
||||||
cookies.signed[:user_id] = user.id
|
# cookies.signed[:user_id] = user.id
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
# User.current = User.find 81403
|
# User.current = User.find 81403
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -438,7 +373,7 @@ class ApplicationController < ActionController::Base
|
||||||
JSON.parse(res)
|
JSON.parse(res)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error("--uri_exec: exception #{e.message}")
|
uid_logger_error("--uri_exec: exception #{e.message}")
|
||||||
raise Educoder::TipException.new("实训平台繁忙(繁忙等级:84)")
|
raise Gitlink::TipException.new("实训平台繁忙(繁忙等级:84)")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -457,7 +392,7 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger("--uri_exec: exception #{e.message}")
|
uid_logger("--uri_exec: exception #{e.message}")
|
||||||
raise Educoder::TipException.new(message)
|
raise Gitlink::TipException.new(message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -481,7 +416,7 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger("--uri_exec: exception #{e.message}")
|
uid_logger("--uri_exec: exception #{e.message}")
|
||||||
raise Educoder::TipException.new("服务器繁忙")
|
raise Gitlink::TipException.new("服务器繁忙")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -653,8 +588,8 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
# 获取Oauth Client
|
# 获取Oauth Client
|
||||||
def get_client(site)
|
def get_client(site)
|
||||||
client_id = Rails.configuration.educoder['client_id']
|
client_id = Rails.configuration.Gitlink['client_id']
|
||||||
client_secret = Rails.configuration.educoder['client_secret']
|
client_secret = Rails.configuration.Gitlink['client_secret']
|
||||||
|
|
||||||
OAuth2::Client.new(client_id, client_secret, site: site)
|
OAuth2::Client.new(client_id, client_secret, site: site)
|
||||||
end
|
end
|
||||||
|
@ -754,10 +689,10 @@ class ApplicationController < ActionController::Base
|
||||||
if @project and current_user.can_read_project?(@project)
|
if @project and current_user.can_read_project?(@project)
|
||||||
logger.info "###########: has project and can read project"
|
logger.info "###########: has project and can read project"
|
||||||
@project
|
@project
|
||||||
elsif @project && current_user.is_a?(AnonymousUser)
|
# elsif @project && current_user.is_a?(AnonymousUser)
|
||||||
logger.info "###########:This is AnonymousUser"
|
# logger.info "###########:This is AnonymousUser"
|
||||||
@project = nil if !@project.is_public?
|
# @project = nil if !@project.is_public?
|
||||||
render_forbidden and return
|
# render_forbidden and return
|
||||||
else
|
else
|
||||||
logger.info "###########:project not found"
|
logger.info "###########:project not found"
|
||||||
@project = nil
|
@project = nil
|
||||||
|
@ -771,11 +706,12 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def base_url
|
def base_url
|
||||||
request.base_url
|
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def convert_image!
|
def convert_image!
|
||||||
@image = params[:image] || user_params[:image]
|
@image = params[:image]
|
||||||
|
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
|
||||||
return unless @image.present?
|
return unless @image.present?
|
||||||
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
||||||
if @image.class == ActionDispatch::Http::UploadedFile
|
if @image.class == ActionDispatch::Http::UploadedFile
|
||||||
|
@ -846,4 +782,8 @@ class ApplicationController < ActionController::Base
|
||||||
HotSearchKeyword.add(keyword)
|
HotSearchKeyword.add(keyword)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_atme_receivers
|
||||||
|
@atme_receivers = User.where(login: params[:receivers_login])
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,8 +32,17 @@ class AttachmentsController < ApplicationController
|
||||||
def get_file
|
def get_file
|
||||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||||
response = Faraday.get(url)
|
if url.starts_with?(base_url)
|
||||||
filename = params[:download_url].to_s.split("/").pop()
|
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
|
||||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -187,7 +196,7 @@ class AttachmentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_save_to_ucloud(path, file, content_type)
|
def file_save_to_ucloud(path, file, content_type)
|
||||||
ufile = Educoder::Ufile.new(
|
ufile = Gitlink::Ufile.new(
|
||||||
ucloud_public_key: edu_setting('public_key'),
|
ucloud_public_key: edu_setting('public_key'),
|
||||||
ucloud_private_key: edu_setting('private_key'),
|
ucloud_private_key: edu_setting('private_key'),
|
||||||
ucloud_public_read: true,
|
ucloud_public_read: true,
|
||||||
|
|
|
@ -6,26 +6,48 @@ class CompareController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
load_compare_params
|
||||||
compare
|
compare
|
||||||
|
@merge_status, @merge_message = get_merge_message
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@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
|
def compare
|
||||||
base, head = compare_params
|
|
||||||
|
|
||||||
# TODO: 处理fork的项目向源项目发送PR的base、head参数问题
|
# TODO: 处理fork的项目向源项目发送PR的base、head参数问题
|
||||||
@compare_result ||=
|
@compare_result ||=
|
||||||
head.include?(":") ? gitea_compare(base, head) : gitea_compare(head, base)
|
@head.include?(":") ? gitea_compare(@base, @head) : gitea_compare(@head, @base)
|
||||||
end
|
end
|
||||||
|
|
||||||
def compare_params
|
def load_compare_params
|
||||||
base = Addressable::URI.unescape(params[:base])
|
@base = Addressable::URI.unescape(params[:base])
|
||||||
head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
|
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
|
||||||
|
|
||||||
[base, head]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def gitea_compare(base, head)
|
def gitea_compare(base, head)
|
||||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head)
|
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,7 @@ module ControllerRescueHandler
|
||||||
end
|
end
|
||||||
# rescue_from ActionView::MissingTemplate, with: :object_not_found
|
# rescue_from ActionView::MissingTemplate, with: :object_not_found
|
||||||
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
|
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
|
||||||
rescue_from Educoder::TipException, with: :tip_show
|
rescue_from Gitlink::TipException, with: :tip_show
|
||||||
rescue_from ::ActionView::MissingTemplate, with: :missing_template
|
rescue_from ::ActionView::MissingTemplate, with: :missing_template
|
||||||
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
|
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
|
||||||
rescue_from ActionController::ParameterMissing, with: :render_parameter_missing
|
rescue_from ActionController::ParameterMissing, with: :render_parameter_missing
|
||||||
|
|
|
@ -36,10 +36,10 @@ module GitCommon
|
||||||
begin
|
begin
|
||||||
@commits = GitService.commits(repo_path: @repo_path)
|
@commits = GitService.commits(repo_path: @repo_path)
|
||||||
logger.info("git first commit is #{@commits.try(:first)}")
|
logger.info("git first commit is #{@commits.try(:first)}")
|
||||||
raise Educoder::TipException.new("请先创建版本库") if @commits.nil?
|
raise Gitlink::TipException.new("请先创建版本库") if @commits.nil?
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
raise Educoder::TipException.new("提交记录异常")
|
raise Gitlink::TipException.new("提交记录异常")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ module GitHelper
|
||||||
|
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
Rails.logger.error(e.message)
|
Rails.logger.error(e.message)
|
||||||
raise Educoder::TipException.new("文档内容获取异常")
|
raise Gitlink::TipException.new("文档内容获取异常")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ module GitHelper
|
||||||
|
|
||||||
# 版本库Fork功能
|
# 版本库Fork功能
|
||||||
def project_fork(container, original_rep_path, username)
|
def project_fork(container, original_rep_path, username)
|
||||||
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
|
raise Gitlink::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
|
||||||
# 将要生成的仓库名字
|
# 将要生成的仓库名字
|
||||||
new_repo_name = "#{username.try(:strip)}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
|
new_repo_name = "#{username.try(:strip)}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
|
||||||
# uid_logger("start fork container: repo_name is #{new_repo_name}")
|
# uid_logger("start fork container: repo_name is #{new_repo_name}")
|
||||||
|
|
|
@ -41,7 +41,7 @@ module LaboratoryHelper
|
||||||
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
||||||
my_projects: "/users/#{current_user.try(:login)}/projects",
|
my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||||
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
||||||
default_url: "https://www.trustie.net/",
|
default_url: Rails.application.config_for(:configuration)['platform_url'],
|
||||||
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
|
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
|
||||||
register_url: "https://www.trustie.net/login?login=false"
|
register_url: "https://www.trustie.net/login?login=false"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ module RenderHelper
|
||||||
render json: { status: 0, message: 'success' }.merge(data)
|
render json: { status: 0, message: 'success' }.merge(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_error(message = '')
|
def render_error(status = -1, message = '')
|
||||||
render json: { status: -1, message: message }
|
render json: { status: status, message: message }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_not_acceptable(message = '请求已拒绝')
|
def render_not_acceptable(message = '请求已拒绝')
|
||||||
|
|
|
@ -29,10 +29,8 @@ class EduSettingsController < ApplicationController
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @edu_setting.save
|
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 }
|
format.json { render :show, status: :created, location: @edu_setting }
|
||||||
else
|
else
|
||||||
format.html { render :new }
|
|
||||||
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
|
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -43,10 +41,8 @@ class EduSettingsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @edu_setting.update(edu_setting_params)
|
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 }
|
format.json { render :show, status: :ok, location: @edu_setting }
|
||||||
else
|
else
|
||||||
format.html { render :edit }
|
|
||||||
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
|
format.json { render json: @edu_setting.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,7 +53,6 @@ class EduSettingsController < ApplicationController
|
||||||
def destroy
|
def destroy
|
||||||
@edu_setting.destroy
|
@edu_setting.destroy
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to edu_settings_url, notice: 'Edu setting was successfully destroyed.' }
|
|
||||||
format.json { head :no_content }
|
format.json { head :no_content }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class ForksController < ApplicationController
|
class ForksController < ApplicationController
|
||||||
before_action :require_login
|
before_action :require_login
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_project
|
before_action :load_project
|
||||||
before_action :authenticate_project!, :authenticate_user!
|
before_action :authenticate_project!, :authenticate_user!
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ class IssueTagsController < ApplicationController
|
||||||
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
issue_tags = @project.issue_tags.order("#{order_name} #{order_type}")
|
issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}")
|
||||||
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||||
@page = params[:page] || 1
|
@page = params[:page] || 1
|
||||||
@limit = params[:limit] || 15
|
@limit = params[:limit] || 15
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
class IssuesController < ApplicationController
|
class IssuesController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :show, :index_chosen]
|
before_action :require_login, except: [:index, :show, :index_chosen]
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_project
|
before_action :load_project
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
|
before_action :check_menu_authorize, except: [:index_chosen]
|
||||||
before_action :check_issue_permission
|
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 :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]
|
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
|
||||||
before_action :check_token_enough, only: [:create, :update]
|
before_action :check_token_enough, :find_atme_receivers, only: [:create, :update]
|
||||||
|
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include TagChosenHelper
|
include TagChosenHelper
|
||||||
|
|
||||||
def index
|
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) || @project.is_public?)
|
||||||
@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 = @project.issues.issue_issue.issue_index_includes
|
||||||
issues = issues.where(is_private: false) unless @user_admin_or_member
|
issues = issues.where(is_private: false) unless @user_admin_or_member
|
||||||
|
|
||||||
|
@ -109,6 +111,8 @@ class IssuesController < ApplicationController
|
||||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
||||||
@issue = Issue.new(issue_params)
|
@issue = Issue.new(issue_params)
|
||||||
if @issue.save!
|
if @issue.save!
|
||||||
|
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||||
if params[:attachment_ids].present?
|
if params[:attachment_ids].present?
|
||||||
params[:attachment_ids].each do |id|
|
params[:attachment_ids].each do |id|
|
||||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||||
|
@ -138,6 +142,10 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||||
|
|
||||||
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||||
|
|
||||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||||
else
|
else
|
||||||
normal_status(-1, "创建失败")
|
normal_status(-1, "创建失败")
|
||||||
|
@ -156,6 +164,7 @@ class IssuesController < ApplicationController
|
||||||
def update
|
def update
|
||||||
last_token = @issue.token
|
last_token = @issue.token
|
||||||
last_status_id = @issue.status_id
|
last_status_id = @issue.status_id
|
||||||
|
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||||
@issue&.issue_tags_relates&.destroy_all
|
@issue&.issue_tags_relates&.destroy_all
|
||||||
params[:issue_tag_ids].each do |tag|
|
params[:issue_tag_ids].each do |tag|
|
||||||
|
@ -200,6 +209,26 @@ class IssuesController < ApplicationController
|
||||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
||||||
if @issue.update_attributes(issue_params)
|
if @issue.update_attributes(issue_params)
|
||||||
|
if @issue&.pull_request.present?
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @issue&.pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
|
||||||
|
else
|
||||||
|
previous_changes = @issue.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name)
|
||||||
|
if @issue.previous_changes[:start_date].present?
|
||||||
|
previous_changes.merge!(start_date: [@issue.previous_changes[:start_date][0].to_s, @issue.previous_changes[:start_date][1].to_s])
|
||||||
|
end
|
||||||
|
if @issue.previous_changes[:due_date].present?
|
||||||
|
previous_changes.merge!(due_date: [@issue.previous_changes[:due_date][0].to_s, @issue.previous_changes[:due_date][1].to_s])
|
||||||
|
end
|
||||||
|
if @issue.previous_changes[:status_id].present? && @issue.previous_changes[:status_id][1] == 5
|
||||||
|
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE)
|
||||||
|
end
|
||||||
|
if @issue.previous_changes[:status_id].present? && @issue.previous_changes[:status_id][0] == 5
|
||||||
|
@issue.project_trends.where(action_type: ProjectTrend::CLOSE).destroy_all
|
||||||
|
end
|
||||||
|
SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, @issue&.id, previous_changes) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
|
||||||
|
end
|
||||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||||
@issue.issue_times.update_all(end_time: Time.now)
|
@issue.issue_times.update_all(end_time: Time.now)
|
||||||
@issue.update_closed_issues_count_in_project!
|
@issue.update_closed_issues_count_in_project!
|
||||||
|
@ -218,7 +247,11 @@ class IssuesController < ApplicationController
|
||||||
change_type = change_token > 0 ? "add" : "minus"
|
change_type = change_token > 0 ? "add" : "minus"
|
||||||
post_to_chain(change_type, change_token.abs, current_user.try(:login))
|
post_to_chain(change_type, change_token.abs, current_user.try(:login))
|
||||||
end
|
end
|
||||||
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id)
|
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) if @issue.previous_changes.present?
|
||||||
|
|
||||||
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||||
|
|
||||||
normal_status(0, "更新成功")
|
normal_status(0, "更新成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "更新失败")
|
normal_status(-1, "更新失败")
|
||||||
|
@ -230,7 +263,7 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user_permission = current_user.present? && current_user.logged? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user)
|
@user_permission = current_user.present? && current_user.logged? && (@project.member?(current_user) || current_user.admin? || @issue.user == current_user)
|
||||||
@issue_attachments = @issue.attachments
|
@issue_attachments = @issue.attachments
|
||||||
@issue_user = @issue.user
|
@issue_user = @issue.user
|
||||||
@issue_assign_to = @issue.get_assign_user
|
@issue_assign_to = @issue.get_assign_user
|
||||||
|
@ -251,6 +284,7 @@ class IssuesController < ApplicationController
|
||||||
status_id = @issue.status_id
|
status_id = @issue.status_id
|
||||||
token = @issue.token
|
token = @issue.token
|
||||||
login = @issue.user.try(:login)
|
login = @issue.user.try(:login)
|
||||||
|
SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigned_to_id, @issue.author_id) if Site.has_notice_menu?
|
||||||
if @issue.destroy
|
if @issue.destroy
|
||||||
if issue_type == "2" && status_id != 5
|
if issue_type == "2" && status_id != 5
|
||||||
post_to_chain("add", token, login)
|
post_to_chain("add", token, login)
|
||||||
|
@ -270,8 +304,12 @@ class IssuesController < ApplicationController
|
||||||
def clean
|
def clean
|
||||||
#批量删除,暂时只能删除未悬赏的
|
#批量删除,暂时只能删除未悬赏的
|
||||||
issue_ids = params[:ids]
|
issue_ids = params[:ids]
|
||||||
if issue_ids.present?
|
issues = Issue.where(id: issue_ids, issue_type: "1")
|
||||||
if Issue.where(id: issue_ids, issue_type: "1").destroy_all
|
if issues.present?
|
||||||
|
issues.find_each do |i|
|
||||||
|
SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, i&.subject, i.assigned_to_id, i.author_id) if Site.has_notice_menu?
|
||||||
|
end
|
||||||
|
if issues.destroy_all
|
||||||
normal_status(0, "删除成功")
|
normal_status(0, "删除成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "删除失败")
|
normal_status(-1, "删除失败")
|
||||||
|
@ -301,9 +339,28 @@ class IssuesController < ApplicationController
|
||||||
# update_hash = params[:issue]
|
# update_hash = params[:issue]
|
||||||
issue_ids = params[:ids]
|
issue_ids = params[:ids]
|
||||||
if issue_ids.present?
|
if issue_ids.present?
|
||||||
|
issues = Issue.where(id: issue_ids)
|
||||||
if update_hash.blank?
|
if update_hash.blank?
|
||||||
normal_status(-1, "请选择批量更新内容")
|
normal_status(-1, "请选择批量更新内容")
|
||||||
elsif Issue.where(id: issue_ids).update_all(update_hash)
|
elsif issues&.update(update_hash)
|
||||||
|
issues.each do |i|
|
||||||
|
i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?
|
||||||
|
previous_changes = i.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name)
|
||||||
|
if i.previous_changes[:start_date].present?
|
||||||
|
previous_changes.merge!(start_date: [i.previous_changes[:start_date][0].to_s, i.previous_changes[:start_date][1].to_s])
|
||||||
|
end
|
||||||
|
if i.previous_changes[:due_date].present?
|
||||||
|
previous_changes.merge!(due_date: [i.previous_changes[:due_date][0].to_s, i.previous_changes[:due_date][1].to_s])
|
||||||
|
end
|
||||||
|
if i.previous_changes[:status_id].present? && i.previous_changes[:status_id][1] == 5
|
||||||
|
i.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE)
|
||||||
|
end
|
||||||
|
if i.previous_changes[:status_id].present? && i.previous_changes[:status_id][0] == 5
|
||||||
|
i.project_trends.where(action_type: ProjectTrend::CLOSE).destroy_all
|
||||||
|
end
|
||||||
|
SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, i&.id, previous_changes) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, i&.id) if i.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
|
||||||
|
end
|
||||||
normal_status(0, "批量更新成功")
|
normal_status(0, "批量更新成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "批量更新失败")
|
normal_status(-1, "批量更新失败")
|
||||||
|
@ -315,7 +372,10 @@ class IssuesController < ApplicationController
|
||||||
|
|
||||||
def copy
|
def copy
|
||||||
@new_issue = @issue.dup
|
@new_issue = @issue.dup
|
||||||
|
@new_issue.author_id = current_user.id
|
||||||
if @new_issue.save
|
if @new_issue.save
|
||||||
|
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @new_issue&.id) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @new_issue&.id) if Site.has_notice_menu?
|
||||||
issue_tags = @issue.issue_tags.pluck(:id)
|
issue_tags = @issue.issue_tags.pluck(:id)
|
||||||
if issue_tags.present?
|
if issue_tags.present?
|
||||||
issue_tags.each do |tag|
|
issue_tags.each do |tag|
|
||||||
|
@ -393,25 +453,29 @@ class IssuesController < ApplicationController
|
||||||
|
|
||||||
def check_project_public
|
def check_project_public
|
||||||
unless @project.is_public || @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id)
|
unless @project.is_public || @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id)
|
||||||
normal_status(-1, "您没有权限")
|
return render_forbidden
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_issue
|
def set_issue
|
||||||
@issue = Issue.find_by_id(params[:id])
|
@issue = Issue.find_by_id(params[:id])
|
||||||
if @issue.blank?
|
if @issue.blank?
|
||||||
normal_status(-1, "标签不存在")
|
return render_not_found
|
||||||
elsif @issue.is_lock &&!(@project.member?(current_user) || current_user.admin?)
|
elsif !(@project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))))
|
||||||
normal_status(-1, "您没有权限")
|
return render_forbidden
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_issue_permission
|
def check_issue_permission
|
||||||
unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))
|
unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))
|
||||||
normal_status(-1, "您没有权限")
|
return render_forbidden
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def operate_issue_permission
|
||||||
|
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
|
||||||
|
end
|
||||||
|
|
||||||
def export_issues(issues)
|
def export_issues(issues)
|
||||||
@table_columns = %w(ID 类型 标题 描述 状态 指派给 优先级 标签 发布人 创建时间 里程碑 开始时间 截止时间 完成度 分类 金额 属于)
|
@table_columns = %w(ID 类型 标题 描述 状态 指派给 优先级 标签 发布人 创建时间 里程碑 开始时间 截止时间 完成度 分类 金额 属于)
|
||||||
@export_issues = []
|
@export_issues = []
|
||||||
|
@ -491,4 +555,8 @@ class IssuesController < ApplicationController
|
||||||
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
|
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_menu_authorize
|
||||||
|
return render_not_found unless @project.has_menu_permission("issues")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class JournalsController < ApplicationController
|
class JournalsController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :get_children_journals]
|
before_action :require_login, except: [:index, :get_children_journals]
|
||||||
|
before_action :require_profile_completed, :find_atme_receivers, only: [:create]
|
||||||
before_action :set_issue
|
before_action :set_issue
|
||||||
before_action :check_issue_permission
|
before_action :check_issue_permission
|
||||||
before_action :set_journal, only: [:destroy, :edit, :update]
|
before_action :set_journal, only: [:destroy, :edit, :update]
|
||||||
|
@ -21,32 +22,35 @@ class JournalsController < ApplicationController
|
||||||
if notes.blank?
|
if notes.blank?
|
||||||
normal_status(-1, "评论内容不能为空")
|
normal_status(-1, "评论内容不能为空")
|
||||||
else
|
else
|
||||||
journal_params = {
|
ActiveRecord::Base.transaction do
|
||||||
journalized_id: @issue.id ,
|
journal_params = {
|
||||||
journalized_type: "Issue",
|
journalized_id: @issue.id ,
|
||||||
user_id: current_user.id ,
|
journalized_type: "Issue",
|
||||||
notes: notes.to_s.strip,
|
user_id: current_user.id ,
|
||||||
parent_id: params[:parent_id]
|
notes: notes.to_s.strip,
|
||||||
}
|
parent_id: params[:parent_id]
|
||||||
journal = Journal.new journal_params
|
}
|
||||||
if journal.save
|
journal = Journal.new journal_params
|
||||||
if params[:attachment_ids].present?
|
if journal.save
|
||||||
params[:attachment_ids].each do |id|
|
if params[:attachment_ids].present?
|
||||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
params[:attachment_ids].each do |id|
|
||||||
unless attachment.blank?
|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||||
attachment.container = journal
|
unless attachment.blank?
|
||||||
attachment.author_id = current_user.id
|
attachment.container = journal
|
||||||
attachment.description = ""
|
attachment.author_id = current_user.id
|
||||||
attachment.save
|
attachment.description = ""
|
||||||
|
attachment.save
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
AtmeService.call(current_user, @atme_receivers, journal) if @atme_receivers.size > 0
|
||||||
|
# @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
|
||||||
|
render :json => { status: 0, message: "评论成功", id: journal.id}
|
||||||
|
# normal_status(0, "评论成功")
|
||||||
|
else
|
||||||
|
normal_status(-1, "评论失败")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
|
|
||||||
render :json => { status: 0, message: "评论成功", id: journal.id}
|
|
||||||
# normal_status(0, "评论成功")
|
|
||||||
else
|
|
||||||
normal_status(-1, "评论失败")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,9 +23,9 @@ class MainController < ApplicationController
|
||||||
|
|
||||||
# TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发
|
# TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发
|
||||||
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
|
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
|
||||||
render file: 'public/h5educoderbuild/index.html', :layout => false
|
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'
|
||||||
else
|
else
|
||||||
render file: 'public/react/build/index.html', :layout => false
|
render file: 'public/react/build/index.html', :layout => false, :content_type=> 'text/html'
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,15 @@ class MembersController < ApplicationController
|
||||||
before_action :require_login
|
before_action :require_login
|
||||||
before_action :load_project
|
before_action :load_project
|
||||||
before_action :find_user_with_id, only: %i[create remove change_role]
|
before_action :find_user_with_id, only: %i[create remove change_role]
|
||||||
|
before_action :check_user_profile_completed, only: [:create]
|
||||||
before_action :operate!, except: %i[index]
|
before_action :operate!, except: %i[index]
|
||||||
before_action :check_member_exists!, only: %i[create]
|
before_action :check_member_exists!, only: %i[create]
|
||||||
before_action :check_member_not_exists!, only: %i[remove change_role]
|
before_action :check_member_not_exists!, only: %i[remove change_role]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
|
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
render_response(interactor)
|
render_response(interactor)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -27,6 +30,8 @@ class MembersController < ApplicationController
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user)
|
interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user)
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectLeft', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
render_response(interactor)
|
render_response(interactor)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -35,6 +40,7 @@ class MembersController < ApplicationController
|
||||||
|
|
||||||
def change_role
|
def change_role
|
||||||
interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role])
|
interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role])
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectRole', current_user.id, @user.id, @project.id, message_role_name) if Site.has_notice_menu?
|
||||||
render_response(interactor)
|
render_response(interactor)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -47,7 +53,7 @@ class MembersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def member_exists?
|
def member_exists?
|
||||||
@project.members.exists?(params[:user_id])
|
@project.members.exists?(user_id: params[:user_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def operate!
|
def operate!
|
||||||
|
@ -55,10 +61,24 @@ class MembersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_member_exists!
|
def check_member_exists!
|
||||||
return render_result(1, "user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
|
return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_member_not_exists!
|
def check_member_not_exists!
|
||||||
return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless @project.member?(params[:user_id])
|
return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_user_profile_completed
|
||||||
|
require_user_profile_completed(@user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def message_role_name
|
||||||
|
case params[:role]
|
||||||
|
when 'Manager' then '管理员'
|
||||||
|
when 'Developer' then '开发者'
|
||||||
|
when 'Reporter' then '报告者'
|
||||||
|
else
|
||||||
|
''
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class Organizations::OrganizationsController < Organizations::BaseController
|
class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
before_action :require_login, except: [:index, :show, :recommend]
|
before_action :require_login, except: [:index, :show, :recommend]
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :convert_image!, only: [:create, :update]
|
before_action :convert_image!, only: [:create, :update]
|
||||||
before_action :load_organization, only: [:show, :update, :destroy]
|
before_action :load_organization, only: [:show, :update, :destroy]
|
||||||
before_action :check_user_can_edit_org, only: [:update, :destroy]
|
before_action :check_user_can_edit_org, only: [:update, :destroy]
|
||||||
|
@ -21,10 +22,12 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
@can_create_project = @organization.can_create_project?(current_user.id)
|
@can_create_project = @organization.can_create_project?(current_user.id)
|
||||||
@is_admin = can_edit_org?
|
@is_admin = can_edit_org?
|
||||||
@is_member = @organization.is_member?(current_user.id)
|
@is_member = @organization.is_member?(current_user.id)
|
||||||
|
Cache::V2::OwnerCommonService.new(@organization.id).read
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
||||||
Organizations::CreateForm.new(organization_params).validate!
|
Organizations::CreateForm.new(organization_params).validate!
|
||||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||||
|
@ -41,7 +44,8 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
@organization.login = organization_params[:name] if organization_params[:name].present?
|
@organization.login = organization_params[:name] if organization_params[:name].present?
|
||||||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||||
@organization.save!
|
@organization.save!
|
||||||
@organization.organization_extension.update_attributes!(organization_params.except(:name, :nickname))
|
sync_organization_extension!
|
||||||
|
|
||||||
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
||||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||||
end
|
end
|
||||||
|
@ -65,8 +69,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
def recommend
|
def recommend
|
||||||
recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer)
|
recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer)
|
||||||
|
|
||||||
@organizations = Organization.with_visibility(%w(common))
|
@organizations = Organization.includes(:organization_extension).where(organization_extensions: {recommend: true}).to_a.each_slice(group_size).to_a
|
||||||
.where(login: recommend).select(:id, :login, :firstname, :lastname, :nickname)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -77,6 +80,10 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
:max_repo_creation, :nickname)
|
:max_repo_creation, :nickname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def group_size
|
||||||
|
params.fetch(:group_size, 4).to_i
|
||||||
|
end
|
||||||
|
|
||||||
def password
|
def password
|
||||||
params.fetch(:password, "")
|
params.fetch(:password, "")
|
||||||
end
|
end
|
||||||
|
@ -95,4 +102,18 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def 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
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
class Organizations::TeamUsersController < Organizations::BaseController
|
class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
before_action :load_organization, :load_team
|
before_action :load_organization, :load_team
|
||||||
before_action :load_operate_user, only: [:create, :destroy]
|
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 :load_team_user, only: [:destroy]
|
||||||
before_action :check_user_can_edit_org, only: [:create, :destroy]
|
before_action :check_user_can_edit_org, only: [:create, :destroy]
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
||||||
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
||||||
|
SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu?
|
||||||
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -29,6 +31,11 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_user.destroy!
|
@team_user.destroy!
|
||||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||||
|
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
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -43,6 +50,11 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_user.destroy!
|
@team_user.destroy!
|
||||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, current_user.login)
|
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
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -73,4 +85,8 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
tip_exception("组织团队成员不存在") if @team_user.nil?
|
tip_exception("组织团队成员不存在") if @team_user.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_user_profile_completed
|
||||||
|
require_user_profile_completed(@operate_user)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
class OwnersController < ApplicationController
|
class OwnersController < ApplicationController
|
||||||
before_action :require_login
|
before_action :require_login, only: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@owners = []
|
@owners = []
|
||||||
|
@ -9,4 +9,53 @@ class OwnersController < ApplicationController
|
||||||
teams: {can_create_org_project: true})
|
teams: {can_create_org_project: true})
|
||||||
.distinct
|
.distinct
|
||||||
end
|
end
|
||||||
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
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class PraiseTreadController < ApplicationController
|
class PraiseTreadController < ApplicationController
|
||||||
before_action :require_login, except: %i[index]
|
before_action :require_login, except: %i[index]
|
||||||
|
before_action :require_profile_completed, only: [:like]
|
||||||
before_action :find_project_with_id
|
before_action :find_project_with_id
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -5,6 +5,10 @@ class ProjectCategoriesController < ApplicationController
|
||||||
@project_categories = q.result(distinct: true)
|
@project_categories = q.result(distinct: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pinned_index
|
||||||
|
@project_categories = ProjectCategory.where.not(pinned_index: 0).order(pinned_index: :desc)
|
||||||
|
end
|
||||||
|
|
||||||
def group_list
|
def group_list
|
||||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
||||||
# projects = Project.no_anomory_projects.visible
|
# projects = Project.no_anomory_projects.visible
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
class ProjectRankController < ApplicationController
|
||||||
|
# 根据时间获取热门项目
|
||||||
|
def index
|
||||||
|
$redis_cache.zunionstore("recent-days-project-rank", get_timeable_key_names)
|
||||||
|
deleted_data = $redis_cache.smembers("v2-project-rank-deleted")
|
||||||
|
$redis_cache.zrem("recent-days-project-rank", deleted_data) unless deleted_data.blank?
|
||||||
|
@project_rank = $redis_cache.zrevrange("recent-days-project-rank", 0, 4, withscores: true)
|
||||||
|
rescue Exception => e
|
||||||
|
@project_rank = []
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# 默认显示7天的
|
||||||
|
def time
|
||||||
|
params.fetch(:time, 7).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_timeable_key_names
|
||||||
|
names_array = []
|
||||||
|
(0...time).to_a.each do |i|
|
||||||
|
date_time_string = (Date.today - i.days).to_s
|
||||||
|
names_array << "v2-project-rank-#{date_time_string}"
|
||||||
|
end
|
||||||
|
names_array
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
|
||||||
before_action :check_project_public
|
before_action :check_project_public
|
||||||
|
|
||||||
def index
|
def index
|
||||||
project_trends = @project.project_trends.includes(:user, trend: :user)
|
project_trends = @project.project_trends.preload(:user, trend: :user)
|
||||||
|
|
||||||
check_time = params[:time] #时间的筛选
|
check_time = params[:time] #时间的筛选
|
||||||
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
||||||
|
@ -14,20 +14,25 @@ class ProjectTrendsController < ApplicationController
|
||||||
project_trends = project_trends.where("created_at between ? and ?",(Time.now.beginning_of_day - check_time.days), Time.now.end_of_day)
|
project_trends = project_trends.where("created_at between ? and ?",(Time.now.beginning_of_day - check_time.days), Time.now.end_of_day)
|
||||||
end
|
end
|
||||||
|
|
||||||
@project_open_issues_count = project_trends.where(trend_type: "Issue", action_type: "create").size
|
|
||||||
@project_close_issues_count = project_trends.where(trend_type: "Issue", action_type: "close").size
|
@project_close_issues_count = project_trends.where(trend_type: "Issue", action_type: "close").size
|
||||||
@project_issues_count = @project_open_issues_count + @project_close_issues_count
|
@project_issues_count = project_trends.where(trend_type: "Issue", action_type: "create").size
|
||||||
|
@project_open_issues_count = @project_issues_count - @project_close_issues_count
|
||||||
@project_pr_count = project_trends.where(trend_type: "PullRequest", action_type: "close").size
|
|
||||||
@project_new_pr_count = project_trends.where(trend_type: "PullRequest", action_type: "create").size
|
|
||||||
@project_pr_all_count = @project_pr_count + @project_new_pr_count
|
|
||||||
|
|
||||||
|
@project_pr_count = project_trends.where(trend_type: "PullRequest", action_type: ["close", "merge"]).size
|
||||||
|
@project_pr_all_count = project_trends.where(trend_type: "PullRequest", action_type: "create").size
|
||||||
|
@project_new_pr_count = @project_pr_all_count - @project_pr_count
|
||||||
if check_type.present?
|
if check_type.present?
|
||||||
project_trends = project_trends.where(trend_type: check_type.to_s.strip)
|
project_trends = project_trends.where(trend_type: check_type.to_s.strip)
|
||||||
end
|
end
|
||||||
|
|
||||||
if check_status.present?
|
if check_status.present?
|
||||||
project_trends = project_trends.where(action_type: check_status.to_s.strip)
|
if check_status == "delay" || check_status == "close"
|
||||||
|
project_trends = project_trends.where(action_type: ["close", "merge"])
|
||||||
|
else
|
||||||
|
project_trends = project_trends.where(action_type: ["create"]).where.not(trend_id: project_trends.where(action_type: ["close", "merge"]).pluck(:trend_id))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
project_trends = project_trends.where(action_type: "create")
|
||||||
end
|
end
|
||||||
project_trends = project_trends.order("created_at desc")
|
project_trends = project_trends.order("created_at desc")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class Projects::AppliedTransferProjectsController < Projects::BaseController
|
class Projects::AppliedTransferProjectsController < Projects::BaseController
|
||||||
before_action :check_auth
|
before_action :check_auth
|
||||||
|
before_action :check_user_profile_completed, only: [:create]
|
||||||
|
|
||||||
def organizations
|
def organizations
|
||||||
@organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)})
|
@organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)})
|
||||||
|
@ -23,4 +24,10 @@ class Projects::AppliedTransferProjectsController < Projects::BaseController
|
||||||
def check_auth
|
def check_auth
|
||||||
return render_forbidden unless current_user.admin? ||@project.owner?(current_user)
|
return render_forbidden unless current_user.admin? ||@project.owner?(current_user)
|
||||||
end
|
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
|
end
|
|
@ -4,4 +4,7 @@ class Projects::BaseController < ApplicationController
|
||||||
before_action :load_project
|
before_action :load_project
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
|
|
||||||
|
def require_manager!
|
||||||
|
return render_forbidden('你没有权限操作') unless current_user.admin? || @project.manager?(current_user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
class Projects::MembersController < Projects::BaseController
|
||||||
|
def index
|
||||||
|
users = @project.all_collaborators.like(params[:search]).includes(:user_extension)
|
||||||
|
@users = kaminari_paginate(users)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
class Projects::ProjectAppliesController < Projects::BaseController
|
class Projects::ProjectAppliesController < Projects::BaseController
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
def create
|
def create
|
||||||
project = Projects::ApplyJoinService.call(current_user, create_params)
|
project = Projects::ApplyJoinService.call(current_user, create_params)
|
||||||
render_ok(project_id: project.id)
|
render_ok(project_id: project.id)
|
||||||
|
|
|
@ -6,7 +6,8 @@ class Projects::ProjectUnitsController < Projects::BaseController
|
||||||
def create
|
def create
|
||||||
if current_user.admin? || @project.manager?(current_user)
|
if current_user.admin? || @project.manager?(current_user)
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
ProjectUnit.update_by_unit_types!(@project, unit_types)
|
before_units, after_units = ProjectUnit.update_by_unit_types!(@project, unit_types)
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, {navbar: true}) unless before_units.eql?(after_units) if Site.has_notice_menu?
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Projects::TeamsController < Projects::BaseController
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_project = TeamProject.build(@owner.id, @operate_team.id, @project.id)
|
@team_project = TeamProject.build(@owner.id, @operate_team.id, @project.id)
|
||||||
Gitea::Organization::TeamProject::CreateService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
Gitea::Organization::TeamProject::CreateService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -25,7 +25,7 @@ class Projects::TeamsController < Projects::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_project.destroy!
|
@team_project.destroy!
|
||||||
Gitea::Organization::TeamProject::DeleteService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
Gitea::Organization::TeamProject::DeleteService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
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
|
|
@ -4,8 +4,9 @@ class ProjectsController < ApplicationController
|
||||||
include ProjectsHelper
|
include ProjectsHelper
|
||||||
include Acceleratorable
|
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_login, except: %i[index branches branches_slice group_type_list simple show fork_users praise_users watch_users recommend banner_recommend about menu_list]
|
||||||
before_action :load_project, except: %i[index group_type_list migrate create recommend]
|
before_action :require_profile_completed, only: [:create, :migrate]
|
||||||
|
before_action :load_repository, except: %i[index group_type_list migrate create recommend banner_recommend]
|
||||||
before_action :authorizate_user_can_edit_project!, only: %i[update]
|
before_action :authorizate_user_can_edit_project!, only: %i[update]
|
||||||
before_action :project_public?, only: %i[fork_users praise_users watch_users]
|
before_action :project_public?, only: %i[fork_users praise_users watch_users]
|
||||||
|
|
||||||
|
@ -16,20 +17,21 @@ class ProjectsController < ApplicationController
|
||||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
|
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("devops")) if @project.has_menu_permission("devops")
|
||||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
|
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("activity"))
|
||||||
menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user)
|
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
|
||||||
|
|
||||||
render json: menu
|
render json: menu
|
||||||
end
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
scope = Projects::ListQuery.call(params)
|
scope = current_user.logged? ? Projects::ListQuery.call(params, current_user.id) : Projects::ListQuery.call(params)
|
||||||
|
|
||||||
# @projects = kaminari_paginate(scope)
|
@projects = kaminari_paginate(scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units))
|
||||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
|
# @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
|
||||||
|
|
||||||
category_id = params[:category_id]
|
category_id = params[:category_id]
|
||||||
@total_count =
|
@total_count =
|
||||||
|
@ -84,6 +86,13 @@ class ProjectsController < ApplicationController
|
||||||
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def branches_slice
|
||||||
|
return @branches = [] unless @project.forge?
|
||||||
|
|
||||||
|
slice_result = Gitea::Repository::Branches::ListSliceService.call(@owner, @project.identifier)
|
||||||
|
@branches_slice = slice_result.is_a?(Hash) && slice_result.key?(:status) ? [] : slice_result
|
||||||
|
end
|
||||||
|
|
||||||
def group_type_list
|
def group_type_list
|
||||||
project_statics = ProjectStatistic.first
|
project_statics = ProjectStatistic.first
|
||||||
|
|
||||||
|
@ -108,28 +117,35 @@ class ProjectsController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
# TODO:
|
# TODO:
|
||||||
# 临时特殊处理修改website、lesson_url操作方法
|
# 临时特殊处理修改website、lesson_url操作方法
|
||||||
if project_params.has_key?("website")
|
if project_params.has_key?("website")
|
||||||
@project.update(project_params)
|
@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
|
else
|
||||||
validate_params = project_params.slice(:name, :description,
|
validate_params = project_params.slice(:name, :description,
|
||||||
:project_category_id, :project_language_id, :private)
|
:project_category_id, :project_language_id, :private, :identifier)
|
||||||
|
|
||||||
Projects::UpdateForm.new(validate_params).validate!
|
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
||||||
|
|
||||||
private = params[:private] || false
|
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||||
|
|
||||||
new_project_params = project_params.except(:private).merge(is_public: !private)
|
new_project_params = project_params.except(:private).merge(is_public: !private)
|
||||||
@project.update_attributes!(new_project_params)
|
@project.update_attributes!(new_project_params)
|
||||||
|
@project.forked_projects.update_all(is_public: @project.is_public)
|
||||||
gitea_params = {
|
gitea_params = {
|
||||||
private: private,
|
private: private,
|
||||||
default_branch: @project.default_branch,
|
default_branch: @project.default_branch,
|
||||||
website: @project.website
|
website: @project.website,
|
||||||
|
name: @project.identifier
|
||||||
}
|
}
|
||||||
if [true, false].include? private
|
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
|
||||||
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
|
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
||||||
@project.repository.update_column(:hidden, private)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -144,6 +160,7 @@ class ProjectsController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
||||||
@project.destroy!
|
@project.destroy!
|
||||||
|
@project.forked_projects.update_all(forked_from_project_id: nil)
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -173,6 +190,8 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def simple
|
def simple
|
||||||
|
# 为了缓存活跃项目的基本信息,后续删除
|
||||||
|
Cache::V2::ProjectCommonService.new(@project.id).read
|
||||||
json_response(@project, current_user)
|
json_response(@project, current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -180,6 +199,10 @@ class ProjectsController < ApplicationController
|
||||||
@projects = Project.recommend.includes(:repository, :project_category, :owner).order(visits: :desc)
|
@projects = Project.recommend.includes(:repository, :project_category, :owner).order(visits: :desc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def banner_recommend
|
||||||
|
@projects = Project.recommend.where.not(recommend_index: 0).includes(:project_category, :owner, :project_language).order(recommend_index: :desc)
|
||||||
|
end
|
||||||
|
|
||||||
def about
|
def about
|
||||||
@project_detail = @project.project_detail
|
@project_detail = @project.project_detail
|
||||||
@attachments = Array(@project_detail&.attachments) if request.get?
|
@attachments = Array(@project_detail&.attachments) if request.get?
|
||||||
|
@ -211,7 +234,7 @@ class ProjectsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
def project_params
|
def project_params
|
||||||
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url,
|
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
|
||||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
|
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
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
|
|
@ -1,14 +1,16 @@
|
||||||
class PullRequestsController < ApplicationController
|
class PullRequestsController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :show, :files, :commits]
|
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_repository
|
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 :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||||
before_action :load_pull_request, only: [:files, :commits]
|
before_action :load_pull_request, only: [:files, :commits]
|
||||||
|
before_action :find_atme_receivers, only: [:create, :update]
|
||||||
include TagChosenHelper
|
include TagChosenHelper
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
return render_not_found unless @project.has_menu_permission("pulls")
|
|
||||||
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
|
# @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 = @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))
|
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||||
|
@ -19,6 +21,7 @@ class PullRequestsController < ApplicationController
|
||||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||||
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||||
|
@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")
|
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "PullRequest")
|
||||||
@issues_size = scopes.size
|
@issues_size = scopes.size
|
||||||
|
@ -56,8 +59,11 @@ class PullRequestsController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||||
if @gitea_pull_request[:status] == :success
|
if @gitea_pull_request[:status] == :success
|
||||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"])
|
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
||||||
render_ok
|
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||||
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
AtmeService.call(current_user, @atme_receivers, @pull_request) if @atme_receivers.size > 0
|
||||||
else
|
else
|
||||||
render_error("create pull request error: #{@gitea_pull_request[:status]}")
|
render_error("create pull request error: #{@gitea_pull_request[:status]}")
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
|
@ -66,21 +72,22 @@ class PullRequestsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@fork_project_user_name = @project&.fork_project&.owner.try(:show_real_name)
|
@fork_project_user_name = @pull_request&.fork_project&.owner.try(:show_real_name)
|
||||||
@fork_project_user = @project&.fork_project&.owner.try(:login)
|
@fork_project_user = @pull_request&.fork_project&.owner.try(:login)
|
||||||
@fork_project_identifier = @project&.fork_project&.repository.try(:identifier)
|
@fork_project_identifier = @pull_request&.fork_project&.repository.try(:identifier)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if params[:title].nil?
|
if params[:title].nil?
|
||||||
normal_status(-1, "名称不能为空")
|
normal_status(-1, "名称不能为空")
|
||||||
elsif params[:issue_tag_ids].nil?
|
elsif params[:issue_tag_ids].nil?
|
||||||
normal_status(-1, "标签不能为空")
|
normal_status(-1, "标记不能为空")
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
merge_params
|
merge_params
|
||||||
|
|
||||||
|
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||||
@issue&.issue_tags_relates&.destroy_all
|
@issue&.issue_tags_relates&.destroy_all
|
||||||
params[:issue_tag_ids].each do |tag|
|
params[:issue_tag_ids].each do |tag|
|
||||||
|
@ -91,7 +98,7 @@ class PullRequestsController < ApplicationController
|
||||||
if @issue.update_attributes(@issue_params)
|
if @issue.update_attributes(@issue_params)
|
||||||
if @pull_request.update_attributes(@local_params.compact)
|
if @pull_request.update_attributes(@local_params.compact)
|
||||||
gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier,
|
gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier,
|
||||||
@pull_request.gpid, @requests_params, current_user.gitea_token)
|
@pull_request.gitea_number, @requests_params, current_user.gitea_token)
|
||||||
|
|
||||||
if gitea_pull[:status] === :success
|
if gitea_pull[:status] === :success
|
||||||
if params[:issue_tag_ids].present?
|
if params[:issue_tag_ids].present?
|
||||||
|
@ -102,6 +109,8 @@ class PullRequestsController < ApplicationController
|
||||||
if params[:status_id].to_i == 5
|
if params[:status_id].to_i == 5
|
||||||
@issue.issue_times.update_all(end_time: Time.now)
|
@issue.issue_times.update_all(end_time: Time.now)
|
||||||
end
|
end
|
||||||
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
AtmeService.call(current_user, @atme_receivers, @pull_request) if @atme_receivers.size > 0
|
||||||
normal_status(0, "PullRequest更新成功")
|
normal_status(0, "PullRequest更新成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "PullRequest更新失败")
|
normal_status(-1, "PullRequest更新失败")
|
||||||
|
@ -114,6 +123,8 @@ class PullRequestsController < ApplicationController
|
||||||
normal_status(-1, e.message)
|
normal_status(-1, e.message)
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
end
|
end
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,7 +134,13 @@ class PullRequestsController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
||||||
colsed === true ? normal_status(1, "已拒绝") : normal_status(-1, '合并失败')
|
if colsed === true
|
||||||
|
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||||
|
normal_status(1, "已拒绝")
|
||||||
|
else
|
||||||
|
normal_status(-1, '合并失败')
|
||||||
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
normal_status(-1, e.message)
|
normal_status(-1, e.message)
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
|
@ -139,7 +156,7 @@ class PullRequestsController < ApplicationController
|
||||||
@issue_user = @issue.user
|
@issue_user = @issue.user
|
||||||
@issue_assign_to = @issue.get_assign_user
|
@issue_assign_to = @issue.get_assign_user
|
||||||
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
||||||
@repository.identifier, @pull_request.gpid, current_user&.gitea_token)
|
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pr_merge
|
def pr_merge
|
||||||
|
@ -150,11 +167,20 @@ class PullRequestsController < ApplicationController
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params)
|
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login, @repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||||
|
|
||||||
if result.status == 200 && @pull_request.merge!
|
if @gitea_pull["merged_by"].present?
|
||||||
@pull_request.project_trend_status!
|
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!
|
||||||
|
# @pull_request.project_trend_status!
|
||||||
|
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
|
||||||
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
||||||
|
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||||
normal_status(1, "合并成功")
|
normal_status(1, "合并成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, result.message)
|
normal_status(-1, result.message)
|
||||||
|
@ -181,7 +207,7 @@ class PullRequestsController < ApplicationController
|
||||||
if can_merge.present?
|
if can_merge.present?
|
||||||
render json: {
|
render json: {
|
||||||
status: -2,
|
status: -2,
|
||||||
message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>",
|
message: "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}''>#{can_merge.first.try(:title)}</a>",
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
normal_status(0, "可以合并")
|
normal_status(0, "可以合并")
|
||||||
|
@ -191,12 +217,12 @@ class PullRequestsController < ApplicationController
|
||||||
|
|
||||||
|
|
||||||
def files
|
def files
|
||||||
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token)
|
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||||
# render json: @files_result
|
# render json: @files_result
|
||||||
end
|
end
|
||||||
|
|
||||||
def commits
|
def commits
|
||||||
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid, current_user&.gitea_token)
|
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||||
# render json: @commits_result
|
# render json: @commits_result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -252,4 +278,8 @@ class PullRequestsController < ApplicationController
|
||||||
status_id: 1,
|
status_id: 1,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_menu_authorize
|
||||||
|
return render_not_found unless @project.has_menu_permission("pulls")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
class RepositoriesController < ApplicationController
|
class RepositoriesController < ApplicationController
|
||||||
|
include RepositoriesHelper
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include OperateProjectAbilityAble
|
include OperateProjectAbilityAble
|
||||||
include Repository::LanguagesPercentagable
|
include Repository::LanguagesPercentagable
|
||||||
|
|
||||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||||
|
before_action :require_profile_completed, only: [:create_file]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit]
|
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||||
before_action :get_ref, only: %i[entries sub_entries top_counts file]
|
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||||
before_action :get_statistics, only: %i[top_counts]
|
before_action :get_statistics, only: %i[top_counts]
|
||||||
|
|
||||||
|
@ -46,23 +48,13 @@ class RepositoriesController < ApplicationController
|
||||||
|
|
||||||
def entries
|
def entries
|
||||||
@project.increment!(:visits)
|
@project.increment!(:visits)
|
||||||
|
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||||
if @project.educoder?
|
if @project.educoder?
|
||||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||||
else
|
else
|
||||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||||
|
|
||||||
# TODO
|
|
||||||
# 临时处理readme文件问题
|
|
||||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, @owner&.gitea_token)
|
|
||||||
@readme =
|
|
||||||
if result[:status] == :success
|
|
||||||
result[:body]
|
|
||||||
else
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,6 +64,7 @@ class RepositoriesController < ApplicationController
|
||||||
|
|
||||||
def sub_entries
|
def sub_entries
|
||||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||||
|
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||||
|
|
||||||
if @project.educoder?
|
if @project.educoder?
|
||||||
if params[:type] === 'file'
|
if params[:type] === 'file'
|
||||||
|
@ -102,10 +95,21 @@ class RepositoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def commits
|
def commits
|
||||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
if params[:filepath].present?
|
||||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||||
|
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||||
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||||
|
else
|
||||||
|
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||||
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def commits_slice
|
||||||
|
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
||||||
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||||
|
end
|
||||||
|
|
||||||
def commit
|
def commit
|
||||||
@sha = params[:sha]
|
@sha = params[:sha]
|
||||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||||
|
@ -119,7 +123,11 @@ class RepositoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def contributors
|
def contributors
|
||||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
if params[:filepath].present?
|
||||||
|
@contributors = []
|
||||||
|
else
|
||||||
|
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@ -182,16 +190,46 @@ class RepositoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def readme
|
def readme
|
||||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
if params[:filepath].present?
|
||||||
|
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||||
|
else
|
||||||
|
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||||
|
end
|
||||||
@readme = result[:status] === :success ? result[:body] : nil
|
@readme = result[:status] === :success ? result[:body] : nil
|
||||||
render json: @readme
|
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref])
|
||||||
|
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
||||||
|
rescue
|
||||||
|
render json: nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def languages
|
def languages
|
||||||
render json: languages_precentagable
|
render json: languages_precentagable
|
||||||
end
|
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 URI.escape(file_path)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_project
|
def find_project
|
||||||
|
@ -212,8 +250,14 @@ class RepositoriesController < ApplicationController
|
||||||
|
|
||||||
# TODO 获取最新commit信息
|
# TODO 获取最新commit信息
|
||||||
def project_commits
|
def project_commits
|
||||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
if params[:filepath].present?
|
||||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||||
|
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||||
|
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||||
|
else
|
||||||
|
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||||
|
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_statistics
|
def get_statistics
|
||||||
|
@ -266,7 +310,7 @@ class RepositoriesController < ApplicationController
|
||||||
|
|
||||||
# uploadPushInfo
|
# uploadPushInfo
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_new_pr(params)
|
def create_new_pr(params)
|
||||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||||
local_params = {
|
local_params = {
|
||||||
|
|
|
@ -4,7 +4,7 @@ class SettingsController < ApplicationController
|
||||||
get_add_menu
|
get_add_menu
|
||||||
get_common_menu
|
get_common_menu
|
||||||
get_personal_menu
|
get_personal_menu
|
||||||
|
get_top_system_notification
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -40,6 +40,10 @@ class SettingsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_top_system_notification
|
||||||
|
@top_system_notification = SystemNotification.is_top.first
|
||||||
|
end
|
||||||
|
|
||||||
def get_site_url(key, value)
|
def get_site_url(key, value)
|
||||||
key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value)
|
key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value)
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
class TemplateMessageSettingsController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
|
||||||
|
def index
|
||||||
|
@group_settings = TemplateMessageSetting.group(:type).count
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,24 @@
|
||||||
|
class UserRankController < ApplicationController
|
||||||
|
# 根据时间获取热门开发者
|
||||||
|
def index
|
||||||
|
$redis_cache.zunionstore("recent-days-user-rank", get_timeable_key_names)
|
||||||
|
@user_rank = $redis_cache.zrevrange("recent-days-user-rank", 0, 3, withscores: true)
|
||||||
|
rescue Exception => e
|
||||||
|
@user_rank = []
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# 默认显示7天的
|
||||||
|
def time
|
||||||
|
params.fetch(:time, 7).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_timeable_key_names
|
||||||
|
names_array = []
|
||||||
|
(0...time).to_a.each do |i|
|
||||||
|
date_time_string = (Date.today - i.days).to_s
|
||||||
|
names_array << "v2-user-rank-#{date_time_string}"
|
||||||
|
end
|
||||||
|
names_array
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,7 +5,7 @@ class Users::BaseController < ApplicationController
|
||||||
helper_method :observed_logged_user?, :observed_user
|
helper_method :observed_logged_user?, :observed_user
|
||||||
|
|
||||||
def observed_user
|
def observed_user
|
||||||
@_observed_user ||= (User.find_by_id(params[:user_id]) || User.find_by_login(params[:user_id]))
|
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def observed_logged_user?
|
def observed_logged_user?
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class Users::HeadmapsController < Users::BaseController
|
class Users::HeadmapsController < Users::BaseController
|
||||||
def index
|
def index
|
||||||
result = Gitea::User::HeadmapService.call(observed_user.login, start_stamp, end_stamp)
|
result = Gitea::User::HeadmapService.call(observed_user.login, start_stamp, end_stamp)
|
||||||
@headmaps = result[2]
|
@headmaps = result[2].blank? ? [] : result[2]
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
class Users::MessagesController < Users::BaseController
|
||||||
|
before_action :private_user_resources!
|
||||||
|
before_action :find_receivers, only: [:create]
|
||||||
|
|
||||||
|
def index
|
||||||
|
limit = params[:limit] || params[:per_page]
|
||||||
|
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
|
||||||
|
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||||
|
result = Notice::Read::ListService.call(observed_user.id, message_type, message_status, page, limit)
|
||||||
|
return render_error if result.nil?
|
||||||
|
@data = result[2]
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
return render_forbidden unless %w(atme).include?(params[:type])
|
||||||
|
case params[:type]
|
||||||
|
when 'atme'
|
||||||
|
Notice::Write::CreateAtmeForm.new(atme_params).validate!
|
||||||
|
case atme_params[:atmeable_type]
|
||||||
|
when 'Issue'
|
||||||
|
SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) if Site.has_notice_menu?
|
||||||
|
when 'PullRequest'
|
||||||
|
SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) if Site.has_notice_menu?
|
||||||
|
when 'Journal'
|
||||||
|
journal = Journal.find_by_id(atme_params[:atmeable_id])
|
||||||
|
if journal.present?
|
||||||
|
if journal&.issue&.pull_request.present?
|
||||||
|
SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) if Site.has_notice_menu?
|
||||||
|
else
|
||||||
|
SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) if Site.has_notice_menu?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
render_ok
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
return render_forbidden unless %w(atme).include?(params[:type])
|
||||||
|
result = Notice::Write::DeleteService.call(params[:ids], observed_user.id, message_type)
|
||||||
|
return render_error if result.nil?
|
||||||
|
|
||||||
|
render_ok
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def read
|
||||||
|
return render_forbidden unless %w(notification atme).include?(params[:type])
|
||||||
|
result = Notice::Write::ChangeStatusService.call(params[:ids], observed_user.id, message_type)
|
||||||
|
if result.nil?
|
||||||
|
render_error
|
||||||
|
else
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def message_type
|
||||||
|
@message_type = begin
|
||||||
|
case params[:type]
|
||||||
|
when "notification" then 1
|
||||||
|
when "atme" then 2
|
||||||
|
else
|
||||||
|
-1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def message_status
|
||||||
|
@message_status = begin
|
||||||
|
case params[:status]
|
||||||
|
when "1" then 1
|
||||||
|
when "2" then 2
|
||||||
|
else
|
||||||
|
-1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def atme_params
|
||||||
|
params.permit(:atmeable_type, :atmeable_id, receivers_login: [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_receivers
|
||||||
|
@receivers = User.where(login: params[:receivers_login])
|
||||||
|
return render_not_found if @receivers.size == 0
|
||||||
|
end
|
||||||
|
end
|
|
@ -14,7 +14,7 @@ class Users::StatisticsController < Users::BaseController
|
||||||
@date_data << date.strftime("%Y.%m.%d")
|
@date_data << date.strftime("%Y.%m.%d")
|
||||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
||||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||||
date_commit_data = commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
||||||
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||||
end
|
end
|
||||||
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}
|
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}
|
||||||
|
@ -188,30 +188,32 @@ class Users::StatisticsController < Users::BaseController
|
||||||
@project_languages_count = time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count
|
@project_languages_count = time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count
|
||||||
@platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count
|
@platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count
|
||||||
else
|
else
|
||||||
|
@platform_result = Cache::V2::PlatformStatisticService.new.read
|
||||||
|
@user_result = Cache::V2::UserStatisticService.new(observed_user.id).read
|
||||||
# 用户被follow数量
|
# 用户被follow数量
|
||||||
@follow_count = Cache::UserFollowCountService.call(observed_user)
|
@follow_count = @user_result["follow-count"].to_i
|
||||||
@platform_follow_count = Cache::PlatformFollowCountService.call
|
@platform_follow_count = @platform_result["follow-count"].to_i
|
||||||
# 用户pr数量
|
# 用户pr数量
|
||||||
@pullrequest_count = Cache::UserPullrequestCountService.call(observed_user)
|
@pullrequest_count = @user_result["pullrequest-count"].to_i
|
||||||
@platform_pullrequest_count = Cache::PlatformPullrequestCountService.call
|
@platform_pullrequest_count = @platform_result["pullrequest-count"].to_i
|
||||||
# 用户issue数量
|
# 用户issue数量
|
||||||
@issues_count = Cache::UserIssueCountService.call(observed_user)
|
@issues_count = @user_result["issue-count"].to_i
|
||||||
@platform_issues_count = Cache::PlatformIssueCountService.call
|
@platform_issues_count = @platform_result["issue-count"].to_i
|
||||||
# 用户总项目数
|
# 用户总项目数
|
||||||
@project_count = Cache::UserProjectCountService.call(observed_user)
|
@project_count = @user_result["project-count"].to_i
|
||||||
@platform_project_count = Cache::PlatformProjectCountService.call
|
@platform_project_count = @platform_result["project-count"].to_i
|
||||||
# 用户项目被fork数量
|
# 用户项目被fork数量
|
||||||
@fork_count = Cache::UserProjectForkCountService.call(observed_user)
|
@fork_count = @user_result["fork-count"].to_i
|
||||||
@platform_fork_count = Cache::PlatformProjectForkCountService.call
|
@platform_fork_count = @platform_result["fork-count"].to_i
|
||||||
# 用户项目关注数
|
# 用户项目关注数
|
||||||
@project_watchers_count = Cache::UserProjectWatchersCountService.call(observed_user)
|
@project_watchers_count = @user_result["project-watcher-count"].to_i
|
||||||
@platform_project_watchers_count = Cache::PlatformProjectWatchersCountService.call
|
@platform_project_watchers_count = @platform_result["project-watcher-count"].to_i
|
||||||
# 用户项目点赞数
|
# 用户项目点赞数
|
||||||
@project_praises_count = Cache::UserProjectPraisesCountService.call(observed_user)
|
@project_praises_count = @user_result["project-praise-count"].to_i
|
||||||
@platform_project_praises_count = Cache::PlatformProjectPraisesCountService.call
|
@platform_project_praises_count = @platform_result["project-praise-count"].to_i
|
||||||
# 用户不同语言项目数量
|
# 用户不同语言项目数量
|
||||||
@project_languages_count = Cache::UserProjectLanguagesCountService.call(observed_user)
|
@project_languages_count = JSON.parse(@user_result["project-language"])
|
||||||
@platform_project_languages_count = Cache::PlatformProjectLanguagesCountService.call
|
@platform_project_languages_count = JSON.parse(@platform_result["project-language"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Users::SystemNotificationHistoriesController < Users::BaseController
|
||||||
|
before_action :private_user_resources!, only: [:create]
|
||||||
|
def create
|
||||||
|
@history = observed_user.system_notification_histories.new(system_notification_id: params[:system_notification_id])
|
||||||
|
if @history.save
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
Rails.logger.info @history.errors.as_json
|
||||||
|
render_error(@history.errors.full_messages.join(","))
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,36 @@
|
||||||
|
class Users::TemplateMessageSettingsController < Users::BaseController
|
||||||
|
before_action :check_auth
|
||||||
|
before_action :get_current_setting
|
||||||
|
|
||||||
|
def current_setting
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_setting
|
||||||
|
Rails.logger.info setting_params[:notification_body]
|
||||||
|
Rails.logger.info setting_params[:email_body]
|
||||||
|
|
||||||
|
@current_setting.notification_body = setting_params[:notification_body].to_hash
|
||||||
|
@current_setting.email_body = setting_params[:email_body].to_hash
|
||||||
|
return render_error("保存失败") unless @current_setting.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def check_auth
|
||||||
|
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_current_setting
|
||||||
|
@current_setting = @_observed_user.user_template_message_setting
|
||||||
|
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def setting_params
|
||||||
|
params.require(:setting).permit(notification_body: {}, email_body: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_setting_params
|
||||||
|
setting_params[:notification_body].keys.equal?(UserTemplateMessageSetting.init_notification_body.keys) && setting_params[:email_body].keys.equal?(UserTemplateMessageSetting.init_email_body)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -51,6 +51,8 @@ class UsersController < ApplicationController
|
||||||
@projects_common_count = user_projects.common.size
|
@projects_common_count = user_projects.common.size
|
||||||
@projects_mirrior_count = user_projects.mirror.size
|
@projects_mirrior_count = user_projects.mirror.size
|
||||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||||
|
# 为了缓存活跃用户的基本信息,后续删除
|
||||||
|
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||||
end
|
end
|
||||||
|
|
||||||
def watch_users
|
def watch_users
|
||||||
|
@ -74,7 +76,7 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id])
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||||
@user.attributes = user_params.except(:image)
|
@user.attributes = user_params.except(:image)
|
||||||
|
@ -91,6 +93,12 @@ class UsersController < ApplicationController
|
||||||
def get_user_info
|
def get_user_info
|
||||||
begin
|
begin
|
||||||
@user = current_user
|
@user = current_user
|
||||||
|
begin
|
||||||
|
result = Notice::Read::CountService.call(current_user.id)
|
||||||
|
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||||
|
rescue
|
||||||
|
@message_unread_total = 0
|
||||||
|
end
|
||||||
# TODO 等消息上线再打开注释
|
# TODO 等消息上线再打开注释
|
||||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -185,7 +193,7 @@ class UsersController < ApplicationController
|
||||||
def trustie_related_projects
|
def trustie_related_projects
|
||||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||||
projects_json = []
|
projects_json = []
|
||||||
domain_url = EduSetting.get('host_name') + '/projects'
|
domain_url = EduSetting.get('host_name')
|
||||||
if projects.present?
|
if projects.present?
|
||||||
projects.each do |p|
|
projects.each do |p|
|
||||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
class VersionReleasesController < ApplicationController
|
class VersionReleasesController < ApplicationController
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
before_action :require_login, except: [:index]
|
before_action :require_login, except: [:index, :show]
|
||||||
before_action :find_version , only: [:edit, :update, :destroy]
|
before_action :check_release_authorize, except: [:index, :show]
|
||||||
|
before_action :find_version , only: [:show, :edit, :update, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
|
@version_releases = kaminari_paginate(@repository.version_releases.order(created_at: :desc))
|
||||||
@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?)
|
@user_admin_permission = current_user.present? && (@repository.project.all_managers.include?(current_user) || current_user.admin?)
|
||||||
@forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
@ -22,6 +22,10 @@ class VersionReleasesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
# @release = Gitea::Versions::GetService.call(current_user.gitea_token, @user&.login, @repository&.identifier, @version&.version_gid)
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if params[:name].nil?
|
if params[:name].nil?
|
||||||
normal_status(-1, "名称不能为空")
|
normal_status(-1, "名称不能为空")
|
||||||
|
@ -37,13 +41,14 @@ class VersionReleasesController < ApplicationController
|
||||||
version_params = releases_params
|
version_params = releases_params
|
||||||
version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id))
|
version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id))
|
||||||
if version_release.save!
|
if version_release.save!
|
||||||
git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call
|
git_version_release = Gitea::Versions::CreateService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call
|
||||||
if git_version_release
|
if git_version_release
|
||||||
update_params = {
|
update_params = {
|
||||||
tarball_url: git_version_release["tarball_url"],
|
tarball_url: git_version_release["tarball_url"],
|
||||||
zipball_url: git_version_release["zipball_url"],
|
zipball_url: git_version_release["zipball_url"],
|
||||||
url: git_version_release["url"],
|
url: git_version_release["url"],
|
||||||
version_gid: git_version_release["id"],
|
version_gid: git_version_release["id"],
|
||||||
|
sha: git_version_release["sha"]
|
||||||
}
|
}
|
||||||
version_release.update_attributes!(update_params)
|
version_release.update_attributes!(update_params)
|
||||||
version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||||
|
@ -81,7 +86,7 @@ class VersionReleasesController < ApplicationController
|
||||||
|
|
||||||
if @version.update_attributes!(version_params)
|
if @version.update_attributes!(version_params)
|
||||||
create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present?
|
create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present?
|
||||||
git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
|
git_version_release = Gitea::Versions::UpdateService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
|
||||||
unless git_version_release
|
unless git_version_release
|
||||||
raise Error, "更新失败"
|
raise Error, "更新失败"
|
||||||
end
|
end
|
||||||
|
@ -102,7 +107,7 @@ class VersionReleasesController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
if @version.destroy
|
if @version.destroy
|
||||||
git_version_release = Gitea::Versions::DeleteService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), @version.try(:version_gid)).call
|
git_version_release = Gitea::Versions::DeleteService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), @version.try(:version_gid)).call
|
||||||
|
|
||||||
if git_version_release.status == 204
|
if git_version_release.status == 204
|
||||||
normal_status(0, "删除成功")
|
normal_status(0, "删除成功")
|
||||||
|
@ -157,4 +162,8 @@ class VersionReleasesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_release_authorize
|
||||||
|
return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.manager?(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
class VersionsController < ApplicationController
|
class VersionsController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :show]
|
before_action :require_login, except: [:index, :show]
|
||||||
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
|
before_action :check_menu_authorize
|
||||||
before_action :check_issue_permission, except: [:show, :index]
|
before_action :check_issue_permission, except: [:show, :index]
|
||||||
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
|
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
|
||||||
|
|
||||||
def index
|
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))
|
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||||
status = params[:status]
|
status = params[:status]
|
||||||
versions = @project.versions.version_includes
|
versions = @project.versions.version_includes
|
||||||
|
@ -25,17 +26,13 @@ class VersionsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
version_issues = @version.issues.issue_includes
|
version_issues = @version.issues.issue_issue.issue_includes
|
||||||
|
|
||||||
status_type = params[:status_type] || "1"
|
status_type = params[:status_type] || "1"
|
||||||
# @close_issues_size = version_issues.where(status_id: 5).size
|
# @close_issues_size = version_issues.where(status_id: 5).size
|
||||||
# @open_issues_size = version_issues.size - @close_issues_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(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(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"
|
version_issues = version_issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present? && params[:tracker_id].to_s != "all"
|
||||||
|
@ -47,10 +44,26 @@ 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.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}")
|
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
|
@page = params[:page] || 1
|
||||||
@limit = params[:limit] || 15
|
@limit = params[:limit] || 15
|
||||||
@version_issues_size = version_issues.size
|
# @version_issues_size = version_issues.size
|
||||||
@version_issues = version_issues.page(@page).per(@limit)
|
@version_issues = version_issues.page(@page).per(@limit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -170,4 +183,8 @@ class VersionsController < ApplicationController
|
||||||
%w(desc asc).include?(params[:order_type]) ? params[:order_type] : 'desc'
|
%w(desc asc).include?(params[:order_type]) ? params[:order_type] : 'desc'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_menu_authorize
|
||||||
|
return render_not_found unless @project.has_menu_permission("versions")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class WatchersController < ApplicationController
|
class WatchersController < ApplicationController
|
||||||
before_action :require_login, except: %i[index]
|
before_action :require_login, except: %i[index]
|
||||||
|
before_action :require_profile_completed, only: [:follow]
|
||||||
# before_action :find_project_with_id
|
# before_action :find_project_with_id
|
||||||
before_action :get_target
|
before_action :get_target
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
module CourseDecorator
|
|
||||||
def can_visited?
|
|
||||||
is_public == 1 || User.current.admin_or_business? || User.current.member_of_course?(self)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,2 +0,0 @@
|
||||||
module EcCourseTargetDecorator
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
module ExperienceDecorator
|
|
||||||
def container_type_text
|
|
||||||
I18n.t("experience.container_type.#{container_type.to_s.underscore}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def content
|
|
||||||
case container_type.to_s.underscore
|
|
||||||
when 'game' then
|
|
||||||
game = Game.find_by(id: container_id)
|
|
||||||
game.present? ? "通过实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关获得的奖励" : ''
|
|
||||||
when 'shixun_publish' then
|
|
||||||
shixun = Shixun.find_by(id: container_id)
|
|
||||||
shixun.present? ? "发布实训“#{shixun.name}”获得的奖励" : ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,39 +0,0 @@
|
||||||
module GradeDecorator
|
|
||||||
def container_type_text
|
|
||||||
I18n.t("grade.container_type.#{container_type.to_s.underscore}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def content
|
|
||||||
case container_type.to_s.underscore
|
|
||||||
when 'avatar' then '用户首次上传头像获得的奖励'
|
|
||||||
when 'phone' then '用户首次绑定手机号码获得的奖励'
|
|
||||||
when 'mail' then '用户首次绑定邮箱获得的奖励'
|
|
||||||
when 'attendance' then '用户每天签到获得的奖励'
|
|
||||||
when 'account' then '新用户首次填写基本资料获得的奖励'
|
|
||||||
when 'memo' then '发布的评论或者帖子获得平台奖励'
|
|
||||||
when 'discusses' then '发布的评论获得平台奖励'
|
|
||||||
when 'star' then '用户给实训评分获得的随机奖励'
|
|
||||||
when 'feedback' then '反馈的问题获得平台奖励'
|
|
||||||
when 'authentication' then '用户首次完成实名认证获得的奖励'
|
|
||||||
when 'professional' then '用户首次完成职业认证获得的奖励'
|
|
||||||
when 'answer' then
|
|
||||||
game = Game.find_by(id: container_id)
|
|
||||||
game.present? ? "查看实训“#{game.challenge.shixun.name}”第#{game.challenge.position}关的参考答案消耗的金币" : ''
|
|
||||||
when 'game' then
|
|
||||||
game = Game.find_by(id: container_id)
|
|
||||||
game.present? ? "通过实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关获得的奖励" : ''
|
|
||||||
when 'test_set' then
|
|
||||||
game = Game.find_by(id: container_id)
|
|
||||||
game.present? ? "查看实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关的隐藏测试集消耗的金币" : ''
|
|
||||||
when 'shixun_publish' then
|
|
||||||
shixun = Shixun.find_by(id: container_id)
|
|
||||||
shixun.present? ? "发布实训“#{shixun.name}”获得的奖励" : ''
|
|
||||||
when 'check_ta_answer' then
|
|
||||||
game = Game.find_by(id: container_id)
|
|
||||||
game.present? ? "查看实训“#{game.challenge.shixun.name}”第#{game.challenge.position}关的TA人解答消耗的金币" : ''
|
|
||||||
when 'hack' then
|
|
||||||
hack = Hack.find_by(id: container_id)
|
|
||||||
hack.present? ? "完成了题目解答“#{hack.name}”,获得金币奖励:#{hack.score}" : ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
module LibraryDecorator
|
|
||||||
extend ApplicationDecorator
|
|
||||||
|
|
||||||
display_time_method :published_at, :created_at, :updated_at
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
module ShixunDecorator
|
|
||||||
def human_status
|
|
||||||
I18n.t("shixun.status.#{status}")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
module SubjectDecorator
|
|
||||||
def can_visited?
|
|
||||||
published? || User.current.admin? || member?(User.current)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
module VideoDecorator
|
|
||||||
extend ApplicationDecorator
|
|
||||||
|
|
||||||
display_time_method :published_at, :created_at, :updated_at
|
|
||||||
end
|
|
|
@ -12,6 +12,7 @@ toc_footers:
|
||||||
includes:
|
includes:
|
||||||
- licenses
|
- licenses
|
||||||
- gitignores
|
- gitignores
|
||||||
|
- public_keys
|
||||||
- users
|
- users
|
||||||
- projects
|
- projects
|
||||||
- repositories
|
- repositories
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,158 @@
|
||||||
|
<!--
|
||||||
|
* @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>
|
||||||
|
|
|
@ -1 +1,502 @@
|
||||||
# Pulls
|
# Pulls
|
||||||
|
|
||||||
|
|
||||||
|
## Get a pull request
|
||||||
|
获取合并请求详情接口
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls/88.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/Jasder/gitlink/pulls/88.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/pulls/:id.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|id |是| | integer | pull id值 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "响应成功",
|
||||||
|
"project_name": "Gitlink",
|
||||||
|
"identifier": "forgeplus",
|
||||||
|
"project_identifier": "forgeplus",
|
||||||
|
"pr_time": "52分钟前",
|
||||||
|
"commits_count": 229,
|
||||||
|
"files_count": 328,
|
||||||
|
"comments_count": 0,
|
||||||
|
"comments_total_count": 0,
|
||||||
|
"pull_request": {
|
||||||
|
"id": 1189,
|
||||||
|
"base": "master",
|
||||||
|
"head": "develop",
|
||||||
|
"status": 0,
|
||||||
|
"fork_project_id": null,
|
||||||
|
"is_original": false,
|
||||||
|
"pull_request_staus": "open",
|
||||||
|
"fork_project_user": null,
|
||||||
|
"create_user": "jasder",
|
||||||
|
"mergeable": true,
|
||||||
|
"state": "open"
|
||||||
|
},
|
||||||
|
"issue": {
|
||||||
|
"id": 51888,
|
||||||
|
"subject": "FIx release v3.2.0",
|
||||||
|
"description": null,
|
||||||
|
"is_private": false,
|
||||||
|
"branch_name": null,
|
||||||
|
"project_author_name": "Gitlink",
|
||||||
|
"closed_on": "",
|
||||||
|
"created_at": "2021-10-12 15:51",
|
||||||
|
"assign_user_name": "victor",
|
||||||
|
"assign_user_login": "moshenglv",
|
||||||
|
"author_name": "段甲生",
|
||||||
|
"author_login": "jasder",
|
||||||
|
"author_picture": "images/avatars/User/36480?t=1615520120",
|
||||||
|
"issue_status": "新增",
|
||||||
|
"priority": "正常",
|
||||||
|
"version": null,
|
||||||
|
"issue_tags": null
|
||||||
|
},
|
||||||
|
"conflict_files": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 获取pull request文件列表
|
||||||
|
获取pull request文件列表
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/Jason/gitlink/pulls/1/files.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/jasder/gitlink/pulls/1/files.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/pulls/:id/files.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |用户登录名 |
|
||||||
|
|repo |是|string |project's identifier |
|
||||||
|
|id |是|int |pull request's id |
|
||||||
|
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|-|-|-|
|
||||||
|
|files_count |int|文件更改的总数量|
|
||||||
|
|total_addition |int|添加代码总行数|
|
||||||
|
|total_deletion |int|删除代码总行数|
|
||||||
|
|files |array||
|
||||||
|
|-- sha |string|commit's sha value|
|
||||||
|
|-- name |string|当前文件名|
|
||||||
|
|-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改|
|
||||||
|
|-- addition |int|文件添加的行数|
|
||||||
|
|-- deletion |int|文件删除的行数|
|
||||||
|
|-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容|
|
||||||
|
|-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否|
|
||||||
|
|-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否|
|
||||||
|
|-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否|
|
||||||
|
|-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否|
|
||||||
|
|-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否|
|
||||||
|
|-- sections |array||
|
||||||
|
|---- fileName |string|文件名称|
|
||||||
|
|---- lines |array||
|
||||||
|
|------ leftIdx |string|文件变动之前所在行数|
|
||||||
|
|------ rightIdx |string|文件更改后所在行数|
|
||||||
|
|------ type |string|文件变更类型,1: 新增,2: 修改, 3: 删除, 4: diff统计信息|
|
||||||
|
|------ content |string|文件变更的内容|
|
||||||
|
|------ sectionInfo |object||
|
||||||
|
|-------- path |string|文件相对仓库的路径|
|
||||||
|
|-------- lastLeftIdx |int||
|
||||||
|
|-------- lastRightIdx |int||
|
||||||
|
|-------- leftHunkSize |int|文件变更之前的行数|
|
||||||
|
|-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)|
|
||||||
|
|-------- leftIdx |int|文件变更之前所在行数|
|
||||||
|
|-------- rightIdx |int|文件变更之后所在行数(即:页面编辑器开始显示的行数)|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"files_count": 6,
|
||||||
|
"total_addition": 447,
|
||||||
|
"total_deletion": 0,
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"sha": "xefenisnii",
|
||||||
|
"name": "文件.txt",
|
||||||
|
"old_name": "文件.txt",
|
||||||
|
"index": 6,
|
||||||
|
"addition": 2,
|
||||||
|
"deletion": 0,
|
||||||
|
"type": 1,
|
||||||
|
"isCreated": true,
|
||||||
|
"isDeleted": false,
|
||||||
|
"isBin": false,
|
||||||
|
"isLFSFile": false,
|
||||||
|
"isRenamed": false,
|
||||||
|
"isSubmodule": false,
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"fileName": "文件.txt",
|
||||||
|
"name": "",
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 0,
|
||||||
|
"type": 4,
|
||||||
|
"content": "@@ -0,0 +1,2 @@",
|
||||||
|
"sectionInfo": {
|
||||||
|
"path": null,
|
||||||
|
"lastLeftIdx": null,
|
||||||
|
"lastRightIdx": null,
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 0,
|
||||||
|
"leftHunkSize": null,
|
||||||
|
"rightHunkSize": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 1,
|
||||||
|
"type": 2,
|
||||||
|
"content": "+用例图一致性更新",
|
||||||
|
"sectionInfo": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 2,
|
||||||
|
"type": 2,
|
||||||
|
"content": "+工程文件直接上传会有文件缺失,现在压缩后上传",
|
||||||
|
"sectionInfo": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 获取pull request的commits列表
|
||||||
|
获取pull request的commits列表
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/jasder/jasder_test/pulls/1/commits.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/jasder/jasder_test/pulls/1/commits.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/pulls/:id/commits.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |用户登录名 |
|
||||||
|
|repo |是|string |project's identifier |
|
||||||
|
|id |是|int |pull request's id |
|
||||||
|
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|commits_count |int|commits总数量|
|
||||||
|
|commits |array||
|
||||||
|
|-- author |object|项目作者|
|
||||||
|
|---- login |string|用户login|
|
||||||
|
|---- name |string|用户姓名|
|
||||||
|
|---- image_url |string|用户头像|
|
||||||
|
|-- committer |object|commit提交用户|
|
||||||
|
|---- login |string|用户login|
|
||||||
|
|---- name |string|用户姓名|
|
||||||
|
|---- image_url |string|用户头像|
|
||||||
|
|-- timestamp |int|commit的unix时间戳|
|
||||||
|
|-- time_from_now|string|commit’s 提交时间距当前时间的时间值|
|
||||||
|
|-- message |string|commit说明信息|
|
||||||
|
|-- sha |string|commit’s sha值|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"commits_count": 1,
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"author": {
|
||||||
|
"id": 36480,
|
||||||
|
"login": "jasder",
|
||||||
|
"name": "段甲生",
|
||||||
|
"image_url": "avatars/User/b"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"id": 36480,
|
||||||
|
"login": "jasder",
|
||||||
|
"name": "段甲生",
|
||||||
|
"image_url": "avatars/User/b"
|
||||||
|
},
|
||||||
|
"timestamp": 1604382982,
|
||||||
|
"time_from_now": "3小时前",
|
||||||
|
"message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n",
|
||||||
|
"sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compare two commits
|
||||||
|
Compare two commits
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/Jason/test-txt/compare/master...develop
|
||||||
|
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/Jason/test-txt/compare/master...Jason/test-txt:develop
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/Jason/test-txt/compare/master...Jason/test-txt:develop')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/compare/{base}...{head}.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |用户登录名 |
|
||||||
|
|repo |是|string |project's identifier |
|
||||||
|
|base |是|string |pull request's id |
|
||||||
|
|head |是|string |pull request's id |
|
||||||
|
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|-|-|-|
|
||||||
|
|commits_count |int|commits总数量|
|
||||||
|
|commits |array||
|
||||||
|
|-- author |object|项目作者|
|
||||||
|
|---- login |string|用户login|
|
||||||
|
|---- name |string|用户姓名|
|
||||||
|
|---- image_url |string|用户头像|
|
||||||
|
|-- committer |object|commit提交用户|
|
||||||
|
|---- login |string|用户login|
|
||||||
|
|---- name |string|用户姓名|
|
||||||
|
|---- image_url |string|用户头像|
|
||||||
|
|-- timestamp |int|commit的unix时间戳|
|
||||||
|
|-- time_from_now|string|commit’s 提交时间距当前时间的时间值|
|
||||||
|
|-- message |string|commit说明信息|
|
||||||
|
|-- sha |string|commit’s sha值|
|
||||||
|
|diff |object||
|
||||||
|
|-- files_count |int|文件更改的总数量|
|
||||||
|
|-- total_addition |int|添加代码总行数|
|
||||||
|
|-- total_deletion |int|删除代码总行数|
|
||||||
|
|-- files |Array||
|
||||||
|
|-- sha |string|commit's sha |
|
||||||
|
|-- name |string|当前文件名|
|
||||||
|
|-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改|
|
||||||
|
|-- addition |int|文件添加的行数|
|
||||||
|
|-- deletion |int|文件删除的行数|
|
||||||
|
|-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容|
|
||||||
|
|-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否|
|
||||||
|
|-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否|
|
||||||
|
|-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否|
|
||||||
|
|-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否|
|
||||||
|
|-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否|
|
||||||
|
|-- sections |array||
|
||||||
|
|---- fileName |string|文件名称|
|
||||||
|
|---- lines |array||
|
||||||
|
|------ leftIdx |string|文件变动之前所在行数|
|
||||||
|
|------ rightIdx |string|文件更改后所在行数|
|
||||||
|
|------ type |string|文件变更类型,1: 内容未改动,2: 添加, 3: 删除, 4: diff统计信息|
|
||||||
|
|------ content |string|文件变更的内容|
|
||||||
|
|------ sectionInfo |object||
|
||||||
|
|-------- path |string|文件相对仓库的路径|
|
||||||
|
|-------- lastLeftIdx |int||
|
||||||
|
|-------- lastRightIdx |int||
|
||||||
|
|-------- leftHunkSize |int|文件变更之前的行数|
|
||||||
|
|-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)|
|
||||||
|
|-------- leftIdx |int|文件变更之前所在行数|
|
||||||
|
|-------- rightIdx |int|文件变更之后所在行数|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"commits_count": 1,
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"author": {
|
||||||
|
"id": 36480,
|
||||||
|
"login": "jasder",
|
||||||
|
"name": "段甲生",
|
||||||
|
"image_url": "avatars/User/b"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"id": 36480,
|
||||||
|
"login": "jasder",
|
||||||
|
"name": "段甲生",
|
||||||
|
"image_url": "avatars/User/b"
|
||||||
|
},
|
||||||
|
"timestamp": 1604382982,
|
||||||
|
"time_from_now": "4小时前",
|
||||||
|
"message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n",
|
||||||
|
"sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"diff": {
|
||||||
|
"files_count": 6,
|
||||||
|
"total_addition": 447,
|
||||||
|
"total_deletion": 0,
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"name": "build.go",
|
||||||
|
"old_name": "build.go",
|
||||||
|
"index": 1,
|
||||||
|
"addition": 33,
|
||||||
|
"deletion": 0,
|
||||||
|
"type": 1,
|
||||||
|
"isCreated": true,
|
||||||
|
"isDeleted": false,
|
||||||
|
"isBin": false,
|
||||||
|
"isLFSFile": false,
|
||||||
|
"isRenamed": false,
|
||||||
|
"isSubmodule": false,
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"fileName": "build.go",
|
||||||
|
"name": "",
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 0,
|
||||||
|
"type": 4,
|
||||||
|
"content": "@@ -0,0 +1,33 @@",
|
||||||
|
"sectionInfo": {
|
||||||
|
"path": "build.go",
|
||||||
|
"lastLeftIdx": 0,
|
||||||
|
"lastRightIdx": 0,
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 1,
|
||||||
|
"leftHunkSize": 0,
|
||||||
|
"rightHunkSize": 33
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"leftIdx": 0,
|
||||||
|
"rightIdx": 1,
|
||||||
|
"type": 2,
|
||||||
|
"content": "+// Copyright 2020 The Gitea Authors. All rights reserved.",
|
||||||
|
"sectionInfo": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## List pull requests
|
||||||
|
获取合并请求列表
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/Jasder/gitlink/pulls.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/pulls.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "响应成功",
|
||||||
|
"open_count": 4,
|
||||||
|
"close_count": 51,
|
||||||
|
"merged_issues_size": 123,
|
||||||
|
"search_count": 4,
|
||||||
|
"limit": null,
|
||||||
|
"user_admin_or_member": true,
|
||||||
|
"user_admin_or_developer": true,
|
||||||
|
"project_name": "Gitlink",
|
||||||
|
"project_author_name": "Gitlink",
|
||||||
|
"issues": [
|
||||||
|
{
|
||||||
|
"pull_request_id": 1189,
|
||||||
|
"pull_request_status": 0,
|
||||||
|
"pull_request_head": "develop",
|
||||||
|
"pull_request_base": "master",
|
||||||
|
"pull_request_staus": "open",
|
||||||
|
"is_original": false,
|
||||||
|
"fork_project_id": null,
|
||||||
|
"fork_project_identifier": null,
|
||||||
|
"fork_project_user": null,
|
||||||
|
"id": 51888,
|
||||||
|
"name": "FIx release v3.2.0",
|
||||||
|
"pr_time": "59分钟前",
|
||||||
|
"assign_user_name": "victor",
|
||||||
|
"assign_user_login": "moshenglv",
|
||||||
|
"author_name": "段甲生",
|
||||||
|
"author_login": "jasder",
|
||||||
|
"avatar_url": "images/avatars/User/36480?t=1615520120",
|
||||||
|
"priority": "正常",
|
||||||
|
"version": null,
|
||||||
|
"journals_count": 0,
|
||||||
|
"issue_tags": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
|
@ -274,6 +274,124 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json')
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 仓库标签列表
|
||||||
|
仓库标签列表
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/yystopf/csfjkkj/tags.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/yystopf/csfjkkj/tags.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/tags.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|page |否| 1 | integer | 页码 |
|
||||||
|
|limit |否| 20| integer | 每页个数 |
|
||||||
|
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|id |int |标签id |
|
||||||
|
|name |string|标签名称|
|
||||||
|
|zipball_url |string|标签zip包下载地址|
|
||||||
|
|tarball_url |string|标签tar包下载地址|
|
||||||
|
|tagger |object|打标签的人|
|
||||||
|
|time_ago |string|打标签的时间|
|
||||||
|
|created_at_unix|string|打标签的时间戳|
|
||||||
|
|message |string|标签信息|
|
||||||
|
|commit |object|标签最后一个commit|
|
||||||
|
|commit.sha |string|commit的id|
|
||||||
|
|commit.message |string|commit的提交信息|
|
||||||
|
|commit.time_ago|string|commit的提交时间|
|
||||||
|
|commit.created_at_unix|string|commit的提交时间戳|
|
||||||
|
|commit.committer|object|commit的提交者|
|
||||||
|
|commit.author|object|commit的作者|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "v2.0.0",
|
||||||
|
"id": "c7d0873ee41796d1a0e193063095ccf539a9bf31",
|
||||||
|
"zipball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v2.0.0.zip",
|
||||||
|
"tarball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v2.0.0.tar.gz",
|
||||||
|
"tagger": {
|
||||||
|
"id": 4,
|
||||||
|
"login": "testforge1",
|
||||||
|
"name": "testforge1",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
|
||||||
|
},
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"created_at_unix": 1632376903,
|
||||||
|
"message": "jdfkls",
|
||||||
|
"commit": {
|
||||||
|
"sha": "08fe383f1e5ebe2e2a384a8ea3ee890a758c7cd7",
|
||||||
|
"message": "add\n",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"created_at_unix": 1632376186,
|
||||||
|
"committer": {
|
||||||
|
"id": 4,
|
||||||
|
"login": "testforge1",
|
||||||
|
"name": "testforge1",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4,
|
||||||
|
"login": "testforge1",
|
||||||
|
"name": "testforge1",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "v1.0.0",
|
||||||
|
"id": "12168ad39c3ef201a445a2db181a3e43d50e40dd",
|
||||||
|
"zipball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v1.0.0.zip",
|
||||||
|
"tarball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v1.0.0.tar.gz",
|
||||||
|
"tagger": {
|
||||||
|
"id": null,
|
||||||
|
"login": "viletyy",
|
||||||
|
"name": "viletyy",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
|
||||||
|
},
|
||||||
|
"time_ago": "10天前",
|
||||||
|
"created_at_unix": 1631588042,
|
||||||
|
"message": "dfks",
|
||||||
|
"commit": {
|
||||||
|
"sha": "5291b5e45a377c1f7710cc6647259887ed7aaccf",
|
||||||
|
"message": "ADD file via upload\n",
|
||||||
|
"time_ago": "21天前",
|
||||||
|
"created_at_unix": 1630648417,
|
||||||
|
"committer": {
|
||||||
|
"id": null,
|
||||||
|
"login": "yystopf",
|
||||||
|
"name": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": null,
|
||||||
|
"login": "yystopf",
|
||||||
|
"name": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## 编辑仓库信息
|
## 编辑仓库信息
|
||||||
编辑仓库信息
|
编辑仓库信息
|
||||||
|
|
||||||
|
@ -867,3 +985,796 @@ await octokit.request('GET /api/jasder/jasder_test/sub_entries.json')
|
||||||
<aside class="success">
|
<aside class="success">
|
||||||
Success Data.
|
Success Data.
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
## 获取仓库README文件
|
||||||
|
获取仓库README文件
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
-d "ref=master" \
|
||||||
|
-d "filepath=lib" \
|
||||||
|
http://localhost:3000/api/yystopf/csfjkkj/readme.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/yystopf/csfjkkj/readme.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/readme.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|ref |否| | string |分支名称、tag名称或是提交记录id,默认为默认分支 |
|
||||||
|
|filepath |否| | string |子目录名称,默认为空 |
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type |string|文件类型, file:文件,dir:文件目录
|
||||||
|
|encoding |string |编码 |
|
||||||
|
|size |int|文件夹或文件大小 单位B
|
||||||
|
|name |string|文件夹或文件名称|
|
||||||
|
|path |string|文件夹或文件相对路径|
|
||||||
|
|content |string|文件内容
|
||||||
|
|sha |string|文件commitid
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"encoding": "base64",
|
||||||
|
"size": 24,
|
||||||
|
"name": "README.md",
|
||||||
|
"path": "lib/README.md",
|
||||||
|
"content": "ZGZhc2RhZGpmIGRrZnNsCgpzZGZkZnMK",
|
||||||
|
"sha": "860962cd21c60b1a9e07d723080c87c32c18d44a"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 获取仓库贡献者
|
||||||
|
获取仓库贡献者
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
-d "ref=master" \
|
||||||
|
-d "filepath=lib" \
|
||||||
|
http://localhost:3000/api/yystopf/csfjkkj/contributors.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/contributors.json`
|
||||||
|
|
||||||
|
### 请求参数:
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|ref |否| | string |分支名称、tag名称或是提交记录id,默认为整个仓库 |
|
||||||
|
|filepath |否| | string |子目录名称,默认为空 |
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|total_count |integer|贡献者数量|
|
||||||
|
|contributions |integer|贡献数量|
|
||||||
|
|login |string |用户登录名 |
|
||||||
|
|type |string|用户类型 |
|
||||||
|
|name |string|用户昵称|
|
||||||
|
|image_url |string|用户头像|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"contributions": 5,
|
||||||
|
"login": "testforge2",
|
||||||
|
"type": "User",
|
||||||
|
"name": "testforge2",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contributions": 79,
|
||||||
|
"login": "yystopf",
|
||||||
|
"type": "User",
|
||||||
|
"name": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_count": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<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>
|
|
@ -1,7 +1,7 @@
|
||||||
<!--
|
<!--
|
||||||
* @Date: 2021-03-01 10:35:21
|
* @Date: 2021-03-01 10:35:21
|
||||||
* @LastEditors: viletyy
|
* @LastEditors: viletyy
|
||||||
* @LastEditTime: 2021-06-11 16:28:51
|
* @LastEditTime: 2021-09-15 18:00:10
|
||||||
* @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md
|
* @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md
|
||||||
-->
|
-->
|
||||||
# Users
|
# Users
|
||||||
|
@ -47,6 +47,305 @@ await octokit.request('GET /api/users/me.json')
|
||||||
Success Data.
|
Success Data.
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
## 用户消息列表
|
||||||
|
获取用户消息列表
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/users/:login/messages.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/users/:login/messages.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET api/users/yystopf/messages.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息|
|
||||||
|
|status | integer | 是否已读,不传为所有消息,1为未读,2为已读 |
|
||||||
|
|limit | integer | 每页个数 |
|
||||||
|
|page | integer | 页码 |
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|total_count | integer | 消息总数 |
|
||||||
|
|type | string | 消息类型 |
|
||||||
|
|unread_notification | integer | 未读系统通知数量 |
|
||||||
|
|unread_atme | integer | 未读@我数量 |
|
||||||
|
|messages.id | integer | 消息id |
|
||||||
|
|messages.status | integer | 消息是否已读,1为未读,2为已读 |
|
||||||
|
|messages.content | string | 消息内容 |
|
||||||
|
|messages.notification_url | string | 消息跳转地址 |
|
||||||
|
|messages.source | string | 消息来源 |
|
||||||
|
|messages.timeago | string | 消息时间 |
|
||||||
|
|messages.type | string | 消息类型,notification为系统消息,atme为@我消息|
|
||||||
|
|sender | object | 消息发送者 |
|
||||||
|
|
||||||
|
#### 消息来源source字段说明
|
||||||
|
类型|说明
|
||||||
|
--------- | -----------
|
||||||
|
|IssueAssigned | 有新指派给我的易修 |
|
||||||
|
|IssueAssignerExpire | 我负责的易修截止日期到达最后一天 |
|
||||||
|
|IssueAtme | 在易修中@我 |
|
||||||
|
|IssueChanged | 我创建或负责的易修状态变更 |
|
||||||
|
|IssueCreatorExpire | 我创建的易修截止日期到达最后一天 |
|
||||||
|
|IssueDeleted | 我创建或负责的易修删除 |
|
||||||
|
|IssueJournal | 我创建或负责的易修有新的评论 |
|
||||||
|
|LoginIpTip | 登录异常提示 |
|
||||||
|
|OrganizationJoined | 账号被拉入组织 |
|
||||||
|
|OrganizationLeft | 账号被移出组织 |
|
||||||
|
|OrganizationRole | 账号组织权限变更 |
|
||||||
|
|ProjectDeleted | 我关注的仓库被删除 |
|
||||||
|
|ProjectFollowed | 我管理的仓库被关注 |
|
||||||
|
|ProjectForked | 我管理的仓库被复刻 |
|
||||||
|
|ProjectIssue | 我管理/关注的仓库有新的易修 |
|
||||||
|
|ProjectJoined | 账号被拉入项目 |
|
||||||
|
|ProjectLeft | 账号被移出项目 |
|
||||||
|
|ProjectMemberJoined | 我管理的仓库有成员加入 |
|
||||||
|
|ProjectMemberLeft | 我管理的仓库有成员移出 |
|
||||||
|
|ProjectMilestone | 我管理的仓库有新的里程碑 |
|
||||||
|
|ProjectPraised | 我管理的仓库被点赞 |
|
||||||
|
|ProjectPullRequest | 我管理/关注的仓库有新的合并请求 |
|
||||||
|
|ProjectRole | 账号仓库权限变更 |
|
||||||
|
|ProjectSettingChanged | 我管理的仓库项目设置被更改 |
|
||||||
|
|ProjectTransfer | 我关注的仓库被转移 |
|
||||||
|
|ProjectVersion | 我关注的仓库有新的发行版 |
|
||||||
|
|PullRequestAssigned | 有新指派给我的合并请求 |
|
||||||
|
|PullReuqestAtme | 在合并请求中@我 |
|
||||||
|
|PullRequestChanged | 我创建或负责的合并请求状态变更 |
|
||||||
|
|PullRequestClosed | 我创建或负责的合并请求被关闭 |
|
||||||
|
|PullRequestJournal | 我创建或负责的合并请求有新的评论 |
|
||||||
|
|PullRequestMerged | 我创建或负责的合并请求被合并 |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total_count": 5,
|
||||||
|
"type": "",
|
||||||
|
"unread_notification": 3,
|
||||||
|
"unread_atme": 2,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"status": 1,
|
||||||
|
"content": "Atme Message Content 1",
|
||||||
|
"notification_url": "http://www.baidu.com",
|
||||||
|
"source": "PullRequestAtme",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"type": "atme",
|
||||||
|
"sender": {
|
||||||
|
"id": 5,
|
||||||
|
"type": "User",
|
||||||
|
"name": "testforge2",
|
||||||
|
"login": "testforge2",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"status": 0,
|
||||||
|
"content": "Atme Message Content 2",
|
||||||
|
"notification_url": "http://www.baidu.com",
|
||||||
|
"source": "IssueAtme",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"type": "atme",
|
||||||
|
"sender": {
|
||||||
|
"id": 4,
|
||||||
|
"type": "User",
|
||||||
|
"name": "testforge1",
|
||||||
|
"login": "testforge1",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"status": 1,
|
||||||
|
"content": "Notification Message Content 1",
|
||||||
|
"notification_url": "http://www.baidu.com",
|
||||||
|
"source": "IssueDelete",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"type": "notification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"status": 0,
|
||||||
|
"content": "Notification Message Content 2",
|
||||||
|
"notification_url": "http://www.baidu.com",
|
||||||
|
"source": "IssueChanged",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"type": "notification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"status": 0,
|
||||||
|
"content": "Notification Message Content 3",
|
||||||
|
"notification_url": "http://www.baidu.com",
|
||||||
|
"source": "ProjectJoined",
|
||||||
|
"time_ago": "1天前",
|
||||||
|
"type": "notification"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 用户阅读系统通知
|
||||||
|
用户阅读系统通知
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/users/yystopf/system_notification_histories.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/users/:login/system_notification_histories.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/users/:login/system_notification_histories.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|system_notification_id |integer |阅读的系统通知id |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 发送消息
|
||||||
|
发送消息, 目前只支持atme
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/users/:login/messages.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/users/:login/messages.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST api/users/yystopf/messages.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type | string | 消息类型 |
|
||||||
|
|receivers_login | array | 需要发送消息的用户名数组|
|
||||||
|
|atmeable_type | string | atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest |
|
||||||
|
|atmeable_id | integer | atme消息对象id |
|
||||||
|
|
||||||
|
> 请求的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "atme",
|
||||||
|
"receivers_login": ["yystopf", "testforge1"],
|
||||||
|
"atmeable_type": "Journal",
|
||||||
|
"atmeable_id": 67
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 阅读消息
|
||||||
|
阅读消息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/users/:login/messages/read.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/users/:login/messages/read.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST api/users/yystopf/messages/read.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息|
|
||||||
|
|ids | array | 消息id数组,包含-1则把所有未读消息标记为已读|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 删除消息
|
||||||
|
删除消息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X DELETE http://localhost:3000/api/users/:login/messages.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('DELETE /api/users/:login/messages.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`DELETE api/users/yystopf/messages.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type | string | 消息类型,atme为@我消息|
|
||||||
|
|ids | array | 消息id数组,包含-1则把所有消息删除|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
|
||||||
## 更改用户信息
|
## 更改用户信息
|
||||||
更改用户信息
|
更改用户信息
|
||||||
|
|
||||||
|
@ -103,6 +402,290 @@ await octokit.request('PATCH/PUT /api/users/:login.json')
|
||||||
"message": "success"
|
"message": "success"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 获取平台消息设置配置信息
|
||||||
|
获取平台消息设置配置信息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/template_message_settings.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/template_message_settings.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/template_message_settings.json`
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|type |string |消息配置类型 |
|
||||||
|
|type_name |string |消息配置类型含义|
|
||||||
|
|total_settings_count |int |配置条数|
|
||||||
|
|settings.name |string |配置名称|
|
||||||
|
|settings.key |string |配置标识|
|
||||||
|
|settings.notification_disabled |boolean |站内信设置是否禁用|
|
||||||
|
|settings.email_disabled |boolean |邮件设置是否禁用|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "响应成功",
|
||||||
|
"setting_types": [
|
||||||
|
{
|
||||||
|
"type": "TemplateMessageSetting::Normal",
|
||||||
|
"type_name": "",
|
||||||
|
"total_settings_count": 3,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "被拉入或移出组织",
|
||||||
|
"key": "Organization",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "被拉入或移出项目",
|
||||||
|
"key": "Project",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "有权限变更",
|
||||||
|
"key": "Permission",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TemplateMessageSetting::CreateOrAssign",
|
||||||
|
"type_name": "我创建的或负责的",
|
||||||
|
"total_settings_count": 4,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "易修被指派",
|
||||||
|
"key": "IssueAssigned",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "合并请求被指派",
|
||||||
|
"key": "PullRequestAssigned",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TemplateMessageSetting::ManageProject",
|
||||||
|
"type_name": "我管理的仓库",
|
||||||
|
"total_settings_count": 4,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "有新的易修",
|
||||||
|
"key": "Issue",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "有新的合并请求",
|
||||||
|
"key": "PullRequest",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "有成员变动",
|
||||||
|
"key": "Member",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "设置更改",
|
||||||
|
"key": "SettingChanged",
|
||||||
|
"notification_disabled": true,
|
||||||
|
"email_disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 获取用户消息设置配置信息
|
||||||
|
获取用户消息设置配置信息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/users/yystopf/template_message_settings.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/uses/yystopf/template_message_settings.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/users/:user_id/template_message_settings.json`
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|notification_body |string |站内信配置 |
|
||||||
|
|email_body |string |邮件配置|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "响应成功",
|
||||||
|
"user": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
},
|
||||||
|
"notification_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": true,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": true,
|
||||||
|
"ManageProject::Issue": true,
|
||||||
|
"ManageProject::PullRequest": true,
|
||||||
|
"ManageProject::Member": true,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": true,
|
||||||
|
"Normal::Project": true,
|
||||||
|
"Normal::Permission": true
|
||||||
|
},
|
||||||
|
"email_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": false,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": false,
|
||||||
|
"ManageProject::Issue": false,
|
||||||
|
"ManageProject::PullRequest": false,
|
||||||
|
"ManageProject::Member": false,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": false,
|
||||||
|
"Normal::Project": true,
|
||||||
|
"Normal::Permission": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 重新设置用户消息设置配置信息
|
||||||
|
重新设置用户消息设置配置信息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/users/yystopf/template_message_settings/update_setting.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/uses/yystopf/template_message_settings/update_setting.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/users/:user_id/template_message_settings/update_setting.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|notification_body |string |站内信配置 |
|
||||||
|
|email_body |string |邮件配置|
|
||||||
|
|
||||||
|
|
||||||
|
> 请求的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"setting": {
|
||||||
|
"notification_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": true,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": true,
|
||||||
|
"ManageProject::Issue": true,
|
||||||
|
"ManageProject::PullRequest": true,
|
||||||
|
"ManageProject::Member": true,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": true,
|
||||||
|
"Normal::Project": true,
|
||||||
|
"Normal::Permission": true
|
||||||
|
},
|
||||||
|
"email_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": false,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": false,
|
||||||
|
"ManageProject::Issue": false,
|
||||||
|
"ManageProject::PullRequest": false,
|
||||||
|
"ManageProject::Member": false,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": false,
|
||||||
|
"Normal::Project": "t",
|
||||||
|
"Normal::Permission": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|notification_body |string |站内信配置 |
|
||||||
|
|email_body |string |邮件配置|
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "响应成功",
|
||||||
|
"user": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
},
|
||||||
|
"notification_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": true,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": true,
|
||||||
|
"ManageProject::Issue": true,
|
||||||
|
"ManageProject::PullRequest": true,
|
||||||
|
"ManageProject::Member": true,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": true,
|
||||||
|
"Normal::Project": true,
|
||||||
|
"Normal::Permission": true
|
||||||
|
},
|
||||||
|
"email_body": {
|
||||||
|
"CreateOrAssign::IssueAssigned": false,
|
||||||
|
"CreateOrAssign::PullRequestAssigned": false,
|
||||||
|
"ManageProject::Issue": false,
|
||||||
|
"ManageProject::PullRequest": false,
|
||||||
|
"ManageProject::Member": false,
|
||||||
|
"ManageProject::SettingChanged": true,
|
||||||
|
"Normal::Organization": false,
|
||||||
|
"Normal::Project": true,
|
||||||
|
"Normal::Permission": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success Data.
|
||||||
|
</aside>
|
||||||
|
|
||||||
## 获取用户星标项目
|
## 获取用户星标项目
|
||||||
获取用户星标项目
|
获取用户星标项目
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
class AddSchoolApplyForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :name, :province, :city, :address, :remarks
|
|
||||||
|
|
||||||
validates :name, presence: true
|
|
||||||
# validates :province, presence: true
|
|
||||||
# validates :city, presence: true
|
|
||||||
# validates :address, presence: true
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
class ApplyShixunMirrorForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :language, :runtime, :run_method, :attachment_id
|
|
||||||
|
|
||||||
validates :language, presence: true
|
|
||||||
validates :runtime, presence: true
|
|
||||||
validates :run_method, presence: true
|
|
||||||
validates :attachment_id, presence: true, numericality: { only_integer: true }
|
|
||||||
|
|
||||||
validate :ensure_attachment_presence
|
|
||||||
def ensure_attachment_presence
|
|
||||||
return unless attachment_id
|
|
||||||
|
|
||||||
if attachment.blank?
|
|
||||||
errors.add(:attachment_id, :attachment_not_exist)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def attachment
|
|
||||||
@attachment ||= Attachment.find_by_id(attachment_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json
|
|
||||||
{ language: language, runtime: runtime, run_method: run_method, attachment_id: attachment_id }.to_json
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,18 +2,32 @@ class BaseForm
|
||||||
include ActiveModel::Model
|
include ActiveModel::Model
|
||||||
|
|
||||||
def check_project_category(project_category_id)
|
def check_project_category(project_category_id)
|
||||||
raise "project_category_id参数值无效." if (ProjectCategory.find_by_id project_category_id).blank?
|
unless project_category_id == ''
|
||||||
|
raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_project_language(project_language_id)
|
def check_project_language(project_language_id)
|
||||||
raise "project_language_id参数值无效." if (ProjectLanguage.find_by_id project_language_id).blank?
|
unless project_language_id == ''
|
||||||
|
raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_repository_name(user_id, repository_name)
|
def check_repository_name(user_id, repository_name)
|
||||||
raise "仓库名称已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists?
|
check_reversed_keyword(repository_name)
|
||||||
|
raise "项目标识已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_project_name(user_id, project_name)
|
def check_project_name(user_id, project_name)
|
||||||
raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists?
|
raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_reversed_keyword(repository_name)
|
||||||
|
raise "项目标识已被占用." if ReversedKeyword.check_exists?(repository_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def strip(str)
|
||||||
|
str.to_s.strip.presence
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
class ExaminationBanks::SaveExamForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :discipline_id, :sub_discipline_id, :difficulty, :name, :duration, :tag_discipline_id
|
|
||||||
|
|
||||||
validates :discipline_id, presence: true
|
|
||||||
validates :sub_discipline_id, presence: true
|
|
||||||
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
|
|
||||||
validates :name, presence: true, length: { maximum: 60, too_long: "不能超过60个字符" }
|
|
||||||
validate :validate_duration
|
|
||||||
|
|
||||||
def validate_duration
|
|
||||||
raise '时长应为大于0的整数' if duration.present? && duration.to_i < 1
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
class ExaminationIntelligentSettings::SaveExamForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :name, :duration
|
|
||||||
|
|
||||||
validates :name, presence: true, length: { maximum: 60 }
|
|
||||||
validate :validate_duration
|
|
||||||
|
|
||||||
def validate_duration
|
|
||||||
raise '时长应为大于0的整数' if duration.present? && duration.to_i < 1
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,11 +0,0 @@
|
||||||
class ExaminationIntelligentSettings::SaveExamSettingForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :discipline_id, :sub_discipline_id, :source, :difficulty, :tag_discipline_id, :question_settings
|
|
||||||
|
|
||||||
validates :discipline_id, presence: true
|
|
||||||
validates :sub_discipline_id, presence: true
|
|
||||||
validates :source, presence: true
|
|
||||||
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
|
|
||||||
validates :question_settings, presence: true
|
|
||||||
end
|
|
|
@ -5,7 +5,7 @@ class Issues::CreateForm
|
||||||
|
|
||||||
validates :subject, presence: { message: "不能为空" }
|
validates :subject, presence: { message: "不能为空" }
|
||||||
|
|
||||||
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
|
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,6 @@ class Issues::UpdateForm
|
||||||
|
|
||||||
validates :subject, presence: { message: "不能为空" }
|
validates :subject, presence: { message: "不能为空" }
|
||||||
|
|
||||||
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
|
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||||
|
|
||||||
end
|
end
|
|
@ -0,0 +1,23 @@
|
||||||
|
class Notice::Write::CreateAtmeForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :receivers_login, :atmeable_type, :atmeable_id
|
||||||
|
|
||||||
|
validate :check_receivers
|
||||||
|
|
||||||
|
def check_receivers
|
||||||
|
receivers_login.each do |login|
|
||||||
|
receiver = User.find_by(login: login) || User.find_by_id(login)
|
||||||
|
raise 'receivers_login值无效.' unless receiver.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_atmeable
|
||||||
|
begin
|
||||||
|
raise 'atmeable对象无效.' unless atmeable_type.constantize.find_by_id(atmeable_id).present?
|
||||||
|
rescue => exception
|
||||||
|
raise 'atmeable对象无效.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,11 +1,9 @@
|
||||||
class Projects::CreateForm < BaseForm
|
class Projects::CreateForm < BaseForm
|
||||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
|
||||||
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
||||||
:project_language_id, :ignore_id, :license_id, :private, :owner
|
:project_language_id, :ignore_id, :license_id, :private, :owner
|
||||||
|
|
||||||
validates :user_id, :name, :description,:repository_name,
|
validates :user_id, :name, :repository_name, presence: true
|
||||||
:project_category_id, :project_language_id, presence: true
|
validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||||
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
|
||||||
|
|
||||||
validates :name, length: { maximum: 50 }
|
validates :name, length: { maximum: 50 }
|
||||||
validates :repository_name, length: { maximum: 100 }
|
validates :repository_name, length: { maximum: 100 }
|
||||||
|
@ -15,6 +13,8 @@ class Projects::CreateForm < BaseForm
|
||||||
validate do
|
validate do
|
||||||
check_project_category(project_category_id)
|
check_project_category(project_category_id)
|
||||||
check_project_language(project_language_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
|
end
|
||||||
|
|
||||||
def check_license
|
def check_license
|
||||||
|
@ -26,13 +26,14 @@ class Projects::CreateForm < BaseForm
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_owner
|
def check_owner
|
||||||
@owner = Owner.find_by(id: user_id)
|
@project_owner = Owner.find_by(id: user_id)
|
||||||
raise "user_id值无效." if user_id && owner.blank?
|
raise "user_id值无效." if user_id && @project_owner.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_max_repo_creation
|
def check_max_repo_creation
|
||||||
return unless owner.is_a?(Organization)
|
return unless @project_owner.is_a?(Organization)
|
||||||
return if owner.max_repo_creation <= -1
|
return if @project_owner.max_repo_creation <= -1
|
||||||
raise "已超过组织设置最大仓库数" if owner.max_repo_creation == owner.num_projects
|
|
||||||
|
raise "已超过组织设置最大仓库数" if @project_owner.max_repo_creation == @project_owner.num_projects
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
class Projects::MigrateForm < BaseForm
|
class Projects::MigrateForm < BaseForm
|
||||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
attr_accessor :user_id, :name, :repository_name, :project_category_id, :description,
|
||||||
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
|
:project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner
|
||||||
|
|
||||||
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, :repository_name, :clone_addr, 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 :clone_addr, format: { with: CustomRegexp::URL_REGEX, multiline: true, message: "地址格式不正确" }
|
||||||
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
validates :name, length: { maximum: 50 }
|
||||||
validates :clone_addr, format: { with: URL_REGEX, multiline: true, message: "地址格式不正确" }
|
validates :repository_name, length: { maximum: 100 }
|
||||||
|
validates :description, length: { maximum: 200 }
|
||||||
validate do
|
validate do
|
||||||
check_project_name(user_id, name) unless name.blank?
|
check_project_name(user_id, name) unless name.blank?
|
||||||
check_repository_name(user_id, repository_name) unless repository_name.blank?
|
check_repository_name(user_id, repository_name) unless repository_name.blank?
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
class Projects::UpdateForm < BaseForm
|
class Projects::UpdateForm < BaseForm
|
||||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private
|
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier
|
||||||
validates :name, :description, :project_category_id, :project_language_id, presence: true
|
validates :name, presence: true
|
||||||
validates :name, length: { maximum: 50 }
|
validates :name, length: { maximum: 50 }
|
||||||
validates :description, length: { maximum: 200 }
|
validates :description, length: { maximum: 200 }
|
||||||
|
validates :identifier, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||||
|
|
||||||
validate do
|
validate do
|
||||||
check_project_category(project_category_id)
|
check_project_category(project_category_id)
|
||||||
check_project_language(project_language_id)
|
check_project_language(project_language_id)
|
||||||
|
|
||||||
|
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
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
|
|
@ -0,0 +1,51 @@
|
||||||
|
module Register
|
||||||
|
class BaseForm < ::BaseForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
EmailError = Class.new(Error)
|
||||||
|
LoginError = Class.new(Error)
|
||||||
|
PhoneError = Class.new(Error)
|
||||||
|
PasswordFormatError = Class.new(Error)
|
||||||
|
VerifiCodeError = Class.new(Error)
|
||||||
|
|
||||||
|
private
|
||||||
|
def check_login(login)
|
||||||
|
login = strip(login)
|
||||||
|
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
||||||
|
|
||||||
|
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
||||||
|
raise LoginError, '登录名已被使用' if login_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_mail(mail)
|
||||||
|
mail = strip(mail)
|
||||||
|
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
||||||
|
|
||||||
|
mail_exist = Owner.exists?(mail: mail)
|
||||||
|
raise EmailError, '邮箱已被使用' if mail_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_phone(phone)
|
||||||
|
phone = strip(phone)
|
||||||
|
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
||||||
|
|
||||||
|
phone_exist = Owner.exists?(phone: phone)
|
||||||
|
raise PhoneError, '手机号已被使用' if phone_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_password(password)
|
||||||
|
password = strip(password)
|
||||||
|
raise PasswordFormatError, "8~16位密码,支持字母数字和符号" unless password =~ CustomRegexp::PASSWORD
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_verifi_code(verifi_code, code)
|
||||||
|
code = strip(code)
|
||||||
|
# return if code == "123123" # TODO 万能验证码,用于测试
|
||||||
|
|
||||||
|
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
||||||
|
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Register
|
||||||
|
class CheckColumnsForm < Register::BaseForm
|
||||||
|
attr_accessor :type, :value
|
||||||
|
|
||||||
|
validates :type, presence: true, numericality: true
|
||||||
|
validates :value, presence: true
|
||||||
|
validate :check!
|
||||||
|
|
||||||
|
def check!
|
||||||
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
|
case strip(type).to_i
|
||||||
|
when 1 then check_login(strip(value))
|
||||||
|
when 2 then check_mail(strip(value))
|
||||||
|
when 3 then check_phone(strip(value))
|
||||||
|
else raise("type值无效")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,27 @@
|
||||||
|
module Register
|
||||||
|
class Form < Register::BaseForm
|
||||||
|
# login 登陆方式,支持邮箱、登陆、手机号等
|
||||||
|
# namespace 用户空间地址
|
||||||
|
# type: 1:手机号注册;2:邮箱注册
|
||||||
|
attr_accessor :login, :namespace, :password, :code, :type
|
||||||
|
|
||||||
|
validates :login, :code, :password, :namespace, presence: true
|
||||||
|
validate :check!
|
||||||
|
|
||||||
|
def check!
|
||||||
|
Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}"
|
||||||
|
db_verifi_code =
|
||||||
|
if type == 1
|
||||||
|
check_phone(login)
|
||||||
|
VerificationCode.where(phone: login, code: code, code_type: 1).last
|
||||||
|
elsif type == 0
|
||||||
|
check_mail(login)
|
||||||
|
VerificationCode.where(email: login, code: code, code_type: 8).last
|
||||||
|
end
|
||||||
|
|
||||||
|
check_login(namespace)
|
||||||
|
check_verifi_code(db_verifi_code, code)
|
||||||
|
check_password(password)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,20 +0,0 @@
|
||||||
class Weapps::CreateCourseForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :course
|
|
||||||
attr_accessor :name, :course_list_name, :credit, :course_module_types, :end_date
|
|
||||||
|
|
||||||
validates :name, presence: true
|
|
||||||
validates :course_list_name, presence: true
|
|
||||||
|
|
||||||
validate :course_name_prefix
|
|
||||||
validate :check_course_modules
|
|
||||||
|
|
||||||
def course_name_prefix
|
|
||||||
raise '课堂名称应以课程名称开头' unless name.index(course_list_name) && name.index(course_list_name) == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_course_modules
|
|
||||||
raise '请至少添加一个课堂模块' if course_module_types.blank?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,15 +0,0 @@
|
||||||
class Weapps::UpdateCourseForm
|
|
||||||
include ActiveModel::Model
|
|
||||||
|
|
||||||
attr_accessor :course
|
|
||||||
attr_accessor :name, :course_list_name, :credit, :end_date
|
|
||||||
|
|
||||||
validates :name, presence: true
|
|
||||||
validates :course_list_name, presence: true
|
|
||||||
|
|
||||||
validate :course_name_prefix
|
|
||||||
|
|
||||||
def course_name_prefix
|
|
||||||
raise '课堂名称应以课程名称开头' unless name.index(course_list_name) && name.index(course_list_name) == 0
|
|
||||||
end
|
|
||||||
end
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue