Compare commits

...

1304 Commits

Author SHA1 Message Date
xxq250 46a11d20d9 fixed 2024-11-08 18:13:29 +08:00
xxq250 c8151bd472 fixed 2024-11-08 18:09:12 +08:00
xxq250 70e0754315 fixed 附件uuid生成暂不使用 2024-11-08 15:42:03 +08:00
xxq250 4d9e36a683 fixed 竞赛bmfile导出 2024-11-08 15:33:12 +08:00
xxq250 f9ce7e27cc fixed 竞赛同步外网 2024-11-08 14:45:23 +08:00
xxq250 3bcb06d9e3 fixed 竞赛上传作品附件不是必需 2024-10-21 10:30:39 +08:00
xxq250 f8a525edff fixed 竞赛部分接口必须登录 2024-09-29 14:40:00 +08:00
xxq250 ee6af7fb7a fixed 竞赛部分接口必须登录 2024-09-29 14:18:25 +08:00
xxq250 23581902fb fixed 竞赛增加服务器时间 2024-09-29 09:38:40 +08:00
xxq250 3d22022042 fixed admin_data管理员数据保护 2024-09-24 09:32:36 +08:00
xxq250 996195b5f4 fixed 竞赛提交作品导出同步内网 2024-07-17 08:35:15 +08:00
xxq250 4290b60f7e 增加敏感词 2024-05-16 10:18:05 +08:00
yystopf 36b34aebe0 修复:未保存数据 2024-04-12 09:55:27 +08:00
yystopf 68bdf7856e 新增:需求字段 2024-04-12 09:15:28 +08:00
yystopf 96d3b9eb2c 新增:列表判断是否为成员 2024-04-10 20:03:57 +08:00
yystopf 516f0a9f4e 新增:移除用户同时移除申请 2024-04-10 17:19:56 +08:00
yystopf 83ed606912 新增:列表返回remark 2024-04-10 13:57:06 +08:00
yystopf cc6d9c668e 新增:创建审核记录remark字段 2024-04-10 10:59:35 +08:00
yystopf 9bbb66f890 新增:通过审核发送消息 2024-04-09 17:02:51 +08:00
yystopf 07324662e5 修复 2024-04-09 15:56:21 +08:00
yystopf 8922593e3d 更改:消息获取来源 2024-04-09 15:24:11 +08:00
yystopf c03693dd07 新增:阅读记录about访问申请 2024-04-09 14:43:29 +08:00
yystopf d1f2236f56 新增:组织项目列表is_need_apply参数 2024-04-09 11:23:49 +08:00
yystopf c646865024 更改:查询申请的name 2024-04-08 17:28:52 +08:00
yystopf 74d99b3785 更改:需要登录才能操作 2024-04-08 15:26:41 +08:00
yystopf e3393eb101 更改:一个人只显示一条记录 2024-04-08 11:41:57 +08:00
yystopf 364a83f496 更改 2024-04-08 11:09:13 +08:00
yystopf 27e0683f3f 更改:是否开启特定功能使用edusetting 2024-04-08 11:05:31 +08:00
yystopf ae7209cdfe 新增:字段返回 2024-04-08 10:39:42 +08:00
yystopf 1fddae4f95 修复 2024-04-08 10:29:15 +08:00
yystopf 17f58f8871 修复 2024-04-08 10:27:05 +08:00
yystopf d9a8e7ea0d 新增:用户手机号字段返回 2024-04-08 10:25:32 +08:00
yystopf 796d95a8f8 新增:用户手机号字段返回 2024-04-08 10:18:21 +08:00
yystopf 6c2b897aff 新增:用户类型字段返回 2024-04-08 09:42:48 +08:00
yystopf ce0f70c836 修复:找不到type 2024-04-08 08:48:07 +08:00
yystopf baf2d03668 更改:埋点触发条件 2024-04-08 08:36:13 +08:00
yystopf 8e846b5884 新增:项目访问埋点及查看 2024-04-07 17:28:24 +08:00
yystopf 207da14a72 修复 2024-04-07 15:20:00 +08:00
yystopf 2db2ebe9a3 新增:访问审核项目当前用户信息 2024-04-07 15:15:47 +08:00
yystopf 2c3cfb0dd6 修复 2024-04-07 12:36:08 +08:00
yystopf 01a6aaafdc 新增:is_need_apply字段 2024-04-07 11:53:41 +08:00
yystopf e84664bec1 修复 2024-04-07 11:41:51 +08:00
yystopf f12b8a300d 新增:访问审核功能接口 2024-04-07 11:35:48 +08:00
yystopf 36ae4a9cb5 新增:组织featured_content 2024-04-03 15:14:52 +08:00
xxq250 a37e3fd91d Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2024-03-11 15:16:54 +08:00
xxq250 4374115512 fixed openkylin批量镜像项目更新时间密集化处理,导致列表项目密集 2024-03-11 15:16:46 +08:00
yystopf f6c6d4d671 fixed 2024-03-06 16:55:57 +08:00
yystopf ac2d50f125 fixed 2024-03-06 16:53:35 +08:00
yystopf 3134081577 更改:图片可以为空 2024-03-06 16:46:25 +08:00
yystopf 0188dcb435 修复:banner允许为空 2024-03-06 16:08:40 +08:00
yystopf 816b95caf9 Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2024-03-06 15:22:27 +08:00
yystopf 7129518a0a 修复:banner允许为空 2024-03-06 15:22:04 +08:00
xxq250 679d630b6f fixed 增加开源协议,并支持对应文件下载 2024-02-23 09:17:32 +08:00
xxq250 f3f797fef1 增加开源协议,并支持对应文件下载 2024-02-23 09:15:40 +08:00
xxq250 8d124a5128 增加开源协议,并支持对应文件下载 2024-02-01 15:13:13 +08:00
xxq250 35f724c901 合并错误代码 2024-02-01 14:19:06 +08:00
xxq250 9106bb5d47 容错处理 2024-02-01 14:05:19 +08:00
xxq250 f3ccf7c03c Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2024-01-31 15:48:44 +08:00
xxq250 8b8fb883cc 内网509接入登录 2024-01-31 15:48:20 +08:00
yystopf 54c6d7d8df 新增:组织logo图片为空提示 2024-01-18 10:05:40 +08:00
yystopf 8e5feb4da9 修复:代码回滚 2024-01-17 14:29:43 +08:00
yystopf 05453a6283 新增:首页组织logo配置 2024-01-17 14:21:07 +08:00
yystopf 7062397ea3 修复:项目搜索标签不能更新为空 2024-01-17 11:14:31 +08:00
yystopf 8e6fdf3b3e 新增:项目搜索标签可在项目设置接口更改 2024-01-16 15:47:48 +08:00
yystopf e7f279ca41 更改:详情新增项目搜索标签返回 2024-01-16 15:44:45 +08:00
yystopf 132d2fbf0c 新增:项目搜索标签删除逻辑 2024-01-16 15:27:00 +08:00
yystopf 2594a4ba1b 更改:项目列表使用topic_id查询时应返回对应的总数 2024-01-16 15:16:55 +08:00
yystopf 4b9b10c914 新增:kaminary_select_paginate函数缺失 2024-01-16 14:50:36 +08:00
yystopf a5b0973dcc 新增:项目搜索标签功能 2024-01-16 14:39:18 +08:00
xxq250 af033bb8d0 废弃代码 2023-10-18 11:34:44 +08:00
xxq250 482578ced7 转移仓库时取消提示新拥有者资料不完善 2023-09-18 10:40:38 +08:00
xxq250 72469f9104 fixed 风雷协议配置 2023-09-13 16:14:11 +08:00
xxq250 3ff361ebb9 fixed 重置密码gitea同步修改 2023-09-12 17:36:32 +08:00
xxq250 569dd6820a 新增:声明感知view 2023-09-12 17:27:49 +08:00
xxq250 7c5e58cae0 新增:声明感知 2023-09-12 17:25:26 +08:00
xxq250 75e9c47bef 新增:声明感知 2023-09-12 17:20:32 +08:00
yystopf 0f4ca060da 新增:声明感知消息 2023-09-12 17:16:17 +08:00
xxq250 34118ff816 注册增加昵称 2023-08-14 16:31:34 +08:00
xxq250 edf0655fb2 台后管理项目类别css 2023-07-10 15:21:49 +08:00
xxq250 4121a90a16 台后管理项目类别css 2023-07-10 15:21:38 +08:00
xxq250 023c23991b 台后管理项目类别css 2023-07-10 15:21:01 +08:00
xxq250 9d54310f1f 台后管理项目类别 2023-07-10 15:19:11 +08:00
xxq250 9fc47bc675 管理员查询所有项目参数 2023-07-06 10:09:26 +08:00
xxq250 6132641ef5 管理员查询所有项目参数 2023-07-06 09:55:18 +08:00
xxq250 50adbd74df Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2023-07-05 18:08:27 +08:00
xxq250 449762b3ea 管理员查询所有项目参数 2023-07-05 18:07:06 +08:00
xxq250 f307158909 readme GBK编码问题 执行顺序调整 2023-06-30 17:03:58 +08:00
xxq250 1b1bb860f7 readme GBK编码问题 log del 2023-06-30 16:22:07 +08:00
xxq250 e375851a37 readme GBK编码问题 log 2023-06-30 16:21:06 +08:00
xxq250 de4376f91f readme GBK编码问题 2023-06-30 14:47:33 +08:00
xxq250 c1ee08ffa4 readme GBK编码问题 2023-06-30 14:34:23 +08:00
xxq250 c795a2a36d readme GBK格式处理 log 2023-06-30 11:32:50 +08:00
xxq250 5372183776 readme GBK格式处理 log 2023-06-30 11:30:25 +08:00
xxq250 c42e8c4b80 readme GBK格式处理 2023-06-30 11:25:59 +08:00
xxq250 448a6c17da readme GBK格式处理 2023-06-30 11:24:41 +08:00
xxq250 e60445057a readme GBK格式处理 2023-06-30 11:21:45 +08:00
xxq250 b32cbccb80 readme GBK格式处理 2023-06-30 11:16:24 +08:00
xxq250 25d1c5f13d Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2023-06-30 10:38:30 +08:00
xxq250 238e5fc65c entries 不需要文件内容 2023-06-30 10:38:22 +08:00
xxq250 7eca07fc06 竞赛删除 2023-06-28 10:56:56 +08:00
xxq250 fdd62a602e config demo 2023-06-27 10:40:44 +08:00
xxq250 b86eba4725 config demo 2023-06-26 14:22:21 +08:00
xxq250 49c96df25d config demo 2023-06-26 14:19:38 +08:00
xxq250 0266968d2c gem 固定 2023-06-26 14:09:10 +08:00
xxq250 f6ef2f5648 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2023-06-26 11:41:44 +08:00
xxq250 b468740b15 gem 固定 2023-06-26 11:41:31 +08:00
xxq250 fce38e3fb7 register入口 2023-06-13 17:01:05 +08:00
xxq250 019e0a540b 风雷协议权限 2023-06-13 16:31:59 +08:00
xxq250 517678f5ae 日志调整 2023-06-13 16:15:00 +08:00
xxq250 7632fa3988 竞赛打分zstp2023 2023-06-13 13:56:06 +08:00
xxq250 bd45e7167e 竞赛打分zstp2023 2023-06-13 13:51:44 +08:00
xxq250 66927793fa 竞赛打分zstp2023 2023-06-13 11:45:54 +08:00
xxq250 2b613ecc7b 竞赛打分zstp2023 2023-06-13 11:35:08 +08:00
xxqfamous ccfb367a88 竞赛打分 2023-06-07 10:23:14 +08:00
xxq250 75faa6bf76 fixed oauth force_ssl_in_redirect_uri false 2023-05-18 11:32:34 +08:00
xxq250 e4e0b0ce57 fixed 查询项目时当前用户包含私有 2023-05-15 22:58:06 +08:00
xxq250 7fdf1af411 增加sidekiq线程 2023-04-25 11:14:31 +08:00
xxq250 2a956d02ed openkylin导入 2023-04-25 10:58:47 +08:00
xxq250 7c249ea9fa openkylin导入 2023-04-25 10:51:03 +08:00
xxq250 73d441397c 组织语言缓存处理 2023-04-10 15:13:21 +08:00
xxq250 dc1d6ce219 fixed 项目列表私有项目查询错误 2023-01-05 09:59:25 +08:00
xxq250 7e019e95ab fixed 项目列表私有项目查询错误 2023-01-05 09:53:17 +08:00
xxq250 ec0846f223 fixed 项目增加项目团队搜索 2023-01-04 11:45:08 +08:00
xxq250 4ca3b66228 项目增加项目团队搜索 2022-12-27 16:07:33 +08:00
xxq250 1010b2a863 项目增加项目团队搜索 2022-12-27 16:04:56 +08:00
xxq250 1d832d1ba7 项目增加项目团队搜索 2022-12-27 16:03:16 +08:00
xxq250 3b3fad7e3c 项目增加项目团队搜索 2022-12-27 15:58:44 +08:00
xxq250 16d8bf8f81 项目增加项目团队搜索 2022-12-27 15:53:10 +08:00
xxq250 5604ee036d 项目增加项目团队搜索 2022-12-27 15:36:50 +08:00
xxq250 31797af44c 项目导出增加项目地址 2022-12-26 11:52:05 +08:00
xxq250 d369741900 项目导出增加地址 2022-12-26 11:47:28 +08:00
xxq250 f69d423672 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-12-14 09:39:19 +08:00
xxq250 28d45a48a1 组织精选项目作者 2022-12-14 09:39:11 +08:00
yystopf ccec8e9819 Merge branch 'develop' into dev_jk_server 2022-12-12 16:17:22 +08:00
yystopf bf5c226117 修复:cherry-pick from develop 2022-12-12 14:26:08 +08:00
yystopf 0f8d2e6a5d 更改:gitea-client 版本更新 2022-12-12 14:25:02 +08:00
xxq250 6cdaafe4e0 组织精选项目作者 2022-12-12 14:08:45 +08:00
xxq250 0e49f81eaf 本地版不需要三方授权登录 2022-12-12 09:57:02 +08:00
yystopf 204554b34c Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-12-09 11:45:36 +08:00
yystopf bc2992cc3d 新增:后台管理更改用户信息邮箱需同步至gitea 2022-12-09 11:45:31 +08:00
xxq250 a631d423c6 fixed 项目跳转链接修正 2022-12-09 11:07:00 +08:00
xxq250 edd1d27b0a fixed 用户项目跳转链接修正 2022-12-09 11:04:24 +08:00
xxq250 3edac3656a fixed 下载文件类增加xlsx,Makefile可显示 2022-12-08 18:14:43 +08:00
xxq250 d0b638cbc0 fixed 下载文件类增加xlsx,Makefile可显示 2022-12-08 17:16:21 +08:00
xxq250 1c16b74f1b fixed 下载文件类增加xlsx,Makefile可显示 2022-12-08 17:15:33 +08:00
yystopf 983f488177 fixed 第三方授权登录配置支持Get方法 2022-12-08 14:31:20 +08:00
yystopf dfa0f1161d Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-12-08 11:52:06 +08:00
yystopf bc6f5cec4d 新增:仓库贡献者行数查询接口 2022-12-08 11:51:59 +08:00
xxq250 ee27c90205 fixed qq命名调整,方便封装 2022-12-06 10:24:48 +08:00
xxq250 aab1e42240 本地版不需要验证码 2022-12-06 09:44:37 +08:00
xxq250 0ec06bf54d 本地版不需要验证码 2022-12-06 09:42:18 +08:00
xxq250 5d9f9cdfb0 本地版区分标识 2022-12-06 09:22:52 +08:00
xxq250 534ee80523 Merge remote-tracking branch 'origin/develop' into develop 2022-12-05 17:46:25 +08:00
xxq250 daf7514afe fixed 第三方授权登录配置 2022-12-05 17:46:21 +08:00
yystopf 4b1f1c697e 更改:下载excel文件不走跳转 2022-12-02 13:59:41 +08:00
yystopf 77c7acd582 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-12-02 12:11:30 +08:00
yystopf 025a6a53e9 修复:图片无法下载的问题 2022-12-02 12:11:24 +08:00
xxq250 6b846b10bb fixed 第三方授权登录(github,gitee,qq,wechat) 2022-12-01 17:51:54 +08:00
xxq250 763d7b499e fixed 第三方授权登录(github,gitee,qq,wechat) 2022-12-01 17:22:22 +08:00
yystopf 9b39446dfb 修复:提交文件内容格式由前端决定 2022-11-29 17:08:26 +08:00
yystopf c6e77ac7ee 修复:提交文件未创建新分支时为空判断 2022-11-29 17:02:10 +08:00
yystopf f5cdb6f02d 新增:旧统计接口移除处理 2022-11-29 14:31:14 +08:00
yystopf f7ca03db81 修复:通用分支移除projects_activity表修改 2022-11-28 11:41:36 +08:00
xxq250 8da8b021f6 Merge remote-tracking branch 'origin/develop' into develop 2022-11-28 11:20:01 +08:00
xxq250 70ba78a9b5 fixed 组织用户不存在 2022-11-28 11:19:56 +08:00
yystopf 6191ddd233 修复:通用分支移除声明表修改 2022-11-28 10:57:05 +08:00
xxq250 35cf298f5d fixed 增加emoji表情支持表字段,长度限制 2022-11-25 14:19:05 +08:00
xxq250 ee5d959404 fixed 增加emoji表情支持表字段,长度限制 2022-11-25 14:15:47 +08:00
xxq250 7f47cd8d46 fixed 增加emoji表情支持表字段 2022-11-25 14:09:26 +08:00
xxq250 06c0ac65bf Merge remote-tracking branch 'origin/develop' into develop 2022-11-23 17:58:56 +08:00
xxq250 8f8dab10c3 fixed 增加emoji表情支持 2022-11-23 17:58:51 +08:00
yystopf a6923bf7ed 新增:get_user_info电话号码展示 2022-11-23 17:44:37 +08:00
“xxq250” 667dca0553 Merge remote-tracking branch 'origin/develop' into develop 2022-11-23 17:07:59 +08:00
“xxq250” f23f02cb80 fixed 增加emoji表情支持 2022-11-23 17:07:54 +08:00
yystopf 38a8191b74 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-11-16 15:27:54 +08:00
yystopf e183f48c02 修复:合并请求查询关闭类型须根据合并请求类型查询 2022-11-16 15:27:49 +08:00
“xxq250” a1731f91a9 fixed 附件下载权限 2022-11-15 17:12:10 +08:00
yystopf ea7cf1cd1f 修复:排序字段 2022-11-15 15:17:06 +08:00
yystopf 255b615327 更改:项目首页分类后数量更改 2022-11-15 14:41:08 +08:00
yystopf 64c6f69f56 新增:统计项目分类下私有项目的数量 2022-11-15 14:25:35 +08:00
yystopf 49abadfa3f 新增:合并请求合并之后挂载的issue设置为关闭 2022-11-11 14:13:38 +08:00
yystopf 4cde7c374e 更改:反馈意见编辑器隐藏上传按钮 2022-11-11 14:04:36 +08:00
yystopf b56930b9ab 修复:反馈意见发送邮件失败错误返回 2022-11-11 12:25:25 +08:00
yystopf f98886b3a0 修复 2022-11-11 11:50:07 +08:00
yystopf 30572aa41c 修复:重复代码移除 2022-11-11 11:11:34 +08:00
yystopf ef83697cb8 修复:tooltip闪烁问题 2022-11-10 16:21:43 +08:00
yystopf 570f664c27 修复:标记issue数量问题 2022-11-10 11:02:50 +08:00
yystopf e24921bba3 修复 2022-11-09 14:56:27 +08:00
yystopf e4d62c5335 新增:字符串截取展示 2022-11-09 14:54:43 +08:00
yystopf 6d9cf8aad2 修复 2022-11-09 14:41:17 +08:00
yystopf e3179dfd6e 新增:新增反馈意见邮件回复功能 2022-11-09 14:35:11 +08:00
yystopf 7817487ab7 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-11-09 11:37:18 +08:00
yystopf 83b46fcb50 新增:用户反馈意见后台管理逻辑 2022-11-09 11:37:12 +08:00
“xxq250” 7cc9d207b6 fixed 项目列表查询count优化 2022-11-08 17:18:04 +08:00
“xxq250” abfb62f342 fixed 项目优化排序 2022-11-08 17:16:25 +08:00
“xxq250” ccbbab0741 fixed 项目优化排序 2022-11-08 15:33:12 +08:00
yystopf 3e5c1da2c5 新增:反馈意见模型及接口 2022-11-08 13:27:46 +08:00
“xxq250” 1731d5fc20 fixed 小程序活动后台管理问题修复 2022-11-07 15:15:04 +08:00
“xxq250” 8cce97258c fixed 小程序活动后台管理 2022-11-07 11:36:31 +08:00
“xxq250” 4ea60a5114 fixed 小程序活动后台管理 2022-11-07 11:34:15 +08:00
“xxq250” dd7be1c392 fixed 小程序活动报名信息 2022-11-04 16:34:36 +08:00
“xxq250” dbc1ea107c fixed 小程序活动报名信息 2022-11-04 14:37:52 +08:00
“xxq250” a4df928c5a fixed 小程序活动报名信息 2022-11-04 14:30:44 +08:00
“xxq250” ab842a6f1a fixed 小程序活动报名信息 2022-11-04 14:22:26 +08:00
“xxq250” 4636a1b3b6 fixed 小程序活动 2022-11-04 11:30:51 +08:00
“xxq250” 591119016e Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-11-04 11:29:49 +08:00
“xxq250” 16fc6ebc4e fixed 小程序活动 2022-11-04 11:27:39 +08:00
viletyy 6a3cc56f85 Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2022-11-04 11:24:31 +08:00
viletyy eac812a7bf merge from develop 2022-11-04 11:24:25 +08:00
“xxq250” 4560b9231e fixed 小程序活动 2022-11-04 11:23:47 +08:00
“xxq250” f3d7938750 fixed 项目名称模糊搜索 2022-11-02 17:04:31 +08:00
“xxq250” 23dc04b560 fixed 项目名称模糊搜索 2022-11-02 17:02:58 +08:00
yystopf 07aefa79eb 更改:项目后台管理移除精选设置 2022-11-02 14:21:49 +08:00
yystopf 423d5a9316 修复:同步项目权限到组织时需预先判断是否存在于团队中 2022-11-01 15:29:07 +08:00
yystopf 9664ca001e 新增: 邮箱验证码重新发送后之前的验证码需设置为无效 2022-10-27 17:57:55 +08:00
“xxq250” f0a67c2f98 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-27 17:16:37 +08:00
“xxq250” b3c1845dbf fixed 配置文件更新 2022-10-27 17:16:33 +08:00
yystopf d613b1f3bb 修复 2022-10-27 16:58:53 +08:00
yystopf c8e063343e 更改:用户排行榜数量以及项目排行榜默认精选项目 2022-10-27 16:46:00 +08:00
“xxq250” 75a78c839d fixed 第三方登录用户名生成 2022-10-27 14:12:29 +08:00
yystopf e15809c186 修复:无法正常转移的问题 2022-10-27 10:48:24 +08:00
yystopf 7d4c0df691 修复 2022-10-27 09:55:55 +08:00
yystopf e72dfa4973 修复:项目迁移设置权限在更改拥有者之后 2022-10-27 09:28:52 +08:00
yystopf 84a8339a04 修复 2022-10-26 15:16:06 +08:00
yystopf 3d5b2e76d7 修复:update_column无法触发count_cache 2022-10-26 14:58:04 +08:00
yystopf 8b14ee3c72 修复:更改组织下项目权限同时更改组织下权限同步至gitea 2022-10-26 14:49:40 +08:00
“xxq250” 10b3eb8a7b 导入用户 2022-10-25 22:04:56 +08:00
“xxq250” f39873efd8 导入用户 2022-10-25 22:02:59 +08:00
“xxq250” f880b316b9 导入用户 2022-10-25 22:00:11 +08:00
“xxq250” 074b999b2b 导入用户 2022-10-25 21:57:27 +08:00
“xxq250” ee17acf7cf Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-25 14:17:35 +08:00
“xxq250” e7af767d02 fixed 第三方登录 2022-10-25 14:17:31 +08:00
yystopf 5b30943feb 修复 2022-10-25 11:14:21 +08:00
yystopf 722f355fe4 修复 2022-10-25 11:07:05 +08:00
yystopf f8f9f3fbb6 新增:消息来源类型匹配 2022-10-25 11:02:51 +08:00
“xxq250” 84186fe694 fixed 竞赛按排序列号排序 2022-10-24 18:05:15 +08:00
“xxq250” d080727633 fixed 竞赛按排序列号排序 2022-10-24 18:02:30 +08:00
“xxq250” 96165a3eec fixed 资讯增加活动报名 2022-10-24 17:57:48 +08:00
“xxq250” 14d8a248d7 fixed 资讯增加活动报名 2022-10-24 17:37:53 +08:00
“xxq250” eb7f4e6da3 fixed 资讯增加活动报名 2022-10-24 16:21:42 +08:00
“xxq250” ef867e1e83 导入用户 2022-10-22 22:41:45 +08:00
“xxq250” 4c4f4396fe 导入用户 2022-10-22 22:27:32 +08:00
“xxq250” e99333113f 导入用户 2022-10-22 22:23:19 +08:00
“xxq250” 7b63fd6b9f fixed 第三方登录email生成 2022-10-21 17:52:24 +08:00
“xxq250” 20b97286e3 fixed 第三方Gitlink登录log 2022-10-21 17:44:28 +08:00
“xxq250” 3a4f6888fb fixed 第三方Gitlink登录log 2022-10-21 17:24:47 +08:00
“xxq250” da48675900 fixed 第三方Gitlink登录log 2022-10-21 17:21:42 +08:00
“xxq250” 74b84f9f86 fixed 第三方Gitlink登录 2022-10-21 17:14:59 +08:00
“xxq250” dbafeb5cee fixed 第三方Gitlink登录 2022-10-21 17:02:18 +08:00
“xxq250” 5ce3b4cea4 fixed 第三方登录 2022-10-21 16:09:17 +08:00
yystopf 3f7366fbcd 修复:更改用户通知邮箱只能自己改自己的 2022-10-21 15:28:48 +08:00
yystopf cfdbc5a682 修复 2022-10-21 15:07:31 +08:00
yystopf 9b880e3209 修复 2022-10-21 15:04:26 +08:00
yystopf c2ef23b746 修复 2022-10-21 14:42:51 +08:00
yystopf 8a33ea6707 修复 2022-10-21 14:40:43 +08:00
yystopf 9ee4c85b7c 更改:验证返回status以及万能验证码 2022-10-21 14:31:32 +08:00
“xxq250” 97da0f908f Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-20 09:42:19 +08:00
“xxq250” 3ea9f0017d fixed 组织包含自己 2022-10-20 09:39:37 +08:00
viletyy 8da237e5b9 Merge branch 'develop' into dev_jk_server 2022-10-19 16:18:41 +08:00
yystopf e9b23d6577 更改:合并请求代码冲突提示语更改 2022-10-19 16:17:44 +08:00
yystopf 64d9c334ce 修复:项目语言验证信息统一 2022-10-19 15:18:15 +08:00
viletyy d832939038 fix 2022-10-18 15:55:32 +08:00
viletyy c0e1ed9d12 Merge branch 'develop' into dev_jk_server 2022-10-18 15:54:59 +08:00
yystopf cad7e24299 修复:项目列表表头样式 2022-10-18 15:53:37 +08:00
viletyy 2a9448517c 修复:readme replace_content缺失 2022-10-18 15:36:11 +08:00
viletyy 5e5fb6e122 Merge branch 'develop' into dev_jk_server 2022-10-18 14:59:48 +08:00
yystopf 3b15dd84fc 新增:标签列表返回总数 2022-10-18 14:52:15 +08:00
viletyy 2bf84c0d5e merge from develop 2022-10-18 13:53:31 +08:00
yystopf 58a43a8b80 更改:合并请求和issue仅加载开启中的里程碑 2022-10-18 13:43:16 +08:00
yystopf e25231738a 新增:标签名字列表 2022-10-18 13:32:57 +08:00
yystopf 35965f542a 新增:标签名字列表 2022-10-18 13:31:12 +08:00
yystopf fa48e3f5ca 修复:许可证和忽略文件内容为空表单提示 2022-10-18 11:14:35 +08:00
viletyy e4e0564228 Merge branch 'develop' into dev_jk_server 2022-10-17 17:37:27 +08:00
yystopf 13e2738fb5 新增:列表页新增only_watched参数 2022-10-17 17:37:03 +08:00
“xxq250” e5f95fa9b5 后台用户管理列表增加专业领域查询 2022-10-17 14:50:22 +08:00
“xxq250” 4416e8bd4f Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-17 14:43:49 +08:00
“xxq250” 5391c97873 后台用户管理列表增加专业领域 2022-10-17 14:43:44 +08:00
viletyy b5df0bb93b merge from develop 2022-10-17 13:18:57 +08:00
yystopf 30437d828c 新增:项目git忽略文件新增验证 2022-10-17 13:16:22 +08:00
yystopf dcc7ab6738 更改:项目分类去掉图片上传 2022-10-17 13:01:08 +08:00
yystopf 57a7a17f73 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-10-17 12:57:32 +08:00
yystopf 5196f33f24 新增:项目许可证新增验证 2022-10-17 12:57:24 +08:00
“xxq250” 480f2b6516 Merge branch 'develop' into dev_jk_server
# Conflicts:
#	app/controllers/attachments_controller.rb
#	app/controllers/members_controller.rb
2022-10-17 11:16:10 +08:00
“xxq250” ee3cacb6c8 fixed 项目语言管理唯一性 2022-10-17 11:14:31 +08:00
“xxq250” b3cbed2963 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	app/controllers/members_controller.rb
2022-10-17 11:09:48 +08:00
“xxq250” dd1af6712c fixed 项目成员提示修改 2022-10-17 11:08:54 +08:00
“xxq250” fc37f18022 fixed 项目语言管理唯一性 2022-10-17 11:07:56 +08:00
“xxq250” bab6efb23d fixed 项目语言管理唯一性 2022-10-17 11:05:46 +08:00
“xxq250” c20599d742 fixed 项目语言管理唯一性 2022-10-17 11:04:13 +08:00
“xxq250” 817b8d3650 fixed 项目成员提示修改 2022-10-17 10:55:21 +08:00
yystopf 8807be6e4d 新增:项目语言新增唯一性验证 2022-10-17 10:52:57 +08:00
yystopf 8d41c27044 更改:项目成员添加提示 2022-10-17 10:42:40 +08:00
yystopf 53fe554d1e 更改:后台管理表头样式 2022-10-17 10:25:17 +08:00
“xxq250” 4e02dbe06b Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	app/controllers/attachments_controller.rb
2022-10-17 10:14:13 +08:00
“xxq250” 620ddff9bb fixed issue评论附件权限 2022-10-17 10:13:30 +08:00
“xxq250” 54bd088ae5 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-17 10:07:50 +08:00
“xxq250” 2af3671811 fixed issue评论附件权限 2022-10-17 10:07:45 +08:00
yystopf 630a7aadeb 新增:组织数据修复任务 2022-10-15 11:29:23 +08:00
yystopf 6383384287 更改:后台管理用户真实姓名改为昵称 2022-10-14 15:31:20 +08:00
yystopf 83f1263f85 修复:更改查询项目判断条件 2022-10-14 14:52:25 +08:00
谢思 e4158d7d3a Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2022-10-14 11:15:40 +08:00
谢思 d328108d9e delete doc 2022-10-14 11:15:34 +08:00
谢思 304fd72f27 update image 2022-10-14 11:14:57 +08:00
“xxq250” 9e62d959fc fixed 三方登录 2022-10-13 16:51:17 +08:00
“xxq250” 63b349c9f3 fixed 竞赛列表可访问 2022-10-12 16:27:39 +08:00
“xxq250” 538d0f7d0f fixed 竞赛增加是否关注 2022-10-12 16:16:22 +08:00
“xxq250” edc0d16c52 fixed 竞赛增加访问量visits 2022-10-12 10:57:30 +08:00
“xxq250” 548a983a7a fixed 竞赛增加访问量 2022-10-12 10:32:40 +08:00
“xxq250” 1852070f5b fixed 竞赛增加开始时间 2022-10-11 16:16:44 +08:00
“xxq250” 433e94de3c fixed 竞赛排序 2022-10-11 15:00:34 +08:00
“xxq250” 9362201452 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-11 14:24:13 +08:00
“xxq250” b416b12914 实名认证状态 2022-10-11 14:24:08 +08:00
yystopf 89f57fa4fc fix: merge from develop 2022-10-10 19:10:55 +08:00
yystopf 9c11cd79e8 修复:消息模版无法查询子类的问题 2022-10-10 19:06:47 +08:00
“xxq250” 86b5d9cb20 竞赛通知模板 2022-10-10 16:35:48 +08:00
“xxq250” ca33c77ff1 nav logo 2022-10-10 16:04:50 +08:00
“xxq250” 9464aadd95 fixed zip下载 2022-10-10 15:01:42 +08:00
“xxq250” 803c468a80 增加gitlink授权登录service 2022-10-10 14:46:30 +08:00
“xxq250” 46c57186b4 增加gitlink授权登录service 2022-10-10 14:40:21 +08:00
“xxq250” 2e116548db 增加gitlink授权登录 2022-10-10 14:33:15 +08:00
“xxq250” 3777fa26a0 增加gitlink授权登录 2022-10-10 14:13:46 +08:00
“xxq250” 65b12bb93a 注册增加领域配置 2022-10-10 13:56:15 +08:00
“xxq250” 4e4f68bd2c 导入用户 2022-10-10 09:10:01 +08:00
“xxq250” 22983c518e fixed 竞赛关注数量 2022-10-09 14:22:33 +08:00
“xxq250” b075fdc3c1 fixed 关注竞赛列表,唯一标识也可 2022-10-09 11:46:34 +08:00
“xxq250” 4c450a6bbc fixed 关注竞赛列表 2022-10-09 11:03:00 +08:00
“xxq250” 16205927d8 fixed 关注竞赛 2022-10-09 10:05:39 +08:00
“xxq250” d446fecbef fixed 关注竞赛 2022-10-09 10:01:04 +08:00
“xxq250” 1c1450a9a4 关注竞赛 2022-10-09 09:57:57 +08:00
“xxq250” 56921a1801 关注竞赛 2022-10-09 09:51:07 +08:00
“xxq250” f0be159722 导入用户 2022-10-08 21:35:15 +08:00
yystopf a7384bc1c3 修复:代码详情页报错 2022-10-08 18:44:04 +08:00
“xxq250” 4b4dfc17e1 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-10-08 15:37:07 +08:00
“xxq250” 997ab5a8f8 注册增加专业领域 2022-10-08 15:37:01 +08:00
谢思 e11a5c0848 update image 2022-10-08 15:06:58 +08:00
谢思 f1df84d725 add image 2022-10-08 15:00:09 +08:00
谢思 26bac63c8e update image 2022-10-08 14:41:24 +08:00
谢思 9263676f01 add image 2022-10-08 14:24:03 +08:00
“xxq250” 4ab868acc5 导入用户 2022-10-07 21:17:14 +08:00
“xxq250” 127a4c6998 导入用户 2022-10-06 18:21:30 +08:00
“xxq250” 026916abb1 导入用户 2022-10-05 21:53:39 +08:00
“xxq250” dc0c493970 导入用户 2022-10-04 20:52:37 +08:00
“xxq250” a77f070f69 导入用户 2022-10-03 22:24:37 +08:00
“xxq250” 6cf7b86cc4 导入用户 2022-09-30 18:18:39 +08:00
“xxq250” 328e6d1192 导入用户 2022-09-30 13:45:32 +08:00
“xxq250” 3fb184e3cc 导入用户 2022-09-29 21:42:16 +08:00
yystopf 55170c7693 新增:更改邮箱相关接口文档 2022-09-29 13:58:14 +08:00
“xxq250” 6b5d19916b Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-29 13:56:46 +08:00
“xxq250” c086eb5f83 导入用户 2022-09-29 13:55:52 +08:00
yystopf 2cde13eabb 新增:接口测试以及功能测试 2022-09-29 12:05:57 +08:00
yystopf d68e7f38a3 新增:更改邮箱service逻辑 2022-09-29 09:30:33 +08:00
谢思 2fd6d3619c add images 2022-09-29 09:20:23 +08:00
“xxq250” 1fb0b27630 导入用户 2022-09-28 21:33:18 +08:00
“xxq250” 3abd2c13e9 fixed oauth2.0 授权成功 2022-09-28 16:19:22 +08:00
yystopf 649d9c4ea6 新增:更改邮箱控制器方法 2022-09-28 16:09:10 +08:00
“xxq250” ca57477dcb fixed osredm3.ico 2022-09-28 14:56:13 +08:00
“xxq250” 043e1b5237 fixed oauth2.0 logged 2022-09-28 14:53:08 +08:00
“xxq250” bcc2579910 fixed oauth2.0 logged 2022-09-28 14:47:12 +08:00
“xxq250” 3836270622 导入用户 2022-09-28 14:17:05 +08:00
“xxq250” b7c3c7c5eb fixed oauth2.0 logo 2022-09-28 10:42:16 +08:00
“xxq250” 15d4336c00 fixed oauth2.0 layout 2022-09-28 10:37:08 +08:00
“xxq250” c367eaca10 fixed oauth2.0 2022-09-28 10:31:32 +08:00
“xxq250” 9fbbd9805f fixed oauth2.0 2022-09-28 10:28:16 +08:00
“xxq250” 095e1c7b7b fixed oauth2.0 2022-09-28 10:22:11 +08:00
“xxq250” d401634af3 导入用户 2022-09-28 07:43:00 +08:00
“xxq250” 14022c0ccc 导入用户 2022-09-27 18:12:33 +08:00
“xxq250” 95303c5394 合并develop代码,js zip 2022-09-27 16:15:15 +08:00
“xxq250” 1701890e1a 合并develop代码,GiteaService.gitea_config 2022-09-27 15:59:19 +08:00
“xxq250” 63f8ca06df 合并develop代码,pr_reviews 2022-09-27 15:50:16 +08:00
“xxq250” a74335fd12 合并develop代码,pr_reviews 2022-09-27 15:46:14 +08:00
“xxq250” 497342bcff 合并develop代码,pr_reviews 2022-09-27 15:43:23 +08:00
“xxq250” 0f6ebbbf2f 合并develop代码 2022-09-27 15:35:30 +08:00
“xxq250” cb302b50dd Merge branch 'develop' into dev_jk_server
# Conflicts:
#	app/assets/javascripts/admin.js
#	app/controllers/accounts_controller.rb
#	app/controllers/application_controller.rb
#	app/controllers/attachments_controller.rb
#	app/controllers/concerns/login_helper.rb
#	app/controllers/concerns/register_helper.rb
#	app/controllers/concerns/render_helper.rb
#	app/controllers/concerns/repository/languages_percentagable.rb
#	app/controllers/repositories_controller.rb
#	app/controllers/users/is_pinned_projects_controller.rb
#	app/controllers/users_controller.rb
#	app/docs/slate/source/api.html.md
#	app/docs/slate/source/includes/_projects.md
#	app/docs/slate/source/includes/_pulls.md
#	app/docs/slate/source/includes/_repositories.md
#	app/docs/slate/source/includes/_teams.md
#	app/docs/slate/source/includes/_users.md
#	app/helpers/application_helper.rb
#	app/imports/admins/new_import_user_from_excel.rb
#	app/libs/custom_regexp.rb
#	app/models/journal.rb
#	app/models/project.rb
#	app/models/user.rb
#	app/queries/admins/user_query.rb
#	app/services/admins/import_user_from_excel_service.rb
#	app/views/admins/users/index.html.erb
#	app/views/members/index.json.jbuilder
#	app/views/settings/show.json.jbuilder
#	config/routes.rb
#	public/导入用户模板.xlsx
2022-09-27 15:32:46 +08:00
“xxq250” a8cf9b21c8 导入用户 2022-09-27 13:46:28 +08:00
“xxq250” 60eebead05 导入用户 2022-09-27 07:14:36 +08:00
“xxq250” fce8166ba7 fixed 用户活跃数 2022-09-26 16:11:34 +08:00
“xxq250” 81d29d3809 用户搜索文案 2022-09-26 16:03:25 +08:00
“xxq250” b0e6f2bcd3 导入用户 2022-09-26 15:44:13 +08:00
“xxq250” c44755f8d7 后台增加导出用户 2022-09-26 15:43:24 +08:00
“xxq250” f5f74f7333 导入用户 2022-09-26 12:32:06 +08:00
“xxq250” ae0efc1115 Merge remote-tracking branch 'origin/develop' into develop 2022-09-26 10:38:32 +08:00
“xxq250” dfc2edd62d fixed注册gitea错误信息 2022-09-26 10:38:28 +08:00
“xxq250” 84de681777 导入用户 2022-09-25 19:55:12 +08:00
“xxq250” 260737f417 导入用户 2022-09-24 21:53:38 +08:00
yystopf d7f3a21add 修复:周统计数据需加入年份 2022-09-23 17:56:39 +08:00
“xxq250” fd07a8c6ae 竞赛增加小程序banner配置 2022-09-23 11:02:00 +08:00
yystopf ef9592ef30 更改:活跃度算法更新 2022-09-23 10:28:12 +08:00
“xxq250” f072a2a7f3 小程序banner增加显示位置 2022-09-23 10:25:21 +08:00
yystopf cc42683316 新增:活跃度计算访问量限制 2022-09-23 10:07:52 +08:00
“xxq250” 8d28b41357 导入用户增加用户类型 2022-09-22 16:22:27 +08:00
“xxq250” a247d5fc7a 导入用户增加用户类型 2022-09-22 16:21:44 +08:00
“xxq250” 3d9aeef8b4 导入用户增加用户类型 2022-09-22 14:57:19 +08:00
“xxq250” 2790f91f1b 导入用户增加用户类型 2022-09-22 14:55:57 +08:00
“xxq250” dfe884ec47 导入用户 2022-09-22 14:42:04 +08:00
“xxq250” da28624c0a 导入用户 2022-09-22 10:25:24 +08:00
“xxq250” 05ca426004 项目详情增加时间语言 2022-09-22 10:24:34 +08:00
yystopf 70f1e6827f 更改:项目已设置语言,则不重新设置语言 2022-09-21 10:06:29 +08:00
yystopf b5188e3272 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-09-21 09:54:53 +08:00
yystopf ff881732d2 更改:项目已设置语言,则不重新设置语言 2022-09-21 09:54:49 +08:00
“xxq250” 0373d08fdc 项目详情增加时间语言 2022-09-20 15:06:40 +08:00
“xxq250” 3ef6ed306f 项目详情增加时间语言 2022-09-20 15:06:27 +08:00
“xxq250” 9ab130f81e 项目详情增加时间语言 2022-09-20 15:04:32 +08:00
“xxq250” 20790f7548 fixed pull_request统计 2022-09-20 14:14:25 +08:00
“xxq250” 2adf87a289 fixed nps数据统计 2022-09-20 09:52:40 +08:00
“xxq250” 6954a860af fixed nps数据统计 2022-09-20 09:47:29 +08:00
“xxq250” bb8e6aeaf8 nps数据统计 2022-09-20 09:41:27 +08:00
“xxq250” b38daf634f fixed 修改密码接口缺少参数 2022-09-19 10:07:32 +08:00
“xxq250” 6d7b7dd058 fixed 修改密码接口 2022-09-19 10:06:49 +08:00
“xxq250” ec0358d6b2 修改密码token skip 2022-09-19 09:25:49 +08:00
“xxq250” 03075b8d48 fixed 后台项目列表issue数量 2022-09-16 11:11:17 +08:00
“xxq250” 6b67344493 后台项目列表导出 2022-09-15 17:05:11 +08:00
“xxq250” ede998ebef 注册接口调整 2022-09-15 16:11:18 +08:00
“xxq250” fba7c7f8b9 去掉namespace为空检测 2022-09-15 16:07:50 +08:00
“xxq250” 4e29cabdef 去掉注册确认密码 2022-09-15 16:05:00 +08:00
“xxq250” 199240962a 注册增加单位和类型 2022-09-15 16:01:23 +08:00
“xxq250” 8608e2d67a 注册增加单位和类型 2022-09-15 15:57:12 +08:00
“xxq250” acaea1901d 更换短信模板 2022-09-15 13:52:10 +08:00
“xxq250” 28d2bbe9a1 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-15 11:42:26 +08:00
“xxq250” a954081f74 特殊开源许可证项目管理开关 2022-09-15 11:42:20 +08:00
谢思 c12f49a987 add image 2022-09-15 11:36:15 +08:00
“xxq250” 180fd51395 banner搜索 2022-09-15 11:22:58 +08:00
“xxq250” 4a566bb0f4 banner图必传 2022-09-15 11:02:57 +08:00
“xxq250” 3f1803b2e5 banner排序号必填 2022-09-15 10:54:59 +08:00
“xxq250” ddeea66dc1 社区动态同步为贴子发布时间 2022-09-15 10:38:25 +08:00
“xxq250” 1f6fa921e8 社区动态同步为贴子发布时间 2022-09-15 10:37:03 +08:00
“xxq250” f780d3a91e 社区动态同步为贴子时间 2022-09-15 10:34:54 +08:00
“xxq250” f2d652fafe 社区动态同步为贴子时间 2022-09-15 10:30:13 +08:00
“xxq250” 369e87ab92 社区动态同步为贴子时间 2022-09-15 10:28:50 +08:00
“xxq250” 9850adfdb5 banner搜索 2022-09-15 10:23:19 +08:00
yystopf 007b90c284 修复:删除旧的逻辑 2022-09-15 10:00:00 +08:00
yystopf 481d1b7db0 修复:commit log统计触发规则 2022-09-15 09:57:28 +08:00
yystopf 733f64eaec 新增:项目排行榜新增提交数算法 2022-09-15 09:44:12 +08:00
yystopf 383660c778 更改:组织缓存信息方式改在控制器里面 2022-09-15 09:38:28 +08:00
“xxq250” 5674800c97 删除用户刷新 2022-09-14 18:16:53 +08:00
“xxq250” 2609908d6b 取消请完善资料后再操作 2022-09-14 18:03:03 +08:00
“xxq250” 2352e1a677 时区读取本地系统local 2022-09-14 17:41:26 +08:00
“xxq250” 618d4ad995 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-14 17:16:27 +08:00
“xxq250” 32823ce9f9 用户信息增加类型搜索 2022-09-14 17:16:21 +08:00
谢思 daa098abf2 Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2022-09-14 16:42:17 +08:00
谢思 0cfe16a8d3 add image 2022-09-14 16:42:13 +08:00
“xxq250” 80ec837964 用户信息增加单位和类型 2022-09-14 16:21:40 +08:00
“xxq250” 090d76ad69 fixed 项目列表查询排序,风雷改为可配置 2022-09-14 09:28:57 +08:00
“xxq250” 517d84c3bd fixed 项目列表查询排序,风雷改为可配置 2022-09-14 09:24:14 +08:00
“xxq250” 851577ea7c fixed 项目列表查询排序,风雷改为可配置 2022-09-14 09:23:22 +08:00
“xxq250” 8fdb2df0ef fixed 项目列表查询排序,增加推荐 2022-09-14 09:19:11 +08:00
“xxq250” 12c91ca680 fixed 项目列表查询排序fork项目放后面 2022-09-13 18:02:46 +08:00
“xxq250” d3967f25ad fixed 项目列表查询排序fork项目放后面 2022-09-13 17:55:35 +08:00
yystopf 9509dc5af2 修复 2022-09-13 11:55:20 +08:00
yystopf cd39370fe5 新增: 同步平台统计数量任务 2022-09-13 11:51:09 +08:00
yystopf 4ed846a68b 更改:导入用户规则 2022-09-13 08:54:56 +08:00
谢思 f22ffcb7c4 update image login 2022-09-09 16:21:06 +08:00
谢思 bd5ffae6ad update image login 2022-09-09 16:06:56 +08:00
谢思 708d66361c update image login 2022-09-09 15:31:30 +08:00
谢思 f997a8a101 update image login 2022-09-09 14:47:37 +08:00
谢思 17cf3b6c87 update image login 2022-09-09 13:34:48 +08:00
谢思 1ae1188421 update image login 2022-09-09 10:48:22 +08:00
谢思 ed84b387d5 update image login 2022-09-09 10:15:13 +08:00
谢思 4bab6d1876 add image login 2022-09-09 09:54:29 +08:00
“xxq250” 35b4fa0e94 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-08 15:30:15 +08:00
“xxq250” 3b4d84fef9 fixed 推荐项目标识 2022-09-08 15:30:09 +08:00
谢思 8168329ba9 Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2022-09-08 15:18:43 +08:00
谢思 89ab25974d update image 2022-09-08 15:17:21 +08:00
“xxq250” e8ce1e46d4 fixed 返回状态码修正 2022-09-08 14:28:07 +08:00
“xxq250” 2e046f313f Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-08 14:22:27 +08:00
“xxq250” 63c40a2025 fixed 返回状态码 2022-09-08 14:22:22 +08:00
yystopf 4bd77a870b 更改:webhook创建数量限制为50个 2022-09-08 14:19:08 +08:00
谢思 4ca4bcac02 Merge branch 'dev_jk_server' of https://gitlink.org.cn/Trustie/forgeplus into dev_jk_server 2022-09-08 14:04:00 +08:00
谢思 3350b80e92 add image 2022-09-08 14:02:56 +08:00
yystopf b1f460d760 更改:webhook创建数量限制为50个 2022-09-08 10:40:52 +08:00
“xxq250” eaa0364e97 注册增加没有密码时初始密码的短信发送 2022-09-08 10:03:42 +08:00
“xxq250” f2b7ae2f22 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-08 10:03:11 +08:00
“xxq250” 3ec44cbfa3 注册增加没有密码时初始密码的短信发送 2022-09-08 10:03:06 +08:00
谢思 1ca3db70b8 add image 2022-09-07 13:51:17 +08:00
“xxq250” 1193acc3a9 token访问 2022-09-06 17:01:14 +08:00
“xxq250” 640094def7 token访问 2022-09-06 16:43:43 +08:00
“xxq250” 6c0bd6a6fe fixed 竞赛列表分页 2022-09-06 16:34:38 +08:00
“xxq250” f3b78cb40d fixed 竞赛列表分页 2022-09-06 15:33:31 +08:00
yystopf a438ab6f3e 新增:提示语locale配置 2022-09-06 14:57:54 +08:00
“xxq250” f5ebe5c5f1 竞赛列表分页 2022-09-06 14:19:16 +08:00
“xxq250” ba97339821 竞赛列表分页 2022-09-06 14:11:43 +08:00
“xxq250” 240e2b22ab 竞赛列表非登录可访问 2022-09-06 14:10:38 +08:00
“xxq250” fef03e6d22 竞赛列表非登录可访问 2022-09-06 14:07:17 +08:00
“xxq250” c42fa03b8b 竞赛上架下架开关 2022-09-06 13:51:50 +08:00
“xxq250” 783474cbd9 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-09-06 11:15:16 +08:00
“xxq250” ed909f620d 小程序banner配置 2022-09-06 11:15:10 +08:00
“xxq250” 3a34d8682c Merge remote-tracking branch 'origin/develop' into develop 2022-09-06 10:30:15 +08:00
“xxq250” 60894f00b1 nps已打分区分 2022-09-06 10:29:51 +08:00
“xxq250” 925b05e004 nps已打分区分 2022-09-06 10:29:49 +08:00
何童崇 9b465dd6cb 添加小程序图片 2022-09-06 10:14:00 +08:00
yystopf 4878d66620 修复 2022-09-06 09:04:46 +08:00
yystopf 632ade9d25 修复 2022-09-06 09:02:30 +08:00
yystopf 5acd45bf85 修复 2022-09-06 09:00:05 +08:00
yystopf d03b45eecf 新增:创建文件对分支长度进行验证 2022-09-06 08:59:24 +08:00
yystopf 0193381d1f 新增:导入用户创建user关联entity 2022-08-31 14:17:49 +08:00
“xxq250” 32a9d762d8 调整nps用户调研接口,需要登录 2022-08-31 10:39:52 +08:00
“xxq250” 0a79950046 调整nps用户调研接口 2022-08-31 10:38:21 +08:00
“xxq250” 4b7c58b13f Merge remote-tracking branch 'origin/develop' into develop 2022-08-30 18:10:33 +08:00
“xxq250” 7148957368 nps用户调研 2022-08-30 18:10:27 +08:00
yystopf aa50c50254 修复 2022-08-30 10:40:27 +08:00
yystopf 60b3c7925d 新增:添加全部或者移除全部团队项目[文档] 2022-08-30 10:34:37 +08:00
yystopf 0f41cabe71 新增:添加全部或者移除全部团队项目 2022-08-30 10:23:35 +08:00
“xxq250” d04ed7e008 fixed 组织成员列表查询优化 2022-08-29 10:05:56 +08:00
“xxq250” c6b35d83d3 fixed 用户管理增加查询条件css 2022-08-23 17:13:21 +08:00
“xxq250” 8776f48f62 fixed 用户管理增加修改企业认证状态 2022-08-23 17:10:11 +08:00
“xxq250” 197c70927d fixed 用户管理增加查询条件 2022-08-23 17:07:41 +08:00
“xxq250” 8ac0c1fcd1 用户管理增加查询条件 2022-08-23 17:01:03 +08:00
“xxq250” fc5aff287f 用户管理增加查询条件 2022-08-23 17:00:17 +08:00
“xxq250” 82835969be 用户管理增加查询条件 2022-08-23 16:57:28 +08:00
“xxq250” b5409fa7e5 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-08-23 16:56:18 +08:00
“xxq250” 3303d801ea 用户管理增加查询条件 2022-08-23 16:56:11 +08:00
yystopf 6168256897 修复: diff filepath为空报错 2022-08-22 10:48:05 +08:00
yystopf 62c5345889 Merge pull request '同步GitLink导入用户功能' (#21) from yystopf/forgeplus:dev_jk_server into dev_jk_server 2022-08-18 16:44:49 +08:00
yystopf e8b8dc682a fix: import user login length required 2022-08-18 16:42:03 +08:00
yystopf 73f41d555c add: download and import user template xlsx 2022-08-18 16:41:52 +08:00
“xxq250” 6eadacb3f0 fixed 发行版 2022-08-18 10:07:37 +08:00
yystopf 4b167dacbb 修复: trace user 手机号为空 2022-08-17 18:39:01 +08:00
yystopf 911c47df8d 新增:文件blame 上个版本的行号 2022-08-17 18:05:15 +08:00
yystopf a37d7b9840 修复: 手机号默认不传 2022-08-17 15:28:58 +08:00
“xxq250” 217ab920a9 fixed commit日志同时更新项目时间 2022-08-16 15:33:15 +08:00
“xxq250” 98ae62d181 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-08-16 14:28:52 +08:00
“xxq250” 98f1723411 fixed 发行版git删除时,不同步处理 2022-08-16 14:28:40 +08:00
yystopf 68a38e75bc 修复: 消息返回接口时间 2022-08-16 14:07:37 +08:00
yystopf ee29c6be5c Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-08-15 15:55:37 +08:00
yystopf c0ee0a694c 更改:代码溯源status改为code 2022-08-15 15:55:33 +08:00
“xxq250” 25fa6f427b Merge remote-tracking branch 'origin/develop' into develop 2022-08-15 14:03:32 +08:00
“xxq250” 467d722d25 fixed reposyncer job任务增加分页 2022-08-15 14:03:27 +08:00
“xxq250” f552fef4e2 rake导入外部项目 2022-08-12 17:48:09 +08:00
yystopf 3e352d3c7c 新增:获取代码溯源系统维护信息接口 2022-08-12 17:23:19 +08:00
“xxq250” fbdb4cbf39 rake导入外部项目 2022-08-12 17:22:02 +08:00
yystopf 13472b2311 新增: 合并请求评论查询is_full 2022-08-11 15:21:11 +08:00
“xxq250” bdddd655bf Merge remote-tracking branch 'origin/develop' into develop 2022-08-11 09:31:49 +08:00
“xxq250” 6ec7a13293 fixed reposyncer 分支组合已配置,不能重复 2022-08-11 09:31:40 +08:00
“xxq250” 716b29c25f fixed 消息模板配置type 2022-08-11 09:29:37 +08:00
“xxq250” 5c4930a362 fixed 消息模板配置type 2022-08-11 09:29:36 +08:00
“xxq250” ad8fed9440 fixed 消息模板配置type 2022-08-11 09:29:35 +08:00
“xxq250” 964bef7896 fixed 消息模板配置type 2022-08-11 09:29:34 +08:00
“xxq250” 7e48e5e8b8 fixed 消息模板配置 2022-08-11 09:29:34 +08:00
“xxq250” 48846a7e31 fixed 已读未读标记优化 2022-08-11 09:29:33 +08:00
yystopf 32db15aad5 新增: commit找不到返回404 2022-08-11 09:29:12 +08:00
“xxq250” 8ec3e4bbaa fixed Gitea::PullRequest::FilesService增加参数 2022-08-11 09:28:12 +08:00
yystopf 4b05838498 新增:合并请求评论新增path参数筛选以及去掉分页最多返回200数据 2022-08-09 09:48:02 +08:00
“xxq250” 2fe5fc369c 组织项目风雷协议特别处理 2022-08-05 16:46:11 +08:00
yystopf b8be0c23cb 修复 2022-08-05 11:05:29 +08:00
yystopf d20a7b1318 修复:项目协作者添加组织成员问题 2022-08-05 10:50:41 +08:00
yystopf f8268accc0 新增: 组织下项目协作者添加当前用户 2022-08-04 17:28:14 +08:00
yystopf a9811768d4 修复: 合并请求评论类型允许为空 2022-08-04 15:46:19 +08:00
yystopf 024bc289de 修改: 合并请求评论必选参数以及审查列表去掉分页 2022-08-03 17:13:45 +08:00
yystopf 96d34d0237 修改:合并请求审查权限 2022-08-03 15:31:04 +08:00
yystopf fea11bdc2e 新增:webhook type类型 2022-08-03 14:20:25 +08:00
“xxq250” d0a164434c 设置跨域域名和ip访问 2022-08-03 11:02:32 +08:00
yystopf ab5d273f98 新增:版本diff新增diff信息 2022-08-02 19:03:54 +08:00
“xxq250” 8bf4e9b8d2 fixed Repository.url 2022-08-02 18:10:01 +08:00
yystopf 096b0b954d 新增: fork仓库协作者可以提交文件至仓库 2022-08-01 17:14:32 +08:00
yystopf df57312056 修复 2022-07-29 17:29:25 +08:00
“xxq250” 59b256dd78 fixed banner url 2022-07-29 15:49:32 +08:00
“xxq250” cfadde830f fixed 组织新闻增加标题和跳转url 2022-07-29 14:54:24 +08:00
“xxq250” f12cfabee3 fixed 精选项目不包含私有仓库 2022-07-28 17:30:09 +08:00
“xxq250” 350783b833 fixed 语言接口token参数错误 2022-07-28 17:22:41 +08:00
“xxq250” b22909a654 fixed 语言接口token参数错误 2022-07-28 17:20:22 +08:00
“xxq250” 579b45dfa4 fixed 精选项目不包含私有仓库 2022-07-28 17:19:39 +08:00
“xxq250” fbc1f95cd1 Merge remote-tracking branch 'origin/develop' into develop 2022-07-28 16:42:29 +08:00
“xxq250” 4ccf8ea5ff CloudIDEA文件标记已读未读 2022-07-28 16:42:21 +08:00
“xxq250” 45a2661f99 fixed 精选项目不包含私有仓库 2022-07-28 16:25:00 +08:00
“xxq250” 2d306e20fb fixed 精选项目不包含私有仓库 2022-07-28 16:10:48 +08:00
“xxq250” f306a5008f fixed 精选项目不包含私有仓库 2022-07-28 16:04:59 +08:00
“xxq250” fc064a53d1 fixed 组织创建不需要完善资料 2022-07-28 15:44:28 +08:00
“xxq250” dc6e62b784 fixed 组织语言百分比相加,降序排序 2022-07-28 15:40:26 +08:00
“xxq250” 20b8a6c005 fixed 组织语言百分比相加,排序 2022-07-28 15:33:33 +08:00
yystopf d5c141f892 修复:pulls文件夹load 2022-07-28 15:19:31 +08:00
“xxq250” e467794901 fixed 组织语言百分比相加 2022-07-28 15:14:47 +08:00
“xxq250” e098216af8 fixed 组织语言 2022-07-28 14:53:34 +08:00
“xxq250” 809cce9085 fixed 组织语言 2022-07-28 14:38:03 +08:00
yystopf 35c6cb98db 新增:批量提交文件支持参数选填 2022-07-28 14:25:33 +08:00
yystopf f417e42864 修复: 提示修改 2022-07-28 14:02:37 +08:00
yystopf 6e54203ebb 修复:批量提交文件参数缺失以及数据为空处理 2022-07-28 13:56:31 +08:00
“xxq250” 79a6841bbc Merge remote-tracking branch 'origin/develop' into develop 2022-07-28 09:31:19 +08:00
“xxq250” b3d78741a3 fixed reposyncer同步仓库接口增加gitlink 2022-07-28 09:31:14 +08:00
“xxq250” 91884b9d2d fixed 组织新闻和介结合并 2022-07-27 16:50:44 +08:00
“xxq250” 6182405108 移植gitlink中banner模块 html 2022-07-27 16:22:35 +08:00
“xxq250” 35336701fa banner配置增加跳转URL 2022-07-27 16:17:43 +08:00
“xxq250” ac82e14eba banner配置增加跳转URL 2022-07-27 16:17:25 +08:00
yystopf 935f3ddf7f Merge pull request '合并请求评论相关接口及文档' (#20) from yystopf/forgeplus:develop into develop 2022-07-27 16:11:17 +08:00
“xxq250” 5ca2cc69ac 移植gitlink中banner模块 html 2022-07-27 16:10:17 +08:00
yystopf a2549f7ff1 新增: 评论及审查相关接口文档 2022-07-27 16:07:15 +08:00
“xxq250” 0a87973e71 移植gitlink中banner模块 2022-07-27 16:02:55 +08:00
“xxq250” a6099973d7 fixed 组织新闻和介结合并 2022-07-27 15:48:32 +08:00
“xxq250” 8b6ae143c0 fixed projects查询 2022-07-27 15:20:18 +08:00
“xxq250” 862186a8f2 fixed 增加组织的新闻和介绍route 2022-07-27 15:18:06 +08:00
“xxq250” fcfd64f353 fixed 增加组织的新闻和介绍 2022-07-27 15:14:55 +08:00
“xxq250” 755c1f9492 fixed 增加组织的新闻和介绍 2022-07-27 15:14:47 +08:00
“xxq250” f85e50a5f0 fixed 增加组织的新闻和介绍 2022-07-27 15:12:27 +08:00
“xxq250” 0f0d348d9f 增加组织的新闻和介绍 2022-07-27 15:03:27 +08:00
yystopf d6b5dc326a 新增: 评论相关api根据需求重写 2022-07-27 14:52:49 +08:00
“xxq250” 53b6ffb15a fixed 增加组织的精选项目配置 2022-07-27 14:14:23 +08:00
“xxq250” 380ef5e057 增加组织的精选项目配置 2022-07-27 14:04:00 +08:00
“xxq250” e69f9263b2 fixed 复赛单位调整 2022-07-27 09:21:39 +08:00
“xxq250” 003bfe7884 Merge remote-tracking branch 'origin/develop' into develop 2022-07-26 17:08:10 +08:00
“xxq250” df5efa0dc6 fixed 邮箱验证正则优化 2022-07-26 17:08:05 +08:00
yystopf a35db9fe80 新增:reviewers修改入口 2022-07-26 16:45:53 +08:00
yystopf 6183f1f76d 修复: 缺少title和body 2022-07-26 14:38:41 +08:00
yystopf e72273f3b2 修复: 合并请求详情中review需要最新的一个 2022-07-26 14:29:12 +08:00
yystopf cc09f724cc Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-07-26 14:14:33 +08:00
yystopf 7a54c5f536 新增: 接口文档更新 2022-07-26 14:14:25 +08:00
“xxq250” bb3f5cec76 fixed reposyncer同步仓库接口 2022-07-26 11:40:49 +08:00
“xxq250” 19ffd9fea1 fixed PullRequest 统一关联关系字段gitea_id 2022-07-26 10:55:42 +08:00
“xxq250” 5877474f59 Merge remote-tracking branch 'origin/develop' into develop 2022-07-26 10:44:21 +08:00
“xxq250” 1bbde165c2 reposyncer同步仓库接口 2022-07-26 10:44:12 +08:00
yystopf 3f5754a3a5 新增:合并请求详情接口 2022-07-25 18:23:06 +08:00
yystopf 5463c22518 新增: 合并请求创建审查接口 2022-07-25 17:28:38 +08:00
yystopf 5db43bf768 新增:新合并请求列表接口 2022-07-25 16:21:03 +08:00
yystopf 1feb166fd5 修复:合并请求评审模型修改 2022-07-25 16:20:42 +08:00
yystopf 0df1e5fdd0 新增:合并请求版本列表和diff接口文档 2022-07-22 18:08:16 +08:00
yystopf 8ba70a33be 新增: pr版本列表和diff接口 2022-07-22 17:33:08 +08:00
“xxq250” b21f44b59e fixed 代码提交日志根据提交commit记录多次 2022-07-22 10:11:21 +08:00
“xxq250” 92a310c916 fixed zstp2022复赛影响启智if 2022-07-20 18:03:40 +08:00
“xxq250” 42815c0812 fixed zstp2022复赛影响启智 2022-07-20 18:01:11 +08:00
“xxq250” 231bf39283 fixed zstp2022复赛影响启智 2022-07-20 17:57:29 +08:00
yystopf 7793eacf75 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-07-19 16:47:06 +08:00
yystopf 25afedcdfd 新增: 批量更改文件 2022-07-19 16:47:01 +08:00
“xxq250” d95a689815 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-07-19 14:58:29 +08:00
xiaoxiaoqiong b386dc51e4 fixed 后台统计优化,7天时间精确 2022-07-19 14:56:02 +08:00
yystopf 1882120df3 新增: 获取单文件blame信息 2022-07-19 11:14:50 +08:00
yystopf 274cd81655 新增:获取commit列表 2022-07-19 10:41:25 +08:00
yystopf 6273349334 新增: 获取比较blame、token以及异常捕获处理 2022-07-18 15:39:51 +08:00
yystopf e8deb83004 fix: gemfile 2022-07-18 11:20:24 +08:00
yystopf 52701d1c2f Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-07-18 11:18:35 +08:00
yystopf b248f770f1 新增:获取单个提交的blame信息接口以及文档 2022-07-18 11:18:29 +08:00
xiaoxiaoqiong 04b9e43382 fixed 后台统计优化,新增项目数 2022-07-18 11:14:45 +08:00
xiaoxiaoqiong 3580a8653d fixed 后台统计优化,新增项目数 2022-07-18 11:04:57 +08:00
xiaoxiaoqiong d9653e461e fixed 后台统计优化,周存率小数计算 2022-07-18 11:00:47 +08:00
xiaoxiaoqiong d9a1d32ec8 fixed 后台统计优化,周存率 2022-07-18 10:55:41 +08:00
xiaoxiaoqiong b5dfd83527 fix 提交日志提交用户信息不匹配 2022-07-18 10:43:57 +08:00
xiaoxiaoqiong df7b91a8ba gemfile.lock reset 2022-07-18 10:38:45 +08:00
xiaoxiaoqiong 8dae15225e 后台统计优化 2022-07-18 10:37:53 +08:00
xiaoxiaoqiong 5fcf789e63 fixed 提交日志记录用户信息,仓库关联 2022-07-18 09:35:19 +08:00
xiaoxiaoqiong ed0655452c 增加从webhook接收仓库日志记录 2022-07-18 09:34:56 +08:00
yystopf 0dd062ce1c 新增: blobs和文件树接口及文档 2022-07-15 17:03:18 +08:00
yystopf bd3cbf33fd fix 2022-07-15 14:41:00 +08:00
yystopf b8d4b15b40 新增: 分支接口文档 2022-07-15 14:40:35 +08:00
yystopf 24d83133e7 新增: 创建分支接口 2022-07-15 14:02:48 +08:00
yystopf 4ed3a9d478 修复:cherry pick doorkeeper配置 2022-07-14 18:13:06 +08:00
xiaoxiaoqiong 0f5fd424fb fixed 同步gitea密码,因为加了base64 2022-07-14 11:01:55 +08:00
yystopf fbbacfa983 修复: apk文件为下载文件 2022-07-14 09:36:52 +08:00
xiaoxiaoqiong 169ec9e0b0 fixed ccks第一轮赛合格人员复赛 2022-07-13 12:59:47 +08:00
xiaoxiaoqiong a95ac23c49 fixed ccks第一轮赛合格人员复赛 2022-07-13 12:21:08 +08:00
xiaoxiaoqiong 30acbec322 fixed ccks第一轮赛合格人员复赛 2022-07-13 12:06:36 +08:00
xiaoxiaoqiong 08292d86ee ccks第一轮赛合格人员复赛 2022-07-12 18:10:37 +08:00
xiaoxiaoqiong 158ba9707d fixed 首页创客项目统计跟列表一致 2022-07-11 09:35:08 +08:00
yystopf d0988e42b4 新增: 平台接口文档更新 2022-07-08 18:01:07 +08:00
xiaoxiaoqiong 73b5c0f63f fixed 打分次数可配置 2022-07-08 15:22:07 +08:00
yystopf d154f0aecc 修复: readme匹配修复 2022-07-08 11:31:17 +08:00
yystopf 29d9410e42 修复: readme 匹配项目 2022-07-07 15:02:25 +08:00
xiaoxiaoqiong dbae651abc fixed 首页项目数量统计 2022-07-07 11:12:13 +08:00
yystopf 3b62f09669 新增: 项目语言匹配并设置 2022-07-07 10:05:12 +08:00
yystopf 5864352049 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-07-07 09:24:18 +08:00
yystopf 1d6d48fc94 新增: pr 最后一次审核展示 2022-07-07 09:24:11 +08:00
xiaoxiaoqiong 484c91a581 fixed 同步gitea密码状态is_sync_pwd更新 2022-07-06 15:26:49 +08:00
xiaoxiaoqiong aabb7518c0 fixed 同步gitea密码状态is_sync_pwd 2022-07-06 14:50:28 +08:00
xiaoxiaoqiong de2afba910 fixed 同步gitea密码状态 2022-07-06 14:49:04 +08:00
xiaoxiaoqiong a465e8de66 fixed 同步gitea密码状态 2022-07-06 14:47:10 +08:00
xiaoxiaoqiong e4a79a4049 fixed 同步gitea密码状态 2022-07-06 14:46:00 +08:00
xiaoxiaoqiong fa1e858a97 fixed 竞赛首页推荐控制,排序 2022-07-06 10:07:27 +08:00
xiaoxiaoqiong 2080d44bdb fixed 竞赛首页推荐控制 2022-07-06 10:00:12 +08:00
xiaoxiaoqiong 97c1da579e fixed 引用issue附件查看时权限 2022-07-05 10:08:23 +08:00
xiaoxiaoqiong 5ab66e0c40 fixed 提交作品次数1 2022-07-01 16:53:44 +08:00
xiaoxiaoqiong b1b7b6a1e0 fixed 提交作品次数 2022-07-01 15:41:47 +08:00
xiaoxiaoqiong 16f2aecb6d fixed 提交作品次数 2022-07-01 15:31:33 +08:00
xiaoxiaoqiong a583d3156a fixed 排行榜去掉手机号搜索 2022-07-01 10:29:46 +08:00
xiaoxiaoqiong 4ca5d4b234 fixed 打分系统内部错误文案 2022-06-30 18:10:30 +08:00
xiaoxiaoqiong 77a8e75e87 fixed 打分系统内部错误文案 2022-06-30 18:09:02 +08:00
yystopf 7b91ad37e5 修复 2022-06-30 16:38:46 +08:00
yystopf 9dbb9a42d6 新增: compare 支持sha对比 2022-06-30 16:33:09 +08:00
xiaoxiaoqiong 09f9f138f0 fixed 排行榜手机号不显示 2022-06-30 14:39:29 +08:00
xiaoxiaoqiong f8aa5ddb00 fixed 排行榜排名数 2022-06-30 14:34:42 +08:00
xiaoxiaoqiong 18d65c169c fixed 打分失败提示 2022-06-30 13:58:29 +08:00
xiaoxiaoqiong 3b3cd46b76 fixed 打分失败 2022-06-30 13:50:48 +08:00
yystopf a608803aa8 新增: 合并请求审查需审查权限 2022-06-30 11:00:18 +08:00
yystopf 76cc185a1d 新增: 合并请求审核model 2022-06-29 17:16:29 +08:00
xiaoxiaoqiong 10f8ff28e1 分页大小改为10行 2022-06-27 11:38:37 +08:00
xiaoxiaoqiong 25a686e4f3 分页大小改为10行 2022-06-27 11:15:07 +08:00
yystopf e76503ae26 fix: gitea client version 2022-06-26 09:06:11 +08:00
yystopf 50991f503f Merge pull request '新增oauth验证接口入口以及webhooks接口' (#14) from yystopf/forgeplus:hh_new_api into develop 2022-06-24 14:16:06 +08:00
yystopf acd031ca7d 修复: gemfile.lock 2022-06-24 14:14:57 +08:00
yystopf b59b76be4a 新增: 更新文档 2022-06-24 11:04:16 +08:00
yystopf 211581cef0 新增: webhooks文档使用新api地址 2022-06-24 09:26:01 +08:00
yystopf 7cad953413 新增: 用户项目列表支持多个参数 2022-06-23 18:16:57 +08:00
yystopf fe58175ee0 新增: webhooks使用token访问的接口 2022-06-23 16:14:00 +08:00
yystopf 5d0849a148 新增: 用户项目列表以及helper方法 2022-06-23 12:19:03 +08:00
yystopf d14bf35ca1 修复: gitea module命名重复问题 2022-06-23 11:33:11 +08:00
xiaoxiaoqiong 9a5ce74d98 定制竞赛排行榜 2022-06-23 08:50:33 +08:00
yystopf d7dd3901b8 新增: 项目详情 2022-06-22 19:08:14 +08:00
yystopf aefd6c08dc 新增: gitea-client引入以及路由定义 2022-06-21 17:39:11 +08:00
yystopf 3c2c742121 修复: 项目邀请链接生成多次返回提示 2022-06-21 11:37:41 +08:00
yystopf 9221e55752 修复: 邀请链接跳转用户已加入仓库的提示以及项目申请记录只创建一条 2022-06-21 11:18:14 +08:00
xiaoxiaoqiong 44db7c48f9 风雷主项目固定排第一 2022-06-21 10:22:20 +08:00
xiaoxiaoqiong 861a84d8ec 风雷主项目固定排第一 2022-06-21 10:19:40 +08:00
xiaoxiaoqiong d496e1c01e 风雷主项目固定排第一 2022-06-21 10:13:58 +08:00
xiaoxiaoqiong e4b2563780 风雷主项目固定排第一 2022-06-21 10:11:53 +08:00
xiaoxiaoqiong 944fb3b89e 风雷主项目固定排第一 2022-06-21 10:06:59 +08:00
yystopf ba1fa8b685 修复: 项目邀请链接私有项目无法访问的情况 2022-06-20 16:37:59 +08:00
yystopf 29e3a55a0c 修复: 项目邀请链接私有项目无法访问的情况 2022-06-20 16:36:01 +08:00
xiaoxiaoqiong c426467a68 Merge remote-tracking branch 'origin/develop' into develop 2022-06-20 15:38:48 +08:00
xiaoxiaoqiong 9fe8df3c1b auth token过期时间7天 2022-06-20 15:38:42 +08:00
yystopf 531495429c 修复: 无法正常更改token长度的问题 2022-06-20 13:05:25 +08:00
yystopf bed2469014 fix: change error 2022-06-20 10:34:25 +08:00
yystopf 45b7f70d9f 新增:项目邀请链接增加时间限制,以及show_link接口新增 2022-06-20 10:16:39 +08:00
yystopf 1ebb6cb561 Merge branch 'develop' of https://gitlink.org.cn/Trustie/forgeplus into develop 2022-06-20 09:34:29 +08:00
yystopf 21ccedab9c 修复: doorkeeper 无法生成jwt token 2022-06-17 18:33:37 +08:00
xiaoxiaoqiong 8f45bcf959 Merge remote-tracking branch 'origin/develop' into develop 2022-06-17 17:02:31 +08:00
xiaoxiaoqiong 1f9caeece5 auth2接入 2022-06-17 17:02:24 +08:00
yystopf 5b4e6f4902 修复: 项目存在敏感词更新forked数量使用update_column 2022-06-17 14:19:41 +08:00
yystopf 3d0e323801 fix 2022-06-17 14:07:33 +08:00
yystopf f6fb50529c 新增: 邀请项目链接接口文档 2022-06-17 14:06:59 +08:00
yystopf c42f3d5928 新增:邀请用户链接生成 2022-06-17 14:06:59 +08:00
yystopf 42d2b51f7f 修复: 项目敏感词判定只在创建或者更新的时候 2022-06-16 13:42:17 +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
xiaoxiaoqiong d243fff299 current_main_site_url 2022-06-01 10:53:24 +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
xiaoxiaoqiong 7ddb59800d 竞赛无赛区赛项配置 2022-05-25 15:31:41 +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
xiaoxiaoqiong cedaeda60c 竞赛增加审核状态过滤 2022-05-24 15:47:46 +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
xiaoxiaoqiong 555df176cc 增加打分重复三元组数量 2022-05-23 15:09:29 +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
xiaoxiaoqiong 20f892a4f0 成员分成多个单元格 2022-05-20 09:54:12 +08:00
xiaoxiaoqiong f77dcd3b30 成员分成多个单元格 2022-05-20 09:54:01 +08:00
xiaoxiaoqiong 701c05c39e 成员分成多个单元格 2022-05-20 09:41:05 +08:00
xiaoxiaoqiong 853c33cb24 成员分成多个单元格 2022-05-20 09:36:46 +08:00
xiaoxiaoqiong 0bd8c19a87 成员分成多个单元格 2022-05-19 18:29:21 +08:00
xiaoxiaoqiong c2171eab9b 成员分成多个单元格 2022-05-19 18:21:44 +08:00
xiaoxiaoqiong 72fb2738db 竞赛配置加映射关系字段,增加报名字段 2022-05-19 17:46:44 +08:00
xiaoxiaoqiong 1cb406e1e8 竞赛配置加映射关系字段,增加报名字段 2022-05-19 17:44:36 +08:00
xiaoxiaoqiong 5b33da0aa5 竞赛配置加映射关系字段,增加报名字段 2022-05-19 17:41:49 +08:00
xiaoxiaoqiong ca78b04f6e 竞赛打分保留4位小数 2022-05-18 11:48:02 +08:00
xiaoxiaoqiong f93c1dff0b 竞赛打分保留4位小数 2022-05-18 11:42:53 +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
xiaoxiaoqiong ef33193f01 增加api请求时间 2022-05-18 10:47:44 +08:00
xiaoxiaoqiong b648774b42 增加api请求时间 2022-05-18 10:11:12 +08:00
yystopf 9cd18397f7 fix: import user login length required 2022-05-18 10:11:09 +08:00
xiaoxiaoqiong 0ffb919242 增加api请求时间 2022-05-18 10:10:49 +08:00
xiaoxiaoqiong 6d4fb8df34 js zip 2022-05-17 14:45:45 +08:00
xiaoxiaoqiong d9c1c3d3a2 js zip 2022-05-17 14:24:45 +08:00
xiaoxiaoqiong 083a839bf5 竞赛api限制打分接口api_url传递 2022-05-17 11:38:15 +08:00
xiaoxiaoqiong 551edde13d 竞赛api限制打分接口api_url传递 2022-05-17 11:36:48 +08:00
xiaoxiaoqiong 768f9a7847 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-05-17 11:30:49 +08:00
xiaoxiaoqiong a8adf6f140 竞赛api限制打分接口 2022-05-17 11:30:39 +08:00
yystopf 77620f7735 add: download and import user template xlsx 2022-05-16 16:59:25 +08:00
xiaoxiaoqiong 59cd230658 竞赛管理员判断方法优化 2022-05-10 09:34:10 +08:00
xiaoxiaoqiong 79a6cea623 登录密码长度验证去掉 2022-05-09 10:09:43 +08:00
xiaoxiaoqiong 45fdf9bb59 登录密码长度验证去掉 2022-05-09 09:34:31 +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 dc7c326ffe 提示语句更改 2022-05-05 16:55:43 +08:00
xiaoxiaoqiong f560723d5a zip目录files 2022-05-05 14:42:01 +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
xiaoxiaoqiong f36dbf9c26 删除多余文件 2022-04-29 11:13:06 +08:00
xiaoxiaoqiong 29f6950e7c 后管管理员 2022-04-28 21:14:38 +08:00
xiaoxiaoqiong cf164ff5f8 后管管理员 2022-04-28 21:04:22 +08:00
xiaoxiaoqiong d6f9530637 后管管理员 2022-04-28 19:52:35 +08:00
yystopf f15cd44dff add: compare add paginate 2022-04-28 18:53:33 +08:00
xiaoxiaoqiong babdec4788 后管js压缩 2022-04-28 18:30:01 +08:00
xiaoxiaoqiong 8731506992 后管优化 2022-04-28 18:08:37 +08:00
xiaoxiaoqiong d90ab310cc 台管云上实验室定制 2022-04-28 17:30:24 +08:00
xiaoxiaoqiong f0e2277f1c 台管地址可配置 2022-04-28 16:53:41 +08:00
xiaoxiaoqiong 88a9194aca 用户管理员查询 2022-04-28 16:34:46 +08:00
xiaoxiaoqiong 53dcd9de71 用户管理员查询 2022-04-28 16:32:50 +08:00
xiaoxiaoqiong 6c68a51091 管理端模态框顶部弹出 2022-04-28 15:38:41 +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
xiaoxiaoqiong 97507c2203 管理员新字段 2022-04-27 18:34:09 +08:00
xiaoxiaoqiong 50db13a7ef 管理员新字段 2022-04-27 18:14:12 +08:00
xiaoxiaoqiong 8115858c47 可修改赛区赛项接口 2022-04-27 17:42:17 +08:00
xiaoxiaoqiong 357cd6d628 增加手机号搜索用户 2022-04-27 17:03:05 +08:00
xiaoxiaoqiong 20a69528fa 报名资料导出 2022-04-27 15:49:36 +08:00
xiaoxiaoqiong a5021df2ac 定制竞赛创建接口 2022-04-27 11:36:34 +08:00
xiaoxiaoqiong 703c2c5bad 定制竞赛创建接口 2022-04-27 11:28:58 +08:00
xiaoxiaoqiong 2d067f0a18 定制竞赛作品下载 2022-04-27 11:11:10 +08:00
xiaoxiaoqiong 0b34f49ea7 定制竞赛创建接口 2022-04-27 09:50:49 +08:00
yystopf 088c617cc1 add: name query for branches 2022-04-26 17:15:59 +08:00
xiaoxiaoqiong 2a2c8361b8 报名导出增加状态过虑 2022-04-22 10:36:55 +08:00
xiaoxiaoqiong 8a3be40410 报名导出增加状态过虑 2022-04-22 10:08:46 +08:00
xiaoxiaoqiong 8ce75ed2d3 报名统计 2022-04-21 20:21:03 +08:00
xiaoxiaoqiong 8052ae832d 分区管理员竞赛馭回 2022-04-21 20:16:33 +08:00
xiaoxiaoqiong adc9936566 管理增加竞赛报名状态 2022-04-21 17:40:10 +08:00
xiaoxiaoqiong c00a8a67f9 竞赛报名状态变更 2022-04-21 10:33:04 +08:00
xiaoxiaoqiong 854ef5ca45 竞赛报名更新 2022-04-21 09:33:47 +08:00
xiaoxiaoqiong dc43b3542c 竞赛外网版本字段控制 2022-04-19 16:05:00 +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
xiaoxiaoqiong 1b8006f438 admin_layout 2022-04-13 14:00:31 +08:00
xiaoxiaoqiong 5c123edfaa 删除多的文件 2022-04-11 18:15:34 +08:00
xiaoxiaoqiong 3f94cf3637 登录同步gitea密码 2022-04-11 18:07:07 +08:00
xiaoxiaoqiong 689a91ab49 Merge branch 'dev_military_server_local' into dev_jk_server
# Conflicts:
#	app/controllers/application_controller.rb
#	app/controllers/attachments_controller.rb
#	app/controllers/competition_infos_controller.rb
2022-04-11 17:41:03 +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
xiaoxiaoqiong a517d1df68 登录cookie_action 2022-04-02 15:49:08 +08:00
xiaoxiaoqiong 547cf7ce86 密码长度20 2022-04-02 10:29:58 +08:00
xiaoxiaoqiong 560adc458c 密码长度20 2022-04-02 10:27:29 +08:00
xiaoxiaoqiong 6dfffb8a6d 竞赛详情更新权限 2022-04-01 19:14:39 +08:00
xiaoxiaoqiong 1c5b42e01b 竞赛详情更新权限 2022-04-01 19:13:46 +08:00
xiaoxiaoqiong 85302102d6 竞赛详情更新权限 2022-04-01 19:10:17 +08:00
xiaoxiaoqiong 316fb0ff58 竞赛详情更新权限 2022-04-01 19:00:27 +08:00
xiaoxiaoqiong d475413fd6 Merge remote-tracking branch 'origin/dev_military_server_local' into dev_military_server_local 2022-04-01 16:44:47 +08:00
xiaoxiaoqiong cd40efc760 竞赛详情更新报错 2022-04-01 16:44:42 +08:00
xiaoxiaoqiong 76ed52b68a 竞赛详情更新报错 2022-04-01 15:09:32 +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
xiaoxiaoqiong d1b5ead752 debug模式对应用户 2022-03-31 09:51:24 +08:00
xiaoxiaoqiong 972373a277 上传图片去掉dun检测 2022-03-31 09:39:42 +08:00
xiaoxiaoqiong 66dead1e6a Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-31 09:02:10 +08:00
xiaoxiaoqiong f901ff8920 赛事详编辑方式 2022-03-31 09:01:40 +08:00
xiaoxiaoqiong 00a4be2879 赛事详编辑方式 2022-03-31 08:57:25 +08:00
xiaoxiaoqiong 90738a6117 登录base64 2022-03-30 22:16:31 +08:00
xiaoxiaoqiong dea5a223d1 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-30 21:07:01 +08:00
xiaoxiaoqiong bd88870405 竞赛通知id 2022-03-30 21:06:30 +08:00
xiaoxiaoqiong 9b11bccd42 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-30 17:42:57 +08:00
xiaoxiaoqiong fae11267f7 竞赛文案 2022-03-30 17:36:07 +08:00
yystopf 747646cd9d add: trace client and api completed 2022-03-30 16:19:32 +08:00
xiaoxiaoqiong f0fc456a1c merge local 2022-03-30 14:13:42 +08:00
xiaoxiaoqiong 2f06e89b54 竞赛banner_url 2022-03-30 14:10:19 +08:00
xiaoxiaoqiong ae3057d150 项目简介长度2000 2022-03-30 13:51:00 +08:00
xiaoxiaoqiong 033865df66 项目简介长度2000 2022-03-30 13:49:54 +08:00
xiaoxiaoqiong 7ca13fb387 项目简介长度2000 2022-03-30 13:22:33 +08:00
xiaoxiaoqiong 2fb263d6c9 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-30 12:25:55 +08:00
xiaoxiaoqiong fda21d782c 竞赛导出调整 2022-03-30 12:25:05 +08:00
xiaoxiaoqiong 71836ca3ae Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-29 17:53:02 +08:00
xiaoxiaoqiong 4dadce904d 管理员状态,和管理赛区 2022-03-29 17:52:34 +08:00
xiaoxiaoqiong e4ec205890 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-29 17:50:54 +08:00
xiaoxiaoqiong aa9006bfe5 管理员状态,和管理赛区 2022-03-29 17:50:26 +08:00
xiaoxiaoqiong 00c1486e89 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-29 09:16:54 +08:00
xiaoxiaoqiong f8ef2d48a0 竞赛报名状态 2022-03-29 09:16:34 +08:00
xiaoxiaoqiong 0f83639565 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-29 09:14:46 +08:00
xiaoxiaoqiong 0607a62b17 竞赛配置增加属性,通知管理 2022-03-29 09:14:10 +08:00
xiaoxiaoqiong 3f0ded057b merge local 2022-03-28 18:07:32 +08:00
xiaoxiaoqiong 1e1d07e697 竞赛配置增加属性,通知管理 2022-03-28 18:05:52 +08:00
xiaoxiaoqiong a72a0de2b9 竞赛配置增加属性,通知管理 2022-03-28 18:05:31 +08:00
yystopf d0d906d04c fix: readme image regex error rescued 2022-03-28 11:05:21 +08:00
xiaoxiaoqiong 6079441f8a Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-28 10:08:38 +08:00
xiaoxiaoqiong f0bc08cd47 附件可重复上传 2022-03-28 10:04:54 +08:00
xiaoxiaoqiong 39526b091b 已报名信息 2022-03-28 09:50:43 +08:00
xiaoxiaoqiong bcd5c6bee0 已报名信息 2022-03-28 09:48:08 +08:00
xiaoxiaoqiong cf0565ddb6 已报名信息 2022-03-28 09:47:21 +08:00
xiaoxiaoqiong c4843da207 Merge branch 'dev_military_server_local' into dev_jk_server 2022-03-25 14:39:06 +08:00
xiaoxiaoqiong cb184792cd 启智竞赛增加时间 2022-03-25 14:38:14 +08:00
xiaoxiaoqiong 78cee5f7d1 启智竞赛报名导出 2022-03-25 13:56:23 +08:00
xiaoxiaoqiong b852b8cf08 启智竞赛接口调整 2022-03-25 09:17:43 +08:00
xiaoxiaoqiong cee09d9f8f Merge branch 'dev_military_server_local' into dev_jk_server
# Conflicts:
#	app/controllers/accounts_controller.rb
#	app/controllers/concerns/login_helper.rb
#	app/controllers/users_controller.rb
#	config/routes.rb
2022-03-24 16:35:04 +08:00
xiaoxiaoqiong 7ab87df7fc 启智竞赛接口调整 2022-03-24 16:03:01 +08:00
xiaoxiaoqiong 78fd1d158f 启智竞赛接口 2022-03-24 10:15:24 +08:00
xiaoxiaoqiong 9b91557bb6 启智竞赛 2022-03-23 16:40:53 +08:00
xiaoxiaoqiong 521a1a2c8a autologin_action可配置 2022-03-22 15:18:09 +08:00
yystopf bc639488aa fix: issues filter error 2022-03-22 10:45:14 +08:00
xiaoxiaoqiong 9ca85d8e8d 后台管理布局css 2022-03-14 18:09:47 +08:00
xiaoxiaoqiong 64ed6b93c9 后台管理布局css 2022-03-14 18:08:13 +08:00
xiaoxiaoqiong f9e613f856 后台管理布局改变 2022-03-14 18:01:23 +08:00
xiaoxiaoqiong b508fd6cf4 后台管理布局改变 2022-03-14 15:42:23 +08:00
xiaoxiaoqiong 43334935d9 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-03-11 14:53:32 +08:00
xiaoxiaoqiong 958b1618b1 gitea 请求延长到20分钟 2022-03-11 14:53:28 +08:00
xiaoxiaoqiong 99fbecc834 gitea 请求延长到20分钟 2022-03-11 14:06:12 +08:00
yystopf e489c57fe8 fix: merge from develop 2022-03-10 11:07:14 +08:00
yystopf 8d0a6d267a fix: download escape 2022-03-10 10:47:06 +08:00
xiaoxiaoqiong cd85fea841 fixed 重复上传协议 2022-03-10 09:53:00 +08:00
yystopf b1c03ed5e8 fix: activity issues must only issue 2022-03-10 09:51:46 +08:00
xiaoxiaoqiong e9daacc1b2 fixed 项目特殊许可证私有可见 2022-03-09 16:09:27 +08:00
xiaoxiaoqiong d48009fab6 fixed 项目特殊许可证私有可见 2022-03-09 15:53:21 +08:00
xiaoxiaoqiong 0b93a3a787 fixed 项目特殊许可证私有可见 test 2022-03-09 15:29:03 +08:00
xiaoxiaoqiong d4c860bf29 fixed 项目特殊许可证私有可见 2022-03-09 15:21:18 +08:00
xiaoxiaoqiong ce4aee366a fixed 新建issues时分支信息 2022-03-08 14:16:58 +08:00
xiaoxiaoqiong 747bc4ab45 fixed 项目中发行版 2022-03-08 14:01:44 +08:00
xiaoxiaoqiong fc3344c78a fixed 项目中下载文件 2022-03-08 13:53:51 +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
xiaoxiaoqiong 9b08a09a1b 登录密码支持base64 2022-03-02 18:02:19 +08:00
xiaoxiaoqiong 01ccbe89cd 通知提醒规则更改5分钟 2022-03-02 16:59:51 +08:00
xiaoxiaoqiong 643dedc8cb 通知提醒规则更改5分钟 2022-03-02 16:55:33 +08:00
xiaoxiaoqiong fbd1533a53 通知竞赛链接跳转 2022-03-02 16:23:58 +08:00
xiaoxiaoqiong 49d1317d21 通知竞赛链接跳转 2022-03-02 16:18:20 +08:00
xiaoxiaoqiong 31d7103da3 通知提醒规则更改5分钟 2022-03-02 15:59:31 +08:00
xiaoxiaoqiong 0b0a57035a 通知提醒规则更改 2022-03-02 15:26:06 +08:00
xiaoxiaoqiong 7449d915ab 通知提醒规则 2022-03-02 10:36:20 +08:00
xiaoxiaoqiong 33c0e026fd 通知提醒规则 2022-03-02 10:35:52 +08:00
yystopf b97c42d0ae fix: email logo 2022-03-02 10:33:35 +08:00
xiaoxiaoqiong 60245b4558 Merge remote-tracking branch 'origin/dev_jk_server' into dev_jk_server 2022-03-02 10:31:31 +08:00
xiaoxiaoqiong 751187a3da 通知提醒规则 2022-03-02 10:31:25 +08:00
yystopf 1bf858c10c fix: remove check image able 2022-03-01 17:59:23 +08:00
yystopf 9e2db8a7f6 fix: merge from develop 2022-03-01 17:37:10 +08:00
xiaoxiaoqiong c575376b44 用户头像男女 2022-02-25 15:46:10 +08:00
xiaoxiaoqiong 8564930dfc 用户头像男女 2022-02-25 15:44:47 +08:00
xiaoxiaoqiong 8e362e902f 用户头像男女 2022-02-25 15:42:23 +08:00
xiaoxiaoqiong abf3541201 用户头像男女 2022-02-25 15:36:31 +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
xiaoxiaoqiong ec9f3a3058 fixed issue编辑错误 2022-02-24 17:48:16 +08:00
xiaoxiaoqiong 5d102f9ef4 统计去掉 2022-02-24 17:38:02 +08:00
xiaoxiaoqiong b7914e54f6 fixed 登录token统一 2022-02-24 14:48:04 +08:00
yystopf 1a93477635 fix: forked templete delay 2022-02-24 14:26:04 +08:00
xiaoxiaoqiong 68cc2999ed fixed 老项目地址跳转 2022-02-24 09:48:02 +08:00
xiaoxiaoqiong 66ca7fd1f0 fixed 固定token key 2022-02-24 09:25:01 +08:00
xiaoxiaoqiong b1c3d62e41 fixed 固定token key 2022-02-23 18:28:16 +08:00
xiaoxiaoqiong a94493ce0d fixed注册gitea检查用户存在 2022-02-22 13:59:17 +08:00
xiaoxiaoqiong c1ea0232bb fixed注册gitea 2022-02-22 13:48:37 +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 58ca8e2651 竞赛通知任务调度log 2022-02-21 17:55:06 +08:00
xiaoxiaoqiong 692d51792a 竞赛通知任务调度log 2022-02-21 17:02:07 +08:00
xiaoxiaoqiong fcc827522c Merge branch 'develop' into dev_jk_server 2022-02-21 16:49:21 +08:00
xiaoxiaoqiong 4e3f9cc019 竞赛通知任务调度 2022-02-21 16:48:59 +08:00
xiaoxiaoqiong fe08cab2e5 Merge branch 'develop' into dev_jk_server 2022-02-21 16:47:08 +08:00
xiaoxiaoqiong 5ed7b3e4ad 竞赛通知任务调度 2022-02-21 16:46:40 +08:00
xiaoxiaoqiong 2e511655f6 Merge branch 'develop' into dev_jk_server
# Conflicts:
#	app/models/concerns/matchable.rb
#	config/routes.rb
2022-02-17 18:31:25 +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
xiaoxiaoqiong 36c4b32acb fixed setting编辑类型下拉选中 2022-02-15 17:09:21 +08:00
xiaoxiaoqiong ada03e45ea debug开启 2022-02-15 16:49:20 +08:00
xiaoxiaoqiong cad35e3757 debug开启 2022-02-15 16:32:41 +08:00
xiaoxiaoqiong f38d6bc976 images 2022-02-15 15:50:58 +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
xiaoxiaoqiong 3fc62ca1d5 注册万能验证码开启,可配置 2022-02-14 13:48:51 +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 87d2cc3e25 fixed 注册登录类型 2022-01-21 15:51:34 +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 c5063e513d fix: issue destroy return duplicate 2022-01-21 11:31:36 +08:00
yystopf 63e50e36ac fix: detail result delay 2022-01-20 09:52:44 +08:00
yystopf dca4ef6a34 fix: contributor error rescue 2022-01-20 09:42:55 +08:00
yystopf 7a2270956c fix: contributor error rescue 2022-01-20 09:41:25 +08:00
yystopf b380afaf5c fix: owner allow nil 2022-01-20 09:29:26 +08:00
yystopf e7af0e2e47 fix: license is secret delay 2022-01-18 18:32:33 +08:00
yystopf 04f2dbee9a merge from develop 2022-01-18 15:30:57 +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
xiaoxiaoqiong 74cbca2421 Merge branch 'dev_military_server_local' into dev_military_server 2021-12-25 20:23:21 +08:00
xiaoxiaoqiong 01bf13ddd9 fixed 手机号注册失败 2021-12-25 20:22:46 +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
xiaoxiaoqiong ea2de5910a Merge branch 'dev_military_server_local' into dev_military_server 2021-12-20 16:35:09 +08:00
xiaoxiaoqiong a5d4799a21 增加首页项目统计基数 2021-12-20 16:34:52 +08:00
xiaoxiaoqiong 335d24bc8b Merge branch 'dev_military_server_local' into dev_military_server 2021-12-20 16:05:46 +08:00
xiaoxiaoqiong e97eacbbf6 增加首页项目统计基数 2021-12-20 16:04:58 +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
xiaoxiaoqiong 2c17ae096e 用户管理搜索优化 2021-12-20 11:16:42 +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 399f6c2a17 Merge branch 'dev_military_server_local' into dev_military_server 2021-12-17 14:26:01 +08:00
xiaoxiaoqiong fb335162fc reset gem lock file 2021-12-14 15:48:15 +08:00
xiaoxiaoqiong c7b40c1230 重复手机注册 2021-12-14 15:46:40 +08:00
xiaoxiaoqiong 293121ab91 其他平台用户注册 2021-12-14 14:41:59 +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 43cccc5429 fix: admins navbar and platform communicates order index and competitions filter 2021-12-09 14:04:03 +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
yystopf fcc5429bbd fix: api platform people 2021-12-07 09:26:32 +08:00
yystopf 1f8f2abcf6 Merge pull request '红山开源首页后台管理' (#280) from yystopf/forgeplus:dev_military_server_local into dev_military_server_local 2021-12-07 09:13:40 +08:00
yystopf a2140574cd fix 2021-12-06 16:59:07 +08:00
yystopf ab47dd0524 add: js compile 2021-12-06 16:57:20 +08:00
yystopf 4310cc9f26 add: platform person admin 2021-12-06 16:41:12 +08:00
yystopf 9648afb0bb add: platform communicate admin 2021-12-06 14:29:05 +08:00
yystopf 557b6ccc13 fix 2021-12-02 17:56:19 +08:00
viletyy d94b3ff2f4 add: platform person 2021-12-02 17:46:25 +08:00
viletyy 4a7878d16e add: platform communicate 2021-12-02 16:59:55 +08:00
viletyy 0a00a4bc0e add: competitions 2021-12-02 15:18:10 +08:00
viletyy b81d92af46 add: platform statistic 2021-12-02 14:39:53 +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
jasder ef6f2c7b42 FIX 删除后台管理不存在的功能入口 2021-11-16 15:44:51 +08:00
jasder 689b24da8f FIX 修改设置默认分支出错的bug 2021-11-10 16:35:26 +08:00
jasder 369877da5f FIX 修改设置默认分支出错的bug 2021-11-10 16:34:38 +08:00
jasder 96c67d359e FIX 发送pr时,分支对比功能添加gitea 接口支持(pr_merge api)(bug) 2021-11-10 11:20:14 +08:00
jasder 3e633ea6cc FIX 发送pr时,分支对比功能添加gitea 接口支持(pr_merge api) 2021-11-10 11:16:17 +08:00
jasder 4fe3f88de6 FIX 版本库在线创建文件去掉敏感词过滤功能 2021-11-10 10:20:19 +08:00
jasder a5fd87a475 FIX 前端调用api地址从后端获取[更改数据结构] 2021-11-09 17:26:42 +08:00
jasder e8bbc7d856 ADD 前端调用api地址从后端获取[bug] 2021-11-09 16:54:10 +08:00
jasder 9a0d7aa02a ADD 前端调用api地址从后端获取 2021-11-09 16:30:03 +08:00
jasder 25e1bf1565 FIX 后台管理修改用户信息支持同步到gitea 2021-11-05 18:54:14 +08:00
jasder 574f6561d1 ADD 后台管理特殊协议列表添加项目名称区分信息 2021-07-26 11:20:21 +08:00
jasder eaddf52cbd FIX 解决标签列表和发行版列表中下周zip包、tar包导致的404问题 2021-06-30 14:30:48 +08:00
jasder ef0a0e5ddd FIX [bug]cherry pick ce85273^..0bfed83 2021-06-23 17:56:04 +08:00
jasder ef81d61a0d FIX cherry pick ce85273^..0bfed83 2021-06-23 17:48:14 +08:00
jasder 071f913123 FIX code bug 2021-06-23 17:32:48 +08:00
jasder 6096fdd7bf FIX 解决在线创建文件错误提示信息不准确的问题 2021-06-23 17:31:45 +08:00
jasder 9ba297ccf6 FIX 后台管理系统添加用户时,自动为用户生成邮箱 2021-06-08 09:27:41 +08:00
jasder 66fd6a71e5 FIX 后台管理系统添加用户时,自动为用户生产登录名 2021-06-07 17:09:23 +08:00
jasder 89bc20e540 FIX 去掉User模型中的open_users关联 2021-06-07 16:44:17 +08:00
jasder 184a6bf1bf FIX 去掉User模型中的compose关联 2021-06-07 16:42:40 +08:00
jasder 8ee089b82d ADD 后台管理系统 添加新增用户功能 2021-06-04 18:01:03 +08:00
jasder abc21413ac Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus into dev_military 2021-06-04 11:35:18 +08:00
vilet.yy ce89ce5169 fix:use concat_ws 2021-04-02 11:39:55 +08:00
vilet.yy b8a4c467fe fix 2021-04-02 11:29:30 +08:00
vilet.yy 300658f8dd fix: apply_signature filter 2021-04-02 11:18:28 +08:00
vilet.yy 9553740960 add: project order index 2021-03-17 15:47:01 +08:00
vilet.yy 1a8d9bb0ce [ADD]add police picture 2021-03-11 10:54:01 +08:00
vilet.yy 8c43f74b69 [ADD]job use model data 2021-03-10 14:11:56 +08:00
vilet.yy 3e7ae82258 [ADD]phenglei user list and cron job 2021-03-10 14:02:41 +08:00
vilet.yy 0aa75e077e [ADD]sync phenglei user job 2021-03-05 17:04:06 +08:00
vilet.yy 8aefcad510 [ADD]create project member rake 2021-03-05 17:04:06 +08:00
vilet.yy 622dcbaf4f Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus into dev_military 2021-03-05 17:03:01 +08:00
jasder 6570125a36 Merge branch 'develop' of https://git.trustie.net/jasder/forgeplus into dev_military 2021-03-05 15:50:40 +08:00
jasder d91e8dcbfe Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus into dev_military 2021-03-05 15:38:06 +08:00
jasder 0c2507b1e9 FIX valid user before register action 2021-03-05 15:37:41 +08:00
vilet.yy 8d29c2bd50 [FIX]org visit phenglei project 2021-03-05 09:50:03 +08:00
vilet.yy 774f632d9a Merge branch 'develop' into dev_military 2021-03-04 13:42:45 +08:00
vilet.yy 2969afd333 [FIX]project category correct projects_count 2021-03-01 16:23:29 +08:00
vilet.yy cc978c8dea [FIX]merge from develop 2021-03-01 13:59:30 +08:00
vilet.yy ce105b4c07 [FIX]project category not include private repo 2021-02-26 16:20:26 +08:00
vilet.yy b5870b1020 [FIX]lose role_name 2021-02-26 15:00:40 +08:00
vilet.yy 1edb3ce7ad [FIX]search projects error 2021-02-25 12:11:32 +08:00
jasder 59257b1caa FIX repo setting api for forbidden 2021-02-09 11:50:12 +08:00
Jasder b552e29aa3 ADD forge host and main web host for setting api 2021-02-04 11:43:11 +08:00
Jasder 21424a23f2 FIX change host 2021-02-04 11:12:51 +08:00
Jasder a82af669bd Merge branch 'dev_military' of http://git.trustie.net/jasder/forgeplus into dev_military 2021-01-28 15:22:53 +08:00
Jasder 0f01abd45f Merge branch 'develop' into dev_military 2021-01-28 15:21:43 +08:00
viletyy 80002be670 [FIX]项目列表total_count 2021-01-28 14:45:33 +08:00
Jasder f7e19cb3a4 Merge branch 'develop' into dev_military 2021-01-14 18:39:31 +08:00
Jasder 5cd6620413 Merge branch 'develop' into dev_military 2021-01-14 18:26:04 +08:00
Jasder f3a9124bdd Merge branch 'develop' into dev_military 2021-01-14 18:23:26 +08:00
Jasder d97a39a3a2 Merge branch 'develop' into dev_military 2021-01-14 17:05:50 +08:00
Jasder 987ff74690 FIX merge 2021-01-13 14:42:26 +08:00
Jasder 37be604e82 FIX [api] get pull files and commits bug 2021-01-13 14:40:23 +08:00
viletyy 83e2c1f889 [FIX]merge 2021-01-13 14:38:02 +08:00
viletyy 46a1c8877b [FIX]pull_request bug 2021-01-13 11:26:21 +08:00
Jasder 0aa39efe9b FIX code bug 2021-01-12 18:25:50 +08:00
Jasder 15d562d7b1 FIX delete batch import users with admin managerment 2021-01-12 18:15:01 +08:00
Jasder 5b261d6e81 FIX merge develop branch 2021-01-12 17:42:44 +08:00
viletyy 4693e77e02 [FIX] 2021-01-11 18:43:22 +08:00
viletyy fbf22ff0df [FIX]增加是否为成员参数 2021-01-11 17:52:58 +08:00
Jasder 0794f77a87 Merge branch 'develop' into dev_military 2021-01-06 14:00:51 +08:00
Jasder e5a46a242f FIX register with validate email 2021-01-06 11:03:00 +08:00
Jasder 4902237bd7 Merge branch 'dev_military_license' of http://git.trustie.net/jasder/forgeplus into dev_military_license 2021-01-06 10:44:37 +08:00
Jasder 4ddc60a1c3 FIX user register bug 2021-01-06 10:44:20 +08:00
viletyy cfa14fff9d [FIX] 2021-01-04 17:52:05 +08:00
viletyy ef327f2994 [FIX] 2021-01-04 16:19:11 +08:00
viletyy bf91c5e382 [FIX] 2021-01-04 15:32:44 +08:00
viletyy 9b687f7885 [FIX] 2021-01-04 15:22:03 +08:00
viletyy a072162324 [ADD]项目创建者审核申请 2021-01-04 12:27:12 +08:00
viletyy 8f1e0f39ea Merge branch 'dev_military_license' of https://git.trustie.net/jasder/forgeplus into dev_military_license 2020-12-31 14:03:06 +08:00
viletyy aaa6483958 [FIX]几处bug修复 2020-12-31 14:02:37 +08:00
Jasder bf730ca18f Merge branch 'dev_military_license' of http://git.trustie.net/jasder/forgeplus into dev_military_license 2020-12-29 18:20:46 +08:00
Jasder 132af875bc Merge branch 'master' into dev_military_license 2020-12-29 18:19:07 +08:00
viletyy a862d994ab [FIX]只有审核成功才添加成员 2020-12-29 18:08:10 +08:00
Jasder 604da93c5c FIX when add members to project, permission set to readable 2020-12-29 17:17:36 +08:00
Jasder 3f525f5779 FIX update model schema 2020-12-29 14:25:40 +08:00
viletyy 05d1e66ea9 [FIX] 2020-12-28 20:29:56 +08:00
viletyy 10c1cccf2c [FIX] 2020-12-28 19:42:59 +08:00
viletyy 27ec7ec7dd [ADD]simple去除访问限制,并加入字段 2020-12-28 18:41:28 +08:00
Jasder 43b4907565 Merge branch 'dev_military_license' of http://git.trustie.net/jasder/forgeplus into dev_military_license 2020-12-28 14:53:52 +08:00
Jasder cb90e1a13f FIX get branches bug 2020-12-28 14:53:30 +08:00
viletyy 749cd058c4 [FIX] 2020-12-28 12:57:58 +08:00
viletyy 47cc70f2c5 [ADD]增加下载文件接口 2020-12-28 12:31:05 +08:00
viletyy 5447d54d30 [FIX] 2020-12-28 10:26:50 +08:00
viletyy 6c436dd631 [ADD]后台审核特殊许可申请 2020-12-27 18:44:03 +08:00
viletyy 9eb7219b9a [FIX] 2020-12-25 18:58:03 +08:00
viletyy ad5fcb25c4 [ADD]接口文档 2020-12-25 17:51:42 +08:00
viletyy d42053ce0c [FIX]merge 2020-12-25 16:33:16 +08:00
viletyy 36bae71947 [ADD]增加特殊许可的验证 2020-12-25 16:17:46 +08:00
Jasder 837aa1ea9e FIX Merge master branch 2020-12-25 15:10:50 +08:00
Sylor-huang c283c7ed58 add: dun_check text and image 2020-11-30 19:36:30 +08:00
sylor_huang@126.com 4cf8588343 Reset Issue Closed_count 2020-09-27 11:17:22 +08:00
sylor_huang@126.com e75fad98f8 change admin projects 2020-09-18 13:41:44 +08:00
sylor_huang@126.com bc37c59f00 Change Header4 2020-09-16 15:08:35 +08:00
sylor_huang@126.com a6a745da93 Change Header1 2020-09-16 14:58:12 +08:00
sylor_huang@126.com 5bef80ee58 Change Index Category 2020-09-11 18:32:42 +08:00
sylor_huang@126.com f9bcc7e02b Close DunCheck 2020-09-07 16:33:26 +08:00
sylor_huang@126.com d35faf3935 Fix:Issues 2020-08-21 11:30:47 +08:00
sylor_huang@126.com 8d7dc9cb60 Test Push 2020-08-21 09:52:31 +08:00
sylor_huang@126.com 248d78d8c1 Merge branch 'dev_trustie' into dev_military 2020-08-20 18:10:07 +08:00
sylor_huang@126.com f632424f13 Change Like 2020-08-20 11:00:19 +08:00
sylor_huang@126.com 95ede63220 Change 2020-08-19 17:58:04 +08:00
sylor_huang@126.com 8fac294d04 Add UserAction Ip 2020-08-18 18:16:58 +08:00
sylor_huang@126.com d67c12beba Ignore migrate files 2020-08-18 18:10:05 +08:00
sylor_huang@126.com a7e4b85352 Change Confilct 2020-08-18 17:54:35 +08:00
Jasder 2ac2920399 FIX merge dev_trustie branch 2020-08-18 17:39:37 +08:00
Jasder 230b934de4 Update remote register forr military platform 2020-08-18 17:33:12 +08:00
sylor_huang@126.com e0bedf175f Change Dun Check 2020-08-18 11:02:09 +08:00
sylor_huang@126.com c9a263e03c Add Dun Check For Project 2020-08-18 10:36:13 +08:00
Jasder 2bd15d9746 Merge branch 'dev_trustie' into dev_military 2020-08-17 18:52:00 +08:00
sylor_huang@126.com fc9588fb63 Add Dun Check 2020-08-17 18:49:18 +08:00
sylor_huang@126.com e611b519ab Fix: Admins page remove .educoer.net words 2020-08-13 14:21:13 +08:00
sylor_huang@126.com 3dd3944ebd Fix: Unknow attribute private for project 2020-08-13 13:50:07 +08:00
sylor_huang@126.com f417bf3308 Change User Defautl Picture 2020-08-13 10:01:13 +08:00
sylor_huang@126.com 9c7c914d12 Change 2020-08-12 18:07:43 +08:00
sylor_huang@126.com b088befae7 Change 2020-08-12 16:39:10 +08:00
sylor_huang@126.com d3636e686b CHange 2020-08-12 16:27:42 +08:00
sylor_huang@126.com 88d98f0ac4 Change 2020-08-12 16:24:30 +08:00
sylor_huang@126.com db6aa954b1 Change 2020-08-12 16:18:16 +08:00
sylor_huang@126.com 04a611a4aa Change 2020-08-12 16:01:42 +08:00
sylor_huang@126.com 9ecea83506 Change 2020-08-12 15:43:55 +08:00
sylor_huang@126.com 82a9907fdc change 2020-08-12 15:31:56 +08:00
sylor_huang@126.com c56c98fd6e Change 2020-08-12 15:30:39 +08:00
sylor_huang@126.com 2948ad2033 Change 2020-08-12 15:28:09 +08:00
sylor_huang@126.com fc611140cf change 2020-08-12 15:25:16 +08:00
sylor_huang@126.com fcb5f58b69 change 2020-08-12 15:15:44 +08:00
sylor_huang@126.com 0f38a130f3 Change 2020-08-12 15:12:26 +08:00
sylor_huang@126.com fc54632a08 Change 2020-08-12 14:45:45 +08:00
sylor_huang@126.com 5963af5c7b Change Sidekiq 2020-08-12 14:41:53 +08:00
sylor_huang@126.com c1f2f7f6e2 Build 2020-08-12 14:06:32 +08:00
sylor_huang@126.com 271699daf1 Change 2020-08-12 11:54:20 +08:00
sylor_huang@126.com 98da7ea34d Change 2020-08-12 11:49:55 +08:00
sylor_huang@126.com 645e4a3586 Change 2020-08-12 11:45:57 +08:00
sylor_huang@126.com 7beca24a05 Change 2020-08-12 11:42:22 +08:00
sylor_huang@126.com d1368c7612 Change 2020-08-12 11:14:37 +08:00
sylor_huang@126.com 28e762810e Set 2020-08-12 10:45:54 +08:00
sylor_huang@126.com 0f60d0adc9 Change 2020-08-11 17:13:42 +08:00
sylor_huang@126.com e634317675 CHnage 2020-08-11 17:11:56 +08:00
sylor_huang@126.com 6b1a0a96c6 CHange 2020-08-11 17:09:48 +08:00
sylor_huang@126.com 298859bd10 Change 2020-08-11 17:07:15 +08:00
sylor_huang@126.com d4d412ab40 Change 2020-08-11 17:00:56 +08:00
sylor_huang@126.com 57d1a1474e Change 2020-08-11 16:21:43 +08:00
sylor_huang@126.com 055b7dbac5 Change 2020-08-11 15:56:37 +08:00
sylor_huang@126.com 30aad87e5a Change 2020-08-11 15:49:03 +08:00
sylor_huang@126.com aecd68fe9a Chnage 2020-08-11 15:44:10 +08:00
sylor_huang@126.com 998a6828d9 change 2020-08-11 15:34:50 +08:00
sylor_huang@126.com 12c04d02e5 Change 2020-08-11 15:30:12 +08:00
sylor_huang@126.com d6ef3d8aa3 Change 2020-08-11 15:23:49 +08:00
sylor_huang@126.com c7a89d1660 Change 2020-08-11 14:49:53 +08:00
sylor_huang@126.com 1939c0d33f Set Auto Login 2020-08-11 11:28:49 +08:00
Jasder 561b9efd92 FIX change manager main site url 2020-08-10 12:08:00 +08:00
Jasder 6c0b87fdd1 FIX bug 2020-08-10 11:26:15 +08:00
Jasder 5d309d1dc4 FIX bug 2020-08-10 11:24:59 +08:00
Jasder 89c230c362 FIX 处理顶部导航错误的问题 2020-08-10 11:23:01 +08:00
Jasder d4156a5582 Delete some url with setting api 2020-08-09 22:07:16 +08:00
Jasder ee8cbb8553 FIX 调整云上实验配置 2020-08-07 14:34:26 +08:00
1089 changed files with 93369 additions and 1275238 deletions

View File

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

273
Gemfile
View File

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

View File

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

View File

@ -329,6 +329,7 @@ http://localhost:3000/api/licenses/ | jq
|licenses|array |返回数据|
|-- id |int |id |
|-- name |string|开源许可证名称|
|-- is_secret |string|是否为特殊许可证|
返回值
@ -337,23 +338,33 @@ http://localhost:3000/api/licenses/ | jq
"licenses": [
{
"id": 57,
"name": "AFL-1.2"
"name": "AFL-1.2",
"is_secret": false
},
{
"id": 76,
"name": "AFL-3.0"
"name": "AFL-3.0",
"is_secret": false
},
{
"id": 214,
"name": "AFL-1.1"
"name": "AFL-1.1",
"is_secret": false
},
{
"id": 326,
"name": "AFL-2.1"
"name": "AFL-2.1",
"is_secret": false
},
{
"id": 350,
"name": "AFL-2.0"
"name": "AFL-2.0",
"is_secret": false
},
{
"id": 359,
"name": "PHengLEI",
"is_secret": true
}
]
}
@ -597,6 +608,8 @@ curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq
|project_category_id |int|项目类别id|
|project_language_id |int|项目语言id|
|private |boolean|项目是否私有, true为私有false: 公开 |
|is_secret |boolean|项目是否为特殊协议项目, truefalse: 否 |
返回值
@ -609,7 +622,8 @@ curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq
"project_description": "my first project mirror_demo",
"project_category_id": 1,
"project_language_id": 2,
"private": false
"private": false,
"is_secret": true
}
```
---
@ -1189,6 +1203,7 @@ http://localhost:3000/api/projects | jq
|forked_count |int|被fork的数量|
|praises_count |int|star数量|
|is_public |boolean|是否公开, true:公开false:未公开|
|is_secret |boolean|是否为特殊许可证项目, true:是false:否|
|mirror_url |string|镜像url|
|last_update_time|int|最后更新时间为UNIX格式的时间戳|
|author |object|项目创建者|
@ -1199,6 +1214,10 @@ http://localhost:3000/api/projects | jq
|language |object|项目语言|
|-- id |int|项目语言id|
|-- name |string|项目语言名称|
|user_apply_signatures |object|用户创建的特殊许可申请|
|-- id |int|用户创建的特殊许可申请id|
|-- status |int|用户创建的特殊许可申请审核状态, 'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
返回值
@ -1214,6 +1233,7 @@ http://localhost:3000/api/projects | jq
"praises_count": 0,
"forked_count": 0,
"is_public": true,
"is_secret": true,
"mirror_url": null,
"last_update_time": 1577697461,
"author": {
@ -1227,7 +1247,13 @@ http://localhost:3000/api/projects | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[
{
"id": 1,
"status": "waiting"
}
]
},
{
"id": 2,
@ -1237,6 +1263,7 @@ http://localhost:3000/api/projects | jq
"praises_count": 0,
"forked_count": 0,
"is_public": true,
"is_secret": false,
"mirror_url": null,
"last_update_time": 1577697403,
"author": {
@ -1250,7 +1277,8 @@ http://localhost:3000/api/projects | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[]
},
{
"id": 3,
@ -1260,6 +1288,7 @@ http://localhost:3000/api/projects | jq
"praises_count": 0,
"forked_count": 0,
"is_public": true,
"is_secret": true,
"mirror_url": null,
"last_update_time": 1577415173,
"author": {
@ -1273,7 +1302,8 @@ http://localhost:3000/api/projects | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[]
},
{
"id": 5,
@ -1283,6 +1313,7 @@ http://localhost:3000/api/projects | jq
"praises_count": 0,
"forked_count": 0,
"is_public": false,
"is_secret": true,
"mirror_url": "https://gitea.com/CasperVector/slew.git",
"last_update_time": 1577346228,
"author": {
@ -1296,7 +1327,8 @@ http://localhost:3000/api/projects | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[]
},
{
"id": 7,
@ -1306,6 +1338,7 @@ http://localhost:3000/api/projects | jq
"praises_count": 0,
"forked_count": 0,
"is_public": true,
"is_secret": true,
"mirror_url": null,
"last_update_time": 1577341572,
"author": {
@ -1319,7 +1352,8 @@ http://localhost:3000/api/projects | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[]
}
]
}
@ -5059,6 +5093,7 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|forked_count |int|被fork的数量|
|praises_count |int|star数量|
|is_public |boolean|是否公开, true:公开false:未公开|
|is_secret |boolean|是否为特殊许可证项目, true:是false:否|
|mirror_url |string|镜像url|
|last_update_time|int|最后更新时间为UNIX格式的时间戳|
|author |object|项目创建者|
@ -5069,7 +5104,9 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|language |object|项目语言|
|-- id |int|项目语言id|
|-- name |string|项目语言名称|
|user_apply_signatures |object|用户创建的特殊许可申请|
|-- id |int|用户创建的特殊许可申请id|
|-- status |int|用户创建的特殊许可申请审核状态, 'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
返回值
```json
@ -5084,6 +5121,7 @@ http://localhost:3000/api/users/Jason/projects.json | jq
"praises_count": 0,
"forked_count": 0,
"is_public": true,
"is_secret": false,
"mirror_url": null,
"last_update_time": 1577697461,
"author": {
@ -5097,9 +5135,163 @@ http://localhost:3000/api/users/Jason/projects.json | jq
"language": {
"id": 2,
"name": "C"
}
},
"user_apply_signatures":[
{
"id": 1,
"status": "waiting"
}
]
}
]
}
```
---
#### 特殊许可证项目申请列表
```
GET /api/apply_signatures
```
*示例*
```bash
curl -X GET \
-d "project_id=36" \
-d "page=1" \
-d "limit=5" \
-d "search=16895620" \
-d "status=waiting" \
http://localhost:3000/api/apply_signatures | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
|-|-|-|-|
|project_id |是|int |项目id |
|page |否|string |页数,第几页 |
|limit |否|string |每页多少条数据默认15条 |
|search |否|string |用户名、登录名匹配搜索 |
|status |否|string |状态匹配搜索,'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过 |
*返回参数说明:*
|参数名|类型|说明|
|-|-|-|
|total_count |int |返回记录总条数 |
|apply_signatures |array|特殊许可证项目申请信息|
|-- id |int|特殊许可证项目申请id|
|-- status |int|特殊许可证项目申请状态,'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|user |object|用户|
|-- id |int|用户id|
|-- name |string|用户名称|
|-- login |string|用户登录名/标识|
|-- image_url |string|用户头像|
|-- email |string|用户邮箱|
|-- is_owner |boolean|是否是项目的拥有者true:是, false:不是|
|attachment |object|上传附件|
|--filename |string|附件名称|
|--path |string|附件地址|
返回值
```json
{
"total_count": 1,
"apply_signatures": [
{
"id": 18,
"status": "passed",
"user": {
"id": 3,
"name": "16895620",
"login": "16895620",
"image_url": "avatars/User/boy.jpg",
"email": "2456233122@qq.com",
"is_owner": false
},
"attachment": {
"filename": "PHengLEI软件开源协议.docx",
"path": "/api/attachments/23"
}
}
]
}
```
---
#### 特殊许可证项目用户创建申请
```
POST /api/apply_signatures
```
*示例*
```bash
curl -X POST \
-d "project_id=8" \
-d "attachment_id=4" \
http://localhost:3000/api/apply_signatures.json | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
|-|-|-|-|
|project_id |是|int |项目id |
|attachment_id |是|int |上传的文件id |
*返回参数说明:*
|参数名|类型|说明|
|-|-|-|
|id |int|特殊许可证项目用户创建申请的id|
|attachment |object|上传的文件|
|--filename |string|上传的文件的文件名|
返回值
```json
{
"id": 5,
"attachment": {
"filename": "timg.jpeg"
}
}
```
---
#### 特殊许可证项目申请修改
```
PATCH /api/apply_signatures/:id
```
*示例*
```bash
curl -X POST \
-d "id=18" \
-d "status=passed" \
-d "project_id=36" \
http://localhost:3000/api/apply_signatures/18 | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
|-|-|-|-|
|id |是|int |特殊许可证项目申请id |
|status |是|string |特殊许可证项目申请状态 'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|project_id |是|int |项目id|
*返回参数说明:*
|参数名|类型|说明|
|-|-|-|
|status |int |0:添加成功, -1: 更改失败, 1: 表示已经是该状态了 |
|message |string|返回信息说明|
返回值
```json
{
"status": 0,
"message": "success"
}
```
---

