Compare commits

..

239 Commits

Author SHA1 Message Date
yystopf 09f0341883 新增: es配置 2022-06-15 18:16:44 +08:00
xiaoxiaoqiong 66c40d4791 fixed gitea接口返回判断 2022-06-15 11:16:08 +08:00
yystopf ce467736a7 修复: readme无法正常跳转目录的问题 2022-06-13 12:53:40 +08:00
yystopf 3e4dd90e17 修复: 用户名称展示时只去掉首末的空格 2022-06-08 10:46:55 +08:00
yystopf 8ae5587516 fix: search name use strip 2022-06-08 10:37:31 +08:00
xiaoxiaoqiong 0b543f7dda 通知邮件支持用户不存在时发送base_url 2022-06-01 16:08:20 +08:00
xiaoxiaoqiong a07204111a 通知邮件支持用户不存在时发送 2022-06-01 15:24:39 +08:00
yystopf 038df804c0 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-06-01 10:01:15 +08:00
yystopf 877948b0cd 新增: 通用消息模板后台创建 2022-06-01 10:00:57 +08:00
xiaoxiaoqiong 9a17c4865f 项目名称和描述增加敏感词检测 2022-06-01 09:27:18 +08:00
yystopf 9427db3e5a 新增: 通用消息模板 2022-05-31 16:34:08 +08:00
yystopf 81da71d478 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-05-30 14:50:23 +08:00
yystopf 169dc84e22 新增: 组织下项目需返回是否为公有项目字段 2022-05-30 14:50:12 +08:00
xiaoxiaoqiong d6fd85f536 Repository.url重写,导入项目时为空 2022-05-30 11:18:24 +08:00
xiaoxiaoqiong 6448a30e03 render_error替换成tip_exception 2022-05-30 10:25:43 +08:00
xiaoxiaoqiong 17fb43cea8 render_error替换成tip_exception 2022-05-30 10:24:39 +08:00
yystopf a6e50d2a25 修复 devops无法激活项目的问题 2022-05-27 10:48:20 +08:00
yystopf bd16ca476d 增加: 退出仓库api文档 2022-05-26 15:08:42 +08:00
yystopf 2ea78b4f20 增加: 已登录用户对用户名、邮箱、电话进行校验 2022-05-25 11:47:35 +08:00
yystopf e36c7a4b6a 修复: 邮箱搜索不需要return 404 2022-05-24 18:09:36 +08:00
yystopf 8e8ec821f2 新增: 根据邮箱来获取用户 2022-05-24 17:26:10 +08:00
yystopf 5cf257c3cc Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-05-24 11:45:53 +08:00
yystopf aa18fe0ad4 修复: 转移项目时新接受者需要移除原来的权限角色 2022-05-24 11:44:05 +08:00
yystopf 1358c23ca6 fix: trasfer project member must remove old permission 2022-05-24 11:43:47 +08:00
yystopf c27cc063e6 add: new update user info simple and sync gitea 2022-05-24 10:59:52 +08:00
yystopf b0092487e6 fix: is readme use regex 2022-05-23 18:10:41 +08:00
yystopf fbebd0a623 fix 2022-05-23 09:27:09 +08:00
yystopf fe23c2afbf fix: replace content next if blank 2022-05-21 16:45:42 +08:00
yystopf 779c86108a fix: readme relative delay and replace_content 2022-05-20 17:00:02 +08:00
yystopf 83e43f0c97 add: new readme delay function 2022-05-20 11:43:22 +08:00
yystopf e237fd46f7 fix: not found user return 404 2022-05-18 11:37:23 +08:00
yystopf ca3c564529 fix: not found user return 404 2022-05-18 11:03:39 +08:00
yystopf 9cd18397f7 fix: import user login length required 2022-05-18 10:11:09 +08:00
yystopf 77620f7735 add: download and import user template xlsx 2022-05-16 16:59:25 +08:00
yystopf 50dc5cce5d fix 2022-05-07 14:06:48 +08:00
yystopf a6cee63d17 fix: change owner must fix foreign_key 2022-05-07 11:57:58 +08:00
yystopf 000197b0d1 fix: issues and pull_request length calculate 2022-05-06 17:25:34 +08:00
yystopf 6aa3321d17 fix: pr title description validate 2022-05-06 14:29:05 +08:00
yystopf d44308fc82 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-05-06 09:56:38 +08:00
yystopf ae7d0d1329 add: issues description and journals notes validate 2022-05-06 09:56:22 +08:00
xiaoxiaoqiong 55c74de8e4 fork_users加入组织 2022-05-05 10:41:02 +08:00
yystopf 7c88ea3d67 add: quit repo 2022-05-05 10:00:02 +08:00
yystopf f15cd44dff add: compare add paginate 2022-04-28 18:53:33 +08:00
yystopf 3abd6037d9 fix: show super description aways desplay 2022-04-28 11:12:16 +08:00
yystopf ec3a556a6f fix: default value for show super description 2022-04-28 11:03:42 +08:00
yystopf 793cbb372a Merge pull request '用户新增个人简介markdown编辑字段' (#8) from yystopf/forgeplus:hh_develop into develop 2022-04-28 10:53:06 +08:00
yystopf 396ac55429 add: user super description 2022-04-28 10:42:55 +08:00
yystopf 088c617cc1 add: name query for branches 2022-04-26 17:15:59 +08:00
yystopf fc3cf01d3f add: get user image action 2022-04-18 13:49:08 +08:00
yystopf 8f5bb0e2d9 fix: organization gitea_token read by associations 2022-04-18 10:52:48 +08:00
yystopf 2dfd69ae21 fix: response data result 2022-04-11 16:08:50 +08:00
yystopf 720c073f32 fix 2022-04-11 15:48:47 +08:00
yystopf 0076468a15 fix: trace client request data 2022-04-11 15:30:28 +08:00
yystopf 910ae48556 fix: exception to ex 2022-04-11 10:50:18 +08:00
yystopf eac7331070 fix: settings need prefix 2022-04-08 15:03:40 +08:00
yystopf 551f333261 fix 2022-04-08 14:52:56 +08:00
yystopf dec264d169 fix: sync user pwd 2022-04-07 16:28:40 +08:00
yystopf 7055974443 fix 2022-04-06 17:04:31 +08:00
yystopf 3536918938 fix 2022-03-31 16:18:16 +08:00
yystopf 56278b84f2 Merge pull request '导航增加动态用户数据获取' (#3) from hh_develop_navbar into develop 2022-03-31 16:08:36 +08:00
yystopf 882a50cf56 add: setting navbar varible 2022-03-31 16:04:48 +08:00
yystopf db4031b8bf fix 2022-03-31 14:24:47 +08:00
yystopf ecfc39565c fix 2022-03-31 13:18:38 +08:00
yystopf 9ced678f91 fix: user trace token 2022-03-31 13:03:54 +08:00
yystopf 7951ca28d5 Merge pull request '代码溯源service封装' (#2) from hh_develop into develop 2022-03-31 12:59:34 +08:00
yystopf 4bbb843edf add: trace users and get trace token 2022-03-31 12:54:39 +08:00
yystopf 747646cd9d add: trace client and api completed 2022-03-30 16:19:32 +08:00
yystopf d0d906d04c fix: readme image regex error rescued 2022-03-28 11:05:21 +08:00
yystopf bc639488aa fix: issues filter error 2022-03-22 10:45:14 +08:00
xiaoxiaoqiong 99fbecc834 gitea 请求延长到20分钟 2022-03-11 14:06:12 +08:00
yystopf 8d0a6d267a fix: download escape 2022-03-10 10:47:06 +08:00
yystopf b1c03ed5e8 fix: activity issues must only issue 2022-03-10 09:51:46 +08:00
yystopf ef12f85687 fix: create pull request valid merge_user_login 2022-03-07 11:17:10 +08:00
yystopf e120c4dac2 add: origin repository need open pr menu 2022-03-07 10:53:07 +08:00
yystopf e1cf2fcdeb fix: owner project not allow repeat name 2022-03-07 10:25:05 +08:00
yystopf c4f380873e fix: is public project attachment allow is not member read 2022-03-07 10:20:51 +08:00
yystopf 5cb2e55f74 add: organization users insist team nickname search 2022-03-07 09:58:05 +08:00
xiaoxiaoqiong 1dd3fbc69a fixed fork列表中存在组织时显示错误 2022-03-03 14:16:57 +08:00
yystopf b97c42d0ae fix: email logo 2022-03-02 10:33:35 +08:00
yystopf a2612d8009 fix 2022-02-24 18:09:11 +08:00
yystopf 2f2655525f fix: user rank user_id must exist 2022-02-24 18:07:18 +08:00
yystopf 1a93477635 fix: forked templete delay 2022-02-24 14:26:04 +08:00
yystopf 7c664addbd fix 2022-02-22 11:03:28 +08:00
yystopf c6b79f82bc fix: change password new version 2022-02-22 10:03:51 +08:00
xiaoxiaoqiong 4e3f9cc019 竞赛通知任务调度 2022-02-21 16:48:59 +08:00
xiaoxiaoqiong 5ed7b3e4ad 竞赛通知任务调度 2022-02-21 16:46:40 +08:00
xiaoxiaoqiong 4e2c46260c Merge remote-tracking branch 'origin/develop' into develop 2022-02-17 18:28:40 +08:00
xiaoxiaoqiong 9ba00b21c9 竞赛通知api 2022-02-17 18:28:32 +08:00
yystopf b11f5fd228 fix: cache rollback 2022-02-17 11:12:50 +08:00
yystopf 90dbe0730a fix: job not affect 2022-02-17 10:59:18 +08:00
yystopf d6633cb73a fix 2022-02-17 09:43:44 +08:00
yystopf a7a6abd22a fix: add rule for issue expire 2022-02-17 09:40:44 +08:00
yystopf c956667ce0 fix 2022-02-17 09:36:49 +08:00
yystopf 5701c818ed fix 2022-02-16 15:10:10 +08:00
yystopf 1ac2ddfaa5 fix: default setting for new template message 2022-02-16 11:46:34 +08:00
yystopf 4aac05d4e1 fix: build user template message data must fronted 2022-02-16 11:17:03 +08:00
yystopf 84b56bfcb8 fix: project milestone create notice template 2022-02-16 09:34:31 +08:00
yystopf 7485564bb9 add: template message platform varible 2022-02-15 18:30:13 +08:00
yystopf b5acf2308a Merge pull request '新增站内信以及里程碑完成度修复' (#299) from yystopf/forgeplus:develop into develop 2022-02-15 17:33:30 +08:00
yystopf e3f4313c80 fix 2022-02-15 17:29:13 +08:00
yystopf b223abe229 fix: init data 2022-02-15 17:26:46 +08:00
yystopf b3bede308c add: some new message rules 2022-02-15 17:13:06 +08:00
xiaoxiaoqiong 2f170a54c6 fixed setting编辑类型下拉选中 2022-02-15 17:10:57 +08:00
yystopf 22293572ac fix: issue changed about version callback 2022-02-14 17:02:59 +08:00
xiaoxiaoqiong 8720cab1e9 通过配置确定github克隆方式 2022-02-14 16:53:29 +08:00
yystopf 959c1e8d95 add: user profile setting message 2022-02-14 13:55:34 +08:00
yystopf 29dc3fff39 fix: migrate use old rule 2022-02-11 16:27:22 +08:00
yystopf 298abdd1b1 fix: devops organization bug 2022-02-10 14:08:14 +08:00
yystopf 26f87fba16 fix: edit transfer need change fork info 2022-01-25 14:26:11 +08:00
yystopf 1e9a32a93e fix: issues select count paginator 2022-01-25 11:39:06 +08:00
yystopf 2dc79052c2 fix: create project trend when status is closed 2022-01-25 10:34:20 +08:00
yystopf 380ca3a066 fix: projects query rule 2022-01-24 14:26:24 +08:00
yystopf 237b0afb08 fix: team user build use find or create by 2022-01-24 10:44:46 +08:00
yystopf e14936e820 fix: issues select count 2022-01-24 10:00:44 +08:00
yystopf 655c85851f Merge branch 'develop' of https://git.trustie.net/Gitlink/forgeplus into develop 2022-01-21 18:20:40 +08:00
yystopf 1c7e414aa4 fix: owner allow nil 2022-01-21 18:19:43 +08:00
yystopf 099fc52e00 fix: contributor error rescue 2022-01-21 18:19:34 +08:00
yystopf 490957ec3b fix: contributor error rescue 2022-01-21 18:19:27 +08:00
yystopf b1884d30d5 fix: detail result delay 2022-01-21 18:19:06 +08:00
xiaoxiaoqiong 98d8ee1fb6 Merge remote-tracking branch 'origin/develop' into develop 2022-01-21 15:50:41 +08:00
xiaoxiaoqiong 2ca77732c8 fixed 注册登录类型 2022-01-21 15:50:37 +08:00
yystopf 70d22f7c4f fix: create team overflow tip 2022-01-14 16:09:38 +08:00
yystopf 25d0e784bb fix: pr assignee info use array 2022-01-14 16:00:59 +08:00
yystopf 5d45b24299 fix: devops return result changed 2022-01-14 10:55:53 +08:00
yystopf b6b8befde7 fix: pr update must edit assignee login 2022-01-14 10:55:01 +08:00
yystopf f33b9559cd fix: download delay 2022-01-13 11:24:27 +08:00
yystopf f9bc2258ec fix: migrate repo github use another addr 2022-01-11 10:48:29 +08:00
yystopf 2a09ced1ce fix: branches use branch name api 2022-01-07 15:41:50 +08:00
yystopf 7a1e6cfbad fix: issue edit and new branches only load name api 2022-01-07 15:19:10 +08:00
yystopf 47d1f727ce fix: create team count limit 2022-01-06 17:38:44 +08:00
yystopf a7665df0ea fix: download file url use cgi escape 2022-01-06 15:04:59 +08:00
yystopf 84f12adce8 fix: webhook tasks list error delay 2022-01-06 14:29:31 +08:00
yystopf 7fde1e0e12 fix: webhook field changed 2022-01-06 11:10:49 +08:00
yystopf 499734ebf9 fix: upload user image allow base64 2022-01-04 22:44:39 +08:00
yystopf f339df699e add: user upload image 2022-01-03 22:32:09 +08:00
yystopf cfd94cb3b7 fix: migrate repo username nil is excepted 2022-01-03 20:33:11 +08:00
yystopf 43e0617429 fix: webhook field changed 2021-12-30 09:47:12 +08:00
yystopf d6b66d5324 fix 2021-12-29 09:56:49 +08:00
yystopf 0c1df3b2cb fix 2021-12-29 09:53:14 +08:00
yystopf fa86d3ea10 fix: branch delay 2021-12-29 09:50:57 +08:00
yystopf 8c99b754fb fix: create pr branch name escape 2021-12-28 18:37:44 +08:00
yystopf f3cf2c87c9 fix: create pr branch name escape 2021-12-28 18:29:58 +08:00
yystopf 8e4e6fc0ac Merge pull request '1224里程碑、1231里程碑内容' (#296) from yystopf/forgeplus:develop into develop 2021-12-28 16:09:45 +08:00
yystopf 75f3166ffa fix 2021-12-28 14:45:12 +08:00
yystopf 04bf423fcb fix 2021-12-28 14:42:55 +08:00
yystopf 51e8c9d908 fix: compare use url escape 2021-12-28 14:22:06 +08:00
yystopf 4304a35b80 fix 2021-12-28 11:07:40 +08:00
yystopf 076375633a fix 2021-12-27 17:55:02 +08:00
yystopf dbf5e711a5 fix 2021-12-27 17:44:08 +08:00
yystopf 4432e65683 fix: operate issue permission reset 2021-12-27 17:32:35 +08:00
yystopf dcf44a78f0 fix: unvalid branch name return error 2021-12-27 16:34:54 +08:00
yystopf 12edc620df fix: complete profile condition 2021-12-24 16:15:59 +08:00
yystopf 4ce03145df fix 2021-12-23 14:33:31 +08:00
yystopf 3e04a37ece add: team remove and joined template message 2021-12-23 14:26:40 +08:00
yystopf 78f464ccba fix: escape 2021-12-23 10:37:57 +08:00
yystopf 64423f1999 fix 2021-12-22 18:16:39 +08:00
yystopf 05c3f60dab fix 2021-12-22 18:08:10 +08:00
yystopf 0083ef33cb fix 2021-12-22 16:03:23 +08:00
yystopf 36b68df273 fix: remote register validate 2021-12-22 14:39:47 +08:00
yystopf e1a5918c22 add: project trends project info 2021-12-22 13:57:02 +08:00
yystopf 26ae9b35df fix: change member role and change team user team 2021-12-22 11:32:40 +08:00
yystopf 8e79b43aaf add: member bind team user 2021-12-22 11:16:27 +08:00
yystopf d28eba6423 fix: create org error 2021-12-21 15:16:38 +08:00
yystopf 688be1bb7d fix: return issue version id 2021-12-21 15:16:38 +08:00
yystopf df69dee282 fix: some error for read raw data 2021-12-21 15:14:10 +08:00
yystopf 45a77e5c07 fix: readme private file path use authorize 2021-12-21 14:24:27 +08:00
yystopf 7849bd0ebf fix: remove pr permission 2021-12-21 10:16:29 +08:00
yystopf 3649bf1fd0 fix 2021-12-20 15:53:24 +08:00
yystopf 6ffc2938a1 fix: download file url escape 2021-12-20 15:39:33 +08:00
yystopf aa60de1dac fix: valid pr title length 2021-12-20 15:38:08 +08:00
yystopf 29f98513e2 fix: org update error 2021-12-20 15:38:08 +08:00
yystopf e35cdf39fb fix: login password validate 2021-12-20 15:34:55 +08:00
yystopf e51b86538b Merge pull request '更改易修为疑修' (#292) from yystopf/forgeplus:develop into develop 2021-12-17 15:44:20 +08:00
yystopf da4fd3a762 fix: 易修 to 疑修 2021-12-17 15:35:30 +08:00
xiaoxiaoqiong efc82b9841 fix: issue is collaborators 2021-12-14 10:17:15 +08:00
yystopf e3df503dd2 fix 2021-12-14 10:13:28 +08:00
yystopf 6a2ad67386 fix 2021-12-14 09:53:54 +08:00
yystopf 3d12db3a07 fix: atme service use perform later 2021-12-14 09:39:26 +08:00
yystopf 1faaf1d7d1 fix: project menu list wiki location 2021-12-13 11:45:58 +08:00
yystopf f8a6f62342 fix: project rank include educoder 2021-12-10 09:35:03 +08:00
yystopf 66d1246a6c fix: educoder project menu return 2021-12-09 15:54:21 +08:00
yystopf f79beef3f9 fix: issues branch educoder use master 2021-12-09 14:33:46 +08:00
yystopf 81e6691632 fix: educoder entries image file type 2021-12-09 11:33:43 +08:00
yystopf 38d6519381 fix 2021-12-09 11:08:54 +08:00
yystopf 16418675ac fix 2021-12-09 11:08:10 +08:00
yystopf 102858bc8c fix: educoder entries file use hash 2021-12-09 11:06:49 +08:00
yystopf 0d64768e4b fix: educoder file visit delay 2021-12-09 09:37:28 +08:00
yystopf beccac652f fix 2021-12-08 18:25:31 +08:00
yystopf 30eb1958c1 fix 2021-12-08 18:23:29 +08:00
yystopf 33e17e8439 fix: educoder sub_entries and commit author 2021-12-08 18:18:19 +08:00
yystopf e0c47c2abd fix: educoder clone url 2021-12-08 16:18:13 +08:00
yystopf 422549f9e7 fix 2021-12-08 15:01:33 +08:00
yystopf 0358229b95 fix: educoder api delay 2021-12-08 14:47:15 +08:00
yystopf c4586fbb36 fix: remove detail language and contributors 2021-12-08 14:11:37 +08:00
xiaoxiaoqiong f94006abfd fixed educode not owner 2021-12-07 16:59:04 +08:00
xiaoxiaoqiong 4d61e7618a fixed detail 2021-12-07 16:46:06 +08:00
xiaoxiaoqiong 36286d9003 fixed:educode项目 2021-12-07 16:20:05 +08:00
yystopf 51356da7f3 fix: owners not return 404 2021-12-07 14:34:57 +08:00
yystopf ebe893022f fix: api doc logo 2021-12-07 14:34:57 +08:00
yystopf c5f22e6c70 fix: org delete status error 2021-12-07 14:34:57 +08:00
xiaoxiaoqiong 922561afb1 项目精选加索引 2021-12-01 17:20:52 +08:00
yystopf 6f7899d16f fix: create pr authorize tip 2021-11-30 20:23:37 +08:00
yystopf 4e3c8e414c fix 2021-11-30 15:36:51 +08:00
yystopf d588a78f62 fix: locales for projects update form 2021-11-30 15:35:36 +08:00
yystopf a7d681c4dd fix: compare commit author image url 2021-11-30 15:03:55 +08:00
yystopf 7a93db9ed2 fix: labels limit and issues operate field 2021-11-30 13:58:51 +08:00
yystopf 74e5fa0e31 fix: fork project id validate 2021-11-29 17:01:39 +08:00
yystopf de995c8714 fix: merge conflict 2021-11-29 15:43:47 +08:00
yystopf ea156cec7e fix: download type add video type 2021-11-29 15:33:09 +08:00
yystopf 7499d8af89 fix: project private params to boolean 2021-11-29 14:43:29 +08:00
yystopf f8654edc3b fix: project labels return success info 2021-11-29 14:28:13 +08:00
yystopf d16f290aa6 fix: create pr validate fork_project_id 2021-11-29 14:17:27 +08:00
yystopf 9385d346f1 fix 2021-11-29 14:03:17 +08:00
yystopf 22f3371090 fix: change issues priority id default value 2021-11-29 11:05:33 +08:00
yystopf c0a4f8f4ec fix: create pull request need compare 2021-11-29 10:53:59 +08:00
yystopf 7586a0fb21 fix: change issue tag change size 2021-11-29 10:27:41 +08:00
yystopf c0e3a91a46 fix: page 500 2021-11-29 09:32:39 +08:00
xiaoxiaoqiong 7ebd8681fa 500页面样式调整 2021-11-26 09:49:13 +08:00
xxq250 72553dec57 Merge pull request '一些功能修改以及bug修复' (#263) from yystopf/forgeplus:hh_hotfix into develop 2021-11-26 09:39:58 +08:00
yystopf dee68808b1 fix 2021-11-25 17:37:05 +08:00
yystopf 96d7917bbf fix: change 500 html 2021-11-25 17:34:21 +08:00
yystopf abca0fe432 fix: change pr path id to number 2021-11-25 15:08:59 +08:00
yystopf d7612a0921 add: create update pr need authorize 2021-11-25 14:16:45 +08:00
yystopf c54950a95f fix: compare params contain .json 2021-11-25 14:06:55 +08:00
yystopf be0f68cede fix 2021-11-25 11:19:50 +08:00
yystopf 1b92b53099 fix 2021-11-25 11:00:19 +08:00
yystopf 5634413cac add: create pullrequest validate 2021-11-25 10:52:42 +08:00
yystopf 1a9ed1425e fix: destroy decrement forked count 2021-11-23 13:48:09 +08:00
yystopf f9d4316a8e fix: change fork project status 2021-11-23 11:43:44 +08:00
yystopf 6f7f815fd4 fix: change warn image 2021-11-19 15:15:40 +08:00
yystopf ddb826733b fix: project setting permission control 2021-11-19 14:56:20 +08:00
yystopf 1f989d0a37 fix: delete organization tip 2021-11-19 14:44:25 +08:00
yystopf d63626424e Merge pull request '更改邮件默认发送规则' (#251) from yystopf/forgeplus:hh_email_fix into develop 2021-11-19 10:38:04 +08:00
yystopf 55ab694505 fix: change email default rule 2021-11-19 10:21:09 +08:00
yystopf 0885575cc4 fix: organization validate name tip 2021-11-18 17:31:22 +08:00
yystopf a188648287 fix: qq qun url 2021-11-18 17:25:50 +08:00
yystopf 8011dabaac fix: undo events 2021-11-18 17:02:09 +08:00
yystopf 88a08e73c0 fix: web icon 2021-11-18 16:13:33 +08:00
yystopf 6713f9b280 fix: pullrequest trend action name 2021-11-17 11:04:15 +08:00
271 changed files with 5410 additions and 3432 deletions

View File

View File

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

View File

@ -128,3 +128,6 @@ gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1' gem 'parallel', '~> 1.19', '>= 1.19.1'
gem 'letter_avatar' gem 'letter_avatar'
gem 'elasticsearch-model', github: 'elastic/elasticsearch-rails', branch: 'main'
gem 'elasticsearch-rails', github: 'elastic/elasticsearch-rails', branch: 'main'

View File

@ -1,3 +1,14 @@
GIT
remote: https://github.com/elastic/elasticsearch-rails.git
revision: b66fe71cc4b9b10069bf6d39dbbfcc0b117a08a5
branch: main
specs:
elasticsearch-model (7.2.1)
activesupport (> 3)
elasticsearch (~> 7)
hashie
elasticsearch-rails (7.2.1)
GEM GEM
remote: https://gems.ruby-china.com/ remote: https://gems.ruby-china.com/
specs: specs:
@ -450,6 +461,8 @@ DEPENDENCIES
chromedriver-helper chromedriver-helper
deep_cloneable (~> 3.0.0) deep_cloneable (~> 3.0.0)
diffy diffy
elasticsearch-model!
elasticsearch-rails!
enumerize enumerize
faraday (~> 0.15.4) faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0) font-awesome-sass (= 4.7.0)

View File

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

View File

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

View File

@ -2,8 +2,24 @@ class Admins::MessageTemplatesController < Admins::BaseController
before_action :get_template, only: [:edit, :update, :destroy] before_action :get_template, only: [:edit, :update, :destroy]
def index def index
message_templates = MessageTemplate.group(:type).count.keys message_templates = MessageTemplate.ransack(sys_notice_or_email_or_email_title_cont: params[:search]).result
@message_templates = kaminari_array_paginate(message_templates) @message_templates = kaminari_paginate(message_templates)
end
def new
@message_template = MessageTemplate::CustomTip.new
end
def create
@message_template = MessageTemplate::CustomTip.new(ignore_params)
if @message_template.save!
redirect_to admins_message_templates_path
flash[:success] = "创建消息模板成功"
else
render :new
flash[:danger] = "创建消息模板失败"
end
end end
def edit def edit

View File

@ -265,9 +265,9 @@ class ApplicationController < ActionController::Base
end end
end end
if !User.current.logged? && Rails.env.development? # if !User.current.logged? && Rails.env.development?
User.current = User.find 104 # User.current = User.find 1
end # end
# 测试版前端需求 # 测试版前端需求
@ -709,14 +709,20 @@ class ApplicationController < ActionController::Base
Rails.application.config_for(:configuration)['platform_url'] || request.base_url Rails.application.config_for(:configuration)['platform_url'] || request.base_url
end end
def image_type?(str)
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
default_type.include?(str&.downcase)
end
def convert_image! def convert_image!
@image = params[:image] @image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image @image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
return unless @image.present? return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile if @image.class == ActionDispatch::Http::UploadedFile
render_error('请上传文件') if @image.size.zero? return render_error('请上传文件') if @image.size.zero?
render_error('文件大小超过限制') if @image.size > max_size.to_i return render_error('文件大小超过限制') if @image.size > max_size.to_i
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
else else
image = @image.to_s.strip image = @image.to_s.strip
return render_error('请上传正确的图片') if image.blank? return render_error('请上传正确的图片') if image.blank?

View File

@ -217,7 +217,7 @@ class AttachmentsController < ApplicationController
if @file.container && current_user.logged? if @file.container && current_user.logged?
if @file.container.is_a?(Issue) if @file.container.is_a?(Issue)
course = @file.container.project course = @file.container.project
candown = course.member?(current_user) candown = course.member?(current_user) || course.is_public
elsif @file.container.is_a?(Journal) elsif @file.container.is_a?(Journal)
course = @file.container.issue.project course = @file.container.issue.project
candown = course.member?(current_user) candown = course.member?(current_user)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,10 @@ class CompareController < ApplicationController
load_compare_params load_compare_params
compare compare
@merge_status, @merge_message = get_merge_message @merge_status, @merge_message = get_merge_message
@page_size = page_size <= 0 ? 1 : page_size
@page_limit = page_limit <=0 ? 15 : page_limit
@page_offset = (@page_size -1) * @page_limit
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
end end
private private
@ -16,6 +20,7 @@ class CompareController < ApplicationController
if @base.blank? || @head.blank? if @base.blank? || @head.blank?
return -2, "请选择分支" return -2, "请选择分支"
else else
return -2, "目标仓库未开启合并请求PR功能" unless @project.has_menu_permission("pulls")
if @head.include?(":") if @head.include?(":")
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
return -2, "请选择正确的仓库" unless fork_project.present? return -2, "请选择正确的仓库" unless fork_project.present?
@ -42,12 +47,22 @@ class CompareController < ApplicationController
end end
def load_compare_params def load_compare_params
@base = Addressable::URI.unescape(params[:base]) # @base = Addressable::URI.unescape(params[:base])
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head] @base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
# @head = Addressable::URI.unescape(@head)
@head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head)
end end
def gitea_compare(base, head) def gitea_compare(base, head)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token) Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
end
def page_size
params.fetch(:page, 1).to_i
end
def page_limit
params.fetch(:limit, 15).to_i
end end
end end

View File

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

View File

@ -108,7 +108,11 @@ module LoginHelper
def sync_pwd_to_gitea!(user, hash={}) def sync_pwd_to_gitea!(user, hash={})
return true if user.is_sync_pwd? return true if user.is_sync_pwd?
sync_params = { email: user.mail } sync_params = {
login_name: user.name,
source_id: 0,
email: user.mail
}
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash)) interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
if interactor.success? if interactor.success?
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########" Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"

View File

@ -27,4 +27,32 @@ module RegisterHelper
result result
end end
def auto_update(user, params={})
return if params.blank?
result = {message: nil, user: nil}
before_login = user.login
user.login = params[:username]
user.password = params[:password]
user.mail = params[:email]
if user.save!
sync_params = {
password: params[:password].to_s,
email: params[:email],
login_name: params[:username],
new_name: params[:username],
source_id: 0
}
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
if interactor.success?
result[:user] = user
else
result[:message] = '用户同步Gitea失败!'
end
else
result[:message] = user.errors.full_messages.join(",")
return
end
end
end end

View File

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

View File

@ -13,7 +13,7 @@ class ForksController < ApplicationController
if current_user&.id == @project.user_id if current_user&.id == @project.user_id
render_result(-1, "自己不能fork自己的项目") render_result(-1, "自己不能fork自己的项目")
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier) elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
render_result(-1, "fork失败你已拥有了这个项目") render_result(0, "fork失败你已拥有了这个项目")
end end
# return if current_user != @project.owner # return if current_user != @project.owner
# render_result(-1, "自己不能fork自己的项目") # render_result(-1, "自己不能fork自己的项目")

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ class MembersController < ApplicationController
before_action :load_project before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role] before_action :find_user_with_id, only: %i[create remove change_role]
before_action :check_user_profile_completed, only: [:create] before_action :check_user_profile_completed, only: [:create]
before_action :operate!, except: %i[index] before_action :operate!
before_action :check_member_exists!, only: %i[create] before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role] before_action :check_member_not_exists!, only: %i[remove change_role]

View File

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

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@ class Organizations::TeamProjectsController < Organizations::BaseController
def index def index
@team_projects = @team.team_projects @team_projects = @team.team_projects
@team_projects = paginate(@team_projects) @team_projects = paginate(@team_projects)
end end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,16 +13,19 @@ class ProjectsController < ApplicationController
def menu_list def menu_list
menu = [] menu = []
user_is_admin = current_user.admin? || @project.manager?(current_user)
menu.append(menu_hash_by_name("home")) menu.append(menu_hash_by_name("home"))
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
menu.append(menu_hash_by_name("activity")) menu.append(menu_hash_by_name("activity"))
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user) menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
render json: menu render json: menu
end end
@ -59,7 +62,7 @@ class ProjectsController < ApplicationController
Projects::MigrateForm.new(mirror_params).validate! Projects::MigrateForm.new(mirror_params).validate!
@project = @project =
if enable_accelerator?(mirror_params[:clone_addr]) if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
source_clone_url = mirror_params[:clone_addr] source_clone_url = mirror_params[:clone_addr]
uid_logger("########## 已动加速器 ##########") uid_logger("########## 已动加速器 ##########")
result = Gitea::Accelerator::MigrateService.call(mirror_params) result = Gitea::Accelerator::MigrateService.call(mirror_params)
@ -71,6 +74,11 @@ class ProjectsController < ApplicationController
else else
Projects::MigrateService.call(current_user, mirror_params) Projects::MigrateService.call(current_user, mirror_params)
end end
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
source_clone_url = mirror_params[:clone_addr]
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
uid_logger("########## 更改clone_addr ##########")
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
else else
Projects::MigrateService.call(current_user, mirror_params) Projects::MigrateService.call(current_user, mirror_params)
end end
@ -82,8 +90,9 @@ class ProjectsController < ApplicationController
def branches def branches
return @branches = [] unless @project.forge? return @branches = [] unless @project.forge?
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) # result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
end end
def branches_slice def branches_slice
@ -129,7 +138,7 @@ class ProjectsController < ApplicationController
validate_params = project_params.slice(:name, :description, validate_params = project_params.slice(:name, :description,
:project_category_id, :project_language_id, :private, :identifier) :project_category_id, :project_language_id, :private, :identifier)
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate! Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
@ -171,6 +180,22 @@ class ProjectsController < ApplicationController
tip_exception(e.message) tip_exception(e.message)
end end
def quit
user_is_admin = current_user.admin? || @project.manager?(current_user)
if !user_is_admin && @project.member(current_user.id) && @project.forge?
ActiveRecord::Base.transaction do
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
render_ok
end
else
render_forbidden('你不能退出该仓库')
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def watch_users def watch_users
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
@watchers_count = watchers.size @watchers_count = watchers.size
@ -184,7 +209,7 @@ class ProjectsController < ApplicationController
end end
def fork_users def fork_users
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
@forks_count = fork_users.size @forks_count = fork_users.size
@fork_users = paginate(fork_users) @fork_users = paginate(fork_users)
end end

View File

@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
before_action :require_login, except: [:index, :show, :files, :commits] before_action :require_login, except: [:index, :show, :files, :commits]
before_action :require_profile_completed, only: [:create] before_action :require_profile_completed, only: [:create]
before_action :load_repository before_action :load_repository
before_action :check_menu_authorize before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
before_action :load_pull_request, only: [:files, :commits] before_action :load_pull_request, only: [:files, :commits]
before_action :find_atme_receivers, only: [:create, :update] before_action :find_atme_receivers, only: [:create, :update]
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues = issues.distinct @all_issues = issues.distinct
@filter_issues = @all_issues @filter_issues = @all_issues
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present? @filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN}) @open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED}) @close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED}) @merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
end end
def new def new
@all_branches = Branches::ListService.call(@owner, @project) @all_branches = Branches::ListService.call(@owner, @project, params[:branch_name])
@is_fork = @project.forked_from_project_id.present? @is_fork = @project.forked_from_project_id.present?
@projects_names = [{ @projects_names = [{
project_user_login: @owner.try(:login), project_user_login: @owner.try(:login),
@ -50,13 +50,15 @@ class PullRequestsController < ApplicationController
end end
def get_branches def get_branches
branch_result = Branches::ListService.call(@owner, @project) branch_result = Branches::ListService.call(@owner, @project, params[:name])
render json: branch_result render json: branch_result
# return json: branch_result # return json: branch_result
end end
def create def create
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params) @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
if @gitea_pull_request[:status] == :success if @gitea_pull_request[:status] == :success
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"]) @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
@ -69,6 +71,8 @@ class PullRequestsController < ApplicationController
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
rescue => e
normal_status(-1, e.message)
end end
def edit def edit
@ -78,6 +82,7 @@ class PullRequestsController < ApplicationController
end end
def update def update
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
if params[:title].nil? if params[:title].nil?
normal_status(-1, "名称不能为空") normal_status(-1, "名称不能为空")
elsif params[:issue_tag_ids].nil? elsif params[:issue_tag_ids].nil?
@ -85,14 +90,21 @@ class PullRequestsController < ApplicationController
else else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
merge_params merge_params
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
params[:issue_tag_ids].each do |tag| return normal_status(-1, "最多只能创建一个标记。")
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag) elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
end @issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end end
if @issue.update_attributes(@issue_params) if @issue.update_attributes(@issue_params)
@ -102,9 +114,16 @@ class PullRequestsController < ApplicationController
if gitea_pull[:status] === :success if gitea_pull[:status] === :success
if params[:issue_tag_ids].present? if params[:issue_tag_ids].present?
params[:issue_tag_ids].each do |tag| if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag) return normal_status(-1, "最多只能创建一个标记。")
end elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end end
if params[:status_id].to_i == 5 if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now) @issue.issue_times.update_all(end_time: Time.now)
@ -197,7 +216,7 @@ class PullRequestsController < ApplicationController
def check_can_merge def check_can_merge
target_head = params[:head] #源分支 target_head = params[:head] #源分支
target_base = params[:base] #目标分支 target_base = params[:base] #目标分支
is_original = params[:is_original] is_original = params[:is_original] || false
if target_head.blank? || target_base.blank? if target_head.blank? || target_base.blank?
normal_status(-2, "请选择分支") normal_status(-2, "请选择分支")
elsif target_head === target_base && !is_original elsif target_head === target_base && !is_original
@ -228,11 +247,11 @@ class PullRequestsController < ApplicationController
private private
def load_pull_request def load_pull_request
@pull_request = PullRequest.find params[:id] @pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
end end
def find_pull_request def find_pull_request
@pull_request = PullRequest.find_by_id(params[:id]) @pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
@issue = @pull_request&.issue @issue = @pull_request&.issue
if @pull_request.blank? if @pull_request.blank?
normal_status(-1, "合并请求不存在") normal_status(-1, "合并请求不存在")
@ -256,12 +275,12 @@ class PullRequestsController < ApplicationController
base: params[:base], #目标分支 base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联 milestone: 0, #里程碑,未与本地的里程碑关联
} }
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
@requests_params = @local_params.merge({ @requests_params = @local_params.merge({
assignee: current_user.try(:login),
# assignees: ["#{params[:assigned_login].to_s}"], # assignees: ["#{params[:assigned_login].to_s}"],
assignees: ["#{current_user.try(:login).to_s}"], assignees: ["#{assignee_login.to_s}"],
labels: params[:issue_tag_ids], labels: params[:issue_tag_ids]
due_date: Time.now # due_date: Time.now
}) })
@issue_params = { @issue_params = {
author_id: current_user.id, author_id: current_user.id,
@ -271,7 +290,7 @@ class PullRequestsController < ApplicationController
assigned_to_id: params[:assigned_to_id], assigned_to_id: params[:assigned_to_id],
fixed_version_id: params[:fixed_version_id], fixed_version_id: params[:fixed_version_id],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
priority_id: params[:priority_id] || "2", priority_id: params[:priority_id],
issue_classify: "pull_request", issue_classify: "pull_request",
issue_type: params[:issue_type] || "1", issue_type: params[:issue_type] || "1",
tracker_id: 2, tracker_id: 2,

View File

@ -12,58 +12,12 @@ class RepositoriesController < ApplicationController
before_action :get_ref, only: %i[entries sub_entries top_counts file archive] before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts] before_action :get_statistics, only: %i[top_counts]
before_action :preload_badge, only: [:badges]
def files def files
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token) result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
render json: result render json: result
end end
def preload_badge
@praised_cache = "praised"
@forked_cache = "forked"
@watchered_cache = "watchered"
@badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
$redis_cache.hset(project_statistic_key, @many_projects_cache, @badge.many_projects)
$redis_cache.hset(project_statistic_key, @manyParisesProject_cache, @badge.manyParisesProject)
$redis_cache.hset(project_statistic_key, @parises_project_cache, @badge.parises_project)
end
####################change for repository############################
def badges
preload_badge
@badges_dic = Hash.new(0)
praises_count = @project.praises_count.to_i
forked_count = @project.forked_count.to_i
watchers_count = @project.watchers_count.to_i
@praised = judge_level(praises_count, 10, 20,100)
redis_judge_reload @praised_cache, @praised
@badges_dic["praised_cache"] = $redis_cache.hget(project_statistic_key, @praised_cache).to_i
@forked = judge_level(forked_count, 5, 10,100)
redis_judge_reload @forked_cache, @forked
@badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
@watchered = judge_level(watchers_count, 10, 20,100)
redis_judge_reload @watchered_cache, @watchered
@badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
badges_visable = Array.new
@badges_dic.each do |key,value|
if value > 0
badges_visable.append({"#{key}":value})
end
end
render :json => {list: badges_visable, count: badges_visable.size}
end
##########################################################
# 新版项目详情 # 新版项目详情
def detail def detail
@user = current_user @user = current_user
@ -110,7 +64,6 @@ class RepositoriesController < ApplicationController
def sub_entries def sub_entries
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
if @project.educoder? if @project.educoder?
if params[:type] === 'file' if params[:type] === 'file'
@ -118,18 +71,35 @@ class RepositoriesController < ApplicationController
logger.info "######### sub_entries: #{@sub_entries}" logger.info "######### sub_entries: #{@sub_entries}"
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
tmp_entries = [{ tmp_entries = {
"content" => @sub_entries['data']['content'], "content" => @sub_entries['data']['content'],
"type" => "blob" "type" => "blob"
}] }
@sub_entries = { @sub_entries = {
"trees"=>tmp_entries, "trees"=>tmp_entries,
"commits" => [{}] "commits" => [{}]
} }
else else
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri}) begin
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
tmp_entries = {
"content" => @sub_entries['data']['content'],
"type" => "blob"
}
@sub_entries = {
"trees"=>tmp_entries,
"commits" => [{}]
}
end
rescue
return render_error('该文件暂未开放,敬请期待.')
end
end end
else else
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref) interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
if interactor.success? if interactor.success?
result = interactor.result result = interactor.result
@ -141,13 +111,17 @@ class RepositoriesController < ApplicationController
end end
def commits def commits
if params[:filepath].present? if @project.educoder?
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) @commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
@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 else
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, if params[:filepath].present?
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
else
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
end
end end
end end
@ -158,8 +132,12 @@ class RepositoriesController < ApplicationController
def commit def commit
@sha = params[:sha] @sha = params[:sha]
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token) if @project.educoder?
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true}) return render_error('暂未开放,敬请期待.')
else
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
end
end end
def tags def tags
@ -169,11 +147,14 @@ class RepositoriesController < ApplicationController
end end
def contributors def contributors
if params[:filepath].present? if params[:filepath].present? || @project.educoder?
@contributors = [] @contributors = []
else else
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
end end
rescue
@contributors = []
end end
def edit def edit
@ -241,21 +222,27 @@ class RepositoriesController < ApplicationController
else else
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token) result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
end end
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
@readme = result[:status] === :success ? result[:body] : nil @readme = result[:status] === :success ? result[:body] : nil
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref]) @readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha") @readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
rescue rescue
render json: nil render json: nil
end end
def languages def languages
render json: languages_precentagable if @project.educoder?
render json: {}
else
render json: languages_precentagable
end
end end
def archive def archive
domain = Gitea.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] api_url = Gitea.gitea_config[:base_url]
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}" archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
file_path = [domain, api_url, archive_url].join file_path = [domain, api_url, archive_url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden? file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
@ -269,11 +256,11 @@ class RepositoriesController < ApplicationController
domain = Gitea.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] api_url = Gitea.gitea_config[:base_url]
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}" url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
file_path = [domain, api_url, url].join file_path = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden? file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
redirect_to URI.escape(file_path) redirect_to file_path
end end
private private
@ -401,37 +388,4 @@ class RepositoriesController < ApplicationController
end end
end end
def judge_level(judged, low, mid, high)
if judged < low
return 0
elsif judged < mid
return 1
elsif judged < high
return 2
else
return 3
end
end
def redis_judge_reload(judge_cache, new_value)
if $redis_cache.hget(project_statistic_key, judge_cache).to_i != new_value
$redis_cache.del(project_statistic_key)
updateService judge_cache, new_value
load_redis
end
end
def project_statistic_key
"project:#{@project.id}"
end
def updateService(update_name, update_value)
@badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
@badge.update_attribute(update_name,update_value)
@badge.save
end
end end

View File

@ -1,6 +1,7 @@
class SettingsController < ApplicationController class SettingsController < ApplicationController
def show def show
@old_projects_url = nil @old_projects_url = nil
get_navbar
get_add_menu get_add_menu
get_common_menu get_common_menu
get_personal_menu get_personal_menu
@ -8,6 +9,14 @@ class SettingsController < ApplicationController
end end
private private
def get_navbar
@navbar = default_laboratory.navbar
if User.current.logged?
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
@navbar << pernal_index
end
end
def get_add_menu def get_add_menu
@add = [] @add = []
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|

View File

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

View File

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

View File

@ -6,7 +6,7 @@ class UsersController < ApplicationController
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
before_action :require_login, only: %i[me list sync_user_info] before_action :require_login, only: %i[me list sync_user_info]
before_action :connect_to_ci_db, only: [:get_user_info] before_action :connect_to_ci_db, only: [:get_user_info]
before_action :convert_image!, only: [:update] before_action :convert_image!, only: [:update, :update_image]
skip_before_action :check_sign, only: [:attachment_show] skip_before_action :check_sign, only: [:attachment_show]
def connect_to_ci_db(options={}) def connect_to_ci_db(options={})
@ -32,7 +32,8 @@ class UsersController < ApplicationController
@waiting_applied_messages = @user.applied_messages.waiting @waiting_applied_messages = @user.applied_messages.waiting
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common @common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common @common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size #@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
else else
@waiting_applied_messages = AppliedMessage.none @waiting_applied_messages = AppliedMessage.none
@common_applied_transfer_projects = AppliedTransferProject.none @common_applied_transfer_projects = AppliedTransferProject.none
@ -81,10 +82,28 @@ class UsersController < ApplicationController
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
@user.attributes = user_params.except(:image) @user.attributes = user_params.except(:image)
unless @user.save unless @user.save
render_error(@user.errors.full_messages.join(", ")) render_error(-1, @user.errors.full_messages.join(", "))
end end
end end
def update_image
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
Util.write_file(@image, avatar_path(@user))
return render_ok({message: '头像修改成功'})
rescue Exception => e
uid_logger_error(e.message)
render_error(-1, '头像修改失败!')
end
def get_image
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
end
def me def me
@user = current_user @user = current_user
end end
@ -282,6 +301,11 @@ class UsersController < ApplicationController
end end
end end
def email_search
return render_error('请输入email') if params[:email].blank?
@user = User.find_by(mail: params[:email])
end
private private
def load_user def load_user
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
@ -294,6 +318,7 @@ class UsersController < ApplicationController
:occupation, :technical_title, :occupation, :technical_title,
:school_id, :department_id, :province, :city, :school_id, :department_id, :province, :city,
:custom_department, :identity, :student_id, :description, :custom_department, :identity, :student_id, :description,
:show_super_description, :super_description,
:show_email, :show_location, :show_department] :show_email, :show_location, :show_department]
) )
end end

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -280,7 +280,7 @@ repo |是| |string |项目标识identifier
### 返回字段说明 ### 返回字段说明
参数 | 类型 | 字段说明 参数 | 类型 | 字段说明
--------- | ----------- | ----------- --------- | ----------- | -----------
menu_name |string|导航名称, home:主页,code:代码库,issues:修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置 menu_name |string|导航名称, home:主页,code:代码库,issues:修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
> 返回的JSON示例: > 返回的JSON示例:
@ -408,7 +408,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
### 请求参数 ### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明 参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ---------- --------- | ------- | ------- | -------- | ----------
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:修,pulls:合并请求,devops:工作流,versions:里程碑 | |unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:修,pulls:合并请求,devops:工作流,versions:里程碑 |
### 返回字段说明: ### 返回字段说明:
@ -849,4 +849,36 @@ await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.j
"created_at": "2021-04-26 09:54", "created_at": "2021-04-26 09:54",
"time_ago": "1分钟前" "time_ago": "1分钟前"
} }
```
## 退出项目
供项目成员(开发者、报告者)退出项目用
> 示例:
```shell
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/quit.json
```
```javascript
await octokit.request('POST /api/:owner/:repo/quit.json')
```
### HTTP 请求
`POST /api/:owner/:repo/quit.json`
### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|owner |是| |string |用户登录名 |
|repo |是| |string |项目标识identifier |
> 返回的JSON示例:
```json
{
"status": 0,
"message": "success"
}
``` ```

View File

@ -1240,11 +1240,11 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
|delete|分支或标签删除| |delete|分支或标签删除|
|fork|仓库被fork| |fork|仓库被fork|
|push|git仓库推送| |push|git仓库推送|
|issue|修已打开、已关闭、已重新打开或编辑| |issue|修已打开、已关闭、已重新打开或编辑|
|issue_assign|修被指派| |issue_assign|修被指派|
|issue_label|修标签被更新或删除| |issue_label|修标签被更新或删除|
|issue_milestone|修被收入里程碑| |issue_milestone|修被收入里程碑|
|issue_comment|修评论| |issue_comment|修评论|
|pull_request|合并请求| |pull_request|合并请求|
|pull_request_assign|合并请求被指派| |pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签| |pull_request_label|合并请求被贴上标签|
@ -1337,11 +1337,11 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
|delete|分支或标签删除| |delete|分支或标签删除|
|fork|仓库被fork| |fork|仓库被fork|
|push|git仓库推送| |push|git仓库推送|
|issue|修已打开、已关闭、已重新打开或编辑| |issue|修已打开、已关闭、已重新打开或编辑|
|issue_assign|修被指派| |issue_assign|修被指派|
|issue_label|修标签被更新或删除| |issue_label|修标签被更新或删除|
|issue_milestone|修被收入里程碑| |issue_milestone|修被收入里程碑|
|issue_comment|修评论| |issue_comment|修评论|
|pull_request|合并请求| |pull_request|合并请求|
|pull_request_assign|合并请求被指派| |pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签| |pull_request_label|合并请求被贴上标签|
@ -1440,11 +1440,11 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|delete|分支或标签删除| |delete|分支或标签删除|
|fork|仓库被fork| |fork|仓库被fork|
|push|git仓库推送| |push|git仓库推送|
|issue|修已打开、已关闭、已重新打开或编辑| |issue|修已打开、已关闭、已重新打开或编辑|
|issue_assign|修被指派| |issue_assign|修被指派|
|issue_label|修标签被更新或删除| |issue_label|修标签被更新或删除|
|issue_milestone|修被收入里程碑| |issue_milestone|修被收入里程碑|
|issue_comment|修评论| |issue_comment|修评论|
|pull_request|合并请求| |pull_request|合并请求|
|pull_request_assign|合并请求被指派| |pull_request_assign|合并请求被指派|
|pull_request_label|合并请求被贴上标签| |pull_request_label|合并请求被贴上标签|

View File

@ -90,13 +90,12 @@ await octokit.request('GET /api/users/:login/messages.json')
#### 消息来源source字段说明 #### 消息来源source字段说明
类型|说明 类型|说明
--------- | ----------- --------- | -----------
|IssueAssigned | 有新指派给我的易修 | |IssueAssigned | 有新指派给我的疑修 |
|IssueAssignerExpire | 我负责的易修截止日期到达最后一天 | |IssueExpire | 我创建或负责的疑修截止日期到达最后一天 |
|IssueAtme | 在易修中@我 | |IssueAtme | 在疑修中@我 |
|IssueChanged | 我创建或负责的易修状态变更 | |IssueChanged | 我创建或负责的疑修状态变更 |
|IssueCreatorExpire | 我创建的易修截止日期到达最后一天 | |IssueDeleted | 我创建或负责的疑修删除 |
|IssueDeleted | 我创建或负责的易修删除 | |IssueJournal | 我创建或负责的疑修有新的评论 |
|IssueJournal | 我创建或负责的易修有新的评论 |
|LoginIpTip | 登录异常提示 | |LoginIpTip | 登录异常提示 |
|OrganizationJoined | 账号被拉入组织 | |OrganizationJoined | 账号被拉入组织 |
|OrganizationLeft | 账号被移出组织 | |OrganizationLeft | 账号被移出组织 |
@ -104,11 +103,12 @@ await octokit.request('GET /api/users/:login/messages.json')
|ProjectDeleted | 我关注的仓库被删除 | |ProjectDeleted | 我关注的仓库被删除 |
|ProjectFollowed | 我管理的仓库被关注 | |ProjectFollowed | 我管理的仓库被关注 |
|ProjectForked | 我管理的仓库被复刻 | |ProjectForked | 我管理的仓库被复刻 |
|ProjectIssue | 我管理/关注的仓库有新的修 | |ProjectIssue | 我管理/关注的仓库有新的修 |
|ProjectJoined | 账号被拉入项目 | |ProjectJoined | 账号被拉入项目 |
|ProjectLeft | 账号被移出项目 | |ProjectLeft | 账号被移出项目 |
|ProjectMemberJoined | 我管理的仓库有成员加入 | |ProjectMemberJoined | 我管理的仓库有成员加入 |
|ProjectMemberLeft | 我管理的仓库有成员移出 | |ProjectMemberLeft | 我管理的仓库有成员移出 |
|ProjectMilestoneCompleted | 我管理的仓库有里程碑完成度100% |
|ProjectMilestone | 我管理的仓库有新的里程碑 | |ProjectMilestone | 我管理的仓库有新的里程碑 |
|ProjectPraised | 我管理的仓库被点赞 | |ProjectPraised | 我管理的仓库被点赞 |
|ProjectPullRequest | 我管理/关注的仓库有新的合并请求 | |ProjectPullRequest | 我管理/关注的仓库有新的合并请求 |
@ -250,7 +250,7 @@ await octokit.request('POST /api/users/:login/messages.json')
--------- | ----------- | ----------- --------- | ----------- | -----------
|type | string | 消息类型 | |type | string | 消息类型 |
|receivers_login | array | 需要发送消息的用户名数组| |receivers_login | array | 需要发送消息的用户名数组|
|atmeable_type | string | atme消息对象是从哪里@我的比如评论Journal、Issue、合并请求PullRequest | |atmeable_type | string | atme消息对象是从哪里@我的比如评论Journal、Issue、合并请求PullRequest |
|atmeable_id | integer | atme消息对象id | |atmeable_id | integer | atme消息对象id |
> 请求的JSON示例: > 请求的JSON示例:
@ -469,7 +469,7 @@ await octokit.request('GET /api/template_message_settings.json')
"total_settings_count": 4, "total_settings_count": 4,
"settings": [ "settings": [
{ {
"name": "修被指派", "name": "修被指派",
"key": "IssueAssigned", "key": "IssueAssigned",
"notification_disabled": true, "notification_disabled": true,
"email_disabled": false "email_disabled": false
@ -488,7 +488,7 @@ await octokit.request('GET /api/template_message_settings.json')
"total_settings_count": 4, "total_settings_count": 4,
"settings": [ "settings": [
{ {
"name": "有新的修", "name": "有新的修",
"key": "Issue", "key": "Issue",
"notification_disabled": true, "notification_disabled": true,
"email_disabled": false "email_disabled": false
@ -875,7 +875,7 @@ await octokit.request('GET /api/users/:login/statistics/activity.json')
参数 | 类型 | 字段说明 参数 | 类型 | 字段说明
--------- | ----------- | ----------- --------- | ----------- | -----------
|dates |array |时间 | |dates |array |时间 |
|issues_count |array |修数量| |issues_count |array |修数量|
|pull_requests_count |array |合并请求数量| |pull_requests_count |array |合并请求数量|
|commtis_count |array |贡献数量| |commtis_count |array |贡献数量|
@ -1084,7 +1084,7 @@ await octokit.request('GET /api/users/:login/project_trends.json')
参数 | 类型 | 字段说明 参数 | 类型 | 字段说明
--------- | ----------- | ----------- --------- | ----------- | -----------
|total_count |int |所选时间内的总动态数 | |total_count |int |所选时间内的总动态数 |
|project_trends.trend_type |string|动态类型IssueVersionRelease版本发布PullRequest合并请求| |project_trends.trend_type |string|动态类型IssueVersionRelease版本发布PullRequest合并请求|
|project_trends.action_type |string|操作类型| |project_trends.action_type |string|操作类型|
|project_trends.trend_id |integer|动态id| |project_trends.trend_id |integer|动态id|
|project_trends.user_name |string|用户名称| |project_trends.user_name |string|用户名称|

View File

@ -63,7 +63,7 @@ under the License.
</span> </span>
</a> </a>
<div class="toc-wrapper"> <div class="toc-wrapper">
<%= image_tag "logo.png", class: 'logo' %> <%= image_tag "logo.png", class: 'logo ' %>
<% if language_tabs.any? %> <% if language_tabs.any? %>
<div class="lang-selector"> <div class="lang-selector">
<% language_tabs.each do |lang| %> <% language_tabs.each do |lang| %>

View File

@ -77,6 +77,7 @@ html, body {
margin: 15px auto; margin: 15px auto;
max-width: 100%; max-width: 100%;
margin-bottom: $logo-margin; margin-bottom: $logo-margin;
max-width: 80%;
} }
&>.search { &>.search {

View File

@ -26,8 +26,34 @@ class BaseForm
raise "项目标识已被占用." if ReversedKeyword.check_exists?(repository_name) raise "项目标识已被占用." if ReversedKeyword.check_exists?(repository_name)
end end
def check_password(password)
password = strip(password)
raise PasswordFormatError, "密码8~16位密码支持字母数字和符号" unless password =~ CustomRegexp::PASSWORD
end
def check_password_confirmation(password, password_confirmation)
password = strip(password)
password_confirmation = strip(password_confirmation)
raise PasswordFormatError, "确认密码为8~16位密码支持字母数字和符号" unless password_confirmation =~ CustomRegexp::PASSWORD
raise PasswordConfirmationError, "两次输入的密码不一致" unless password == password_confirmation
end
def check_verifi_code(verifi_code, code)
code = strip(code)
# return if code == "123123" # TODO 万能验证码,用于测试
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
end
private private
def strip(str) def strip(str)
str.to_s.strip.presence str.to_s.strip.presence
end end
# 1 手机类型0 邮箱类型
# 注意新版的login是自动名生成的
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end
end end

View File

@ -4,7 +4,7 @@ class Gitea::User::UpdateForm
attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local, attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local,
:full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login, :full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login,
:source_id, :website :source_id, :website, :new_name
validates :username, presence: true validates :username, presence: true
validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true } validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true }

View File

@ -1,11 +1,11 @@
class Issues::CreateForm class Issues::CreateForm
include ActiveModel::Model include ActiveModel::Model
attr_accessor :subject attr_accessor :subject, :description
validates :subject, presence: { message: "不能为空" } validates :subject, presence: { message: "不能为空" }
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" } validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
end end

View File

@ -1,10 +1,12 @@
class Issues::UpdateForm class Issues::UpdateForm
include ActiveModel::Model include ActiveModel::Model
attr_accessor :subject attr_accessor :subject, :description
validates :subject, presence: { message: "不能为空" } validates :subject, presence: { message: "不能为空" }
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" } validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
end end

View File

@ -0,0 +1,7 @@
class Journals::CreateForm
include ActiveModel::Model
attr_accessor :notes
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
end

View File

@ -0,0 +1,8 @@
class Journals::UpdateForm
include ActiveModel::Model
attr_accessor :notes
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
end

View File

@ -1,6 +1,6 @@
class Organizations::CreateForm < BaseForm class Organizations::CreateForm < BaseForm
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname, :original_name
validates :name, :nickname, :visibility, presence: true validates :name, :nickname, :visibility, presence: true
validates :name, :nickname, length: { maximum: 100 } validates :name, :nickname, length: { maximum: 100 }
@ -8,4 +8,11 @@ class Organizations::CreateForm < BaseForm
validates :description, length: { maximum: 200 } validates :description, length: { maximum: 200 }
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validate do
check_name(name) unless name.blank? || name == original_name
end
def check_name(name)
raise "组织账号已被使用." if Owner.where(login: name.strip).exists?
end
end end

View File

@ -1,5 +1,5 @@
class Projects::UpdateForm < BaseForm class Projects::UpdateForm < BaseForm
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier, :project_name
validates :name, presence: true validates :name, presence: true
validates :name, length: { maximum: 50 } validates :name, length: { maximum: 50 }
validates :description, length: { maximum: 200 } validates :description, length: { maximum: 200 }
@ -10,6 +10,7 @@ class Projects::UpdateForm < BaseForm
check_project_language(project_language_id) check_project_language(project_language_id)
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
check_project_name(user_id, name) unless name.blank? || name == project_name
end end
end end

View File

@ -10,28 +10,40 @@ module Register
VerifiCodeError = Class.new(Error) VerifiCodeError = Class.new(Error)
private private
def check_login(login) def check_login(login, user=nil)
login = strip(login) login = strip(login)
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login) login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
raise LoginError, '登录名已被使用' if login_exist if user.present?
raise LoginError, '登录名已被使用' if login_exist && login != user&.login
else
raise LoginError, '登录名已被使用' if login_exist
end
end end
def check_mail(mail) def check_mail(mail, user=nil)
mail = strip(mail) mail = strip(mail)
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
mail_exist = Owner.exists?(mail: mail) mail_exist = Owner.exists?(mail: mail)
raise EmailError, '邮箱已被使用' if mail_exist if user.present?
raise EmailError, '邮箱已被使用' if mail_exist && mail != user&.mail
else
raise EmailError, '邮箱已被使用' if mail_exist
end
end end
def check_phone(phone) def check_phone(phone, user=nil)
phone = strip(phone) phone = strip(phone)
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
phone_exist = Owner.exists?(phone: phone) phone_exist = Owner.exists?(phone: phone)
raise PhoneError, '手机号已被使用' if phone_exist if user.present?
raise PhoneError, '手机号已被使用' if phone_exist && phone != user&.phone
else
raise PhoneError, '手机号已被使用' if phone_exist
end
end end
def check_password(password) def check_password(password)
@ -41,7 +53,7 @@ module Register
def check_verifi_code(verifi_code, code) def check_verifi_code(verifi_code, code)
code = strip(code) code = strip(code)
return if code == "123123" # TODO 万能验证码,用于测试 # return if code == "123123" # TODO 万能验证码,用于测试
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective? raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?

View File

@ -10,7 +10,8 @@ module Register
def check! def check!
Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}" Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}"
db_verifi_code = type = phone_mail_type(strip(login))
db_verifi_code =
if type == 1 if type == 1
check_phone(login) check_phone(login)
VerificationCode.where(phone: login, code: code, code_type: 1).last VerificationCode.where(phone: login, code: code, code_type: 1).last

View File

@ -0,0 +1,19 @@
module Register
class LoginCheckColumnsForm < Register::BaseForm
attr_accessor :type, :value, :user
validates :type, presence: true, numericality: true
validates :value, presence: true
validate :check!
def check!
# params[:type] 为事件类型 1登录名(login) 2email(邮箱) 3phone(手机号)
case strip(type).to_i
when 1 then check_login(strip(value), user)
when 2 then check_mail(strip(value), user)
when 3 then check_phone(strip(value), user)
else raise("type值无效")
end
end
end
end

View File

@ -0,0 +1,16 @@
module Register
class RemoteForm < Register::BaseForm
# login 登陆方式,支持邮箱、登陆、手机号等
attr_accessor :username, :email, :password, :platform
validates :username, :email, :password, presence: true
validate :check!
def check!
Rails.logger.info "Register::RemoteForm params: username: #{username}; email: #{email}; password: #{password}; platform: #{platform}"
check_login(username)
check_mail(email)
check_password(password)
end
end
end

View File

@ -4,5 +4,5 @@ class Users::LoginForm
attr_accessor :password, :login attr_accessor :password, :login
validates :login, presence: true validates :login, presence: true
validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位支持字母数字和符号" } validates :password, presence: true, length: { minimum: 6, maximum: 16 }, format: { with: CustomRegexp::LOGIN_PASSWORD, message: "6~16位支持字母数字和符号" }
end end

View File

@ -147,6 +147,15 @@ module ApplicationHelper
end end
end end
def url_to_avatar_with_platform_url(source)
platform_url = Rails.application.config_for(:configuration)['platform_url']
if platform_url
return Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(source).to_s
else
return url_to_avatar(source).to_s
end
end
# 主页banner图 # 主页banner图
def banner_img(source_type) def banner_img(source_type)
if File.exist?(disk_filename(source_type, "banner")) if File.exist?(disk_filename(source_type, "banner"))

View File

@ -10,19 +10,19 @@ module RepositoriesHelper
end end
def download_type(str) def download_type(str)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2) default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
default_type.include?(str&.downcase) default_type.include?(str&.downcase) || str.blank?
end end
def image_type?(str) def image_type?(str)
default_type = %w(png jpg gif tif psd svg bmp webp jpeg) default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
default_type.include?(str&.downcase) default_type.include?(str&.downcase)
end end
def is_readme?(type, str) def is_readme?(type, str)
return false if type != 'file' || str.blank? return false if type != 'file' || str.blank?
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"] readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
readme_types.include?(str.to_s.downcase) readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
end end
def render_commit_author(author_json) def render_commit_author(author_json)
@ -36,7 +36,6 @@ module RepositoriesHelper
end end
def render_cache_commit_author(author_json) def render_cache_commit_author(author_json)
Rails.logger.info author_json['Email']
if author_json["name"].present? && author_json["email"].present? if author_json["name"].present? && author_json["email"].present?
return find_user_in_redis_cache(author_json['name'], author_json['email']) return find_user_in_redis_cache(author_json['name'], author_json['email'])
end end
@ -45,7 +44,7 @@ module RepositoriesHelper
end end
end end
def readme_render_decode64_content(str, path) def readme_render_decode64_content(str, owner, repo, ref)
return nil if str.blank? return nil if str.blank?
begin begin
content = Base64.decode64(str).force_encoding('UTF-8') content = Base64.decode64(str).force_encoding('UTF-8')
@ -57,21 +56,28 @@ module RepositoriesHelper
total_images = ss + ss_src total_images = ss + ss_src
if total_images.length > 0 if total_images.length > 0
total_images.each do |s| total_images.each do |s|
begin
image_title = /\"(.*?)\"/ image_title = /\"(.*?)\"/
r_content = s[0] r_content = s[0]
remove_title = r_content.to_s.scan(image_title) remove_title = r_content.to_s.scan(image_title)
if remove_title.length > 0 if remove_title.length > 0
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
end end
if r_content.include?("?") # if r_content.include?("?")
new_r_content = r_content + "&raw=true" # new_r_content = r_content + "&raw=true"
else # else
new_r_content = r_content + "?raw=true" # new_r_content = r_content + "?raw=true"
end # end
new_r_content = r_content
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:") unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
new_r_content = "#{path}" + new_r_content # new_r_content = "#{path}" + new_r_content
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join
end end
content = content.gsub(/#{r_content}/, new_r_content) content = content.gsub(/#{r_content}/, new_r_content)
rescue
next
end
end end
end end
@ -81,6 +87,45 @@ module RepositoriesHelper
end end
end end
# author hui.he
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
return nil if str.blank?
content = Base64.decode64(str).force_encoding('UTF-8')
s_regex = /\[.*?\]\((.*?)\)/
src_regex = /src=\"(.*?)\"/
ss = content.to_s.scan(s_regex)
ss_src = content.to_s.scan(src_regex)
total_sources = ss + ss_src
total_sources.uniq!
total_sources.each do |s|
begin
s_content = s[0]
# 链接直接跳过不做替换
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
ext = File.extname(s_content)[1..-1]
if (image_type?(ext) || download_type(ext)) && !s_content.to_s.end_with?('/')
s_content = File.expand_path(s_content, file_path)
s_content = s_content.split("#{Rails.root}/")[1]
# content = content.gsub(s[0], "/#{s_content}")
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
content = content.gsub(s[0], s_content)
else
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
s_content = File.expand_path(s_content, path)
s_content = s_content.split("#{Rails.root}/")[1]
content = content.gsub(s[0], "/#{s_content}")
end
rescue
next
end
end
return content
rescue
return str
end
# unix_time values for example: 1604382982 # unix_time values for example: 1604382982
def render_format_time_with_unix(unix_time) def render_format_time_with_unix(unix_time)
Time.at(unix_time).strftime("%Y-%m-%d %H:%M") Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
@ -91,10 +136,21 @@ module RepositoriesHelper
date.to_time.strftime("%Y-%m-%d %H:%M") date.to_time.strftime("%Y-%m-%d %H:%M")
end end
def readme_decode64_content(entry, owner, repo, ref, path=nil)
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
Rails.logger.info("content===#{content}")
# readme_render_decode64_content(content, owner, repo, ref)
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
end
def decode64_content(entry, owner, repo, ref, path=nil) def decode64_content(entry, owner, repo, ref, path=nil)
if is_readme?(entry['type'], entry['name']) if is_readme?(entry['type'], entry['name'])
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
readme_render_decode64_content(content, path) Rails.logger.info("content===#{content}")
# readme_render_decode64_content(content, owner, repo, ref)
return Base64.decode64(content).force_encoding('UTF-8')
else else
file_type = File.extname(entry['name'].to_s)[1..-1] file_type = File.extname(entry['name'].to_s)[1..-1]
if image_type?(file_type) if image_type?(file_type)

View File

@ -26,8 +26,13 @@ module TagChosenHelper
end end
def render_branches(project) def render_branches(project)
branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier) if project.educoder?
branches.collect{|i| i["name"] if i.is_a?(Hash)} return ['master']
else
branches = Gitea::Repository::Branches::ListNameService.call(project&.owner, project.identifier)
return branches.collect{|i| i["name"] if i.is_a?(Hash)} if branches.is_a?(Array)
return branches["branch_name"] if branches.is_a?(Hash)
end
end end
def render_cache_trackers def render_cache_trackers

View File

@ -0,0 +1,15 @@
class Admins::NewImportUserFromExcel < BaseImportXlsx
UserData = Struct.new(:login, :email, :password, :nickname)
def read_each(&block)
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
data = row.map(&method(:cell_value))[0..3]
block.call UserData.new(*data)
end
end
private
def cell_value(obj)
obj&.cell_value
end
end

View File

@ -13,7 +13,7 @@ module Gitea
end end
def success? def success?
@error.nil? @error.nil? && @result[:status].to_s == "success"
end end
def result def result

View File

@ -7,6 +7,8 @@ class CacheAsyncClearJob < ApplicationJob
Cache::V2::ProjectCommonService.new(id).clear Cache::V2::ProjectCommonService.new(id).clear
when "owner_common_service" when "owner_common_service"
Cache::V2::OwnnerCommonService.new(id).clear Cache::V2::OwnnerCommonService.new(id).clear
when "project_rank_service"
Cache::V2::ProjectRankService.new(id).clear
end end
end end
end end

View File

@ -3,8 +3,7 @@ class DelayExpiredIssueJob < ApplicationJob
def perform def perform
Issue.where(due_date: Date.today + 1.days).find_each do |issue| 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('IssueExpire', issue.id) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) if Site.has_notice_menu?
end end
end end

View File

@ -6,7 +6,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob
return if repo.blank? return if repo.blank?
puts "############ MigrateRemoteRepositoryJob starting ... ############" puts "############ MigrateRemoteRepositoryJob starting ... ############"
params.except!(:auth_password, :auth_username) if params[:auth_username].nil?
gitea_repository = Gitea::Repository::MigrateService.new(token, params).call gitea_repository = Gitea::Repository::MigrateService.new(token, params).call
puts "#gitea_repository#{gitea_repository}" puts "#gitea_repository#{gitea_repository}"
if gitea_repository[0]==201 if gitea_repository[0]==201

View File

@ -4,6 +4,24 @@ class SendTemplateMessageJob < ApplicationJob
def perform(source, *args) def perform(source, *args)
Rails.logger.info "SendTemplateMessageJob [args] #{args}" Rails.logger.info "SendTemplateMessageJob [args] #{args}"
case source case source
when 'CustomTip'
receivers_id, template_id, props = args[0], args[1], args[2]
template = MessageTemplate.find_by_id(template_id)
return unless template.present?
receivers = User.where(id: receivers_id).or(User.where(mail: receivers_id))
not_exists_receivers = receivers_id - receivers.pluck(:id) - receivers.pluck(:mail)
receivers_string, content, notification_url = MessageTemplate::CustomTip.get_message_content(receivers, template, props)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {receivers_id: receivers_id, template_id: template_id, props: props})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::CustomTip.get_email_message_content(receiver, template, props)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
not_exists_receivers.each do |mail|
valid_email_regex = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/i
next unless (mail =~ valid_email_regex)
email_title, email_content = MessageTemplate::CustomTip.get_email_content(template, props)
Notice::Write::EmailCreateService.call(mail, email_title, email_content)
end
when 'FollowTip' when 'FollowTip'
watcher_id = args[0] watcher_id = args[0]
watcher = Watcher.find_by_id(watcher_id) watcher = Watcher.find_by_id(watcher_id)
@ -24,19 +42,13 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end 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' when 'IssueAtme'
receivers, operator_id, issue_id = args[0], args[1], args[2] receivers, operator_id, issue_id = args[0], args[1], args[2]
operator = User.find_by_id(operator_id) operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id) issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present? return unless operator.present? && issue.present?
# receivers = receivers.where.not(id: operator&.id) # receivers = receivers.where.not(id: operator&.id)
receivers = User.where(id: receivers)
receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue) 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, operator_id) Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2, operator_id)
when 'IssueChanged' when 'IssueChanged'
@ -51,13 +63,17 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::IssueChanged.get_email_message_content(receiver, operator, issue, change_params) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end end
when 'IssueCreatorExpire' when 'IssueExpire'
issue_id = args[0] issue_id = args[0]
issue = Issue.find_by_id(issue_id) issue = Issue.find_by_id(issue_id)
return unless issue.present? return unless issue.present?
receivers = User.where(id: issue&.author_id) receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id])
receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue) receivers_string, content, notification_url = MessageTemplate::IssueExpire.get_message_content(receivers, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id}) Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::IssueExpire.get_email_message_content(receiver, issue)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'IssueDeleted' when 'IssueDeleted'
operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3] 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) operator = User.find_by_id(operator_id)
@ -93,18 +109,14 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end end
when 'OrganizationRole' when 'ProjectForked'
user_id, organization_id, role = args[0], args[1], args[2] operator_id, project_id = args[0], args[1]
user = User.find_by_id(user_id) operator = User.find_by_id(operator_id)
organization = Organization.find_by_id(organization_id) project = Project.find_by_id(project_id)
return unless user.present? && organization.present? return unless operator.present? && project.present?
receivers = User.where(id: user.id) receivers = project&.all_managers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role) receivers_string, content, notification_url = MessageTemplate::ProjectForked.get_message_content(receivers, operator, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role}) Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
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' when 'ProjectIssue'
operator_id, issue_id = args[0], args[1] operator_id, issue_id = args[0], args[1]
operator = User.find_by_id(operator_id) operator = User.find_by_id(operator_id)
@ -174,6 +186,37 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end end
when 'ProjectMilestoneCompleted'
milestone_id = args[0]
milestone = Version.find_by_id(milestone_id)
return unless milestone.present? && milestone&.project.present?
receivers = milestone&.project&.all_managers
receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneCompleted.get_message_content(receivers, milestone)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestoneCompleted.get_email_message_content(receiver, milestone)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectMilestone'
milestone_id, operator_id = args[0], args[1]
milestone = Version.find_by_id(milestone_id)
operator = User.find_by_id(operator_id)
return unless milestone.present? && milestone&.project.present? && operator.present?
receivers = milestone&.project&.all_managers.where.not(id: operator_id)
receivers_string, content, notification_url = MessageTemplate::ProjectMilestone.get_message_content(receivers, operator, milestone)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'ProjectPraised'
operator_id, project_id = args[0], args[1]
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::ProjectPraised.get_message_content(receivers, operator, project)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
when 'ProjectPullRequest' when 'ProjectPullRequest'
operator_id, pull_request_id = args[0], args[1] operator_id, pull_request_id = args[0], args[1]
operator = User.find_by_id(operator_id) operator = User.find_by_id(operator_id)
@ -235,6 +278,7 @@ class SendTemplateMessageJob < ApplicationJob
pull_request = PullRequest.find_by_id(pull_request_id) pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present? return unless operator.present? && pull_request.present?
# receivers = receivers.where.not(id: operator&.id) # receivers = receivers.where.not(id: operator&.id)
receivers = User.where(id: receivers)
receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request) 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, operator_id) Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2, operator_id)
when 'PullRequestChanged' when 'PullRequestChanged'
@ -274,6 +318,56 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestMerged.get_email_message_content(receiver, operator, pull_request) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end end
when 'TeamJoined'
user_id, organization_id, team_id = args[0], args[1], args[2]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
team = Team.find_by_id(team_id)
return unless user.present? && organization.present? && team.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::TeamJoined.get_message_content(receivers, organization, team)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::TeamJoined.get_email_message_content(receiver, organization, team)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'TeamLeft'
user_id, organization_id, team_id = args[0], args[1], args[2]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
team = Team.find_by_id(team_id)
return unless user.present? && organization.present? && team.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::TeamLeft.get_message_content(receivers, organization, team)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::TeamLeft.get_email_message_content(receiver, organization, team)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'CompetitionBegin'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionBegin.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
when 'CompetitionReview'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionReview.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
when 'CompetitionResult'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionResult.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
end end
end end
end end

View File

@ -1,14 +1,15 @@
module CustomRegexp module CustomRegexp
PHONE = /1\d{10}/ PHONE = /1\d{10}/
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/ EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ #只含有数字、字母、下划线不能以下划线开头和结尾
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/ LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/ NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
LOGIN_PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{6,16}\z/
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\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])$/ 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 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_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
MD_REGEX = /^.+(\.[m|M][d|D])$/
end end

View File

@ -7,7 +7,7 @@ module Notice
config = Rails.application.config_for(:configuration).symbolize_keys! config = Rails.application.config_for(:configuration).symbolize_keys!
notice_config = config[:notice].symbolize_keys! notice_config = config[:notice].symbolize_keys!
raise 'notice config missing' if notice_config.blank? raise 'notice config missing' if notice_config.blank?
rescue => exception rescue => ex
raise ex if Rails.env.production? raise ex if Rails.env.production?
puts %Q{\033[33m [warning] gitea config or configuration.yml missing, puts %Q{\033[33m [warning] gitea config or configuration.yml missing,

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

@ -0,0 +1,21 @@
module Trace
class << self
def trace_config
trace_config = {}
begin
config = Rails.application.config_for(:configuration).symbolize_keys!
trace_config = config[:trace].symbolize_keys!
raise 'trace config missing' if trace_config.blank?
rescue => ex
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}
trace_config = {}
end
trace_config
end
end
end

View File

@ -29,6 +29,7 @@ module Util
file.write(io) file.write(io)
end end
end end
true
end end
def download_file(url, save_path) def download_file(url, save_path)

View File

@ -17,7 +17,7 @@
# disk_directory :string(255) # disk_directory :string(255)
# attachtype :integer default("1") # attachtype :integer default("1")
# is_public :integer default("1") # is_public :integer default("1")
# copy_from :integer # copy_from :string(255)
# quotes :integer default("0") # quotes :integer default("0")
# is_publish :integer default("1") # is_publish :integer default("1")
# publish_time :datetime # publish_time :datetime
@ -26,15 +26,15 @@
# cloud_url :string(255) default("") # cloud_url :string(255) default("")
# course_second_category_id :integer default("0") # course_second_category_id :integer default("0")
# delay_publish :boolean default("0") # delay_publish :boolean default("0")
# link :string(255)
# clone_id :integer
# #
# Indexes # Indexes
# #
# index_attachments_on_author_id (author_id) # index_attachments_on_author_id (author_id)
# index_attachments_on_clone_id (clone_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type) # index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on) # index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
# #

View File

@ -1,21 +0,0 @@
# == Schema Information
#
# Table name: badges
#
# id :integer not null, primary key
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# many_projects :integer default("0")
# manyParisesProject :integer default("0")
# parises_project :integer default("0")
# manyWatchersProject :integer default("0")
# watchers_project :integer default("0")
# many_fans :integer default("0")
# many_pr :integer default("0")
# many_issue :integer default("0")
# active_in_week :integer default("0")
#
class Badge < ApplicationRecord
end

View File

@ -5,10 +5,10 @@ class Ci::Repo < Ci::RemoteBase
has_one :perm, foreign_key: :perm_repo_uid has_one :perm, foreign_key: :perm_repo_uid
has_many :builds, foreign_key: :build_repo_id, dependent: :destroy has_many :builds, foreign_key: :build_repo_id, dependent: :destroy
def self.find_with_namespace(namespace_path, identifier) def self.find_with_namespace(namespace_path, identifier, user_login)
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} " logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
user_login = user_login || namespace_path
user = Ci::User.find_by_user_login namespace_path user = Ci::User.find_by(user_login: user_login)
repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first
[user, repo] [user, repo]

View File

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

View File

@ -5,7 +5,7 @@ module Matchable
scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? } scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? }
scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? } scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? }
scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) } scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) }
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? } scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "%#{search.split(" ").join('|')}%") unless search.blank? }
end end
end end

View File

@ -21,13 +21,37 @@ module ProjectOperable
end end
def add_member!(user_id, role_name='Developer') def add_member!(user_id, role_name='Developer')
member = members.create!(user_id: user_id) if self.owner.is_a?(Organization)
case role_name
when 'Manager'
team = self.owner.teams.admin.take
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
when 'Developer'
team = self.owner.teams.write.take
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
when 'Reporter'
team = self.owner.teams.read.take
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
end
end
member = members.create!(user_id: user_id, team_user_id: team_user&.id)
set_developer_role(member, role_name) set_developer_role(member, role_name)
end end
def remove_member!(user_id) def remove_member!(user_id)
member = members.find_by(user_id: user_id) member = members.find_by(user_id: user_id)
member.destroy! if member && self.user_id != user_id member.destroy! if member && self.user_id != user_id
team_user = TeamUser.find_by_id(member&.team_user_id)
team_user.destroy! if team_user
end end
def member?(user_id) def member?(user_id)
@ -47,6 +71,28 @@ module ProjectOperable
def change_member_role!(user_id, role) def change_member_role!(user_id, role)
member = self.member(user_id) member = self.member(user_id)
if self.owner.is_a?(Organization) && member.team_user.present?
case role&.name
when 'Manager'
team = self.owner.teams.admin.take
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
when 'Developer'
team = self.owner.teams.write.take
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
when 'Reporter'
team = self.owner.teams.read.take
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
end
end
member.member_roles.last.update_attributes!(role: role) member.member_roles.last.update_attributes!(role: role)
end end

