forked from Trustie/forgeplus
Compare commits
573 Commits
master
...
dev_educod
Author | SHA1 | Date |
---|---|---|
|
0c85516a56 | |
|
f4183a42cf | |
|
44dea80793 | |
|
52f386802d | |
|
0656827d86 | |
|
2280bf02ac | |
|
d0cb7eb269 | |
|
7f5e00b516 | |
|
f2a0a22469 | |
|
489385ffae | |
|
b7c8649507 | |
|
4fe7196d40 | |
|
7a7b93c4af | |
|
202d091ff5 | |
|
3f1ffcdb34 | |
|
bdd9885a41 | |
|
3285c89698 | |
|
6afd275814 | |
|
0fb519c963 | |
|
0840f632aa | |
|
59b72f9122 | |
|
1201607a39 | |
|
1ce6070138 | |
|
cb9230a1a5 | |
|
a76079ee8e | |
|
9bd43d80c6 | |
|
f50c9eb9d2 | |
|
89db4e35ac | |
|
9cd4c876ff | |
|
ac1a4cc7b7 | |
|
c475760518 | |
|
88ef03d5d7 | |
|
3470fa262c | |
|
0fa3361e69 | |
|
2191102fa8 | |
|
033d36406e | |
|
6e62aecbbc | |
|
fb44955a5f | |
|
6454c375ed | |
|
534fdec9f2 | |
|
dfa0f1161d | |
|
bc6f5cec4d | |
|
ee27c90205 | |
|
534ee80523 | |
|
daf7514afe | |
|
4b1f1c697e | |
|
77c7acd582 | |
|
025a6a53e9 | |
|
6b846b10bb | |
|
763d7b499e | |
|
9b39446dfb | |
|
c6e77ac7ee | |
|
f5cdb6f02d | |
|
f7ca03db81 | |
|
8da8b021f6 | |
|
70ba78a9b5 | |
|
6191ddd233 | |
|
35cf298f5d | |
|
ee5d959404 | |
|
7f47cd8d46 | |
|
06c0ac65bf | |
|
8f8dab10c3 | |
|
a6923bf7ed | |
![]() |
667dca0553 | |
![]() |
f23f02cb80 | |
|
38a8191b74 | |
|
e183f48c02 | |
![]() |
a1731f91a9 | |
|
ea7cf1cd1f | |
|
255b615327 | |
|
64c6f69f56 | |
|
49abadfa3f | |
|
4cde7c374e | |
|
b56930b9ab | |
|
f98886b3a0 | |
|
30572aa41c | |
|
ef83697cb8 | |
|
570f664c27 | |
|
e24921bba3 | |
|
e4d62c5335 | |
|
6d9cf8aad2 | |
|
e3179dfd6e | |
|
7817487ab7 | |
|
83b46fcb50 | |
![]() |
7cc9d207b6 | |
![]() |
abfb62f342 | |
![]() |
ccbbab0741 | |
|
3e5c1da2c5 | |
|
07aefa79eb | |
|
423d5a9316 | |
|
9664ca001e | |
|
e15809c186 | |
|
7d4c0df691 | |
|
e72dfa4973 | |
|
84a8339a04 | |
|
3d5b2e76d7 | |
|
8b14ee3c72 | |
|
3f7366fbcd | |
|
cfdbc5a682 | |
|
9b880e3209 | |
|
c2ef23b746 | |
|
8a33ea6707 | |
|
9ee4c85b7c | |
|
e9b23d6577 | |
|
64d9c334ce | |
|
cad7e24299 | |
|
3b15dd84fc | |
|
58a43a8b80 | |
|
e25231738a | |
|
35965f542a | |
|
fa48e3f5ca | |
|
13e2738fb5 | |
|
30437d828c | |
|
dcc7ab6738 | |
|
57a7a17f73 | |
|
5196f33f24 | |
![]() |
b3cbed2963 | |
![]() |
dd1af6712c | |
|
8807be6e4d | |
|
8d41c27044 | |
|
53fe554d1e | |
![]() |
4e02dbe06b | |
![]() |
620ddff9bb | |
|
630a7aadeb | |
|
6383384287 | |
|
83f1263f85 | |
|
9c11cd79e8 | |
|
a7384bc1c3 | |
|
55170c7693 | |
|
2cde13eabb | |
|
d68e7f38a3 | |
|
649d9c4ea6 | |
![]() |
fce8166ba7 | |
![]() |
ae0efc1115 | |
![]() |
dfc2edd62d | |
![]() |
fcdbf4ec7f | |
![]() |
1068168968 | |
|
d7f3a21add | |
|
ef9592ef30 | |
|
cc42683316 | |
|
70f1e6827f | |
|
b5188e3272 | |
|
ff881732d2 | |
![]() |
2adf87a289 | |
![]() |
6954a860af | |
![]() |
bb8e6aeaf8 | |
![]() |
6d7b7dd058 | |
|
007b90c284 | |
|
481d1b7db0 | |
|
733f64eaec | |
|
383660c778 | |
|
4bd77a870b | |
|
b1f460d760 | |
|
a438ab6f3e | |
![]() |
3a34d8682c | |
![]() |
60894f00b1 | |
![]() |
925b05e004 | |
|
4878d66620 | |
|
632ade9d25 | |
|
5acd45bf85 | |
|
d03b45eecf | |
![]() |
32a9d762d8 | |
![]() |
0a79950046 | |
![]() |
4b7c58b13f | |
![]() |
7148957368 | |
|
aa50c50254 | |
|
60b3c7925d | |
|
0f41cabe71 | |
![]() |
d04ed7e008 | |
![]() |
7993a89ce3 | |
|
6168256897 | |
|
4b167dacbb | |
|
911c47df8d | |
|
a37d7b9840 | |
![]() |
217ab920a9 | |
![]() |
98ae62d181 | |
![]() |
98f1723411 | |
|
68a38e75bc | |
|
ee29c6be5c | |
|
c0ee0a694c | |
![]() |
25fa6f427b | |
![]() |
467d722d25 | |
|
3e352d3c7c | |
|
13472b2311 | |
![]() |
bdddd655bf | |
![]() |
6ec7a13293 | |
![]() |
716b29c25f | |
![]() |
5c4930a362 | |
![]() |
ad8fed9440 | |
![]() |
964bef7896 | |
![]() |
7e48e5e8b8 | |
![]() |
48846a7e31 | |
|
32db15aad5 | |
![]() |
8ec3e4bbaa | |
|
4b05838498 | |
|
b8be0c23cb | |
|
d20a7b1318 | |
|
f8268accc0 | |
|
a9811768d4 | |
|
024bc289de | |
|
96d34d0237 | |
|
fea11bdc2e | |
|
ab5d273f98 | |
![]() |
8bf4e9b8d2 | |
|
096b0b954d | |
|
df57312056 | |
![]() |
f12cfabee3 | |
![]() |
b22909a654 | |
![]() |
579b45dfa4 | |
![]() |
fbc1f95cd1 | |
![]() |
4ccf8ea5ff | |
|
d5c141f892 | |
|
35c6cb98db | |
|
f417e42864 | |
|
6e54203ebb | |
![]() |
79a6841bbc | |
![]() |
b3d78741a3 | |
|
935f3ddf7f | |
|
a2549f7ff1 | |
|
d6b5dc326a | |
![]() |
003bfe7884 | |
![]() |
df5efa0dc6 | |
|
a35db9fe80 | |
|
6183f1f76d | |
|
e72273f3b2 | |
|
cc09f724cc | |
|
7a54c5f536 | |
![]() |
bb3f5cec76 | |
![]() |
19ffd9fea1 | |
![]() |
5877474f59 | |
![]() |
1bbde165c2 | |
|
3f5754a3a5 | |
|
5463c22518 | |
|
5db43bf768 | |
|
1feb166fd5 | |
|
0df1e5fdd0 | |
|
8ba70a33be | |
![]() |
b21f44b59e | |
![]() |
1c56f21c96 | |
|
7793eacf75 | |
|
25afedcdfd | |
|
d95a689815 | |
|
b386dc51e4 | |
|
1882120df3 | |
|
274cd81655 | |
|
6273349334 | |
|
e8deb83004 | |
|
52701d1c2f | |
|
b248f770f1 | |
|
04b9e43382 | |
|
3580a8653d | |
|
d9653e461e | |
|
d9a1d32ec8 | |
|
b5dfd83527 | |
|
df7b91a8ba | |
|
8dae15225e | |
|
5fcf789e63 | |
|
ed0655452c | |
|
0dd062ce1c | |
|
bd3cbf33fd | |
|
b8d4b15b40 | |
|
24d83133e7 | |
|
4ed3a9d478 | |
|
fbbacfa983 | |
|
d47708dc1c | |
|
625ed024e2 | |
|
60842e64e5 | |
|
993135602f | |
|
35e8f1d423 | |
|
dbea2e1c3d | |
|
f1fdf0c37f | |
|
d0988e42b4 | |
|
ef8f33e1cd | |
|
b380b61873 | |
|
6730466230 | |
|
94d6cac626 | |
|
640d841242 | |
|
6a0066b71c | |
|
aafbb8011b | |
|
72a87ea909 | |
|
abf909d0e7 | |
|
a2321d5370 | |
|
d154f0aecc | |
|
68e4c8ad5a | |
|
cf533f49cc | |
|
29d9410e42 | |
|
2a9a835939 | |
|
d756646b1a | |
|
3b62f09669 | |
|
5864352049 | |
|
1d6d48fc94 | |
|
484c91a581 | |
|
7b91ad37e5 | |
|
9dbb9a42d6 | |
|
a608803aa8 | |
|
76cc185a1d | |
|
e76503ae26 | |
|
50991f503f | |
|
acd031ca7d | |
|
b59b76be4a | |
|
211581cef0 | |
|
7cad953413 | |
|
fe58175ee0 | |
|
5d0849a148 | |
|
d14bf35ca1 | |
|
d7dd3901b8 | |
|
aefd6c08dc | |
|
3c2c742121 | |
|
9221e55752 | |
|
ba1fa8b685 | |
|
29e3a55a0c | |
|
c426467a68 | |
|
9fe8df3c1b | |
|
531495429c | |
|
bed2469014 | |
|
45b7f70d9f | |
|
1ebb6cb561 | |
|
21ccedab9c | |
|
8f45bcf959 | |
|
1f9caeece5 | |
|
5b4e6f4902 | |
|
3d0e323801 | |
|
f6fb50529c | |
|
c42f3d5928 | |
|
42d2b51f7f | |
|
66c40d4791 | |
|
ce467736a7 | |
|
3e4dd90e17 | |
|
8ae5587516 | |
|
0b543f7dda | |
|
a07204111a | |
|
038df804c0 | |
|
877948b0cd | |
|
9a17c4865f | |
|
9427db3e5a | |
|
81da71d478 | |
|
169dc84e22 | |
|
d6fd85f536 | |
|
6448a30e03 | |
|
17fb43cea8 | |
|
a6e50d2a25 | |
|
bd16ca476d | |
|
3dfe5d5d0f | |
|
eadc517a25 | |
|
1652e615be | |
|
2ea78b4f20 | |
|
e36c7a4b6a | |
|
8e8ec821f2 | |
|
5cf257c3cc | |
|
aa18fe0ad4 | |
|
1358c23ca6 | |
|
c27cc063e6 | |
|
b0092487e6 | |
|
fbebd0a623 | |
|
fe23c2afbf | |
|
779c86108a | |
|
83e43f0c97 | |
|
e545424b7d | |
|
e237fd46f7 | |
|
ca3c564529 | |
|
9cd18397f7 | |
|
7574071445 | |
|
77620f7735 | |
|
50dc5cce5d | |
|
a6cee63d17 | |
|
000197b0d1 | |
|
6aa3321d17 | |
|
d44308fc82 | |
|
ae7d0d1329 | |
|
55c74de8e4 | |
|
7c88ea3d67 | |
|
f15cd44dff | |
|
3abd6037d9 | |
|
ec3a556a6f | |
|
793cbb372a | |
|
396ac55429 | |
|
088c617cc1 | |
|
17314b9164 | |
|
e6521ffdd2 | |
|
fc3cf01d3f | |
|
8f5bb0e2d9 | |
|
ef559b11a0 | |
|
7f59f6739f | |
|
d6937f195c | |
|
2dfd69ae21 | |
|
720c073f32 | |
|
0076468a15 | |
|
910ae48556 | |
|
eac7331070 | |
|
551f333261 | |
|
dec264d169 | |
|
7055974443 | |
|
3536918938 | |
|
56278b84f2 | |
|
882a50cf56 | |
|
db4031b8bf | |
|
ecfc39565c | |
|
9ced678f91 | |
|
7951ca28d5 | |
|
4bbb843edf | |
|
747646cd9d | |
|
d0d906d04c | |
|
bc639488aa | |
|
99fbecc834 | |
|
8d0a6d267a | |
|
b1c03ed5e8 | |
|
ef12f85687 | |
|
e120c4dac2 | |
|
e1cf2fcdeb | |
|
c4f380873e | |
|
5cb2e55f74 | |
|
1dd3fbc69a | |
|
b97c42d0ae | |
|
a2612d8009 | |
|
2f2655525f | |
|
1a93477635 | |
|
7c664addbd | |
|
c6b79f82bc | |
|
4e3f9cc019 | |
|
5ed7b3e4ad | |
|
4e2c46260c | |
|
9ba00b21c9 | |
|
b11f5fd228 | |
|
90dbe0730a | |
|
d6633cb73a | |
|
a7a6abd22a | |
|
c956667ce0 | |
|
5701c818ed | |
|
1ac2ddfaa5 | |
|
4aac05d4e1 | |
|
84b56bfcb8 | |
|
7485564bb9 | |
|
b5acf2308a | |
|
e3f4313c80 | |
|
b223abe229 | |
|
b3bede308c | |
|
2f170a54c6 | |
|
22293572ac | |
|
8720cab1e9 | |
|
959c1e8d95 | |
|
29dc3fff39 | |
|
298abdd1b1 | |
|
26f87fba16 | |
|
1e9a32a93e | |
|
2dc79052c2 | |
|
380ca3a066 | |
|
237b0afb08 | |
|
e14936e820 | |
|
655c85851f | |
|
1c7e414aa4 | |
|
099fc52e00 | |
|
490957ec3b | |
|
b1884d30d5 | |
|
98d8ee1fb6 | |
|
2ca77732c8 | |
|
70d22f7c4f | |
|
25d0e784bb | |
|
5d45b24299 | |
|
b6b8befde7 | |
|
f33b9559cd | |
|
f9bc2258ec | |
|
2a09ced1ce | |
|
7a1e6cfbad | |
|
47d1f727ce | |
|
a7665df0ea | |
|
84f12adce8 | |
|
7fde1e0e12 | |
|
499734ebf9 | |
|
f339df699e | |
|
cfd94cb3b7 | |
|
43e0617429 | |
|
d6b66d5324 | |
|
0c1df3b2cb | |
|
fa86d3ea10 | |
|
8c99b754fb | |
|
f3cf2c87c9 | |
|
8e4e6fc0ac | |
|
75f3166ffa | |
|
04bf423fcb | |
|
51e8c9d908 | |
|
4304a35b80 | |
|
076375633a | |
|
dbf5e711a5 | |
|
4432e65683 | |
|
dcf44a78f0 | |
|
12edc620df | |
|
4ce03145df | |
|
3e04a37ece | |
|
78f464ccba | |
|
64423f1999 | |
|
05c3f60dab | |
|
0083ef33cb | |
|
36b68df273 | |
|
e1a5918c22 | |
|
26ae9b35df | |
|
8e79b43aaf | |
|
d28eba6423 | |
|
688be1bb7d | |
|
df69dee282 | |
|
45a77e5c07 | |
|
7849bd0ebf | |
|
3649bf1fd0 | |
|
6ffc2938a1 | |
|
aa60de1dac | |
|
29f98513e2 | |
|
e35cdf39fb | |
|
e51b86538b | |
|
da4fd3a762 | |
|
efc82b9841 | |
|
e3df503dd2 | |
|
6a2ad67386 | |
|
3d12db3a07 | |
|
1faaf1d7d1 | |
|
f8a6f62342 | |
|
66d1246a6c | |
|
f79beef3f9 | |
|
81e6691632 | |
|
38d6519381 | |
|
16418675ac | |
|
102858bc8c | |
|
0d64768e4b | |
|
beccac652f | |
|
30eb1958c1 | |
|
33e17e8439 | |
|
e0c47c2abd | |
|
422549f9e7 | |
|
0358229b95 | |
|
c4586fbb36 | |
|
f94006abfd | |
|
4d61e7618a | |
|
36286d9003 | |
|
51356da7f3 | |
|
ebe893022f | |
|
c5f22e6c70 | |
|
922561afb1 | |
|
6f7899d16f | |
|
4e3c8e414c | |
|
d588a78f62 | |
|
a7d681c4dd | |
|
7a93db9ed2 | |
|
74e5fa0e31 | |
|
de995c8714 | |
|
ea156cec7e | |
|
7499d8af89 | |
|
f8654edc3b | |
|
d16f290aa6 | |
|
9385d346f1 | |
|
22f3371090 | |
|
c0a4f8f4ec | |
|
7586a0fb21 | |
|
c0e3a91a46 | |
|
7ebd8681fa | |
|
72553dec57 | |
|
dee68808b1 | |
|
96d7917bbf | |
|
abca0fe432 | |
|
d7612a0921 | |
|
c54950a95f | |
|
be0f68cede | |
|
1b92b53099 | |
|
5634413cac | |
|
1a9ed1425e | |
|
f9d4316a8e | |
|
6f7f815fd4 | |
|
ddb826733b | |
|
1f989d0a37 | |
|
d63626424e | |
|
55ab694505 | |
|
0885575cc4 | |
|
a188648287 | |
|
8011dabaac | |
|
88a08e73c0 | |
|
6713f9b280 |
|
@ -23,7 +23,7 @@
|
||||||
* Fix 版本库中附件下载400(#51625)
|
* Fix 版本库中附件下载400(#51625)
|
||||||
* Fix loading页面优化(#51588)
|
* Fix loading页面优化(#51588)
|
||||||
* Fix 提交详情页面优化(#51577)
|
* Fix 提交详情页面优化(#51577)
|
||||||
* Fix 修复易修复制功能(#51569)
|
* Fix 修复疑修复制功能(#51569)
|
||||||
* Fix 修复新建发行版用户信息显示错误的问题(#51665)
|
* Fix 修复新建发行版用户信息显示错误的问题(#51665)
|
||||||
* Fix 修复查看文件详细信息报错的问题(#51561)
|
* Fix 修复查看文件详细信息报错的问题(#51561)
|
||||||
* Fix 修复提交记录中时间显示格式问题(#51526)
|
* Fix 修复提交记录中时间显示格式问题(#51526)
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
|
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
|
||||||
|
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Fix 解决易修标题过长导致的排版问题(45469)
|
* Fix 解决疑修标题过长导致的排版问题(45469)
|
||||||
* Fix 解决合并请求详情页面排版错误的问题(45457)
|
* Fix 解决合并请求详情页面排版错误的问题(45457)
|
||||||
* FIX 解决转移仓库界面专有名词描述错误的问题(45455)
|
* FIX 解决转移仓库界面专有名词描述错误的问题(45455)
|
||||||
* Fix 解决markdown格式文件自动生成数字排序的问题(45454)
|
* Fix 解决markdown格式文件自动生成数字排序的问题(45454)
|
||||||
|
|
274
Gemfile
274
Gemfile
|
@ -1,130 +1,144 @@
|
||||||
source 'https://gems.ruby-china.com'
|
#source 'https://gems.ruby-china.com'
|
||||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
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 'rails', '~> 5.2.0'
|
||||||
gem 'puma', '~> 3.11'
|
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
|
||||||
gem 'sass-rails', '~> 5.0'
|
gem 'puma', '~> 3.11'
|
||||||
gem 'uglifier', '>= 1.3.0'
|
gem 'sass-rails', '~> 5.0'
|
||||||
|
gem 'uglifier', '>= 1.3.0'
|
||||||
# gem 'coffee-rails', '~> 4.2'
|
|
||||||
gem 'turbolinks', '~> 5'
|
# gem 'coffee-rails', '~> 4.2'
|
||||||
gem 'jbuilder', '~> 2.5'
|
gem 'turbolinks', '~> 5'
|
||||||
gem 'groupdate', '~> 4.1.0'
|
gem 'jbuilder', '~> 2.5'
|
||||||
gem 'chartkick'
|
gem 'groupdate', '~> 4.1.0'
|
||||||
gem 'grape-entity', '~> 0.7.1'
|
gem 'chartkick'
|
||||||
gem 'kaminari', '~> 1.1', '>= 1.1.1'
|
gem 'grape-entity', '~> 0.7.1'
|
||||||
|
gem 'kaminari', '~> 1.1', '>= 1.1.1'
|
||||||
gem 'bootsnap', '>= 1.1.0', require: false
|
|
||||||
|
gem 'bootsnap', '>= 1.1.0', require: false
|
||||||
gem 'chinese_pinyin'
|
|
||||||
|
gem 'chinese_pinyin'
|
||||||
gem 'rack-cors'
|
|
||||||
gem 'redis-rails'
|
gem 'rack-cors'
|
||||||
gem 'roo-xls'
|
gem 'redis-rails'
|
||||||
gem 'simple_xlsx_reader'
|
gem 'roo-xls'
|
||||||
|
gem 'simple_xlsx_reader'
|
||||||
gem 'rubyzip'
|
|
||||||
|
gem 'rubyzip'
|
||||||
gem 'spreadsheet'
|
|
||||||
gem 'ruby-ole'
|
gem 'spreadsheet'
|
||||||
# 导出为xlsx
|
gem 'ruby-ole'
|
||||||
gem 'axlsx', '~> 3.0.0.pre'
|
# 导出为xlsx
|
||||||
gem 'axlsx_rails', '~> 0.5.2'
|
gem 'axlsx', '~> 3.0.0.pre'
|
||||||
|
gem 'axlsx_rails', '~> 0.5.2'
|
||||||
gem 'oauth2'
|
|
||||||
#导出为pdf
|
gem 'oauth2'
|
||||||
gem 'pdfkit'
|
#导出为pdf
|
||||||
gem 'wkhtmltopdf-binary'
|
gem 'pdfkit'
|
||||||
# gem 'request_store'
|
gem 'wkhtmltopdf-binary'
|
||||||
#gem 'iconv'
|
# gem 'request_store'
|
||||||
# markdown 转html
|
#gem 'iconv'
|
||||||
gem 'redcarpet', '~> 3.4'
|
# markdown 转html
|
||||||
|
gem 'redcarpet', '~> 3.4'
|
||||||
gem 'rqrcode', '~> 0.10.1'
|
|
||||||
gem 'rqrcode_png'
|
gem 'rqrcode', '~> 0.10.1'
|
||||||
|
gem 'rqrcode_png'
|
||||||
gem 'acts-as-taggable-on', '~> 6.0'
|
|
||||||
|
gem 'acts-as-taggable-on', '~> 6.0'
|
||||||
# a tree structure
|
|
||||||
gem 'ancestry'
|
# a tree structure
|
||||||
gem 'acts_as_list'
|
gem 'ancestry'
|
||||||
gem 'omniauth-cas'
|
gem 'acts_as_list'
|
||||||
|
gem 'omniauth-cas'
|
||||||
# profiler Middleware
|
|
||||||
gem 'rack-mini-profiler'
|
# profiler Middleware
|
||||||
|
gem 'rack-mini-profiler'
|
||||||
# object-based searching
|
|
||||||
gem 'ransack'
|
# object-based searching
|
||||||
|
gem 'ransack'
|
||||||
group :development, :test do
|
|
||||||
gem 'rspec-rails', '~> 3.8'
|
group :development, :test do
|
||||||
end
|
gem 'rspec-rails', '~> 3.8'
|
||||||
|
end
|
||||||
group :development do
|
|
||||||
gem 'prettier'
|
group :development do
|
||||||
gem 'rubocop', '~> 0.52.0'
|
gem 'prettier'
|
||||||
gem 'solargraph', '~> 0.38.0'
|
gem 'rubocop', '~> 0.52.0'
|
||||||
gem 'awesome_print'
|
gem 'solargraph', '~> 0.38.0'
|
||||||
gem 'web-console', '>= 3.3.0'
|
gem 'awesome_print'
|
||||||
gem 'listen', '>= 3.0.5', '< 3.2'
|
gem 'web-console', '>= 3.3.0'
|
||||||
gem 'spring'
|
gem 'listen', '>= 3.0.5', '< 3.2'
|
||||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
gem 'spring'
|
||||||
gem "annotate", "~> 2.6.0"
|
gem 'spring-watcher-listen', '~> 2.0.0'
|
||||||
end
|
gem "annotate", "~> 2.6.0"
|
||||||
|
end
|
||||||
group :test do
|
|
||||||
gem 'capybara', '>= 2.15', '< 4.0'
|
group :test do
|
||||||
gem 'selenium-webdriver'
|
gem 'capybara', '>= 2.15', '< 4.0'
|
||||||
gem 'chromedriver-helper'
|
gem 'selenium-webdriver'
|
||||||
end
|
gem 'chromedriver-helper'
|
||||||
|
end
|
||||||
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
|
||||||
|
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
||||||
#编码检测
|
|
||||||
gem 'rchardet', '~> 1.8'
|
#编码检测
|
||||||
|
gem 'rchardet', '~> 1.8'
|
||||||
# http client
|
|
||||||
gem 'faraday', '~> 0.15.4'
|
# http client
|
||||||
|
gem 'faraday', '~> 0.15.4'
|
||||||
# view
|
|
||||||
gem 'active_decorator'
|
# view
|
||||||
gem 'bootstrap', '~> 4.3.1'
|
gem 'active_decorator'
|
||||||
gem 'jquery-rails'
|
gem 'bootstrap', '~> 4.3.1'
|
||||||
gem 'simple_form'
|
gem 'jquery-rails'
|
||||||
gem 'font-awesome-sass', '4.7.0'
|
gem 'simple_form'
|
||||||
|
gem 'font-awesome-sass', '4.7.0'
|
||||||
# i18n
|
|
||||||
gem 'rails-i18n', '~> 5.1'
|
# i18n
|
||||||
|
gem 'rails-i18n', '~> 5.1'
|
||||||
# job
|
|
||||||
gem 'sidekiq'
|
# job
|
||||||
gem 'sinatra'
|
gem 'sidekiq'
|
||||||
gem "sidekiq-cron", "~> 1.1"
|
gem 'sinatra'
|
||||||
|
gem "sidekiq-cron", "~> 1.1"
|
||||||
# batch insert
|
gem 'sidekiq-failures'
|
||||||
gem 'bulk_insert'
|
|
||||||
|
# batch insert
|
||||||
# elasticsearch
|
gem 'bulk_insert'
|
||||||
gem 'searchkick'
|
|
||||||
|
# elasticsearch
|
||||||
gem 'aasm'
|
gem 'searchkick'
|
||||||
gem 'enumerize'
|
|
||||||
|
gem 'aasm'
|
||||||
gem 'diffy'
|
gem 'enumerize'
|
||||||
|
|
||||||
gem 'deep_cloneable', '~> 3.0.0'
|
gem 'diffy'
|
||||||
|
|
||||||
# oauth2
|
gem 'deep_cloneable', '~> 3.0.0'
|
||||||
gem 'omniauth', '~> 1.9.0'
|
|
||||||
gem 'omniauth-oauth2', '~> 1.6.0'
|
# oauth2
|
||||||
|
gem 'omniauth', '~> 1.9.0'
|
||||||
# global var
|
gem 'omniauth-oauth2', '~> 1.6.0'
|
||||||
gem 'request_store'
|
gem "omniauth-github"
|
||||||
|
gem "omniauth-rails_csrf_protection"
|
||||||
# 敏感词汇
|
gem 'omniauth-gitee', '~> 1.0.0'
|
||||||
gem 'harmonious_dictionary', '~> 0.0.1'
|
gem "omniauth-wechat-oauth2"
|
||||||
|
|
||||||
gem 'parallel', '~> 1.19', '>= 1.19.1'
|
# global var
|
||||||
|
gem 'request_store'
|
||||||
gem 'letter_avatar'
|
|
||||||
|
# 敏感词汇
|
||||||
|
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.10.6'
|
|
@ -106,6 +106,10 @@ GEM
|
||||||
activerecord (>= 3.1.0, < 7)
|
activerecord (>= 3.1.0, < 7)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.3)
|
||||||
diffy (3.3.0)
|
diffy (3.3.0)
|
||||||
|
doorkeeper (5.5.1)
|
||||||
|
railties (>= 5)
|
||||||
|
doorkeeper-jwt (0.4.1)
|
||||||
|
jwt (>= 2.1)
|
||||||
e2mmap (0.1.0)
|
e2mmap (0.1.0)
|
||||||
elasticsearch (7.5.0)
|
elasticsearch (7.5.0)
|
||||||
elasticsearch-api (= 7.5.0)
|
elasticsearch-api (= 7.5.0)
|
||||||
|
@ -450,6 +454,8 @@ DEPENDENCIES
|
||||||
chromedriver-helper
|
chromedriver-helper
|
||||||
deep_cloneable (~> 3.0.0)
|
deep_cloneable (~> 3.0.0)
|
||||||
diffy
|
diffy
|
||||||
|
doorkeeper
|
||||||
|
doorkeeper-jwt
|
||||||
enumerize
|
enumerize
|
||||||
faraday (~> 0.15.4)
|
faraday (~> 0.15.4)
|
||||||
font-awesome-sass (= 4.7.0)
|
font-awesome-sass (= 4.7.0)
|
||||||
|
@ -458,6 +464,7 @@ DEPENDENCIES
|
||||||
harmonious_dictionary (~> 0.0.1)
|
harmonious_dictionary (~> 0.0.1)
|
||||||
jbuilder (~> 2.5)
|
jbuilder (~> 2.5)
|
||||||
jquery-rails
|
jquery-rails
|
||||||
|
jwt
|
||||||
kaminari (~> 1.1, >= 1.1.1)
|
kaminari (~> 1.1, >= 1.1.1)
|
||||||
letter_avatar
|
letter_avatar
|
||||||
listen (>= 3.0.5, < 3.2)
|
listen (>= 3.0.5, < 3.2)
|
||||||
|
|
|
@ -1,136 +1,137 @@
|
||||||
//= require rails-ujs
|
//= require rails-ujs
|
||||||
//= require activestorage
|
//= require activestorage
|
||||||
//= require turbolinks
|
//= require turbolinks
|
||||||
//= require jquery3
|
//= require jquery3
|
||||||
//= require popper
|
//= require popper
|
||||||
//= require bootstrap-sprockets
|
//= require bootstrap-sprockets
|
||||||
//= require jquery.validate.min
|
//= require jquery.validate.min
|
||||||
//= require additional-methods.min
|
//= require additional-methods.min
|
||||||
//= require bootstrap-notify
|
//= require bootstrap-notify
|
||||||
//= require jquery.cookie.min
|
//= require jquery.cookie.min
|
||||||
//= require select2
|
//= require select2
|
||||||
//= require moment.min
|
//= require moment.min
|
||||||
//= require jquery.cxselect
|
//= require jquery.cxselect
|
||||||
//= require bootstrap-datepicker
|
//= require bootstrap-datepicker
|
||||||
//= require bootstrap-datetimepicker
|
//= require bootstrap-datetimepicker
|
||||||
//= require bootstrap.viewer
|
//= require bootstrap.viewer
|
||||||
//= require jquery.mloading
|
//= require bootstrap/bootstrap-toggle
|
||||||
//= require jquery-confirm.min
|
//= require jquery.mloading
|
||||||
//= require common
|
//= require jquery-confirm.min
|
||||||
|
//= require common
|
||||||
//= require echarts
|
|
||||||
//= require codemirror/lib/codemirror
|
//= require echarts
|
||||||
//= require codemirror/mode/shell/shell
|
//= require codemirror/lib/codemirror
|
||||||
//= require editormd/editormd
|
//= require codemirror/mode/shell/shell
|
||||||
//= require editormd/languages/zh-tw
|
//= require editormd/editormd
|
||||||
//= require dragula/dragula
|
//= require editormd/languages/zh-tw
|
||||||
|
//= require dragula/dragula
|
||||||
//= require_tree ./i18n
|
|
||||||
//= require_tree ./admins
|
//= require_tree ./i18n
|
||||||
|
//= require_tree ./admins
|
||||||
|
|
||||||
$.ajaxSetup({
|
|
||||||
beforeSend: function(xhr) {
|
$.ajaxSetup({
|
||||||
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
|
beforeSend: function(xhr) {
|
||||||
}
|
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
// ******** select2 global config ********
|
|
||||||
$.fn.select2.defaults.set('theme', 'bootstrap4');
|
// ******** select2 global config ********
|
||||||
$.fn.select2.defaults.set('language', 'zh-CN');
|
$.fn.select2.defaults.set('theme', 'bootstrap4');
|
||||||
|
$.fn.select2.defaults.set('language', 'zh-CN');
|
||||||
Turbolinks.setProgressBarDelay(200);
|
|
||||||
|
Turbolinks.setProgressBarDelay(200);
|
||||||
$.notifyDefaults({
|
|
||||||
type: 'success',
|
$.notifyDefaults({
|
||||||
z_index: 9999,
|
type: 'success',
|
||||||
delay: 2000
|
z_index: 9999,
|
||||||
});
|
delay: 2000
|
||||||
|
});
|
||||||
function show_success_flash(){
|
|
||||||
$.notify({
|
function show_success_flash(){
|
||||||
message: '操作成功'
|
$.notify({
|
||||||
},{
|
message: '操作成功'
|
||||||
type: 'success'
|
},{
|
||||||
});
|
type: 'success'
|
||||||
}
|
});
|
||||||
|
}
|
||||||
$(document).on('turbolinks:load', function(){
|
|
||||||
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' });
|
$(document).on('turbolinks:load', function(){
|
||||||
$('[data-toggle="popover"]').popover();
|
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' });
|
||||||
|
$('[data-toggle="popover"]').popover();
|
||||||
// 图片查看大图
|
|
||||||
$('img.preview-image').bootstrapViewer();
|
// 图片查看大图
|
||||||
|
$('img.preview-image').bootstrapViewer();
|
||||||
// flash alert提示框自动关闭
|
|
||||||
if($('.admin-alert-container .alert').length > 0){
|
// flash alert提示框自动关闭
|
||||||
setTimeout(function(){
|
if($('.admin-alert-container .alert').length > 0){
|
||||||
$('.admin-alert-container .alert:not(.alert-danger)').alert('close');
|
setTimeout(function(){
|
||||||
}, 2000);
|
$('.admin-alert-container .alert:not(.alert-danger)').alert('close');
|
||||||
setTimeout(function(){
|
}, 2000);
|
||||||
$('.admin-alert-container .alert.alert-danger').alert('close');
|
setTimeout(function(){
|
||||||
}, 5000);
|
$('.admin-alert-container .alert.alert-danger').alert('close');
|
||||||
}
|
}, 5000);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
$(document).on("turbolinks:before-cache", function () {
|
|
||||||
$('[data-toggle="tooltip"]').tooltip('hide');
|
$(document).on("turbolinks:before-cache", function () {
|
||||||
$('[data-toggle="popover"]').popover('hide');
|
$('[data-toggle="tooltip"]').tooltip('hide');
|
||||||
});
|
$('[data-toggle="popover"]').popover('hide');
|
||||||
// var progressBar = new Turbolinks.ProgressBar();
|
});
|
||||||
|
// var progressBar = new Turbolinks.ProgressBar();
|
||||||
// $(document).on('ajax:send', function(event){
|
|
||||||
// console.log('ajax send', event);
|
// $(document).on('ajax:send', function(event){
|
||||||
// progressBar.setValue(0)
|
// console.log('ajax send', event);
|
||||||
// progressBar.show()
|
// progressBar.setValue(0)
|
||||||
// });
|
// progressBar.show()
|
||||||
//
|
// });
|
||||||
// $(document).on('ajax:complete', function(event){
|
//
|
||||||
// console.log('ajax complete', event);
|
// $(document).on('ajax:complete', function(event){
|
||||||
// progressBar.setValue(1)
|
// console.log('ajax complete', event);
|
||||||
// progressBar.hide() // 分页时不触发,奇怪
|
// progressBar.setValue(1)
|
||||||
// });
|
// progressBar.hide() // 分页时不触发,奇怪
|
||||||
// $(document).on('ajax:success', function(event){
|
// });
|
||||||
// console.log('ajax success', event);
|
// $(document).on('ajax:success', function(event){
|
||||||
// });
|
// console.log('ajax success', event);
|
||||||
// $(document).on('ajax:error', function(event){
|
// });
|
||||||
// console.log('ajax error', event);
|
// $(document).on('ajax:error', function(event){
|
||||||
// });
|
// console.log('ajax error', event);
|
||||||
|
// });
|
||||||
$(function () {
|
|
||||||
});
|
$(function () {
|
||||||
|
});
|
||||||
$(document).on('turbolinks:load', function() {
|
|
||||||
|
$(document).on('turbolinks:load', function() {
|
||||||
$('.logo-item-left').on("change", 'input[type="file"]', function () {
|
|
||||||
var $fileInput = $(this);
|
$('.logo-item-left').on("change", 'input[type="file"]', function () {
|
||||||
var file = this.files[0];
|
var $fileInput = $(this);
|
||||||
var imageType = /image.*/;
|
var file = this.files[0];
|
||||||
if (file && file.type.match(imageType)) {
|
var imageType = /image.*/;
|
||||||
var reader = new FileReader();
|
if (file && file.type.match(imageType)) {
|
||||||
reader.onload = function () {
|
var reader = new FileReader();
|
||||||
var $box = $fileInput.parent();
|
reader.onload = function () {
|
||||||
$box.find('img').attr('src', reader.result).css('display', 'block');
|
var $box = $fileInput.parent();
|
||||||
$box.addClass('has-img');
|
$box.find('img').attr('src', reader.result).css('display', 'block');
|
||||||
};
|
$box.addClass('has-img');
|
||||||
reader.readAsDataURL(file);
|
};
|
||||||
} else {
|
reader.readAsDataURL(file);
|
||||||
}
|
} else {
|
||||||
});
|
}
|
||||||
|
});
|
||||||
$('.attachment-item-left').on("change", 'input[type="file"]', function () {
|
|
||||||
var $fileInput = $(this);
|
$('.attachment-item-left').on("change", 'input[type="file"]', function () {
|
||||||
var file = this.files[0];
|
var $fileInput = $(this);
|
||||||
var imageType = /image.*/;
|
var file = this.files[0];
|
||||||
if (file && file.type.match(imageType)) {
|
var imageType = /image.*/;
|
||||||
var reader = new FileReader();
|
if (file && file.type.match(imageType)) {
|
||||||
reader.onload = function () {
|
var reader = new FileReader();
|
||||||
var $box = $fileInput.parent();
|
reader.onload = function () {
|
||||||
$box.find('img').attr('src', reader.result).css('display', 'block');
|
var $box = $fileInput.parent();
|
||||||
$box.addClass('has-img');
|
$box.find('img').attr('src', reader.result).css('display', 'block');
|
||||||
};
|
$box.addClass('has-img');
|
||||||
reader.readAsDataURL(file);
|
};
|
||||||
} else {
|
reader.readAsDataURL(file);
|
||||||
}
|
} else {
|
||||||
});
|
}
|
||||||
|
});
|
||||||
})
|
})
|
|
@ -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);
|
|
@ -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
|
|
@ -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"}
|
|
@ -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);
|
|
@ -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
|
|
@ -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"}
|
|
@ -8,6 +8,7 @@
|
||||||
@import "jquery.mloading";
|
@import "jquery.mloading";
|
||||||
@import "jquery-confirm.min";
|
@import "jquery-confirm.min";
|
||||||
@import "bootstrap-datetimepicker.min";
|
@import "bootstrap-datetimepicker.min";
|
||||||
|
@import "bootstrap/bootstrap-toggle.min";
|
||||||
|
|
||||||
@import "codemirror/lib/codemirror";
|
@import "codemirror/lib/codemirror";
|
||||||
@import "editormd/css/editormd.min";
|
@import "editormd/css/editormd.min";
|
||||||
|
@ -203,4 +204,14 @@ input.form-control {
|
||||||
color: #23272B;
|
color: #23272B;
|
||||||
font-size: 1rem;
|
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;
|
||||||
}
|
}
|
|
@ -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; }
|
||||||
|
|
|
@ -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}
|
|
@ -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; }
|
||||||
|
|
|
@ -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}
|
|
@ -1,371 +1,422 @@
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
include ApplicationHelper
|
before_action :require_login, only: [:login_check, :simple_update]
|
||||||
|
include ApplicationHelper
|
||||||
#skip_before_action :check_account, :only => [:logout]
|
|
||||||
|
#skip_before_action :check_account, :only => [:logout]
|
||||||
def index
|
|
||||||
render json: session
|
def simple_update
|
||||||
end
|
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, ""))
|
||||||
|
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
|
||||||
# 其他平台同步注册的用户
|
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, ""))
|
||||||
def remote_register
|
Register::RemoteForm.new(simple_update_params).validate!
|
||||||
username = params[:username]&.gsub(/\s+/, "")
|
|
||||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
ActiveRecord::Base.transaction do
|
||||||
email = params[:email]&.gsub(/\s+/, "")
|
result = auto_update(current_user, simple_update_params)
|
||||||
password = params[:password]
|
if result[:message].blank?
|
||||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
render_ok
|
||||||
|
else
|
||||||
ActiveRecord::Base.transaction do
|
render_error(result[:message])
|
||||||
result = autologin_register(username, email, password, platform)
|
end
|
||||||
if result[:message].blank?
|
end
|
||||||
render_ok({user: result[:user]})
|
end
|
||||||
else
|
|
||||||
render_error(result[:message])
|
def index
|
||||||
end
|
render json: session
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
|
||||||
uid_logger_error(e.message)
|
# 为了同步平台上未注册gitea的用户
|
||||||
tip_exception(-1, e.message)
|
def gitea_register
|
||||||
end
|
user = User.find_by(login: sync_gitea_params[:login])
|
||||||
|
Users::SyncGiteaForm.new(sync_gitea_params.merge(user: user)).validate!
|
||||||
# 其他平台修改用户的信息,这边同步修改
|
return render_error("该用户已同步协作平台") if user.gitea_token.present? && user.gitea_uid.present?
|
||||||
def remote_update
|
|
||||||
ActiveRecord::Base.transaction do
|
result = create_gitea_user!(user, sync_gitea_params[:login], sync_gitea_params[:email], sync_gitea_params[:password])
|
||||||
user_params = params[:user_params]
|
result[:user] ? render_ok : render_error(result[:message])
|
||||||
user_extension_params = params[:user_extension_params]
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
u = User.find_by(login: params[:old_user_login])
|
tip_exception(-1, e.message)
|
||||||
user_mail = u.try(:mail)
|
end
|
||||||
|
|
||||||
if u.present?
|
# 其他平台同步注册的用户
|
||||||
ue = u.user_extension
|
def remote_register
|
||||||
u.login = user_params["login"] if user_params["login"]
|
Register::RemoteForm.new(remote_register_params).validate!
|
||||||
u.mail = user_params["mail"] if user_params["mail"]
|
username = params[:username]&.gsub(/\s+/, "")
|
||||||
u.lastname = user_params["lastname"] if user_params["lastname"]
|
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||||
|
email = params[:email]&.gsub(/\s+/, "")
|
||||||
ue.gender = user_extension_params["gender"]
|
password = params[:password]
|
||||||
ue.school_id = user_extension_params["school_id"]
|
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||||
ue.location = user_extension_params["location"]
|
|
||||||
ue.location_city = user_extension_params["location_city"]
|
ActiveRecord::Base.transaction do
|
||||||
ue.identity = user_extension_params["identity"]
|
result = autologin_register(username, email, password, platform)
|
||||||
ue.technical_title = user_extension_params["technical_title"]
|
if result[:message].blank?
|
||||||
ue.student_id = user_extension_params["student_id"]
|
render_ok({user: result[:user]})
|
||||||
ue.description = user_extension_params["description"]
|
else
|
||||||
ue.save!
|
render_error(result[:message])
|
||||||
u.save!
|
end
|
||||||
|
end
|
||||||
sync_params = {}
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
if (user_params["mail"] && user_params["mail"] != user_mail)
|
tip_exception(-1, e.message)
|
||||||
sync_params = sync_params.merge(email: user_params["mail"])
|
end
|
||||||
end
|
|
||||||
|
# 其他平台修改用户的信息,这边同步修改
|
||||||
if sync_params.present?
|
def remote_update
|
||||||
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
ActiveRecord::Base.transaction do
|
||||||
if interactor.success?
|
user_params = params[:user_params]
|
||||||
render_ok
|
user_extension_params = params[:user_extension_params]
|
||||||
else
|
|
||||||
render_error(interactor.error)
|
u = User.find_by(login: params[:old_user_login])
|
||||||
end
|
user_mail = u.try(:mail)
|
||||||
end
|
|
||||||
end
|
if u.present?
|
||||||
end
|
ue = u.user_extension
|
||||||
rescue Exception => e
|
u.login = user_params["login"] if user_params["login"]
|
||||||
uid_logger_error(e.message)
|
u.mail = user_params["mail"] if user_params["mail"]
|
||||||
tip_exception(-1, e.message)
|
u.lastname = user_params["lastname"] if user_params["lastname"]
|
||||||
end
|
|
||||||
|
ue.gender = user_extension_params["gender"]
|
||||||
# 其他平台同步登录
|
ue.school_id = user_extension_params["school_id"]
|
||||||
def remote_login
|
ue.location = user_extension_params["location"]
|
||||||
@user = User.try_to_login(params[:login], params[:password])
|
ue.location_city = user_extension_params["location_city"]
|
||||||
if @user
|
ue.identity = user_extension_params["identity"]
|
||||||
successful_authentication(@user)
|
ue.technical_title = user_extension_params["technical_title"]
|
||||||
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
ue.student_id = user_extension_params["student_id"]
|
||||||
else
|
ue.description = user_extension_params["description"]
|
||||||
render_error("用户不存在")
|
ue.save!
|
||||||
end
|
u.save!
|
||||||
end
|
|
||||||
|
sync_params = {}
|
||||||
#修改密码
|
|
||||||
def remote_password
|
if (user_params["mail"] && user_params["mail"] != user_mail)
|
||||||
@user = User.find_by(login: params[:login])
|
sync_params = sync_params.merge(email: user_params["mail"])
|
||||||
return render_error("未找到相关用户!") if @user.blank?
|
end
|
||||||
|
|
||||||
sync_params = {
|
if sync_params.present?
|
||||||
password: params[:password].to_s,
|
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
||||||
email: @user.mail
|
if interactor.success?
|
||||||
}
|
render_ok
|
||||||
|
else
|
||||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
render_error(interactor.error)
|
||||||
if interactor.success?
|
end
|
||||||
@user.update_attribute(:password, params[:password])
|
end
|
||||||
render_ok
|
end
|
||||||
else
|
end
|
||||||
render_error(interactor.error)
|
rescue Exception => e
|
||||||
end
|
uid_logger_error(e.message)
|
||||||
end
|
tip_exception(-1, e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
# 其他平台同步登录
|
||||||
# 用户注册
|
def remote_login
|
||||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
@user = User.try_to_login(params[:login], params[:password])
|
||||||
# params[:login] 邮箱或者手机号
|
if @user
|
||||||
# params[:namespace] 登录名
|
successful_authentication(@user)
|
||||||
# params[:code] 验证码
|
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
||||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
else
|
||||||
# 本地forge注册入口需要重新更改逻辑
|
render_error("用户不存在")
|
||||||
def register
|
end
|
||||||
# type只可能是1或者8
|
end
|
||||||
user = nil
|
|
||||||
begin
|
#修改密码
|
||||||
Register::Form.new(register_params).validate!
|
def remote_password
|
||||||
|
@user = User.find_by(login: params[:login])
|
||||||
user = Users::RegisterService.call(register_params)
|
return render_error("未找到相关用户!") if @user.blank?
|
||||||
password = register_params[:password].strip
|
|
||||||
|
sync_params = {
|
||||||
# gitea用户注册, email, username, password
|
password: params[:password].to_s,
|
||||||
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
email: @user.mail,
|
||||||
if interactor.success?
|
login_name: @user.login,
|
||||||
gitea_user = interactor.result
|
source_id: 0
|
||||||
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
}
|
||||||
user.gitea_token = result['sha1']
|
|
||||||
user.gitea_uid = gitea_user[:body]['id']
|
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||||
if user.save!
|
if interactor.success?
|
||||||
UserExtension.create!(user_id: user.id)
|
@user.update_attribute(:password, params[:password])
|
||||||
successful_authentication(user)
|
render_ok
|
||||||
render_ok
|
else
|
||||||
end
|
render_error(interactor.error)
|
||||||
else
|
end
|
||||||
tip_exception(-1, interactor.error)
|
end
|
||||||
end
|
|
||||||
rescue Register::BaseForm::EmailError => e
|
|
||||||
render_error(-2, e.message)
|
|
||||||
rescue Register::BaseForm::LoginError => e
|
# 用户注册
|
||||||
render_error(-3, e.message)
|
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||||
rescue Register::BaseForm::PhoneError => e
|
# params[:login] 邮箱或者手机号
|
||||||
render_error(-4, e.message)
|
# params[:namespace] 登录名
|
||||||
rescue Register::BaseForm::PasswordFormatError => e
|
# params[:code] 验证码
|
||||||
render_error(-5, e.message)
|
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||||
rescue Register::BaseForm::VerifiCodeError => e
|
# 本地forge注册入口需要重新更改逻辑
|
||||||
render_error(-6, e.message)
|
def register
|
||||||
rescue Exception => e
|
# type只可能是1或者8
|
||||||
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
user = nil
|
||||||
uid_logger_error(e.message)
|
begin
|
||||||
tip_exception(-1, e.message)
|
Register::Form.new(register_params).validate!
|
||||||
end
|
|
||||||
end
|
user = Users::RegisterService.call(register_params)
|
||||||
|
password = register_params[:password].strip
|
||||||
# 用户登录
|
|
||||||
def login
|
# gitea用户注册, email, username, password
|
||||||
Users::LoginForm.new(account_params).validate!
|
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||||
@user = User.try_to_login(params[:login], params[:password])
|
if interactor.success?
|
||||||
|
gitea_user = interactor.result
|
||||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
||||||
# user is already in local database
|
user.gitea_token = result['sha1']
|
||||||
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
user.gitea_uid = gitea_user[:body]['id']
|
||||||
|
if user.save!
|
||||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
UserExtension.create!(user_id: user.id)
|
||||||
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
successful_authentication(user)
|
||||||
|
render_ok
|
||||||
password_ok = @user.check_password?(params[:password].to_s)
|
end
|
||||||
unless password_ok
|
else
|
||||||
if login_control.remain_times-1 == 0
|
tip_exception(-1, interactor.error)
|
||||||
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
end
|
||||||
else
|
rescue Register::BaseForm::EmailError => e
|
||||||
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
render_error(-2, e.message)
|
||||||
end
|
rescue Register::BaseForm::LoginError => e
|
||||||
login_control.increment!
|
render_error(-3, e.message)
|
||||||
return
|
rescue Register::BaseForm::PhoneError => e
|
||||||
end
|
render_error(-4, e.message)
|
||||||
|
rescue Register::BaseForm::PasswordFormatError => e
|
||||||
successful_authentication(@user)
|
render_error(-5, e.message)
|
||||||
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
rescue Register::BaseForm::VerifiCodeError => e
|
||||||
|
render_error(-6, e.message)
|
||||||
# session[:user_id] = @user.id
|
rescue Exception => e
|
||||||
end
|
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
||||||
|
uid_logger_error(e.message)
|
||||||
def change_password
|
tip_exception(-1, e.message)
|
||||||
@user = User.find_by(login: params[:login])
|
end
|
||||||
return render_error("未找到相关用户!") if @user.blank?
|
end
|
||||||
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
|
||||||
|
# 用户登录
|
||||||
sync_params = {
|
def login
|
||||||
password: params[:password].to_s,
|
Users::LoginForm.new(account_params).validate!
|
||||||
email: @user.mail
|
@user = User.try_to_login(params[:login], params[:password])
|
||||||
}
|
|
||||||
|
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
# user is already in local database
|
||||||
if interactor.success?
|
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
||||||
@user.update_attribute(:password, params[:password])
|
|
||||||
render_ok
|
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||||
else
|
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
||||||
render_error(interactor.error)
|
|
||||||
end
|
password_ok = @user.check_password?(params[:password].to_s)
|
||||||
end
|
unless password_ok
|
||||||
|
if login_control.remain_times-1 == 0
|
||||||
# 忘记密码
|
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
||||||
def reset_password
|
else
|
||||||
begin
|
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
||||||
code = params[:code]
|
end
|
||||||
login_type = phone_mail_type(params[:login].strip)
|
login_control.increment!
|
||||||
# 获取验证码
|
return
|
||||||
if login_type == 1
|
end
|
||||||
phone = params[:login]
|
|
||||||
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last
|
successful_authentication(@user)
|
||||||
user = User.find_by_phone(phone)
|
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
||||||
else
|
|
||||||
email = params[:login]
|
# session[:user_id] = @user.id
|
||||||
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
|
end
|
||||||
user = User.find_by_mail(email) #这里有问题,应该是为email,而不是mail 6.13-hs
|
|
||||||
end
|
def change_password
|
||||||
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
|
@user = User.find_by(login: params[:login])
|
||||||
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
|
return render_error("未找到相关用户!") if @user.blank?
|
||||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
|
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
||||||
|
|
||||||
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
sync_params = {
|
||||||
ActiveRecord::Base.transaction do
|
password: params[:password].to_s,
|
||||||
user.save!
|
email: @user.mail,
|
||||||
LimitForbidControl::UserLogin.new(user).clear
|
login_name: @user.login,
|
||||||
end
|
source_id: 0
|
||||||
sucess_status
|
}
|
||||||
rescue Exception => e
|
|
||||||
uid_logger_error(e.message)
|
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||||
tip_exception(e.message)
|
if interactor.success?
|
||||||
end
|
@user.update_attribute(:password, params[:password])
|
||||||
end
|
render_ok
|
||||||
|
else
|
||||||
def successful_authentication(user)
|
render_error(interactor.error)
|
||||||
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
end
|
||||||
# Valid user
|
end
|
||||||
self.logged_user = user
|
|
||||||
# generate a key and set cookie if autologin
|
# 忘记密码
|
||||||
|
def reset_password
|
||||||
set_autologin_cookie(user)
|
begin
|
||||||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
code = params[:code]
|
||||||
user.update_column(:last_login_on, Time.now)
|
login_type = phone_mail_type(params[:login].strip)
|
||||||
session[:"#{default_yun_session}"] = user.id
|
# 获取验证码
|
||||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
if login_type == 1
|
||||||
# 注册完成后有一天的试用申请(先去掉)
|
phone = params[:login]
|
||||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last
|
||||||
end
|
user = User.find_by_phone(phone)
|
||||||
|
else
|
||||||
def set_autologin_cookie(user)
|
email = params[:login]
|
||||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
|
||||||
sync_user_token_to_trustie(user.login, token.value)
|
user = User.find_by_mail(email) #这里有问题,应该是为email,而不是mail 6.13-hs
|
||||||
|
end
|
||||||
cookie_options = {
|
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
|
||||||
:value => token.value,
|
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
|
||||||
:expires => 1.month.from_now,
|
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
|
||||||
:path => '/',
|
|
||||||
:secure => false,
|
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
||||||
:httponly => true
|
ActiveRecord::Base.transaction do
|
||||||
}
|
user.save!
|
||||||
if edu_setting('cookie_domain').present?
|
LimitForbidControl::UserLogin.new(user).clear
|
||||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
end
|
||||||
end
|
sucess_status
|
||||||
cookies[autologin_cookie_name] = cookie_options
|
rescue Exception => e
|
||||||
cookies.signed[:user_id] ||= user.id
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def logout
|
def successful_authentication(user)
|
||||||
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
||||||
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
# Valid user
|
||||||
logout_user
|
self.logged_user = user
|
||||||
render :json => {status: 1, message: "退出成功!"}
|
# generate a key and set cookie if autologin
|
||||||
end
|
|
||||||
|
set_autologin_cookie(user)
|
||||||
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||||
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
user.update_column(:last_login_on, Time.now)
|
||||||
def valid_email_and_phone
|
session[:"#{default_yun_session}"] = user.id
|
||||||
check_mail_and_phone_valid(params[:login], params[:type])
|
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||||
end
|
# 注册完成后有一天的试用申请(先去掉)
|
||||||
|
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||||
# 发送验证码
|
end
|
||||||
# params[:login] 手机号或者邮箱号
|
|
||||||
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
def set_autologin_cookie(user)
|
||||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
sync_user_token_to_trustie(user.login, token.value)
|
||||||
def get_verification_code
|
|
||||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
cookie_options = {
|
||||||
value = params[:login]
|
:value => token.value,
|
||||||
type = params[:type].strip.to_i
|
:expires => 1.month.from_now,
|
||||||
login_type = phone_mail_type(value)
|
:path => '/',
|
||||||
send_type = verify_type(login_type, type)
|
:secure => false,
|
||||||
verification_code = code.sample(6).join
|
:httponly => true
|
||||||
|
}
|
||||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
if edu_setting('cookie_domain').present?
|
||||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||||
|
end
|
||||||
logger.info "########### 验证码:#{verification_code}"
|
cookies[autologin_cookie_name] = cookie_options
|
||||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
cookies.signed[:user_id] ||= user.id
|
||||||
|
|
||||||
# 记录验证码
|
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
||||||
check_verification_code(verification_code, send_type, value)
|
end
|
||||||
render_ok
|
|
||||||
end
|
def logout
|
||||||
|
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
||||||
# check user's login or email or phone is used
|
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
||||||
# params[:value] 手机号或者邮箱号或者登录名
|
logout_user
|
||||||
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
render :json => {status: 1, message: "退出成功!"}
|
||||||
def check
|
end
|
||||||
Register::CheckColumnsForm.new(check_params).validate!
|
|
||||||
render_ok
|
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
||||||
end
|
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
||||||
|
def valid_email_and_phone
|
||||||
private
|
check_mail_and_phone_valid(params[:login], params[:type])
|
||||||
|
end
|
||||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
|
||||||
# login_type 1:手机类型 2:邮箱类型
|
# 发送验证码
|
||||||
def verify_type login_type, type
|
# params[:login] 手机号或者邮箱号
|
||||||
case type
|
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||||
when 1
|
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||||
login_type == 1 ? 1 : 8
|
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||||
when 2
|
def get_verification_code
|
||||||
login_type == 1 ? 2 : 3
|
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||||
when 3
|
value = params[:login]
|
||||||
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
type = params[:type].strip.to_i
|
||||||
when 4
|
login_type = phone_mail_type(value)
|
||||||
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
send_type = verify_type(login_type, type)
|
||||||
when 5
|
verification_code = code.sample(6).join
|
||||||
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
|
|
||||||
end
|
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||||
end
|
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||||
|
|
||||||
def generate_login(login)
|
logger.info "########### 验证码:#{verification_code}"
|
||||||
type = phone_mail_type(login.strip)
|
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||||
|
|
||||||
if type == 1
|
# 记录验证码
|
||||||
uid_logger("start register by phone: type is #{type}")
|
check_verification_code(verification_code, send_type, value)
|
||||||
pre = 'p'
|
render_ok
|
||||||
email = nil
|
end
|
||||||
phone = login
|
|
||||||
else
|
# check user's login or email or phone is used
|
||||||
uid_logger("start register by email: type is #{type}")
|
# params[:value] 手机号或者邮箱号或者登录名
|
||||||
pre = 'm'
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
email = login
|
def check
|
||||||
phone = nil
|
Register::CheckColumnsForm.new(check_params).validate!
|
||||||
end
|
render_ok
|
||||||
code = generate_identifier User, 8, pre
|
end
|
||||||
|
|
||||||
{ login: pre + code, email: email, phone: phone }
|
def login_check
|
||||||
end
|
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
|
||||||
|
render_ok
|
||||||
def user_params
|
end
|
||||||
params.require(:user).permit(:login, :email, :phone)
|
|
||||||
end
|
private
|
||||||
|
|
||||||
def account_params
|
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||||
params.require(:account).permit(:login, :password)
|
# login_type 1:手机类型 2:邮箱类型
|
||||||
end
|
def verify_type login_type, type
|
||||||
|
case type
|
||||||
def check_params
|
when 1
|
||||||
params.permit(:type, :value)
|
login_type == 1 ? 1 : 8
|
||||||
end
|
when 2
|
||||||
|
login_type == 1 ? 2 : 3
|
||||||
def register_params
|
when 3
|
||||||
params.permit(:login, :namespace, :password, :code)
|
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
||||||
end
|
when 4
|
||||||
|
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
||||||
end
|
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 sync_gitea_params
|
||||||
|
params.permit(:login, :email, :password)
|
||||||
|
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
|
||||||
|
|
|
@ -1,10 +1,33 @@
|
||||||
class Admins::DashboardsController < Admins::BaseController
|
class Admins::DashboardsController < Admins::BaseController
|
||||||
def index
|
def index
|
||||||
@active_user_count = User.where(last_login_on: today).count
|
# 用户活跃数
|
||||||
@weekly_active_user_count = User.where(last_login_on: current_week).count
|
day_user_ids = CommitLog.where(created_at: today).pluck(:user_id).uniq
|
||||||
@month_active_user_count = User.where(last_login_on: current_month).count
|
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
|
end
|
||||||
|
|
||||||
def month_active_user
|
def month_active_user
|
||||||
|
@ -42,10 +65,14 @@ class Admins::DashboardsController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_week
|
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
|
end
|
||||||
|
|
||||||
def current_month
|
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
|
||||||
end
|
end
|
|
@ -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
|
|
@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
|
||||||
def create
|
def create
|
||||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
result = Admins::ImportUserService.call(params[:file].to_io)
|
result = Admins::ImportUserFromExcelService.call(params[:file].to_io)
|
||||||
render_ok(result)
|
render_ok(result)
|
||||||
rescue Admins::ImportUserService::Error => ex
|
rescue Admins::ImportUserService::Error => ex
|
||||||
render_error(ex)
|
render_error(ex)
|
||||||
|
|
|
@ -2,8 +2,24 @@ class Admins::MessageTemplatesController < Admins::BaseController
|
||||||
before_action :get_template, only: [:edit, :update, :destroy]
|
before_action :get_template, only: [:edit, :update, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
message_templates = MessageTemplate.group(:type).count.keys
|
message_templates = MessageTemplate.ransack(sys_notice_or_email_or_email_title_cont: params[:search]).result
|
||||||
@message_templates = kaminari_array_paginate(message_templates)
|
@message_templates = kaminari_paginate(message_templates)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@message_template = MessageTemplate.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
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@ -31,7 +47,9 @@ class Admins::MessageTemplatesController < Admins::BaseController
|
||||||
|
|
||||||
private
|
private
|
||||||
def message_template_params
|
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
|
end
|
||||||
|
|
||||||
def get_template
|
def get_template
|
||||||
|
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
||||||
class Admins::ProjectIgnoresController < Admins::BaseController
|
class Admins::ProjectIgnoresController < Admins::BaseController
|
||||||
before_action :set_ignore, only: [:edit,:update, :destroy,:show]
|
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
|
def index
|
||||||
sort_by = Ignore.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
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)
|
@project_ignore = Ignore.new(ignore_params)
|
||||||
|
|
||||||
if @project_ignore.save!
|
if @project_ignore.save
|
||||||
redirect_to admins_project_ignores_path
|
redirect_to admins_project_ignores_path
|
||||||
flash[:success] = "创建成功"
|
flash[:success] = "创建成功"
|
||||||
else
|
else
|
||||||
render :new
|
redirect_to admins_project_ignores_path
|
||||||
flash[:danger] = "创建失败"
|
flash[:danger] = @project_ignore.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ class Admins::ProjectIgnoresController < Admins::BaseController
|
||||||
redirect_to admins_project_ignores_path
|
redirect_to admins_project_ignores_path
|
||||||
flash[:success] = "更新成功"
|
flash[:success] = "更新成功"
|
||||||
else
|
else
|
||||||
render :edit
|
redirect_to admins_project_ignores_path
|
||||||
flash[:danger] = "更新失败"
|
flash[:danger] = @project_ignore.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,23 +98,23 @@ class Admins::ProjectIgnoresController < Admins::BaseController
|
||||||
params.require(:ignore).permit(:name,:content)
|
params.require(:ignore).permit(:name,:content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_params
|
# def validate_params
|
||||||
name = params[:ignore][:name]
|
# name = params[:ignore][:name]
|
||||||
if name.blank?
|
# if name.blank?
|
||||||
flash[:danger] = "名称不允许为空"
|
# flash[:danger] = "名称不允许为空"
|
||||||
redirect_to admins_project_ignores_path
|
# redirect_to admins_project_ignores_path
|
||||||
elsif check_ignore_present?(name) && @project_ignore.blank?
|
# elsif check_ignore_present?(name) && @project_ignore.blank?
|
||||||
flash[:danger] = "创建失败:名称已存在"
|
# flash[:danger] = "创建失败:名称已存在"
|
||||||
redirect_to admins_project_ignores_path
|
# redirect_to admins_project_ignores_path
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
|
||||||
def check_ignore_present?(name)
|
# def check_ignore_present?(name)
|
||||||
return true if name.blank?
|
# return true if name.blank?
|
||||||
name_downcase = name.downcase
|
# name_downcase = name.downcase
|
||||||
name_upcase = name.upcase
|
# name_upcase = name.upcase
|
||||||
name_first_big = name.capitalize
|
# name_first_big = name.capitalize
|
||||||
Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
|
# Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
|
||||||
end
|
# end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,17 +27,18 @@ class Admins::ProjectLanguagesController < Admins::BaseController
|
||||||
flash[:success] = '创建成功'
|
flash[:success] = '创建成功'
|
||||||
else
|
else
|
||||||
redirect_to admins_project_languages_path
|
redirect_to admins_project_languages_path
|
||||||
flash[:danger] = '创建失败'
|
flash[:danger] = @project_language.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if @project_language.update_attribute(:name, @name)
|
@project_language.attributes = {name: @name}
|
||||||
|
if @project_language.save
|
||||||
redirect_to admins_project_languages_path
|
redirect_to admins_project_languages_path
|
||||||
flash[:success] = '更新成功'
|
flash[:success] = '更新成功'
|
||||||
else
|
else
|
||||||
redirect_to admins_project_languages_path
|
redirect_to admins_project_languages_path
|
||||||
flash[:success] = '更新失败'
|
flash[:danger] = @project_language.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Admins::ProjectLicensesController < Admins::BaseController
|
class Admins::ProjectLicensesController < Admins::BaseController
|
||||||
before_action :set_license, only: [:edit,:update, :destroy,:show]
|
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
|
def index
|
||||||
sort_by = License.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
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
|
# position: max_position
|
||||||
# }
|
# }
|
||||||
@project_license = License.new(license_params)
|
@project_license = License.new(license_params)
|
||||||
|
if @project_license.save
|
||||||
if @project_license.save!
|
|
||||||
redirect_to admins_project_licenses_path
|
redirect_to admins_project_licenses_path
|
||||||
flash[:success] = "创建成功"
|
flash[:success] = "创建成功"
|
||||||
else
|
else
|
||||||
render :new
|
redirect_to admins_project_licenses_path
|
||||||
flash[:danger] = "创建失败"
|
flash[:danger] = @project_license.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -54,12 +53,13 @@ class Admins::ProjectLicensesController < Admins::BaseController
|
||||||
# permissions: permissions.to_s,
|
# permissions: permissions.to_s,
|
||||||
# limitations: limitations.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
|
redirect_to admins_project_licenses_path
|
||||||
flash[:success] = "更新成功"
|
flash[:success] = "更新成功"
|
||||||
else
|
else
|
||||||
render :edit
|
render admins_project_licenses_path
|
||||||
flash[:danger] = "更新失败"
|
flash[:danger] = @project_license.errors.full_messages.join(",")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,23 +98,23 @@ class Admins::ProjectLicensesController < Admins::BaseController
|
||||||
params.require(:license).permit(:name,:content)
|
params.require(:license).permit(:name,:content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_params
|
# def validate_params
|
||||||
name = params[:license][:name]
|
# name = params[:license][:name]
|
||||||
if name.blank?
|
# if name.blank?
|
||||||
flash[:danger] = "名称不允许为空"
|
# flash[:danger] = "名称不允许为空"
|
||||||
redirect_to admins_project_licenses_path
|
# redirect_to admins_project_licenses_path
|
||||||
elsif check_license_present?(name) && @project_license.blank?
|
# elsif check_license_present?(name) && @project_license.blank?
|
||||||
flash[:danger] = "创建失败:名称已存在"
|
# flash[:danger] = "创建失败:名称已存在"
|
||||||
redirect_to admins_project_licenses_path
|
# redirect_to admins_project_licenses_path
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
|
||||||
def check_license_present?(name)
|
# def check_license_present?(name)
|
||||||
return true if name.blank?
|
# return true if name.blank?
|
||||||
name_downcase = name.downcase
|
# name_downcase = name.downcase
|
||||||
name_upcase = name.upcase
|
# name_upcase = name.upcase
|
||||||
name_first_big = name.capitalize
|
# name_first_big = name.capitalize
|
||||||
License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
|
# License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
|
||||||
end
|
# end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
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 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
|
|
@ -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
|
|
@ -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]}, @project.owner&.gitea_token)
|
||||||
|
# puts @result_object
|
||||||
|
end
|
||||||
|
end
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -174,11 +174,11 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_profile_completed
|
def require_profile_completed
|
||||||
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
|
# tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_user_profile_completed(user)
|
def require_user_profile_completed(user)
|
||||||
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
|
# tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
|
||||||
end
|
end
|
||||||
|
|
||||||
# 异常提醒
|
# 异常提醒
|
||||||
|
@ -248,42 +248,57 @@ class ApplicationController < ActionController::Base
|
||||||
#return if params[:controller] == "main"
|
#return if params[:controller] == "main"
|
||||||
# Find the current user
|
# Find the current user
|
||||||
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
||||||
User.current = find_current_user
|
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
|
||||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
|
||||||
|
if @doorkeeper_token.present?
|
||||||
# 开放课程通过链接访问的用户
|
# client方法对接,需要一直带着用户标识uid
|
||||||
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
if @doorkeeper_token.resource_owner_id.blank?
|
||||||
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
|
||||||
|
User.current = User.find(params[:uid])
|
||||||
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
else
|
||||||
user = open_class_user
|
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
|
||||||
if user
|
|
||||||
start_user_session(user)
|
|
||||||
set_autologin_cookie(user)
|
|
||||||
end
|
end
|
||||||
User.current = user
|
|
||||||
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
|
||||||
|
end
|
||||||
|
|
||||||
|
if !User.current.logged? && Rails.env.development?
|
||||||
|
user = User.find 1
|
||||||
|
User.current = user
|
||||||
|
start_user_session(user)
|
||||||
|
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
|
||||||
end
|
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
|
|
||||||
# User.current = User.find 81403
|
# User.current = User.find 81403
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -686,7 +701,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
@project, @owner = Project.find_with_namespace(namespace, id)
|
@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"
|
logger.info "###########: has project and can read project"
|
||||||
@project
|
@project
|
||||||
# elsif @project && current_user.is_a?(AnonymousUser)
|
# elsif @project && current_user.is_a?(AnonymousUser)
|
||||||
|
@ -694,9 +709,15 @@ class ApplicationController < ActionController::Base
|
||||||
# @project = nil if !@project.is_public?
|
# @project = nil if !@project.is_public?
|
||||||
# render_forbidden and return
|
# render_forbidden and return
|
||||||
else
|
else
|
||||||
logger.info "###########:project not found"
|
if @project.present?
|
||||||
@project = nil
|
logger.info "###########: has project and but can't read project"
|
||||||
render_not_found and return
|
@project = nil
|
||||||
|
render_forbidden and return
|
||||||
|
else
|
||||||
|
logger.info "###########:project not found"
|
||||||
|
@project = nil
|
||||||
|
render_not_found and return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@project
|
@project
|
||||||
end
|
end
|
||||||
|
@ -709,14 +730,20 @@ class ApplicationController < ActionController::Base
|
||||||
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def image_type?(str)
|
||||||
|
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||||
|
default_type.include?(str&.downcase)
|
||||||
|
end
|
||||||
|
|
||||||
def convert_image!
|
def convert_image!
|
||||||
@image = params[:image]
|
@image = params[:image]
|
||||||
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
|
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
|
||||||
return unless @image.present?
|
return unless @image.present?
|
||||||
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
||||||
if @image.class == ActionDispatch::Http::UploadedFile
|
if @image.class == ActionDispatch::Http::UploadedFile
|
||||||
render_error('请上传文件') if @image.size.zero?
|
return render_error('请上传文件') if @image.size.zero?
|
||||||
render_error('文件大小超过限制') if @image.size > max_size.to_i
|
return render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||||
|
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
|
||||||
else
|
else
|
||||||
image = @image.to_s.strip
|
image = @image.to_s.strip
|
||||||
return render_error('请上传正确的图片') if image.blank?
|
return render_error('请上传正确的图片') if image.blank?
|
||||||
|
|
|
@ -1,261 +1,258 @@
|
||||||
#coding=utf-8
|
#coding=utf-8
|
||||||
#
|
#
|
||||||
# 文件上传
|
# 文件上传
|
||||||
class AttachmentsController < ApplicationController
|
class AttachmentsController < ApplicationController
|
||||||
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
||||||
before_action :find_file, only: %i[show destroy]
|
before_action :find_file, only: %i[show destroy]
|
||||||
before_action :attachment_candown, only: [:show]
|
before_action :attachment_candown, only: [:show]
|
||||||
skip_before_action :check_sign, only: [:show, :create]
|
skip_before_action :check_sign, only: [:show, :create]
|
||||||
|
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# 1. 优先跳到cdn
|
# 1. 优先跳到cdn
|
||||||
# 2. 如果没有cdn,send_file
|
# 2. 如果没有cdn,send_file
|
||||||
if @file.cloud_url.present?
|
if @file.cloud_url.present?
|
||||||
update_downloads(@file)
|
update_downloads(@file)
|
||||||
redirect_to @file.cloud_url and return
|
redirect_to @file.cloud_url and return
|
||||||
end
|
end
|
||||||
|
|
||||||
type_attachment = params[:disposition] || "attachment"
|
type_attachment = params[:disposition] || "attachment"
|
||||||
if type_attachment == "inline"
|
if type_attachment == "inline"
|
||||||
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
||||||
elsif type_attachment == "MP4"
|
elsif type_attachment == "MP4"
|
||||||
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
||||||
else
|
else
|
||||||
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
||||||
end
|
end
|
||||||
update_downloads(@file)
|
update_downloads(@file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def get_file
|
def get_file
|
||||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
url = 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)
|
if url.starts_with?(base_url) && !url.starts_with?("#{base_url}/repo")
|
||||||
domain = Gitea.gitea_config[:domain]
|
domain = GiteaService.gitea_config[:domain]
|
||||||
api_url = Gitea.gitea_config[:base_url]
|
api_url = GiteaService.gitea_config[:base_url]
|
||||||
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
|
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
|
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
|
||||||
response = Faraday.get(request_url)
|
response = Faraday.get(request_url)
|
||||||
filename = url.to_s.split("/").pop()
|
filename = url.to_s.split("/").pop()
|
||||||
else
|
else
|
||||||
response = Faraday.get(url)
|
response = Faraday.get(url)
|
||||||
filename = params[:download_url].to_s.split("/").pop()
|
filename = params[:download_url].to_s.split("/").pop()
|
||||||
end
|
end
|
||||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
# 1. 本地存储
|
# 1. 本地存储
|
||||||
# 2. 上传到云
|
# 2. 上传到云
|
||||||
begin
|
begin
|
||||||
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
||||||
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
||||||
raise "未上传文件" unless upload_file
|
raise "未上传文件" unless upload_file
|
||||||
|
|
||||||
folder = file_storage_directory
|
folder = file_storage_directory
|
||||||
raise "存储目录未定义" unless folder.present?
|
raise "存储目录未定义" unless folder.present?
|
||||||
|
|
||||||
month_folder = current_month_folder
|
month_folder = current_month_folder
|
||||||
save_path = File.join(folder, month_folder)
|
save_path = File.join(folder, month_folder)
|
||||||
|
|
||||||
ext = file_ext(upload_file.original_filename)
|
ext = file_ext(upload_file.original_filename)
|
||||||
|
|
||||||
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
||||||
|
|
||||||
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
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 = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
|
||||||
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
||||||
|
|
||||||
logger.info "local_path: #{local_path}"
|
logger.info "local_path: #{local_path}"
|
||||||
logger.info "remote_path: #{remote_path}"
|
logger.info "remote_path: #{remote_path}"
|
||||||
|
|
||||||
|
|
||||||
disk_filename = local_path[save_path.size + 1, local_path.size]
|
disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||||
#存数据库
|
#存数据库
|
||||||
#
|
#
|
||||||
@attachment = Attachment.where(disk_filename: disk_filename,
|
@attachment = Attachment.where(disk_filename: disk_filename,
|
||||||
author_id: current_user.id,
|
author_id: current_user.id,
|
||||||
cloud_url: remote_path).first
|
cloud_url: remote_path).first
|
||||||
if @attachment.blank?
|
if @attachment.blank?
|
||||||
@attachment = Attachment.new
|
@attachment = Attachment.new
|
||||||
@attachment.filename = upload_file.original_filename
|
@attachment.filename = upload_file.original_filename
|
||||||
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||||
@attachment.filesize = upload_file.tempfile.size
|
@attachment.filesize = upload_file.tempfile.size
|
||||||
@attachment.content_type = content_type
|
@attachment.content_type = content_type
|
||||||
@attachment.digest = digest
|
@attachment.digest = digest
|
||||||
@attachment.author_id = current_user.id
|
@attachment.author_id = current_user.id
|
||||||
@attachment.disk_directory = month_folder
|
@attachment.disk_directory = month_folder
|
||||||
@attachment.cloud_url = remote_path
|
@attachment.cloud_url = remote_path
|
||||||
@attachment.save!
|
@attachment.save!
|
||||||
else
|
else
|
||||||
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
||||||
end
|
end
|
||||||
|
|
||||||
render_json
|
render_json
|
||||||
rescue => e
|
rescue => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
begin
|
begin
|
||||||
@file_path = absolute_path(local_path(@file))
|
@file_path = absolute_path(local_path(@file))
|
||||||
#return normal_status(403, "") unless @file.author == current_user
|
#return normal_status(403, "") unless @file.author == current_user
|
||||||
@file.destroy!
|
@file.destroy!
|
||||||
|
|
||||||
delete_file(@file_path)
|
delete_file(@file_path)
|
||||||
normal_status("删除成功")
|
normal_status("删除成功")
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 附件为视频时,点击播放
|
# 附件为视频时,点击播放
|
||||||
def preview_attachment
|
def preview_attachment
|
||||||
attachment = Attachment.find_by(id: params[:id])
|
attachment = Attachment.find_by(id: params[:id])
|
||||||
dir_path = "#{Rails.root}/public/preview"
|
dir_path = "#{Rails.root}/public/preview"
|
||||||
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
||||||
if params[:status] == "preview"
|
if params[:status] == "preview"
|
||||||
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
||||||
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
||||||
else
|
else
|
||||||
normal_status(-1, "出现错误,请稍后重试")
|
normal_status(-1, "出现错误,请稍后重试")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
||||||
normal_status(1, "操作成功")
|
normal_status(1, "操作成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "出现错误,请稍后重试")
|
normal_status(-1, "出现错误,请稍后重试")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def find_file
|
def find_file
|
||||||
@file =
|
@file =
|
||||||
if params[:type] == 'history'
|
if params[:type] == 'history'
|
||||||
AttachmentHistory.find params[:id]
|
AttachmentHistory.find params[:id]
|
||||||
else
|
else
|
||||||
Attachment.find params[:id]
|
Attachment.find params[:id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_file(file_path)
|
def delete_file(file_path)
|
||||||
File.delete(file_path) if File.exist?(file_path)
|
File.delete(file_path) if File.exist?(file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_month_folder
|
def current_month_folder
|
||||||
date = Time.now
|
date = Time.now
|
||||||
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_ext(file_name)
|
def file_ext(file_name)
|
||||||
ext = ''
|
ext = ''
|
||||||
exts = file_name.split(".")
|
exts = file_name.split(".")
|
||||||
if exts.size > 1
|
if exts.size > 1
|
||||||
ext = ".#{exts.last}"
|
ext = ".#{exts.last}"
|
||||||
end
|
end
|
||||||
ext
|
ext
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_save_to_local(save_path, temp_file, ext)
|
def file_save_to_local(save_path, temp_file, ext)
|
||||||
unless Dir.exists?(save_path)
|
unless Dir.exists?(save_path)
|
||||||
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
||||||
end
|
end
|
||||||
|
|
||||||
digest = md5_file(temp_file)
|
digest = md5_file(temp_file)
|
||||||
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
||||||
local_file_path = File.join(save_path, digest) + ext
|
local_file_path = File.join(save_path, digest) + ext
|
||||||
save_temp_file(temp_file, local_file_path)
|
save_temp_file(temp_file, local_file_path)
|
||||||
|
|
||||||
[local_file_path, digest]
|
[local_file_path, digest]
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_temp_file(temp_file, save_file_path)
|
def save_temp_file(temp_file, save_file_path)
|
||||||
File.open(save_file_path, 'wb') do |f|
|
File.open(save_file_path, 'wb') do |f|
|
||||||
temp_file.rewind
|
temp_file.rewind
|
||||||
while (buffer = temp_file.read(8192))
|
while (buffer = temp_file.read(8192))
|
||||||
f.write(buffer)
|
f.write(buffer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def md5_file(temp_file)
|
def md5_file(temp_file)
|
||||||
md5 = Digest::MD5.new
|
md5 = Digest::MD5.new
|
||||||
temp_file.rewind
|
temp_file.rewind
|
||||||
while (buffer = temp_file.read(8192))
|
while (buffer = temp_file.read(8192))
|
||||||
md5.update(buffer)
|
md5.update(buffer)
|
||||||
end
|
end
|
||||||
md5.hexdigest
|
md5.hexdigest
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_save_to_ucloud(path, file, content_type)
|
def file_save_to_ucloud(path, file, content_type)
|
||||||
ufile = Gitlink::Ufile.new(
|
ufile = Gitlink::Ufile.new(
|
||||||
ucloud_public_key: edu_setting('public_key'),
|
ucloud_public_key: edu_setting('public_key'),
|
||||||
ucloud_private_key: edu_setting('private_key'),
|
ucloud_private_key: edu_setting('private_key'),
|
||||||
ucloud_public_read: true,
|
ucloud_public_read: true,
|
||||||
ucloud_public_bucket: edu_setting('public_bucket'),
|
ucloud_public_bucket: edu_setting('public_bucket'),
|
||||||
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
||||||
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
||||||
)
|
)
|
||||||
File.open(file) do |f|
|
File.open(file) do |f|
|
||||||
ufile.put(path, f, 'Content-Type' => content_type)
|
ufile.put(path, f, 'Content-Type' => content_type)
|
||||||
end
|
end
|
||||||
edu_setting('public_cdn_host') + "/" + path
|
edu_setting('public_cdn_host') + "/" + path
|
||||||
end
|
end
|
||||||
|
|
||||||
def attachment_candown
|
def attachment_candown
|
||||||
unless current_user.admin? || current_user.business?
|
unless current_user.admin? || current_user.business?
|
||||||
candown = true
|
candown = true
|
||||||
unless params[:type] == 'history'
|
if @file.container
|
||||||
if @file.container && current_user.logged?
|
if @file.container.is_a?(Issue)
|
||||||
if @file.container.is_a?(Issue)
|
project = @file.container.project
|
||||||
course = @file.container.project
|
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||||
candown = course.member?(current_user)
|
elsif @file.container.is_a?(Journal)
|
||||||
elsif @file.container.is_a?(Journal)
|
project = @file.container.issue.project
|
||||||
course = @file.container.issue.project
|
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||||
candown = course.member?(current_user)
|
else
|
||||||
else
|
project = nil
|
||||||
course = nil
|
end
|
||||||
end
|
tip_exception(403, "您没有权限进入") if project.present? && !candown
|
||||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
end
|
||||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
def send_file_with_range(path, options = {})
|
||||||
end
|
logger.info("########request.headers: #{request.headers}")
|
||||||
|
logger.info("########request.headers: #{File.exist?(path)}")
|
||||||
def send_file_with_range(path, options = {})
|
|
||||||
logger.info("########request.headers: #{request.headers}")
|
if File.exist?(path)
|
||||||
logger.info("########request.headers: #{File.exist?(path)}")
|
size = File.size(path)
|
||||||
|
logger.info("########request.headers: #{request.headers}")
|
||||||
if File.exist?(path)
|
if !request.headers["Range"]
|
||||||
size = File.size(path)
|
status_code = 200 # 200 OK
|
||||||
logger.info("########request.headers: #{request.headers}")
|
offset = 0
|
||||||
if !request.headers["Range"]
|
length = File.size(path)
|
||||||
status_code = 200 # 200 OK
|
else
|
||||||
offset = 0
|
status_code = 206 # 206 Partial Content
|
||||||
length = File.size(path)
|
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
||||||
else
|
offset = bytes.begin
|
||||||
status_code = 206 # 206 Partial Content
|
length = bytes.end - bytes.begin
|
||||||
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
end
|
||||||
offset = bytes.begin
|
response.header["Accept-Ranges"] = "bytes"
|
||||||
length = bytes.end - bytes.begin
|
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
||||||
end
|
response.header["status"] = status_code
|
||||||
response.header["Accept-Ranges"] = "bytes"
|
|
||||||
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
send_data IO.binread(path, length, offset), options
|
||||||
response.header["status"] = status_code
|
else
|
||||||
|
raise ActionController::MissingFile, "Cannot read file #{path}."
|
||||||
send_data IO.binread(path, length, offset), options
|
end
|
||||||
else
|
end
|
||||||
raise ActionController::MissingFile, "Cannot read file #{path}."
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
|
||||||
namespace = params[:owner]
|
namespace = params[:owner]
|
||||||
id = params[:repo] || params[:id]
|
id = params[:repo] || params[:id]
|
||||||
|
|
||||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
|
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id, current_user.login)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_all_repo
|
def load_all_repo
|
||||||
|
|
|
@ -14,12 +14,12 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
flag, msg = check_bind_cloud_account!
|
flag, msg = check_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = bind_account!
|
@cloud_account = bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
|
@ -27,17 +27,17 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate
|
def activate
|
||||||
return render_error('请先认证') unless current_user.ci_certification?
|
return tip_exception('请先认证') unless current_user.ci_certification?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@cloud_account = Ci::CloudAccount.find params[:id]
|
@cloud_account = Ci::CloudAccount.find params[:id]
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
if @repo
|
if @repo
|
||||||
return render_error('该项目已经激活') if @repo.repo_active?
|
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||||
@repo.activate!(@project)
|
@repo.activate!(@project)
|
||||||
else
|
else
|
||||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||||
|
@ -50,7 +50,7 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,39 +59,39 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
|
|
||||||
def bind
|
def bind
|
||||||
flag, msg = check_bind_cloud_account!
|
flag, msg = check_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = bind_account!
|
@cloud_account = bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def trustie_bind
|
def trustie_bind
|
||||||
account = params[:account].to_s
|
account = params[:account].to_s
|
||||||
return render_error("account不能为空.") if account.blank?
|
return tip_exception("account不能为空.") if account.blank?
|
||||||
|
|
||||||
flag, msg = check_trustie_bind_cloud_account!
|
flag, msg = check_trustie_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = trustie_bind_account!
|
@cloud_account = trustie_bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unbind
|
def unbind
|
||||||
|
@ -107,18 +107,18 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def oauth_grant
|
def oauth_grant
|
||||||
password = params[:password].to_s
|
password = params[:password].to_s
|
||||||
return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
|
return tip_exception('你输入的密码不正确.') unless current_user.check_password?(password)
|
||||||
|
|
||||||
oauth = current_user.oauths.last
|
oauth = current_user.oauths.last
|
||||||
return render_error("服务器出小差了.") if oauth.blank?
|
return tip_exception("服务器出小差了.") if oauth.blank?
|
||||||
|
|
||||||
result = gitea_oauth_grant!(password, oauth)
|
result = gitea_oauth_grant!(password, oauth)
|
||||||
return render_error('授权失败.') unless result === true
|
return tip_exception('授权失败.') unless result === true
|
||||||
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
|
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
|
||||||
if size > 0
|
if size > 0
|
||||||
render_error("#{params[:branch]}分支已经存在流水线!")
|
tip_exception("#{params[:branch]}分支已经存在流水线!")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
|
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
|
||||||
|
@ -53,7 +53,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok({id: pipeline.id})
|
render_ok({id: pipeline.id})
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 在代码库创建文件
|
# 在代码库创建文件
|
||||||
|
@ -81,6 +81,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
repo_branch: pipeline.branch,
|
repo_branch: pipeline.branch,
|
||||||
repo_config: pipeline.file_name
|
repo_config: pipeline.file_name
|
||||||
}
|
}
|
||||||
|
Rails.logger.info("########create_params===#{create_params.to_json}")
|
||||||
repo = Ci::Repo.create_repo(create_params)
|
repo = Ci::Repo.create_repo(create_params)
|
||||||
repo
|
repo
|
||||||
end
|
end
|
||||||
|
@ -118,7 +119,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -132,7 +133,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def content
|
def content
|
||||||
|
@ -182,7 +183,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage
|
def update_stage
|
||||||
|
@ -192,7 +193,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_stage
|
def delete_stage
|
||||||
|
@ -205,7 +206,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage_index(pipeline_id, show_index, diff)
|
def update_stage_index(pipeline_id, show_index, diff)
|
||||||
|
@ -229,7 +230,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
unless steps.empty?
|
unless steps.empty?
|
||||||
steps.each do |step|
|
steps.each do |step|
|
||||||
unless step[:template_id]
|
unless step[:template_id]
|
||||||
render_error('请选择模板!')
|
tip_exception('请选择模板!')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if !step[:id]
|
if !step[:id]
|
||||||
|
@ -246,7 +247,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_stage_step
|
def create_stage_step
|
||||||
|
@ -262,7 +263,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage_step
|
def update_stage_step
|
||||||
|
@ -279,7 +280,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_stage_step
|
def delete_stage_step
|
||||||
|
@ -289,6 +290,6 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,19 +30,19 @@ class Ci::ProjectsController < Ci::BaseController
|
||||||
@file = interactor.result
|
@file = interactor.result
|
||||||
render_result(1, "更新成功")
|
render_result(1, "更新成功")
|
||||||
else
|
else
|
||||||
render_error(interactor.error)
|
tip_exception(interactor.error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate
|
def activate
|
||||||
return render_error('你还未认证') unless current_user.ci_certification?
|
return tip_exception('你还未认证') unless current_user.ci_certification?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
if @repo
|
if @repo
|
||||||
return render_error('该项目已经激活') if @repo.repo_active?
|
@repo.destroy! if @repo&.repo_user_id == 0
|
||||||
|
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||||
@repo.activate!(@project)
|
@repo.activate!(@project)
|
||||||
return render_ok
|
|
||||||
else
|
else
|
||||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||||
@ci_user.update_column(:user_syncing, false)
|
@ci_user.update_column(:user_syncing, false)
|
||||||
|
@ -55,12 +55,12 @@ class Ci::ProjectsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deactivate
|
def deactivate
|
||||||
return render_error('该项目已经取消激活') if !@repo.repo_active?
|
return tip_exception('该项目已经取消激活') if !@repo.repo_active?
|
||||||
|
|
||||||
@project.update_column(:open_devops, false)
|
@project.update_column(:open_devops, false)
|
||||||
@repo.deactivate_repos!
|
@repo.deactivate_repos!
|
||||||
|
|
|
@ -20,14 +20,14 @@ class Ci::SecretsController < Ci::BaseController
|
||||||
if result["id"]
|
if result["id"]
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error(result["message"])
|
tip_exception(result["message"])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
||||||
if result["id"]
|
if result["id"]
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error(result["message"])
|
tip_exception(result["message"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -39,14 +39,14 @@ class Ci::SecretsController < Ci::BaseController
|
||||||
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error("参数名不能为空")
|
tip_exception("参数名不能为空")
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def ci_drone_url
|
def ci_drone_url
|
||||||
user = User.find_by(login: params[:owner])
|
user = User.find_by(login: params[:owner]) || User.find_by(login: current_user.login)
|
||||||
user&.ci_cloud_account.drone_url
|
user&.ci_cloud_account.drone_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -63,7 +63,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
)
|
)
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -73,7 +73,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
#======流水线模板查询=====#
|
#======流水线模板查询=====#
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
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)
|
||||||
|
# 统计数据新增
|
||||||
|
CacheAsyncSetJob.perform_later("project_common_service", {commits: 1}, project.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,26 +6,37 @@ class CompareController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
load_compare_params
|
if params[:type] == "sha"
|
||||||
compare
|
load_compare_params
|
||||||
@merge_status, @merge_message = get_merge_message
|
@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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def get_merge_message
|
|
||||||
|
def get_merge_message
|
||||||
if @base.blank? || @head.blank?
|
if @base.blank? || @head.blank?
|
||||||
return -2, "请选择分支"
|
return -2, "请选择分支"
|
||||||
else
|
else
|
||||||
|
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||||
if @head.include?(":")
|
if @head.include?(":")
|
||||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
fork_project = @project.forked_projects.joins(:owner).where(users: { login: @head.to_s.split("/")[0] }).take
|
||||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||||
@exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take
|
@exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take
|
||||||
else
|
else
|
||||||
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
|
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).last
|
||||||
end
|
end
|
||||||
if @exist_pullrequest.present?
|
if @exist_pullrequest.present?
|
||||||
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
|
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
|
||||||
else
|
else
|
||||||
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
|
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
|
||||||
return -2, "分支内容相同,无需创建合并请求"
|
return -2, "分支内容相同,无需创建合并请求"
|
||||||
end
|
end
|
||||||
|
@ -42,12 +53,22 @@ class CompareController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_compare_params
|
def load_compare_params
|
||||||
@base = Addressable::URI.unescape(params[:base])
|
# @base = Addressable::URI.unescape(params[:base])
|
||||||
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
|
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
|
||||||
|
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
|
||||||
|
# @head = Addressable::URI.unescape(@head)
|
||||||
|
@head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head)
|
||||||
end
|
end
|
||||||
|
|
||||||
def gitea_compare(base, head)
|
def gitea_compare(base, head)
|
||||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
|
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_size
|
||||||
|
params.fetch(:page, 1).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_limit
|
||||||
|
params.fetch(:limit, 15).to_i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,15 +18,15 @@ module Acceleratorable
|
||||||
end
|
end
|
||||||
|
|
||||||
def accelerator_domain
|
def accelerator_domain
|
||||||
Gitea.gitea_config[:accelerator]["domain"]
|
GiteaService.gitea_config[:accelerator]["domain"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def accelerator_username
|
def accelerator_username
|
||||||
Gitea.gitea_config[:accelerator]["access_key_id"]
|
GiteaService.gitea_config[:accelerator]["access_key_id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def config_accelerator?
|
def config_accelerator?
|
||||||
Gitea.gitea_config[:accelerator].present?
|
GiteaService.gitea_config[:accelerator].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_foreign_url?(clone_addr)
|
def is_foreign_url?(clone_addr)
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -160,9 +160,9 @@ module Ci::CloudAccountManageable
|
||||||
state = SecureRandom.hex(8)
|
state = SecureRandom.hex(8)
|
||||||
# redirect_uri eg:
|
# redirect_uri eg:
|
||||||
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
||||||
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
# redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
||||||
clientId = client_id(oauth)
|
# clientId = client_id(oauth)
|
||||||
grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{clientId}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
|
grant_url = "#{@cloud_account.drone_url}/login"
|
||||||
logger.info "[gitea] grant_url: #{grant_url}"
|
logger.info "[gitea] grant_url: #{grant_url}"
|
||||||
|
|
||||||
conn = Faraday.new(url: grant_url) do |req|
|
conn = Faraday.new(url: grant_url) do |req|
|
||||||
|
@ -188,6 +188,7 @@ module Ci::CloudAccountManageable
|
||||||
response = conn.get
|
response = conn.get
|
||||||
logger.info "[drone] response headers: #{response.headers}"
|
logger.info "[drone] response headers: #{response.headers}"
|
||||||
|
|
||||||
|
# true
|
||||||
response.headers['location'].include?('error') ? false : true
|
response.headers['location'].include?('error') ? false : true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,15 @@ module LaboratoryHelper
|
||||||
# my_projects: "/users/#{current_user.try(:login)}/projects",
|
# my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||||
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
|
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
|
||||||
{
|
{
|
||||||
new_syllabuses: "https://www.trustie.net/syllabuses/new",
|
new_syllabuses: "https://forge.educoder.net/syllabuses/new",
|
||||||
new_course: "https://www.trustie.net/courses/new",
|
new_course: "https://forge.educoder.net/courses/new",
|
||||||
edit_account: "https://www.trustie.net/my/account",
|
edit_account: "https://forge.educoder.net/my/account",
|
||||||
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
my_courses: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_courselist",
|
||||||
my_projects: "/users/#{current_user.try(:login)}/projects",
|
my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||||
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
my_organ: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_organizations",
|
||||||
default_url: Rails.application.config_for(:configuration)['platform_url'],
|
default_url: "https://www.educoder.net/",
|
||||||
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
|
tiding_url: "https://www.educoder.net/users/#{current_user.try(:login)}/user_tidings",
|
||||||
register_url: "https://www.trustie.net/login?login=false"
|
register_url: "https://www.educoder.net/user/register"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ module LoginHelper
|
||||||
|
|
||||||
def set_autologin_cookie(user)
|
def set_autologin_cookie(user)
|
||||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||||
sync_user_token_to_trustie(user.login, token.value)
|
# 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 "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
|
||||||
cookie_options = {
|
cookie_options = {
|
||||||
|
@ -108,10 +108,15 @@ module LoginHelper
|
||||||
def sync_pwd_to_gitea!(user, hash={})
|
def sync_pwd_to_gitea!(user, hash={})
|
||||||
return true if user.is_sync_pwd?
|
return true if user.is_sync_pwd?
|
||||||
|
|
||||||
sync_params = { email: user.mail }
|
sync_params = {
|
||||||
|
login_name: user.name,
|
||||||
|
source_id: 0,
|
||||||
|
email: user.mail
|
||||||
|
}
|
||||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
||||||
if interactor.success?
|
if interactor.success?
|
||||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
||||||
|
user.update_column(:is_sync_pwd, true)
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
|
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
|
||||||
|
|
|
@ -1,30 +1,82 @@
|
||||||
module RegisterHelper
|
module RegisterHelper
|
||||||
extend ActiveSupport::Concern
|
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}
|
result = {message: nil, user: nil}
|
||||||
|
email = email.blank? ? "#{username}@example.org" : email
|
||||||
|
|
||||||
user = User.new(admin: false, login: username, mail: email, type: "User")
|
user = User.new(admin: false, login: username, mail: email, type: "User")
|
||||||
user.password = password
|
user.password = password
|
||||||
user.platform = platform
|
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?
|
return unless user.valid?
|
||||||
|
|
||||||
|
create_gitea_user!(user, username, email, password)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_gitea_user!(forge_user, username, email, password=random_password)
|
||||||
|
|
||||||
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
||||||
if interactor.success?
|
result = {}
|
||||||
gitea_user = interactor.result
|
if interactor.success? || interactor.result[:message].to_s.include?("已被注册")
|
||||||
result = Gitea::User::GenerateTokenService.call(username, password)
|
gitea_user = interactor.result[:message].to_s.include?("已被注册") ? Gitea::User::GetService.call(username, password) : interactor.result
|
||||||
user.gitea_token = result['sha1']
|
Rails.logger.info "##### [gitea] create_gitea_user result: #{gitea_user}"
|
||||||
user.gitea_uid = gitea_user[:body]['id']
|
if gitea_user[:body].present?
|
||||||
if user.save!
|
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||||
UserExtension.create!(user_id: user.id)
|
forge_user.gitea_token = result['sha1']
|
||||||
result[:user] = {id: user.id, token: user.gitea_token}
|
forge_user.gitea_uid = gitea_user[:body]['id'] if gitea_user[:body].present? && gitea_user[:body]['id'] !=0
|
||||||
|
forge_user.mail = email
|
||||||
|
if forge_user.save
|
||||||
|
UserExtension.create!(user_id: forge_user.id) if forge_user.user_extension.blank?
|
||||||
|
result[:user] = {id: forge_user.id, token: forge_user.gitea_token}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result[:message] = interactor.result[:message]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
result[:message] = interactor.error
|
Rails.logger.info "##### [gitea] create_gitea_user result: #{interactor.result[:message]}"
|
||||||
|
result[:message] = interactor.result[:message]
|
||||||
end
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def random_password
|
||||||
|
"#{Random.rand(11111111)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def auto_update(user, params={})
|
||||||
|
return if params.blank?
|
||||||
|
result = {message: nil, user: nil}
|
||||||
|
before_login = user.login
|
||||||
|
user.login = params[:username]
|
||||||
|
user.password = params[:password]
|
||||||
|
user.mail = params[:email]
|
||||||
|
|
||||||
|
if user.save!
|
||||||
|
sync_params = {
|
||||||
|
password: params[:password].to_s,
|
||||||
|
email: params[:email],
|
||||||
|
login_name: params[:username],
|
||||||
|
new_name: params[:username],
|
||||||
|
source_id: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||||
|
if interactor.success?
|
||||||
|
result[:user] = user
|
||||||
|
else
|
||||||
|
result[:message] = '用户同步Gitea失败!'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result[:message] = user.errors.full_messages.join(",")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ module RenderHelper
|
||||||
render json: { status: 0, message: 'success' }.merge(data)
|
render json: { status: 0, message: 'success' }.merge(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_error(status = -1, message = '')
|
def render_error(message = '', status=-1)
|
||||||
render json: { status: status, message: message }
|
render json: { status: status, message: message }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,26 @@ module Repository::LanguagesPercentagable
|
||||||
result = Gitea::Repository::Languages::ListService.call(@owner.login,
|
result = Gitea::Repository::Languages::ListService.call(@owner.login,
|
||||||
@repository.identifier, current_user&.gitea_token)
|
@repository.identifier, current_user&.gitea_token)
|
||||||
|
|
||||||
result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
@transform_language = @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
|
||||||
|
update_project_language(@transform_language) unless @transform_language.nil?
|
||||||
|
@transform_language
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_project_language(language)
|
||||||
|
db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
|
||||||
|
@project.update_column(:project_language_id, db_language.id) if @project.project_language_id.nil?
|
||||||
|
rescue
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}
|
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}
|
||||||
|
|
|
@ -6,14 +6,23 @@ class ForksController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call
|
@new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call
|
||||||
|
|
||||||
|
# TODO: fix Educoder shixun
|
||||||
|
if @new_project.persisted?
|
||||||
|
ProjectScore.create(:project_id => @new_project.id, :score => 0) if @new_project.project_score.nil?
|
||||||
|
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @new_project.id)
|
||||||
|
@project.project_infos << project_info
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def authenticate_project!
|
def authenticate_project!
|
||||||
|
Rails.logger.info "authenticate_project1=======================#{current_user&.id},#{@project.user_id}"
|
||||||
|
Rails.logger.info "authenticate_project2=======================#{current_user&.id == @project.user_id}"
|
||||||
if current_user&.id == @project.user_id
|
if current_user&.id == @project.user_id
|
||||||
render_result(-1, "自己不能fork自己的项目")
|
render_result(-1, "自己不能fork自己的项目")
|
||||||
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
|
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
|
||||||
render_result(-1, "fork失败,你已拥有了这个项目")
|
render_result(0, "fork失败,你已拥有了这个项目")
|
||||||
end
|
end
|
||||||
# return if current_user != @project.owner
|
# return if current_user != @project.owner
|
||||||
# render_result(-1, "自己不能fork自己的项目")
|
# render_result(-1, "自己不能fork自己的项目")
|
||||||
|
|
|
@ -2,12 +2,12 @@ class IssueTagsController < ApplicationController
|
||||||
before_action :require_login, except: [:index]
|
before_action :require_login, except: [:index]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
before_action :check_issue_permission, except: :index
|
before_action :check_issue_tags_permission
|
||||||
before_action :set_issue_tag, only: [:edit, :update, :destroy]
|
before_action :set_issue_tag, only: [:edit, :update, :destroy]
|
||||||
|
|
||||||
|
|
||||||
def index
|
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))
|
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||||
@page = params[:page] || 1
|
@page = params[:page] || 1
|
||||||
@limit = params[:limit] || 15
|
@limit = params[:limit] || 15
|
||||||
|
@ -17,7 +17,7 @@ class IssueTagsController < ApplicationController
|
||||||
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
title = params[:name].to_s.strip.first(10)
|
title = params[:name].to_s.strip.first(15)
|
||||||
desc = params[:description].to_s.first(30)
|
desc = params[:description].to_s.first(30)
|
||||||
color = params[:color] || "#ccc"
|
color = params[:color] || "#ccc"
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class IssueTagsController < ApplicationController
|
||||||
|
|
||||||
if title.present?
|
if title.present?
|
||||||
if IssueTag.exists?(name: title, project_id: @project.id)
|
if IssueTag.exists?(name: title, project_id: @project.id)
|
||||||
normal_status(-1, "标签已存在")
|
normal_status(-1, "项目标记已存在")
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
|
@ -37,12 +37,12 @@ class IssueTagsController < ApplicationController
|
||||||
if issue_tag.save
|
if issue_tag.save
|
||||||
# gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
|
# gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
|
||||||
# if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
|
# if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
|
||||||
# normal_status(0, "标签创建成功")
|
normal_status(0, "项目标记创建成功!")
|
||||||
# else
|
# else
|
||||||
# normal_status(-1, "标签创建失败")
|
# normal_status(-1, "项目标记创建失败")
|
||||||
# end
|
# end
|
||||||
else
|
else
|
||||||
normal_status(-1, "标签创建失败")
|
normal_status(-1, "项目标记创建失败")
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "create version release error: #{e.message}"
|
puts "create version release error: #{e.message}"
|
||||||
|
@ -51,7 +51,7 @@ class IssueTagsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
normal_status(-1, "标签名称不能为空")
|
normal_status(-1, "项目标记名称不能为空")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ class IssueTagsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
title = params[:name]
|
title = params[:name].to_s.strip.first(15)
|
||||||
desc = params[:description]
|
desc = params[:description].to_s.first(30)
|
||||||
color = params[:color] || "#ccc"
|
color = params[:color] || "#ccc"
|
||||||
|
|
||||||
tag_params = {
|
tag_params = {
|
||||||
|
@ -71,19 +71,19 @@ class IssueTagsController < ApplicationController
|
||||||
}
|
}
|
||||||
if title.present?
|
if title.present?
|
||||||
if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title)
|
if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title)
|
||||||
normal_status(-1, "标签已存在")
|
normal_status(-1, "项目标记已存在")
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
if @issue_tag.update_attributes(tag_params)
|
if @issue_tag.update_attributes(tag_params)
|
||||||
# gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
|
# gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
|
||||||
# if gitea_tag
|
# if gitea_tag
|
||||||
# normal_status(0, "标签更新成功")
|
# normal_status(0, "项目标记更新成功")
|
||||||
# else
|
# else
|
||||||
# normal_status(-1, "标签更新失败")
|
# normal_status(-1, "项目标记更新失败")
|
||||||
# end
|
# end
|
||||||
else
|
else
|
||||||
normal_status(-1, "标签更新失败")
|
normal_status(-1, "项目标记更新失败")
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "create version release error: #{e.message}"
|
puts "create version release error: #{e.message}"
|
||||||
|
@ -92,7 +92,7 @@ class IssueTagsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
normal_status(-1, "标签名称不能为空")
|
normal_status(-1, "项目标记名称不能为空")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -102,12 +102,12 @@ class IssueTagsController < ApplicationController
|
||||||
if @issue_tag.destroy
|
if @issue_tag.destroy
|
||||||
# issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
|
# issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
|
||||||
# if issue_tag
|
# if issue_tag
|
||||||
# normal_status(0, "标签删除成功")
|
# normal_status(0, "项目标记删除成功")
|
||||||
# else
|
# else
|
||||||
# normal_status(-1, "标签删除失败")
|
# normal_status(-1, "项目标记删除失败")
|
||||||
# end
|
# end
|
||||||
else
|
else
|
||||||
normal_status(-1, "标签删除失败")
|
normal_status(-1, "项目标记删除失败")
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "create version release error: #{e.message}"
|
puts "create version release error: #{e.message}"
|
||||||
|
@ -122,16 +122,16 @@ class IssueTagsController < ApplicationController
|
||||||
@user = @project.owner
|
@user = @project.owner
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_issue_permission
|
def check_issue_tags_permission
|
||||||
unless @project.member?(current_user) || current_user.admin?
|
unless @project.manager?(current_user) || current_user.admin?
|
||||||
normal_status(-1, "您没有权限")
|
return render_forbidden('你不是管理员,没有权限操作')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_issue_tag
|
def set_issue_tag
|
||||||
@issue_tag = IssueTag.find_by_id(params[:id])
|
@issue_tag = IssueTag.find_by_id(params[:id])
|
||||||
unless @issue_tag.present?
|
unless @issue_tag.present?
|
||||||
normal_status(-1, "标签不存在")
|
normal_status(-1, "项目标记不存在")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ class IssuesController < ApplicationController
|
||||||
include TagChosenHelper
|
include TagChosenHelper
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@user_operate_issue = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
|
||||||
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
|
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
|
||||||
issues = @project.issues.issue_issue.issue_index_includes
|
issues = @project.issues.issue_issue.issue_index_includes
|
||||||
issues = issues.where(is_private: false) unless @user_admin_or_member
|
issues = issues.where(is_private: false) unless @user_admin_or_member
|
||||||
|
@ -23,13 +24,13 @@ class IssuesController < ApplicationController
|
||||||
@filter_issues = @all_issues
|
@filter_issues = @all_issues
|
||||||
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
||||||
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
||||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||||
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
||||||
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
||||||
@assign_to_me = @filter_issues.where(assigned_to_id: current_user&.id)
|
|
||||||
@my_published = @filter_issues.where(author_id: current_user&.id)
|
|
||||||
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
||||||
@issues_size = scopes.size
|
@issues_size = scopes.size
|
||||||
|
@assign_to_me = scopes.where(assigned_to_id: current_user&.id)
|
||||||
|
@my_published = scopes.where(author_id: current_user&.id)
|
||||||
@issues = paginate(scopes)
|
@issues = paginate(scopes)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
@ -108,7 +109,7 @@ class IssuesController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
issue_params = issue_send_params(params)
|
issue_params = issue_send_params(params)
|
||||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||||
@issue = Issue.new(issue_params)
|
@issue = Issue.new(issue_params)
|
||||||
if @issue.save!
|
if @issue.save!
|
||||||
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||||
|
@ -125,9 +126,15 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if params[:issue_tag_ids].present?
|
if params[:issue_tag_ids].present?
|
||||||
params[:issue_tag_ids].each do |tag|
|
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
return normal_status(-1, "最多只能创建一个标记。")
|
||||||
end
|
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||||
|
params[:issue_tag_ids].each do |tag|
|
||||||
|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return normal_status(-1, "请输入正确的标记。")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if params[:assigned_to_id].present?
|
if params[:assigned_to_id].present?
|
||||||
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
|
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
|
||||||
|
@ -142,11 +149,13 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||||
|
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
|
||||||
|
|
||||||
|
|
||||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||||
|
|
||||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
render json: {status: 0, message: "创建成功", id: @issue.id}
|
||||||
else
|
else
|
||||||
normal_status(-1, "创建失败")
|
normal_status(-1, "创建失败")
|
||||||
end
|
end
|
||||||
|
@ -165,11 +174,18 @@ class IssuesController < ApplicationController
|
||||||
last_token = @issue.token
|
last_token = @issue.token
|
||||||
last_status_id = @issue.status_id
|
last_status_id = @issue.status_id
|
||||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
if params[:issue_tag_ids].present?
|
||||||
@issue&.issue_tags_relates&.destroy_all
|
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||||
params[:issue_tag_ids].each do |tag|
|
return normal_status(-1, "最多只能创建一个标记。")
|
||||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||||
end
|
@issue&.issue_tags_relates&.destroy_all
|
||||||
|
params[:issue_tag_ids].each do |tag|
|
||||||
|
next if tag == [""]
|
||||||
|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return normal_status(-1, "请输入正确的标记。")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
issue_files = params[:attachment_ids]
|
issue_files = params[:attachment_ids]
|
||||||
|
@ -207,7 +223,7 @@ class IssuesController < ApplicationController
|
||||||
normal_status(-1, "不允许修改为关闭状态")
|
normal_status(-1, "不允许修改为关闭状态")
|
||||||
else
|
else
|
||||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||||
if @issue.update_attributes(issue_params)
|
if @issue.update_attributes(issue_params)
|
||||||
if @issue&.pull_request.present?
|
if @issue&.pull_request.present?
|
||||||
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||||
|
@ -231,7 +247,7 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||||
@issue.issue_times.update_all(end_time: Time.now)
|
@issue.issue_times.update_all(end_time: Time.now)
|
||||||
@issue.update_closed_issues_count_in_project!
|
# @issue.update_closed_issues_count_in_project!
|
||||||
if @issue.issue_type.to_s == "2" && last_status_id != 5
|
if @issue.issue_type.to_s == "2" && last_status_id != 5
|
||||||
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token
|
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token
|
||||||
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
||||||
|
@ -473,7 +489,8 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def operate_issue_permission
|
def operate_issue_permission
|
||||||
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
|
@issue = Issue.find_by_id(params[:id]) unless @issue.present?
|
||||||
|
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_issues(issues)
|
def export_issues(issues)
|
||||||
|
|
|
@ -23,6 +23,7 @@ class JournalsController < ApplicationController
|
||||||
normal_status(-1, "评论内容不能为空")
|
normal_status(-1, "评论内容不能为空")
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
Journals::CreateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||||
journal_params = {
|
journal_params = {
|
||||||
journalized_id: @issue.id ,
|
journalized_id: @issue.id ,
|
||||||
journalized_type: "Issue",
|
journalized_type: "Issue",
|
||||||
|
@ -53,6 +54,9 @@ class JournalsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -70,7 +74,8 @@ class JournalsController < ApplicationController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
content = params[:content]
|
content = params[:content]
|
||||||
if content.present?
|
if content.present?
|
||||||
|
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||||
if @journal.update_attribute(:notes, content)
|
if @journal.update_attribute(:notes, content)
|
||||||
normal_status(0, "更新成功")
|
normal_status(0, "更新成功")
|
||||||
else
|
else
|
||||||
|
@ -79,7 +84,9 @@ class JournalsController < ApplicationController
|
||||||
else
|
else
|
||||||
normal_status(-1, "评论的内容不能为空")
|
normal_status(-1, "评论的内容不能为空")
|
||||||
end
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_children_journals
|
def get_children_journals
|
||||||
|
|
|
@ -21,6 +21,14 @@ class MainController < ApplicationController
|
||||||
uid_logger("main start is #{cookies[:_educoder_session]}")
|
uid_logger("main start is #{cookies[:_educoder_session]}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if params[:path] && params[:path].start_with?('projects/')
|
||||||
|
project_id = params[:path].split("/")[1]
|
||||||
|
project = Project.find_by_id(project_id)
|
||||||
|
if project.present?
|
||||||
|
return redirect_to("/projects/#{project.owner.login}/#{project.identifier}", status: 301)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发
|
# TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发
|
||||||
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
|
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
|
||||||
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'
|
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'
|
||||||
|
|
|
@ -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
|
|
@ -3,11 +3,19 @@ class MembersController < ApplicationController
|
||||||
before_action :load_project
|
before_action :load_project
|
||||||
before_action :find_user_with_id, only: %i[create remove change_role]
|
before_action :find_user_with_id, only: %i[create remove change_role]
|
||||||
before_action :check_user_profile_completed, only: [:create]
|
before_action :check_user_profile_completed, only: [:create]
|
||||||
before_action :operate!, except: %i[index]
|
before_action :operate!
|
||||||
before_action :check_member_exists!, only: %i[create]
|
before_action :check_member_exists!, only: %i[create]
|
||||||
before_action :check_member_not_exists!, only: %i[remove change_role]
|
before_action :check_member_not_exists!, only: %i[remove change_role]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
if @user.gitea_token.blank?
|
||||||
|
result = Gitea::User::GetService.call(@user.login)
|
||||||
|
if result[:status] == :error
|
||||||
|
# gitea不存在用户@user,直接注册
|
||||||
|
user_result = create_gitea_user!(@user, @user.login, @user.mail)
|
||||||
|
return render_error(user_result[:message]) if user_result[:message]
|
||||||
|
end
|
||||||
|
end
|
||||||
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
|
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
|
||||||
SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||||
|
@ -26,6 +34,9 @@ class MembersController < ApplicationController
|
||||||
|
|
||||||
@total_count = scope.size
|
@total_count = scope.size
|
||||||
@members = paginate(scope)
|
@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
|
end
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
|
@ -61,11 +72,14 @@ class MembersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_member_exists!
|
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
|
end
|
||||||
|
|
||||||
def check_member_not_exists!
|
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
|
end
|
||||||
|
|
||||||
def check_user_profile_completed
|
def check_user_profile_completed
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -2,6 +2,7 @@ class Oauth::BaseController < ActionController::Base
|
||||||
include RenderHelper
|
include RenderHelper
|
||||||
include LoginHelper
|
include LoginHelper
|
||||||
include ControllerRescueHandler
|
include ControllerRescueHandler
|
||||||
|
include RegisterHelper
|
||||||
# include LaboratoryHelper
|
# include LaboratoryHelper
|
||||||
|
|
||||||
skip_before_action :verify_authenticity_token
|
skip_before_action :verify_authenticity_token
|
||||||
|
@ -22,7 +23,7 @@ class Oauth::BaseController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def auth_hash
|
def auth_hash
|
||||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
# Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||||
request.env['omniauth.auth']
|
request.env['omniauth.auth']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
class Oauth::CallbacksController < Oauth::BaseController
|
||||||
|
def create
|
||||||
|
process_callback
|
||||||
|
rescue Exception => e
|
||||||
|
Rails.logger.info "授权失败:#{e}"
|
||||||
|
tip_exception("授权失败")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def config_providers
|
||||||
|
config = Rails.application.config_for(:configuration)
|
||||||
|
config.dig("oauth").keys
|
||||||
|
end
|
||||||
|
|
||||||
|
# QQ: {"ret":0,"msg":"","is_lost":0,"nickname":"颜值不算太高","gender":"男","gender_type":1,"province":"","city":"","year":"2013","constellation":"","figureurl":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/30","figureurl_1":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/50","figureurl_2":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/100","figureurl_qq_1":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=40\u0026t=1568887757","figureurl_qq_2":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=100\u0026t=1568887757","figureurl_qq":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=140\u0026t=1568887757","figureurl_type":"1","is_yellow_vip":"0","vip":"0","yellow_vip_level":"0","level":"0","is_yellow_year_vip":"0"}
|
||||||
|
def process_callback
|
||||||
|
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||||
|
if auth_hash.blank?
|
||||||
|
redirect_to("/login") && return
|
||||||
|
end
|
||||||
|
|
||||||
|
new_user = false
|
||||||
|
platform = auth_hash[:provider]
|
||||||
|
uid = auth_hash[:uid]
|
||||||
|
mail = auth_hash.info.email || nil
|
||||||
|
nickname = ["gitee", "github"].include?(platform) ? auth_hash.info.name : auth_hash.info.nickname
|
||||||
|
|
||||||
|
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid)
|
||||||
|
if open_user.present? && open_user.user.present?
|
||||||
|
successful_authentication(open_user.user)
|
||||||
|
else
|
||||||
|
if current_user.blank? || !current_user.logged?
|
||||||
|
has_user = User.find_by(mail: mail)
|
||||||
|
if has_user.present?
|
||||||
|
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: has_user.id, uid: uid, extra: auth_hash.extra)
|
||||||
|
successful_authentication(has_user)
|
||||||
|
else
|
||||||
|
new_user = true
|
||||||
|
login = build_login_name(platform, auth_hash.info.nickname)
|
||||||
|
mail = "#{login}@example.org" if mail.blank?
|
||||||
|
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||||
|
rand_password = code.sample(10).join
|
||||||
|
reg_result = autologin_register(login, mail, rand_password, platform, nil, nickname)
|
||||||
|
Rails.logger.info("[OAuth2] omniauth.auth [reg_result] #{reg_result} ")
|
||||||
|
if reg_result[:message].blank?
|
||||||
|
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: reg_result[:user][:id], uid: uid, extra: auth_hash.extra)
|
||||||
|
successful_authentication(open_user.user)
|
||||||
|
else
|
||||||
|
tip_exception(reg_result.present? ? reg_result[:message] : "授权失败")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: login, extra: auth_hash.extra)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
redirect_to root_path(new_user: new_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
# gitee,github nickname=login,如果系统未占用保留原用户名
|
||||||
|
def build_login_name(provider, nickname)
|
||||||
|
if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank?
|
||||||
|
nickname
|
||||||
|
else
|
||||||
|
User.generate_user_login('p')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,130 @@
|
||||||
|
class ObRepositorySyncsController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :load_project
|
||||||
|
before_action :load_ob_repository_sync, except: [:create]
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
def index
|
||||||
|
render_ok(data: @ob_repository_sync)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def create
|
||||||
|
tip_exception "参数错误" if params[:github_address].blank? && params[:gitee_address].blank?
|
||||||
|
project_name ="#{@project.owner.name}:#{@project.identifier}"
|
||||||
|
service = ObRepositorySync::ApiService.new(project_name)
|
||||||
|
domain = GiteaService.gitea_config[:domain]
|
||||||
|
project_params = params.merge({ "gitlink_address": "#{domain}/#{@project.owner&.login}/#{@project.identifier}.git" })
|
||||||
|
res = service.create_projects(project_params)
|
||||||
|
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
sync_id = res["data"]["id"]
|
||||||
|
ob_repository_sync = ObRepositorySync.find_or_initialize_by(project_id: @project.id)
|
||||||
|
ob_repository_sync.project_id = @project.id
|
||||||
|
ob_repository_sync.user_id = current_user.id
|
||||||
|
ob_repository_sync.name = project_name
|
||||||
|
ob_repository_sync.github_address = "#{params[:github_address]}"
|
||||||
|
ob_repository_sync.gitee_address = "#{params[:gitee_address]}"
|
||||||
|
ob_repository_sync.github_token = "#{params[:github_token]}"
|
||||||
|
ob_repository_sync.gitee_token = "#{params[:gitee_token]}"
|
||||||
|
ob_repository_sync.sync_id = sync_id
|
||||||
|
ob_repository_sync.save!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.delete_project @ob_repository_sync.sync_id
|
||||||
|
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
if res["code"].to_s == "200"
|
||||||
|
@ob_repository_sync.destroy!
|
||||||
|
end
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def jobs
|
||||||
|
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
|
||||||
|
page = params[:page] || 1
|
||||||
|
limit = params[:limit] || 10
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
source = ""
|
||||||
|
if params[:type] && params[:type].to_s.downcase == "github"
|
||||||
|
source = "github_branch"
|
||||||
|
elsif params[:type] && params[:type].to_s.downcase == "gitee"
|
||||||
|
source = "gitee_branch"
|
||||||
|
end
|
||||||
|
res = service.get_projects_jobs(source, page, limit)
|
||||||
|
data = res["data"]["list"]
|
||||||
|
render_ok(count: res["data"]["total"], data: data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_jobs
|
||||||
|
tip_exception "必须配置一个分支" if params[:github_branch].blank? && params[:gitee_branch].blank? && params[:gitlink_branch].blank?
|
||||||
|
ob_jobs = ObRepositorySyncJob.where(ob_repository_sync_id: @ob_repository_sync.id)
|
||||||
|
ob_jobs = ob_jobs.where(job_type: params[:job_type]) if params[:job_type].present?
|
||||||
|
ob_jobs = ob_jobs.where(github_branch: params[:github_branch]) if params[:github_branch].present?
|
||||||
|
ob_jobs = ob_jobs.where(gitee_branch: params[:gitee_branch]) if params[:gitee_branch].present?
|
||||||
|
ob_jobs = ob_jobs.where(gitlink_branch: params[:gitlink_branch]) if params[:gitlink_branch].present?
|
||||||
|
tip_exception "该分支组合已配置,不能重复!" if ob_jobs.count > 0
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.create_projects_jobs(params)
|
||||||
|
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
job_id = res["data"]["id"]
|
||||||
|
job = ObRepositorySyncJob.new
|
||||||
|
job.ob_repository_sync_id = @ob_repository_sync.id
|
||||||
|
job.github_branch = "#{params[:github_branch]}"
|
||||||
|
job.gitee_branch = "#{params[:gitee_branch]}"
|
||||||
|
job.gitlink_branch = "#{params[:gitlink_branch]}"
|
||||||
|
job.job_type = "#{params[:job_type]}"
|
||||||
|
job.base = "#{params[:base]}"
|
||||||
|
job.job_id = job_id
|
||||||
|
job.save
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def delete_job
|
||||||
|
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.delete_job params[:job_id]
|
||||||
|
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
job = ObRepositorySyncJob.find_by(ob_repository_sync_id: @ob_repository_sync.id, job_id: params[:job_id])
|
||||||
|
job.destroy! if job.present?
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_job
|
||||||
|
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.start_job params[:job_id]
|
||||||
|
tip_exception "启动错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop_job
|
||||||
|
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.stop_job params[:job_id]
|
||||||
|
tip_exception "停止错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def job_logs
|
||||||
|
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
|
||||||
|
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||||
|
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||||
|
res = service.job_logs params[:job_id]
|
||||||
|
tip_exception "请求错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||||
|
render_ok(count: res["data"]["total"], data: res["data"]["list"])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_ob_repository_sync
|
||||||
|
@ob_repository_sync = ObRepositorySync.find_by(project_id: @project.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def authenticate_user!
|
||||||
|
return if @project.member?(current_user) || current_user.admin?
|
||||||
|
render_forbidden('你没有权限操作')
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,8 +4,14 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@organization_users = @organization.organization_users.includes(:user)
|
@organization_users = @organization.organization_users.includes(:user)
|
||||||
search = params[:search].to_s.downcase
|
if params[:search].present?
|
||||||
@organization_users = @organization_users.joins(:user).merge(User.like(search))
|
search = params[:search].to_s.downcase
|
||||||
|
user_condition_users = User.like(search).to_sql
|
||||||
|
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||||
|
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||||
|
|
||||||
|
@organization_users = @organization_users.where(user_id: users).distinct
|
||||||
|
end
|
||||||
|
|
||||||
@organization_users = kaminari_paginate(@organization_users)
|
@organization_users = kaminari_paginate(@organization_users)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,9 +28,10 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
||||||
Organizations::CreateForm.new(organization_params).validate!
|
Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate!
|
||||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||||
|
Cache::V2::OwnerCommonService.new(@organization.id).reset
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -39,15 +40,16 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
Organizations::CreateForm.new(organization_params).validate!
|
Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate!
|
||||||
login = @organization.login
|
login = @organization.login
|
||||||
@organization.login = organization_params[:name] if organization_params[:name].present?
|
@organization.login = organization_params[:name] if organization_params[:name].present?
|
||||||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||||
@organization.save!
|
@organization.save!
|
||||||
sync_organization_extension!
|
sync_organization_extension!
|
||||||
|
|
||||||
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload)
|
||||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||||
|
Cache::V2::OwnerCommonService.new(@organization.id).reset
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -57,10 +59,16 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
tip_exception("密码不正确") unless current_user.check_password?(password)
|
tip_exception("密码不正确") unless current_user.check_password?(password)
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
Gitea::Organization::DeleteService.call(@organization.gitea_token, @organization.login)
|
gitea_destroy = Gitea::Organization::DeleteService.call(current_user.gitea_token, @organization.login)
|
||||||
@organization.destroy!
|
if gitea_destroy[:status] == 204
|
||||||
|
@organization.destroy!
|
||||||
|
render_ok
|
||||||
|
elsif gitea_destroy[:status] == 500
|
||||||
|
tip_exception("当组织内含有仓库时,无法删除此组织")
|
||||||
|
else
|
||||||
|
tip_exception("")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
render_ok
|
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
|
|
|
@ -21,6 +21,17 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_all
|
||||||
|
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@organization.projects.each do |project|
|
||||||
|
TeamProject.build(@organization.id, @team.id, project.id)
|
||||||
|
end
|
||||||
|
Gitea::Organization::TeamProject::CreateAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
@ -33,6 +44,17 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy_all
|
||||||
|
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@team.team_projects.each do |project|
|
||||||
|
project.destroy!
|
||||||
|
end
|
||||||
|
Gitea::Organization::TeamProject::DeleteAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def load_organization
|
def load_organization
|
||||||
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
|
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
|
||||||
|
@ -47,7 +69,7 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_operate_project
|
def load_operate_project
|
||||||
@operate_project = Project.find_by(id: project_mark) || Project.find_by(identifier: project_mark)
|
@operate_project = @organization.projects.where(id: project_mark).take || @organization.projects.where(identifier: project_mark).take
|
||||||
tip_exception("项目不存在") if @operate_project.nil?
|
tip_exception("项目不存在") if @operate_project.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
||||||
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
||||||
SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||||
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@team_user.destroy!
|
@team_user.destroy!
|
||||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||||
|
SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||||
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
|
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
|
||||||
unless org_team_users.present?
|
unless org_team_users.present?
|
||||||
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!
|
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!
|
||||||
|
|
|
@ -4,15 +4,24 @@ class Organizations::TeamsController < Organizations::BaseController
|
||||||
before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
|
before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
|
||||||
@teams = @organization.teams
|
|
||||||
#else
|
|
||||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
|
||||||
#end
|
|
||||||
@is_admin = can_edit_org?
|
|
||||||
@teams = @teams.includes(:team_units, :team_users)
|
|
||||||
|
|
||||||
@teams = kaminari_paginate(@teams)
|
if params[:is_full].present?
|
||||||
|
if can_edit_org?
|
||||||
|
@teams = @organization.teams
|
||||||
|
else
|
||||||
|
@teams = []
|
||||||
|
end
|
||||||
|
else
|
||||||
|
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||||
|
@teams = @organization.teams
|
||||||
|
#else
|
||||||
|
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||||
|
#end
|
||||||
|
@is_admin = can_edit_org?
|
||||||
|
@teams = @teams.includes(:team_units, :team_users)
|
||||||
|
|
||||||
|
@teams = kaminari_paginate(@teams)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def search
|
def search
|
||||||
|
@ -34,8 +43,12 @@ class Organizations::TeamsController < Organizations::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
Organizations::CreateTeamForm.new(team_params).validate!
|
if @organization.teams.count >= 50
|
||||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
return tip_exception("组织的团队数量已超过限制!")
|
||||||
|
else
|
||||||
|
Organizations::CreateTeamForm.new(team_params).validate!
|
||||||
|
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
|
|
@ -20,7 +20,7 @@ class OwnersController < ApplicationController
|
||||||
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
|
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
|
||||||
@is_member = @owner.is_member?(current_user.id)
|
@is_member = @owner.is_member?(current_user.id)
|
||||||
# 用户
|
# 用户
|
||||||
else
|
elsif @owner.is_a?(User)
|
||||||
#待办事项,现在未做
|
#待办事项,现在未做
|
||||||
if User.current.admin? || User.current.login == @owner.login
|
if User.current.admin? || User.current.login == @owner.login
|
||||||
@waiting_applied_messages = @owner.applied_messages.waiting
|
@waiting_applied_messages = @owner.applied_messages.waiting
|
||||||
|
@ -45,7 +45,6 @@ class OwnersController < ApplicationController
|
||||||
@projects_common_count = user_projects.common.size
|
@projects_common_count = user_projects.common.size
|
||||||
@projects_mirrior_count = user_projects.mirror.size
|
@projects_mirrior_count = user_projects.mirror.size
|
||||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||||
puts @owner.as_json
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ class PraiseTreadController < ApplicationController
|
||||||
begin
|
begin
|
||||||
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
|
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
|
||||||
current_user.like!(@project)
|
current_user.like!(@project)
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectPraised', current_user.id, @project.id) if Site.has_notice_menu?
|
||||||
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
|
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
|
|
@ -10,7 +10,7 @@ class ProjectCategoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def group_list
|
def group_list
|
||||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
@project_categories = ProjectCategory.select("id, name, projects_count, private_projects_count, (projects_count - private_projects_count) as public_projects_count").having('public_projects_count > 0').order(public_projects_count: :desc)
|
||||||
# projects = Project.no_anomory_projects.visible
|
# projects = Project.no_anomory_projects.visible
|
||||||
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
|
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
|
||||||
before_action :check_project_public
|
before_action :check_project_public
|
||||||
|
|
||||||
def index
|
def index
|
||||||
project_trends = @project.project_trends.preload(:user, trend: :user)
|
project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner)
|
||||||
|
|
||||||
check_time = params[:time] #时间的筛选
|
check_time = params[:time] #时间的筛选
|
||||||
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
class Projects::ProjectInviteLinksController < Projects::BaseController
|
||||||
|
before_action :require_manager!, except: [:show_link, :redirect_link]
|
||||||
|
before_action :require_login
|
||||||
|
|
||||||
|
def current_link
|
||||||
|
role = params[:role]
|
||||||
|
is_apply = params[:is_apply]
|
||||||
|
return render_error('请输入正确的参数!') unless role.present? && is_apply.present?
|
||||||
|
@project_invite_link = ProjectInviteLink.find_by(user_id: current_user.id, project_id: @project.id, role: role, is_apply: is_apply)
|
||||||
|
@project_invite_link = ProjectInviteLink.build!(@project, current_user, role, is_apply) unless @project_invite_link.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_link
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
params_data = link_params.merge({user_id: current_user.id, project_id: @project.id})
|
||||||
|
Projects::ProjectInviteLinks::CreateForm.new(params_data).validate!
|
||||||
|
@project_invite_link = ProjectInviteLink.build!(project, user, params_data[:role], params_data[:is_apply])
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_link
|
||||||
|
@project_invite_link = ProjectInviteLink.find_by(sign: params[:invite_sign])
|
||||||
|
return render_not_found unless @project_invite_link.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def redirect_link
|
||||||
|
Projects::LinkJoinService.call(current_user, @project, params[:invite_sign])
|
||||||
|
render_ok
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
normal_status(-1, e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
def link_params
|
||||||
|
params.require(:project_invite_link).permit(:role, :is_apply)
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,7 +9,7 @@ class Projects::WebhooksController < Projects::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 19
|
return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49
|
||||||
return render_error("参数错误.") unless webhook_params.present?
|
return render_error("参数错误.") unless webhook_params.present?
|
||||||
form = Projects::Webhooks::CreateForm.new(webhook_params)
|
form = Projects::Webhooks::CreateForm.new(webhook_params)
|
||||||
return render json: {status: -1, message: form.errors} unless form.validate!
|
return render json: {status: -1, message: form.errors} unless form.validate!
|
||||||
|
|
|
@ -13,16 +13,20 @@ class ProjectsController < ApplicationController
|
||||||
def menu_list
|
def menu_list
|
||||||
menu = []
|
menu = []
|
||||||
|
|
||||||
|
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||||
|
|
||||||
menu.append(menu_hash_by_name("home"))
|
menu.append(menu_hash_by_name("home"))
|
||||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
|
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
|
||||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki")
|
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
||||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
|
|
||||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
|
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
|
||||||
|
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||||
menu.append(menu_hash_by_name("activity"))
|
menu.append(menu_hash_by_name("activity"))
|
||||||
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
|
menu.append(menu_hash_by_name("sonar"))
|
||||||
|
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
||||||
|
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||||
|
|
||||||
render json: menu
|
render json: menu
|
||||||
end
|
end
|
||||||
|
@ -36,8 +40,9 @@ class ProjectsController < ApplicationController
|
||||||
category_id = params[:category_id]
|
category_id = params[:category_id]
|
||||||
@total_count =
|
@total_count =
|
||||||
if category_id.blank?
|
if category_id.blank?
|
||||||
ps = ProjectStatistic.first
|
# ps = ProjectStatistic.first
|
||||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||||
|
@projects.total_count
|
||||||
else
|
else
|
||||||
cate = ProjectCategory.find_by(id: category_id)
|
cate = ProjectCategory.find_by(id: category_id)
|
||||||
cate&.projects_count || 0
|
cate&.projects_count || 0
|
||||||
|
@ -49,6 +54,13 @@ class ProjectsController < ApplicationController
|
||||||
Projects::CreateForm.new(project_params).validate!
|
Projects::CreateForm.new(project_params).validate!
|
||||||
@project = Projects::CreateService.new(current_user, project_params).call
|
@project = Projects::CreateService.new(current_user, project_params).call
|
||||||
|
|
||||||
|
# TODO: fix Educoder shixun
|
||||||
|
if @project.persisted?
|
||||||
|
ProjectScore.create(:project_id => @project.id, :score => 0) if @project.project_score.nil?
|
||||||
|
|
||||||
|
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @project.id)
|
||||||
|
@project.project_infos << project_info
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
@ -59,7 +71,7 @@ class ProjectsController < ApplicationController
|
||||||
Projects::MigrateForm.new(mirror_params).validate!
|
Projects::MigrateForm.new(mirror_params).validate!
|
||||||
|
|
||||||
@project =
|
@project =
|
||||||
if enable_accelerator?(mirror_params[:clone_addr])
|
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
|
||||||
source_clone_url = mirror_params[:clone_addr]
|
source_clone_url = mirror_params[:clone_addr]
|
||||||
uid_logger("########## 已动加速器 ##########")
|
uid_logger("########## 已动加速器 ##########")
|
||||||
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||||
|
@ -71,6 +83,11 @@ class ProjectsController < ApplicationController
|
||||||
else
|
else
|
||||||
Projects::MigrateService.call(current_user, mirror_params)
|
Projects::MigrateService.call(current_user, mirror_params)
|
||||||
end
|
end
|
||||||
|
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
|
||||||
|
source_clone_url = mirror_params[:clone_addr]
|
||||||
|
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
|
||||||
|
uid_logger("########## 更改clone_addr ##########")
|
||||||
|
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
|
||||||
else
|
else
|
||||||
Projects::MigrateService.call(current_user, mirror_params)
|
Projects::MigrateService.call(current_user, mirror_params)
|
||||||
end
|
end
|
||||||
|
@ -82,8 +99,9 @@ class ProjectsController < ApplicationController
|
||||||
def branches
|
def branches
|
||||||
return @branches = [] unless @project.forge?
|
return @branches = [] unless @project.forge?
|
||||||
|
|
||||||
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||||
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||||
|
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
|
||||||
end
|
end
|
||||||
|
|
||||||
def branches_slice
|
def branches_slice
|
||||||
|
@ -94,18 +112,18 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def group_type_list
|
def group_type_list
|
||||||
project_statics = ProjectStatistic.first
|
# project_statics = ProjectStatistic.first
|
||||||
|
|
||||||
@project_statics_list = [
|
@project_statics_list = [
|
||||||
{
|
{
|
||||||
project_type: 'common',
|
project_type: 'common',
|
||||||
name: '开源托管项目',
|
name: '开源托管项目',
|
||||||
projects_count: project_statics&.common_projects_count || 0
|
projects_count: Project.common.size || 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
project_type: 'mirror',
|
project_type: 'mirror',
|
||||||
name: '开源镜像项目',
|
name: '开源镜像项目',
|
||||||
projects_count: project_statics&.mirror_projects_count || 0
|
projects_count: Project.sync_mirror.size + Project.mirror.size || 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -129,7 +147,7 @@ class ProjectsController < ApplicationController
|
||||||
validate_params = project_params.slice(:name, :description,
|
validate_params = project_params.slice(:name, :description,
|
||||||
:project_category_id, :project_language_id, :private, :identifier)
|
:project_category_id, :project_language_id, :private, :identifier)
|
||||||
|
|
||||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
|
||||||
|
|
||||||
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||||
|
|
||||||
|
@ -144,6 +162,15 @@ class ProjectsController < ApplicationController
|
||||||
}
|
}
|
||||||
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
|
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
|
||||||
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
||||||
|
# 更新对应所属分类下的项目数量(私有)
|
||||||
|
before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public
|
||||||
|
after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public
|
||||||
|
before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id
|
||||||
|
after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id
|
||||||
|
before_pc = ProjectCategory.find_by_id(before_pc_id)
|
||||||
|
after_pc = ProjectCategory.find_by_id(after_pc_id)
|
||||||
|
before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public
|
||||||
|
after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public
|
||||||
end
|
end
|
||||||
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
|
||||||
end
|
end
|
||||||
|
@ -161,6 +188,8 @@ class ProjectsController < ApplicationController
|
||||||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
||||||
@project.destroy!
|
@project.destroy!
|
||||||
@project.forked_projects.update_all(forked_from_project_id: nil)
|
@project.forked_projects.update_all(forked_from_project_id: nil)
|
||||||
|
# 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量
|
||||||
|
@project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -171,6 +200,22 @@ class ProjectsController < ApplicationController
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def quit
|
||||||
|
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||||
|
if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
|
||||||
|
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render_forbidden('你不能退出该仓库')
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
|
||||||
def watch_users
|
def watch_users
|
||||||
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
||||||
@watchers_count = watchers.size
|
@watchers_count = watchers.size
|
||||||
|
@ -184,7 +229,7 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def fork_users
|
def fork_users
|
||||||
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
|
fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||||
@forks_count = fork_users.size
|
@forks_count = fork_users.size
|
||||||
@fork_users = paginate(fork_users)
|
@fork_users = paginate(fork_users)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :show, :files, :commits]
|
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||||
before_action :require_profile_completed, only: [:create]
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :check_menu_authorize
|
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
|
||||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||||
before_action :load_pull_request, only: [:files, :commits]
|
before_action :load_pull_request, only: [:files, :commits]
|
||||||
before_action :find_atme_receivers, only: [:create, :update]
|
before_action :find_atme_receivers, only: [:create, :update]
|
||||||
|
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
|
||||||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||||
@all_issues = issues.distinct
|
@all_issues = issues.distinct
|
||||||
@filter_issues = @all_issues
|
@filter_issues = @all_issues
|
||||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||||
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
||||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||||
|
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@all_branches = Branches::ListService.call(@owner, @project)
|
@all_branches = Branches::ListService.call(@owner, @project, params[:branch_name])
|
||||||
@is_fork = @project.forked_from_project_id.present?
|
@is_fork = @project.forked_from_project_id.present?
|
||||||
@projects_names = [{
|
@projects_names = [{
|
||||||
project_user_login: @owner.try(:login),
|
project_user_login: @owner.try(:login),
|
||||||
|
@ -50,16 +50,20 @@ class PullRequestsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_branches
|
def get_branches
|
||||||
branch_result = Branches::ListService.call(@owner, @project)
|
branch_result = Branches::ListService.call(@owner, @project, params[:name])
|
||||||
render json: branch_result
|
render json: branch_result
|
||||||
# return json: branch_result
|
# return json: branch_result
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||||
if @gitea_pull_request[:status] == :success
|
if @gitea_pull_request[:status] == :success
|
||||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
||||||
|
reviewers = User.where(id: params[:reviewer_ids])
|
||||||
|
@pull_request.reviewers = reviewers
|
||||||
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||||
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
|
@ -69,6 +73,8 @@ class PullRequestsController < ApplicationController
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
rescue => e
|
||||||
|
normal_status(-1, e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@ -78,6 +84,7 @@ class PullRequestsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
|
||||||
if params[:title].nil?
|
if params[:title].nil?
|
||||||
normal_status(-1, "名称不能为空")
|
normal_status(-1, "名称不能为空")
|
||||||
elsif params[:issue_tag_ids].nil?
|
elsif params[:issue_tag_ids].nil?
|
||||||
|
@ -85,15 +92,11 @@ class PullRequestsController < ApplicationController
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
begin
|
begin
|
||||||
|
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||||
merge_params
|
merge_params
|
||||||
|
|
||||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
reviewers = User.where(id: params[:reviewer_ids])
|
||||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
@pull_request.reviewers = reviewers
|
||||||
@issue&.issue_tags_relates&.destroy_all
|
|
||||||
params[:issue_tag_ids].each do |tag|
|
|
||||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if @issue.update_attributes(@issue_params)
|
if @issue.update_attributes(@issue_params)
|
||||||
if @pull_request.update_attributes(@local_params.compact)
|
if @pull_request.update_attributes(@local_params.compact)
|
||||||
|
@ -102,9 +105,16 @@ class PullRequestsController < ApplicationController
|
||||||
|
|
||||||
if gitea_pull[:status] === :success
|
if gitea_pull[:status] === :success
|
||||||
if params[:issue_tag_ids].present?
|
if params[:issue_tag_ids].present?
|
||||||
params[:issue_tag_ids].each do |tag|
|
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
return normal_status(-1, "最多只能创建一个标记。")
|
||||||
end
|
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||||
|
@issue&.issue_tags_relates&.destroy_all
|
||||||
|
params[:issue_tag_ids].each do |tag|
|
||||||
|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return normal_status(-1, "请输入正确的标记。")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if params[:status_id].to_i == 5
|
if params[:status_id].to_i == 5
|
||||||
@issue.issue_times.update_all(end_time: Time.now)
|
@issue.issue_times.update_all(end_time: Time.now)
|
||||||
|
@ -136,6 +146,8 @@ class PullRequestsController < ApplicationController
|
||||||
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
||||||
if colsed === true
|
if colsed === true
|
||||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
|
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
|
||||||
|
# 合并请求下issue处理为关闭
|
||||||
|
@issue&.update_attributes!({status_id:5})
|
||||||
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||||
normal_status(1, "已拒绝")
|
normal_status(1, "已拒绝")
|
||||||
else
|
else
|
||||||
|
@ -157,6 +169,7 @@ class PullRequestsController < ApplicationController
|
||||||
@issue_assign_to = @issue.get_assign_user
|
@issue_assign_to = @issue.get_assign_user
|
||||||
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
||||||
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||||
|
# @last_review = @pull_request.reviews.take
|
||||||
end
|
end
|
||||||
|
|
||||||
def pr_merge
|
def pr_merge
|
||||||
|
@ -180,6 +193,8 @@ class PullRequestsController < ApplicationController
|
||||||
# @pull_request.project_trend_status!
|
# @pull_request.project_trend_status!
|
||||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
|
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
|
||||||
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
||||||
|
# 合并请求下issue处理为关闭
|
||||||
|
@issue&.update_attributes!({status_id:5})
|
||||||
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||||
normal_status(1, "合并成功")
|
normal_status(1, "合并成功")
|
||||||
else
|
else
|
||||||
|
@ -197,7 +212,7 @@ class PullRequestsController < ApplicationController
|
||||||
def check_can_merge
|
def check_can_merge
|
||||||
target_head = params[:head] #源分支
|
target_head = params[:head] #源分支
|
||||||
target_base = params[:base] #目标分支
|
target_base = params[:base] #目标分支
|
||||||
is_original = params[:is_original]
|
is_original = params[:is_original] || false
|
||||||
if target_head.blank? || target_base.blank?
|
if target_head.blank? || target_base.blank?
|
||||||
normal_status(-2, "请选择分支")
|
normal_status(-2, "请选择分支")
|
||||||
elsif target_head === target_base && !is_original
|
elsif target_head === target_base && !is_original
|
||||||
|
@ -228,11 +243,11 @@ class PullRequestsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
def load_pull_request
|
def load_pull_request
|
||||||
@pull_request = PullRequest.find params[:id]
|
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_pull_request
|
def find_pull_request
|
||||||
@pull_request = PullRequest.find_by_id(params[:id])
|
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||||
@issue = @pull_request&.issue
|
@issue = @pull_request&.issue
|
||||||
if @pull_request.blank?
|
if @pull_request.blank?
|
||||||
normal_status(-1, "合并请求不存在")
|
normal_status(-1, "合并请求不存在")
|
||||||
|
@ -243,7 +258,7 @@ class PullRequestsController < ApplicationController
|
||||||
|
|
||||||
def get_relatived
|
def get_relatived
|
||||||
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
|
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
|
||||||
@project_versions = @project.versions&.select(:id,:name, :status).as_json
|
@project_versions = @project.versions.opening&.select(:id,:name, :status).as_json
|
||||||
@project_members = @project.all_developers
|
@project_members = @project.all_developers
|
||||||
@project_priories = IssuePriority&.select(:id,:name, :position).as_json
|
@project_priories = IssuePriority&.select(:id,:name, :position).as_json
|
||||||
end
|
end
|
||||||
|
@ -256,12 +271,12 @@ class PullRequestsController < ApplicationController
|
||||||
base: params[:base], #目标分支
|
base: params[:base], #目标分支
|
||||||
milestone: 0, #里程碑,未与本地的里程碑关联
|
milestone: 0, #里程碑,未与本地的里程碑关联
|
||||||
}
|
}
|
||||||
|
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||||
@requests_params = @local_params.merge({
|
@requests_params = @local_params.merge({
|
||||||
assignee: current_user.try(:login),
|
|
||||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||||
assignees: ["#{current_user.try(:login).to_s}"],
|
assignees: ["#{assignee_login.to_s}"],
|
||||||
labels: params[:issue_tag_ids],
|
labels: params[:issue_tag_ids]
|
||||||
due_date: Time.now
|
# due_date: Time.now
|
||||||
})
|
})
|
||||||
@issue_params = {
|
@issue_params = {
|
||||||
author_id: current_user.id,
|
author_id: current_user.id,
|
||||||
|
@ -271,7 +286,7 @@ class PullRequestsController < ApplicationController
|
||||||
assigned_to_id: params[:assigned_to_id],
|
assigned_to_id: params[:assigned_to_id],
|
||||||
fixed_version_id: params[:fixed_version_id],
|
fixed_version_id: params[:fixed_version_id],
|
||||||
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
|
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
|
||||||
priority_id: params[:priority_id] || "2",
|
priority_id: params[:priority_id],
|
||||||
issue_classify: "pull_request",
|
issue_classify: "pull_request",
|
||||||
issue_type: params[:issue_type] || "1",
|
issue_type: params[:issue_type] || "1",
|
||||||
tracker_id: 2,
|
tracker_id: 2,
|
||||||
|
|
|
@ -1,358 +1,407 @@
|
||||||
class RepositoriesController < ApplicationController
|
class RepositoriesController < ApplicationController
|
||||||
include RepositoriesHelper
|
include RepositoriesHelper
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include OperateProjectAbilityAble
|
include OperateProjectAbilityAble
|
||||||
include Repository::LanguagesPercentagable
|
include Repository::LanguagesPercentagable
|
||||||
|
|
||||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||||
before_action :require_profile_completed, only: [:create_file]
|
before_action :require_profile_completed, only: [:create_file]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
before_action :get_ref, only: %i[entries sub_entries top_counts files archive]
|
||||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||||
before_action :get_statistics, only: %i[top_counts]
|
before_action :get_statistics, only: %i[top_counts]
|
||||||
|
|
||||||
def files
|
def files
|
||||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||||
render json: result
|
render json: result
|
||||||
end
|
end
|
||||||
|
|
||||||
# 新版项目详情
|
# 新版项目详情
|
||||||
def detail
|
def detail
|
||||||
@user = current_user
|
@user = current_user
|
||||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||||
@project_fork_id = @project.try(:forked_from_project_id)
|
@project_fork_id = @project.try(:forked_from_project_id)
|
||||||
if @project_fork_id.present?
|
if @project_fork_id.present?
|
||||||
@fork_project = Project.find_by(id: @project_fork_id)
|
@fork_project = Project.find_by(id: @project_fork_id)
|
||||||
@fork_project_user = @fork_project.owner
|
@fork_project_user = @fork_project.owner
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user = current_user
|
@user = current_user
|
||||||
@repo = @project.repository
|
@repo = @project.repository
|
||||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||||
@project_fork_id = @project.try(:forked_from_project_id)
|
@project_fork_id = @project.try(:forked_from_project_id)
|
||||||
if @project_fork_id.present?
|
if @project_fork_id.present?
|
||||||
@fork_project = Project.find_by(id: @project_fork_id)
|
@fork_project = Project.find_by(id: @project_fork_id)
|
||||||
@fork_project_user = @fork_project.owner
|
@fork_project_user = @fork_project.owner
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def entries
|
def entries
|
||||||
@project.increment!(:visits)
|
@week_project_visit_record, @month_project_visit_record = TimeableVisitRecord.build(@project.id)
|
||||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
if @week_project_visit_record.visits < 300 && @month_project_visit_record.visits < 1000
|
||||||
if @project.educoder?
|
@week_project_visit_record.increment!(:visits)
|
||||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
@month_project_visit_record.increment!(:visits)
|
||||||
else
|
@project.increment!(:visits)
|
||||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
end
|
||||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
if @project.educoder?
|
||||||
end
|
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||||
end
|
else
|
||||||
|
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||||
def top_counts
|
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def sub_entries
|
|
||||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
def top_counts
|
||||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||||
|
end
|
||||||
if @project.educoder?
|
|
||||||
if params[:type] === 'file'
|
def sub_entries
|
||||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||||
logger.info "######### sub_entries: #{@sub_entries}"
|
|
||||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
if @project.educoder?
|
||||||
|
if params[:type] === 'file'
|
||||||
tmp_entries = [{
|
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||||
"content" => @sub_entries['data']['content'],
|
logger.info "######### sub_entries: #{@sub_entries}"
|
||||||
"type" => "blob"
|
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||||
}]
|
|
||||||
@sub_entries = {
|
tmp_entries = {
|
||||||
"trees"=>tmp_entries,
|
"content" => @sub_entries['data']['content'],
|
||||||
"commits" => [{}]
|
"type" => "blob"
|
||||||
}
|
}
|
||||||
else
|
@sub_entries = {
|
||||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
"trees"=>tmp_entries,
|
||||||
end
|
"commits" => [{}]
|
||||||
else
|
}
|
||||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
else
|
||||||
if interactor.success?
|
begin
|
||||||
result = interactor.result
|
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
|
||||||
else
|
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||||
render_error(interactor.error)
|
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||||
end
|
tmp_entries = {
|
||||||
end
|
"content" => @sub_entries['data']['content'],
|
||||||
end
|
"type" => "blob"
|
||||||
|
}
|
||||||
def commits
|
@sub_entries = {
|
||||||
if params[:filepath].present?
|
"trees"=>tmp_entries,
|
||||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
"commits" => [{}]
|
||||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
}
|
||||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
end
|
||||||
else
|
rescue
|
||||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
return render_error('该文件暂未开放,敬请期待.')
|
||||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
end
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||||
def commits_slice
|
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||||
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
if interactor.success?
|
||||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
result = interactor.result
|
||||||
end
|
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||||
|
else
|
||||||
def commit
|
render_error(interactor.error)
|
||||||
@sha = params[:sha]
|
end
|
||||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
end
|
||||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
end
|
||||||
end
|
|
||||||
|
def commits
|
||||||
def tags
|
if @project.educoder?
|
||||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
|
||||||
|
else
|
||||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
if params[:filepath].present?
|
||||||
end
|
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||||
|
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||||
def contributors
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call
|
||||||
if params[:filepath].present?
|
else
|
||||||
@contributors = []
|
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||||
else
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call
|
||||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def commits_slice
|
||||||
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
||||||
end
|
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||||
|
end
|
||||||
def create_file
|
|
||||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
def commit
|
||||||
if interactor.success?
|
@sha = params[:sha]
|
||||||
@file = interactor.result
|
if @project.educoder?
|
||||||
# create_new_pr(params)
|
return render_error('暂未开放,敬请期待.')
|
||||||
#如果是更新流水线文件
|
else
|
||||||
if params[:pipeline_id]
|
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token)
|
||||||
update_pipeline(params[:pipeline_id])
|
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token, {diff: true})
|
||||||
end
|
render_error(@commit[:message], @commit[:status]) if @commit.has_key?(:status) || @commit_diff.has_key?(:status)
|
||||||
else
|
end
|
||||||
render_error(interactor.error)
|
end
|
||||||
end
|
|
||||||
end
|
def tags
|
||||||
|
if params[:only_name].present?
|
||||||
def update_pipeline(pipeline_id)
|
result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||||
pipeline = Ci::Pipeline.find(pipeline_id)
|
|
||||||
if pipeline
|
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||||
pipeline.update!(sync: 1)
|
else
|
||||||
end
|
name_result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||||
end
|
|
||||||
|
@tag_names = result.is_a?(Hash) && result.key?(:status) ? [] : name_result
|
||||||
def update_file
|
|
||||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
result = Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||||
if interactor.success?
|
|
||||||
@file = interactor.result
|
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||||
# TODO: 是否创建pr
|
end
|
||||||
# create_new_pr(params)
|
end
|
||||||
render_result(1, "更新成功")
|
|
||||||
else
|
def contributors
|
||||||
render_error(interactor.error)
|
if params[:filepath].present? || @project.educoder?
|
||||||
end
|
@contributors = []
|
||||||
end
|
else
|
||||||
|
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||||
def delete_file
|
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
end
|
||||||
if interactor.success?
|
rescue
|
||||||
@file = interactor.result
|
@contributors = []
|
||||||
render_result(1, "文件删除成功")
|
end
|
||||||
else
|
|
||||||
render_error(interactor.error)
|
def edit
|
||||||
end
|
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
def repo_hook
|
def create_file
|
||||||
|
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||||
end
|
if interactor.success?
|
||||||
|
@file = interactor.result
|
||||||
def sync_mirror
|
# create_new_pr(params)
|
||||||
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
#如果是更新流水线文件
|
||||||
|
if params[:pipeline_id]
|
||||||
@repository.sync_mirror!
|
update_pipeline(params[:pipeline_id])
|
||||||
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
end
|
||||||
render_ok
|
else
|
||||||
end
|
render_error(interactor.error)
|
||||||
|
end
|
||||||
def readme
|
end
|
||||||
if params[:filepath].present?
|
|
||||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
def update_pipeline(pipeline_id)
|
||||||
else
|
pipeline = Ci::Pipeline.find(pipeline_id)
|
||||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
if pipeline
|
||||||
end
|
pipeline.update!(sync: 1)
|
||||||
@readme = result[:status] === :success ? result[:body] : nil
|
end
|
||||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref])
|
end
|
||||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
|
||||||
rescue
|
def update_file
|
||||||
render json: nil
|
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||||
end
|
if interactor.success?
|
||||||
|
@file = interactor.result
|
||||||
def languages
|
# TODO: 是否创建pr
|
||||||
render json: languages_precentagable
|
# create_new_pr(params)
|
||||||
end
|
render_result(1, "更新成功")
|
||||||
|
else
|
||||||
def archive
|
render_error(interactor.error)
|
||||||
domain = Gitea.gitea_config[:domain]
|
end
|
||||||
api_url = Gitea.gitea_config[:base_url]
|
end
|
||||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
|
|
||||||
|
def delete_file
|
||||||
file_path = [domain, api_url, archive_url].join
|
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
if interactor.success?
|
||||||
|
@file = interactor.result
|
||||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
render_result(1, "文件删除成功")
|
||||||
|
else
|
||||||
redirect_to file_path
|
render_error(interactor.error)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def raw
|
|
||||||
domain = Gitea.gitea_config[:domain]
|
def repo_hook
|
||||||
api_url = Gitea.gitea_config[:base_url]
|
|
||||||
|
end
|
||||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
|
|
||||||
file_path = [domain, api_url, url].join
|
def sync_mirror
|
||||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden?
|
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
||||||
|
|
||||||
redirect_to URI.escape(file_path)
|
@repository.sync_mirror!
|
||||||
end
|
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
||||||
|
render_ok
|
||||||
private
|
end
|
||||||
|
|
||||||
def find_project
|
def readme
|
||||||
@project = Project.find params[:id]
|
if params[:filepath].present?
|
||||||
render_not_found("未找到相关的仓库") unless @project
|
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], @owner&.gitea_token)
|
||||||
end
|
else
|
||||||
|
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], @owner&.gitea_token)
|
||||||
def find_project_with_includes
|
end
|
||||||
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
@path = GiteaService.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||||
end
|
@readme = result[:status] === :success ? result[:body] : nil
|
||||||
|
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||||
def authorizate!
|
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||||
return if current_user && current_user.admin?
|
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
|
||||||
if @project.repository.hidden? && !@project.member?(current_user)
|
rescue
|
||||||
render_forbidden
|
render json: nil
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
def languages
|
||||||
# TODO 获取最新commit信息
|
if @project.educoder?
|
||||||
def project_commits
|
render json: {}
|
||||||
if params[:filepath].present?
|
else
|
||||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
render json: languages_precentagable
|
||||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
end
|
||||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
end
|
||||||
else
|
|
||||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
def archive
|
||||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
domain = GiteaService.gitea_config[:domain]
|
||||||
end
|
api_url = GiteaService.gitea_config[:base_url]
|
||||||
end
|
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
|
||||||
|
|
||||||
def get_statistics
|
file_path = [domain, api_url, archive_url].join
|
||||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("?")
|
||||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
|
||||||
end
|
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||||
|
|
||||||
def get_ref
|
redirect_to file_path
|
||||||
@ref = params[:ref] || @project&.default_branch
|
end
|
||||||
end
|
|
||||||
|
def raw
|
||||||
def get_latest_commit
|
domain = GiteaService.gitea_config[:domain]
|
||||||
latest_commit = @project.educoder? ? nil : project_commits
|
api_url = GiteaService.gitea_config[:base_url]
|
||||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
|
||||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
||||||
end
|
file_path = [domain, api_url, url].join
|
||||||
|
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("&")
|
||||||
def content_params
|
|
||||||
{
|
redirect_to file_path
|
||||||
filepath: params[:filepath],
|
end
|
||||||
branch: params[:branch],
|
|
||||||
new_branch: params[:new_branch],
|
private
|
||||||
content: params[:content],
|
|
||||||
message: params[:message],
|
def find_project
|
||||||
committer: {
|
@project = Project.find params[:id]
|
||||||
email: current_user.mail,
|
render_not_found("未找到相关的仓库") unless @project
|
||||||
name: current_user.login
|
end
|
||||||
},
|
|
||||||
identifier: @project.identifier
|
def find_project_with_includes
|
||||||
}
|
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def hook_params(hook_type, params)
|
def authorizate!
|
||||||
# if hook_type == "push"
|
return if current_user && current_user.admin?
|
||||||
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
if @project.repository.hidden? && !@project.member?(current_user)
|
||||||
# uploadPushInfo = {
|
render_forbidden
|
||||||
# "sha": params["commits"].present? ? params["commits"].last : "",
|
end
|
||||||
# "branch": params["ref"].to_s.split("/").last,
|
end
|
||||||
# "modification_lines": params["commits"].length
|
|
||||||
# }
|
# TODO 获取最新commit信息
|
||||||
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
def project_commits
|
||||||
# uploadPushInfo = {
|
if params[:filepath].present?
|
||||||
# "branch": params["base"]["ref"].to_s.split("/").last,
|
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||||
# "sha": params["pull_request"]["merge_base"],
|
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||||
# "modification_lines": 1 #pull_request中没有commits数量
|
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call
|
||||||
# }
|
else
|
||||||
# else
|
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||||
# uploadPushInfo = {}
|
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call
|
||||||
# end
|
end
|
||||||
|
end
|
||||||
# uploadPushInfo
|
|
||||||
end
|
def get_statistics
|
||||||
|
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||||
def create_new_pr(params)
|
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(@project&.owner&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
end
|
||||||
local_params = {
|
|
||||||
title: params[:message], #标题
|
def get_ref
|
||||||
body: params[:content], #内容
|
@ref = params[:ref] || @project&.default_branch
|
||||||
head: params[:new_branch], #源分支
|
end
|
||||||
base: params[:branch], #目标分支
|
|
||||||
milestone: 0 #里程碑,未与本地的里程碑关联
|
def get_latest_commit
|
||||||
|
latest_commit = @project.educoder? ? nil : project_commits
|
||||||
}
|
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||||
requests_params = local_params.merge({
|
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||||
assignee: current_user.try(:login),
|
end
|
||||||
assignees: [],
|
|
||||||
labels: [],
|
def content_params
|
||||||
due_date: Time.now
|
{
|
||||||
})
|
filepath: params[:filepath],
|
||||||
|
branch: params[:branch],
|
||||||
issue_params = {
|
new_branch: params[:new_branch],
|
||||||
author_id: current_user.id,
|
content: params[:content],
|
||||||
project_id: @project.id,
|
message: params[:message],
|
||||||
subject: params[:message],
|
committer: {
|
||||||
description: params[:content],
|
email: current_user.mail,
|
||||||
assigned_to_id: nil,
|
name: current_user.login
|
||||||
fixed_version_id: nil,
|
},
|
||||||
issue_tags_value: nil,
|
identifier: @project.identifier
|
||||||
issue_classify: "pull_request",
|
}
|
||||||
issue_type: "1",
|
end
|
||||||
tracker_id: 2,
|
|
||||||
status_id: 1,
|
def hook_params(hook_type, params)
|
||||||
priority_id: params[:priority_id] || "2"
|
# if hook_type == "push"
|
||||||
}
|
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
||||||
@pull_issue = Issue.new(issue_params)
|
# uploadPushInfo = {
|
||||||
if @pull_issue.save!
|
# "sha": params["commits"].present? ? params["commits"].last : "",
|
||||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
# "branch": params["ref"].to_s.split("/").last,
|
||||||
if local_requests.save
|
# "modification_lines": params["commits"].length
|
||||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
# }
|
||||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
||||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
# uploadPushInfo = {
|
||||||
end
|
# "branch": params["base"]["ref"].to_s.split("/").last,
|
||||||
end
|
# "sha": params["pull_request"]["merge_base"],
|
||||||
end
|
# "modification_lines": 1 #pull_request中没有commits数量
|
||||||
end
|
# }
|
||||||
end
|
# else
|
||||||
|
# uploadPushInfo = {}
|
||||||
end
|
# end
|
||||||
|
|
||||||
|
# uploadPushInfo
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_new_pr(params)
|
||||||
|
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||||
|
local_params = {
|
||||||
|
title: params[:message], #标题
|
||||||
|
body: params[:content], #内容
|
||||||
|
head: params[:new_branch], #源分支
|
||||||
|
base: params[:branch], #目标分支
|
||||||
|
milestone: 0 #里程碑,未与本地的里程碑关联
|
||||||
|
|
||||||
|
}
|
||||||
|
requests_params = local_params.merge({
|
||||||
|
assignee: current_user.try(:login),
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
due_date: Time.now
|
||||||
|
})
|
||||||
|
|
||||||
|
issue_params = {
|
||||||
|
author_id: current_user.id,
|
||||||
|
project_id: @project.id,
|
||||||
|
subject: params[:message],
|
||||||
|
description: params[:content],
|
||||||
|
assigned_to_id: nil,
|
||||||
|
fixed_version_id: nil,
|
||||||
|
issue_tags_value: nil,
|
||||||
|
issue_classify: "pull_request",
|
||||||
|
issue_type: "1",
|
||||||
|
tracker_id: 2,
|
||||||
|
status_id: 1,
|
||||||
|
priority_id: params[:priority_id] || "2"
|
||||||
|
}
|
||||||
|
@pull_issue = Issue.new(issue_params)
|
||||||
|
if @pull_issue.save!
|
||||||
|
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||||
|
if local_requests.save
|
||||||
|
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||||
|
if gitea_request[:status] == :success && local_requests.update_attributes(gitea_number: gitea_request["body"]["number"])
|
||||||
|
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
class ReviewsController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :load_project
|
||||||
|
before_action :load_pull_request
|
||||||
|
|
||||||
|
def create
|
||||||
|
return render_forbidden('您不是审查人员,无法进行审查!') if current_user&.id != @pull_request.issue.assigned_to_id
|
||||||
|
@review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
|
||||||
|
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
|
|
@ -1,13 +1,23 @@
|
||||||
class SettingsController < ApplicationController
|
class SettingsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
@old_projects_url = nil
|
@old_projects_url = nil
|
||||||
|
get_navbar
|
||||||
get_add_menu
|
get_add_menu
|
||||||
get_common_menu
|
get_common_menu
|
||||||
get_personal_menu
|
get_personal_menu
|
||||||
get_top_system_notification
|
get_top_system_notification
|
||||||
|
get_banner
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def get_navbar
|
||||||
|
@navbar = default_laboratory.navbar
|
||||||
|
if User.current.logged?
|
||||||
|
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
|
||||||
|
@navbar << pernal_index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_add_menu
|
def get_add_menu
|
||||||
@add = []
|
@add = []
|
||||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||||
|
@ -58,4 +68,14 @@ class SettingsController < ApplicationController
|
||||||
def append_http(url)
|
def append_http(url)
|
||||||
url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('')
|
url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_banner
|
||||||
|
@banner = {
|
||||||
|
title: EduSetting.get("banner_title") || '大学开源',
|
||||||
|
sub_title: EduSetting.get("banner_sub_title") || '让大学绽放开源之花',
|
||||||
|
content: EduSetting.get("banner_content") || "Powered by Trustie and GitLink"
|
||||||
|
}
|
||||||
|
|
||||||
|
@banner
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
class SonarTasksController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :load_project
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
def index
|
||||||
|
@sonar_task = SonarTask.find_by(project_id: @project.id)
|
||||||
|
tip_exception(-1, "代码未检测,请点击开始检测按钮检测!") if @sonar_task.blank?
|
||||||
|
if @sonar_task.complete_status == 0
|
||||||
|
service = Sonar::ApiService.new(@project.id)
|
||||||
|
service.task_result(@sonar_task.task_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
Sonar::ApiService.call(@project.id)
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def type_detail
|
||||||
|
service = Sonar::ApiService.new(@project.id)
|
||||||
|
@data = service.type_detail(params[:task_id], params[:type])
|
||||||
|
end
|
||||||
|
|
||||||
|
def code_source
|
||||||
|
service = Sonar::ApiService.new(@project.id)
|
||||||
|
@data = service.source_code(params[:task_id], params[:component])
|
||||||
|
Rails.logger.info "data=======#{@data}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def authenticate_user!
|
||||||
|
return if @project.member?(current_user) || current_user.admin? || current_user.business? || educoder_auth_teacher?(current_user)
|
||||||
|
render_forbidden('你没有权限操作')
|
||||||
|
end
|
||||||
|
|
||||||
|
def educoder_auth_teacher?(user)
|
||||||
|
user.user_extension&.identity == 'teacher' && user.professional_certification?
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,24 +2,24 @@ class StatisticController < ApplicationController
|
||||||
|
|
||||||
# 平台概况
|
# 平台概况
|
||||||
def platform_profile
|
def platform_profile
|
||||||
@platform_user_query = Statistic::PlatformUserQuery.new(params).call
|
@platform_user_query = Statistic::PlatformUserQuery.new(params).call rescue [0, 0, 0]
|
||||||
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call
|
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call rescue [0, 0, 0]
|
||||||
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call
|
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call rescue [0, 0, 0]
|
||||||
end
|
end
|
||||||
|
|
||||||
# 平台代码提交数据
|
# 平台代码提交数据
|
||||||
def platform_code
|
def platform_code
|
||||||
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call
|
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call rescue [0, 0]
|
||||||
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call
|
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call rescue [0, 0]
|
||||||
end
|
end
|
||||||
|
|
||||||
# 项目案例活跃度排行榜
|
# 项目案例活跃度排行榜
|
||||||
def active_project_rank
|
def active_project_rank
|
||||||
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call
|
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call rescue []
|
||||||
end
|
end
|
||||||
|
|
||||||
# 开发者活跃度排行榜
|
# 开发者活跃度排行榜
|
||||||
def active_developer_rank
|
def active_developer_rank
|
||||||
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call
|
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call rescue []
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
class Traces::BaseController < ApplicationController
|
||||||
|
|
||||||
|
helper_method :observed_logged_user?, :observed_user
|
||||||
|
before_action :check_trace_system
|
||||||
|
|
||||||
|
def observed_user
|
||||||
|
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||||
|
end
|
||||||
|
|
||||||
|
def observed_logged_user?
|
||||||
|
observed_user.id == User.current&.id
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def check_auth
|
||||||
|
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_trace_system
|
||||||
|
code, data, error = Trace::SystemInfoService.call(current_user.trace_token)
|
||||||
|
return render_ok({code: 501, data: {operate_time: data['operate_time']}, message: '系统维护中'}) if data['status'] === 0
|
||||||
|
rescue
|
||||||
|
# 这里根据需求跳转到404
|
||||||
|
return render_not_found
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,10 @@
|
||||||
class Users::IsPinnedProjectsController < Users::BaseController
|
class Users::IsPinnedProjectsController < Users::BaseController
|
||||||
before_action :private_user_resources!, only: [:pin]
|
before_action :private_user_resources!, only: [:pin]
|
||||||
def index
|
def index
|
||||||
@is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
|
@is_pinned_projects = observed_user.pinned_projects.left_joins(:project)
|
||||||
|
.where("projects.is_public = TRUE")
|
||||||
|
.order(position: :desc, created_at: :asc)
|
||||||
|
.includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
|
||||||
@is_pinned_projects = kaminari_paginate(@is_pinned_projects)
|
@is_pinned_projects = kaminari_paginate(@is_pinned_projects)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
|
||||||
@commit_data = []
|
@commit_data = []
|
||||||
date_range.each do |date|
|
date_range.each do |date|
|
||||||
@date_data << date.strftime("%Y.%m.%d")
|
@date_data << date.strftime("%Y.%m.%d")
|
||||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
|
||||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||||
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
||||||
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||||
|
|
|
@ -23,6 +23,8 @@ class Users::TemplateMessageSettingsController < Users::BaseController
|
||||||
def get_current_setting
|
def get_current_setting
|
||||||
@current_setting = @_observed_user.user_template_message_setting
|
@current_setting = @_observed_user.user_template_message_setting
|
||||||
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
||||||
|
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
|
||||||
|
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
|
||||||
end
|
end
|
||||||
|
|
||||||
def setting_params
|
def setting_params
|
||||||
|
|
|
@ -1,312 +1,373 @@
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include Ci::DbConnectable
|
include Ci::DbConnectable
|
||||||
|
|
||||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||||
before_action :require_login, only: %i[me list sync_user_info]
|
before_action :require_login, only: %i[me list]
|
||||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||||
before_action :convert_image!, only: [:update]
|
before_action :convert_image!, only: [:update]
|
||||||
skip_before_action :check_sign, only: [:attachment_show]
|
skip_before_action :check_sign, only: [:attachment_show]
|
||||||
|
|
||||||
def connect_to_ci_db(options={})
|
def connect_to_ci_db(options={})
|
||||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||||
connect_to_trustie_ci_database(options)
|
connect_to_trustie_ci_database(options)
|
||||||
else
|
else
|
||||||
connect_to_ci_database(options)
|
connect_to_ci_database(options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def list
|
def list
|
||||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||||
@total_count = scope.size
|
@total_count = scope.size
|
||||||
@users = paginate(scope)
|
@users = paginate(scope)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
#待办事项,现在未做
|
#待办事项,现在未做
|
||||||
if User.current.admin? || User.current.login == @user.login
|
if User.current.admin? || User.current.login == @user.login
|
||||||
@waiting_applied_messages = @user.applied_messages.waiting
|
@waiting_applied_messages = @user.applied_messages.waiting
|
||||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||||
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||||
else
|
else
|
||||||
@waiting_applied_messages = AppliedMessage.none
|
@waiting_applied_messages = AppliedMessage.none
|
||||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||||
@common_applied_projects = AppliedProject.none
|
@common_applied_projects = AppliedProject.none
|
||||||
@undo_events = 0
|
@undo_events = 0
|
||||||
end
|
end
|
||||||
#用户的组织数量
|
#用户的组织数量
|
||||||
# @user_composes_count = @user.composes.size
|
# @user_composes_count = @user.composes.size
|
||||||
@user_composes_count = 0
|
@user_composes_count = 0
|
||||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||||
@user_org_count = user_organizations.size
|
@user_org_count = user_organizations.size
|
||||||
normal_projects = Project.members_projects(@user.id).to_sql
|
normal_projects = Project.members_projects(@user.id).to_sql
|
||||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||||
@projects_common_count = user_projects.common.size
|
@projects_common_count = user_projects.common.size
|
||||||
@projects_mirrior_count = user_projects.mirror.size
|
@projects_mirrior_count = user_projects.mirror.size
|
||||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||||
# 为了缓存活跃用户的基本信息,后续删除
|
end
|
||||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
|
||||||
end
|
def watch_users
|
||||||
|
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||||
def watch_users
|
if params[:search].present?
|
||||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||||
if params[:search].present?
|
watchers = watchers.where(watchable_id: search_user_ids)
|
||||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
end
|
||||||
watchers = watchers.where(watchable_id: search_user_ids)
|
@watchers_count = watchers.size
|
||||||
end
|
@watchers = paginate(watchers)
|
||||||
@watchers_count = watchers.size
|
end
|
||||||
@watchers = paginate(watchers)
|
|
||||||
end
|
def fan_users
|
||||||
|
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||||
def fan_users
|
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
@watchers_count = watchers.size
|
||||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
@watchers = paginate(watchers)
|
||||||
@watchers_count = watchers.size
|
end
|
||||||
@watchers = paginate(watchers)
|
|
||||||
end
|
def hovercard
|
||||||
|
end
|
||||||
def hovercard
|
|
||||||
end
|
def update
|
||||||
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
def update
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
@user.attributes = user_params.except(:image)
|
||||||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
unless @user.save
|
||||||
@user.attributes = user_params.except(:image)
|
render_error(@user.errors.full_messages.join(", "))
|
||||||
unless @user.save
|
end
|
||||||
render_error(@user.errors.full_messages.join(", "))
|
end
|
||||||
end
|
|
||||||
end
|
def update_image
|
||||||
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
def me
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
@user = current_user
|
|
||||||
end
|
Util.write_file(@image, avatar_path(@user))
|
||||||
|
return render_ok({message: '头像修改成功'})
|
||||||
# 贴吧获取用户信接口
|
rescue Exception => e
|
||||||
def get_user_info
|
uid_logger_error(e.message)
|
||||||
begin
|
render_error(-1, '头像修改失败!')
|
||||||
@user = current_user
|
end
|
||||||
begin
|
|
||||||
result = Notice::Read::CountService.call(current_user.id)
|
def get_image
|
||||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
rescue
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
@message_unread_total = 0
|
|
||||||
end
|
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||||
# TODO 等消息上线再打开注释
|
end
|
||||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
|
||||||
rescue Exception => e
|
def me
|
||||||
uid_logger_error(e.message)
|
@user = current_user
|
||||||
missing_template
|
end
|
||||||
end
|
|
||||||
|
# 贴吧获取用户信接口
|
||||||
end
|
def get_user_info
|
||||||
|
begin
|
||||||
def attachment_show
|
@user = current_user
|
||||||
file_name = params[:file_name]
|
begin
|
||||||
path = params[:path] || file_storage_directory
|
result = Notice::Read::CountService.call(current_user.id)
|
||||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||||
:type => 'game',
|
rescue
|
||||||
:disposition => 'attachment' #inline can open in browser
|
@message_unread_total = 0
|
||||||
end
|
end
|
||||||
|
# TODO 等消息上线再打开注释
|
||||||
def html_show
|
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||||
@contents = File.read("#{params[:path]}")
|
rescue Exception => e
|
||||||
respond_to do |format|
|
uid_logger_error(e.message)
|
||||||
format.html {render :layout => false}
|
missing_template
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
end
|
||||||
# Redo: 消息总数缓存
|
|
||||||
def get_navigation_info
|
def attachment_show
|
||||||
# @old_domain = edu_setting('old_edu_host')
|
file_name = params[:file_name]
|
||||||
# @user = current_user
|
path = params[:path] || file_storage_directory
|
||||||
# # 新消息数
|
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
:type => 'game',
|
||||||
#
|
:disposition => 'attachment' #inline can open in browser
|
||||||
# @user_url = "/users/#{@user.login}"
|
end
|
||||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
|
||||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
def html_show
|
||||||
end
|
@contents = File.read("#{params[:path]}")
|
||||||
|
respond_to do |format|
|
||||||
# 用户回复功能
|
format.html {render :layout => false}
|
||||||
def reply_message
|
end
|
||||||
message = JournalsForMessage.new(reply_message_params)
|
end
|
||||||
message.user_id = current_user.id
|
|
||||||
message.save!
|
# Redo: 消息总数缓存
|
||||||
|
def get_navigation_info
|
||||||
render_ok(id: message.id)
|
# @old_domain = edu_setting('old_edu_host')
|
||||||
end
|
# @user = current_user
|
||||||
|
# # 新消息数
|
||||||
# 搜索用户具有管理员角色的项目
|
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||||
def search_user_projects
|
#
|
||||||
projects = Project.where.not(status: 9)
|
# @user_url = "/users/#{@user.login}"
|
||||||
|
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||||
projects = projects.where(members: { user_id: current_user.id })
|
end
|
||||||
|
|
||||||
search = params[:search].to_s.strip
|
# 用户回复功能
|
||||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
def reply_message
|
||||||
|
message = JournalsForMessage.new(reply_message_params)
|
||||||
@projects = projects.select(:id, :name)
|
message.user_id = current_user.id
|
||||||
end
|
message.save!
|
||||||
|
|
||||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
render_ok(id: message.id)
|
||||||
def homepage_info
|
end
|
||||||
#待办事项,现在未做
|
|
||||||
@undo_events = 10
|
# 搜索用户具有管理员角色的项目
|
||||||
#用户的组织数量
|
def search_user_projects
|
||||||
# @user_composes_count = @user.composes.size
|
projects = Project.where.not(status: 9)
|
||||||
@user_composes_count = 10
|
|
||||||
end
|
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||||
|
projects = projects.where(members: { user_id: current_user.id })
|
||||||
def brief_introduction
|
|
||||||
content = params[:content].to_s.strip
|
search = params[:search].to_s.strip
|
||||||
|
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||||
current_user.user_extension.update!(brief_introduction: content)
|
|
||||||
|
@projects = projects.select(:id, :name)
|
||||||
render_ok
|
end
|
||||||
end
|
|
||||||
|
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||||
def attendance
|
def homepage_info
|
||||||
attendance = Users::AttendanceService.call(current_user)
|
#待办事项,现在未做
|
||||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
@undo_events = 10
|
||||||
rescue Users::AttendanceService::Error => ex
|
#用户的组织数量
|
||||||
render_error(ex.message)
|
# @user_composes_count = @user.composes.size
|
||||||
end
|
@user_composes_count = 10
|
||||||
|
end
|
||||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
|
||||||
def sync_token
|
def brief_introduction
|
||||||
return render_error('未找相关用户!') unless @user
|
content = params[:content].to_s.strip
|
||||||
|
|
||||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
current_user.user_extension.update!(brief_introduction: content)
|
||||||
token.update_column(:value, params[:token])
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def trustie_related_projects
|
def attendance
|
||||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
attendance = Users::AttendanceService.call(current_user)
|
||||||
projects_json = []
|
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||||
domain_url = EduSetting.get('host_name')
|
rescue Users::AttendanceService::Error => ex
|
||||||
if projects.present?
|
render_error(ex.message)
|
||||||
projects.each do |p|
|
end
|
||||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
|
||||||
pj = {
|
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||||
id: p.id,
|
def sync_token
|
||||||
name: p.name,
|
return render_error('未找相关用户!') unless @user
|
||||||
is_public: p.is_public,
|
|
||||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||||
status: p.status,
|
token.update_column(:value, params[:token])
|
||||||
is_member: p.member?(current_user.try(:id)),
|
render_ok
|
||||||
owner: {
|
end
|
||||||
name: p.owner.try(:show_real_name),
|
|
||||||
login: p.owner.login
|
def trustie_related_projects
|
||||||
},
|
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||||
members_count: p&.members.size,
|
projects_json = []
|
||||||
issues_count: p.issues_count - p.pull_requests_count,
|
domain_url = EduSetting.get('host_name') + '/projects'
|
||||||
commits_count: p&.project_score&.changeset_num.to_i,
|
if projects.present?
|
||||||
http_url: domain_url + project_url,
|
projects.each do |p|
|
||||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||||
http_issues_url: domain_url + project_url + "/issues",
|
pj = {
|
||||||
http_commits_url: domain_url + project_url + "/commits",
|
id: p.id,
|
||||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
name: p.name,
|
||||||
}
|
is_public: p.is_public,
|
||||||
projects_json.push(pj)
|
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||||
end
|
status: p.status,
|
||||||
end
|
is_member: p.member?(current_user.try(:id)),
|
||||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
owner: {
|
||||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
name: p.owner.try(:show_real_name),
|
||||||
end
|
login: p.owner.login
|
||||||
|
},
|
||||||
def trustie_projects
|
members_count: p&.members.size,
|
||||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
issues_count: p.issues_count - p.pull_requests_count,
|
||||||
projects = Project.visible
|
commits_count: p&.project_score&.changeset_num.to_i,
|
||||||
|
http_url: domain_url + project_url,
|
||||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||||
|
http_issues_url: domain_url + project_url + "/issues",
|
||||||
search = params[:search].to_s.strip
|
http_commits_url: domain_url + project_url + "/commits",
|
||||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||||
|
}
|
||||||
projects = projects.select(:id, :name).limit(10).as_json
|
projects_json.push(pj)
|
||||||
render json: { projects: projects }
|
end
|
||||||
end
|
end
|
||||||
|
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||||
def projects
|
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
end
|
||||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
|
||||||
@total_count = scope.size
|
def trustie_projects
|
||||||
@projects = paginate(scope)
|
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||||
end
|
projects = Project.visible
|
||||||
|
|
||||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
|
||||||
def sync_gitea_pwd
|
search = params[:search].to_s.strip
|
||||||
return render_error("未找到相关的用户") if @user.blank?
|
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||||
|
|
||||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
projects = projects.select(:id, :name).limit(10).as_json
|
||||||
flag ? render_ok : render_error('同步失败!')
|
render json: { projects: projects }
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO
|
def projects
|
||||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
def sync_salt
|
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||||
user = User.find_by_login params[:login]
|
@total_count = scope.size
|
||||||
return if user.blank?
|
@projects = paginate(scope)
|
||||||
user.update_column(:salt, params[:salt])
|
end
|
||||||
render_ok
|
|
||||||
end
|
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||||
|
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||||
def sync_user_info
|
def sync_gitea_pwd
|
||||||
user = User.find_by_login params[:login]
|
return render_error("未找到相关的用户") if @user.blank?
|
||||||
return render_forbidden unless user === current_user
|
|
||||||
|
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||||
sync_params = {
|
flag ? render_ok : render_error('同步失败!')
|
||||||
email: params[:email],
|
end
|
||||||
password: params[:password]
|
|
||||||
}
|
# TODO
|
||||||
|
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
def sync_salt
|
||||||
|
user = User.find_by_login params[:login]
|
||||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
return if user.blank?
|
||||||
if interactor.success?
|
user.update_column(:salt, params[:salt])
|
||||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO)
|
render_ok
|
||||||
render_ok
|
end
|
||||||
else
|
|
||||||
render_error(interactor.error)
|
# TODO: For Educoder
|
||||||
end
|
def change_password
|
||||||
end
|
user = User.find_by_login params[:login]
|
||||||
|
return render_error("用户 #{params[:login]} 不存在.") if user.nil?
|
||||||
private
|
|
||||||
def load_user
|
form_params= {
|
||||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
login: params[:login],
|
||||||
end
|
email: user&.mail,
|
||||||
|
password: params[:password],
|
||||||
def user_params
|
user: user
|
||||||
params.require(:user).permit(:nickname, :image,
|
}
|
||||||
user_extension_attributes: [
|
Gitea::User::ChangePasswordForm.new(form_params).validate!
|
||||||
:gender, :location, :location_city,
|
|
||||||
:occupation, :technical_title,
|
sync_params = {
|
||||||
:school_id, :department_id, :province, :city,
|
password: params[:password].to_s,
|
||||||
:custom_department, :identity, :student_id, :description,
|
email: user.mail,
|
||||||
:show_email, :show_location, :show_department]
|
login_name: user.login,
|
||||||
)
|
source_id: 0
|
||||||
end
|
}
|
||||||
|
|
||||||
def reply_message_params
|
if sync_params.present?
|
||||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
if interactor.success?
|
||||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
user.update!(password: params[:password], is_sync_pwd: true)
|
||||||
end
|
render_ok
|
||||||
|
else
|
||||||
def check_user_exist
|
render_error(interactor.error)
|
||||||
return if @user.present?
|
end
|
||||||
render_not_found
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
# TODO: For Educoder
|
||||||
|
def change_email
|
||||||
|
user = User.find_by_login params[:login]
|
||||||
|
return render_error("用户 #{rq_params[:login]} 不存在.") if user.nil?
|
||||||
|
|
||||||
|
form_params= {
|
||||||
|
login: params[:login],
|
||||||
|
email: user&.mail,
|
||||||
|
user: user
|
||||||
|
}
|
||||||
|
|
||||||
|
Gitea::User::ChangeEmailForm.new(form_params).validate!
|
||||||
|
|
||||||
|
sync_params = {
|
||||||
|
email: params[:email]
|
||||||
|
}
|
||||||
|
|
||||||
|
if sync_params.present?
|
||||||
|
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||||
|
if interactor.success?
|
||||||
|
user.update!(mail: params[:email])
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
render_error(interactor.error)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def email_search
|
||||||
|
return render_error('请输入email') if params[:email].blank?
|
||||||
|
@user = User.find_by(mail: params[:email])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def load_user
|
||||||
|
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_params
|
||||||
|
params.require(:user).permit(:nickname, :image,
|
||||||
|
user_extension_attributes: [
|
||||||
|
:gender, :location, :location_city,
|
||||||
|
:occupation, :technical_title,
|
||||||
|
:school_id, :department_id, :province, :city,
|
||||||
|
:custom_department, :identity, :student_id, :description,
|
||||||
|
:show_super_description, :super_description,
|
||||||
|
:show_email, :show_location, :show_department]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reply_message_params
|
||||||
|
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||||
|
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||||
|
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_user_exist
|
||||||
|
return if @user.present?
|
||||||
|
render_not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ class VersionReleasesController < ApplicationController
|
||||||
def new
|
def new
|
||||||
#获取所有的分支
|
#获取所有的分支
|
||||||
@all_branches = []
|
@all_branches = []
|
||||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
|
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier), params[:branch_name]).call
|
||||||
if get_all_branches && get_all_branches.size > 0
|
if get_all_branches && get_all_branches.size > 0
|
||||||
get_all_branches.each do |b|
|
get_all_branches.each do |b|
|
||||||
@all_branches.push(b["name"])
|
@all_branches.push(b["name"])
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
---
|
---
|
||||||
title: Trustie API Reference
|
title: GitLink API Reference
|
||||||
|
|
||||||
language_tabs: # must be one of https://git.io/vQNgJ
|
language_tabs: # must be one of https://git.io/vQNgJ
|
||||||
- shell: Shell
|
- shell: Shell
|
||||||
- javascript: JavaScript
|
- javascript: JavaScript
|
||||||
|
|
||||||
toc_footers:
|
toc_footers:
|
||||||
- <a href='https://www.trustie.net/login?login=false'>Sign Up for a User</a>
|
- <a href='https://www.gitlink.org.cn/login'>Sign In for a User</a>
|
||||||
- <a href='https://www.trustie.net'>Powered by Trustie</a>
|
- <a href='https://www.gitlink.org.cn'>Powered by GitLink</a>
|
||||||
|
|
||||||
includes:
|
includes:
|
||||||
- licenses
|
- licenses
|
||||||
|
@ -30,8 +30,8 @@ code_clipboard: true
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
Welcome to the Trustie API! You can use our API to access Trustie API endpoints, which can get information on projects, repository, and users in our platform.
|
Welcome to the GitLink API! You can use our API to access GitLink API endpoints, which can get information on projects, repository, and users in our platform.
|
||||||
|
|
||||||
We have language bindings in Shell,avaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
|
We have language bindings in Shell,avaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
|
||||||
|
|
||||||
This example API documentation page was created with [Trustie](https://www.trustie.net). Feel free to edit it and use it as a base for your own API's documentation.
|
This example API documentation page was created with [GitLink](https://www.gitlink.org.cn). Feel free to edit it and use it as a base for your own API's documentation.
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1,4 +1,278 @@
|
||||||
# Projects
|
# Projects
|
||||||
|
## 获取项目邀请链接(项目管理员)
|
||||||
|
当前登录(管理员)用户获取项目邀请链接的接口(第一次请求会默认生成role类型为developer和is_apply为true的链接)
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/current_link.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/yystopf/kellect/project_invite_links/current_link.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET /api/:owner/:repo/project_invite_links/current_link.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||||
|
|is_apply |是| |boolean |是否需要审核 |
|
||||||
|
|
||||||
|
### 返回字段说明
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|id |int |链接id |
|
||||||
|
|role |string |邀请角色|
|
||||||
|
|is_apply |boolean |是否需要审核 |
|
||||||
|
|sign |string |邀请标识(放在链接后面即可)|
|
||||||
|
|expired_at |string |链接过期时间|
|
||||||
|
|user.id |int |链接创建者的id |
|
||||||
|
|user.type |string |链接创建者的类型 |
|
||||||
|
|user.name |string |链接创建者的名称 |
|
||||||
|
|user.login |string |链接创建者的标识 |
|
||||||
|
|user.image_url |string |链接创建者头像 |
|
||||||
|
|project.id |int |链接关联项目的id |
|
||||||
|
|project.identifier |string |链接关联项目的标识 |
|
||||||
|
|project.name |string |链接关联项目的名称 |
|
||||||
|
|project.description |string |链接关联项目的描述 |
|
||||||
|
|project.is_public |bool |链接关联项目是否公开 |
|
||||||
|
|project.owner.id |bool |链接关联项目拥有者id |
|
||||||
|
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||||
|
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||||
|
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||||
|
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"role": "developer",
|
||||||
|
"is_apply": false,
|
||||||
|
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||||
|
"expired_at": "2022-06-23 10:08",
|
||||||
|
"user": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"id": 474,
|
||||||
|
"identifier": "kellect",
|
||||||
|
"name": "kellect",
|
||||||
|
"description": null,
|
||||||
|
"is_public": true,
|
||||||
|
"owner": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## 生成项目邀请链接(项目管理员)
|
||||||
|
当前登录(管理员)用户生成的项目邀请链接,可选role和is_apply参数
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/generate_link.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/yystopf/kellect/project_invite_links/generate_link.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/:owner/:repo/project_invite_links/generate_link.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||||
|
|is_apply |是| |boolean |是否需要审核 |
|
||||||
|
|
||||||
|
|
||||||
|
> 请求的JSON示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"role": "developer",
|
||||||
|
"is_apply": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回字段说明
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|id |int |链接id |
|
||||||
|
|role |string |邀请角色|
|
||||||
|
|is_apply |boolean |是否需要审核 |
|
||||||
|
|sign |string |邀请标识(放在链接后面即可)|
|
||||||
|
|expired_at |string |链接过期时间|
|
||||||
|
|user.id |int |链接创建者的id |
|
||||||
|
|user.type |string |链接创建者的类型 |
|
||||||
|
|user.name |string |链接创建者的名称 |
|
||||||
|
|user.login |string |链接创建者的标识 |
|
||||||
|
|user.image_url |string |链接创建者头像 |
|
||||||
|
|project.id |int |链接关联项目的id |
|
||||||
|
|project.identifier |string |链接关联项目的标识 |
|
||||||
|
|project.name |string |链接关联项目的名称 |
|
||||||
|
|project.description |string |链接关联项目的描述 |
|
||||||
|
|project.is_public |bool |链接关联项目是否公开 |
|
||||||
|
|project.owner.id |bool |链接关联项目拥有者id |
|
||||||
|
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||||
|
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||||
|
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||||
|
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"role": "developer",
|
||||||
|
"is_apply": false,
|
||||||
|
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||||
|
"expired_at": "2022-06-23 10:08",
|
||||||
|
"user": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"id": 474,
|
||||||
|
"identifier": "kellect",
|
||||||
|
"name": "kellect",
|
||||||
|
"description": null,
|
||||||
|
"is_public": true,
|
||||||
|
"owner": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 获取邀请链接信息(被邀请用户)
|
||||||
|
用户请求邀请链接时,通过该接口来获取链接的信息
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/:owner/:repo/project_invite_links/show_link.json?invite_sign=xxx`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||||
|
|
||||||
|
### 返回字段说明
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|id |int |链接id |
|
||||||
|
|role |string |邀请角色|
|
||||||
|
|is_apply |boolean |是否需要审核 |
|
||||||
|
|sign |string |邀请标识(放在链接后面即可)|
|
||||||
|
|expired_at |string |链接过期时间|
|
||||||
|
|user.id |int |链接创建者的id |
|
||||||
|
|user.type |string |链接创建者的类型 |
|
||||||
|
|user.name |string |链接创建者的名称 |
|
||||||
|
|user.login |string |链接创建者的标识 |
|
||||||
|
|user.image_url |string |链接创建者头像 |
|
||||||
|
|project.id |int |链接关联项目的id |
|
||||||
|
|project.identifier |string |链接关联项目的标识 |
|
||||||
|
|project.name |string |链接关联项目的名称 |
|
||||||
|
|project.description |string |链接关联项目的描述 |
|
||||||
|
|project.is_public |bool |链接关联项目是否公开 |
|
||||||
|
|project.owner.id |bool |链接关联项目拥有者id |
|
||||||
|
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||||
|
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||||
|
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||||
|
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"role": "developer",
|
||||||
|
"is_apply": false,
|
||||||
|
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||||
|
"expired_at": "2022-06-23 10:08",
|
||||||
|
"user": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"id": 474,
|
||||||
|
"identifier": "kellect",
|
||||||
|
"name": "kellect",
|
||||||
|
"description": null,
|
||||||
|
"is_public": true,
|
||||||
|
"owner": {
|
||||||
|
"id": 2,
|
||||||
|
"type": "User",
|
||||||
|
"name": "heh",
|
||||||
|
"login": "yystopf",
|
||||||
|
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接受项目邀请链接(被邀请用户)
|
||||||
|
当前登录(非项目)用户加入项目的接口,如果项目链接不需要审核,请求成功后即加入项目,如果需要审核,那么会提交一个申请,需要项目管理员审核
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/:owner/:repo/project_invite_links/redirect_link.json?invite_sign=xxx`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 申请加入项目
|
## 申请加入项目
|
||||||
申请加入项目
|
申请加入项目
|
||||||
|
@ -280,7 +554,7 @@ repo |是| |string |项目标识identifier
|
||||||
### 返回字段说明
|
### 返回字段说明
|
||||||
参数 | 类型 | 字段说明
|
参数 | 类型 | 字段说明
|
||||||
--------- | ----------- | -----------
|
--------- | ----------- | -----------
|
||||||
menu_name |string|导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||||
|
|
||||||
|
|
||||||
> 返回的JSON示例:
|
> 返回的JSON示例:
|
||||||
|
@ -408,7 +682,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
|
||||||
### 请求参数
|
### 请求参数
|
||||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
--------- | ------- | ------- | -------- | ----------
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||||
|
|
||||||
|
|
||||||
### 返回字段说明:
|
### 返回字段说明:
|
||||||
|
@ -849,4 +1123,36 @@ await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.j
|
||||||
"created_at": "2021-04-26 09:54",
|
"created_at": "2021-04-26 09:54",
|
||||||
"time_ago": "1分钟前"
|
"time_ago": "1分钟前"
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 退出项目
|
||||||
|
供项目成员(开发者、报告者)退出项目用
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/quit.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/:owner/:repo/quit.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/:owner/:repo/quit.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
```
|
```
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue