FIX 合并主干分支代码以及解决代码冲突

This commit is contained in:
jasder 2021-10-23 16:06:49 +08:00
commit 6220d851ae
247 changed files with 10108 additions and 1272 deletions

View File

@ -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);

View File

@ -1,4 +1,35 @@
# 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
* ENHANCEMENTS

View File

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

View File

@ -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("√")
}
});
}
})
});
})

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

@ -247,11 +247,11 @@ class ApplicationController < ActionController::Base
end
def require_profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
end
def require_user_profile_completed(user)
tip_exception(412, "请用户完善资料后再操作") unless user.profile_completed
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
end
# 异常提醒
@ -280,7 +280,7 @@ class ApplicationController < ActionController::Base
# 资料是否完善
def check_account
if !current_user.profile_completed?
if !current_user. profile_is_completed?
#info_url = '/account/profile'
tip_exception(402, nil)
end
@ -762,10 +762,10 @@ class ApplicationController < ActionController::Base
if @project and current_user.can_read_project?(@project)
logger.info "########### has project and can read project"
@project
elsif @project && current_user.is_a?(AnonymousUser)
logger.info "###########This is AnonymousUser"
@project = nil if !@project.is_public?
render_forbidden and return
# elsif @project && current_user.is_a?(AnonymousUser)
# logger.info "###########This is AnonymousUser"
# @project = nil if !@project.is_public?
# render_forbidden and return
else
logger.info "###########project not found"
@project = nil

View File

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

View File

@ -24,7 +24,7 @@ class CompareController < ApplicationController
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
end
if @exist_pullrequest.present?
return -2, "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}/Messagecount'>#{@exist_pullrequest.try(:title)}</a>"
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, "分支内容相同,无需创建合并请求"

View File

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

View File

@ -15,7 +15,7 @@ class IssuesController < ApplicationController
include TagChosenHelper
def index
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member
@ -111,6 +111,8 @@ class IssuesController < ApplicationController
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
@issue = Issue.new(issue_params)
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?
params[:attachment_ids].each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
@ -158,6 +160,7 @@ class IssuesController < ApplicationController
def update
last_token = @issue.token
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?
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
@ -202,6 +205,26 @@ class IssuesController < ApplicationController
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
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 #任务由非关闭状态到关闭状态时
@issue.issue_times.update_all(end_time: Time.now)
@issue.update_closed_issues_count_in_project!
@ -253,6 +276,7 @@ class IssuesController < ApplicationController
status_id = @issue.status_id
token = @issue.token
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_type == "2" && status_id != 5
post_to_chain("add", token, login)
@ -272,8 +296,12 @@ class IssuesController < ApplicationController
def clean
#批量删除,暂时只能删除未悬赏的
issue_ids = params[:ids]
if issue_ids.present?
if Issue.where(id: issue_ids, issue_type: "1").destroy_all
issues = Issue.where(id: issue_ids, issue_type: "1")
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, "删除成功")
else
normal_status(-1, "删除失败")
@ -307,7 +335,24 @@ class IssuesController < ApplicationController
if update_hash.blank?
normal_status(-1, "请选择批量更新内容")
elsif issues&.update(update_hash)
issues.map{|i| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?}
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, "批量更新成功")
else
normal_status(-1, "批量更新失败")
@ -321,6 +366,8 @@ class IssuesController < ApplicationController
@new_issue = @issue.dup
@new_issue.author_id = current_user.id
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)
if issue_tags.present?
issue_tags.each do |tag|
@ -398,27 +445,27 @@ class IssuesController < ApplicationController
def check_project_public
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
def set_issue
@issue = Issue.find_by_id(params[:id])
if @issue.blank?
normal_status(-1, "标签不存在")
elsif @issue.is_lock &&!(@project.member?(current_user) || current_user.admin?)
normal_status(-1, "您没有权限")
return render_not_found
elsif !(@project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))))
return render_forbidden
end
end
def check_issue_permission
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
def operate_issue_permission
return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.member?(current_user)
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)

View File

@ -31,9 +31,9 @@ class MainController < ApplicationController
# TODO: 这块之后需要整合者架构重新变化统一跳转到index后再路由分发
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
render file: 'public/react/build/index.html', :layout => false
render file: 'public/react/build/index.html', :layout => false, :content_type=> 'text/html'
end
end

View File

@ -17,7 +17,8 @@ class MembersController < ApplicationController
end
end
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)
rescue Exception => e
uid_logger_error(e.message)
@ -37,6 +38,8 @@ class MembersController < ApplicationController
def remove
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)
rescue Exception => e
uid_logger_error(e.message)
@ -45,6 +48,7 @@ class MembersController < ApplicationController
def change_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)
rescue Exception => e
uid_logger_error(e.message)
@ -75,4 +79,14 @@ class MembersController < ApplicationController
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

View File

@ -43,7 +43,8 @@ class Organizations::OrganizationsController < Organizations::BaseController
@organization.login = organization_params[:name] if organization_params[:name].present?
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
@organization.save!
@organization.organization_extension.update_attributes!(organization_params.except(:name, :nickname))
sync_organization_extension!
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
end
@ -97,4 +98,18 @@ class Organizations::OrganizationsController < Organizations::BaseController
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
end
def set_max_repo_creation
organization_params[:max_repo_creation].blank? ? -1 : organization_params[:max_repo_creation]
end
def organization_extension_params
organization_params
.except(:name, :nickname)
.merge(max_repo_creation: set_max_repo_creation)
end
def sync_organization_extension!
@organization.organization_extension.update_attributes!(organization_extension_params)
end
end

View File

@ -18,6 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.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)
end
rescue Exception => e

View File

@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
before_action :check_project_public
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_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)
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_issues_count = @project_open_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_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", "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?
project_trends = project_trends.where(trend_type: check_type.to_s.strip)
end
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
project_trends = project_trends.order("created_at desc")

View File

@ -6,7 +6,8 @@ class Projects::ProjectUnitsController < Projects::BaseController
def create
if current_user.admin? || @project.manager?(current_user)
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
end
else

View File