View File

@ -1,19 +1,18 @@
# == Schema Information # == Schema Information
# #
# Table name: edu_settings # Table name: edu_settings
# #
# id :integer not null, primary key # id :integer not null, primary key
# name :string(255) # name :string(255)
# value :string(255) # value :string(255)
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# description :string(255) # description :string(255)
# #
# Indexes # Indexes
# #
# index_edu_settings_on_name (name) UNIQUE # index_edu_settings_on_name (name) UNIQUE
# #
class EduSetting < ApplicationRecord class EduSetting < ApplicationRecord
after_commit :expire_value_cache after_commit :expire_value_cache

View File

@ -17,7 +17,7 @@
class ForkUser < ApplicationRecord class ForkUser < ApplicationRecord
belongs_to :project belongs_to :project
belongs_to :user belongs_to :owner, class_name: 'Owner', foreign_key: :user_id
belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic

View File

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

View File

@ -11,7 +11,7 @@
# category_id :integer # category_id :integer
# status_id :integer not null # status_id :integer not null
# assigned_to_id :integer # assigned_to_id :integer
# priority_id :integer not null # priority_id :integer
# fixed_version_id :integer # fixed_version_id :integer
# author_id :integer not null # author_id :integer not null
# created_on :datetime # created_on :datetime
@ -75,7 +75,7 @@ class Issue < ApplicationRecord
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)} scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
scope :closed, ->{where(status_id: 5)} scope :closed, ->{where(status_id: 5)}
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
after_update :change_versions_count after_save :change_versions_count, :send_update_message_to_notice_system
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
def incre_project_common def incre_project_common
@ -153,6 +153,10 @@ class Issue < ApplicationRecord
end end
end end
def is_collaborators?
self.assigned_to_id.present? ? self.project.member?(self.assigned_to_id) : false
end
def get_issue_tags_name def get_issue_tags_name
if issue_tags.present? if issue_tags.present?
issue_tags.select(:name).uniq.pluck(:name).join(",") issue_tags.select(:name).uniq.pluck(:name).join(",")
@ -166,11 +170,25 @@ class Issue < ApplicationRecord
end end
def change_versions_count def change_versions_count
if self.version.present? && self.saved_change_to_status_id? if self.saved_change_to_fixed_version_id?
before_version = Version.find_by_id(self.fixed_version_id_before_last_save)
Rails.logger.info self.fixed_version_id_before_last_save
if before_version.present?
Rails.logger.info self.status_id
Rails.logger.info self.status_id_before_last_save
# 更改前状态为完成 或者 更改前后都为完成状态
if self.status_id_before_last_save == 5
percent = before_version.issues_count == 0 ? 0.0 : ((before_version.closed_issues_count - 1).to_f / before_version.issues_count)
before_version.update_attributes(closed_issues_count: (before_version.closed_issues_count - 1), percent: percent)
end
end
end
if self.version.present? && (self.saved_change_to_status_id? || self.saved_change_to_fixed_version_id?)
if self.status_id == 5 if self.status_id == 5
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count + 1).to_f / self.version.issues_count) percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count + 1).to_f / self.version.issues_count)
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count + 1), percent: percent) self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count + 1), percent: percent)
elsif self.status_id_before_last_save == 5 elsif self.status_id_before_last_save == 5 && !self.saved_change_to_fixed_version_id?
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count - 1).to_f / self.version.issues_count) percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count - 1).to_f / self.version.issues_count)
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count - 1), percent: percent) self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count - 1), percent: percent)
end end
@ -178,7 +196,11 @@ class Issue < ApplicationRecord
end end
def update_closed_issues_count_in_project! def update_closed_issues_count_in_project!
self.project.decrement!(:closed_issues_count) self.project.decrement!(:closed_issues_count) if self.status_id == 5
end
def send_update_message_to_notice_system
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
end end
end end

View File

@ -6,7 +6,7 @@
# journalized_id :integer default("0"), not null # journalized_id :integer default("0"), not null
# journalized_type :string(30) default(""), not null # journalized_type :string(30) default(""), not null
# user_id :integer default("0"), not null # user_id :integer default("0"), not null
# notes :text(65535) # notes :text(4294967295)
# created_on :datetime not null # created_on :datetime not null
# private_notes :boolean default("0"), not null # private_notes :boolean default("0"), not null
# parent_id :integer # parent_id :integer

View File

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

View File

@ -11,23 +11,26 @@
# course_group_id :integer default("0") # course_group_id :integer default("0")
# is_collect :integer default("1") # is_collect :integer default("1")
# graduation_group_id :integer default("0") # graduation_group_id :integer default("0")
# team_user_id :integer
# #
# Indexes # Indexes
# #
# index_members_on_course_id (course_id) # index_members_on_course_id (course_id)
# index_members_on_project_id (project_id) # index_members_on_project_id (project_id)
# index_members_on_team_user_id (team_user_id)
# index_members_on_user_id (user_id) # index_members_on_user_id (user_id)
# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE # index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE
# #
class Member < ApplicationRecord class Member < ApplicationRecord
belongs_to :user belongs_to :user
# belongs_to :course, optional: true # belongs_to :course, optional: true
belongs_to :project, optional: true belongs_to :project, optional: true
belongs_to :team_user, optional: true
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
validates :user_id, :project_id, presence: true
validates :user_id, :project_id, presence: true
end
end

View File