View File

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

View File

@ -6,7 +6,7 @@ $(document).on('turbolinks:load', function(){
});
var sidebarController = $('#sidebar').data('current-controller');
if (sidebarController.length > 0) {
if (sidebarController && sidebarController.length > 0) {
$('#sidebar a.active').removeClass('active');
$('#sidebar ul.collapse.show').removeClass('show');
var activeLi = $('#sidebar a[data-controller="' + sidebarController + '"]');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -0,0 +1,32 @@
class Admins::ApplySignaturesController < Admins::BaseController
def index
sort_by = params[:sort_by] ||= 'created_on'
sort_direction = params[:sort_direction] ||= 'desc'
@apply_signatures = paginate ApplySignature.waiting.includes(:attachments)
end
def update
ActiveRecord::Base.transaction do
begin
apply_signature = ApplySignature.find_by!(id: params[:id])
apply_signature.update_attributes!(apply_signatures_params)
if apply_signature.status == "passed"
Projects::AddMemberInteractor.call(apply_signature.project.owner, apply_signature.project, apply_signature.user, "read", true)
end
redirect_to admins_apply_signatures_path
flash[:success] = "更新成功"
rescue => e
raise ActiveRecord::Rollback
redirect_to admins_apply_signatures_path
flash[:danger] = "更新失败"
end
end
end
private
def apply_signatures_params
params.permit(:status)
end
end

View File

@ -1,10 +1,33 @@
class Admins::DashboardsController < Admins::BaseController
def index
@active_user_count = User.where(last_login_on: today).count
@weekly_active_user_count = User.where(last_login_on: current_week).count
@month_active_user_count = User.where(last_login_on: current_month).count
# 用户活跃数
day_user_ids = CommitLog.where(created_at: today).pluck(:user_id).uniq
weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:user_id).uniq
month_user_ids = CommitLog.where(created_at: current_month).pluck(:user_id).uniq
@active_user_count = User.where(last_login_on: today).or(User.where(id: day_user_ids)).count
@weekly_active_user_count = User.where(last_login_on: current_week).or(User.where(id: weekly_user_ids)).count
@month_active_user_count = User.where(last_login_on: current_month).or(User.where(id: month_user_ids)).count
user_ids = User.where(created_on: pre_week).pluck(:id).uniq
weekly_keep_user_count = User.where(id: user_ids).where(last_login_on: current_week).count
@weekly_keep_rate = format("%.2f", user_ids.size > 0 ? weekly_keep_user_count.to_f / user_ids.size : 0)
@new_user_count = User.where(created_on: current_month).count
# 新用户注册数
@day_new_user_count = User.where(created_on: today).count
@weekly_new_user_count = User.where(created_on: current_week).count
@month_new_user_count = User.where(created_on: current_month).count
# 活跃项目数
day_project_ids = (CommitLog.where(created_at: today).pluck(:project_id).uniq + Issue.where(created_on: today).pluck(:project_id).uniq).uniq
weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq
month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq
@day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count
@weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
@month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
# 新增项目数
@day_new_project_count = Project.where(created_on: today).count
@weekly_new_project_count = Project.where(created_on: current_week).count
@month_new_project_count = Project.where(created_on: current_month).count
end
def month_active_user
@ -42,10 +65,14 @@ class Admins::DashboardsController < Admins::BaseController
end
def current_week
7.days.ago.beginning_of_day..Time.now.end_of_day
7.days.ago.end_of_day..Time.now.end_of_day
end
def current_month
30.days.ago.beginning_of_day..Time.now.end_of_day
30.days.ago.end_of_day..Time.now.end_of_day
end
def pre_week
14.days.ago.end_of_day..7.days.ago.end_of_day
end
end

View File

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

View File

@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
def create
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)
rescue Admins::ImportUserService::Error => ex
render_error(ex)

View File

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

View File

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

View File

@ -0,0 +1,36 @@
class Admins::PhengleiUsersController < Admins::BaseController
before_action :phenglei_project, only: [:index]
def index
if params[:keyword].present?
@phenglei_users = PhengleiUser.ransack(phone_cont: params[:keyword]).result
else
@phenglei_users = PhengleiUser
end
@phenglei_users = @phenglei_users.page(page).per(per_page)
end
def new
@phenglei_user = PhengleiUser.new
end
def create
@phenglei_user = PhengleiUser.new(phenglei_user_params)
if @phenglei_user.save
redirect_to admins_phenglei_users_path
flash[:success] = "创建成功"
else
redirect_to admins_phenglei_users_path
flash[:error] = "创建失败"
end
end
private
def phenglei_project
@phenglei_project = Project.find_by_id(EduSetting.get("sync_phenglei_user_project"))
end
def phenglei_user_params
params.require(:phenglei_user).permit(:phone)
end
end

View File

@ -0,0 +1,97 @@
class Admins::PlatformCommunicatesController < Admins::BaseController
before_action :get_communicate, only: [:edit, :update, :destroy, :show, :online_switch]
def index
params[:location] = "pc"
sort_by = PlatformCommunicate.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'order_index'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = PlatformCommunicate.where(location: params[:location]).ransack(title_cont: params[:search])
communicates = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@communicates = kaminari_paginate(communicates)
end
def applet
params[:location] = "applet"
sort_by = PlatformCommunicate.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'order_index'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = PlatformCommunicate.where(location: params[:location]).ransack(title_cont: params[:search])
communicates = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@communicates = kaminari_paginate(communicates)
end
def show
watchers = @communicate.watchers
if params[:search].present?
like_sql = 'users.lastname LIKE :keyword OR users.nickname LIKE :keyword OR users.mail LIKE :keyword OR users.phone LIKE :keyword OR users.login LIKE :keyword OR users.company_name LIKE :keyword'
watchers = watchers.left_joins(:user).where(like_sql, keyword: "%#{params[:search]}%")
end
if params[:user_type].present?
watchers = watchers.left_joins(:user).where("users.user_type = ?", params[:user_type])
end
if params[:professional_field].present?
watchers = watchers.left_joins(:user).where("users.professional_field = ?", params[:professional_field])
end
@watchers = kaminari_paginate watchers
end
def new
location = params[:location] || "pc"
@communicate = PlatformCommunicate.new(location: location)
end
def create
@communicate = PlatformCommunicate.new(communicate_params)
if @communicate.save
redirect_to @communicate.location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:success] = '创建成功'
else
redirect_to @communicate.location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:danger] = "创建失败"
end
end
def edit
end
def update
@communicate.attributes = communicate_params
if @communicate.save
redirect_to @communicate.location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:success] = '更新成功'
else
redirect_to @communicate.location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:danger] = '更新失败'
end
end
def destroy
location = @communicate.location
if @communicate.destroy
redirect_to location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:success] = '删除成功'
else
redirect_to location == 'pc' ? "/admins/platform_communicates?location=pc" : "/admins/platform_communicates/applet?location=applet"
flash[:danger] = '删除失败'
end
end
def online_switch
if @communicate.status
@communicate.update_attributes!(status: false)
else
@communicate.update_attributes!(status: true)
end
# render_ok
end
private
def get_communicate
@communicate = PlatformCommunicate.find_by_id(params[:id])
end
def communicate_params
params.require(:platform_communicate).permit!
end
end