@ -4,7 +4,7 @@ class ProjectsController < ApplicationController
include ProjectsHelper
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 about menu_list]
before_action :require_profile_completed, only: [:create, :migrate]
before_action :load_repository, except: %i[index group_type_list migrate create recommend]
before_action :authorizate_user_can_edit_project!, only: %i[update]
@ -28,7 +28,7 @@ class ProjectsController < ApplicationController
end
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 = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
@ -46,7 +46,6 @@ class ProjectsController < ApplicationController
def create
ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{project_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(project_params[:repository_name]).present?
Projects::CreateForm.new(project_params).validate!
@project = Projects::CreateService.new(current_user, project_params).call
@ -64,7 +63,6 @@ class ProjectsController < ApplicationController
end
def migrate
tip_exception("无法使用以下关键词:#{mirror_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(mirror_params[:repository_name]).present?
Projects::MigrateForm.new(mirror_params).validate!
@project =
@ -95,6 +93,13 @@ class ProjectsController < ApplicationController
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
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
project_statics = ProjectStatistic.first
@ -129,9 +134,9 @@ class ProjectsController < ApplicationController
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
else
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 = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
@ -141,13 +146,13 @@ class ProjectsController < ApplicationController
gitea_params = {
private: private,
default_branch: @project.default_branch,
website: @project.website
website: @project.website,
name: @project.identifier
}
if [true, false].include? private
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
@project.repository.update_column(:hidden, private)
end
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
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
rescue Exception => e
uid_logger_error(e.message)
@ -230,7 +235,7 @@ class ProjectsController < ApplicationController
private
def project_params
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch,
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
end

View File

@ -59,7 +59,8 @@ class PullRequestsController < ApplicationController
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
if @gitea_pull_request[:status] == :success
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
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?
else
render_error("create pull request error: #{@gitea_pull_request[:status]}")
raise ActiveRecord::Rollback
@ -68,21 +69,22 @@ class PullRequestsController < ApplicationController
end
def edit
@fork_project_user_name = @project&.fork_project&.owner.try(:show_real_name)
@fork_project_user = @project&.fork_project&.owner.try(:login)
@fork_project_identifier = @project&.fork_project&.repository.try(:identifier)
@fork_project_user_name = @pull_request&.fork_project&.owner.try(:show_real_name)
@fork_project_user = @pull_request&.fork_project&.owner.try(:login)
@fork_project_identifier = @pull_request&.fork_project&.repository.try(:identifier)
end
def update
if params[:title].nil?
normal_status(-1, "名称不能为空")
elsif params[:issue_tag_ids].nil?
normal_status(-1, "不能为空")
normal_status(-1, "不能为空")
else
ActiveRecord::Base.transaction do
begin
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?
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
@ -116,6 +118,8 @@ class PullRequestsController < ApplicationController
normal_status(-1, e.message)
raise ActiveRecord::Rollback
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
@ -125,7 +129,13 @@ class PullRequestsController < ApplicationController
ActiveRecord::Base.transaction do
begin
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
normal_status(-1, e.message)
raise ActiveRecord::Rollback
@ -162,8 +172,10 @@ class PullRequestsController < ApplicationController
end
if success_condition && @pull_request.merge!
@pull_request.project_trend_status!
# @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)
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
normal_status(1, "合并成功")
else
normal_status(-1, result.message)
@ -190,7 +202,7 @@ class PullRequestsController < ApplicationController
if can_merge.present?
render json: {
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
normal_status(0, "可以合并")

View File

@ -1,4 +1,5 @@
class RepositoriesController < ApplicationController
include RepositoriesHelper
include ApplicationHelper
include OperateProjectAbilityAble
include Repository::LanguagesPercentagable
@ -54,16 +55,6 @@ class RepositoriesController < ApplicationController
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
# 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
@ -73,6 +64,7 @@ class RepositoriesController < ApplicationController
def sub_entries
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 params[:type] === 'file'
@ -103,8 +95,19 @@ class RepositoriesController < ApplicationController
end
def commits
@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
if params[:filepath].present?
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
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
@ -120,7 +123,11 @@ class RepositoriesController < ApplicationController
end
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
def edit
@ -183,10 +190,16 @@ class RepositoriesController < ApplicationController
end
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
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
def languages
@ -206,6 +219,17 @@ class RepositoriesController < ApplicationController
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
def find_project
@ -226,8 +250,14 @@ class RepositoriesController < ApplicationController
# TODO 获取最新commit信息
def project_commits
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
if params[:filepath].present?
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
def get_statistics

View File

@ -4,7 +4,7 @@ class SettingsController < ApplicationController
get_add_menu
get_common_menu
get_personal_menu
get_top_system_notification
end
private
@ -40,6 +40,10 @@ class SettingsController < ApplicationController
end
end
def get_top_system_notification
@top_system_notification = SystemNotification.is_top.first
end
def get_site_url(key, value)
key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value)
end

View File

@ -0,0 +1,8 @@
class TemplateMessageSettingsController < ApplicationController
before_action :require_login
def index
@group_settings = TemplateMessageSetting.group(:type).count
end
end

View File

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

View File

@ -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

View File

@ -14,7 +14,7 @@ class Users::StatisticsController < Users::BaseController
@date_data << date.strftime("%Y.%m.%d")
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
date_commit_data = commit_data.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)
end
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}

View File

@ -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

View File

@ -91,6 +91,12 @@ class UsersController < ApplicationController
def get_user_info
begin
@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 等消息上线再打开注释
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
rescue Exception => e

View File

@ -1,14 +1,14 @@
class VersionReleasesController < ApplicationController
before_action :load_repository
before_action :set_user
before_action :require_login, except: [:index]
before_action :find_version , only: [:edit, :update, :destroy]
before_action :require_login, except: [:index, :show]
before_action :check_release_authorize, except: [:index, :show]
before_action :find_version , only: [:show, :edit, :update, :destroy]
def index
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
@version_releases = version_releases
@version_releases = kaminari_paginate(@repository.version_releases.order(created_at: :desc))
@user_permission = current_user.present? && (@repository.project.all_developers.include?(current_user) || current_user.admin?)
@forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments)
@user_admin_permission = current_user.present? && (@repository.project.all_managers.include?(current_user) || current_user.admin?)
end
def new
@ -22,6 +22,10 @@ class VersionReleasesController < ApplicationController
end
end
def show
# @release = Gitea::Versions::GetService.call(current_user.gitea_token, @user&.login, @repository&.identifier, @version&.version_gid)
end
def create
if params[:name].nil?
normal_status(-1, "名称不能为空")
@ -37,13 +41,14 @@ class VersionReleasesController < ApplicationController
version_params = releases_params
version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id))
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
update_params = {
tarball_url: git_version_release["tarball_url"],
zipball_url: git_version_release["zipball_url"],
url: git_version_release["url"],
version_gid: git_version_release["id"],
sha: git_version_release["sha"]
}
version_release.update_attributes!(update_params)
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)
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
raise Error, "更新失败"
end
@ -102,7 +107,7 @@ class VersionReleasesController < ApplicationController
ActiveRecord::Base.transaction do
begin
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
normal_status(0, "删除成功")
@ -157,4 +162,8 @@ class VersionReleasesController < ApplicationController
end
end
def check_release_authorize
return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.manager?(current_user)
end
end

View File

@ -1 +1,502 @@
# 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|commits 提交时间距当前时间的时间值|
|-- message |string|commit说明信息|
|-- sha |string|commits 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|commits 提交时间距当前时间的时间值|
|-- message |string|commit说明信息|
|-- sha |string|commits 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
}
]
}
```

View File

@ -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"
}
}
}
]
```
## 编辑仓库信息
编辑仓库信息
@ -868,6 +986,128 @@ await octokit.request('GET /api/jasder/jasder_test/sub_entries.json')
Success Data.
</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列表

View File

@ -1,7 +1,7 @@
<!--
* @Date: 2021-03-01 10:35:21
* @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
-->
# Users
@ -47,6 +47,275 @@ await octokit.request('GET /api/users/me.json')
Success Data.
</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>
## 发送消息
发送消息, 目前只支持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 +372,290 @@ await octokit.request('PATCH/PUT /api/users/:login.json')
"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>
## 获取用户星标项目
获取用户星标项目

View File

@ -2,18 +2,28 @@ class BaseForm
include ActiveModel::Model
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
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
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
def check_project_name(user_id, project_name)
raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists?
end
def check_reversed_keyword(repository_name)
raise "项目标识已被占用." if ReversedKeyword.is_reversed(repository_name).exists?
end
end

View File

@ -5,7 +5,7 @@ class Issues::CreateForm
validates :subject, presence: { message: "不能为空" }
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
end

View File

@ -5,6 +5,6 @@ class Issues::UpdateForm
validates :subject, presence: { message: "不能为空" }
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
end

View File

@ -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

View File

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

View File

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

View File

@ -1,11 +1,14 @@
class Projects::UpdateForm < BaseForm
attr_accessor :name, :description, :project_category_id, :project_language_id, :private
validates :name, :description, :project_category_id, :project_language_id, presence: true
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier
validates :name, presence: true
validates :name, length: { maximum: 50 }
validates :description, length: { maximum: 200 }
validate do
check_project_category(project_category_id)
check_project_language(project_language_id)
Rails.logger.info project_identifier
Rails.logger.info identifier
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
end
end

View File

@ -434,6 +434,10 @@ module ApplicationHelper
User.find_by_login login
end
def find_user_by_login_and_mail(login, mail)
User.find_by(login: login, mail: mail)
end
def find_user_by_gitea_uid(gitea_uid)
User.find_by(gitea_uid: gitea_uid)
end

View File

@ -21,6 +21,10 @@ module ProjectsHelper
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.tar.gz")].join
end
def render_download_file_url(owner, repository, filepath, ref)
[base_url, "/api/#{owner&.login}/#{repository.identifier}/raw?filepath=#{filepath}&ref=#{ref}"].join
end
def render_http_url(project)
[gitea_domain, project.owner.login, "#{project.identifier}.git"].join('/')
end

View File

@ -6,16 +6,16 @@ module RepositoriesHelper
def render_decode64_content(str)
return nil if str.blank?
Base64.decode64(str).force_encoding("UTF-8")
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
end
def download_type(str)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2)
default_type.include?(str&.downcase)
end
def image_type?(str)
default_type = %w(png jpg gif tif psd svg gif bmp webp jpeg)
default_type = %w(png jpg gif tif psd svg bmp webp jpeg)
default_type.include?(str&.downcase)
end
@ -26,9 +26,13 @@ module RepositoriesHelper
end
def render_commit_author(author_json)
return nil if author_json.blank? || author_json["id"].blank?
# find_user_by_login author_json['name']
find_user_by_gitea_uid author_json['id']
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
if author_json["id"].present?
return find_user_by_gitea_uid author_json['id']
end
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
end
end
def readme_render_decode64_content(str, path)
@ -79,12 +83,15 @@ module RepositoriesHelper
def decode64_content(entry, owner, repo, ref, path=nil)
if is_readme?(entry['type'], entry['name'])
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content']
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
readme_render_decode64_content(content, path)
else
file_type = File.extname(entry['name'].to_s)[1..-1]
if image_type?(file_type)
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
end
if download_type(file_type)
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] : entry['content']
return entry['content']
end
render_decode64_content(entry['content'])
end

View File

@ -18,12 +18,30 @@ class BroadcastMirrorRepoMsgJob < ApplicationJob
id: project.id,
type: project.numerical_for_project_type
}
# 新增失败重试机制, 重试三次
result = broadcast(project, json_data)
if result == 0
count = 3
while count > 0
sleep 3.seconds
result = broadcast(project, json_data)
if result > 0
break
end
count -= 1
end
end
end
def broadcast(project, json_data)
puts "############ broadcast start.......... "
puts "############ broadcast channel_name: channel_room_#{project.id}"
puts "############ broadcast project data: #{json_data} "
cable_result = ActionCable.server.broadcast "channel_room_#{project.id}", project: json_data
puts "############ broadcast result: #{cable_result == 1 ? 'successed' : 'failed'} "
puts "############ broadcast result: #{cable_result > 0 ? 'successed' : 'failed'} "
return cable_result
end
end

View File

@ -0,0 +1,11 @@
class DelayExpiredIssueJob < ApplicationJob
queue_as :message
def perform
Issue.where(due_date: Date.today + 1.days).find_each do |issue|
SendTemplateMessageJob.perform_later('IssueAssignerExpire', issue.id) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) if Site.has_notice_menu?
end
end
end

View File

@ -16,5 +16,6 @@ class MigrateRemoteRepositoryJob < ApplicationJob
else
repo&.mirror&.failed!
end
BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting?
end
end

View File

@ -0,0 +1,279 @@
class SendTemplateMessageJob < ApplicationJob
queue_as :message
def perform(source, *args)
Rails.logger.info "SendTemplateMessageJob [args] #{args}"
case source
when 'FollowTip'
watcher_id = args[0]
watcher = Watcher.find_by_id(watcher_id)
return unless watcher.present?
receivers = User.where(id: watcher.watchable_id)
followeder = User.find_by_id(watcher.user_id)
receivers_string, content, notification_url = MessageTemplate::FollowedTip.get_message_content(receivers, followeder)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {watcher_id: watcher.id})
when 'IssueAssigned'
operator_id, issue_id = args[0], args[1]
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueAssigned.get_message_content(receivers, operator, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'IssueAssignerExpire'
issue_id = args[0]
issue = Issue.find_by_id(issue_id)
return unless issue.present?
receivers = User.where(id: issue&.assigned_to_id)
receivers_string, content, notification_url = MessageTemplate::IssueAssignerExpire.get_message_content(receivers, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
when 'IssueAtme'
receivers, operator_id, issue_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = receivers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2)
when 'IssueChanged'
operator_id, issue_id, change_params = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id]).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueChanged.get_message_content(receivers, operator, issue, change_params.symbolize_keys)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id, change_params: change_params.symbolize_keys})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::IssueChanged.get_email_message_content(receiver, operator, issue, change_params)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'IssueCreatorExpire'
issue_id = args[0]
issue = Issue.find_by_id(issue_id)
return unless issue.present?
receivers = User.where(id: issue&.author_id)
receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
when 'IssueDeleted'
operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3]
operator = User.find_by_id(operator_id)
return unless operator.present?
receivers = User.where(id: [issue_assigned_to_id, issue_author_id]).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueDeleted.get_message_content(receivers, operator, issue_title)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_title: issue_title})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::IssueDeleted.get_email_message_content(receiver, operator, issue_title)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'OrganizationJoined'
user_id, organization_id = args[0], args[1]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
return unless user.present? && organization.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::OrganizationJoined.get_message_content(receivers, organization)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationJoined.get_email_message_content(receiver, organization)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'OrganizationLeft'
user_id, organization_id = args[0], args[1]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
return unless user.present? && organization.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::OrganizationLeft.get_message_content(receivers, organization)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'OrganizationRole'
user_id, organization_id, role = args[0], args[1], args[2]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
return unless user.present? && organization.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationRole.get_email_message_content(receiver, organization, role)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectIssue'
operator_id, issue_id = args[0], args[1]
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present? && issue&.project.present?
managers = issue&.project&.all_managers.where.not(id: operator&.id)
followers = User.none # TODO
receivers_string, content, notification_url = MessageTemplate::ProjectIssue.get_message_content(managers, followers, operator, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id})
managers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, true, operator, issue)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
followers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, false, operator, issue)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectJoined'
operator_id, user_id, project_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
user = User.find_by_id(user_id)
project = Project.find_by_id(project_id)
return unless operator.present? && user.present? && project.present?
receivers = User.where(id: user.id).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::ProjectJoined.get_message_content(receivers, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectJoined.get_email_message_content(receiver, project)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectLeft'
operator_id, user_id, project_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
user = User.find_by_id(user_id)
project = Project.find_by_id(project_id)
return unless operator.present? && user.present? && project.present?
receivers = User.where(id: user.id).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::ProjectLeft.get_message_content(receivers, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectLeft.get_email_message_content(receiver, project)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectMemberJoined'
operator_id, user_id, project_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
user = User.find_by_id(user_id)
project = Project.find_by_id(project_id)
return unless operator.present? && user.present? && project.present?
receivers = project&.all_managers.where.not(id: [operator&.id, user&.id])
receivers_string, content, notification_url = MessageTemplate::ProjectMemberJoined.get_message_content(receivers, user, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberJoined.get_email_message_content(receiver, user, project)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectMemberLeft'
operator_id, user_id, project_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
user = User.find_by_id(user_id)
project = Project.find_by_id(project_id)
return unless operator.present? && user.present? && project.present?
receivers = project&.all_managers.where.not(id: [operator&.id, user&.id])
receivers_string, content, notification_url = MessageTemplate::ProjectMemberLeft.get_message_content(receivers, user, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectPullRequest'
operator_id, pull_request_id = args[0], args[1]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present? && pull_request&.project.present?
managers = pull_request&.project&.all_managers.where.not(id: operator&.id)
followers = User.none # TODO
receivers_string, content, notification_url = MessageTemplate::ProjectPullRequest.get_message_content(managers, followers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id})
managers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, true, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
followers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, false, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectRole'
operator_id, user_id, project_id, role = args[0], args[1], args[2], args[3]
operator = User.find_by_id(operator_id)
user = User.find_by_id(user_id)
project = Project.find_by_id(project_id)
return unless operator.present? && user.present? && project.present?
receivers = User.where(id: user.id).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::ProjectRole.get_message_content(receivers, project, role)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id, role: role})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectRole.get_email_message_content(receiver, project, role)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectSettingChanged'
operator_id, project_id, change_params = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
project = Project.find_by_id(project_id)
return unless operator.present? && project.present?
receivers = project.all_managers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::ProjectSettingChanged.get_message_content(receivers, operator, project, change_params.symbolize_keys)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id, change_params: change_params.symbolize_keys})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectSettingChanged.get_email_message_content(receiver, operator, project, change_params.symbolize_keys)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'PullRequestAssigned'
operator_id, pull_request_id = args[0], args[1]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
issue = Issue.find_by_id(pull_request&.issue_id)
return unless operator.present? && pull_request.present? && issue.present?
receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestAssigned.get_message_content(receivers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestAssigned.get_email_message_content(receiver, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'PullRequestAtme'
receivers, operator_id, pull_request_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present?
receivers = receivers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2)
when 'PullRequestChanged'
operator_id, pull_request_id, change_params = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
issue = Issue.find_by_id(pull_request&.issue_id)
return unless operator.present? && pull_request.present? && issue.present?
receivers = User.where(id: [issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestChanged.get_message_content(receivers, operator, pull_request, change_params.symbolize_keys)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id, change_params: change_params})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestChanged.get_email_message_content(receiver, operator, pull_request, change_params.symbolize_keys)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'PullRequestClosed'
operator_id, pull_request_id = args[0], args[1]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present?
receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestClosed.get_message_content(receivers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestClosed.get_email_message_content(receiver, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'PullRequestMerged'
operator_id, pull_request_id = args[0], args[1]
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present?
receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestMerged.get_message_content(receivers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestMerged.get_email_message_content(receiver, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
end
end
end

View File

@ -26,6 +26,7 @@ class SyncMirroredRepositoryJob < ApplicationJob
result = Gitea::Repository::SyncMirroredService.call(repo.owner.login,
repo.identifier, token: user.gitea_token)
repo&.mirror.set_status! if result[:status] === 200
BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting?
end
end

View File

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

21
app/libs/notice.rb Normal file
View File

@ -0,0 +1,21 @@
module Notice
class << self
def notice_config
notice_config = {}
begin
config = Rails.application.config_for(:configuration).symbolize_keys!
notice_config = config[:notice].symbolize_keys!
raise 'notice config missing' if notice_config.blank?
rescue => exception
raise ex if Rails.env.production?
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
notice_config = {}
end
notice_config
end
end
end

View File

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

View File

@ -17,6 +17,8 @@
class EduSetting < ApplicationRecord
after_commit :expire_value_cache
scope :by_search, -> (keyword){ where("name LIKE :keyword OR value LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
def value_cache_key
self.class.value_cache_key(name)
end

View File

@ -0,0 +1,106 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
class MessageTemplate < ApplicationRecord
def self.build_init_data
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个易修')
self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在易修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
email_html = File.read("#{email_template_html_dir}/issue_changed.html")
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: '易修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
email_html = File.read("#{email_template_html_dir}/issue_deleted.html")
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', email: email_html, email_title: '易修 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论易修{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '')
email_html = File.read("#{email_template_html_dir}/organization_joined.html")
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: '你已加入 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_left.html")
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: '你已被移出 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_role.html")
self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '')
self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_issue.html")
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 新建了一个易修')
email_html = File.read("#{email_template_html_dir}/project_joined.html")
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '你已加入 {repository} 项目')
email_html = File.read("#{email_template_html_dir}/project_left.html")
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: '你已被移出 {repository} 项目')
email_html = File.read("#{email_template_html_dir}/project_member_joined.html")
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已加入项目 {nickname2}/{repository}')
email_html = File.read("#{email_template_html_dir}/project_member_left.html")
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已被移出项目 {nickname2}/{repository}')
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 提交了一个合并请求')
email_html = File.read("#{email_template_html_dir}/project_role.html")
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_setting_changed.html")
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: '您管理的仓库 {nickname2}/{repository} 仓库设置已被更改')
self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases')
email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html")
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求')
self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_changed.html")
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_closed.html")
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
end
def self.sys_notice
self.last&.sys_notice
end
def self.email
self.last&.email
end
def self.email_title
self.last&.email_title
end
def self.notification_url
self.last&.notification_url.gsub('{baseurl}', base_url)
end
def self.base_url
Rails.application.config_for(:configuration)['platform_url']
end
def self.receivers_string(receivers)
receivers.pluck(:id).join(",")
end
def self.receivers_email_string(receivers)
receivers.pluck(:mail).join(",")
end
def self.email_template_html_dir
"#{Rails.root}/public/message_template"
end
def simple_type
self.type.split("::")[-1]
end
end

View File

@ -0,0 +1,24 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 被关注提示
class MessageTemplate::FollowedTip < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, followeder)
return receivers_string(receivers), sys_notice.gsub('{nickname}', followeder&.real_name), notification_url.gsub('{login}', followeder.login)
rescue
return '', '', ''
end
end

View File

@ -0,0 +1,63 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 有新指派给我的易修
class MessageTemplate::IssueAssigned < MessageTemplate
# MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)
def self.get_message_content(receivers, operator, issue)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::IssueAssigned"]
end
end
return '', '', '' if receivers.blank?
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, issue)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::IssueAssigned"]
end
project = issue&.project
owner = project&.owner
title = email_title
title.gsub!('{nickname1}', operator&.real_name)
title.gsub!('{nickname2}', owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', issue&.subject)
content.gsub!('{id}', issue&.id.to_s)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::IssueAssigned.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,29 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我负责的易修截止日期到达最后一天
class MessageTemplate::IssueAssignerExpire < MessageTemplate
# MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
def self.get_message_content(receivers, issue)
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,29 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 在易修中@我
class MessageTemplate::IssueAtme < MessageTemplate
# MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)
def self.get_message_content(receivers, operator, issue)
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}")
return 0, '', ''
end
end

View File

@ -0,0 +1,368 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建或负责的易修状态变更
class MessageTemplate::IssueChanged < MessageTemplate
# MessageTemplate::IssueChanged.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last, {status_id: [1, 2], assigned_to_id: [nil, 203], tracker_id: [4, 3], priority_id: [2, 4], fixed_version_id: [nil, 5], due_date: ['', '2021-09-11'], done_ratio: [0, 40], issue_tags_value: ["", "7"], branch_name: ["", "master"]})
def self.get_message_content(receivers, operator, issue, change_params)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueChanged"]
end
end
return '', '', '' if receivers.blank?
return '', '', '' if change_params.blank?
project = issue&.project
owner = project&.owner
content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
change_count = change_params.keys.size
# 易修负责人修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end
# 易修状态修改
if change_params[:status_id].present?
status1 = IssueStatus.find_by_id(change_params[:status_id][0])
status2 = IssueStatus.find_by_id(change_params[:status_id][1])
if change_count > 1
content.sub!('{ifstatus}', '<br/>')
else
content.sub!('{ifstatus}', '')
end
content.sub!('{endstatus}', '')
content.gsub!('{status1}', status1&.name)
content.gsub!('{status2}', status2&.name)
else
content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
end
# 易修类型修改
if change_params[:tracker_id].present?
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
if change_count > 1
content.sub!('{iftracker}', '<br/>')
else
content.sub!('{iftracker}', '')
end
content.sub!('{endtracker}', '')
content.gsub!('{tracker1}', tracker1&.name)
content.gsub!('{tracker2}', tracker2&.name)
else
content.gsub!(/({iftracker})(.*)({endtracker})/, '')
end
# 易修里程碑修改
if change_params[:fixed_version_id].present?
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
if change_count > 1
content.sub!('{ifmilestone}', '<br/>')
else
content.sub!('{ifmilestone}', '')
end
content.sub!('{endmilestone}', '')
content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑')
content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑')
else
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end
# 易修标记修改
if change_params[:issue_tags_value].present?
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",")
tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",")
if change_count > 1
content.sub!('{iftag}', '<br/>')
else
content.sub!('{iftag}', '')
end
content.sub!('{endtag}', '')
content.gsub!('{tag1}', tag1)
content.gsub!('{tag2}', tag2)
else
content.gsub!(/({iftag})(.*)({endtag})()/, '')
end
# 易修优先级修改
if change_params[:priority_id].present?
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
if change_count > 1
content.sub!('{ifpriority}', '<br/>')
else
content.sub!('{ifpriority}', '')
end
content.sub!('{endpriority}', '')
content.gsub!('{priority1}', priority1&.name)
content.gsub!('{priority2}', priority2&.name)
else
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end
# 易修完成度修改
if change_params[:done_ratio].present?
doneratio1 = change_params[:done_ratio][0]
doneratio2 = change_params[:done_ratio][1]
if change_count > 1
content.sub!('{ifdoneratio}', '<br/>')
else
content.sub!('{ifdoneratio}', '')
end
content.sub!('{enddoneratio}', '')
content.gsub!('{doneratio1}', "#{doneratio1}%")
content.gsub!('{doneratio2}', "#{doneratio2}%")
else
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
end
# 易修指定分支修改
if change_params[:branch_name].present?
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
if change_count > 1
content.sub!('{ifbranch}', '<br/>')
else
content.sub!('{ifbranch}', '')
end
content.sub!('{endbranch}', '')
content.gsub!('{branch1}', branch1)
content.gsub!('{branch2}', branch2)
else
content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
end
# 易修开始日期修改
if change_params[:start_date].present?
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
if change_count > 1
content.sub!('{ifstartdate}', '<br/>')
else
content.sub!('{ifstartdate}', '')
end
content.sub!('{endstartdate}', '')
content.gsub!('{startdate1}', startdate1 )
content.gsub!('{startdate2}', startdate2)
else
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
end
# 易修结束日期修改
if change_params[:due_date].present?
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
if change_count > 1
content.sub!('{ifduedate}', '<br/>')
else
content.sub!('{ifduedate}', '')
end
content.sub!('{endduedate}', '')
content.gsub!('{duedate1}', duedate1)
content.gsub!('{duedate2}', duedate2)
else
content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
end
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, issue, change_params)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"]
end
project = issue&.project
owner = project&.owner
title = email_title
title.gsub!('{title}', issue&.subject)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{title}', issue&.subject)
content.gsub!('{id}', issue&.id.to_s)
change_count = change_params.keys.size
# 易修负责人修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end
# 易修状态修改
if change_params[:status_id].present?
status1 = IssueStatus.find_by_id(change_params[:status_id][0])
status2 = IssueStatus.find_by_id(change_params[:status_id][1])
if change_count > 1
content.sub!('{ifstatus}', '<br/>')
else
content.sub!('{ifstatus}', '')
end
content.sub!('{endstatus}', '')
content.gsub!('{status1}', status1&.name)
content.gsub!('{status2}', status2&.name)
else
content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
end
# 易修类型修改
if change_params[:tracker_id].present?
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
if change_count > 1
content.sub!('{iftracker}', '<br/>')
else
content.sub!('{iftracker}', '')
end
content.sub!('{endtracker}', '')
content.gsub!('{tracker1}', tracker1&.name)
content.gsub!('{tracker2}', tracker2&.name)
else
content.gsub!(/({iftracker})(.*)({endtracker})/, '')
end
# 易修里程碑修改
if change_params[:fixed_version_id].present?
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
if change_count > 1
content.sub!('{ifmilestone}', '<br/>')
else
content.sub!('{ifmilestone}', '')
end
content.sub!('{endmilestone}', '')
content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑')
content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑')
else
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end
# 易修标记修改
if change_params[:issue_tags_value].present?
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",")
tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",")
if change_count > 1
content.sub!('{iftag}', '<br/>')
else
content.sub!('{iftag}', '')
end
content.sub!('{endtag}', '')
content.gsub!('{tag1}', tag1)
content.gsub!('{tag2}', tag2)
else
content.gsub!(/({iftag})(.*)({endtag})()/, '')
end
# 易修优先级修改
if change_params[:priority_id].present?
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
if change_count > 1
content.sub!('{ifpriority}', '<br/>')
else
content.sub!('{ifpriority}', '')
end
content.sub!('{endpriority}', '')
content.gsub!('{priority1}', priority1&.name)
content.gsub!('{priority2}', priority2&.name)
else
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end
# 易修完成度修改
if change_params[:done_ratio].present?
doneratio1 = change_params[:done_ratio][0]
doneratio2 = change_params[:done_ratio][1]
if change_count > 1
content.sub!('{ifdoneratio}', '<br/>')
else
content.sub!('{ifdoneratio}', '')
end
content.sub!('{enddoneratio}', '')
content.gsub!('{doneratio1}', "#{doneratio1}%")
content.gsub!('{doneratio2}', "#{doneratio2}%")
else
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
end
# 易修指定分支修改
if change_params[:branch_name].present?
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
if change_count > 1
content.sub!('{ifbranch}', '<br/>')
else
content.sub!('{ifbranch}', '')
end
content.sub!('{endbranch}', '')
content.gsub!('{branch1}', branch1)
content.gsub!('{branch2}', branch2)
else
content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
end
# 易修开始日期修改
if change_params[:start_date].present?
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
if change_count > 1
content.sub!('{ifstartdate}', '<br/>')
else
content.sub!('{ifstartdate}', '')
end
content.sub!('{endstartdate}', '')
content.gsub!('{startdate1}', startdate1 )
content.gsub!('{startdate2}', startdate2)
else
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
end
# 易修结束日期修改
if change_params[:due_date].present?
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
if change_count > 1
content.sub!('{ifduedate}', '<br/>')
else
content.sub!('{ifduedate}', '')
end
content.sub!('{endduedate}', '')
content.gsub!('{duedate1}', duedate1)
content.gsub!('{duedate2}', duedate2)
else
content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
end
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::IssueChanged.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,29 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建的易修截止日期到达最后一天
class MessageTemplate::IssueCreatorExpire < MessageTemplate
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
def self.get_message_content(receivers, issue)
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,51 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建或负责的易修删除
class MessageTemplate::IssueDeleted < MessageTemplate
# MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah")
def self.get_message_content(receivers, operator, issue_title)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueChanged"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue_title)
return receivers_string(receivers), content, notification_url
rescue => e
Rails.logger.info("MessageTemplate::IssueDeleted.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, issue_title)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"]
end
title = email_title
title.gsub!('{title}', issue_title)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname}', operator&.real_name)
content.gsub!('{login}', operator&.login)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', issue_title)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::IssueDeleted.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我创建或负责的易修有新的评论
class MessageTemplate::IssueJournal < MessageTemplate
# MessageTemplate::IssueJournal.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueJournal.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 登录异常提示
class MessageTemplate::LoginIpTip < MessageTemplate
# MessageTemplate::LoginIpTip.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::LoginIpTip.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,51 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号被拉入组织
class MessageTemplate::OrganizationJoined < MessageTemplate
# MessageTemplate::OrganizationJoined.get_message_content(User.where(login: 'yystopf'), Organization.last)
def self.get_message_content(receivers, organization)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Organization"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{organization}', organization&.real_name)
url = notification_url.gsub('{login}', organization&.name)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::OrganizationJoined.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, organization)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Organization"]
end
title = email_title
title.gsub!('{organization}', organization&.real_name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', organization&.login)
content.gsub!('{organization}', organization&.real_name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::OrganizationJoined.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,51 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号被移出组织
class MessageTemplate::OrganizationLeft < MessageTemplate
# MessageTemplate::OrganizationLeft.get_message_content(User.where(login: 'yystopf'), Organization.last)
def self.get_message_content(receivers, organization)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Organization"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{organization}', organization&.real_name)
url = notification_url.gsub('{login}', organization&.name)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::OrganizationLeft.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, organization)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Organization"]
end
title = email_title
title.gsub!('{organization}', organization&.real_name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', organization&.login)
content.gsub!('{organization}', organization&.real_name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::OrganizationLeft.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,53 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号组织权限变更
class MessageTemplate::OrganizationRole < MessageTemplate
# MessageTemplate::OrganizationRole.get_message_content(User.where(login: 'yystopf'), Organization.last, '管理员')
def self.get_message_content(receivers, organization, role)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{role}', role)
url = notification_url.gsub('{login}', organization&.login)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::OrganizationRole.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, organization, role)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
end
title = email_title
title.gsub!('{organization}', organization&.real_name)
title.gsub!('{role}', role)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', organization&.login)
content.gsub!('{organization}', organization&.real_name)
content.gsub!('{role}', role)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::OrganizationRole.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我关注的仓库被删除
class MessageTemplate::ProjectDeleted < MessageTemplate
# MessageTemplate::ProjectDeleted.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectDeleted.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理的仓库被关注
class MessageTemplate::ProjectFollowed < MessageTemplate
# MessageTemplate::ProjectFollowed.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectFollowed.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理的仓库被复刻
class MessageTemplate::ProjectForked < MessageTemplate
# MessageTemplate::ProjectForked.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,66 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理/关注的仓库有新的易修
class MessageTemplate::ProjectIssue < MessageTemplate
# MessageTemplate::ProjectIssue.get_message_content(User.where(login: 'yystopf'), User.where(login: 'forgetest1'), User.last, Issue.last)
def self.get_message_content(managers, followers, operator, issue)
managers.each do |receiver|
if receiver.user_template_message_setting.present?
managers = managers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Issue"]
end
end
project = issue&.project
owner = project&.owner
receivers = managers + followers
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectIssue.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, is_manager, operator, issue)
if receiver.user_template_message_setting.present? && is_manager
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::Issue"]
end
project = issue&.project
owner = project&.owner
title = email_title
title.gsub!('{nickname1}', operator&.real_name)
title.gsub!('{nickname2}', owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{repository}', project&.name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{title}', issue&.subject)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectIssue.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,54 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号被拉入项目
class MessageTemplate::ProjectJoined < MessageTemplate
# MessageTemplate::ProjectJoined.get_message_content(User.where(login: 'yystopf'), Project.last)
def self.get_message_content(receivers, project)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Project"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{repository}', project&.name)
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectJoined.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, project)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Project"]
end
title = email_title
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', project&.owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{nickname}', project&.owner&.real_name)
content.gsub!('{repository}', project&.name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectJoined.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,53 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号被移出项目
class MessageTemplate::ProjectLeft < MessageTemplate
# MessageTemplate::ProjectLeft.get_message_content(User.where(login: 'yystopf'), Project.last)
def self.get_message_content(receivers, project)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Project"]
end
end
content = sys_notice.gsub('{repository}', project&.name)
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectLeft.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, project)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Project"]
end
title = email_title
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', project&.owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{nickname}', project&.owner&.real_name)
content.gsub!('{repository}', project&.name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectLeft.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,58 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我管理的仓库有成员加入
class MessageTemplate::ProjectMemberJoined < MessageTemplate
# MessageTemplate::ProjectMemberJoined.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers, user, project)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Member"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, user, project)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::Member"]
end
title = email_title
title.gsub!('{nickname1}', user&.real_name)
title.gsub!('{nickname2}', project&.owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', user&.login)
content.gsub!('{login2}', project&.owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{nickname1}', user&.real_name)
content.gsub!('{nickname2}', project&.owner&.real_name)
content.gsub!('{repository}', project&.name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,58 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我管理的仓库有成员移出
class MessageTemplate::ProjectMemberLeft < MessageTemplate
# MessageTemplate::ProjectMemberLeft.get_message_content(User.where(login: 'yystopf'), User.last, Project.last)
def self.get_message_content(receivers, user, project)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Member"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, user, project)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::Member"]
end
title = email_title
title.gsub!('{nickname1}', user&.real_name)
title.gsub!('{nickname2}', project&.owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', user&.login)
content.gsub!('{login2}', project&.owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{nickname1}', user&.real_name)
content.gsub!('{nickname2}', project&.owner&.real_name)
content.gsub!('{repository}', project&.name)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理的仓库有新的里程碑
class MessageTemplate::ProjectMilestone < MessageTemplate
# MessageTemplate::ProjectMilestone.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectMilestone.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理的仓库被点赞
class MessageTemplate::ProjectPraised < MessageTemplate
# MessageTemplate::ProjectPraised.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectPraised.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,66 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我管理/关注的仓库有新的合并请求
class MessageTemplate::ProjectPullRequest < MessageTemplate
# MessageTemplate::ProjectPullRequest.get_message_content(User.where(login: 'yystopf'), User.where(login: 'testforge2'), User.last, PullRequest.last)
def self.get_message_content(managers, followers, operator, pull_request)
managers.each do |receiver|
if receiver.user_template_message_setting.present?
managers = managers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::PullRequest"]
end
end
project = pull_request&.project
owner = project&.owner
receivers = managers + followers
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectPullRequest.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, is_manager, operator, pull_request)
if receiver.user_template_message_setting.present? && is_manager
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::PullRequest"]
end
project = pull_request&.project
owner = project&.owner
title = email_title
title.gsub!('{nickname1}', operator&.real_name)
title.gsub!('{nickname2}', owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{repository}', project&.name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{id}', pull_request&.id.to_s)
content.gsub!('{title}', pull_request&.title)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectPullRequest.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,56 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 账号仓库权限变更
class MessageTemplate::ProjectRole < MessageTemplate
# MessageTemplate::ProjectRole.get_message_content(User.where(login: 'yystopf'), Project.last, '管理员')
def self.get_message_content(receivers, project, role)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname}', project&.owner&.real_name).gsub('{repository}', project&.name).gsub('{role}', role)
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectRole.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, project, role)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
end
title = email_title
title.gsub!('{repository}', project&.name)
title.gsub!('{role}', role)
title.gsub!('{nickname}', project&.owner&.real_name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login}', project&.owner&.login)
content.gsub!('{nickname}', project&.owner&.real_name)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{role}', role)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectRole.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,310 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我管理的仓库项目设置被更改
class MessageTemplate::ProjectSettingChanged < MessageTemplate
# MessageTemplate::ProjectSettingChanged.get_message_content(User.where(login: 'yystopf'), User.last, Project.last, {description: '测试修改项目简介', category: '大数据', language: 'Ruby', permission: '公有', navbar: '易修, 合并请求'})
def self.get_message_content(receivers, operator, project, change_params)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::SettingChanged"]
end
end
return '', '', '' if receivers.blank?
return '', '', '' if change_params.blank?
owner = project&.owner
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier)
change_count = change_params.keys.size
# 项目名称更改
if change_params[:name].present?
if change_count > 1
content.sub!('{ifname}', '<br/>')
else
content.sub!('{ifname}', '')
end
content.sub!('{endname}', '')
content.gsub!('{name}', change_params[:name][1])
else
content.gsub!(/({ifname})(.*)({endname})/, '')
end
# 项目标识更改
if change_params[:identifier].present?
if change_count > 1
content.sub!('{ifidentifier}', '<br/>')
else
content.sub!('{ifidentifier}', '')
end
content.sub!('{endidentifier}', '')
content.gsub!('{identifier}', change_params[:identifier][1])
else
content.gsub!(/({ifidentifier})(.*)({endidentifier})/, '')
end
# 项目简介更改
if change_params[:description].present?
if change_params[:description][1].blank?
if change_count > 1
content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介')
else
content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介')
end
else
if change_count > 1
content.sub!('{ifdescription}', '<br/>')
else
content.sub!('{ifdescription}', '')
end
content.sub!('{enddescription}', '')
content.gsub!('{description}', change_params[:description][1])
end
else
content.gsub!(/({ifdescription})(.*)({enddescription})/, '')
end
# 项目类别更改
if change_params[:project_category_id].present?
category = ProjectCategory.find_by_id(change_params[:project_category_id][1])
if category.present?
if change_count > 1
content.sub!('{ifcategory}', '<br/>')
else
content.sub!('{ifcategory}', '')
end
content.sub!('{endcategory}', '')
content.gsub!('{category}', category&.name)
else
if change_count > 1
content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别')
else
content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别')
end
end
else
content.gsub!(/({ifcategory})(.*)({endcategory})/, '')
end
# 项目语言更改
if change_params[:project_language_id].present?
language = ProjectLanguage.find_by_id(change_params[:project_language_id][1])
if language.present?
if change_count > 1
content.sub!('{iflanguage}', '<br/>')
else
content.sub!('{iflanguage}', '')
end
content.sub!('{endlanguage}', '')
content.gsub!('{language}', language&.name)
else
if change_count > 1
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言')
else
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言')
end
end
else
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '')
end
# 项目公私有更改
if change_params[:is_public].present?
permission = change_params[:is_public][1] ? '公有' : '私有'
if change_count > 1
content.sub!('{ifpermission}', '<br/>')
else
content.sub!('{ifpermission}', '')
end
content.sub!('{endpermission}', '')
content.gsub!('{permission}', permission)
else
content.gsub!(/({ifpermission})(.*)({endpermission})/, '')
end
# 项目导航更改
if change_params[:navbar].present?
unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type)
unit_types.delete('code')
unit_types.unshift('代码库')
unit_types.unshift('主页')
unit_types.append('动态')
navbar = unit_types.join('')
navbar.gsub!('issues', '易修')
navbar.gsub!('pulls', '合并请求')
navbar.gsub!('wiki', 'Wiki')
navbar.gsub!('devops', '工作流')
navbar.gsub!('versions', '里程碑')
navbar.gsub!('resources', '资源库')
if change_count > 1
content.sub!('{ifnavbar}', '<br/>')
else
content.sub!('{ifnavbar}', '')
end
content.sub!('{endnavbar}', '')
content.gsub!('{navbar}', navbar)
else
content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '')
end
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, project, change_params)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::SettingChanged"]
end
return '', '', '' if change_params.blank?
owner = project&.owner
title = email_title
title.gsub!('{nickname2}', owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
change_count = change_params.keys.size
# 项目名称更改
if change_params[:name].present?
if change_count > 1
content.sub!('{ifname}', '<br/>')
else
content.sub!('{ifname}', '')
end
content.sub!('{endname}', '')
content.gsub!('{name}', change_params[:name][1])
else
content.gsub!(/({ifname})(.*)({endname})/, '')
end
# 项目标识更改
if change_params[:identifier].present?
if change_count > 1
content.sub!('{ifidentifier}', '<br/>')
else
content.sub!('{ifidentifier}', '')
end
content.sub!('{endidentifier}', '')
content.gsub!('{identifier}', change_params[:identifier][1])
else
content.gsub!(/({ifidentifier})(.*)({endidentifier})/, '')
end
# 项目简介更改
if change_params[:description].present?
if change_params[:description][1].blank?
if change_count > 1
content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介')
else
content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介')
end
else
if change_count > 1
content.sub!('{ifdescription}', '<br/>')
else
content.sub!('{ifdescription}', '')
end
content.sub!('{enddescription}', '')
content.gsub!('{description}', change_params[:description][1])
end
else
content.gsub!(/({ifdescription})(.*)({enddescription})/, '')
end
# 项目类别更改
if change_params[:project_category_id].present?
category = ProjectCategory.find_by_id(change_params[:project_category_id][1])
if category.present?
if change_count > 1
content.sub!('{ifcategory}', '<br/>')
else
content.sub!('{ifcategory}', '')
end
content.sub!('{endcategory}', '')
content.gsub!('{category}', category&.name)
else
if change_count > 1
content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别')
else
content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别')
end
end
else
content.gsub!(/({ifcategory})(.*)({endcategory})/, '')
end
# 项目语言更改
if change_params[:project_language_id].present?
language = ProjectLanguage.find_by_id(change_params[:project_language_id][1])
if language.present?
if change_count > 1
content.sub!('{iflanguage}', '<br/>')
else
content.sub!('{iflanguage}', '')
end
content.sub!('{endlanguage}', '')
content.gsub!('{language}', language&.name)
else
if change_count > 1
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言')
else
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言')
end
end
else
content.gsub!(/({iflanguage})(.*)({endlanguage})/, '')
end
# 项目公私有更改
if change_params[:is_public].present?
permission = change_params[:is_public][1] ? '公有' : '私有'
if change_count > 1
content.sub!('{ifpermission}', '<br/>')
else
content.sub!('{ifpermission}', '')
end
content.sub!('{endpermission}', '')
content.gsub!('{permission}', permission)
else
content.gsub!(/({ifpermission})(.*)({endpermission})/, '')
end
# 项目导航更改
if change_params[:navbar].present?
unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type)
unit_types.delete('code')
unit_types.unshift('代码库')
unit_types.unshift('主页')
unit_types.append('动态')
navbar = unit_types.join('')
navbar.gsub!('issues', '易修')
navbar.gsub!('pulls', '合并请求')
navbar.gsub!('wiki', 'Wiki')
navbar.gsub!('devops', '工作流')
navbar.gsub!('versions', '里程碑')
navbar.gsub!('resources', '资源库')
if change_count > 1
content.sub!('{ifnavbar}', '<br/>')
else
content.sub!('{ifnavbar}', '')
end
content.sub!('{endnavbar}', '')
content.gsub!('{navbar}', navbar)
else
content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '')
end
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我关注的仓库被转移
class MessageTemplate::ProjectTransfer < MessageTemplate
# MessageTemplate::ProjectTransfer.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectTransfer.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我关注的仓库有新的发行版
class MessageTemplate::ProjectVersion < MessageTemplate
# MessageTemplate::ProjectVersion.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectVersion.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,63 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 有新指派给我的合并请求
class MessageTemplate::PullRequestAssigned < MessageTemplate
# MessageTemplate::PullRequestAssigned.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last)
def self.get_message_content(receivers, operator, pull_request)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::PullRequestAssigned"]
end
end
return '', '', '' if receivers.blank?
project = pull_request&.project
owner = project&.owner
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestAssigned.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, pull_request)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::PullRequestAssigned"]
end
project = pull_request&.project
owner = project&.owner
title = email_title
title.gsub!('{nickname1}', operator&.real_name)
title.gsub!('{nickname2}', owner&.real_name)
title.gsub!('{repository}', project&.name)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', pull_request&.title)
content.gsub!('{id}', pull_request&.id.to_s)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::PullRequestAssigned.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,29 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 在合并请求中@我
class MessageTemplate::PullRequestAtme < MessageTemplate
# MessageTemplate::PullRequestAtme.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last)
def self.get_message_content(receivers, operator, pull_request)
project = pull_request&.project
owner = project&.owner
content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', pull_request&.title)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestAtme.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,192 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建或负责的合并请求状态变更
class MessageTemplate::PullRequestChanged < MessageTemplate
# MessageTemplate::PullRequestChanged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last, {assigned_to_id: [nil, 203], priority_id: [2, 4], fixed_version_id: [nil, 5], issue_tags_value: ["", "7"]})
def self.get_message_content(receivers, operator, pull_request, change_params)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["CreateOrAssign::PullRequestChanged"]
end
end
return '', '', '' if receivers.blank?
return '', '', '' if change_params.blank?
project = pull_request&.project
owner = project&.owner
issue = pull_request&.issue
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub("{title}", pull_request&.title)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s)
change_count = change_params.keys.size
# 合并请求审查成员修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end
# 合并请求里程碑修改
if change_params[:fixed_version_id].present?
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
if change_count > 1
content.sub!('{ifmilestone}', '<br/>')
else
content.sub!('{ifmilestone}', '')
end
content.sub!('{endmilestone}', '')
content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑')
content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑')
else
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end
# 合并请求标记修改
if change_params[:issue_tags_value].present?
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",")
tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",")
if change_count > 1
content.sub!('{iftag}', '<br/>')
else
content.sub!('{iftag}', '')
end
content.sub!('{endtag}', '')
content.gsub!('{tag1}', tag1)
content.gsub!('{tag2}', tag2)
else
content.gsub!(/({iftag})(.*)({endtag})()/, '')
end
# 合并请求优先级修改
if change_params[:priority_id].present?
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
if change_count > 1
content.sub!('{ifpriority}', '<br/>')
else
content.sub!('{ifpriority}', '')
end
content.sub!('{ifpriority}', '')
content.sub!('{endpriority}', '')
content.gsub!('{priority1}', priority1&.name)
content.gsub!('{priority2}', priority2&.name)
else
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestChanged.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, pull_request, change_params)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::PullRequestChanged"]
end
project = pull_request&.project
owner = project&.owner
title = email_title
title.gsub!('{title}', pull_request&.title)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', pull_request&.title)
content.gsub!('{id}', pull_request&.id.to_s)
change_count = change_params.keys.size
# 合并请求审查成员修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end
# 合并请求里程碑修改
if change_params[:fixed_version_id].present?
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
if change_count > 1
content.sub!('{ifmilestone}', '<br/>')
else
content.sub!('{ifmilestone}', '')
end
content.sub!('{endmilestone}', '')
content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑')
content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑')
else
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end
# 合并请求标记修改
if change_params[:issue_tags_value].present?
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",")
tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",")
if change_count > 1
content.sub!('{iftag}', '<br/>')
else
content.sub!('{iftag}', '')
end
content.sub!('{endtag}', '')
content.gsub!('{tag1}', tag1)
content.gsub!('{tag2}', tag2)
else
content.gsub!(/({iftag})(.*)({endtag})()/, '')
end
# 合并请求优先级修改
if change_params[:priority_id].present?
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
if change_count > 1
content.sub!('{ifpriority}', '<br/>')
else
content.sub!('{ifpriority}', '')
end
content.sub!('{ifpriority}', '')
content.sub!('{endpriority}', '')
content.gsub!('{priority1}', priority1&.name)
content.gsub!('{priority2}', priority2&.name)
else
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::PullRequestChanged.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,61 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建或负责的合并请求被关闭
class MessageTemplate::PullRequestClosed < MessageTemplate
# MessageTemplate::PullRequestClosed.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last)
def self.get_message_content(receivers, operator, pull_request)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["CreateOrAssign::PullRequestChanged"]
end
end
return '', '', '' if receivers.blank?
project = pull_request&.project
owner = project&.owner
content = sys_notice.gsub('{title}', pull_request&.title)
url = notification_url
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestClosed.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, pull_request)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::PullRequestChanged"]
end
project = pull_request&.project
owner = project&.owner
title = email_title
title.gsub!('{title}', pull_request&.title)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', pull_request&.title)
content.gsub!('{id}', pull_request&.id.to_s)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::PullRequestClosed.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# TODO 我创建或负责的合并请求有新的评论
class MessageTemplate::PullRequestJournal < MessageTemplate
# MessageTemplate::PullRequestJournal.get_message_content(User.where(login: 'yystopf'))
def self.get_message_content(receivers)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestJournal.get_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,61 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
# 我创建或负责的合并请求被合并
class MessageTemplate::PullRequestMerged < MessageTemplate
# MessageTemplate::PullRequestMerged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last)
def self.get_message_content(receivers, operator, pull_request)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["CreateOrAssign::PullRequestChanged"]
end
end
return '', '', '' if receivers.blank?
project = pull_request&.project
owner = project&.owner
content = sys_notice.gsub('{title}', pull_request&.title)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::PullRequestMerged.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, operator, pull_request)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::PullRequestChanged"]
end
project = pull_request&.project
owner = project&.owner
title = email_title
title.gsub!('{title}', pull_request&.title)
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{login1}', operator&.login)
content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', pull_request&.title)
content.gsub!('{id}', pull_request&.id.to_s)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::PullRequestMerged.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -18,7 +18,7 @@ class Mirror < ApplicationRecord
# 0: 同步镜像成功1: 正在同步镜像2: 同步失败; 默认值为0
enum status: { succeeded: 0, waiting: 1, failed: 2 }
after_update :websocket_boardcast, if: :saved_change_to_status?
# after_update :websocket_boardcast, if: :saved_change_to_status?
belongs_to :repository, foreign_key: :repo_id