@ -13,59 +13,71 @@
# #
class MessageTemplate < ApplicationRecord class MessageTemplate < ApplicationRecord
PLATFORM = 'GitLink'
def self.build_init_data def self.build_init_data
MessageTemplate.where.not(type: 'MessageTemplate::CustomTip').destroy_all
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}') 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") 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: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个易修') 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: "#{PLATFORM}: {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}')
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") 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: 'GitLink: 易修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') 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: "#{PLATFORM}: 疑修 {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_expire.html")
self.create(type: 'MessageTemplate::IssueExpire', sys_notice: '疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: 疑修截止日期到达最后一天")
email_html = File.read("#{email_template_html_dir}/issue_deleted.html") 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: 'GitLink: 易修 {title} 有状态变更', notification_url: '') self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将修 <b>{title}</b> 删除', email: email_html, email_title: "#{PLATFORM}: 疑修 {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::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: '') 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") 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: 'GitLink: 你已加入 {organization} 组织') self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {organization} 组织")
email_html = File.read("#{email_template_html_dir}/organization_left.html") 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: 'GitLink: 你已被移出 {organization} 组织') self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {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: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '') 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::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}') self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库 <b>{nickname2}/{repository}</b> 到 <b>{nickname1}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_issue.html") 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: 'GitLink: {nickname1} 在 {nickname2}/{repository} 新建了一个易修') 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: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个疑修")
email_html = File.read("#{email_template_html_dir}/project_joined.html") 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: 'GitLink: 你已加入 {repository} 项目') self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {repository} 项目")
email_html = File.read("#{email_template_html_dir}/project_left.html") 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: 'GitLink: 你已被移出 {repository} 项目') self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {repository} 项目")
email_html = File.read("#{email_template_html_dir}/project_member_joined.html") 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: 'GitLink: {nickname1} 已加入项目 {nickname2}/{repository}') self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 已加入项目 {nickname2}/{repository}")
email_html = File.read("#{email_template_html_dir}/project_member_left.html") 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: 'GitLink: {nickname1} 已被移出项目 {nickname2}/{repository}') self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {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}') email_html = File.read("#{email_template_html_dir}/project_milestone.html")
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}') self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{name}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑")
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/project_pull_request.html") 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: 'GitLink: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求') 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: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求")
email_html = File.read("#{email_template_html_dir}/project_role.html") 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: 'GitLink: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}') self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '#{PLATFORM}: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_setting_changed.html") 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: 'GitLink: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改') 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: "#{PLATFORM}: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改")
self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') 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') 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") 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: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求') 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: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求")
self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') 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") 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: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') 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: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_closed.html") 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: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '') self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '')
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') 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") 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: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/team_joined.html")
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/team_left.html")
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
# 竞赛通知
self.create(type: 'MessageTemplate::CompetitionBegin', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入比赛进行阶段,可在此期间提交作品', notification_url: '{to_url}')
self.create(type: 'MessageTemplate::CompetitionResult', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入成绩公示阶段,可查看排行榜信息', notification_url: '{to_url}')
self.create(type: 'MessageTemplate::CompetitionReview', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交', notification_url: '{to_url}')
end end
def self.sys_notice def self.sys_notice

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛进入比赛进行阶段
# 触发场景
# 赛队成员报名的竞赛已进入比赛进行阶段
# 通知文案格式
# 你报名的竞赛 xxx 已进入比赛进行阶段,可在此阶段提交作品
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 已进入比赛进行阶段,可在此期间提交作品
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionBegin < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.to_s.gsub('{competition_name}', competition&.name), notification_url.to_s.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
# rescue
# return '', '', ''
end
end

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛进入成绩公示阶段
# 触发场景
# 赛队成员报名的竞赛已进入成绩公示阶段
# 通知文案格式
# 你报名的竞赛 xxx 已进入成绩公示阶段,可查看排行榜信息
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 已进入成绩公示阶段,可查看排行榜信息
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionResult < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
rescue
return '', '', ''
end
end

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛比赛结束时间临近
# 触发场景
# 赛队成员报名的竞赛阶段处于比赛进行中且距比赛结束日期仅剩3天
# 通知文案格式
# 你报名的竞赛 xxx 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionReview < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
rescue
return '', '', ''
end
end

View File

@ -0,0 +1,71 @@
# == 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::CustomTip < MessageTemplate
# MessageTemplate::CustomTip.get_message_content(User.where(login: 'yystopf'), "hahah")
def self.get_message_content(receivers, template, props={})
return '', '', '' if receivers.blank? || template.blank?
content = template.sys_notice
notification_url = template.notification_url
props.each do |k, v|
content.gsub!("{#{k}}", v)
notification_url.gsub!("{#{k}}", v)
end
notification_url.gsub!('{baseurl}', base_url)
return receivers_string(receivers), content, notification_url
rescue => e
Rails.logger.info("MessageTemplate::CustomTip.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, template, props={})
return '', '', '' if receiver.blank? || template.blank?
title = template.email_title
content = template.email
props.each do |k, v|
title.gsub!("{#{k}}", v)
content.gsub!("{#{k}}", v)
end
content.gsub!('{receiver}', receiver&.real_name)
title.gsub!('{platform}', PLATFORM)
content.gsub!('{platform}', PLATFORM)
content.gsub!('{baseurl}', base_url)
return receiver&.mail, title, content
rescue => e
Rails.logger.info("MessageTemplate::CustomTip.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_content(template, props = {})
return '', '', '' if template.blank?
title = template.email_title
content = template.email
props.each do |k, v|
title.gsub!("{#{k}}", v)
content.gsub!("{#{k}}", v)
end
title.gsub!('{platform}', PLATFORM)
content.gsub!('{platform}', PLATFORM)
content.gsub!('{baseurl}', base_url)
return title, content
rescue => e
Rails.logger.info("MessageTemplate::CustomTip.get_email_content [ERROR] #{e}")
return '', ''
end
end

View File

@ -12,7 +12,7 @@
# email_title :string(255) # email_title :string(255)
# #
# 有新指派给我的 # 有新指派给我的
class MessageTemplate::IssueAssigned < MessageTemplate class MessageTemplate::IssueAssigned < MessageTemplate
# MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) # MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)
@ -36,26 +36,29 @@ class MessageTemplate::IssueAssigned < MessageTemplate
def self.get_email_message_content(receiver, operator, issue) def self.get_email_message_content(receiver, operator, issue)
if receiver.user_template_message_setting.present? if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::IssueAssigned"] return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::IssueAssigned"]
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)
content.gsub!('{platform}', PLATFORM)
return receiver&.mail, title, content
else
return '', '', ''
end 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 rescue => e
Rails.logger.info("MessageTemplate::IssueAssigned.get_email_message_content [ERROR] #{e}") Rails.logger.info("MessageTemplate::IssueAssigned.get_email_message_content [ERROR] #{e}")
return '', '', '' return '', '', ''

View File

@ -12,7 +12,7 @@
# email_title :string(255) # email_title :string(255)
# #
# 我负责的修截止日期到达最后一天 # 我负责的修截止日期到达最后一天
class MessageTemplate::IssueAssignerExpire < MessageTemplate class MessageTemplate::IssueAssignerExpire < MessageTemplate
# MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) # MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)

View File

@ -12,7 +12,7 @@
# email_title :string(255) # email_title :string(255)
# #
# 在修中@我 # 在修中@我
class MessageTemplate::IssueAtme < MessageTemplate class MessageTemplate::IssueAtme < MessageTemplate
# MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) # MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)

View File

@ -12,7 +12,7 @@
# email_title :string(255) # email_title :string(255)
# #
# 我创建或负责的修状态变更 # 我创建或负责的修状态变更
class MessageTemplate::IssueChanged < MessageTemplate 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"]}) # 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"]})
@ -29,7 +29,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) 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) url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
change_count = change_params.keys.size change_count = change_params.keys.size
# 修负责人修改 # 修负责人修改
if change_params[:assigned_to_id].present? if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
@ -44,7 +44,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '') content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end end
# 修状态修改 # 修状态修改
if change_params[:status_id].present? if change_params[:status_id].present?
status1 = IssueStatus.find_by_id(change_params[:status_id][0]) status1 = IssueStatus.find_by_id(change_params[:status_id][0])
status2 = IssueStatus.find_by_id(change_params[:status_id][1]) status2 = IssueStatus.find_by_id(change_params[:status_id][1])
@ -59,7 +59,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifstatus})(.*)({endstatus})/, '') content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
end end
# 修类型修改 # 修类型修改
if change_params[:tracker_id].present? if change_params[:tracker_id].present?
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0]) tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1]) tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
@ -74,7 +74,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({iftracker})(.*)({endtracker})/, '') content.gsub!(/({iftracker})(.*)({endtracker})/, '')
end end
# 修里程碑修改 # 修里程碑修改
if change_params[:fixed_version_id].present? if change_params[:fixed_version_id].present?
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
@ -89,7 +89,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end end
# 修标记修改 # 修标记修改
if change_params[:issue_tags_value].present? if change_params[:issue_tags_value].present?
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
@ -106,7 +106,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({iftag})(.*)({endtag})()/, '') content.gsub!(/({iftag})(.*)({endtag})()/, '')
end end
# 修优先级修改 # 修优先级修改
if change_params[:priority_id].present? if change_params[:priority_id].present?
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
@ -121,7 +121,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifpriority})(.*)({endpriority})/, '') content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end end
# 修完成度修改 # 修完成度修改
if change_params[:done_ratio].present? if change_params[:done_ratio].present?
doneratio1 = change_params[:done_ratio][0] doneratio1 = change_params[:done_ratio][0]
doneratio2 = change_params[:done_ratio][1] doneratio2 = change_params[:done_ratio][1]
@ -136,7 +136,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '') content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
end end
# 修指定分支修改 # 修指定分支修改
if change_params[:branch_name].present? if change_params[:branch_name].present?
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0] branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1] branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
@ -151,7 +151,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifbranch})(.*)({endbranch})/, '') content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
end end
# 修开始日期修改 # 修开始日期修改
if change_params[:start_date].present? if change_params[:start_date].present?
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0] startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1] startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
@ -166,7 +166,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
else else
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '') content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
end end
# 修结束日期修改 # 修结束日期修改
if change_params[:due_date].present? if change_params[:due_date].present?
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0] duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1] duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
@ -191,177 +191,181 @@ class MessageTemplate::IssueChanged < MessageTemplate
return '', '', '' if change_params.blank? return '', '', '' if change_params.blank?
if receiver.user_template_message_setting.present? if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"] return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"]
end project = issue&.project
project = issue&.project owner = project&.owner
owner = project&.owner title = email_title
title = email_title title.gsub!('{title}', issue&.subject)
title.gsub!('{title}', issue&.subject) content = email
content = email content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{receiver}', receiver&.real_name) content.gsub!('{baseurl}', base_url)
content.gsub!('{baseurl}', base_url) content.gsub!('{login1}', operator&.login)
content.gsub!('{login1}', operator&.login) content.gsub!('{nickname1}', operator&.real_name)
content.gsub!('{nickname1}', operator&.real_name) content.gsub!('{login2}', owner&.login)
content.gsub!('{login2}', owner&.login) content.gsub!('{nickname2}', owner&.real_name)
content.gsub!('{nickname2}', owner&.real_name) content.gsub!('{identifier}', project&.identifier)
content.gsub!('{identifier}', project&.identifier) content.gsub!('{repository}', project&.name)
content.gsub!('{repository}', project&.name) content.gsub!('{title}', issue&.subject)
content.gsub!('{title}', issue&.subject) content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{id}', issue&.id.to_s) change_count = change_params.keys.size
change_count = change_params.keys.size # 疑修负责人修改
# 易修负责人修改 if change_params[:assigned_to_id].present?
if change_params[:assigned_to_id].present? assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) if change_count > 1
if change_count > 1 content.sub!('{ifassigner}', '<br/>')
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 else
content.sub!('{ifassigner}', '') content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end end
content.sub!('{endassigner}', '') # 疑修状态修改
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员') if change_params[:status_id].present?
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员') status1 = IssueStatus.find_by_id(change_params[:status_id][0])
else status2 = IssueStatus.find_by_id(change_params[:status_id][1])
content.gsub!(/({ifassigner})(.*)({endassigner})/, '') if change_count > 1
end content.sub!('{ifstatus}', '<br/>')
# 易修状态修改 else
if change_params[:status_id].present? content.sub!('{ifstatus}', '')
status1 = IssueStatus.find_by_id(change_params[:status_id][0]) end
status2 = IssueStatus.find_by_id(change_params[:status_id][1]) content.sub!('{endstatus}', '')
if change_count > 1 content.gsub!('{status1}', status1&.name)
content.sub!('{ifstatus}', '<br/>') content.gsub!('{status2}', status2&.name)
else else
content.sub!('{ifstatus}', '') content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
end end
content.sub!('{endstatus}', '') # 疑修类型修改
content.gsub!('{status1}', status1&.name) if change_params[:tracker_id].present?
content.gsub!('{status2}', status2&.name) tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
else tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
content.gsub!(/({ifstatus})(.*)({endstatus})/, '') if change_count > 1
end content.sub!('{iftracker}', '<br/>')
# 易修类型修改 else
if change_params[:tracker_id].present? content.sub!('{iftracker}', '')
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0]) end
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1]) content.sub!('{endtracker}', '')
if change_count > 1 content.gsub!('{tracker1}', tracker1&.name)
content.sub!('{iftracker}', '<br/>') content.gsub!('{tracker2}', tracker2&.name)
else else
content.sub!('{iftracker}', '') content.gsub!(/({iftracker})(.*)({endtracker})/, '')
end end
content.sub!('{endtracker}', '') # 疑修里程碑修改
content.gsub!('{tracker1}', tracker1&.name) if change_params[:fixed_version_id].present?
content.gsub!('{tracker2}', tracker2&.name) fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
else fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
content.gsub!(/({iftracker})(.*)({endtracker})/, '') if change_count > 1
end content.sub!('{ifmilestone}', '<br/>')
# 易修里程碑修改 else
if change_params[:fixed_version_id].present? content.sub!('{ifmilestone}', '')
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) end
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) content.sub!('{endmilestone}', '')
if change_count > 1 content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑')
content.sub!('{ifmilestone}', '<br/>') content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑')
else else
content.sub!('{ifmilestone}', '') content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
end end
content.sub!('{endmilestone}', '') # 疑修标记修改
content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑') if change_params[:issue_tags_value].present?
content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑') issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
else issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",")
end tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",")
# 易修标记修改 if change_count > 1
if change_params[:issue_tags_value].present? content.sub!('{iftag}', '<br/>')
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct else
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct content.sub!('{iftag}', '')
tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",") end
tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",") content.sub!('{endtag}', '')
if change_count > 1 content.gsub!('{tag1}', tag1)
content.sub!('{iftag}', '<br/>') content.gsub!('{tag2}', tag2)
else else
content.sub!('{iftag}', '') content.gsub!(/({iftag})(.*)({endtag})()/, '')
end end
content.sub!('{endtag}', '') # 疑修优先级修改
content.gsub!('{tag1}', tag1) if change_params[:priority_id].present?
content.gsub!('{tag2}', tag2) priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
else priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
content.gsub!(/({iftag})(.*)({endtag})()/, '') if change_count > 1
end content.sub!('{ifpriority}', '<br/>')
# 易修优先级修改 else
if change_params[:priority_id].present? content.sub!('{ifpriority}', '')
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) end
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) content.sub!('{endpriority}', '')
if change_count > 1 content.gsub!('{priority1}', priority1&.name)
content.sub!('{ifpriority}', '<br/>') content.gsub!('{priority2}', priority2&.name)
else else
content.sub!('{ifpriority}', '') content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
end end
content.sub!('{endpriority}', '') # 疑修完成度修改
content.gsub!('{priority1}', priority1&.name) if change_params[:done_ratio].present?
content.gsub!('{priority2}', priority2&.name) doneratio1 = change_params[:done_ratio][0]
else doneratio2 = change_params[:done_ratio][1]
content.gsub!(/({ifpriority})(.*)({endpriority})/, '') if change_count > 1
end content.sub!('{ifdoneratio}', '<br/>')
# 易修完成度修改 else
if change_params[:done_ratio].present? content.sub!('{ifdoneratio}', '')
doneratio1 = change_params[:done_ratio][0] end
doneratio2 = change_params[:done_ratio][1] content.sub!('{enddoneratio}', '')
if change_count > 1 content.gsub!('{doneratio1}', "#{doneratio1}%")
content.sub!('{ifdoneratio}', '<br/>') content.gsub!('{doneratio2}', "#{doneratio2}%")
else else
content.sub!('{ifdoneratio}', '') content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
end end
content.sub!('{enddoneratio}', '') # 疑修指定分支修改
content.gsub!('{doneratio1}', "#{doneratio1}%") if change_params[:branch_name].present?
content.gsub!('{doneratio2}', "#{doneratio2}%") branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
else branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '') if change_count > 1
end content.sub!('{ifbranch}', '<br/>')
# 易修指定分支修改 else
if change_params[:branch_name].present? content.sub!('{ifbranch}', '')
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0] end
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1] content.sub!('{endbranch}', '')
if change_count > 1 content.gsub!('{branch1}', branch1)
content.sub!('{ifbranch}', '<br/>') content.gsub!('{branch2}', branch2)
else else
content.sub!('{ifbranch}', '') content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
end end
content.sub!('{endbranch}', '') # 疑修开始日期修改
content.gsub!('{branch1}', branch1) if change_params[:start_date].present?
content.gsub!('{branch2}', branch2) startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
else startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
content.gsub!(/({ifbranch})(.*)({endbranch})/, '') if change_count > 1
end content.sub!('{ifstartdate}', '<br/>')
# 易修开始日期修改 else
if change_params[:start_date].present? content.sub!('{ifstartdate}', '')
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0] end
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1] content.sub!('{endstartdate}', '')
if change_count > 1 content.gsub!('{startdate1}', startdate1 )
content.sub!('{ifstartdate}', '<br/>') content.gsub!('{startdate2}', startdate2)
else else
content.sub!('{ifstartdate}', '') content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
end end
content.sub!('{endstartdate}', '') # 疑修结束日期修改
content.gsub!('{startdate1}', startdate1 ) if change_params[:due_date].present?
content.gsub!('{startdate2}', startdate2) duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
else duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '') if change_count > 1
end content.sub!('{ifduedate}', '<br/>')
# 易修结束日期修改 else
if change_params[:due_date].present? content.sub!('{ifduedate}', '')
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0] end
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1] content.sub!('{endduedate}', '')
if change_count > 1 content.gsub!('{duedate1}', duedate1)
content.sub!('{ifduedate}', '<br/>') content.gsub!('{duedate2}', duedate2)
else else
content.sub!('{ifduedate}', '') content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
end end
content.sub!('{endduedate}', '') content.gsub!('{platform}', PLATFORM)
content.gsub!('{duedate1}', duedate1)
content.gsub!('{duedate2}', duedate2)
else
content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
end
return receiver&.mail, title, content return receiver&.mail, title, content
else
return '', '', ''
end
rescue => e rescue => e
Rails.logger.info("MessageTemplate::IssueChanged.get_email_message_content [ERROR] #{e}") Rails.logger.info("MessageTemplate::IssueChanged.get_email_message_content [ERROR] #{e}")
return '', '', '' return '', '', ''

View File

@ -1,29 +1,3 @@
# == 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 class MessageTemplate::IssueCreatorExpire < MessageTemplate
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) end
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

@ -12,7 +12,7 @@
# email_title :string(255) # email_title :string(255)
# #
# 我创建或负责的修删除 # 我创建或负责的修删除
class MessageTemplate::IssueDeleted < MessageTemplate class MessageTemplate::IssueDeleted < MessageTemplate
# MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah") # MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah")
@ -33,17 +33,20 @@ class MessageTemplate::IssueDeleted < MessageTemplate
def self.get_email_message_content(receiver, operator, issue_title) def self.get_email_message_content(receiver, operator, issue_title)
if receiver.user_template_message_setting.present? if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"] return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"]
end title = email_title
title = email_title title.gsub!('{title}', issue_title)
title.gsub!('{title}', issue_title) content = email
content = email content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{receiver}', receiver&.real_name) content.gsub!('{nickname}', operator&.real_name)
content.gsub!('{nickname}', operator&.real_name) content.gsub!('{login}', operator&.login)
content.gsub!('{login}', operator&.login) content.gsub!('{baseurl}', base_url)
content.gsub!('{baseurl}', base_url) content.gsub!('{title}', issue_title)
content.gsub!('{title}', issue_title) content.gsub!('{platform}', PLATFORM)
return receiver&.mail, title, content return receiver&.mail, title, content
else
return '', '', ''
end
rescue => e rescue => e
Rails.logger.info("MessageTemplate::IssueDeleted.get_email_message_content [ERROR] #{e}") Rails.logger.info("MessageTemplate::IssueDeleted.get_email_message_content [ERROR] #{e}")
return '', '', '' return '', '', ''

View File

@ -0,0 +1,67 @@
# == 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::IssueExpire < MessageTemplate
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
def self.get_message_content(receivers, issue)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
send_setting = receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueExpire"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["CreateOrAssign::IssueExpire"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless send_setting
end
end
return '', '', '' if receivers.blank?
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::IssueExpire.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, issue)
if receiver.user_template_message_setting.present?
send_setting = receiver.user_template_message_setting.email_body["CreateOrAssign::IssueExpire"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["CreateOrAssign::IssueExpire"] : send_setting
return '', '', '' unless send_setting
project = issue&.project
owner = project&.owner
title = email_title
content = email
content.gsub!('{receiver}', receiver&.real_name)
content.gsub!('{nickname}', owner&.real_name)
content.gsub!('{login}', 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)
content.gsub!('{platform}', PLATFORM)
return receiver&.mail, title, content
else
return '', '', ''
end
rescue => e
Rails.logger.info("MessageTemplate::IssueExpire.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

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