View File

@ -0,0 +1,69 @@
class Admins::PlatformPeopleController < Admins::BaseController
before_action :get_person, only: [:edit, :update, :destroy]
def index
sort_by = PlatformPerson.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = PlatformPerson.ransack(name_cont: params[:search])
people = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@people = kaminari_paginate(people)
end
def new
@person = PlatformPerson.new
end
def create
@person = PlatformPerson.new(person_params)
if @person.save
save_image_file(params[:image], @person)
redirect_to admins_platform_people_path
flash[:success] = '创建论坛交流人物成功'
else
redirect_to admins_platform_people_path
flash[:danger] = "创建论坛交流人物失败"
end
end
def edit
end
def update
@person.attributes = person_params
if @person.save
save_image_file(params[:image], @person)
redirect_to admins_platform_people_path
flash[:success] = '更新论坛交流人物成功'
else
redirect_to admins_platform_people_path
flash[:danger] = '更新论坛交流人物失败'
end
end
def destroy
if @person.destroy
redirect_to admins_platform_people_path
flash[:success] = '删除论坛交流人物成功'
else
redirect_to admins_platform_people_path
flash[:danger] = '删除论坛交流人物失败'
end
end
private
def get_person
@person = PlatformPerson.find_by_id(params[:id])
end
def person_params
params.require(:platform_person).permit!
end
def save_image_file(file, topic)
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
file_path = Util::FileManage.source_disk_filename(topic, 'image')
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(file, file_path)
end
end

View File

@ -5,7 +5,7 @@ class Admins::ProjectCategoriesController < Admins::BaseController
def index
sort_by = ProjectCategory.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = ProjectCategory.ransack(name_cont: params[:name])
q = ProjectCategory.ransack(name_cont: params[:search])
project_categories = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@project_categories = paginate(project_categories)

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
class Admins::ProjectsController < Admins::BaseController
before_action :find_project, only: [:edit, :update]
before_action :find_project, only: [:edit, :update, :sync_phenglei_user]
def index
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
search = params[:search].to_s.strip
projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score, :license)
end
def edit ;end
@ -43,6 +43,28 @@ class Admins::ProjectsController < Admins::BaseController
flash[:danger] = "删除失败"
end
def export
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
search = params[:search].to_s.strip
projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
@projects = projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score, :license)
filename = ["项目列表", Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << '.xlsx'
@domain_url = EduSetting.get('host_name')
render xlsx: 'export', filename: filename
end
def sync_phenglei_user
if @project.is_secret
SyncPhengleiUserJob.perform_later(@project.id)
redirect_to admins_phenglei_users_path
flash[:success] = "已开启后台同步任务"
else
redirect_to admins_phenglei_users_path
flash[:danger] = "非风雷协议项目"
end
end
private
def find_project
@project = Project.find_by_id(params[:id])

View File

@ -0,0 +1,57 @@
class Admins::Topic::ActivityForumsController < Admins::Topic::BaseController
before_action :find_activity_forum, only: [:edit, :update, :destroy]
def index
q = ::Topic::ActivityForum.ransack(title_cont: params[:search])
activity_forums = q.result(distinct: true)
@activity_forums = paginate(activity_forums)
end
def new
@activity_forum = ::Topic::ActivityForum.new
end
def create
@activity_forum = ::Topic::ActivityForum.new(activity_forum_params)
if @activity_forum.save
redirect_to admins_topic_activity_forums_path
flash[:success] = "新增平台动态成功"
else
redirect_to admins_topic_activity_forums_path
flash[:danger] = "新增平台动态失败"
end
end
def edit
end
def update
@activity_forum.attributes = activity_forum_params
if @activity_forum.save
redirect_to admins_topic_activity_forums_path
flash[:success] = "更新平台动态成功"
else
redirect_to admins_topic_activity_forums_path
flash[:danger] = "更新平台动态失败"
end
end
def destroy
if @activity_forum.destroy
redirect_to admins_topic_activity_forums_path
flash[:success] = "删除平台动态成功"
else
redirect_to admins_topic_activity_forums_path
flash[:danger] = "删除平台动态失败"
end
end
private
def find_activity_forum
@activity_forum = ::Topic::ActivityForum.find_by_id(params[:id])
end
def activity_forum_params
params.require(:topic_activity_forum).permit(:title, :uuid, :url, :order_index)
end
end

View File

@ -0,0 +1,60 @@
class Admins::Topic::AppletBannersController < Admins::Topic::BaseController
before_action :find_banner, only: [:edit, :update, :destroy]
def index
@banners = ::Topic::AppletBanner
@banners = @banners.where("title like ?", "%#{params[:search]}%") if params[:search].present?
@banners = @banners.where(location: params[:location]) if params[:location].present?
@banners = paginate(@banners)
end
def new
@banner = ::Topic::AppletBanner.new
end
def create
@banner = ::Topic::AppletBanner.new(banner_params)
if @banner.save
save_image_file(params[:image], @banner)
redirect_to admins_topic_applet_banners_path
flash[:success] = "新增banner成功"
else
redirect_to admins_topic_applet_banners_path
flash[:danger] = "新增banner失败"
end
end
def edit
end
def update
@banner.attributes = banner_params
if @banner.save
save_image_file(params[:image], @banner)
redirect_to admins_topic_applet_banners_path
flash[:success] = "更新banner成功"
else
redirect_to admins_topic_applet_banners_path
flash[:danger] = "更新banner失败"
end
end
def destroy
if @banner.destroy
redirect_to admins_topic_applet_banners_path
flash[:success] = "删除banner成功"
else
redirect_to admins_topic_applet_banners_path
flash[:danger] = "删除banner失败"
end
end
private
def find_banner
@banner = ::Topic::AppletBanner.find_by_id(params[:id])
end
def banner_params
params.require(:topic_applet_banner).permit(:title, :order_index, :url, :location)
end
end

View File

@ -0,0 +1,58 @@
class Admins::Topic::BannersController < Admins::Topic::BaseController
before_action :find_banner, only: [:edit, :update, :destroy]
def index
@banners = paginate(::Topic::Banner)
@banners = paginate(::Topic::Banner.where("title like ?", "%#{params[:search]}%")) if params[:search].present?
end
def new
@banner = ::Topic::Banner.new
end
def create
@banner = ::Topic::Banner.new(banner_params)
if @banner.save
save_image_file(params[:image], @banner)
redirect_to admins_topic_banners_path
flash[:success] = "新增banner成功"
else
redirect_to admins_topic_banners_path
flash[:danger] = "新增banner失败"
end
end
def edit
end
def update
@banner.attributes = banner_params
if @banner.save
save_image_file(params[:image], @banner)
redirect_to admins_topic_banners_path
flash[:success] = "更新banner成功"
else
redirect_to admins_topic_banners_path
flash[:danger] = "更新banner失败"
end
end
def destroy
if @banner.destroy
redirect_to admins_topic_banners_path
flash[:success] = "删除banner成功"
else
redirect_to admins_topic_banners_path
flash[:danger] = "删除banner失败"
end
end
private
def find_banner
@banner = ::Topic::Banner.find_by_id(params[:id])
end
def banner_params
params.require(:topic_banner).permit(:title, :order_index, :url)
end
end

View File

@ -0,0 +1,11 @@
class Admins::Topic::BaseController < Admins::BaseController
protected
def save_image_file(file, topic)
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
file_path = Util::FileManage.source_disk_filename(topic, 'image')
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(file, file_path)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::CardsController < Admins::Topic::BaseController
before_action :find_card, only: [:edit, :update, :destroy]
def index
q = ::Topic::Card.ransack(title_cont: params[:search])
cards = q.result(distinct: true)
@cards = paginate(cards)
end
def new
@card = ::Topic::Card.new
end
def create
@card = ::Topic::Card.new(card_params)
if @card.save
redirect_to admins_topic_cards_path
flash[:success] = "新增合作单位成功"
else
redirect_to admins_topic_cards_path
flash[:danger] = "新增合作单位失败"
end
end
def edit
end
def update
@card.attributes = card_params
if @card.save
redirect_to admins_topic_cards_path
flash[:success] = "更新合作单位成功"
else
redirect_to admins_topic_cards_path
flash[:danger] = "更新合作单位失败"
end
end
def destroy
if @card.destroy
redirect_to admins_topic_cards_path
flash[:success] = "删除合作单位成功"
else
redirect_to admins_topic_cards_path
flash[:danger] = "删除合作单位失败"
end
end
private
def find_card
@card = ::Topic::Card.find_by_id(params[:id])
end
def card_params
params.require(:topic_card).permit(:title, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::CooperatorsController < Admins::Topic::BaseController
before_action :find_cooperator, only: [:edit, :update, :destroy]
def index
@cooperators = paginate(::Topic::Cooperator)
end
def new
@cooperator = ::Topic::Cooperator.new
end
def create
@cooperator = ::Topic::Cooperator.new(cooperator_params)
if @cooperator.save
save_image_file(params[:image], @cooperator)
redirect_to admins_topic_cooperators_path
flash[:success] = "新增合作单位成功"
else
redirect_to admins_topic_cooperators_path
flash[:danger] = "新增合作单位失败"
end
end
def edit
end
def update
@cooperator.attributes = cooperator_params
if @cooperator.save
save_image_file(params[:image], @cooperator)
redirect_to admins_topic_cooperators_path
flash[:success] = "更新合作单位成功"
else
redirect_to admins_topic_cooperators_path
flash[:danger] = "更新合作单位失败"
end
end
def destroy
if @cooperator.destroy
redirect_to admins_topic_cooperators_path
flash[:success] = "删除合作单位成功"
else
redirect_to admins_topic_cooperators_path
flash[:danger] = "删除合作单位失败"
end
end
private
def find_cooperator
@cooperator = ::Topic::Cooperator.find_by_id(params[:id])
end
def cooperator_params
params.require(:topic_cooperator).permit(:title, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::ExcellentProjectsController < Admins::Topic::BaseController
before_action :find_excellent_project, only: [:edit, :update, :destroy]
def index
q = ::Topic::ExcellentProject.ransack(title_cont: params[:search])
excellent_projects = q.result(distinct: true)
@excellent_projects = paginate(excellent_projects)
end
def new
@excellent_project = ::Topic::ExcellentProject.new
end
def create
@excellent_project = ::Topic::ExcellentProject.new(excellent_project_params)
if @excellent_project.save
redirect_to admins_topic_excellent_projects_path
flash[:success] = "新增优秀仓库成功"
else
redirect_to admins_topic_excellent_projects_path
flash[:danger] = "新增优秀仓库失败"
end
end
def edit
end
def update
@excellent_project.attributes = excellent_project_params
if @excellent_project.save
redirect_to admins_topic_excellent_projects_path
flash[:success] = "更新优秀仓库成功"
else
redirect_to admins_topic_excellent_projects_path
flash[:danger] = "更新优秀仓库失败"
end
end
def destroy
if @excellent_project.destroy
redirect_to admins_topic_excellent_projects_path
flash[:success] = "删除优秀仓库成功"
else
redirect_to admins_topic_excellent_projects_path
flash[:danger] = "删除优秀仓库失败"
end
end
private
def find_excellent_project
@excellent_project = ::Topic::ExcellentProject.find_by_id(params[:id])
end
def excellent_project_params
params.require(:topic_excellent_project).permit(:title, :uuid, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::ExperienceForumsController < Admins::Topic::BaseController
before_action :find_experience_forum, only: [:edit, :update, :destroy]
def index
q = ::Topic::ExperienceForum.ransack(title_cont: params[:search])
experience_forums = q.result(distinct: true)
@experience_forums = paginate(experience_forums)
end
def new
@experience_forum = ::Topic::ExperienceForum.new
end
def create
@experience_forum = ::Topic::ExperienceForum.new(experience_forum_params)
if @experience_forum.save
redirect_to admins_topic_experience_forums_path
flash[:success] = "新增经验分享成功"
else
redirect_to admins_topic_experience_forums_path
flash[:danger] = "新增经验分享失败"
end
end
def edit
end
def update
@experience_forum.attributes = experience_forum_params
if @experience_forum.save
redirect_to admins_topic_experience_forums_path
flash[:success] = "更新经验分享成功"
else
redirect_to admins_topic_experience_forums_path
flash[:danger] = "更新经验分享失败"
end
end
def destroy
if @experience_forum.destroy
redirect_to admins_topic_experience_forums_path
flash[:success] = "删除经验分享成功"
else
redirect_to admins_topic_experience_forums_path
flash[:danger] = "删除经验分享失败"
end
end
private
def find_experience_forum
@experience_forum = ::Topic::ExperienceForum.find_by_id(params[:id])
end
def experience_forum_params
params.require(:topic_experience_forum).permit(:title, :uuid, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::GlccNewsController < Admins::Topic::BaseController
before_action :find_glcc, only: [:edit, :update, :destroy]
def index
q = ::Topic::GlccNews.ransack(title_cont: params[:search])
glcc_news = q.result(distinct: true)
@glcc_news = paginate(glcc_news)
end
def new
@glcc = ::Topic::GlccNews.new
end
def create
@glcc = ::Topic::GlccNews.new(glcc_params)
if @glcc.save
redirect_to admins_topic_glcc_news_index_path
flash[:success] = "新增新闻稿成功"
else
redirect_to admins_topic_glcc_news_index_path
flash[:danger] = "新增新闻稿失败"
end
end
def edit
end
def update
@glcc.attributes = glcc_params
if @glcc.save
redirect_to admins_topic_glcc_news_index_path
flash[:success] = "更新新闻稿成功"
else
redirect_to admins_topic_glcc_news_index_path
flash[:danger] = "更新新闻稿失败"
end
end
def destroy
if @glcc.destroy
redirect_to admins_topic_glcc_news_index_path
flash[:success] = "删除新闻稿成功"
else
redirect_to admins_topic_glcc_news_index_path
flash[:danger] = "删除新闻稿失败"
end
end
private
def find_glcc
@glcc = ::Topic::GlccNews.find_by_id(params[:id])
end
def glcc_params
params.require(:topic_glcc_news).permit(:title, :uuid, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::OrganizationsController < Admins::Topic::BaseController
before_action :find_organization, only: [:edit, :update, :destroy]
def index
@organizations = paginate(::Topic::Organization)
end
def new
@organization = ::Topic::Organization.new
end
def create
@organization = ::Topic::Organization.new(organization_params)
if @organization.save
save_image_file(params[:image], @organization)
redirect_to admins_topic_organizations_path
flash[:success] = "新增组织logo成功"
else
redirect_to admins_topic_organizations_path
flash[:danger] = "新增组织logo失败"
end
end
def edit
end
def update
@organization.attributes = organization_params
if @organization.save
save_image_file(params[:image], @organization)
redirect_to admins_topic_organizations_path
flash[:success] = "更新组织logo成功"
else
redirect_to admins_topic_organizations_path
flash[:danger] = "更新组织logo失败"
end
end
def destroy
if @organization.destroy
redirect_to admins_topic_organizations_path
flash[:success] = "删除组织logo成功"
else
redirect_to admins_topic_organizations_path
flash[:danger] = "删除组织logo失败"
end
end
private
def find_organization
@organization = ::Topic::Organization.find_by_id(params[:id])
end
def organization_params
params.require(:topic_organization).permit(:title, :url, :order_index)
end
end

View File

@ -0,0 +1,57 @@
class Admins::Topic::PinnedForumsController < Admins::Topic::BaseController
before_action :find_pinned_forum, only: [:edit, :update, :destroy]
def index
q = ::Topic::PinnedForum.ransack(title_cont: params[:search])
pinned_forums = q.result(distinct: true)
@pinned_forums = paginate(pinned_forums)
end
def new
@pinned_forum = ::Topic::PinnedForum.new
end
def create
@pinned_forum = ::Topic::PinnedForum.new(pinned_forum_params)
if @pinned_forum.save
redirect_to admins_topic_pinned_forums_path
flash[:success] = "新增精选文章成功"
else
redirect_to admins_topic_pinned_forums_path
flash[:danger] = "新增精选文章失败"
end
end
def edit
end
def update
@pinned_forum.attributes = pinned_forum_params
if @pinned_forum.save
redirect_to admins_topic_pinned_forums_path
flash[:success] = "更新精选文章成功"
else
redirect_to admins_topic_pinned_forums_path
flash[:danger] = "更新精选文章失败"
end
end
def destroy
if @pinned_forum.destroy
redirect_to admins_topic_pinned_forums_path
flash[:success] = "删除精选文章成功"
else
redirect_to admins_topic_pinned_forums_path
flash[:danger] = "删除精选文章失败"
end
end
private
def find_pinned_forum
@pinned_forum = ::Topic::PinnedForum.find_by_id(params[:id])
end
def pinned_forum_params
params.require(:topic_pinned_forum).permit(:title, :uuid, :url, :order_index)
end
end

View File

@ -1,5 +1,5 @@
class Admins::UsersController < Admins::BaseController
before_action :finder_user, except: [:index]
before_action :finder_user, except: [:index, :export]
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
@ -24,6 +24,16 @@ class Admins::UsersController < Admins::BaseController
render 'edit'
end
def export
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
users = Admins::UserQuery.call(params)
@users = users.includes(:user_extension, projects: :members)
filename = ["用户列表", Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << '.xlsx'
render xlsx: 'export', filename: filename
end
def destroy
@user.destroy!
Gitea::User::DeleteService.call(@user.login)
@ -57,7 +67,50 @@ class Admins::UsersController < Admins::BaseController
render_ok
end
def new
@user = User.new
end
def create
Users::AdminCreateUserForm.new(validate_create_params).validate!
user = User.new(create_params)
login = User.generate_login("p")
user.type = 'User'
user.login = login
user.mail = "#{login}@example.org"
ActiveRecord::Base.transaction do
if user.save!
UserExtension.create!(user_id: user.id)
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: create_params[:password]})
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.call(user.login, create_params[:password])
user.gitea_token = result['sha1']
user.gitea_uid = gitea_user[:body]['id']
user.save!
end
end
end
flash[:success] = '保存成功'
redirect_to admins_users_path
rescue ActiveRecord::RecordInvalid => e
logger.info "------------ #{e.message}"
puts e.message
flash.now[:danger] = e.message
render 'new'
rescue Exception => ex
flash.now[:danger] = ex.message
render 'new'
end
private
def finder_user
@user = User.find(params[:id])
end
def finder_user
@user = User.find(params[:id])
@ -66,6 +119,14 @@ class Admins::UsersController < Admins::BaseController
def update_params
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
mail phone location location_city school_id department_id admin business is_test
password professional_certification authentication login])
password professional_certification authentication login bank_certification enterprise_certification])
end
def create_params
params.require(:user).permit(%i[nickname gender mail phone location location_city password professional_certification])
end
def validate_create_params
create_params.slice(:phone, :password)
end
end

View File

@ -0,0 +1,63 @@
class Api::V1::BaseController < ApplicationController
include Api::ProjectHelper
include Api::UserHelper
include Api::PullHelper
# before_action :doorkeeper_authorize!
# skip_before_action :user_setup
protected
# def current_user
# #client方法对接需要一直带着用户标识uid
# Rails.logger.info doorkeeper_token
# if doorkeeper_token && doorkeeper_token.resource_owner_id.blank?
# # return User.anonymous if params[:uid].nil?
# # tip_exception("2222")
# # return render_error('缺少用户标识!') if params[:uid].nil?
# User.current = User.find(params[:uid])
# else
# User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
# end
# end
def kaminary_select_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 200) ? 200 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
end
def limit
params.fetch(:limit, 15)
end
def page
params.fetch(:page, 1)
end
# 具有对仓库的管理权限
def require_manager_above
@project = load_project
return render_forbidden if !current_user.admin? && !@project.manager?(current_user)
end
# 具有对仓库的操作权限
def require_operate_above
@project = load_project
return render_forbidden if !current_user.admin? && !@project.operator?(current_user)
end
# 具有仓库的操作权限或者fork仓库的操作权限
def require_operate_above_or_fork_project
@project = load_project
puts !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
return render_forbidden if !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
end
# 具有对仓库的访问权限
def require_public_and_member_above
@project = load_project
return render_forbidden if !@project.is_public && !current_user.admin? && !@project.member?(current_user)
end
end

View File

@ -0,0 +1,46 @@
class Api::V1::ProjectTopicsController < Api::V1::BaseController
def index
@project_topics = ProjectTopic
@project_topics = @project_topics.ransack(name_cont: params[:keyword]) if params[:keyword].present?
@project_topics = @project_topics.includes(:projects)
@project_topics = kaminary_select_paginate(@project_topics)
end
def create
ActiveRecord::Base.transaction do
@project = Project.find_by_id(create_params[:project_id])
return render_not_found unless @project.present?
return render_error("请输入项目搜索标签名称.") unless create_params[:name].present?
@project_topic = ProjectTopic.find_or_create_by!(name: create_params[:name].downcase)
@project_topic_ralate = @project_topic.project_topic_ralates.find_or_create_by!(project_id: create_params[:project_id])
if @project_topic.present? && @project_topic_ralate.present?
render_ok
else
render_error("项目关联搜索标签失败.")
end
end
end
def destroy
ActiveRecord::Base.transaction do
@project = Project.find_by_id(create_params[:project_id])
return render_not_found unless @project.present?
@project_topic = ProjectTopic.find_by_id(params[:id])
@project_topic_ralate = @project_topic.project_topic_ralates.find_by(project_id: @project.id)
if @project_topic_ralate.destroy!
render_ok
else
render_error("项目取消关联搜索标签失败.")
end
end
end
private
def create_params
params.permit(:project_id, :name)
end
end

View File

@ -0,0 +1,18 @@
class Api::V1::Projects::BranchesController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:all]
def all
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
end
before_action :require_operate_above, only: [:create]
def create
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
end
private
def branch_params
params.require(:branch).permit(:new_branch_name, :old_branch_name)
end
end

View File

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

View File

@ -0,0 +1,12 @@
class Api::V1::Projects::CommitsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index, :diff]
def index
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
puts @result_object
end
def diff
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
end
end

View File

@ -0,0 +1,17 @@
class Api::V1::Projects::ContentsController < Api::V1::BaseController
before_action :require_operate_above_or_fork_project, only: [:batch]
def batch
@batch_content_params = batch_content_params
# 处理下author和committer信息如果没传则默认为当前用户信息
@batch_content_params.merge!(author_email: current_user.mail, author_name: current_user.login) if batch_content_params[:author_email].blank? && batch_content_params[:author_name].blank?
@batch_content_params.merge!(committer_email: current_user.mail, committer_name: current_user.login) if batch_content_params[:committer_email].blank? && batch_content_params[:committer_name].blank?
@result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, @batch_content_params, @project.owner.gitea_token)
end
private
def batch_content_params
params.require(:content).permit(:author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch, files: [ :action_type, :content, :encoding, :file_path])
end
end

View File

@ -0,0 +1,12 @@
class Api::V1::Projects::GitController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:trees, :blobs]
def trees
@result_object = Api::V1::Projects::Git::TreesService.call(@project, params[:sha], {recursive: params[:recursive], page: page, limit: limit}, current_user&.gitea_token)
end
def blobs
@result_object = Api::V1::Projects::Git::BlobsService.call(@project, params[:sha], current_user&.gitea_token)
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,61 @@
class Api::V1::Projects::WebhooksController < Api::V1::BaseController
before_action :require_manager_above
before_action :find_webhook, only: [:show, :update, :destroy, :tests, :hooktasks]
def index
# @result_object = Api::V1::Projects::Webhooks::ListService.call(@project, current_user&.gitea_token)
@webhooks = @project.webhooks
@webhooks = @webhooks.where(type: params[:type]) if params[:type].present?
@webhooks = kaminari_paginate(@webhooks)
end
def create
return render_error("webhooks数量已到上限请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49
@result_object = Api::V1::Projects::Webhooks::CreateService.call(@project, create_webhook_params, current_user&.gitea_token)
end
def show
@result_object = Api::V1::Projects::Webhooks::GetService.call(@project, params[:id], current_user&.gitea_token)
end
def update
@result_object = Api::V1::Projects::Webhooks::UpdateService.call(@project, params[:id], webhook_params, current_user&.gitea_token)
end
def destroy
@result_object = Api::V1::Projects::Webhooks::DeleteService.call(@project, params[:id], current_user&.gitea_token)
if @result_object
return render_ok
else
return render_error('删除失败!')
end
end
def tests
@result_object = Api::V1::Projects::Webhooks::TestsService.call(@project, params[:id], current_user&.gitea_token)
if @result_object
return render_ok
else
return render_error('推送失败!')
end
end
def hooktasks
@hooktasks = @webhook.tasks.where(is_delivered: true).order("delivered desc")
@hooktasks = kaminari_paginate(@hooktasks)
end
private
def create_webhook_params
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, :type, events: [])
end
def webhook_params
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, events: [])
end
def find_webhook
@webhook = Gitea::Webhook.find_by_id(params[:id])
return render_not_found unless @webhook.present?
end
end

View File

@ -0,0 +1,19 @@
class Api::V1::ProjectsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:show, :compare, :blame]
def index
render_ok
end
def show
@result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token)
end
def compare
@result_object = Api::V1::Projects::CompareService.call(@project, params[:from], params[:to], current_user&.gitea_token)
end
def blame
@result_object = Api::V1::Projects::BlameService.call(@project, params[:sha], params[:filepath], current_user&.gitea_token)
end
end

View File

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

View File

@ -0,0 +1,13 @@
class Api::V1::Users::ProjectsController < Api::V1::BaseController
before_action :load_observe_user
def index
@object_results = Api::V1::Users::Projects::ListService.call(@observe_user, query_params, current_user)
@projects = kaminari_paginate(@object_results)
end
private
def query_params
params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search)
end
end

View File

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

View File

@ -82,7 +82,7 @@ class ApplicationController < ActionController::Base
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end
user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
if user_exist && type.to_i == 1
tip_exception(-2, "该手机号码或邮箱已被注册")
@ -125,7 +125,7 @@ class ApplicationController < ActionController::Base
tip_exception(-2,"邮件发送失败,请稍后重试")
end
end
ver_params = {code_type: send_type, code: code}.merge(sigle_para)
ver_params = { code_type: send_type, code: code, status: 1 }.merge(sigle_para)
VerificationCode.create!(ver_params)
end
@ -174,11 +174,11 @@ class ApplicationController < ActionController::Base
end
def require_profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
# tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
end
def require_user_profile_completed(user)
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
# tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
end
# 异常提醒
@ -248,42 +248,55 @@ class ApplicationController < ActionController::Base
#return if params[:controller] == "main"
# Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
# 开放课程通过链接访问的用户
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
user = open_class_user
if user
start_user_session(user)
set_autologin_cookie(user)
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
if @doorkeeper_token.present?
# client方法对接需要一直带着用户标识uid
if @doorkeeper_token.resource_owner_id.blank?
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
User.current = User.find(params[:uid])
else
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
end
end
else
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
# 开放课程通过链接访问的用户
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
user = open_class_user
if user
start_user_session(user)
set_autologin_cookie(user)
end
User.current = user
end
User.current = user
end
end
# if !User.current.logged? && Rails.env.development?
# User.current = User.find 1
# end
if !User.current.logged? && Rails.env.development?
User.current = User.find 1
end
# 测试版前端需求
logger.info("subdomain:#{request.subdomain}")
# if request.subdomain != "www"
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
# User.current = User.find 81403
# elsif params[:debug] == 'student'
# User.current = User.find 8686
# elsif params[:debug] == 'admin'
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
# user = User.find 36480
# User.current = user
# cookies.signed[:user_id] = user.id
# end
# end
if request.subdomain != "www"
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 6
elsif params[:debug] == 'student'
User.current = User.find 7
elsif params[:debug] == 'admin'
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
user = User.find 1
User.current = user
cookies.signed[:user_id] = user.id
end
end
# User.current = User.find 81403
end
@ -309,9 +322,11 @@ class ApplicationController < ActionController::Base
# auto-login feature starts a new session
user = nil
Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
user = User.try_to_autologin(cookies[autologin_cookie_name])
user = User.try_to_autologin(cookies[autologin_cookie_name], autologin_action)
# start_user_session(user) if user # TODO 解决sso退出不同步的问题
user
elsif params[:token].present?
User.try_to_autologin(params[:token], autologin_action)
end
end
@ -686,7 +701,7 @@ class ApplicationController < ActionController::Base
@project, @owner = Project.find_with_namespace(namespace, id)
if @project and current_user.can_read_project?(@project)
if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
logger.info "########### has project and can read project"
@project
# elsif @project && current_user.is_a?(AnonymousUser)
@ -694,9 +709,15 @@ class ApplicationController < ActionController::Base
# @project = nil if !@project.is_public?
# render_forbidden and return
else
logger.info "###########project not found"
@project = nil
render_not_found and return
if @project.present?
logger.info "########### has project and but can't read project"
@project = nil
render_forbidden and return
else
logger.info "###########project not found"
@project = nil
render_not_found and return
end
end
@project
end
@ -709,14 +730,20 @@ class ApplicationController < ActionController::Base
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
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!
@image = params[:image]
@image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile
render_error('请上传文件') if @image.size.zero?
render_error('文件大小超过限制') if @image.size > max_size.to_i
return render_error('请上传文件') if @image.size.zero?
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
image = @image.to_s.strip
return render_error('请上传正确的图片') if image.blank?
@ -725,7 +752,7 @@ class ApplicationController < ActionController::Base
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
def avatar_path(object)
ApplicationController.helpers.disk_filename(object.class, object.id)
end

View File

@ -0,0 +1,121 @@
class ApplySignaturesController < ApplicationController
include ApplicationHelper
before_action :require_login
before_action :find_project, only: [:index, :show_pro_info, :create, :create_simple_info, :update]
before_action :require_owner, only: [:update]
before_action :find_apply_signature, only: [:update, :create_detail]
def index
search = params[:search].to_s.downcase
@apply_signatures = @project.apply_signatures.with_status(status).includes(user: :user_extension)
@apply_signatures = @apply_signatures.joins(:user).where("apply_signatures.name like ?" ,"%#{search}%").or(@apply_signatures.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%")) if search.present?
@apply_signatures = kaminari_paginate(@apply_signatures)
end
def show_pro_info
@user_apply_signature = @project.apply_signatures.with_user_id(current_user.id).take
end
def template_file
license_name = params[:license_name] || "PHengLEI"
license = License.find_by_name(license_name)
file = license.attachments.take
# normal_status(-1, "文件不存在") if file.blank?
if file.blank?
send_file("#{Rails.root.to_s}/public/#{license_name}-License.docx", filename: "#{license_name}软件开源协议.docx",stream:false, type: 'application/octet-stream')
else
send_file(absolute_path(local_path(file)), filename: file.title,stream:false, type: file.content_type.presence || 'application/octet-stream')
end
end
def create
tip_exception "您已上传开源许可协议" if current_user.apply_signatures.where(project_id: params[:project_id]).where(status: ['waiting', 'passed']).present?
ActiveRecord::Base.transaction do
begin
@signature = current_user.apply_signatures.find_or_create_by!(project_id: params[:project_id])
@signature.status = 0
@signature.attachments = Attachment.none
@attachment = Attachment.find_by_id(params[:attachment_id])
@attachment.container = @signature
@signature.save!
@attachment.save!
rescue Exception => e
tip_exception("#{e}")
raise ActiveRecord::Rollback
end
render_json
end
end
def create_simple_info
current_user.apply_signatures.where(project_id: params[:project_id]).where(status: ['unpassed']).destroy_all
tip_exception "您已提交基本信息" if current_user.apply_signatures.where(project_id: params[:project_id]).where(status: ['waiting', 'passed']).present?
ActiveRecord::Base.transaction do
begin
ApplySignatures::CreateSimpleInfoForm.new(simple_info_params).validate!
@signature = current_user.apply_signatures.find_or_create_by!(project_id: params[:project_id])
@signature.name = params[:name]
@signature.phone = params[:phone]
@signature.company_name = params[:company_name]
@signature.position = params[:position]
@signature.email = params[:email]
@signature.remark = params[:remark]
@signature.save!
rescue Exception => e
tip_exception("#{e}")
raise ActiveRecord::Rollback
end
end
render_ok
end
def create_detail
if ApplySignatureReadDetail.create!(apply_signature: @apply_signature, user: @apply_signature.user)
render_ok
else
render_error("阅读审核记录失败")
end
end
def update
return normal_status(-1, "已经是该状态了") if @apply_signature.status == params[:status]
@apply_signature.update_attributes!(apply_signature_params)
if @apply_signature.status == "passed"
SendTemplateMessageJob.perform_later('ApplySignaturePassed', @apply_signature.user_id, @apply_signature.id)
Projects::AddMemberInteractor.call(@apply_signature.project.owner, @apply_signature.project, @apply_signature.user, "read", true)
else
Projects::DeleteMemberInteractor.call(@apply_signature.project.owner, @apply_signature.project, @apply_signature.user)
end
render_ok
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
private
def find_project
@project = Project.find_by_id(params[:project_id])
normal_status(-1, "项目不存在") unless @project.present?
end
def find_apply_signature
@apply_signature = ApplySignature.find_by_id(params[:id])
normal_status(-1, "申请不存在") unless @apply_signature.present?
end
def apply_signature_params
params.permit(:status, :cdkey)
end
def simple_info_params
params.permit(:name, :phone, :remark, :company_name, :position, :email)
end
def status
params.fetch(:status, "all")
end
def require_owner
normal_status(403, "") unless @project.owner?(current_user) || current_user.admin?
end
end

View File

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

View File

@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
namespace = params[:owner]
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
def load_all_repo

View File

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

View File

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

View File

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

View File

@ -20,14 +20,14 @@ class Ci::SecretsController < Ci::BaseController
if result["id"]
render_ok
else
render_error(result["message"])
tip_exception(result["message"])
end
else
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
if result["id"]
render_ok
else
render_error(result["message"])
tip_exception(result["message"])
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
render_ok
else
render_error("参数名不能为空")
tip_exception("参数名不能为空")
end
rescue Exception => ex
render_ok
end
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
end

View File

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

View File

@ -0,0 +1,139 @@
#coding=utf-8
class ClaimsController < ApplicationController
# skip_before_action :verify_authenticity_token
protect_from_forgery with: :null_session
before_action :require_login, except: [:index]
before_action :set_issue
def index
@user_claimed = 0
@claims = @issue.claims.claim_includes.order("created_at desc")
@claims.each do |claim|
if claim.user_id == current_user.id
@user_claimed = 1
break
end
end
render file: 'app/views/claims/list.json.jbuilder'
end
def create
@claim = Claim.find_by_sql(["select id from claims where issue_id=? and user_id=?",params[:issue_id], current_user.id])
if @claim.present?
return normal_status(-1,"您已经声明过该易修")
end
ActiveRecord::Base.transaction do
@claim = Claim.new(parse_issue_params(params))
if @claim.save
@claims = @issue.claims.claim_includes.order("created_at desc")
@user_claimed = 1
journal_params = {
journalized_id: params[:issue_id],
journalized_type: "Issue",
user_id: current_user.id ,
notes: "新建声明: #{params[:claim_note]}",
}
journal = Journal.new(journal_params)
if journal.save
SendTemplateMessageJob.perform_later('IssueClaim', current_user.id, @issue&.id)
render file: 'app/views/claims/list.json.jbuilder'
else
normal_status(-1,"新建声明关联评论操作失败")
end
else
normal_status(-1,"新建声明操作失败")
end
end
end
def update
@claim = Claim.find_by_id(params[:claim_id])
if @claim.blank?
return normal_status(-1,"易修不存在")
end
if @claim.user_id != current_user.id
return normal_status(-1,"你不能更新别人的声明")
end
ActiveRecord::Base.transaction do
if @claim.update_attribute(:note,params[:claim_note])
@claims = @issue.claims.claim_includes.order("created_at desc")
@user_claimed = 1
journal_params = {
journalized_id: params[:issue_id],
journalized_type: "Issue",
user_id: current_user.id ,
notes: "更新声明: #{params[:claim_note]}",
}
journal = Journal.new(journal_params)
if journal.save
render file: 'app/views/claims/list.json.jbuilder'
else
normal_status(-1,"新建声明关联评论操作失败")
end
else
normal_status(-1,"声明更新操作失败")
end
end
end
def destroy
@claim = Claim.find_by_sql(["select id from claims where issue_id=? and user_id=?",params[:issue_id], current_user.id])
if @claim.blank?
normal_status(-1,"您未曾声明过该易修")
else
@claim = @claim[0]
# 判断current user是否是claimer
ActiveRecord::Base.transaction do
if @claim.destroy
@claims = @issue.claims.claim_includes.order("created_at desc")
@user_claimed = 0
journal_params = {
journalized_id: params[:issue_id],
journalized_type: "Issue",
user_id: current_user.id ,
notes: "取消声明",
}
journal = Journal.new(journal_params)
if journal.save
render file: 'app/views/claims/list.json.jbuilder'
else
normal_status(-1,"新建声明关联评论操作失败")
end
else
normal_status(-1,"取消声明操作失败")
end
end
end
end
private
def parse_issue_params(params)
{
issue_id: params[:issue_id],
user_id: current_user.id,
note: params[:claim_note],
}
end
def set_issue
@issue = Issue.find_by_id(params[:issue_id])
unless @issue.present?
normal_status(-1, "易修不存在")
end
end
end

View File

@ -0,0 +1,35 @@
class CommitLogsController < ApplicationController
def create
tip_exception "未认证" unless params[:token].to_s == "7917908927b6f1b792f2027a08a8b24a2de42c1692c2fd45da0dee5cf90a5af5"
ref = params[:ref]
user_name = params[:pusher][:login]
user_mail = params[:pusher][:email]
user = User.find_by(mail: user_mail)
user = User.find_by(login: user_name) if user.blank?
repository_id = params[:repository][:id]
repository_name = params[:repository][:name]
repository_full_name = params[:repository][:full_name]
owner_name = repository_full_name.split("/")[0]
owner = User.find_by(login: owner_name)
project = Project.where(identifier: repository_name).where(user_id: owner&.id)&.first
project = Project.where(identifier: repository_name).where(gpid: repository_id)&.first if project.blank?
# project.update_column(:updated_on, Time.now) if project.present?
params[:commits].each do |commit|
commit_id = commit[:id]
message = commit[:message]
CommitLog.create(user: user, project: project, repository_id: repository_id,
name: repository_name, full_name: repository_full_name,
ref: ref, commit_id: commit_id, message: message)
end
# c
if project.present?
if repository_full_name.to_s.include?("openkylin")
project.update_column(:updated_on, Time.now - rand(1..100).minutes)
else
project.update_column(:updated_on, Time.now)
end
end
end
end

View File

@ -6,9 +6,18 @@ class CompareController < ApplicationController
end
def show
load_compare_params
compare
@merge_status, @merge_message = get_merge_message
if params[:type] == "sha"
load_compare_params
@compare_result ||= gitea_compare(@base, @head)
else
load_compare_params
compare
@merge_status, @merge_message = get_merge_message
end
@page_size = page_size <= 0 ? 1 : page_size
@page_limit = page_limit <=0 ? 15 : page_limit
@page_offset = (@page_size -1) * @page_limit
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
end
private
@ -16,6 +25,7 @@ class CompareController < ApplicationController
if @base.blank? || @head.blank?
return -2, "请选择分支"
else
return -2, "目标仓库未开启合并请求PR功能" unless @project.has_menu_permission("pulls")
if @head.include?(":")
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
return -2, "请选择正确的仓库" unless fork_project.present?
@ -42,12 +52,22 @@ class CompareController < ApplicationController
end
def load_compare_params
@base = Addressable::URI.unescape(params[:base])
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
# @base = Addressable::URI.unescape(params[:base])
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
@head = params[:head].include?('.json') ? params[:head][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
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

View File

@ -0,0 +1,506 @@
class CompetitionInfosController < ApplicationController
include ApplicationHelper
before_action :find_competition, only: [:show, :edit, :update, :update_zone_or_sub, :enroll, :upload, :enroll_status,
:statistics, :enroll_list, :ranking_list, :enroll_update, :enroll_status_update, :apply_status_update,
:upload_enroll_template, :upload_apply_template, :enroll_template, :apply_template, :online_switch, :destroy]
before_action :require_admin, only: [:new, :edit, :create, :destroy]
before_action :check_competition_manager, only: [:update, :enroll_status_update, :online_switch, :enroll_list]
before_action :require_login, only: [:enroll, :enroll_update, :enroll_status_update, :upload, :upload_enroll_template]
def index
competition_infos = CompetitionInfo.order(sort_no: :desc)
competition_infos = competition_infos.where("competition_infos.title like ?", "%#{params[:name]}%") if params[:name].present?
competition_infos = competition_infos.joins(:watchers).where(watchers: { user_id: current_user.id }) if params[:category].to_s == "watched"
@competition_infos = paginate(competition_infos)
respond_to do |format|
format.html
format.json { render_ok(data: @competition_infos.as_json, count: competition_infos.count) }
end
end
def list
@competition_infos = CompetitionInfo.order(sort_no: :desc)
@competition_infos = @competition_infos.where(id: params[:ids].to_s.split(",")) if params[:ids].present?
end
def recommend
sort_direction = ["asc", "desc"].include?(params[:sort_direction].to_s) ? params[:sort_direction] : "desc"
sort_by = params[:sort_by] || "created_at"
competition_infos = CompetitionInfo.where(status: true)
competition_infos = competition_infos.where("title like ?", "%#{params[:name]}%") if params[:name].present?
@total_count = competition_infos.count
if sort_by.to_s == "hot"
competition_infos = competition_infos.select("competition_infos.*, (SELECT count(1) from competition_users where competition_users.competition_info_id = competition_infos.id ) as count").order("count #{sort_direction}")
elsif sort_by.to_s == "new"
sort_by = "created_at"
competition_infos = competition_infos.order("#{sort_by} #{params[:sort_direction]}")
else
competition_infos = competition_infos.order("#{sort_by} #{params[:sort_direction]}")
end
@competition_infos = paginate(competition_infos)
render_ok(data: @competition_infos.as_json, count: @total_count)
end
# GET /competition_infos/new
def new
@competition_info = CompetitionInfo.new
end
# GET /competition_infos/1/edit
def edit
respond_to do |format|
format.html
format.json { render_ok(data: @competition_info.as_json) }
end
end
# POST /competition_infos.json
def create
@competition_info = CompetitionInfo.new(competition_info_params)
@competition_info.admin_data = params[:admin_data] if params[:admin_data].present?
respond_to do |format|
if @competition_info.save
format.html { redirect_to competition_infos_path, notice: '创建成功.' }
format.json { render_ok(data: @competition_info.as_json) }
else
format.html { render :new }
format.json { render json: @competition_info.errors, status: -1 }
end
end
end
# PATCH/PUT /competition_infos/1.json
def update
# @competition_info = CompetitionInfo.find params[:id]
respond_to do |format|
@competition_info.admin_data = params[:admin_data] if params[:admin_data].present?
if @competition_info.update!(competition_info_params)
format.html { redirect_to competition_infos_path, notice: '更新成功.' }
format.json { render_ok(data: @competition_info.as_json) }
else
format.html { render :edit }
format.json { render json: @competition_info.errors, status: -1 }
end
end
end
def online_switch
if @competition_info.status
@competition_info.update_attributes!(status: false)
else
@competition_info.update_attributes!(status: true)
end
render_ok
end
def update_zone_or_sub
tip_exception "参数错误" if params[:new].blank? || params[:old].blank? || params[:type].blank?
if params[:type].to_s == "zone"
competition_users = CompetitionUser.where(competition_info: @competition_info.id).where(zone: params[:old].to_s)
competition_users.update_all(zone: params[:new].to_s)
elsif params[:type].to_s == "sub"
competition_users = CompetitionUser.where(competition_info: @competition_info.id).where(sub_competition: params[:old].to_s)
competition_users.update_all(sub_competition: params[:new].to_s)
end
render_ok
end
def enroll_list
competition_users = CompetitionUser.where(competition_info: @competition_info.id).order("updated_at desc")
zones = @competition_info.manager_zones(current_user)
if @competition_info.identifier == "qz2022"
if params[:zone].present?
competition_users = zones.include?(params[:zone].to_s) ? competition_users.where(zone: params[:zone].to_s) : competition_users.where(zone: [])
else
competition_users = current_user.admin? ? competition_users : competition_users.where(zone: zones)
end
if params[:sub_competition].present?
competition_users = competition_users.where(sub_competition: params[:sub_competition].to_s)
end
end
if params[:keyword].present?
competition_users = competition_users.where("competition_users.org_name LIKE :keyword OR competition_users.leader LIKE :keyword OR competition_users.phone LIKE :keyword", keyword: "%#{params[:keyword].to_s}%")
end
if params[:status].present?
competition_users = competition_users.where(status: params[:status].to_s.split(","))
end
if params[:apply_status].present?
competition_users = competition_users.where(ext3: params[:apply_status].to_s.split(","))
end
if params[:upload].to_s == "true"
# competition_users = competition_users.joins("join attachments on attachments.container_type='CompetitionUser' and attachments.container_id = competition_users.id")
competition_users = competition_users.where(status: 3)
end
if params[:sub_item].present?
competition_users = competition_users.where(sub_item: params[:sub_item])
end
@competition_users_count = competition_users.count
competition_users = competition_users.select("DISTINCT competition_users.*")
@competition_users = paginate(competition_users)
respond_to do |format|
format.json
# 导出功能
format.xlsx {
set_export_cookies
competition_users = params[:upload].to_s == "true" ? competition_users.where(status: [2, 3]) : competition_users.where(status: [1, 2, 3])
enroll_fields = @competition_info.enroll_fields
enroll_fields = enroll_fields.delete_if { |key, value| ["sub_item", "works_name", "works_url"].include?(value) } if params[:upload].to_s != "true"
@table_columns = enroll_fields.keys
@table_columns = @table_columns + %w(参赛报名表下载链接)
@table_columns = @table_columns + %w(作品下载链接) if params[:upload].to_s == "true" && !enroll_fields.values.include?("works_url")
@table_columns = @table_columns + %w(申请表下载链接) if params[:apply_status].present?
@table_columns = @table_columns + %w(bm审查下载链接) if @competition_info.identifier == "KXSYSJ-2024" && params[:upload].to_s == "true"
# 重排成员放最后
enroll_fields_values = enroll_fields.values - ["members_to_string"] + ["members_to_string"]
@export_infos = []
@export_infos_new = []
max_members = []
competition_users.each do |u|
info_array = []
file_array = []
file = Attachment.where_id_or_uuid(u.enroll_template_id).first
file_array = file_array + [file.blank? ? "" : "#{EduSetting.get('host_name')}/#{download_url(file)}"]
if params[:upload].to_s == "true" && !enroll_fields.values.include?("works_url")
file_array = file_array + [u.attachments.blank? ? "" : "#{EduSetting.get('host_name')}/#{download_url(u.attachments.first)}"]
end
if params[:apply_status].present?
file = Attachment.where_id_or_uuid(u.ext2).first
file_array = file_array + [file.blank? ? "" : "#{EduSetting.get('host_name')}/#{download_url(file)}"]
end
if @competition_info.identifier == "KXSYSJ-2024" && params[:upload].to_s == "true"
file = Attachment.where_id_or_uuid(u.bm_file_id).first
file_array = file_array + [file.blank? ? "" : "#{EduSetting.get('host_name')}/#{download_url(file)}"]
end
enroll_fields_values.each do |val|
if "members_to_string" == val.to_s
members = u.send("#{val}")
max_members.push(members.size)
info_array = info_array + file_array + members
else
info_array.push("#{u.send("#{val}")}")
end
end
@export_infos.push(info_array)
end
Rails.logger.info("######_______________1111########@export_infos: #{@export_infos}")
if max_members.present? && max_members.max > 1
max_members.max.times do |n|
@table_columns = @table_columns - ["成员"]
@table_columns.push("成员#{n + 1}")
end
total_col = enroll_fields.values.size + max_members.max.to_i
@export_infos.each do |info|
blank_str = []
(total_col - 1 - info.size).times do
blank_str.push("")
end
@export_infos_new.push(info + blank_str)
end
else
@table_columns = @table_columns - ["成员"] + ["成员"]
@export_infos_new = @export_infos
end
export_name = "竞赛报名列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
export_name = "竞赛作品列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}" if params[:upload].to_s == "true"
Rails.logger.info("######_______________########export_infos_new: #{@export_infos_new}")
render xlsx: "#{export_name.strip}", template: "competition_infos/enroll_list.xlsx.axlsx", locals: { table_columns: @table_columns, export_infos: @export_infos_new }
}
format.zip {
competition_users = params[:upload].to_s == "true" ? competition_users.where(status: [2, 3]) : competition_users.where(status: [1, 2, 3])
Rails.logger.info("######_______________########competition_users.size: #{competition_users.size}")
service = Competition::ZipWorkFileService.new(competition_users, "files")
send_file service.zip, filename: service.filename, type: 'application/zip'
}
end
end
def enroll_template
file_attr_name = params[:file].to_s == "bm_file_id" ? params[:file].to_s : "enroll_template_id"
competition_users = CompetitionUser.where(competition_info: @competition_info.id).order("updated_at desc")
competition_users = competition_users.where(status: [1, 2, 3])
competition_users = competition_users.where("competition_users.enroll_template_id is not null") if file_attr_name.to_s == "enroll_template_id"
competition_users = competition_users.where("competition_users.bm_file_id is not null") if file_attr_name.to_s == "bm_file_id"
zones = @competition_info.manager_zones(current_user)
if params[:zone].present?
competition_users = zones.include?(params[:zone].to_s) ? competition_users.where(zone: params[:zone].to_s) : competition_users.where(zone: [])
else
competition_users = current_user.admin? ? competition_users : competition_users.where(zone: zones)
end
if params[:sub_competition].present?
competition_users = competition_users.where(sub_competition: params[:sub_competition].to_s)
end
if params[:keyword].present?
competition_users = competition_users.where("competition_users.org_name LIKE :keyword OR competition_users.leader LIKE :keyword OR competition_users.phone LIKE :keyword", keyword: "%#{params[:keyword].to_s}%")
end
respond_to do |format|
format.json
format.zip {
Rails.logger.info("######_______________########competition_users.size: #{competition_users.size}")
service = Competition::ZipEnrollTemplateService.new(competition_users, "files", file_attr_name)
send_file service.zip, filename: service.filename, type: 'application/zip'
}
end
end
def apply_template
competition_users = CompetitionUser.where(competition_info: @competition_info.id).order("updated_at desc")
competition_users = competition_users.where(status: [1, 2, 3]).where("competition_users.ext2 is not null")
zones = @competition_info.manager_zones(current_user)
if params[:zone].present?
competition_users = zones.include?(params[:zone].to_s) ? competition_users.where(zone: params[:zone].to_s) : competition_users.where(zone: [])
else
competition_users = current_user.admin? ? competition_users : competition_users.where(zone: zones)
end
if params[:sub_competition].present?
competition_users = competition_users.where(sub_competition: params[:sub_competition].to_s)
end
if params[:keyword].present?
competition_users = competition_users.where("competition_users.org_name LIKE :keyword OR competition_users.leader LIKE :keyword OR competition_users.phone LIKE :keyword", keyword: "%#{params[:keyword].to_s}%")
end
respond_to do |format|
format.json
format.zip {
Rails.logger.info("######_______________########competition_users.size: #{competition_users.size}")
service = Competition::ZipApplyTemplateService.new(competition_users, "files")
send_file service.zip, filename: service.filename, type: 'application/zip'
}
end
end
def show
@competition_info.increment!(:visits)
end
def enroll_status_update
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: params[:user_id])
tip_exception "未找到该报名用户" if competition_user.blank?
tip_exception "状态参数错误" unless ['0', '1', '2'].include?(params[:status].to_s)
old_status = competition_user.status
stage = competition_user.ext5
# 作品驳回时得分清0
if old_status.to_i == 3 && params[:status].to_i ==2
stage_score = competition_user.competition_user_scores.find_by(stage: stage.to_i)
stage_score.update_attributes!(score: 0, last_score: 0) if stage_score.present?
competition_user.update_attributes!(score: 0)
cache_key = "limit_forbid_control:#{@competition_info.identifier}:competition_api_score:#{competition_user.id}-#{stage}"
Rails.cache.delete(cache_key)
api_score_control = LimitForbidControl::CompetitionApiScore.new(@competition_user&.id)
api_score_control.clear
end
competition_user.update_attributes!(status: params[:status].to_i)
render_ok
end
def apply_status_update
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: params[:user_id])
tip_exception "未找到该报名用户" if competition_user.blank?
tip_exception "状态参数错误" unless ['0', '1', '2'].include?(params[:status].to_s)
competition_user.update_attributes!(ext3: params[:status].to_i)
render_ok
end
def enroll
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
tip_exception "您已经报名!" if competition_user.present?
competition_user = CompetitionUser.new(enroll_params)
competition_user.competition_info = @competition_info
competition_user.user = current_user
competition_user.members = params[:members]
competition_user.status = 1
competition_user.save
render_ok
end
def enroll_update
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
tip_exception "未报名,请先报名" if competition_user.blank?
competition_user.update_attributes!(enroll_params)
competition_user.members = params[:members]
competition_user.status = 1
competition_user.save
render_ok
end
def upload_enroll_template
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
tip_exception "未报名,请先报名" if competition_user.blank?
tip_exception "附件参数enroll_template_id不能为空" if params[:enroll_template_id].blank?
competition_user.update_attributes!(enroll_template_id: params[:enroll_template_id])
render_ok
end
def enroll_status
@competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
# first_round_ids = CompetitionUser.where(competition_info_id: @competition_info.id).where("score > 26").pluck(:id)
# 第一轮赛合格人员
first_round_ids = [541, 543, 544, 545, 546, 548, 550, 551, 552, 554, 555, 556, 558, 560, 563, 565, 567, 576, 579, 581]
@second_round = first_round_ids.include?(@competition_user&.id)
if @competition_info.identifier.to_s == "dmsc" || @competition_info.identifier.to_s == "zswd"
cache_key = "limit_forbid_control:#{@competition_info.identifier}:competition_api_score:#{@competition_user&.id}-#{@stage}"
@count_control = Rails.cache.read(cache_key)
else
api_score_control = LimitForbidControl::CompetitionApiScore.new(@competition_user&.id)
@count_control = api_score_control.forbid?
end
end
def upload
@stage = params[:stage] || params[:ext5]
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
tip_exception "未报名,请先报名" if competition_user.blank?
# tip_exception "附件参数attachment_ids不能为空" if params[:attachment_ids].blank?
# 第一轮赛合格人员
# first_round_ids = CompetitionUser.where(competition_info_id: @competition_info.id).where("score > 26").pluck(:id)
first_round_ids = [541, 543, 544, 545, 546, 548, 550, 551, 552, 554, 555, 556, 558, 560, 563, 565, 567, 576, 579, 581]
tip_exception "您不在复赛名单中,不能参加复赛!" if @competition_info.identifier == "zstp2022" && !first_round_ids.include?(competition_user&.id)
if @competition_info.identifier.to_s == "dmsc" || @competition_info.identifier.to_s == "zswd"
cache_key = "limit_forbid_control:#{@competition_info.identifier}:competition_api_score:#{competition_user.id}-#{@stage}"
allow_count = 1
count_control = Rails.cache.read(cache_key)
if count_control.present? && count_control.to_i >= allow_count
return normal_status(-1, "打分受限当前竞赛仅支持3天打一次榜")
else
Rails.cache.write(cache_key, count_control.to_i + 1, expires_in: 5.minutes)
end
else
api_score_control = LimitForbidControl::CompetitionApiScore.new(competition_user.id)
return normal_status(-1, "今日打分已达上限,请明日再试") if api_score_control.forbid?
api_score_control.increment!
end
competition_user.bm_file_id = params[:bm_file_id] if params[:bm_file_id].present?
# tip_exception "您已经提交作品!" if competition_user.present? && competition_user.attachments.present?
if params[:attachment_ids].present?
competition_user.attachments.update_all(container_id: nil, container_type: nil)
params[:attachment_ids].each do |id|
attachment = Attachment.where_id_or_uuid(id).first
unless attachment.blank?
attachment.container = competition_user
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
forge_url = Rails.application.config_for(:configuration)['platform_url'] || EduSetting.get("main_site")
filePath = "#{forge_url}/api/attachments/#{attachment.id}"
if EduSetting.get("competition_ccks_ids").to_s.split(",").include?(@competition_info.identifier.to_s)
api_url = "/script/ccks"
CompetitionAutoScoreNewJob.perform_later(competition_user.id, api_url, filePath)
elsif EduSetting.get("competition_zstp2023_ids").to_s.split(",").include?(@competition_info.identifier.to_s)
api_url = "/script/ccks2023"
CompetitionAutoScoreNewJob.perform_later(competition_user.id, api_url, filePath)
elsif @competition_info.identifier.to_s == "dmsc"
api_url = "/script/qyCode"
CompetitionAutoScoreNewJob.perform_later(competition_user.id, api_url, filePath, @stage)
elsif @competition_info.identifier.to_s == "zswd"
api_url = "/script/qyMilitary"
CompetitionAutoScoreNewJob.perform_later(competition_user.id, api_url, filePath, @stage)
elsif @competition_info.identifier.to_s == "mmlss"
api_url = "/script/mmlssEval"
CompetitionAutoScoreNewJob.perform_later(competition_user.id, api_url, filePath, @stage)
end
end
end
competition_user.sub_item = params[:sub_item] if params[:sub_item].present?
competition_user.works_name = params[:works_name] if params[:works_name].present?
competition_user.works_url = params[:works_url] if params[:works_url].present?
if @stage.present?
competition_user.update_attributes!(api_status: 1, status: 3, ext5: @stage)
else
competition_user.update_attributes!(api_status: 1, status: 3)
end
render_ok
end
# 自动打分接口
def auto_score
filePath = params[:filePath].to_s
team_id = params[:team_id].to_s
api_url = params[:api_url].to_s
tip_exception("参数错误") if filePath.blank? || team_id.blank? || api_url.blank?
competition_team = CompetitionTeam.find team_id
competition_team.update_attributes!(api_status: 1)
api_score_control = LimitForbidControl::CompetitionApiScore.new(team_id)
return normal_status(-1, "今日打分已达上限,请明日再试") if api_score_control.forbid?
api_score_control.increment!
CompetitionAutoScoreJob.perform_later(team_id, api_url, filePath)
render_ok
end
# 赛事风采
def statistics
@competition_users = @competition_info.competition_users.where(status: [1, 2, 3])
@upload_count = @competition_users.joins("join attachments on attachments.container_type='CompetitionUser' and attachments.container_id = competition_users.id").count
end
# 排名
def ranking_list
@stage = params[:stage] || params[:ext5]
if @stage.present?
competition_users = @competition_info.competition_users.joins(:competition_user_scores)
.where("competition_users.status = 3")
.where("competition_user_scores.stage = ? ", @stage.to_i)
.where("competition_user_scores.score > 0")
.order("competition_user_scores.score desc, competition_user_scores.created_at asc")
@rank_num = competition_users.pluck(:id)
if params[:keyword].present?
competition_users = competition_users.where("competition_users.org_name LIKE :keyword OR competition_users.leader LIKE :keyword OR competition_users.ext4 LIKE :keyword ", keyword: "%#{params[:keyword].to_s}%")
end
@competition_users_count = competition_users.count
@competition_users = paginate(competition_users)
else
competition_users = @competition_info.competition_users.where("competition_users.status = 3").where("score > 0").order("score desc, created_at asc")
@rank_num = competition_users.pluck(:id)
if params[:keyword].present?
competition_users = competition_users.where("competition_users.org_name LIKE :keyword OR competition_users.leader LIKE :keyword OR competition_users.ext4 LIKE :keyword ", keyword: "%#{params[:keyword].to_s}%")
end
@competition_users_count = competition_users.count
@competition_users = paginate(competition_users)
end
end
def destroy
if @competition_info.destroy!
flash[:success] = '删除成功'
else
flash[:danger] = '删除失败'
end
redirect_to "api/competition_infos"
end
private
def enroll_params
params.permit(:org_name, :org_job, :org_rank, :leader, :zone, :sub_competition, :phone,
:subject_source_type, :subject_source_name, :enroll_template_id, :mail, :ext1, :ext2, :ext3, :ext4, :ext5,
:bm_file_id, :teacher_name, :teacher_dept, :teacher_email, :teacher_phone, :teacher_professional)
end
def competition_info_params
params.require(:competition_info).permit(:title, :zones, :zones_local, :sub_competitions, :identifier, :content,
:video_url, :is_local, :manager_ids, :upload_date, :enroll_date, :guide, :about_us,
:banner_url, :enroll_template, :enroll_columns, :applet_banner_url, :start_at,:start_upload_date, :sort_no,
:ext1, :ext2, :ext3, :ext4, :ext5)
end
def find_competition
if CompetitionInfo.where(:identifier => params[:id]).exists?
@competition_info = CompetitionInfo.where(:identifier => params[:id]).first
else
@competition_info = CompetitionInfo.find(params[:id])
end
end
def manager_competition_zones
if current_user.admin?
@competition_info.competition_zones
else
@competition_info.manager_zones(current_user)
end
end
def check_competition_manager
unless @competition_info.is_manager?(current_user)
tip_exception(403, "你没有权限操作!")
end
end
end

View File

@ -0,0 +1,95 @@
class CompetitionNoticesController < ApplicationController
include ApplicationHelper
before_action :find_competition, only: [:show, :index, :update, :destroy, :create]
# before_action :require_admin, only: [:show, :index, :update, :destroy, :create]
before_action :manager_competition_zones, only: [:enroll_list]
def index
competition_notices = CompetitionNotice.where(competition_info_id: @competition_info.id).order("created_at desc")
if current_user.logged?
competition_notices.each do |notice|
CompetitionNoticeUser.find_or_create_by!(user_id: current_user.id, competition_notice_id: notice.id)
end
end
@competition_notices_count = competition_notices.size
@competition_notices = paginate(competition_notices)
end
def create
@competition_notice = CompetitionNotice.new(competition_notice_params)
@competition_notice.user = current_user
@competition_notice.competition_info = @competition_info
@competition_notice.save
if params[:attachment_ids].present?
params[:attachment_ids].each do |id|
attachment = Attachment.find_by_id(id)
unless attachment.blank?
attachment.container = @competition_notice
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
render_ok
end
# PATCH/PUT /competition_infos/1.json
def update
@competition_notice = CompetitionNotice.find params[:id]
@competition_notice.update(competition_notice_params)
@competition_notice.attachments.update_all(container_id: nil, container_type: nil)
if params[:attachment_ids].present?
params[:attachment_ids].each do |id|
attachment = Attachment.find_by_id(id)
unless attachment.blank?
attachment.container = @competition_notice
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
render_ok
end
def show
@competition_notice = CompetitionNotice.find params[:id]
end
def upload
competition_user = CompetitionUser.find_by(competition_info: @competition_notice.id, user_id: current_user.id)
tip_exception "未报名,请先报名" if competition_user.blank?
tip_exception "附件参数attachment_ids不能为空" if params[:attachment_ids].blank?
# tip_exception "您已经提交作品!" if competition_user.present? && competition_user.attachments.present?
competition_user.attachments.update_all(container_id: nil, container_type: nil)
render_ok
end
def destroy
@competition_notice = CompetitionNotice.find params[:id]
@competition_notice.destroy
render_ok
end
private
def competition_notice_params
params.permit(:title, :content)
end
def find_competition
if CompetitionInfo.where(:identifier => params[:competition_info_id]).exists?
@competition_info = CompetitionInfo.where(:identifier => params[:competition_info_id]).first
else
@competition_info = CompetitionInfo.find(params[:competition_info_id])
end
end
def manager_competition_zones
if current_user.admin?
end
end
end

View File

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

View File

@ -0,0 +1,20 @@
module Api::ProjectHelper
extend ActiveSupport::Concern
def load_project
namespace = params[:owner]
repo = params[:repo]
@project, @owner = Project.find_with_namespace(namespace, repo)
if @project
logger.info "###########project founded"
@project
else
logger.info "###########project not found"
@project = nil
render_not_found and return
end
@project
end
end

View File

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

View File

@ -0,0 +1,28 @@
module Api::UserHelper
extend ActiveSupport::Concern
def load_observe_user
username = params[:owner]
@observe_user = User.find_by(login: username)
if @observe_user
logger.info "###########observe_user not founded"
@observe_user
else
logger.info "###########observe_user not found"
@observe_user = nil
render_not_found and return
end
@observe_user
end
# 是否具有查看用户或编辑用户的权限
def check_auth_for_observe_user
return render_forbidden unless current_user.admin? || @observe_user.id == current_user.id
end
def strip(str)
str.to_s.strip.presence
end
end

View File

@ -15,7 +15,7 @@ module Base::PaginateHelper
end
def per_page
params[:per_page].to_i <= 0 || params[:per_page].to_i > 100 ? 20 : params[:per_page].to_i
params[:per_page].to_i <= 0 || params[:per_page].to_i > 200 ? 10 : params[:per_page].to_i
end
alias_method :limit, :per_page

View File

@ -160,9 +160,9 @@ module Ci::CloudAccountManageable
state = SecureRandom.hex(8)
# 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
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
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}"
# redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
# clientId = client_id(oauth)
grant_url = "#{@cloud_account.drone_url}/login"
logger.info "[gitea] grant_url: #{grant_url}"
conn = Faraday.new(url: grant_url) do |req|
@ -188,6 +188,7 @@ module Ci::CloudAccountManageable
response = conn.get
logger.info "[drone] response headers: #{response.headers}"
# true
response.headers['location'].include?('error') ? false : true
end