View File

@ -22,6 +22,9 @@ class OrganizationUser < ApplicationRecord
validates :user_id, uniqueness: {scope: :organization_id}
after_create :send_create_message_to_notice_system
after_destroy :send_destroy_message_to_notice_system
def self.build(organization_id, user_id)
org_user = self.find_by(organization_id: organization_id, user_id: user_id)
return org_user unless org_user.nil?
@ -31,4 +34,12 @@ class OrganizationUser < ApplicationRecord
def teams
organization.teams.joins(:team_users).where(team_users: {user_id: user_id})
end
def send_create_message_to_notice_system
SendTemplateMessageJob.perform_later('OrganizationJoined', self.user_id, self.organization_id) if Site.has_notice_menu?
end
def send_destroy_message_to_notice_system
SendTemplateMessageJob.perform_later('OrganizationLeft', self.user_id, self.organization_id) if Site.has_notice_menu?
end
end

View File

@ -125,8 +125,8 @@ class Project < ApplicationRecord
has_many :has_pinned_users, through: :pinned_projects, source: :user
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
after_save :check_project_members, :reset_cache_data
before_save :set_invite_code
after_save :check_project_members
before_save :set_invite_code, :reset_cache_data, :reset_unmember_followed
after_destroy :reset_cache_data
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
@ -135,6 +135,18 @@ class Project < ApplicationRecord
delegate :content, to: :project_detail, allow_nil: true
delegate :name, to: :license, prefix: true, allow_nil: true
def self.all_visible(user_id=nil)
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
org_public_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'common'})).to_sql
if user_id.present?
org_limit_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'limited'})).to_sql
org_privacy_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension, :organization_users).where(organization_extensions: {visibility: 'privacy'}, organization_users: {user_id: user_id})).to_sql
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } UNION #{ org_limit_projects_sql } UNION #{org_privacy_projects_sql} ) AS projects").visible
else
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } ) AS projects").visible
end
end
def reset_cache_data
if changes[:user_id].present?
first_owner = Owner.find_by_id(changes[:user_id].first)
@ -144,6 +156,12 @@ class Project < ApplicationRecord
self.reset_user_cache_async_job(self.owner)
end
def reset_unmember_followed
if changes[:is_public].present? && changes[:is_public] == [true, false]
self.watchers.where.not(user_id: self.all_collaborators).destroy_all
end
end
def set_invite_code
if self.invite_code.nil?
self.invite_code= self.generate_dcode('invite_code', 6)

View File

@ -20,6 +20,7 @@
class ProjectTrend < ApplicationRecord
CLOSE = 'close'
CREATE = 'create'
MERGE = 'merge'
belongs_to :project
belongs_to :trend, polymorphic: true, optional: true

View File

@ -32,9 +32,13 @@ class ProjectUnit < ApplicationRecord
types.delete("pulls") if project.sync_mirror?
# 默认code类型自动创建
types << "code"
before_units = project.project_units.pluck(:unit_type).sort
project.project_units.where.not(unit_type: types).each(&:destroy!)
types.each do |type|
project.project_units.find_or_create_by!(unit_type: type)
end
after_units = project.project_units.pluck(:unit_type).sort
return before_units, after_units
end
end

View File

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

View File

@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: system_notifications
#
# id :integer not null, primary key
# subject :string(255)
# sub_subject :string(255)
# content :text(65535)
# is_top :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
class SystemNotification < ApplicationRecord
default_scope { order(created_at: :desc)}
scope :is_top, lambda { where(is_top: true) }
end

View File

@ -54,4 +54,15 @@ class Team < ApplicationRecord
team_users.where(user_id: user_id).present?
end
def authorize_name
case self.authorize
when 'read' then '报告者'
when 'write' then '开发者'
when 'admin' then '管理员'
when 'owner' then '拥有者'
else
''
end
end
end

View File

@ -0,0 +1,30 @@
# == Schema Information
#
# Table name: template_message_settings
#
# id :integer not null, primary key
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
class TemplateMessageSetting < ApplicationRecord
scope :openning, ->() {where(openning: true)}
def self.type_name
""
end
def self.build_init_data
TemplateMessageSetting::CreateOrAssign.build_init_data
TemplateMessageSetting::ManageProject.build_init_data
TemplateMessageSetting::Normal.build_init_data
TemplateMessageSetting::WatchProject.build_init_data
end
end

View File

@ -0,0 +1,31 @@
# == Schema Information
#
# Table name: template_message_settings
#
# id :integer not null, primary key
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
#我创建的或负责的
class TemplateMessageSetting::CreateOrAssign < TemplateMessageSetting
def self.type_name
"我创建的或负责的"
end
def self.order_index
20
end
def self.build_init_data
self.find_or_create_by(name: "易修状态变更", key: "IssueChanged")
self.find_or_create_by(name: "合并请求状态变更", key: "PullRequestChanged")
end
end

View File

@ -0,0 +1,33 @@
# == Schema Information
#
# Table name: template_message_settings
#
# id :integer not null, primary key
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
#我管理的
class TemplateMessageSetting::ManageProject < TemplateMessageSetting
def self.type_name
"我管理的仓库"
end
def self.order_index
30
end
def self.build_init_data
self.find_or_create_by(name: "有新的易修", key: "Issue")
self.find_or_create_by(name: "有新的合并请求", key: "PullRequest")
self.find_or_create_by(name: "有成员变动", key: "Member")
self.find_or_create_by(name: "仓库设置被更改", key: "SettingChanged")
end
end