View File

@ -8,6 +8,9 @@ module LaboratoryHelper
helper_method :default_setting
helper_method :default_yun_session
helper_method :default_course_links
helper_method :manager_main_site_url
helper_method :main_web_site_url
helper_method :current_main_site_url
end
def current_laboratory
@ -32,18 +35,30 @@ module LaboratoryHelper
end
def default_course_links
# my_projects: "/users/#{current_user.try(:login)}/projects",
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
{
new_syllabuses: "https://www.trustie.net/syllabuses/new",
new_course: "https://www.trustie.net/courses/new",
edit_account: "https://www.trustie.net/my/account",
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
my_projects: "/users/#{current_user.try(:login)}/projects",
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
default_url: Rails.application.config_for(:configuration)['platform_url'],
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
register_url: "https://www.trustie.net/login?login=false"
# new_syllabuses: "https://www.trustie.net/syllabuses/new",
# new_course: "https://www.trustie.net/courses/new",
# edit_account: "https://www.trustie.net/my/account",
# my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
# my_projects: "/users/#{current_user.try(:login)}/projects",
# my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
# default_url: "https://www.trustie.net/",
tiding_url: "#{main_web_site_url}/users/#{current_user.try(:login)}/user_tidings",
register_url: "#{current_main_site_url}/register"
}
end
def manager_main_site_url
url = EduSetting.get('managements_url') || "#{current_main_site_url}/managements"
{name: '管理', link: "#{url}"}
end
def main_web_site_url
EduSetting.get('host_main_site')
end
def current_main_site_url
EduSetting.get('host_name')
end
end

View File

@ -6,14 +6,16 @@ module LoginHelper
end
def autologin_cookie_name
edu_setting('autologin_cookie_name').presence || 'autologin'
edu_setting('autologin_cookie_name').presence || 'autologin_forge_military'
end
def autologin_action
EduSetting.get('autologin_action').presence || 'autologin'
end
def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin")
sync_user_token_to_trustie(user.login, token.value)
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
Rails.logger.info("set_cookie_user_id is=======> #{user.id}")
token = Token.get_or_create_permanent_login_token(user, autologin_action)
cookie_options = {
:value => token.value,
:expires => 1.month.from_now,
@ -108,10 +110,15 @@ module LoginHelper
def sync_pwd_to_gitea!(user, hash={})
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))
if interactor.success?
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
user.update_column(:is_sync_pwd, true)
true
else
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"

View File

@ -1,30 +1,66 @@
module RegisterHelper
extend ActiveSupport::Concern
def autologin_register(username, email, password, platform= 'forge')
def autologin_register(username, email, password, platform = 'forge', phone = nil, nickname =nil, need_edit_info = false)
result = {message: nil, user: nil}
email = email.blank? ? "#{username}@example.org" : email
user = User.new(admin: false, login: username, mail: email, type: "User")
user.password = password
user.platform = platform
user.activate
user.phone = phone if phone.present?
user.nickname = nickname if nickname.present?
if need_edit_info
user.need_edit_info
else
user.activate
end
return unless user.valid?
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
result ={}
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.call(username, password)
user.gitea_token = result['sha1']
user.gitea_uid = gitea_user[:body]['id']
user.gitea_uid = gitea_user[:body]['id'] if gitea_user[:body].present?
if user.save!
UserExtension.create!(user_id: user.id)
UserExtension.create!(user_id: user.id) if user.user_extension.blank?
result[:user] = {id: user.id, token: user.gitea_token}
end
else
result[:message] = interactor.error
result[:message] = interactor.result[:message]
end
result
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

View File

@ -1,31 +1,31 @@
module RenderHelper
def render_ok(data = {})
render json: { status: 0, message: 'success' }.merge(data)
end
def render_error(status = -1, message = '')
render json: { status: status, message: message }
end
def render_not_acceptable(message = '请求已拒绝')
render json: { status: 406, message: message }
end
def render_not_found(message = I18n.t('error.record_not_found'))
render json: { status: 404, message: message }
# render status: 404, json: { errors: errors }
end
def render_forbidden(message = I18n.t('error.forbidden'))
render json: { status: 403, message: message }
# render status: 403, json: { errors: errors }
end
def render_unauthorized(message = I18n.t('error.unauthorized'))
render json: { status: 401, message: message }
end
def render_result(status=1, message='success')
render json: { status: status, message: message }
end
end
module RenderHelper
def render_ok(data = {})
render json: { status: 0, message: 'success' }.merge(data)
end
def render_error(message = '', status = -1)
render json: { status: status, message: message }
end
def render_not_acceptable(message = '请求已拒绝')
render json: { status: 406, message: message }
end
def render_not_found(message = I18n.t('error.record_not_found'))
render json: { status: 404, message: message }
# render status: 404, json: { errors: errors }
end
def render_forbidden(message = I18n.t('error.forbidden'))
render json: { status: 403, message: message }
# render status: 403, json: { errors: errors }
end
def render_unauthorized(message = I18n.t('error.unauthorized'))
render json: { status: 401, message: message }
end
def render_result(status=1, message='success')
render json: { status: status, message: message }
end
end

View File

@ -5,7 +5,17 @@ module Repository::LanguagesPercentagable
result = Gitea::Repository::Languages::ListService.call(@owner.login,
@repository.identifier, current_user&.gitea_token)
result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
@transform_language = result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
update_project_language(@transform_language) unless @transform_language.nil?
@transform_language
end
def update_project_language(language)
return if @project.project_language.present?
db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
@project.update_column(:project_language_id, db_language.id)
rescue
return
end
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}

View File

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

View File

@ -0,0 +1,6 @@
class Home::CompetitionsController < ApplicationController
def index
@competitions = Competition.active.where(show_index: true).order(sort_no: :desc).limit(3)
end
end

View File

@ -0,0 +1,8 @@
class Home::PlatformCommunicatesController < ApplicationController
def index
location = params[:location] || "pc"
scope = PlatformCommunicate.where(status:true).where(location: location).order(order_index: :desc)
@communicates = kaminari_paginate(scope)
end
end

View File

@ -0,0 +1,7 @@
class Home::PlatformPeopleController < ApplicationController
def index
scope = PlatformPerson.order(created_at: :desc)
@people = kaminari_paginate(scope)
end
end

View File

@ -0,0 +1,10 @@
class Home::PlatformStatisticsController < ApplicationController
def index
@platform_statistic = PlatformStatistic.data
@project_statistic = ProjectStatistic.data
@platform_statistic.increment!(:visits)
@tasks_count = ActiveRecord::Base.connection.exec_query("SELECT COUNT(1) FROM tasks b LEFT JOIN task_details a ON a.task_id = b.id WHERE b.is_delete = 0 AND b.published = 1 AND status IN (3, 4, 5, 6, 7, 8)").rows[0][0]
@memos_count = ActiveRecord::Base.connection.exec_query("SELECT COUNT(*) FROM memos").rows[0][0]
end
end

View File

@ -0,0 +1,7 @@
class HomeController < ApplicationController
def to_competitions
competition_url = Rails.application.config_for(:configuration)['web_site'] || EduSetting.get('host_main_site')
redirect_to "#{competition_url}/competitions/#{params[:identifier].to_s}/home"
end
end

View File

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

View File

@ -15,6 +15,7 @@ class IssuesController < ApplicationController
include TagChosenHelper
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?)
issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member
@ -23,13 +24,13 @@ class IssuesController < ApplicationController
@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(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)
@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")
@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)
respond_to do |format|
@ -108,7 +109,7 @@ class IssuesController < ApplicationController
def create
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)
if @issue.save!
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
@ -125,10 +126,17 @@ class IssuesController < ApplicationController
end
end
if params[:issue_tag_ids].present?
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
return normal_status(-1, "最多只能创建一个标记。")
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
if params[:assigned_to_id].present?
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
container_id: @issue.id, container_type: 'Issue',
@ -142,11 +150,13 @@ class IssuesController < ApplicationController
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: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
render json: {status: 0, message: "创建成", id: @issue.id}
render json: {status: 0, message: "创建成", id: @issue.id}
else
normal_status(-1, "创建失败")
end
@ -157,19 +167,27 @@ class IssuesController < ApplicationController
def edit
# @issue_chosen = issue_left_chosen(@project, @issue.id)
@cannot_edit_tags = @issue.issue_type=="2" && @issue.status_id == 5 #悬赏任务已解决且关闭的状态下,不能修改
@issue_attachments = @issue.attachments
end
def update
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
return normal_status(-1, "您没有权限修改token") if @issue.will_save_change_to_token? && @issue.user_id != current_user&.id
last_token = @issue.token
last_status_id = @issue.status_id
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
end
if params[:issue_tag_ids].present?
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
return normal_status(-1, "最多只能创建一个标记。")
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|
next if tag == [""]
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
else
return normal_status(-1, "请输入正确的标记。")
end
end
issue_files = params[:attachment_ids]
@ -188,6 +206,7 @@ class IssuesController < ApplicationController
end
end
end
# if params[:issue_tag_ids].present?
# issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
@ -207,7 +226,7 @@ class IssuesController < ApplicationController
normal_status(-1, "不允许修改为关闭状态")
else
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&.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?
@ -231,7 +250,7 @@ class IssuesController < ApplicationController
end
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
@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.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时才给token
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
@ -256,6 +275,8 @@ class IssuesController < ApplicationController
else
normal_status(-1, "更新失败")
end
end
rescue Exception => exception
puts exception.message
@ -289,20 +310,17 @@ class IssuesController < ApplicationController
if issue_type == "2" && status_id != 5
post_to_chain("add", token, login)
end
normal_status(0, "删除成功")
return normal_status(0, "删除成功")
else
normal_status(-1, "删除失败")
return normal_status(-1, "删除失败")
end
rescue => exception
Rails.logger.info("#########_______exception.message_________##########{exception.message}")
normal_status(-1, "删除失败")
else
end
end
def clean
#批量删除,暂时只能删除未悬赏的
issue_ids = params[:ids]
issues = Issue.where(id: issue_ids, issue_type: "1")
if issues.present?
@ -473,7 +491,8 @@ class IssuesController < ApplicationController
end
def operate_issue_permission
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
@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
def export_issues(issues)

View File

@ -23,6 +23,7 @@ class JournalsController < ApplicationController
normal_status(-1, "评论内容不能为空")
else
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 = {
journalized_id: @issue.id ,
journalized_type: "Issue",
@ -53,6 +54,9 @@ class JournalsController < ApplicationController
end
end
end
rescue Exception => exception
puts exception.message
normal_status(-1, exception.message)
end
def destroy
@ -70,16 +74,19 @@ class JournalsController < ApplicationController
def update
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)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")
normal_status(-1, @journal.errors.messages.values[0][0])
end
else
normal_status(-1, "评论的内容不能为空")
end
rescue Exception => exception
puts exception.message
normal_status(-1, exception.message)
end
def get_children_journals

View File

@ -4,6 +4,8 @@ class MainController < ApplicationController
skip_before_action :user_setup
skip_before_action :setup_laboratory
#before_action :sso_login, only: [:index]
def first_stamp
render :json => { status: 0, message: Time.now.to_i }
end
@ -29,4 +31,110 @@ class MainController < ApplicationController
end
end
def sso_login
return if current_user.logged?
return unless EduSetting.get("509_SSO_LOGIN_OPEN").to_s == "true"
user_token = params['access_token']
Rails.logger.info "=== params.access_token user_token ====#{user_token}"
app_domain = EduSetting.get("509_APP_DOMAIN")
access_token = get_509_sso_token
if access_token.present?
api_user_url ="#{app_domain}/api/sso/user?access_token=#{user_token}"
user_params = url_http_post(api_user_url, {})
if user_params['rsltcode'].to_s == "0"
login = user_params['account']
login = login[0..20] if login.size > 29
phone = user_params['mobile']
mail = user_params['useremail']
mail = "#{login}@example.org" if mail.blank?
nickname = user_params['fullname']
orgName = user_params['orgName']
user = phone.present? ? User.find_by(phone: phone) : nil
user = User.where("login = ? or phone = ? or mail = ? ", login.presence, phone.presence, mail.presence).first if user.nil?
if user.blank?
Rails.logger.info "=== 创建新用户 ===="
user = User.new(type: "User")
user.login = login
user.phone = phone
user.mail = mail
user.nickname = nickname if nickname.present?
user.company_name = orgName if orgName.present?
user.user_type = "6"
user.professional_field = "12"
password = "a12345678"
user.password = password
# gitea用户注册, email, username, password
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.call(user.login, password)
user.gitea_token = result['sha1']
user.gitea_uid = gitea_user[:body]['id']
if user.save!
UserExtension.create!(user_id: user.id)
end
else
tip_exception(-1, interactor.result[:message])
end
else
user.update!(phone: phone) if user.phone.blank? && phone.present? && User.find_by(phone: phone).blank?
user.update!(nickname: nickname) if user.nickname.blank? && nickname.present?
end
successful_authentication(user)
else
Rails.logger.error("#############api_url:#{api_user_url},code: #{user_params['rsltcode']}, msg: #{user_params['rsltcode']}")
end
end
end
def get_509_sso_token
app_id = EduSetting.get("509_APP_ID")
app_secret = EduSetting.get("509_APP_SECRET")
app_domain = EduSetting.get("509_APP_DOMAIN")
api_token_url ="#{app_domain}/api/uaa/oauth/token?client_id=#{app_id}&client_secret=#{app_secret}&grant_type=client_credentials"
# api_token_url ="#{app_domain}/oauth/token?client_id=#{app_id}&client_secret=#{app_secret}&grant_type=client_credentials"
access_token = Rails.cache.read("509_APP/access_token")
if access_token.present?
api_check_token_url = "#{app_domain}/api/sso/valtoken/#{access_token}"
# api_check_token_url = "#{app_domain}/api/sso/user?access_token=#{access_token}"
result = url_http_post(api_check_token_url, {})
if result['rsltcode'].to_s != "0"
data = url_http_post(api_token_url, {})
access_token = data['access_token']
Rails.cache.write("509_APP/access_token", access_token, expires_in: 5.days)
end
else
data = url_http_post(api_token_url, {})
access_token = data['access_token']
Rails.cache.write("509_APP/access_token", access_token, expires_in: 5.days)
end
access_token
end
def url_http_post(api_url,params)
Rails.logger.info "api_url==#{api_url}"
uri = URI.parse(api_url)
http = Net::HTTP.new uri.host, uri.port
http.open_timeout = 60
http.read_timeout = 60
if uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
end
begin
request = Net::HTTP::Post.new(uri)
request.set_form_data(params) if params.present?
request['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'
response = http.start { |http| http.request(request) }
Rails.logger.info "api response.body==#{response.body}"
JSON.parse response.body
rescue =>err
Rails.logger.error("#############api_url:#{api_url},error:#{err.message.size}")
# Rails.logger.error("#############api_url:#{api_url},error:#{err.message}")
return {}
end
end
end

View File

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

View File

@ -3,7 +3,7 @@ class MembersController < ApplicationController
before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role]
before_action :check_user_profile_completed, only: [:create]
before_action :operate!, except: %i[index]
before_action :operate!
before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role]
@ -26,6 +26,9 @@ class MembersController < ApplicationController
@total_count = scope.size
@members = paginate(scope)
if @project.owner.is_a?(Organization) && (params[:page].to_i == 1 || params[:page].blank?) && !@project.members.exists?(user_id: current_user.id)
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
end
end
def remove
@ -61,11 +64,14 @@ class MembersController < ApplicationController
end
def check_member_exists!
return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
return render_error("#{@user&.nickname}已经是项目成员") if member_exists? || (params[:user_id].to_i == current_user.id && @current_user_header_team.present?)
end
def check_member_not_exists!
return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
return render_error("用户为组织成员,请到组织下操作!") if (params[:user_id].to_i == current_user.id && @current_user_header_team.present?) && !member_exists?
return render_error("#{@user&.nickname}还不是项目成员") unless member_exists?
end
def check_user_profile_completed

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

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

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