View File

@ -0,0 +1,33 @@
# == Schema Information
#
# Table name: template_message_settings
#
# id :integer not null, primary key
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
class TemplateMessageSetting::Normal < TemplateMessageSetting
def self.type_name
"我的状态"
end
def self.order_index
10
end
def self.build_init_data
self.find_or_create_by(name: "账号有权限变更", key: "Permission")
self.find_or_create_by(name: "被拉入或移出组织", key: "Organization")
self.find_or_create_by(name: "被拉入或移出项目", key: "Project")
self.find_or_create_by(name: "有新的易修指派给我", key: "IssueAssigned")
self.find_or_create_by(name: "有新的合并请求指派给我", key: "PullRequestAssigned")
end
end

View File

@ -0,0 +1,29 @@
# == Schema Information
#
# Table name: template_message_settings
#
# id :integer not null, primary key
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
#我关注的
class TemplateMessageSetting::WatchProject < TemplateMessageSetting
def self.type_name
"我关注的仓库"
end
def self.order_index
40
end
def self.build_init_data
end
end

View File

@ -171,6 +171,8 @@ class User < Owner
has_many :pull_requests, dependent: :destroy
has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy
has_one :user_template_message_setting, dependent: :destroy
# Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) }
scope :like, lambda { |keywords|
@ -186,7 +188,7 @@ class User < Owner
:show_email, :show_location, :show_department,
:technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true
before_save :update_hashed_password, :set_lastname, :set_profile_completed
before_save :update_hashed_password, :set_lastname
after_create do
SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie?
end
@ -757,6 +759,10 @@ class User < Owner
laboratory_id.present? && laboratory_id != 1
end
def profile_is_completed?
self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
end
protected
def validate_password_length
# 管理员的初始密码是5位
@ -783,10 +789,6 @@ class User < Owner
def set_lastname
self.lastname = self.nickname if changes[:nickname].present?
end
def set_profile_completed
self.profile_completed = self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
end
end

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