Compare commits
602 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07d93716aa | ||
|
|
88b5e0b703 | ||
|
|
32fa312b2a | ||
|
|
1306d637a2 | ||
|
|
462b3752e4 | ||
|
|
029f2c4545 | ||
|
|
b3e7beb7c5 | ||
|
|
a549d1ae6b | ||
|
|
467456f7a1 | ||
|
|
2374d63536 | ||
|
|
117eb3b2bc | ||
|
|
de985a30bc | ||
|
|
06d905f415 | ||
|
|
0ad41be0f3 | ||
|
|
d6f5dbff3e | ||
|
|
1e665a0bf4 | ||
|
|
ef16089c6d | ||
|
|
4b4ea1f929 | ||
|
|
45af29912f | ||
|
|
9075c90c46 | ||
|
|
63a2566007 | ||
|
|
43cad817e8 | ||
|
|
ed4c754fff | ||
|
|
1e0c7a0afc | ||
|
|
3a3b556065 | ||
|
|
9244f6b628 | ||
|
|
ff26b72333 | ||
|
|
6803935c4d | ||
|
|
3757546f1b | ||
|
|
a677ac8384 | ||
|
|
bdbfb10cff | ||
|
|
4d661e1183 | ||
|
|
dd28b557ae | ||
|
|
0e0f18ce7c | ||
|
|
7964bfccdb | ||
|
|
3c515f2cd2 | ||
|
|
db73ac92d7 | ||
|
|
4cd82d442e | ||
|
|
311871eefc | ||
|
|
a929f7e6ac | ||
|
|
cf51e07bde | ||
|
|
8d6c3cd48a | ||
|
|
3817704806 | ||
|
|
d4c6bf770d | ||
|
|
399f9f4a4e | ||
|
|
f2390e2803 | ||
|
|
dbaa6a0e13 | ||
|
|
7bf7ed6123 | ||
|
|
a390abdefb | ||
|
|
c1bc5e14eb | ||
|
|
4b911fea03 | ||
|
|
1fcdaafa6f | ||
|
|
f24b81e27f | ||
|
|
e01966f7b8 | ||
|
|
dcb9497148 | ||
|
|
4f2513337f | ||
|
|
015269914e | ||
|
|
bbdcfd6baf | ||
|
|
f0d6550f16 | ||
|
|
8400bee3b1 | ||
|
|
bc1f9dc24b | ||
|
|
cdc349a2d1 | ||
|
|
c2c93f8cd6 | ||
|
|
9fc082ea81 | ||
|
|
4c7a9adb98 | ||
|
|
030e5cec58 | ||
|
|
716f4cb11c | ||
|
|
a5a07da892 | ||
|
|
72108b20e2 | ||
|
|
767117f9b0 | ||
|
|
fb7f06a752 | ||
|
|
0b4006fc47 | ||
|
|
0ccd47f413 | ||
|
|
02f896c12e | ||
|
|
bb4c3831b2 | ||
|
|
3267e4a785 | ||
|
|
89b988cab5 | ||
|
|
4d42a38954 | ||
|
|
8387b3928e | ||
|
|
afa52e4d63 | ||
|
|
8949aad030 | ||
|
|
c0c7af2194 | ||
|
|
f5382ec085 | ||
|
|
407073d7a2 | ||
|
|
7f4375822a | ||
|
|
719ab720a7 | ||
|
|
b11ac88692 | ||
|
|
681c33d1f4 | ||
|
|
7f35947d8e | ||
|
|
68941d4dfa | ||
|
|
1d2616b79b | ||
|
|
d4b097a88c | ||
|
|
902c5cf7ca | ||
|
|
b15f790221 | ||
|
|
a47c2e8890 | ||
|
|
a3202fd51e | ||
|
|
1cceefce33 | ||
|
|
033f970af3 | ||
|
|
d1c3e35d3f | ||
|
|
a6328fc1b1 | ||
|
|
35b868eeca | ||
|
|
695439775e | ||
|
|
05cd37097c | ||
|
|
bd915d9398 | ||
|
|
8c45cd0e36 | ||
|
|
3fbf1bf35a | ||
|
|
cd9b2ab2f7 | ||
|
|
de397f3bc1 | ||
|
|
72bd73f605 | ||
|
|
1896a154f5 | ||
|
|
1618b68bfa | ||
|
|
c1f201c49a | ||
|
|
8d224ad23b | ||
|
|
e2685ccc81 | ||
|
|
c42092ba7a | ||
|
|
999170d898 | ||
|
|
37430a3401 | ||
|
|
0fa9dd8527 | ||
|
|
489d162477 | ||
|
|
9008ab3407 | ||
|
|
87b96f8d33 | ||
|
|
a49be27145 | ||
|
|
27b2355738 | ||
|
|
eeb5923e89 | ||
|
|
a9067167bb | ||
|
|
a9a0c854e1 | ||
|
|
0c7c188c45 | ||
|
|
c2753fdfb4 | ||
|
|
c29c20ab3c | ||
|
|
880a5eb25c | ||
|
|
e48d3bfd01 | ||
|
|
5abb3d8150 | ||
|
|
c45a75ad34 | ||
|
|
3567ac3d3e | ||
|
|
43f868de3d | ||
|
|
f41590912d | ||
|
|
056b5ed72f | ||
|
|
1764c32b9e | ||
|
|
b21ab498f8 | ||
|
|
1c6c6b271c | ||
|
|
e6c81a635b | ||
|
|
f93de3a516 | ||
|
|
e19eefe219 | ||
|
|
8784bd79d0 | ||
|
|
31366334cb | ||
|
|
425acecfdb | ||
|
|
29f314a502 | ||
|
|
cc68d1945b | ||
|
|
7bacdd718a | ||
|
|
958fe0f7db | ||
|
|
e670fa2af6 | ||
|
|
a3d93e8bbe | ||
|
|
7a889a8e12 | ||
|
|
d081d4a422 | ||
|
|
34ccc058fa | ||
|
|
7f9a353b94 | ||
|
|
31490e0d6c | ||
|
|
ca45bd0361 | ||
|
|
63baab088d | ||
|
|
2b9721d1b3 | ||
|
|
617208053c | ||
|
|
4aa6cd66fc | ||
|
|
1c6cbdd4e4 | ||
|
|
f8212da329 | ||
|
|
4122a837fa | ||
|
|
5fa2dd6e65 | ||
|
|
307f3e0dd7 | ||
|
|
fc4c74660b | ||
|
|
caf938562e | ||
|
|
ce3a371eee | ||
|
|
8781a8e203 | ||
|
|
37c832cdf7 | ||
|
|
f68fa930ea | ||
|
|
007ab330e6 | ||
|
|
794781d121 | ||
|
|
91cacb1e8f | ||
|
|
46f5d3a2e9 | ||
|
|
76318f8830 | ||
|
|
852bda3d32 | ||
|
|
0324f807f4 | ||
|
|
864e3f8d9c | ||
|
|
102466ac58 | ||
|
|
63b77f2320 | ||
|
|
8fecd80108 | ||
|
|
348d6f5e75 | ||
|
|
00df69bc89 | ||
|
|
7a549f830e | ||
|
|
3f82d8b979 | ||
|
|
9fe6cfca48 | ||
|
|
ebd2dde688 | ||
|
|
6e1261f277 | ||
|
|
91d548f7e6 | ||
|
|
76eda2fc21 | ||
|
|
1c1819a78a | ||
|
|
8b2cad5637 | ||
|
|
2d6128672f | ||
|
|
185b41beb4 | ||
|
|
2083000027 | ||
|
|
18d3fa953b | ||
|
|
f76e71825d | ||
|
|
6bf6d35637 | ||
|
|
9c03fd9cae | ||
|
|
34c8a46d7d | ||
|
|
26949607d2 | ||
|
|
e7c0d87d98 | ||
|
|
6d106d3943 | ||
|
|
a37cf9548c | ||
|
|
5e6acf9601 | ||
|
|
b52a5e6bd6 | ||
|
|
bb194ddb3c | ||
|
|
a38b34c37a | ||
|
|
1921ab40ea | ||
|
|
976c18aa5f | ||
|
|
4cddef1cea | ||
|
|
cbe94b88e2 | ||
|
|
275c5b51ed | ||
|
|
f85dbe83c8 | ||
|
|
a9c326b200 | ||
|
|
92f1c474f3 | ||
|
|
a6d02cff36 | ||
|
|
be94f9e35d | ||
|
|
e282580101 | ||
|
|
331f0953e9 | ||
|
|
133b892e0d | ||
|
|
60da49f856 | ||
|
|
d1d94216d1 | ||
|
|
bf50e3e5ae | ||
|
|
a978b88997 | ||
|
|
6dd5eac7fc | ||
|
|
968354923e | ||
|
|
59ddf81a45 | ||
|
|
3a7106f05a | ||
|
|
5c7a4f0b32 | ||
|
|
0e09048537 | ||
|
|
7362469d89 | ||
|
|
1273fbf86e | ||
|
|
a27879c0cf | ||
|
|
049cea30b0 | ||
|
|
b342c81c17 | ||
|
|
ead14f5bf0 | ||
|
|
0a53ca444a | ||
|
|
f79c10162e | ||
|
|
60b2b56d38 | ||
|
|
b6a19e7b89 | ||
|
|
71bc75e6ac | ||
|
|
e4fee6c138 | ||
|
|
7d8e3721ae | ||
|
|
fb421a1f46 | ||
|
|
2a9805b987 | ||
|
|
126f929c39 | ||
|
|
da42bfadb5 | ||
|
|
6ad72728f6 | ||
|
|
64d9c016bd | ||
|
|
12e7c81dd8 | ||
|
|
16d0aed403 | ||
|
|
da9317fa56 | ||
|
|
be92babd00 | ||
|
|
e2dd576a1b | ||
|
|
8f2c91568c | ||
|
|
98eaa2aa27 | ||
|
|
42b8220632 | ||
|
|
a91d968cab | ||
|
|
646de92781 | ||
|
|
ae2b722f55 | ||
|
|
7aeb9168b0 | ||
|
|
f53ed108b0 | ||
|
|
285038972b | ||
|
|
e5563843a2 | ||
|
|
c972e1ee1f | ||
|
|
5e8d037e27 | ||
|
|
ed7dc1704d | ||
|
|
436ce03772 | ||
|
|
d821aba002 | ||
|
|
4ce1540094 | ||
|
|
67243bda31 | ||
|
|
8f991831b8 | ||
|
|
87efa38721 | ||
|
|
f7301bd5b9 | ||
|
|
099a3b4eac | ||
|
|
3d4e21f1ec | ||
|
|
68dca26a5d | ||
|
|
1fc096ec75 | ||
|
|
21c2bc119c | ||
|
|
d23293c762 | ||
|
|
138e5a0b1e | ||
|
|
79dacea962 | ||
|
|
4e6b5e7879 | ||
|
|
c0979381a4 | ||
|
|
676f577e7e | ||
|
|
c1a8e3d1eb | ||
|
|
0c44316b22 | ||
|
|
2211e8d1cd | ||
|
|
3783cadf2d | ||
|
|
a071047c13 | ||
|
|
281f07244b | ||
|
|
6f34a6a77f | ||
|
|
e078919f07 | ||
|
|
7b13e6efc2 | ||
|
|
3f59238207 | ||
|
|
eff9416469 | ||
|
|
6fbb3841a6 | ||
|
|
d8c4781377 | ||
|
|
bc6e958229 | ||
|
|
a6d8d1036a | ||
|
|
3d403a013d | ||
|
|
9ca02a00a6 | ||
|
|
3e8e9c8ae4 | ||
|
|
7bc1805827 | ||
|
|
e27f792c24 | ||
|
|
98fab24bea | ||
|
|
f566c47dda | ||
|
|
0190aac240 | ||
|
|
cc382c5006 | ||
|
|
946a166791 | ||
|
|
31cd649041 | ||
|
|
1585b0c6cc | ||
|
|
15b43f555d | ||
|
|
d8ec832806 | ||
|
|
bab5a18232 | ||
|
|
a20cf3b64e | ||
|
|
356df7ae6b | ||
|
|
8f03fdce7f | ||
|
|
1fc6cb4997 | ||
|
|
eb832e88f4 | ||
|
|
b16b69350e | ||
|
|
da6fa029f6 | ||
|
|
94ad0706f5 | ||
|
|
bf8c2c4348 | ||
|
|
aa58cca040 | ||
|
|
5cc7cd8518 | ||
|
|
ff142eb64d | ||
|
|
500e28442f | ||
|
|
5bd3715a4c | ||
|
|
3d13f6ea0c | ||
|
|
6eefccdacc | ||
|
|
29a22691d2 | ||
|
|
d55f207274 | ||
|
|
cf6fe4f8cb | ||
|
|
4367443287 | ||
|
|
8d2b3ada80 | ||
|
|
f3be605286 | ||
|
|
aebebdc5d1 | ||
|
|
05e4728de7 | ||
|
|
b51945f096 | ||
|
|
1f2abd8d67 | ||
|
|
1d9f9352a6 | ||
|
|
53e42bf91e | ||
|
|
94d0e012de | ||
|
|
8fd931dc12 | ||
|
|
74d10b9b9d | ||
|
|
2356580cee | ||
|
|
1840a352f5 | ||
|
|
c93d0978f2 | ||
|
|
df4f4e94b3 | ||
|
|
51b2f789bd | ||
|
|
947887f261 | ||
|
|
6f34fdb616 | ||
|
|
8518d005fd | ||
|
|
bb911043de | ||
|
|
da0333f1cb | ||
|
|
d8a0ee1956 | ||
|
|
91c71471ab | ||
|
|
98eacb2238 | ||
|
|
80c13bf0ef | ||
|
|
e17c2e5da5 | ||
|
|
4a618908e8 | ||
|
|
a208e7d655 | ||
|
|
c1b9ae7fc2 | ||
|
|
dc8a6244fc | ||
|
|
0f52e42c2d | ||
|
|
85af2405cf | ||
|
|
47ace633dc | ||
|
|
85d5518b6b | ||
|
|
5104bd7988 | ||
|
|
3e425b51fd | ||
|
|
37dbfa4cd7 | ||
|
|
0d23c81662 | ||
|
|
b436b31d5a | ||
|
|
72133fbed6 | ||
|
|
abbdacedc5 | ||
|
|
ddd3251912 | ||
|
|
605e2a417c | ||
|
|
f8fe394e7a | ||
|
|
2a545e0fb1 | ||
|
|
ce812466c7 | ||
|
|
47bf7a8047 | ||
|
|
85d405c810 | ||
|
|
f596a413ef | ||
|
|
9e53fe5c29 | ||
|
|
3690f04e4a | ||
|
|
f3e8bc9f8f | ||
|
|
dcf0530218 | ||
|
|
47338bc13d | ||
|
|
6fb9726b99 | ||
|
|
8015fd7600 | ||
|
|
4919b89ab8 | ||
|
|
2925372ff4 | ||
|
|
778430b54a | ||
|
|
5282ba862a | ||
|
|
0464602978 | ||
|
|
9b03cf0ddd | ||
|
|
cdff1da901 | ||
|
|
1a065fb146 | ||
|
|
022008a2a6 | ||
|
|
a3715598cc | ||
|
|
1be48dd805 | ||
|
|
6384041d17 | ||
|
|
140e73bc82 | ||
|
|
e3fae6f52c | ||
|
|
65d8c73bae | ||
|
|
177dd8bb53 | ||
|
|
380b20eed6 | ||
|
|
c207b4bb33 | ||
|
|
b87eb8ea14 | ||
|
|
8902e265b4 | ||
|
|
b8ea28d6d0 | ||
|
|
f741673638 | ||
|
|
0a0b9a271a | ||
|
|
7d2b4186c3 | ||
|
|
90689190a3 | ||
|
|
8acadeea76 | ||
|
|
75c6513c67 | ||
|
|
73540ffe6b | ||
|
|
92bb166246 | ||
|
|
8cf8ce4ac0 | ||
|
|
0f1b1d78b1 | ||
|
|
d3bbef27e7 | ||
|
|
f0634ba876 | ||
|
|
1d68fe1a60 | ||
|
|
6bd6dcf6df | ||
|
|
28d2920472 | ||
|
|
34bfea8bbf | ||
|
|
2d91944285 | ||
|
|
0026ba2751 | ||
|
|
b623dd12c1 | ||
|
|
722d152082 | ||
|
|
7623766241 | ||
|
|
e34c5a3503 | ||
|
|
004672aa6c | ||
|
|
ad4a28f4f6 | ||
|
|
d8ae3efec3 | ||
|
|
cd81a1c52a | ||
|
|
dcf73ddeff | ||
|
|
d81b706f12 | ||
|
|
30fa5fe1a4 | ||
|
|
7a7bfa5170 | ||
|
|
e969c78645 | ||
|
|
7adac1bc51 | ||
|
|
e859d6f259 | ||
|
|
a0880edc6e | ||
|
|
61fcdbbf7e | ||
|
|
43af695ba1 | ||
|
|
facd90e7a6 | ||
|
|
6201f96b8a | ||
|
|
c26cea262b | ||
|
|
1f1d6bf2a0 | ||
|
|
4c06d1cb24 | ||
|
|
2985d08951 | ||
|
|
66ca7157db | ||
|
|
4addf051d4 | ||
|
|
ab914ce6d5 | ||
|
|
6a4b224397 | ||
|
|
6adbd114c1 | ||
|
|
037f96c5ae | ||
|
|
f54dca06a9 | ||
|
|
370fa70924 | ||
|
|
5be1214c26 | ||
|
|
f7a30e2fae | ||
|
|
3f815b2052 | ||
|
|
defe4f9bc3 | ||
|
|
943775fd90 | ||
|
|
42844df966 | ||
|
|
b0fe58dc69 | ||
|
|
e07b57852e | ||
|
|
7c7c18fdea | ||
|
|
a84664026e | ||
|
|
02a0fd5b64 | ||
|
|
6505a42be0 | ||
|
|
e674608d10 | ||
|
|
c7af8cbc90 | ||
|
|
9475fbae78 | ||
|
|
00e61d6807 | ||
|
|
19084d3c6c | ||
|
|
e014bf8ed0 | ||
|
|
f6e2309e70 | ||
|
|
9d2154c4ab | ||
|
|
1dfd27a028 | ||
|
|
b97ebaf620 | ||
|
|
8ee2eb5d2e | ||
|
|
20b647020b | ||
|
|
3eedad2737 | ||
|
|
ce7c0def88 | ||
|
|
dab8fc4584 | ||
|
|
8a597f0138 | ||
|
|
3363f2f4d6 | ||
|
|
c7f2d6af55 | ||
|
|
e878ddb7c0 | ||
|
|
336f0b0823 | ||
|
|
3ea3f24a02 | ||
|
|
d567a382e3 | ||
|
|
18fe77084f | ||
|
|
dc253ea234 | ||
|
|
9304114b57 | ||
|
|
1fd5251376 | ||
|
|
edddc7c791 | ||
|
|
10768aa204 | ||
|
|
e98559c3ff | ||
|
|
2212dc4aaa | ||
|
|
e1fdac3e9a | ||
|
|
1162f61ca3 | ||
|
|
39ea5c0e2e | ||
|
|
509b0cfafc | ||
|
|
fda5c699c2 | ||
|
|
cb7ee4698f | ||
|
|
d010e270e6 | ||
|
|
d1e08bd38c | ||
|
|
dbccdcc1b1 | ||
|
|
5c63523972 | ||
|
|
de4681b2be | ||
|
|
a132332b86 | ||
|
|
b25e42a77f | ||
|
|
5236a62861 | ||
|
|
0f155829b7 | ||
|
|
84dda45df9 | ||
|
|
9c7505489f | ||
|
|
75cad1d9d6 | ||
|
|
2cc3111a77 | ||
|
|
bf811e4d4a | ||
|
|
d6774d2ca3 | ||
|
|
bd669e3907 | ||
|
|
1a4860a57a | ||
|
|
41fa53253c | ||
|
|
c00ead8a72 | ||
|
|
e49dc6a06e | ||
|
|
0e12a8dab9 | ||
|
|
3652a39de0 | ||
|
|
79335e46fd | ||
|
|
7c6e02aaf3 | ||
|
|
7f55430652 | ||
|
|
8235623362 | ||
|
|
83435c49ea | ||
|
|
93de41b39b | ||
|
|
b1d4b74a44 | ||
|
|
bfdf47bc98 | ||
|
|
33f669a5f8 | ||
|
|
3576fa0d59 | ||
|
|
1dcfb90202 | ||
|
|
22cf18e16f | ||
|
|
0ebe7d6d23 | ||
|
|
23081bb299 | ||
|
|
4c7fe48c40 | ||
|
|
499cc7b803 | ||
|
|
7db98aa70e | ||
|
|
e031fd60ad | ||
|
|
bc4fad9e22 | ||
|
|
5ac4d677e9 | ||
|
|
b42bdd80e8 | ||
|
|
76fa9d2488 | ||
|
|
dfc43a6d3d | ||
|
|
67bc58dd60 | ||
|
|
2d39560dc1 | ||
|
|
c49ff7395e | ||
|
|
e0ada97770 | ||
|
|
3a2003ba86 | ||
|
|
9a81be0d37 | ||
|
|
5e2c5e95b6 | ||
|
|
34a93ccf57 | ||
|
|
922fb74197 | ||
|
|
7bf2d6cb06 | ||
|
|
11e5c965c3 | ||
|
|
34157d118c | ||
|
|
7b92950f1c | ||
|
|
97d7028c31 | ||
|
|
a7f2961621 | ||
|
|
00dda99789 | ||
|
|
2e27ce3b61 | ||
|
|
2c10c5a069 | ||
|
|
bd4dd4c4a0 | ||
|
|
7d33b60f3f | ||
|
|
aecce5694b | ||
|
|
0e4ca51951 | ||
|
|
dde043f6cd | ||
|
|
c778a60e4f | ||
|
|
c347327d54 | ||
|
|
fd328cf6e8 | ||
|
|
7b473d7514 | ||
|
|
dff576b75d | ||
|
|
52ae83d008 | ||
|
|
5aacd9d4c7 | ||
|
|
d24d3fa283 | ||
|
|
c8a226f61c | ||
|
|
7a281c477a | ||
|
|
91c789ec63 | ||
|
|
9ead3d1cdb | ||
|
|
402c19a924 | ||
|
|
b5e8994844 | ||
|
|
4bd327a0c5 | ||
|
|
184325077e | ||
|
|
8236f942ff | ||
|
|
8963f8c3c2 | ||
|
|
5e41c26203 | ||
|
|
45837c533e |
7
.babelrc
7
.babelrc
@@ -14,14 +14,16 @@
|
|||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"syntax-dynamic-import",
|
"syntax-dynamic-import",
|
||||||
"transform-object-rest-spread",
|
["transform-object-rest-spread", { "useBuiltIns": true }],
|
||||||
|
"transform-decorators-legacy",
|
||||||
"transform-class-properties",
|
"transform-class-properties",
|
||||||
[
|
[
|
||||||
"react-intl",
|
"react-intl",
|
||||||
{
|
{
|
||||||
"messagesDir": "./build/messages"
|
"messagesDir": "./build/messages"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"preval"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"development": {
|
"development": {
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"transform-react-inline-elements",
|
||||||
[
|
[
|
||||||
"transform-runtime",
|
"transform-runtime",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
.env.*
|
.env.*
|
||||||
public/system
|
public/system
|
||||||
public/assets
|
public/assets
|
||||||
|
public/packs
|
||||||
node_modules
|
node_modules
|
||||||
storybook
|
storybook
|
||||||
neo4j
|
neo4j
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ DB_NAME=gonano
|
|||||||
DB_PASS=$DATA_DB_PASS
|
DB_PASS=$DATA_DB_PASS
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
|
|
||||||
|
DATABASE_URL=postgresql://$DATA_DB_USER:$DATA_DB_PASS@$DATA_DB_HOST/gonano
|
||||||
|
|
||||||
# Federation
|
# Federation
|
||||||
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
|
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
|
||||||
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
||||||
@@ -67,7 +69,7 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
|
|||||||
# PAPERCLIP_ROOT_URL=/system
|
# PAPERCLIP_ROOT_URL=/system
|
||||||
|
|
||||||
# Optional asset host for multi-server setups
|
# Optional asset host for multi-server setups
|
||||||
# CDN_HOST=assets.example.com
|
# CDN_HOST=https://assets.example.com
|
||||||
|
|
||||||
# S3 (optional)
|
# S3 (optional)
|
||||||
# S3_ENABLED=true
|
# S3_ENABLED=true
|
||||||
|
|||||||
@@ -31,6 +31,17 @@ PAPERCLIP_SECRET=
|
|||||||
SECRET_KEY_BASE=
|
SECRET_KEY_BASE=
|
||||||
OTP_SECRET=
|
OTP_SECRET=
|
||||||
|
|
||||||
|
# VAPID keys (used for push notifications
|
||||||
|
# You can generate the keys using the following command (first is the private key, second is the public one)
|
||||||
|
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
||||||
|
# be invalidated, requiring the users to access the website again to resubscribe.
|
||||||
|
#
|
||||||
|
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
|
||||||
|
#
|
||||||
|
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
||||||
|
VAPID_PRIVATE_KEY=
|
||||||
|
VAPID_PUBLIC_KEY=
|
||||||
|
|
||||||
# Registrations
|
# Registrations
|
||||||
# Single user mode will disable registrations and redirect frontpage to the first profile
|
# Single user mode will disable registrations and redirect frontpage to the first profile
|
||||||
# SINGLE_USER_MODE=true
|
# SINGLE_USER_MODE=true
|
||||||
@@ -65,7 +76,7 @@ SMTP_FROM_ADDRESS=notifications@example.com
|
|||||||
# PAPERCLIP_ROOT_URL=/system
|
# PAPERCLIP_ROOT_URL=/system
|
||||||
|
|
||||||
# Optional asset host for multi-server setups
|
# Optional asset host for multi-server setups
|
||||||
# CDN_HOST=assets.example.com
|
# CDN_HOST=https://assets.example.com
|
||||||
|
|
||||||
# S3 (optional)
|
# S3 (optional)
|
||||||
# S3_ENABLED=true
|
# S3_ENABLED=true
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
---
|
---
|
||||||
|
root: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
browser: true
|
browser: true
|
||||||
node: false
|
node: true
|
||||||
es6: true
|
es6: true
|
||||||
|
|
||||||
parser: babel-eslint
|
parser: babel-eslint
|
||||||
@@ -21,22 +23,10 @@ parserOptions:
|
|||||||
|
|
||||||
rules:
|
rules:
|
||||||
|
|
||||||
no-cond-assign: error
|
|
||||||
no-console: warn
|
|
||||||
no-irregular-whitespace: error
|
|
||||||
no-unreachable: error
|
|
||||||
valid-typeof: error
|
|
||||||
consistent-return: error
|
|
||||||
dot-notation: error
|
|
||||||
eqeqeq: error
|
|
||||||
no-fallthrough: error
|
|
||||||
no-unused-expressions: error
|
|
||||||
strict: off
|
|
||||||
no-catch-shadow: error
|
|
||||||
indent:
|
|
||||||
- warn
|
|
||||||
- 2
|
|
||||||
brace-style: warn
|
brace-style: warn
|
||||||
|
comma-dangle:
|
||||||
|
- error
|
||||||
|
- always-multiline
|
||||||
comma-spacing:
|
comma-spacing:
|
||||||
- warn
|
- warn
|
||||||
- before: false
|
- before: false
|
||||||
@@ -44,22 +34,70 @@ rules:
|
|||||||
comma-style:
|
comma-style:
|
||||||
- warn
|
- warn
|
||||||
- last
|
- last
|
||||||
|
consistent-return: error
|
||||||
|
dot-notation: error
|
||||||
|
eqeqeq: error
|
||||||
|
indent:
|
||||||
|
- warn
|
||||||
|
- 2
|
||||||
|
jsx-quotes:
|
||||||
|
- error
|
||||||
|
- prefer-single
|
||||||
|
no-catch-shadow: error
|
||||||
|
no-cond-assign: error
|
||||||
|
no-console:
|
||||||
|
- warn
|
||||||
|
- allow:
|
||||||
|
- error
|
||||||
|
no-fallthrough: error
|
||||||
|
no-irregular-whitespace: error
|
||||||
no-mixed-spaces-and-tabs: warn
|
no-mixed-spaces-and-tabs: warn
|
||||||
no-nested-ternary: warn
|
no-nested-ternary: warn
|
||||||
no-trailing-spaces: warn
|
no-trailing-spaces: warn
|
||||||
semi: error
|
no-undef: error
|
||||||
|
no-unreachable: error
|
||||||
|
no-unused-expressions: error
|
||||||
|
no-unused-vars:
|
||||||
|
- error
|
||||||
|
- vars: all
|
||||||
|
args: after-used
|
||||||
|
ignoreRestSiblings: true
|
||||||
|
object-curly-spacing:
|
||||||
|
- error
|
||||||
|
- always
|
||||||
padded-blocks:
|
padded-blocks:
|
||||||
- error
|
- error
|
||||||
- classes: always
|
- classes: always
|
||||||
comma-dangle:
|
quotes:
|
||||||
- error
|
- error
|
||||||
- always-multiline
|
- single
|
||||||
|
semi: error
|
||||||
|
strict: off
|
||||||
|
valid-typeof: error
|
||||||
|
|
||||||
react/jsx-wrap-multilines: error
|
react/jsx-boolean-value: error
|
||||||
|
react/jsx-closing-bracket-location:
|
||||||
|
- error
|
||||||
|
- line-aligned
|
||||||
|
react/jsx-curly-spacing: error
|
||||||
|
react/jsx-equals-spacing: error
|
||||||
|
react/jsx-first-prop-new-line:
|
||||||
|
- error
|
||||||
|
- multiline-multiprop
|
||||||
|
react/jsx-indent:
|
||||||
|
- error
|
||||||
|
- 2
|
||||||
react/jsx-no-bind: error
|
react/jsx-no-bind: error
|
||||||
react/self-closing-comp: error
|
react/jsx-no-duplicate-props: error
|
||||||
react/prop-types: error
|
react/jsx-no-undef: error
|
||||||
|
react/jsx-tag-spacing: error
|
||||||
|
react/jsx-uses-react: error
|
||||||
|
react/jsx-uses-vars: error
|
||||||
|
react/jsx-wrap-multilines: error
|
||||||
react/no-multi-comp: off
|
react/no-multi-comp: off
|
||||||
|
react/no-string-refs: error
|
||||||
|
react/prop-types: error
|
||||||
|
react/self-closing-comp: error
|
||||||
|
|
||||||
jsx-a11y/accessible-emoji: warn
|
jsx-a11y/accessible-emoji: warn
|
||||||
jsx-a11y/anchor-has-content: warn
|
jsx-a11y/anchor-has-content: warn
|
||||||
|
|||||||
14
.gitattributes
vendored
Normal file
14
.gitattributes
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
*.eot -text
|
||||||
|
*.gif -text
|
||||||
|
*.gz -text
|
||||||
|
*.ico -text
|
||||||
|
*.jpg -text
|
||||||
|
*.mp3 -text
|
||||||
|
*.ogg -text
|
||||||
|
*.png -text
|
||||||
|
*.ttf -text
|
||||||
|
*.webm -text
|
||||||
|
*.woff -text
|
||||||
|
*.woff2 -text
|
||||||
|
spec/fixtures/requests/** -text !eol
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,6 +20,8 @@ coverage
|
|||||||
public/system
|
public/system
|
||||||
public/assets
|
public/assets
|
||||||
public/packs
|
public/packs
|
||||||
|
public/packs-test
|
||||||
|
public/sw.js
|
||||||
.env
|
.env
|
||||||
.env.production
|
.env.production
|
||||||
node_modules/
|
node_modules/
|
||||||
@@ -33,6 +35,7 @@ config/deploy/*
|
|||||||
|
|
||||||
# Ignore IDE files
|
# Ignore IDE files
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
# Ignore postgres + redis volume optionally created by docker-compose
|
# Ignore postgres + redis volume optionally created by docker-compose
|
||||||
postgres
|
postgres
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ plugins:
|
|||||||
- last 2 versions
|
- last 2 versions
|
||||||
- IE >= 11
|
- IE >= 11
|
||||||
- iOS >= 9
|
- iOS >= 9
|
||||||
|
postcss-object-fit-images: {}
|
||||||
|
|||||||
96
.rubocop.yml
96
.rubocop.yml
@@ -1,26 +1,35 @@
|
|||||||
Rails:
|
AllCops:
|
||||||
Enabled: true
|
TargetRubyVersion: 2.3
|
||||||
|
Exclude:
|
||||||
|
- 'spec/**/*'
|
||||||
|
- 'db/**/*'
|
||||||
|
- 'app/views/**/*'
|
||||||
|
- 'config/**/*'
|
||||||
|
- 'bin/*'
|
||||||
|
- 'Rakefile'
|
||||||
|
- 'node_modules/**/*'
|
||||||
|
- 'Vagrantfile'
|
||||||
|
- 'vendor/**/*'
|
||||||
|
|
||||||
Style/PerlBackrefs:
|
Bundler/OrderedGems:
|
||||||
AutoCorrect: false
|
|
||||||
|
|
||||||
Style/ClassAndModuleChildren:
|
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Metrics/BlockNesting:
|
Layout/AccessModifierIndentation:
|
||||||
Max: 2
|
EnforcedStyle: indent
|
||||||
|
|
||||||
Metrics/LineLength:
|
Layout/EmptyLineAfterMagicComment:
|
||||||
AllowURI: true
|
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Metrics/MethodLength:
|
Layout/SpaceInsideHashLiteralBraces:
|
||||||
CountComments: false
|
EnforcedStyle: space
|
||||||
Max: 10
|
|
||||||
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 100
|
Max: 100
|
||||||
|
|
||||||
|
Metrics/BlockLength:
|
||||||
|
Exclude:
|
||||||
|
- 'lib/tasks/**/*'
|
||||||
|
|
||||||
Metrics/BlockNesting:
|
Metrics/BlockNesting:
|
||||||
Max: 3
|
Max: 3
|
||||||
|
|
||||||
@@ -31,22 +40,36 @@ Metrics/ClassLength:
|
|||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
Max: 15
|
Max: 15
|
||||||
|
|
||||||
|
Metrics/LineLength:
|
||||||
|
AllowURI: true
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
Metrics/MethodLength:
|
Metrics/MethodLength:
|
||||||
|
CountComments: false
|
||||||
Max: 55
|
Max: 55
|
||||||
|
|
||||||
Metrics/ModuleLength:
|
Metrics/ModuleLength:
|
||||||
CountComments: false
|
CountComments: false
|
||||||
Max: 200
|
Max: 200
|
||||||
|
|
||||||
Metrics/PerceivedComplexity:
|
|
||||||
Max: 10
|
|
||||||
|
|
||||||
Metrics/ParameterLists:
|
Metrics/ParameterLists:
|
||||||
Max: 4
|
Max: 4
|
||||||
CountKeywordArgs: true
|
CountKeywordArgs: true
|
||||||
|
|
||||||
Style/AccessModifierIndentation:
|
Metrics/PerceivedComplexity:
|
||||||
EnforcedStyle: indent
|
Max: 10
|
||||||
|
|
||||||
|
Rails:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
Rails/HasAndBelongsToMany:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Rails/SkipsModelValidations:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/ClassAndModuleChildren:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
Style/CollectionMethods:
|
Style/CollectionMethods:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
@@ -62,36 +85,25 @@ Style/DoubleNegation:
|
|||||||
Style/FrozenStringLiteralComment:
|
Style/FrozenStringLiteralComment:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
Style/SpaceInsideHashLiteralBraces:
|
Style/GuardClause:
|
||||||
EnforcedStyle: space
|
|
||||||
|
|
||||||
Style/TrailingCommaInLiteral:
|
|
||||||
EnforcedStyleForMultiline: 'comma'
|
|
||||||
|
|
||||||
Style/RegexpLiteral:
|
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Style/Lambda:
|
Style/Lambda:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Style/GuardClause:
|
Style/PercentLiteralDelimiters:
|
||||||
|
PreferredDelimiters:
|
||||||
|
'%i': '()'
|
||||||
|
'%w': '()'
|
||||||
|
|
||||||
|
Style/PerlBackrefs:
|
||||||
|
AutoCorrect: false
|
||||||
|
|
||||||
|
Style/RegexpLiteral:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Rails/HasAndBelongsToMany:
|
Style/SymbolArray:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Bundler/OrderedGems:
|
Style/TrailingCommaInLiteral:
|
||||||
Enabled: false
|
EnforcedStyleForMultiline: 'comma'
|
||||||
|
|
||||||
AllCops:
|
|
||||||
TargetRubyVersion: 2.3
|
|
||||||
Exclude:
|
|
||||||
- 'spec/**/*'
|
|
||||||
- 'db/**/*'
|
|
||||||
- 'app/views/**/*'
|
|
||||||
- 'config/**/*'
|
|
||||||
- 'bin/*'
|
|
||||||
- 'Rakefile'
|
|
||||||
- 'node_modules/**/*'
|
|
||||||
- 'Vagrantfile'
|
|
||||||
- 'vendor/**/*'
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ cache:
|
|||||||
yarn: true
|
yarn: true
|
||||||
directories:
|
directories:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
- public/assets
|
||||||
|
- public/packs-test
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: false
|
sudo: required
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
@@ -30,6 +32,7 @@ addons:
|
|||||||
- g++-6
|
- g++-6
|
||||||
- libprotobuf-dev
|
- libprotobuf-dev
|
||||||
- protobuf-compiler
|
- protobuf-compiler
|
||||||
|
- libicu-dev
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
- 2.3.4
|
- 2.3.4
|
||||||
@@ -50,6 +53,6 @@ before_script:
|
|||||||
- ln -s /usr/bin/x86_64-linux-gnu-g++-6 "$HOME/g++"
|
- ln -s /usr/bin/x86_64-linux-gnu-g++-6 "$HOME/g++"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- bundle exec parallel_test spec/ --group-by filesize --type rspec
|
- travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec
|
||||||
- npm test
|
- npm test
|
||||||
- bundle exec i18n-tasks unused
|
- bundle exec i18n-tasks unused
|
||||||
|
|||||||
2
Aptfile
2
Aptfile
@@ -3,3 +3,5 @@ libprotobuf-dev
|
|||||||
ffmpeg
|
ffmpeg
|
||||||
libxdamage1
|
libxdamage1
|
||||||
libxfixes3
|
libxfixes3
|
||||||
|
libicu-dev
|
||||||
|
libidn11-dev
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ EXPOSE 3000 4000
|
|||||||
WORKDIR /mastodon
|
WORKDIR /mastodon
|
||||||
|
|
||||||
RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
|
RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
|
||||||
|
&& echo "@edge https://nl.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
|
||||||
&& apk -U upgrade \
|
&& apk -U upgrade \
|
||||||
&& apk add -t build-dependencies \
|
&& apk add -t build-dependencies \
|
||||||
build-base \
|
build-base \
|
||||||
|
icu-dev \
|
||||||
|
libidn-dev \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
libxslt-dev \
|
libxslt-dev \
|
||||||
postgresql-dev \
|
postgresql-dev \
|
||||||
@@ -25,7 +28,9 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
|
|||||||
ffmpeg \
|
ffmpeg \
|
||||||
file \
|
file \
|
||||||
git \
|
git \
|
||||||
|
icu-libs \
|
||||||
imagemagick@edge \
|
imagemagick@edge \
|
||||||
|
libidn \
|
||||||
libpq \
|
libpq \
|
||||||
libxml2 \
|
libxml2 \
|
||||||
libxslt \
|
libxslt \
|
||||||
@@ -34,7 +39,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
|
|||||||
protobuf \
|
protobuf \
|
||||||
su-exec \
|
su-exec \
|
||||||
tini \
|
tini \
|
||||||
&& npm install -g npm@3 && npm install -g yarn \
|
yarn@edge \
|
||||||
&& update-ca-certificates \
|
&& update-ca-certificates \
|
||||||
&& rm -rf /tmp/* /var/cache/apk/*
|
&& rm -rf /tmp/* /var/cache/apk/*
|
||||||
|
|
||||||
|
|||||||
22
Gemfile
22
Gemfile
@@ -6,7 +6,7 @@ ruby '>= 2.3.0', '< 2.5.0'
|
|||||||
gem 'pkg-config', '~> 1.2'
|
gem 'pkg-config', '~> 1.2'
|
||||||
|
|
||||||
gem 'puma', '~> 3.8'
|
gem 'puma', '~> 3.8'
|
||||||
gem 'rails', '~> 5.0'
|
gem 'rails', '~> 5.1.0'
|
||||||
gem 'uglifier', '~> 3.2'
|
gem 'uglifier', '~> 3.2'
|
||||||
|
|
||||||
gem 'hamlit-rails', '~> 0.2'
|
gem 'hamlit-rails', '~> 0.2'
|
||||||
@@ -18,26 +18,32 @@ gem 'aws-sdk', '~> 2.9'
|
|||||||
gem 'paperclip', '~> 5.1'
|
gem 'paperclip', '~> 5.1'
|
||||||
gem 'paperclip-av-transcoder', '~> 0.6'
|
gem 'paperclip-av-transcoder', '~> 0.6'
|
||||||
|
|
||||||
|
gem 'active_model_serializers', '~> 0.10'
|
||||||
gem 'addressable', '~> 2.5'
|
gem 'addressable', '~> 2.5'
|
||||||
gem 'bootsnap', '~> 0.3'
|
gem 'bootsnap'
|
||||||
|
gem 'browser'
|
||||||
|
gem 'charlock_holmes', '~> 0.7.3'
|
||||||
gem 'cld3', '~> 3.1'
|
gem 'cld3', '~> 3.1'
|
||||||
gem 'devise', '~> 4.2'
|
gem 'devise', '~> 4.2'
|
||||||
gem 'devise-two-factor', '~> 3.0'
|
gem 'devise-two-factor', '~> 3.0'
|
||||||
gem 'doorkeeper', '~> 4.2'
|
gem 'doorkeeper', '~> 4.2'
|
||||||
gem 'fast_blank', '~> 1.0'
|
gem 'fast_blank', '~> 1.0'
|
||||||
gem 'goldfinger', '~> 1.2'
|
gem 'goldfinger', '~> 2.0'
|
||||||
gem 'hiredis', '~> 0.6'
|
gem 'hiredis', '~> 0.6'
|
||||||
gem 'redis-namespace', '~> 1.5'
|
gem 'redis-namespace', '~> 1.5'
|
||||||
gem 'htmlentities', '~> 4.3'
|
gem 'htmlentities', '~> 4.3'
|
||||||
gem 'http', '~> 2.2'
|
gem 'http', '~> 2.2'
|
||||||
gem 'http_accept_language', '~> 2.1'
|
gem 'http_accept_language', '~> 2.1'
|
||||||
gem 'httplog', '~> 0.99'
|
gem 'httplog', '~> 0.99'
|
||||||
|
gem 'idn-ruby', require: 'idn'
|
||||||
gem 'kaminari', '~> 1.0'
|
gem 'kaminari', '~> 1.0'
|
||||||
gem 'link_header', '~> 0.0'
|
gem 'link_header', '~> 0.0'
|
||||||
|
gem 'mime-types', '~> 3.1'
|
||||||
gem 'nokogiri', '~> 1.7'
|
gem 'nokogiri', '~> 1.7'
|
||||||
gem 'oj', '~> 3.0'
|
gem 'oj', '~> 3.0'
|
||||||
gem 'ostatus2', '~> 2.0'
|
gem 'ostatus2', '~> 2.0'
|
||||||
gem 'ox', '~> 2.5'
|
gem 'ox', '~> 2.5'
|
||||||
|
gem 'pundit', '~> 1.1'
|
||||||
gem 'rabl', '~> 0.13'
|
gem 'rabl', '~> 0.13'
|
||||||
gem 'rack-attack', '~> 5.0'
|
gem 'rack-attack', '~> 5.0'
|
||||||
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
|
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
|
||||||
@@ -45,19 +51,22 @@ gem 'rack-timeout', '~> 0.4'
|
|||||||
gem 'rails-i18n', '~> 5.0'
|
gem 'rails-i18n', '~> 5.0'
|
||||||
gem 'rails-settings-cached', '~> 0.6'
|
gem 'rails-settings-cached', '~> 0.6'
|
||||||
gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
|
gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
|
||||||
|
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||||
gem 'rqrcode', '~> 0.10'
|
gem 'rqrcode', '~> 0.10'
|
||||||
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
|
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
|
||||||
gem 'sanitize', '~> 4.4'
|
gem 'sanitize', '~> 4.4'
|
||||||
gem 'sidekiq', '~> 5.0'
|
gem 'sidekiq', '~> 5.0'
|
||||||
gem 'sidekiq-scheduler', '~> 2.1'
|
gem 'sidekiq-scheduler', '~> 2.1'
|
||||||
gem 'sidekiq-unique-jobs', '~> 5.0'
|
gem 'sidekiq-unique-jobs', '~> 5.0'
|
||||||
|
gem 'sidekiq-bulk', '~>0.1.1'
|
||||||
gem 'simple-navigation', '~> 4.0'
|
gem 'simple-navigation', '~> 4.0'
|
||||||
gem 'simple_form', '~> 3.4'
|
gem 'simple_form', '~> 3.4'
|
||||||
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
|
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
|
||||||
gem 'statsd-instrument', '~> 2.1'
|
gem 'statsd-instrument', '~> 2.1'
|
||||||
gem 'twitter-text', '~> 1.14'
|
gem 'twitter-text', '~> 1.14'
|
||||||
gem 'tzinfo-data', '~> 1.2017'
|
gem 'tzinfo-data', '~> 1.2017'
|
||||||
gem 'webpacker', '~> 1.2'
|
gem 'webpacker', '~> 2.0'
|
||||||
|
gem 'webpush'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'fabrication', '~> 2.16'
|
gem 'fabrication', '~> 2.16'
|
||||||
@@ -69,8 +78,9 @@ end
|
|||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'capybara', '~> 2.14'
|
gem 'capybara', '~> 2.14'
|
||||||
|
gem 'climate_control', '~> 0.2'
|
||||||
gem 'faker', '~> 1.7'
|
gem 'faker', '~> 1.7'
|
||||||
gem 'microformats2', '~> 3.0'
|
gem 'microformats', '~> 4.0'
|
||||||
gem 'rails-controller-testing', '~> 1.0'
|
gem 'rails-controller-testing', '~> 1.0'
|
||||||
gem 'rspec-sidekiq', '~> 3.0'
|
gem 'rspec-sidekiq', '~> 3.0'
|
||||||
gem 'simplecov', '~> 0.14', require: false
|
gem 'simplecov', '~> 0.14', require: false
|
||||||
@@ -86,7 +96,7 @@ group :development do
|
|||||||
gem 'bullet', '~> 5.5'
|
gem 'bullet', '~> 5.5'
|
||||||
gem 'letter_opener', '~> 1.4'
|
gem 'letter_opener', '~> 1.4'
|
||||||
gem 'letter_opener_web', '~> 1.3'
|
gem 'letter_opener_web', '~> 1.3'
|
||||||
gem 'rubocop', '~> 0.48', require: false
|
gem 'rubocop', require: false
|
||||||
gem 'brakeman', '~> 3.6', require: false
|
gem 'brakeman', '~> 3.6', require: false
|
||||||
gem 'bundler-audit', '~> 0.5', require: false
|
gem 'bundler-audit', '~> 0.5', require: false
|
||||||
gem 'scss_lint', '~> 0.53', require: false
|
gem 'scss_lint', '~> 0.53', require: false
|
||||||
|
|||||||
220
Gemfile.lock
220
Gemfile.lock
@@ -1,64 +1,69 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.0.3)
|
actioncable (5.1.2)
|
||||||
actionpack (= 5.0.3)
|
actionpack (= 5.1.2)
|
||||||
nio4r (>= 1.2, < 3.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (~> 0.6.1)
|
websocket-driver (~> 0.6.1)
|
||||||
actionmailer (5.0.3)
|
actionmailer (5.1.2)
|
||||||
actionpack (= 5.0.3)
|
actionpack (= 5.1.2)
|
||||||
actionview (= 5.0.3)
|
actionview (= 5.1.2)
|
||||||
activejob (= 5.0.3)
|
activejob (= 5.1.2)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (5.0.3)
|
actionpack (5.1.2)
|
||||||
actionview (= 5.0.3)
|
actionview (= 5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
rack-test (~> 0.6.3)
|
rack-test (~> 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
actionview (5.0.3)
|
actionview (5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubis (~> 2.7.0)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||||
|
active_model_serializers (0.10.6)
|
||||||
|
actionpack (>= 4.1, < 6)
|
||||||
|
activemodel (>= 4.1, < 6)
|
||||||
|
case_transform (>= 0.2)
|
||||||
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
||||||
active_record_query_trace (1.5.4)
|
active_record_query_trace (1.5.4)
|
||||||
activejob (5.0.3)
|
activejob (5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.0.3)
|
activemodel (5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
activerecord (5.0.3)
|
activerecord (5.1.2)
|
||||||
activemodel (= 5.0.3)
|
activemodel (= 5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
arel (~> 7.0)
|
arel (~> 8.0)
|
||||||
activesupport (5.0.3)
|
activesupport (5.1.2)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
addressable (2.5.1)
|
addressable (2.5.1)
|
||||||
public_suffix (~> 2.0, >= 2.0.2)
|
public_suffix (~> 2.0, >= 2.0.2)
|
||||||
airbrussh (1.2.0)
|
airbrussh (1.3.0)
|
||||||
sshkit (>= 1.6.1, != 1.7.0)
|
sshkit (>= 1.6.1, != 1.7.0)
|
||||||
annotate (2.7.1)
|
annotate (2.7.2)
|
||||||
activerecord (>= 3.2, < 6.0)
|
activerecord (>= 3.2, < 6.0)
|
||||||
rake (>= 10.4, < 12.0)
|
rake (>= 10.4, < 13.0)
|
||||||
arel (7.1.4)
|
arel (8.0.0)
|
||||||
ast (2.3.0)
|
ast (2.3.0)
|
||||||
attr_encrypted (3.0.3)
|
attr_encrypted (3.0.3)
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
av (0.9.0)
|
av (0.9.0)
|
||||||
cocaine (~> 0.5.3)
|
cocaine (~> 0.5.3)
|
||||||
aws-sdk (2.9.21)
|
aws-sdk (2.10.6)
|
||||||
aws-sdk-resources (= 2.9.21)
|
aws-sdk-resources (= 2.10.6)
|
||||||
aws-sdk-core (2.9.21)
|
aws-sdk-core (2.10.6)
|
||||||
aws-sigv4 (~> 1.0)
|
aws-sigv4 (~> 1.0)
|
||||||
jmespath (~> 1.0)
|
jmespath (~> 1.0)
|
||||||
aws-sdk-resources (2.9.21)
|
aws-sdk-resources (2.10.6)
|
||||||
aws-sdk-core (= 2.9.21)
|
aws-sdk-core (= 2.10.6)
|
||||||
aws-sigv4 (1.0.0)
|
aws-sigv4 (1.0.0)
|
||||||
bcrypt (3.1.11)
|
bcrypt (3.1.11)
|
||||||
better_errors (2.1.1)
|
better_errors (2.1.1)
|
||||||
@@ -67,9 +72,10 @@ GEM
|
|||||||
rack (>= 0.9.0)
|
rack (>= 0.9.0)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (0.3.0)
|
bootsnap (1.1.1)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
brakeman (3.6.1)
|
brakeman (3.6.2)
|
||||||
|
browser (2.4.0)
|
||||||
builder (3.2.3)
|
builder (3.2.3)
|
||||||
bullet (5.5.1)
|
bullet (5.5.1)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
@@ -77,7 +83,7 @@ GEM
|
|||||||
bundler-audit (0.5.0)
|
bundler-audit (0.5.0)
|
||||||
bundler (~> 1.2)
|
bundler (~> 1.2)
|
||||||
thor (~> 0.18)
|
thor (~> 0.18)
|
||||||
capistrano (3.8.1)
|
capistrano (3.8.2)
|
||||||
airbrussh (>= 1.0.0)
|
airbrussh (>= 1.0.0)
|
||||||
i18n
|
i18n
|
||||||
rake (>= 10.0.0)
|
rake (>= 10.0.0)
|
||||||
@@ -85,7 +91,7 @@ GEM
|
|||||||
capistrano-bundler (1.2.0)
|
capistrano-bundler (1.2.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
sshkit (~> 1.2)
|
sshkit (~> 1.2)
|
||||||
capistrano-rails (1.2.3)
|
capistrano-rails (1.3.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
capistrano-bundler (~> 1.1)
|
capistrano-bundler (~> 1.1)
|
||||||
capistrano-rbenv (2.1.1)
|
capistrano-rbenv (2.1.1)
|
||||||
@@ -93,15 +99,18 @@ GEM
|
|||||||
sshkit (~> 1.3)
|
sshkit (~> 1.3)
|
||||||
capistrano-yarn (2.0.2)
|
capistrano-yarn (2.0.2)
|
||||||
capistrano (~> 3.0)
|
capistrano (~> 3.0)
|
||||||
capybara (2.14.0)
|
capybara (2.14.4)
|
||||||
addressable
|
addressable
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
nokogiri (>= 1.3.3)
|
nokogiri (>= 1.3.3)
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
xpath (~> 2.0)
|
xpath (~> 2.0)
|
||||||
|
case_transform (0.2)
|
||||||
|
activesupport
|
||||||
|
charlock_holmes (0.7.3)
|
||||||
chunky_png (1.3.8)
|
chunky_png (1.3.8)
|
||||||
cld3 (3.1.2)
|
cld3 (3.1.3)
|
||||||
ffi (>= 1.1.0, < 1.10.0)
|
ffi (>= 1.1.0, < 1.10.0)
|
||||||
climate_control (0.2.0)
|
climate_control (0.2.0)
|
||||||
cocaine (0.5.8)
|
cocaine (0.5.8)
|
||||||
@@ -130,7 +139,7 @@ GEM
|
|||||||
docile (1.1.5)
|
docile (1.1.5)
|
||||||
domain_name (0.5.20170404)
|
domain_name (0.5.20170404)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
doorkeeper (4.2.5)
|
doorkeeper (4.2.6)
|
||||||
railties (>= 4.2)
|
railties (>= 4.2)
|
||||||
dotenv (2.2.1)
|
dotenv (2.2.1)
|
||||||
dotenv-rails (2.2.1)
|
dotenv-rails (2.2.1)
|
||||||
@@ -141,8 +150,9 @@ GEM
|
|||||||
thread
|
thread
|
||||||
thread_safe
|
thread_safe
|
||||||
encryptor (3.0.0)
|
encryptor (3.0.0)
|
||||||
|
erubi (1.6.1)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
et-orbi (1.0.4)
|
et-orbi (1.0.5)
|
||||||
tzinfo
|
tzinfo
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
fabrication (2.16.1)
|
fabrication (2.16.1)
|
||||||
@@ -155,11 +165,12 @@ GEM
|
|||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
globalid (0.4.0)
|
globalid (0.4.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
goldfinger (1.2.0)
|
goldfinger (2.0.0)
|
||||||
addressable (~> 2.4)
|
addressable (~> 2.5)
|
||||||
http (~> 2.0)
|
http (~> 2.2)
|
||||||
nokogiri (~> 1.6)
|
nokogiri (~> 1.8)
|
||||||
hamlit (2.8.1)
|
oj (~> 3.0)
|
||||||
|
hamlit (2.8.4)
|
||||||
temple (>= 0.8.0)
|
temple (>= 0.8.0)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
@@ -171,6 +182,7 @@ GEM
|
|||||||
hashdiff (0.3.4)
|
hashdiff (0.3.4)
|
||||||
highline (1.7.8)
|
highline (1.7.8)
|
||||||
hiredis (0.6.1)
|
hiredis (0.6.1)
|
||||||
|
hkdf (0.3.0)
|
||||||
htmlentities (4.3.4)
|
htmlentities (4.3.4)
|
||||||
http (2.2.2)
|
http (2.2.2)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
@@ -180,12 +192,12 @@ GEM
|
|||||||
http-cookie (1.0.3)
|
http-cookie (1.0.3)
|
||||||
domain_name (~> 0.5)
|
domain_name (~> 0.5)
|
||||||
http-form_data (1.0.3)
|
http-form_data (1.0.3)
|
||||||
http_accept_language (2.1.0)
|
http_accept_language (2.1.1)
|
||||||
http_parser.rb (0.6.0)
|
http_parser.rb (0.6.0)
|
||||||
httplog (0.99.3)
|
httplog (0.99.4)
|
||||||
colorize
|
colorize
|
||||||
rack
|
rack
|
||||||
i18n (0.8.1)
|
i18n (0.8.4)
|
||||||
i18n-tasks (0.9.15)
|
i18n-tasks (0.9.15)
|
||||||
activesupport (>= 4.0.2)
|
activesupport (>= 4.0.2)
|
||||||
ast (>= 2.1.0)
|
ast (>= 2.1.0)
|
||||||
@@ -196,8 +208,11 @@ GEM
|
|||||||
parser (>= 2.2.3.0)
|
parser (>= 2.2.3.0)
|
||||||
rainbow (~> 2.2)
|
rainbow (~> 2.2)
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
|
idn-ruby (0.1.0)
|
||||||
jmespath (1.3.1)
|
jmespath (1.3.1)
|
||||||
json (2.1.0)
|
json (2.1.0)
|
||||||
|
jsonapi-renderer (0.1.2)
|
||||||
|
jwt (1.5.6)
|
||||||
kaminari (1.0.1)
|
kaminari (1.0.1)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
kaminari-actionview (= 1.0.1)
|
kaminari-actionview (= 1.0.1)
|
||||||
@@ -225,32 +240,34 @@ GEM
|
|||||||
railties (>= 4, < 5.2)
|
railties (>= 4, < 5.2)
|
||||||
loofah (2.0.3)
|
loofah (2.0.3)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.6.5)
|
mail (2.6.6)
|
||||||
mime-types (>= 1.16, < 4)
|
mime-types (>= 1.16, < 4)
|
||||||
|
mario-redis-lock (1.2.0)
|
||||||
|
redis (~> 3, >= 3.0.5)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
microformats2 (3.1.0)
|
microformats (4.0.7)
|
||||||
json
|
json
|
||||||
nokogiri
|
nokogiri
|
||||||
mime-types (3.1)
|
mime-types (3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2016.0521)
|
mime-types-data (3.2016.0521)
|
||||||
mimemagic (0.3.2)
|
mimemagic (0.3.2)
|
||||||
mini_portile2 (2.1.0)
|
mini_portile2 (2.2.0)
|
||||||
minitest (5.10.2)
|
minitest (5.10.2)
|
||||||
msgpack (1.1.0)
|
msgpack (1.1.0)
|
||||||
multi_json (1.12.1)
|
multi_json (1.12.1)
|
||||||
net-scp (1.2.1)
|
net-scp (1.2.1)
|
||||||
net-ssh (>= 2.6.5)
|
net-ssh (>= 2.6.5)
|
||||||
net-ssh (4.1.0)
|
net-ssh (4.1.0)
|
||||||
nio4r (2.0.0)
|
nio4r (2.1.0)
|
||||||
nokogiri (1.7.2)
|
nokogiri (1.8.0)
|
||||||
mini_portile2 (~> 2.1.0)
|
mini_portile2 (~> 2.2.0)
|
||||||
nokogumbo (1.4.11)
|
nokogumbo (1.4.13)
|
||||||
nokogiri
|
nokogiri
|
||||||
oj (3.0.9)
|
oj (3.2.0)
|
||||||
openssl (2.0.3)
|
openssl (2.0.4)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ostatus2 (2.0.0)
|
ostatus2 (2.0.1)
|
||||||
addressable (~> 2.4)
|
addressable (~> 2.4)
|
||||||
http (~> 2.0)
|
http (~> 2.0)
|
||||||
nokogiri (~> 1.6)
|
nokogiri (~> 1.6)
|
||||||
@@ -270,10 +287,10 @@ GEM
|
|||||||
parallel
|
parallel
|
||||||
parser (2.4.0.0)
|
parser (2.4.0.0)
|
||||||
ast (~> 2.2)
|
ast (~> 2.2)
|
||||||
pg (0.20.0)
|
pg (0.21.0)
|
||||||
pghero (1.7.0)
|
pghero (1.7.0)
|
||||||
activerecord
|
activerecord
|
||||||
pkg-config (1.2.0)
|
pkg-config (1.2.3)
|
||||||
powerpack (0.1.1)
|
powerpack (0.1.1)
|
||||||
pry (0.10.4)
|
pry (0.10.4)
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
@@ -282,7 +299,9 @@ GEM
|
|||||||
pry-rails (0.3.6)
|
pry-rails (0.3.6)
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.10.4)
|
||||||
public_suffix (2.0.5)
|
public_suffix (2.0.5)
|
||||||
puma (3.8.2)
|
puma (3.9.1)
|
||||||
|
pundit (1.1.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
rabl (0.13.1)
|
rabl (0.13.1)
|
||||||
activesupport (>= 2.3.14)
|
activesupport (>= 2.3.14)
|
||||||
rack (2.0.3)
|
rack (2.0.3)
|
||||||
@@ -294,17 +313,17 @@ GEM
|
|||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rack-timeout (0.4.2)
|
rack-timeout (0.4.2)
|
||||||
rails (5.0.3)
|
rails (5.1.2)
|
||||||
actioncable (= 5.0.3)
|
actioncable (= 5.1.2)
|
||||||
actionmailer (= 5.0.3)
|
actionmailer (= 5.1.2)
|
||||||
actionpack (= 5.0.3)
|
actionpack (= 5.1.2)
|
||||||
actionview (= 5.0.3)
|
actionview (= 5.1.2)
|
||||||
activejob (= 5.0.3)
|
activejob (= 5.1.2)
|
||||||
activemodel (= 5.0.3)
|
activemodel (= 5.1.2)
|
||||||
activerecord (= 5.0.3)
|
activerecord (= 5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
bundler (>= 1.3.0, < 2.0)
|
bundler (>= 1.3.0, < 2.0)
|
||||||
railties (= 5.0.3)
|
railties (= 5.1.2)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-controller-testing (1.0.2)
|
rails-controller-testing (1.0.2)
|
||||||
actionpack (~> 5.x, >= 5.0.1)
|
actionpack (~> 5.x, >= 5.0.1)
|
||||||
@@ -320,15 +339,15 @@ GEM
|
|||||||
railties (~> 5.0)
|
railties (~> 5.0)
|
||||||
rails-settings-cached (0.6.5)
|
rails-settings-cached (0.6.5)
|
||||||
rails (>= 4.2.0)
|
rails (>= 4.2.0)
|
||||||
railties (5.0.3)
|
railties (5.1.2)
|
||||||
actionpack (= 5.0.3)
|
actionpack (= 5.1.2)
|
||||||
activesupport (= 5.0.3)
|
activesupport (= 5.1.2)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.2.2)
|
rainbow (2.2.2)
|
||||||
rake
|
rake
|
||||||
rake (11.3.0)
|
rake (12.0.0)
|
||||||
redis (3.3.3)
|
redis (3.3.3)
|
||||||
redis-actionpack (5.0.1)
|
redis-actionpack (5.0.1)
|
||||||
actionpack (>= 4.0, < 6)
|
actionpack (>= 4.0, < 6)
|
||||||
@@ -370,11 +389,12 @@ GEM
|
|||||||
rspec-expectations (~> 3.6.0)
|
rspec-expectations (~> 3.6.0)
|
||||||
rspec-mocks (~> 3.6.0)
|
rspec-mocks (~> 3.6.0)
|
||||||
rspec-support (~> 3.6.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-sidekiq (3.0.1)
|
rspec-sidekiq (3.0.3)
|
||||||
rspec-core (~> 3.0, >= 3.0.0)
|
rspec-core (~> 3.0, >= 3.0.0)
|
||||||
sidekiq (>= 2.4.0)
|
sidekiq (>= 2.4.0)
|
||||||
rspec-support (3.6.0)
|
rspec-support (3.6.0)
|
||||||
rubocop (0.48.1)
|
rubocop (0.49.1)
|
||||||
|
parallel (~> 1.10)
|
||||||
parser (>= 2.3.3.1, < 3.0)
|
parser (>= 2.3.3.1, < 3.0)
|
||||||
powerpack (~> 0.1)
|
powerpack (~> 0.1)
|
||||||
rainbow (>= 1.99.1, < 3.0)
|
rainbow (>= 1.99.1, < 3.0)
|
||||||
@@ -382,23 +402,26 @@ GEM
|
|||||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||||
ruby-oembed (0.12.0)
|
ruby-oembed (0.12.0)
|
||||||
ruby-progressbar (1.8.1)
|
ruby-progressbar (1.8.1)
|
||||||
rufus-scheduler (3.4.0)
|
rufus-scheduler (3.4.2)
|
||||||
et-orbi (~> 1.0)
|
et-orbi (~> 1.0)
|
||||||
safe_yaml (1.0.4)
|
safe_yaml (1.0.4)
|
||||||
sanitize (4.4.0)
|
sanitize (4.5.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
nokogumbo (~> 1.4.1)
|
nokogumbo (~> 1.4.1)
|
||||||
sass (3.4.24)
|
sass (3.4.24)
|
||||||
scss_lint (0.53.0)
|
scss_lint (0.54.0)
|
||||||
rake (>= 0.9, < 13)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.4.20)
|
sass (~> 3.4.20)
|
||||||
sidekiq (5.0.0)
|
sidekiq (5.0.3)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
connection_pool (~> 2.2, >= 2.2.0)
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
redis (~> 3.3, >= 3.3.3)
|
redis (~> 3.3, >= 3.3.3)
|
||||||
sidekiq-scheduler (2.1.4)
|
sidekiq-bulk (0.1.1)
|
||||||
|
activesupport
|
||||||
|
sidekiq
|
||||||
|
sidekiq-scheduler (2.1.7)
|
||||||
redis (~> 3)
|
redis (~> 3)
|
||||||
rufus-scheduler (~> 3.2)
|
rufus-scheduler (~> 3.2)
|
||||||
sidekiq (>= 3)
|
sidekiq (>= 3)
|
||||||
@@ -435,7 +458,7 @@ GEM
|
|||||||
thread (0.2.2)
|
thread (0.2.2)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.7)
|
tilt (2.0.7)
|
||||||
twitter-text (1.14.5)
|
twitter-text (1.14.6)
|
||||||
unf (~> 0.1.0)
|
unf (~> 0.1.0)
|
||||||
tzinfo (1.2.3)
|
tzinfo (1.2.3)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
@@ -446,7 +469,7 @@ GEM
|
|||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.4)
|
unf_ext (0.0.7.4)
|
||||||
unicode-display_width (1.2.1)
|
unicode-display_width (1.3.0)
|
||||||
uniform_notifier (1.10.0)
|
uniform_notifier (1.10.0)
|
||||||
warden (1.2.7)
|
warden (1.2.7)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
@@ -454,28 +477,33 @@ GEM
|
|||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff
|
hashdiff
|
||||||
webpacker (1.2)
|
webpacker (2.0)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
multi_json (~> 1.2)
|
multi_json (~> 1.2)
|
||||||
railties (>= 4.2)
|
railties (>= 4.2)
|
||||||
|
webpush (0.3.2)
|
||||||
|
hkdf (~> 0.2)
|
||||||
|
jwt
|
||||||
websocket-driver (0.6.5)
|
websocket-driver (0.6.5)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.2)
|
websocket-extensions (0.1.2)
|
||||||
xpath (2.0.0)
|
xpath (2.1.0)
|
||||||
nokogiri (~> 1.3)
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
active_model_serializers (~> 0.10)
|
||||||
active_record_query_trace (~> 1.5)
|
active_record_query_trace (~> 1.5)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
annotate (~> 2.7)
|
annotate (~> 2.7)
|
||||||
aws-sdk (~> 2.9)
|
aws-sdk (~> 2.9)
|
||||||
better_errors (~> 2.1)
|
better_errors (~> 2.1)
|
||||||
binding_of_caller (~> 0.7)
|
binding_of_caller (~> 0.7)
|
||||||
bootsnap (~> 0.3)
|
bootsnap
|
||||||
brakeman (~> 3.6)
|
brakeman (~> 3.6)
|
||||||
|
browser
|
||||||
bullet (~> 5.5)
|
bullet (~> 5.5)
|
||||||
bundler-audit (~> 0.5)
|
bundler-audit (~> 0.5)
|
||||||
capistrano (~> 3.8)
|
capistrano (~> 3.8)
|
||||||
@@ -483,7 +511,9 @@ DEPENDENCIES
|
|||||||
capistrano-rbenv (~> 2.1)
|
capistrano-rbenv (~> 2.1)
|
||||||
capistrano-yarn (~> 2.0)
|
capistrano-yarn (~> 2.0)
|
||||||
capybara (~> 2.14)
|
capybara (~> 2.14)
|
||||||
|
charlock_holmes (~> 0.7.3)
|
||||||
cld3 (~> 3.1)
|
cld3 (~> 3.1)
|
||||||
|
climate_control (~> 0.2)
|
||||||
devise (~> 4.2)
|
devise (~> 4.2)
|
||||||
devise-two-factor (~> 3.0)
|
devise-two-factor (~> 3.0)
|
||||||
doorkeeper (~> 4.2)
|
doorkeeper (~> 4.2)
|
||||||
@@ -492,7 +522,7 @@ DEPENDENCIES
|
|||||||
faker (~> 1.7)
|
faker (~> 1.7)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
fuubar (~> 2.2)
|
fuubar (~> 2.2)
|
||||||
goldfinger (~> 1.2)
|
goldfinger (~> 2.0)
|
||||||
hamlit-rails (~> 0.2)
|
hamlit-rails (~> 0.2)
|
||||||
hiredis (~> 0.6)
|
hiredis (~> 0.6)
|
||||||
htmlentities (~> 4.3)
|
htmlentities (~> 4.3)
|
||||||
@@ -500,12 +530,15 @@ DEPENDENCIES
|
|||||||
http_accept_language (~> 2.1)
|
http_accept_language (~> 2.1)
|
||||||
httplog (~> 0.99)
|
httplog (~> 0.99)
|
||||||
i18n-tasks (~> 0.9)
|
i18n-tasks (~> 0.9)
|
||||||
|
idn-ruby
|
||||||
kaminari (~> 1.0)
|
kaminari (~> 1.0)
|
||||||
letter_opener (~> 1.4)
|
letter_opener (~> 1.4)
|
||||||
letter_opener_web (~> 1.3)
|
letter_opener_web (~> 1.3)
|
||||||
link_header (~> 0.0)
|
link_header (~> 0.0)
|
||||||
lograge (~> 0.5)
|
lograge (~> 0.5)
|
||||||
microformats2 (~> 3.0)
|
mario-redis-lock (~> 1.2)
|
||||||
|
microformats (~> 4.0)
|
||||||
|
mime-types (~> 3.1)
|
||||||
nokogiri (~> 1.7)
|
nokogiri (~> 1.7)
|
||||||
oj (~> 3.0)
|
oj (~> 3.0)
|
||||||
ostatus2 (~> 2.0)
|
ostatus2 (~> 2.0)
|
||||||
@@ -518,11 +551,12 @@ DEPENDENCIES
|
|||||||
pkg-config (~> 1.2)
|
pkg-config (~> 1.2)
|
||||||
pry-rails (~> 0.3)
|
pry-rails (~> 0.3)
|
||||||
puma (~> 3.8)
|
puma (~> 3.8)
|
||||||
|
pundit (~> 1.1)
|
||||||
rabl (~> 0.13)
|
rabl (~> 0.13)
|
||||||
rack-attack (~> 5.0)
|
rack-attack (~> 5.0)
|
||||||
rack-cors (~> 0.4)
|
rack-cors (~> 0.4)
|
||||||
rack-timeout (~> 0.4)
|
rack-timeout (~> 0.4)
|
||||||
rails (~> 5.0)
|
rails (~> 5.1.0)
|
||||||
rails-controller-testing (~> 1.0)
|
rails-controller-testing (~> 1.0)
|
||||||
rails-i18n (~> 5.0)
|
rails-i18n (~> 5.0)
|
||||||
rails-settings-cached (~> 0.6)
|
rails-settings-cached (~> 0.6)
|
||||||
@@ -532,11 +566,12 @@ DEPENDENCIES
|
|||||||
rqrcode (~> 0.10)
|
rqrcode (~> 0.10)
|
||||||
rspec-rails (~> 3.6)
|
rspec-rails (~> 3.6)
|
||||||
rspec-sidekiq (~> 3.0)
|
rspec-sidekiq (~> 3.0)
|
||||||
rubocop (~> 0.48)
|
rubocop
|
||||||
ruby-oembed (~> 0.12)
|
ruby-oembed (~> 0.12)
|
||||||
sanitize (~> 4.4)
|
sanitize (~> 4.4)
|
||||||
scss_lint (~> 0.53)
|
scss_lint (~> 0.53)
|
||||||
sidekiq (~> 5.0)
|
sidekiq (~> 5.0)
|
||||||
|
sidekiq-bulk (~> 0.1.1)
|
||||||
sidekiq-scheduler (~> 2.1)
|
sidekiq-scheduler (~> 2.1)
|
||||||
sidekiq-unique-jobs (~> 5.0)
|
sidekiq-unique-jobs (~> 5.0)
|
||||||
simple-navigation (~> 4.0)
|
simple-navigation (~> 4.0)
|
||||||
@@ -548,10 +583,11 @@ DEPENDENCIES
|
|||||||
tzinfo-data (~> 1.2017)
|
tzinfo-data (~> 1.2017)
|
||||||
uglifier (~> 3.2)
|
uglifier (~> 3.2)
|
||||||
webmock (~> 3.0)
|
webmock (~> 3.0)
|
||||||
webpacker (~> 1.2)
|
webpacker (~> 2.0)
|
||||||
|
webpush
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 2.4.1p111
|
ruby 2.4.1p111
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.14.6
|
1.15.2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Mastodon
|

|
||||||
========
|
========
|
||||||
|
|
||||||
[][travis]
|
[][travis]
|
||||||
@@ -13,7 +13,7 @@ An alternative implementation of the GNU social project. Based on [ActivityStrea
|
|||||||
|
|
||||||
Click on the screenshot to watch a demo of the UI:
|
Click on the screenshot to watch a demo of the UI:
|
||||||
|
|
||||||
[][youtube_demo]
|
[][youtube_demo]
|
||||||
|
|
||||||
[youtube_demo]: https://www.youtube.com/watch?v=YO1jQ8_rAMU
|
[youtube_demo]: https://www.youtube.com/watch?v=YO1jQ8_rAMU
|
||||||
|
|
||||||
|
|||||||
7
Vagrantfile
vendored
7
Vagrantfile
vendored
@@ -35,6 +35,8 @@ sudo apt-get install \
|
|||||||
postgresql-contrib \
|
postgresql-contrib \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
yarn \
|
yarn \
|
||||||
|
libicu-dev \
|
||||||
|
libidn11-dev \
|
||||||
libprotobuf-dev \
|
libprotobuf-dev \
|
||||||
libreadline-dev \
|
libreadline-dev \
|
||||||
-y
|
-y
|
||||||
@@ -42,9 +44,12 @@ sudo apt-get install \
|
|||||||
# Install rvm
|
# Install rvm
|
||||||
read RUBY_VERSION < .ruby-version
|
read RUBY_VERSION < .ruby-version
|
||||||
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
||||||
curl -sSL https://get.rvm.io | bash -s stable --ruby=$RUBY_VERSION
|
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
|
||||||
source /home/vagrant/.rvm/scripts/rvm
|
source /home/vagrant/.rvm/scripts/rvm
|
||||||
|
|
||||||
|
# Install Ruby
|
||||||
|
rvm install ruby-$RUBY_VERSION
|
||||||
|
|
||||||
# Configure database
|
# Configure database
|
||||||
sudo -u postgres createuser -U postgres vagrant -s
|
sudo -u postgres createuser -U postgres vagrant -s
|
||||||
sudo -u postgres createdb -U postgres mastodon_development
|
sudo -u postgres createdb -U postgres mastodon_development
|
||||||
|
|||||||
2
app.json
2
app.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "Mastodon",
|
"name": "Mastodon",
|
||||||
"description": "A GNU Social-compatible microblogging server",
|
"description": "A GNU Social-compatible microblogging server",
|
||||||
"repository": "https://github.com/tootsuite/mastodon",
|
"repository": "https://github.com/tootsuite/mastodon",
|
||||||
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
|
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/javascript/images/logo.svg",
|
||||||
"env": {
|
"env": {
|
||||||
"HEROKU": {
|
"HEROKU": {
|
||||||
"description": "Leave this as true",
|
"description": "Leave this as true",
|
||||||
|
|||||||
@@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
class AboutController < ApplicationController
|
class AboutController < ApplicationController
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
before_action :set_instance_presenter, only: [:show, :more]
|
before_action :set_instance_presenter, only: [:show, :more, :terms]
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
||||||
|
@initial_state_json = serializable_resource.to_json
|
||||||
|
end
|
||||||
|
|
||||||
def more; end
|
def more; end
|
||||||
|
|
||||||
@@ -15,6 +18,7 @@ class AboutController < ApplicationController
|
|||||||
def new_user
|
def new_user
|
||||||
User.new.tap(&:build_account)
|
User.new.tap(&:build_account)
|
||||||
end
|
end
|
||||||
|
|
||||||
helper_method :new_user
|
helper_method :new_user
|
||||||
|
|
||||||
def set_instance_presenter
|
def set_instance_presenter
|
||||||
@@ -24,4 +28,11 @@ class AboutController < ApplicationController
|
|||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'about-body'
|
@body_classes = 'about-body'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initial_state_params
|
||||||
|
{
|
||||||
|
settings: {},
|
||||||
|
token: current_session&.token,
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
include AccountControllerConcern
|
include AccountControllerConcern
|
||||||
|
include SignatureVerification
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@@ -12,10 +13,12 @@ class AccountsController < ApplicationController
|
|||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
render xml: AtomSerializer.render(AtomSerializer.new.feed(@account, @entries.to_a))
|
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.to_a))
|
||||||
end
|
end
|
||||||
|
|
||||||
format.activitystreams2
|
format.json do
|
||||||
|
render json: @account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
27
app/controllers/activitypub/outboxes_controller.rb
Normal file
27
app/controllers/activitypub/outboxes_controller.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ActivityPub::OutboxesController < Api::BaseController
|
||||||
|
before_action :set_account
|
||||||
|
|
||||||
|
def show
|
||||||
|
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
|
@statuses = cache_collection(@statuses, Status)
|
||||||
|
|
||||||
|
render json: outbox_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find_local!(params[:account_username])
|
||||||
|
end
|
||||||
|
|
||||||
|
def outbox_presenter
|
||||||
|
ActivityPub::CollectionPresenter.new(
|
||||||
|
id: account_outbox_url(@account),
|
||||||
|
type: :ordered,
|
||||||
|
size: @account.statuses_count,
|
||||||
|
items: @statuses
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -2,16 +2,43 @@
|
|||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class AccountsController < BaseController
|
class AccountsController < BaseController
|
||||||
|
before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload]
|
||||||
|
before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = filtered_accounts.page(params[:page])
|
@accounts = filtered_accounts.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show; end
|
||||||
@account = Account.find(params[:id])
|
|
||||||
|
def subscribe
|
||||||
|
Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
|
||||||
|
redirect_to admin_account_path(@account.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsubscribe
|
||||||
|
UnsubscribeService.new.call(@account)
|
||||||
|
redirect_to admin_account_path(@account.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def redownload
|
||||||
|
@account.reset_avatar!
|
||||||
|
@account.reset_header!
|
||||||
|
@account.save!
|
||||||
|
|
||||||
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_remote_account!
|
||||||
|
redirect_to admin_account_path(@account.id) if @account.local?
|
||||||
|
end
|
||||||
|
|
||||||
def filtered_accounts
|
def filtered_accounts
|
||||||
AccountFilter.new(filter_params).results
|
AccountFilter.new(filter_params).results
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,13 +3,29 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class InstancesController < BaseController
|
class InstancesController < BaseController
|
||||||
def index
|
def index
|
||||||
@instances = ordered_instances.page(params[:page])
|
@instances = ordered_instances
|
||||||
|
end
|
||||||
|
|
||||||
|
def resubscribe
|
||||||
|
params.require(:by_domain)
|
||||||
|
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
|
||||||
|
redirect_to admin_instances_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def paginated_instances
|
||||||
|
Account.remote.by_domain_accounts.page(params[:page])
|
||||||
|
end
|
||||||
|
|
||||||
|
helper_method :paginated_instances
|
||||||
|
|
||||||
def ordered_instances
|
def ordered_instances
|
||||||
Account.remote.by_domain_accounts
|
paginated_instances.map { |account| Instance.new(account) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def subscribeable_accounts
|
||||||
|
Account.with_followers.remote.where(domain: params[:by_domain])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin
|
|
||||||
class PubsubhubbubController < BaseController
|
|
||||||
def index
|
|
||||||
@subscriptions = Subscription.order(id: :desc).includes(:account).page(params[:page])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -2,8 +2,17 @@
|
|||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ReportedStatusesController < BaseController
|
class ReportedStatusesController < BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action :set_report
|
before_action :set_report
|
||||||
before_action :set_status
|
before_action :set_status, only: [:update, :destroy]
|
||||||
|
|
||||||
|
def create
|
||||||
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
|
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
|
redirect_to admin_report_path(@report)
|
||||||
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@status.update(status_params)
|
@status.update(status_params)
|
||||||
@@ -11,8 +20,9 @@ module Admin
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @status, :destroy?
|
||||||
RemovalWorker.perform_async(@status.id)
|
RemovalWorker.perform_async(@status.id)
|
||||||
redirect_to admin_report_path(@report)
|
render json: @status
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -21,6 +31,10 @@ module Admin
|
|||||||
params.require(:status).permit(:sensitive)
|
params.require(:status).permit(:sensitive)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def form_status_batch_params
|
||||||
|
params.require(:form_status_batch).permit(:action, status_ids: [])
|
||||||
|
end
|
||||||
|
|
||||||
def set_report
|
def set_report
|
||||||
@report = Report.find(params[:report_id])
|
@report = Report.find(params[:report_id])
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ module Admin
|
|||||||
@reports = filtered_reports.page(params[:page])
|
@reports = filtered_reports.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
@form = Form::StatusBatch.new
|
||||||
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
process_report
|
process_report
|
||||||
|
|||||||
@@ -8,13 +8,21 @@ module Admin
|
|||||||
site_title
|
site_title
|
||||||
site_description
|
site_description
|
||||||
site_extended_description
|
site_extended_description
|
||||||
|
site_terms
|
||||||
open_registrations
|
open_registrations
|
||||||
closed_registrations_message
|
closed_registrations_message
|
||||||
|
open_deletion
|
||||||
|
timeline_preview
|
||||||
|
).freeze
|
||||||
|
|
||||||
|
BOOLEAN_SETTINGS = %w(
|
||||||
|
open_registrations
|
||||||
|
open_deletion
|
||||||
|
timeline_preview
|
||||||
).freeze
|
).freeze
|
||||||
BOOLEAN_SETTINGS = %w(open_registrations).freeze
|
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@settings = Setting.all_as_records
|
@admin_settings = Form::AdminSettings.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@@ -23,19 +31,19 @@ module Admin
|
|||||||
setting.update(value: value_for_update(key, value))
|
setting.update(value: value_for_update(key, value))
|
||||||
end
|
end
|
||||||
|
|
||||||
flash[:notice] = 'Success!'
|
flash[:notice] = I18n.t('generic.changes_saved_msg')
|
||||||
redirect_to edit_admin_settings_path
|
redirect_to edit_admin_settings_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params.permit(ADMIN_SETTINGS)
|
params.require(:form_admin_settings).permit(ADMIN_SETTINGS)
|
||||||
end
|
end
|
||||||
|
|
||||||
def value_for_update(key, value)
|
def value_for_update(key, value)
|
||||||
if BOOLEAN_SETTINGS.include?(key)
|
if BOOLEAN_SETTINGS.include?(key)
|
||||||
value == 'true'
|
value == '1'
|
||||||
else
|
else
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|||||||
69
app/controllers/admin/statuses_controller.rb
Normal file
69
app/controllers/admin/statuses_controller.rb
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
class StatusesController < BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
helper_method :current_params
|
||||||
|
|
||||||
|
before_action :set_account
|
||||||
|
before_action :set_status, only: [:update, :destroy]
|
||||||
|
|
||||||
|
PAR_PAGE = 20
|
||||||
|
|
||||||
|
def index
|
||||||
|
@statuses = @account.statuses
|
||||||
|
if params[:media]
|
||||||
|
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
|
||||||
|
@statuses.merge!(Status.where(id: account_media_status_ids))
|
||||||
|
end
|
||||||
|
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PAR_PAGE)
|
||||||
|
|
||||||
|
@form = Form::StatusBatch.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
|
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@status.update(status_params)
|
||||||
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
authorize @status, :destroy?
|
||||||
|
RemovalWorker.perform_async(@status.id)
|
||||||
|
render json: @status
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def status_params
|
||||||
|
params.require(:status).permit(:sensitive)
|
||||||
|
end
|
||||||
|
|
||||||
|
def form_status_batch_params
|
||||||
|
params.require(:form_status_batch).permit(:action, status_ids: [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_status
|
||||||
|
@status = @account.statuses.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_params
|
||||||
|
page = (params[:page] || 1).to_i
|
||||||
|
{
|
||||||
|
media: params[:media],
|
||||||
|
page: page > 1 && page,
|
||||||
|
}.select { |_, value| value.present? }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
19
app/controllers/admin/subscriptions_controller.rb
Normal file
19
app/controllers/admin/subscriptions_controller.rb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
class SubscriptionsController < BaseController
|
||||||
|
def index
|
||||||
|
@subscriptions = ordered_subscriptions.page(requested_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ordered_subscriptions
|
||||||
|
Subscription.order(id: :desc).includes(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def requested_page
|
||||||
|
params[:page].to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Activitypub::ActivitiesController < ApiController
|
|
||||||
# before_action :set_follow, only: [:show_follow]
|
|
||||||
before_action :set_status, only: [:show_status]
|
|
||||||
|
|
||||||
respond_to :activitystreams2
|
|
||||||
|
|
||||||
# Show a status in AS2 format, as either an Announce (reblog) or a Create (post) activity.
|
|
||||||
def show_status
|
|
||||||
return forbidden unless @status.permitted?
|
|
||||||
|
|
||||||
if @status.reblog?
|
|
||||||
render :show_status_announce
|
|
||||||
else
|
|
||||||
render :show_status_create
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_status
|
|
||||||
@status = Status.find(params[:id])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Activitypub::NotesController < ApiController
|
|
||||||
before_action :set_status
|
|
||||||
|
|
||||||
respond_to :activitystreams2
|
|
||||||
|
|
||||||
def show
|
|
||||||
forbidden unless @status.permitted?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_status
|
|
||||||
@status = Status.find(params[:id])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Activitypub::OutboxController < ApiController
|
|
||||||
before_action :set_account
|
|
||||||
|
|
||||||
respond_to :activitystreams2
|
|
||||||
|
|
||||||
def show
|
|
||||||
if params[:max_id] || params[:since_id]
|
|
||||||
show_outbox_page
|
|
||||||
else
|
|
||||||
show_base_outbox
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def show_base_outbox
|
|
||||||
@statuses = Status.as_outbox_timeline(@account)
|
|
||||||
@statuses = cache_collection(@statuses)
|
|
||||||
|
|
||||||
set_maps(@statuses)
|
|
||||||
|
|
||||||
set_first_last_page(@statuses)
|
|
||||||
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def show_outbox_page
|
|
||||||
all_statuses = Status.as_outbox_timeline(@account)
|
|
||||||
@statuses = all_statuses.paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
|
|
||||||
|
|
||||||
all_statuses = cache_collection(all_statuses)
|
|
||||||
@statuses = cache_collection(@statuses)
|
|
||||||
|
|
||||||
set_maps(@statuses)
|
|
||||||
|
|
||||||
set_first_last_page(all_statuses)
|
|
||||||
|
|
||||||
@next_page_url = api_activitypub_outbox_url(pagination_params(max_id: @statuses.last.id)) unless @statuses.empty?
|
|
||||||
@prev_page_url = api_activitypub_outbox_url(pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
|
|
||||||
|
|
||||||
@paginated = @next_page_url || @prev_page_url
|
|
||||||
@part_of_url = api_activitypub_outbox_url
|
|
||||||
|
|
||||||
set_pagination_headers(@next_page_url, @prev_page_url)
|
|
||||||
|
|
||||||
render :show_page
|
|
||||||
end
|
|
||||||
|
|
||||||
def cache_collection(raw)
|
|
||||||
super(raw, Status)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_account
|
|
||||||
@account = Account.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_first_last_page(statuses) # rubocop:disable Style/AccessorMethodName
|
|
||||||
return if statuses.empty?
|
|
||||||
|
|
||||||
@first_page_url = api_activitypub_outbox_url(max_id: statuses.first.id + 1)
|
|
||||||
@last_page_url = api_activitypub_outbox_url(since_id: statuses.last.id - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:local, :limit).merge(core_params)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ApiController < ApplicationController
|
class Api::BaseController < ApplicationController
|
||||||
DEFAULT_STATUSES_LIMIT = 20
|
DEFAULT_STATUSES_LIMIT = 20
|
||||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||||
|
|
||||||
protect_from_forgery with: :null_session
|
include RateLimitHeaders
|
||||||
|
|
||||||
skip_before_action :verify_authenticity_token
|
skip_before_action :verify_authenticity_token
|
||||||
skip_before_action :store_current_location
|
skip_before_action :store_current_location
|
||||||
|
|
||||||
before_action :set_rate_limit_headers
|
|
||||||
|
|
||||||
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
|
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
|
||||||
render json: { error: e.to_s }, status: 422
|
render json: { error: e.to_s }, status: 422
|
||||||
end
|
end
|
||||||
@@ -19,11 +17,7 @@ class ApiController < ApplicationController
|
|||||||
render json: { error: 'Record not found' }, status: 404
|
render json: { error: 'Record not found' }, status: 404
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue_from Goldfinger::Error do
|
rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
|
||||||
render json: { error: 'Remote account could not be resolved' }, status: 422
|
|
||||||
end
|
|
||||||
|
|
||||||
rescue_from HTTP::Error do
|
|
||||||
render json: { error: 'Remote data could not be fetched' }, status: 503
|
render json: { error: 'Remote data could not be fetched' }, status: 503
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -45,17 +39,6 @@ class ApiController < ApplicationController
|
|||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def set_rate_limit_headers
|
|
||||||
return if request.env['rack.attack.throttle_data'].nil?
|
|
||||||
|
|
||||||
now = Time.now.utc
|
|
||||||
match_data = request.env['rack.attack.throttle_data']['api']
|
|
||||||
|
|
||||||
response.headers['X-RateLimit-Limit'] = match_data[:limit].to_s
|
|
||||||
response.headers['X-RateLimit-Remaining'] = (match_data[:limit] - match_data[:count]).to_s
|
|
||||||
response.headers['X-RateLimit-Reset'] = (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_pagination_headers(next_path = nil, prev_path = nil)
|
def set_pagination_headers(next_path = nil, prev_path = nil)
|
||||||
links = []
|
links = []
|
||||||
links << [next_path, [%w(rel next)]] if next_path
|
links << [next_path, [%w(rel next)]] if next_path
|
||||||
@@ -1,33 +1,24 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::OEmbedController < ApiController
|
class Api::OEmbedController < Api::BaseController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@stream_entry = stream_entry_from_url(params[:url])
|
@stream_entry = find_stream_entry.stream_entry
|
||||||
@width = params[:maxwidth].present? ? params[:maxwidth].to_i : 400
|
render json: @stream_entry, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
|
||||||
@height = params[:maxheight].present? ? params[:maxheight].to_i : nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def stream_entry_from_url(url)
|
def find_stream_entry
|
||||||
params = Rails.application.routes.recognize_path(url)
|
StreamEntryFinder.new(params[:url])
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound unless recognized_stream_entry_url?(params)
|
|
||||||
|
|
||||||
stream_entry(params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def recognized_stream_entry_url?(params)
|
def maxwidth_or_default
|
||||||
%w(stream_entries statuses).include?(params[:controller]) && params[:action] == 'show'
|
(params[:maxwidth].presence || 400).to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def stream_entry(params)
|
def maxheight_or_default
|
||||||
if params[:controller] == 'stream_entries'
|
params[:maxheight].present? ? params[:maxheight].to_i : nil
|
||||||
StreamEntry.find(params[:id])
|
|
||||||
else
|
|
||||||
Status.find(params[:id]).stream_entry
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::PushController < ApiController
|
class Api::PushController < Api::BaseController
|
||||||
|
include SignatureVerification
|
||||||
|
|
||||||
def update
|
def update
|
||||||
response, status = process_push_request
|
response, status = process_push_request
|
||||||
render plain: response, status: status
|
render plain: response, status: status
|
||||||
@@ -11,7 +13,7 @@ class Api::PushController < ApiController
|
|||||||
def process_push_request
|
def process_push_request
|
||||||
case hub_mode
|
case hub_mode
|
||||||
when 'subscribe'
|
when 'subscribe'
|
||||||
Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds)
|
Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds, verified_domain)
|
||||||
when 'unsubscribe'
|
when 'unsubscribe'
|
||||||
Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
|
Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
|
||||||
else
|
else
|
||||||
@@ -57,6 +59,10 @@ class Api::PushController < ApiController
|
|||||||
TagManager.instance.web_domain?(hub_topic_domain)
|
TagManager.instance.web_domain?(hub_topic_domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verified_domain
|
||||||
|
return signed_request_account.domain if signed_request_account
|
||||||
|
end
|
||||||
|
|
||||||
def hub_topic_domain
|
def hub_topic_domain
|
||||||
hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
|
hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::SalmonController < ApiController
|
class Api::SalmonController < Api::BaseController
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
respond_to :txt
|
respond_to :txt
|
||||||
|
|
||||||
def update
|
def update
|
||||||
payload = request.body.read
|
if verify_payload?
|
||||||
|
process_salmon
|
||||||
if !payload.nil? && verify?(payload)
|
|
||||||
SalmonWorker.perform_async(@account.id, payload.force_encoding('UTF-8'))
|
|
||||||
head 201
|
head 201
|
||||||
else
|
else
|
||||||
head 202
|
head 202
|
||||||
@@ -21,7 +19,15 @@ class Api::SalmonController < ApiController
|
|||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify?(payload)
|
def payload
|
||||||
VerifySalmonService.new.call(payload)
|
@_payload ||= request.body.read
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_payload?
|
||||||
|
payload.present? && VerifySalmonService.new.call(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_salmon
|
||||||
|
SalmonWorker.perform_async(@account.id, payload.force_encoding('UTF-8'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::SubscriptionsController < ApiController
|
class Api::SubscriptionsController < Api::BaseController
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
respond_to :txt
|
respond_to :txt
|
||||||
|
|
||||||
def show
|
def show
|
||||||
if @account.subscription(api_subscription_url(@account.id)).valid?(params['hub.topic'])
|
if subscription.valid?(params['hub.topic'])
|
||||||
@account.update(subscription_expires_at: Time.now.utc + (params['hub.lease_seconds'] || 86_400).to_i.seconds)
|
@account.update(subscription_expires_at: future_expires)
|
||||||
render plain: HTMLEntities.new.encode(params['hub.challenge']), status: 200
|
render plain: encoded_challenge, status: 200
|
||||||
else
|
else
|
||||||
head 404
|
head 404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
body = request.body.read
|
|
||||||
subscription = @account.subscription(api_subscription_url(@account.id))
|
|
||||||
|
|
||||||
if subscription.verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
|
if subscription.verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
|
||||||
ProcessingWorker.perform_async(@account.id, body.force_encoding('UTF-8'))
|
ProcessingWorker.perform_async(@account.id, body.force_encoding('UTF-8'))
|
||||||
end
|
end
|
||||||
@@ -26,6 +23,28 @@ class Api::SubscriptionsController < ApiController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def subscription
|
||||||
|
@_subscription ||= @account.subscription(
|
||||||
|
api_subscription_url(@account.id)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def body
|
||||||
|
@_body ||= request.body.read
|
||||||
|
end
|
||||||
|
|
||||||
|
def encoded_challenge
|
||||||
|
HTMLEntities.new.encode(params['hub.challenge'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def future_expires
|
||||||
|
Time.now.utc + lease_seconds_or_default
|
||||||
|
end
|
||||||
|
|
||||||
|
def lease_seconds_or_default
|
||||||
|
(params['hub.lease_seconds'] || 1.day).to_i.seconds
|
||||||
|
end
|
||||||
|
|
||||||
def set_account
|
def set_account
|
||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|||||||
23
app/controllers/api/v1/accounts/credentials_controller.rb
Normal file
23
app/controllers/api/v1/accounts/credentials_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::CredentialsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :write }, only: [:update]
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
def show
|
||||||
|
@account = current_account
|
||||||
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
current_account.update!(account_params)
|
||||||
|
@account = current_account
|
||||||
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def account_params
|
||||||
|
params.permit(:display_name, :note, :avatar, :header)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :set_account
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = load_accounts
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_follows).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:active_relationships).references(:active_relationships)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_follows
|
||||||
|
Follow.where(target_account: @account).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_account_followers_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_account_followers_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.active_relationships.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.active_relationships.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:limit).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :set_account
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = load_accounts
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_follows).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:passive_relationships).references(:passive_relationships)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_follows
|
||||||
|
Follow.where(account: @account).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_account_following_index_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_account_following_index_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.passive_relationships.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.passive_relationships.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:limit).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
23
app/controllers/api/v1/accounts/relationships_controller.rb
Normal file
23
app/controllers/api/v1/accounts/relationships_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::RelationshipsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = Account.where(id: account_ids).select('id')
|
||||||
|
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def relationships
|
||||||
|
AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_ids
|
||||||
|
@_account_ids ||= Array(params[:id]).map(&:to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
28
app/controllers/api/v1/accounts/search_controller.rb
Normal file
28
app/controllers/api/v1/accounts/search_controller.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::SearchController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def show
|
||||||
|
@accounts = account_search
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def account_search
|
||||||
|
AccountSearchService.new.call(
|
||||||
|
params[:q],
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
resolving_search?,
|
||||||
|
current_account
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolving_search?
|
||||||
|
params[:resolve] == 'true'
|
||||||
|
end
|
||||||
|
end
|
||||||
91
app/controllers/api/v1/accounts/statuses_controller.rb
Normal file
91
app/controllers/api/v1/accounts/statuses_controller.rb
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :set_account
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@statuses = load_statuses
|
||||||
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_statuses
|
||||||
|
cached_account_statuses
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_account_statuses
|
||||||
|
cache_collection account_statuses, Status
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_statuses
|
||||||
|
default_statuses.tap do |statuses|
|
||||||
|
statuses.merge!(only_media_scope) if params[:only_media]
|
||||||
|
statuses.merge!(no_replies_scope) if params[:exclude_replies]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_statuses
|
||||||
|
permitted_account_statuses.paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def permitted_account_statuses
|
||||||
|
@account.statuses.permitted_for(@account, current_account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def only_media_scope
|
||||||
|
Status.where(id: account_media_status_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_media_status_ids
|
||||||
|
@account.media_attachments.attached.reorder(nil).select(:status_id).distinct
|
||||||
|
end
|
||||||
|
|
||||||
|
def no_replies_scope
|
||||||
|
Status.without_replies
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_account_statuses_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @statuses.empty?
|
||||||
|
api_v1_account_statuses_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@statuses.first.id
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,132 +1,45 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::AccountsController < ApiController
|
class Api::V1::AccountsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute, :update_credentials]
|
before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
|
||||||
before_action -> { doorkeeper_authorize! :follow }, only: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
|
before_action -> { doorkeeper_authorize! :follow }, only: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
|
||||||
before_action -> { doorkeeper_authorize! :write }, only: [:update_credentials]
|
before_action :require_user!, except: [:show]
|
||||||
before_action :require_user!, except: [:show, :following, :followers, :statuses]
|
before_action :set_account
|
||||||
before_action :set_account, except: [:verify_credentials, :update_credentials, :suggestions, :search]
|
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
render json: @account, serializer: REST::AccountSerializer
|
||||||
def verify_credentials
|
|
||||||
@account = current_user.account
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_credentials
|
|
||||||
current_account.update!(account_params)
|
|
||||||
@account = current_account
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def following
|
|
||||||
@accounts = Account.includes(:passive_relationships)
|
|
||||||
.references(:passive_relationships)
|
|
||||||
.merge(Follow.where(account: @account)
|
|
||||||
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = following_api_v1_account_url(pagination_params(max_id: @accounts.last.passive_relationships.first.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = following_api_v1_account_url(pagination_params(since_id: @accounts.first.passive_relationships.first.id)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
|
|
||||||
render :index
|
|
||||||
end
|
|
||||||
|
|
||||||
def followers
|
|
||||||
@accounts = Account.includes(:active_relationships)
|
|
||||||
.references(:active_relationships)
|
|
||||||
.merge(Follow.where(target_account: @account)
|
|
||||||
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
|
||||||
params[:max_id],
|
|
||||||
params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = followers_api_v1_account_url(pagination_params(max_id: @accounts.last.active_relationships.first.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = followers_api_v1_account_url(pagination_params(since_id: @accounts.first.active_relationships.first.id)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
|
|
||||||
render :index
|
|
||||||
end
|
|
||||||
|
|
||||||
def statuses
|
|
||||||
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
|
|
||||||
@statuses = @statuses.where(id: MediaAttachment.where(account: @account).where.not(status_id: nil).reorder('').select('distinct status_id')) if params[:only_media]
|
|
||||||
@statuses = @statuses.without_replies if params[:exclude_replies]
|
|
||||||
@statuses = cache_collection(@statuses, Status)
|
|
||||||
|
|
||||||
set_maps(@statuses)
|
|
||||||
|
|
||||||
next_path = statuses_api_v1_account_url(statuses_pagination_params(max_id: @statuses.last.id)) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
|
||||||
prev_path = statuses_api_v1_account_url(statuses_pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow
|
def follow
|
||||||
FollowService.new.call(current_user.account, @account.acct)
|
FollowService.new.call(current_user.account, @account.acct)
|
||||||
set_relationship
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
render :relationship
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def block
|
def block
|
||||||
BlockService.new.call(current_user.account, @account)
|
BlockService.new.call(current_user.account, @account)
|
||||||
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
@following = { @account.id => false }
|
|
||||||
@followed_by = { @account.id => false }
|
|
||||||
@blocking = { @account.id => true }
|
|
||||||
@requested = { @account.id => false }
|
|
||||||
@muting = { @account.id => current_account.muting?(@account.id) }
|
|
||||||
@domain_blocking = { @account.id => current_account.domain_blocking?(@account.domain) }
|
|
||||||
|
|
||||||
render :relationship
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def mute
|
def mute
|
||||||
MuteService.new.call(current_user.account, @account)
|
MuteService.new.call(current_user.account, @account)
|
||||||
set_relationship
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
render :relationship
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfollow
|
def unfollow
|
||||||
UnfollowService.new.call(current_user.account, @account)
|
UnfollowService.new.call(current_user.account, @account)
|
||||||
set_relationship
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
render :relationship
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def unblock
|
def unblock
|
||||||
UnblockService.new.call(current_user.account, @account)
|
UnblockService.new.call(current_user.account, @account)
|
||||||
set_relationship
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
render :relationship
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmute
|
def unmute
|
||||||
UnmuteService.new.call(current_user.account, @account)
|
UnmuteService.new.call(current_user.account, @account)
|
||||||
set_relationship
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
render :relationship
|
|
||||||
end
|
|
||||||
|
|
||||||
def relationships
|
|
||||||
ids = params[:id].is_a?(Enumerable) ? params[:id].map(&:to_i) : [params[:id].to_i]
|
|
||||||
|
|
||||||
@accounts = Account.where(id: ids).select('id')
|
|
||||||
@following = Account.following_map(ids, current_user.account_id)
|
|
||||||
@followed_by = Account.followed_by_map(ids, current_user.account_id)
|
|
||||||
@blocking = Account.blocking_map(ids, current_user.account_id)
|
|
||||||
@muting = Account.muting_map(ids, current_user.account_id)
|
|
||||||
@requested = Account.requested_map(ids, current_user.account_id)
|
|
||||||
@domain_blocking = Account.domain_blocking_map(ids, current_user.account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def search
|
|
||||||
@accounts = AccountSearchService.new.call(params[:q], limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:resolve] == 'true', current_account)
|
|
||||||
|
|
||||||
render :index
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -135,24 +48,7 @@ class Api::V1::AccountsController < ApiController
|
|||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_relationship
|
def relationships
|
||||||
@following = Account.following_map([@account.id], current_user.account_id)
|
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
||||||
@followed_by = Account.followed_by_map([@account.id], current_user.account_id)
|
|
||||||
@blocking = Account.blocking_map([@account.id], current_user.account_id)
|
|
||||||
@muting = Account.muting_map([@account.id], current_user.account_id)
|
|
||||||
@requested = Account.requested_map([@account.id], current_user.account_id)
|
|
||||||
@domain_blocking = Account.domain_blocking_map([@account.id], current_user.account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:limit).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def statuses_pagination_params(core_params)
|
|
||||||
params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_params
|
|
||||||
params.permit(:display_name, :note, :avatar, :header)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,14 +1,28 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::AppsController < ApiController
|
class Api::V1::AppsController < Api::BaseController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@app = Doorkeeper::Application.create!(name: app_params[:client_name], redirect_uri: app_params[:redirect_uris], scopes: (app_params[:scopes] || Doorkeeper.configuration.default_scopes), website: app_params[:website])
|
@app = Doorkeeper::Application.create!(application_options)
|
||||||
|
render json: @app, serializer: REST::ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def application_options
|
||||||
|
{
|
||||||
|
name: app_params[:client_name],
|
||||||
|
redirect_uri: app_params[:redirect_uris],
|
||||||
|
scopes: app_scopes_or_default,
|
||||||
|
website: app_params[:website],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def app_scopes_or_default
|
||||||
|
app_params[:scopes] || Doorkeeper.configuration.default_scopes
|
||||||
|
end
|
||||||
|
|
||||||
def app_params
|
def app_params
|
||||||
params.permit(:client_name, :redirect_uris, :scopes, :website)
|
params.permit(:client_name, :redirect_uris, :scopes, :website)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,26 +1,63 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::BlocksController < ApiController
|
class Api::V1::BlocksController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :follow }
|
before_action -> { doorkeeper_authorize! :follow }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = Account.includes(:blocked_by)
|
@accounts = load_accounts
|
||||||
.references(:blocked_by)
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
.merge(Block.where(account: current_account)
|
|
||||||
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = api_v1_blocks_url(pagination_params(max_id: @accounts.last.blocked_by_ids.last)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = api_v1_blocks_url(pagination_params(since_id: @accounts.first.blocked_by_ids.first)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_blocks).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:blocked_by).references(:blocked_by)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_blocks
|
||||||
|
Block.where(account: current_account).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_blocks_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_blocks_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.blocked_by_ids.last
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.blocked_by_ids.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.permit(:limit).merge(core_params)
|
params.permit(:limit).merge(core_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::DomainBlocksController < ApiController
|
class Api::V1::DomainBlocksController < Api::BaseController
|
||||||
|
BLOCK_LIMIT = 100
|
||||||
|
|
||||||
before_action -> { doorkeeper_authorize! :follow }
|
before_action -> { doorkeeper_authorize! :follow }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers, only: :show
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@blocks = AccountDomainBlock.where(account: current_account).paginate_by_max_id(limit_param(100), params[:max_id], params[:since_id])
|
@blocks = load_domain_blocks
|
||||||
|
|
||||||
next_path = api_v1_domain_blocks_url(pagination_params(max_id: @blocks.last.id)) if @blocks.size == limit_param(100)
|
|
||||||
prev_path = api_v1_domain_blocks_url(pagination_params(since_id: @blocks.first.id)) unless @blocks.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
render json: @blocks.map(&:domain)
|
render json: @blocks.map(&:domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -28,6 +26,46 @@ class Api::V1::DomainBlocksController < ApiController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_domain_blocks
|
||||||
|
account_domain_blocks.paginate_by_max_id(
|
||||||
|
limit_param(BLOCK_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_domain_blocks
|
||||||
|
current_account.domain_blocks
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_domain_blocks_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @blocks.empty?
|
||||||
|
api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@blocks.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@blocks.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@blocks.size == limit_param(BLOCK_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.permit(:limit).merge(core_params)
|
params.permit(:limit).merge(core_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,25 +1,72 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::FavouritesController < ApiController
|
class Api::V1::FavouritesController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
results = Favourite.where(account: current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
|
@statuses = load_statuses
|
||||||
@statuses = cache_collection(Status.where(id: results.map(&:status_id)), Status)
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
|
|
||||||
set_maps(@statuses)
|
|
||||||
|
|
||||||
next_path = api_v1_favourites_url(pagination_params(max_id: results.last.id)) if results.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
|
||||||
prev_path = api_v1_favourites_url(pagination_params(since_id: results.first.id)) unless results.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_statuses
|
||||||
|
cached_favourites
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_favourites
|
||||||
|
cache_collection(
|
||||||
|
Status.where(
|
||||||
|
id: results.map(&:status_id)
|
||||||
|
),
|
||||||
|
Status
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def results
|
||||||
|
@_results ||= account_favourites.paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_favourites
|
||||||
|
current_account.favourites
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_favourites_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless results.empty?
|
||||||
|
api_v1_favourites_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
results.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
results.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
results.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.permit(:limit).merge(core_params)
|
params.permit(:limit).merge(core_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,34 +1,75 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::FollowRequestsController < ApiController
|
class Api::V1::FollowRequestsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :follow }
|
before_action -> { doorkeeper_authorize! :follow }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = Account.includes(:follow_requests)
|
@accounts = load_accounts
|
||||||
.references(:follow_requests)
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
.merge(FollowRequest.where(target_account: current_account)
|
|
||||||
.paginate_by_max_id(DEFAULT_ACCOUNTS_LIMIT, params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = api_v1_follow_requests_url(pagination_params(max_id: @accounts.last.follow_requests.last.id)) if @accounts.size == DEFAULT_ACCOUNTS_LIMIT
|
|
||||||
prev_path = api_v1_follow_requests_url(pagination_params(since_id: @accounts.first.follow_requests.first.id)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize
|
def authorize
|
||||||
AuthorizeFollowService.new.call(Account.find(params[:id]), current_account)
|
AuthorizeFollowService.new.call(account, current_account)
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
def reject
|
def reject
|
||||||
RejectFollowService.new.call(Account.find(params[:id]), current_account)
|
RejectFollowService.new.call(account, current_account)
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def account
|
||||||
|
Account.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_follow_requests).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:follow_requests).references(:follow_requests)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_follow_requests
|
||||||
|
FollowRequest.where(target_account: current_account).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_follow_requests_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_follow_requests_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.follow_requests.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.follow_requests.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.permit(:limit).merge(core_params)
|
params.permit(:limit).merge(core_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::FollowsController < ApiController
|
class Api::V1::FollowsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :follow }
|
before_action -> { doorkeeper_authorize! :follow }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ class Api::V1::FollowsController < ApiController
|
|||||||
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
|
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
|
||||||
|
|
||||||
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
||||||
render :show
|
render json: @account, serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::InstancesController < ApiController
|
class Api::V1::InstancesController < Api::BaseController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
render json: {}, serializer: REST::InstanceSerializer
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::MediaController < ApiController
|
class Api::V1::MediaController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :write }
|
before_action -> { doorkeeper_authorize! :write }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|
||||||
@@ -10,11 +10,12 @@ class Api::V1::MediaController < ApiController
|
|||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@media = MediaAttachment.create!(account: current_user.account, file: media_params[:file])
|
@media = current_account.media_attachments.create!(file: media_params[:file])
|
||||||
|
render json: @media, serializer: REST::MediaAttachmentSerializer
|
||||||
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
||||||
render json: { error: 'File type of uploaded media could not be verified' }, status: 422
|
render json: file_type_error, status: 422
|
||||||
rescue Paperclip::Error
|
rescue Paperclip::Error
|
||||||
render json: { error: 'Error processing thumbnail for uploaded media' }, status: 500
|
render json: processing_error, status: 500
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -22,4 +23,12 @@ class Api::V1::MediaController < ApiController
|
|||||||
def media_params
|
def media_params
|
||||||
params.permit(:file)
|
params.permit(:file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def file_type_error
|
||||||
|
{ error: 'File type of uploaded media could not be verified' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def processing_error
|
||||||
|
{ error: 'Error processing thumbnail for uploaded media' }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,26 +1,63 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::MutesController < ApiController
|
class Api::V1::MutesController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :follow }
|
before_action -> { doorkeeper_authorize! :follow }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = Account.includes(:muted_by)
|
@accounts = load_accounts
|
||||||
.references(:muted_by)
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
.merge(Mute.where(account: current_account)
|
|
||||||
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = api_v1_mutes_url(pagination_params(max_id: @accounts.last.muted_by_ids.last)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = api_v1_mutes_url(pagination_params(since_id: @accounts.first.muted_by_ids.first)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_mutes).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:muted_by).references(:muted_by)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_mutes
|
||||||
|
Mute.where(account: current_account).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_mutes_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_mutes_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.muted_by_ids.last
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.muted_by_ids.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.permit(:limit).merge(core_params)
|
params.permit(:limit).merge(core_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,42 +1,80 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::NotificationsController < ApiController
|
class Api::V1::NotificationsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
DEFAULT_NOTIFICATIONS_LIMIT = 15
|
DEFAULT_NOTIFICATIONS_LIMIT = 15
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@notifications = Notification.where(account: current_account).browserable(exclude_types).paginate_by_max_id(limit_param(DEFAULT_NOTIFICATIONS_LIMIT), params[:max_id], params[:since_id])
|
@notifications = load_notifications
|
||||||
@notifications = cache_collection(@notifications, Notification)
|
render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
|
||||||
statuses = @notifications.select { |n| !n.target_status.nil? }.map(&:target_status)
|
|
||||||
|
|
||||||
set_maps(statuses)
|
|
||||||
|
|
||||||
next_path = api_v1_notifications_url(pagination_params(max_id: @notifications.last.id)) unless @notifications.empty?
|
|
||||||
prev_path = api_v1_notifications_url(pagination_params(since_id: @notifications.first.id)) unless @notifications.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@notification = Notification.where(account: current_account).find(params[:id])
|
@notification = current_account.notifications.find(params[:id])
|
||||||
|
render json: @notification, serializer: REST::NotificationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear
|
def clear
|
||||||
Notification.where(account: current_account).delete_all
|
current_account.notifications.delete_all
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
def dismiss
|
def dismiss
|
||||||
Notification.find_by!(account: current_account, id: params[:id]).destroy!
|
current_account.notifications.find_by!(id: params[:id]).destroy!
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_notifications
|
||||||
|
cache_collection paginated_notifications, Notification
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_notifications
|
||||||
|
browserable_account_notifications.paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def browserable_account_notifications
|
||||||
|
current_account.notifications.browserable(exclude_types)
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_statuses_from_notifications
|
||||||
|
@notifications.reject { |notification| notification.target_status.nil? }.map(&:target_status)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
unless @notifications.empty?
|
||||||
|
api_v1_notifications_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @notifications.empty?
|
||||||
|
api_v1_notifications_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@notifications.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@notifications.first.id
|
||||||
|
end
|
||||||
|
|
||||||
def exclude_types
|
def exclude_types
|
||||||
val = params.permit(exclude_types: [])[:exclude_types] || []
|
val = params.permit(exclude_types: [])[:exclude_types] || []
|
||||||
val = [val] unless val.is_a?(Enumerable)
|
val = [val] unless val.is_a?(Enumerable)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::ReportsController < ApiController
|
class Api::V1::ReportsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read }, except: [:create]
|
before_action -> { doorkeeper_authorize! :read }, except: [:create]
|
||||||
before_action -> { doorkeeper_authorize! :write }, only: [:create]
|
before_action -> { doorkeeper_authorize! :write }, only: [:create]
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
@@ -8,22 +8,36 @@ class Api::V1::ReportsController < ApiController
|
|||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@reports = Report.where(account: current_account)
|
@reports = current_account.reports
|
||||||
|
render json: @reports, each_serializer: REST::ReportSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
status_ids = report_params[:status_ids].is_a?(Enumerable) ? report_params[:status_ids] : [report_params[:status_ids]]
|
@report = current_account.reports.create!(
|
||||||
|
target_account: reported_account,
|
||||||
|
status_ids: reported_status_ids,
|
||||||
|
comment: report_params[:comment]
|
||||||
|
)
|
||||||
|
|
||||||
@report = Report.create!(account: current_account,
|
User.admins.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
|
||||||
target_account: Account.find(report_params[:account_id]),
|
|
||||||
status_ids: Status.find(status_ids).pluck(:id),
|
|
||||||
comment: report_params[:comment])
|
|
||||||
|
|
||||||
render :show
|
render json: @report, serializer: REST::ReportSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def reported_status_ids
|
||||||
|
Status.find(status_ids).pluck(:id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_ids
|
||||||
|
Array(report_params[:status_ids])
|
||||||
|
end
|
||||||
|
|
||||||
|
def reported_account
|
||||||
|
Account.find(report_params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
def report_params
|
def report_params
|
||||||
params.permit(:account_id, :comment, status_ids: [])
|
params.permit(:account_id, :comment, status_ids: [])
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,30 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::SearchController < ApiController
|
class Api::V1::SearchController < Api::BaseController
|
||||||
|
RESULTS_LIMIT = 5
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@search = OpenStruct.new(SearchService.new.call(params[:q], 5, params[:resolve] == 'true', current_account))
|
@search = Search.new(search_results)
|
||||||
|
render json: @search, serializer: REST::SearchSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def search_results
|
||||||
|
SearchService.new.call(
|
||||||
|
params[:q],
|
||||||
|
RESULTS_LIMIT,
|
||||||
|
resolving_search?,
|
||||||
|
current_account
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolving_search?
|
||||||
|
params[:resolve] == 'true'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action :authorize_if_got_token
|
||||||
|
before_action :set_status
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = load_accounts
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_favourites).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account
|
||||||
|
.includes(:favourites)
|
||||||
|
.references(:favourites)
|
||||||
|
.where(favourites: { status_id: @status.id })
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_favourites
|
||||||
|
Favourite.paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.favourites.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.favourites.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_status
|
||||||
|
@status = Status.find(params[:status_id])
|
||||||
|
authorize @status, :show?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404 instead of a 403 error code
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_if_got_token
|
||||||
|
request_token = Doorkeeper::OAuth::Token.from_request(request, *Doorkeeper.configuration.access_token_methods)
|
||||||
|
doorkeeper_authorize! :read if request_token
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:limit).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
38
app/controllers/api/v1/statuses/favourites_controller.rb
Normal file
38
app/controllers/api/v1/statuses/favourites_controller.rb
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Statuses::FavouritesController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :write }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def create
|
||||||
|
@status = favourited_status
|
||||||
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@status = requested_status
|
||||||
|
@favourites_map = { @status.id => false }
|
||||||
|
|
||||||
|
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
|
||||||
|
|
||||||
|
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def favourited_status
|
||||||
|
service_result.status.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_result
|
||||||
|
FavouriteService.new.call(current_user.account, requested_status)
|
||||||
|
end
|
||||||
|
|
||||||
|
def requested_status
|
||||||
|
Status.find(params[:status_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
41
app/controllers/api/v1/statuses/mutes_controller.rb
Normal file
41
app/controllers/api/v1/statuses/mutes_controller.rb
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Statuses::MutesController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :write }
|
||||||
|
before_action :require_user!
|
||||||
|
before_action :set_status
|
||||||
|
before_action :set_conversation
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def create
|
||||||
|
current_account.mute_conversation!(@conversation)
|
||||||
|
@mutes_map = { @conversation.id => true }
|
||||||
|
|
||||||
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
current_account.unmute_conversation!(@conversation)
|
||||||
|
@mutes_map = { @conversation.id => false }
|
||||||
|
|
||||||
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_status
|
||||||
|
@status = Status.find(params[:status_id])
|
||||||
|
authorize @status, :show?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404 instead of a 403 error code
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_conversation
|
||||||
|
@conversation = @status.conversation
|
||||||
|
raise Mastodon::ValidationError if @conversation.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action :authorize_if_got_token
|
||||||
|
before_action :set_status
|
||||||
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = load_accounts
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_accounts
|
||||||
|
default_accounts.merge(paginated_statuses).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_accounts
|
||||||
|
Account.includes(:statuses).references(:statuses)
|
||||||
|
end
|
||||||
|
|
||||||
|
def paginated_statuses
|
||||||
|
Status.where(reblog_of_id: @status.id).paginate_by_max_id(
|
||||||
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
|
params[:max_id],
|
||||||
|
params[:since_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
if records_continue?
|
||||||
|
api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
unless @accounts.empty?
|
||||||
|
api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.statuses.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_status
|
||||||
|
@status = Status.find(params[:status_id])
|
||||||
|
authorize @status, :show?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404 instead of a 403 error code
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_if_got_token
|
||||||
|
request_token = Doorkeeper::OAuth::Token.from_request(request, *Doorkeeper.configuration.access_token_methods)
|
||||||
|
doorkeeper_authorize! :read if request_token
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:limit).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
35
app/controllers/api/v1/statuses/reblogs_controller.rb
Normal file
35
app/controllers/api/v1/statuses/reblogs_controller.rb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :write }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def create
|
||||||
|
@status = ReblogService.new.call(current_user.account, status_for_reblog)
|
||||||
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@status = status_for_destroy.reblog
|
||||||
|
@reblogs_map = { @status.id => false }
|
||||||
|
|
||||||
|
authorize status_for_destroy, :unreblog?
|
||||||
|
RemovalWorker.perform_async(status_for_destroy.id)
|
||||||
|
|
||||||
|
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def status_for_reblog
|
||||||
|
Status.find params[:status_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_for_destroy
|
||||||
|
current_user.account.statuses.where(reblog_of_id: params[:status_id]).first!
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::StatusesController < ApiController
|
class Api::V1::StatusesController < Api::BaseController
|
||||||
before_action :authorize_if_got_token, except: [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite, :mute, :unmute]
|
include Authorization
|
||||||
before_action -> { doorkeeper_authorize! :write }, only: [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite, :mute, :unmute]
|
|
||||||
before_action :require_user!, except: [:show, :context, :card, :reblogged_by, :favourited_by]
|
before_action :authorize_if_got_token, except: [:create, :destroy]
|
||||||
before_action :set_status, only: [:show, :context, :card, :reblogged_by, :favourited_by, :mute, :unmute]
|
before_action -> { doorkeeper_authorize! :write }, only: [:create, :destroy]
|
||||||
before_action :set_conversation, only: [:mute, :unmute]
|
before_action :require_user!, except: [:show, :context, :card]
|
||||||
|
before_action :set_status, only: [:show, :context, :card]
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
cached = Rails.cache.read(@status.cache_key)
|
cached = Rails.cache.read(@status.cache_key)
|
||||||
@status = cached unless cached.nil?
|
@status = cached unless cached.nil?
|
||||||
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def context
|
def context
|
||||||
@@ -20,45 +22,20 @@ class Api::V1::StatusesController < ApiController
|
|||||||
loaded_ancestors = cache_collection(ancestors_results, Status)
|
loaded_ancestors = cache_collection(ancestors_results, Status)
|
||||||
loaded_descendants = cache_collection(descendants_results, Status)
|
loaded_descendants = cache_collection(descendants_results, Status)
|
||||||
|
|
||||||
@context = OpenStruct.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
||||||
statuses = [@status] + @context[:ancestors] + @context[:descendants]
|
statuses = [@status] + @context.ancestors + @context.descendants
|
||||||
|
|
||||||
set_maps(statuses)
|
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def card
|
def card
|
||||||
@card = PreviewCard.find_by(status: @status)
|
@card = PreviewCard.find_by(status: @status)
|
||||||
render_empty if @card.nil?
|
|
||||||
|
if @card.nil?
|
||||||
|
render_empty
|
||||||
|
else
|
||||||
|
render json: @card, serializer: REST::PreviewCardSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblogged_by
|
|
||||||
@accounts = Account.includes(:statuses)
|
|
||||||
.references(:statuses)
|
|
||||||
.merge(Status.where(reblog_of_id: @status.id)
|
|
||||||
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = reblogged_by_api_v1_status_url(pagination_params(max_id: @accounts.last.statuses.last.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = reblogged_by_api_v1_status_url(pagination_params(since_id: @accounts.first.statuses.first.id)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
|
|
||||||
render :accounts
|
|
||||||
end
|
|
||||||
|
|
||||||
def favourited_by
|
|
||||||
@accounts = Account.includes(:favourites)
|
|
||||||
.references(:favourites)
|
|
||||||
.where(favourites: { status_id: @status.id })
|
|
||||||
.merge(Favourite.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
|
|
||||||
.to_a
|
|
||||||
|
|
||||||
next_path = favourited_by_api_v1_status_url(pagination_params(max_id: @accounts.last.favourites.last.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
prev_path = favourited_by_api_v1_status_url(pagination_params(since_id: @accounts.first.favourites.first.id)) unless @accounts.empty?
|
|
||||||
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
|
|
||||||
render :accounts
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -72,70 +49,26 @@ class Api::V1::StatusesController < ApiController
|
|||||||
application: doorkeeper_token.application,
|
application: doorkeeper_token.application,
|
||||||
idempotency: request.headers['Idempotency-Key'])
|
idempotency: request.headers['Idempotency-Key'])
|
||||||
|
|
||||||
render :show
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@status = Status.where(account_id: current_user.account).find(params[:id])
|
@status = Status.where(account_id: current_user.account).find(params[:id])
|
||||||
|
authorize @status, :destroy?
|
||||||
|
|
||||||
RemovalWorker.perform_async(@status.id)
|
RemovalWorker.perform_async(@status.id)
|
||||||
|
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblog
|
|
||||||
@status = ReblogService.new.call(current_user.account, Status.find(params[:id]))
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def unreblog
|
|
||||||
reblog = Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!
|
|
||||||
@status = reblog.reblog
|
|
||||||
@reblogs_map = { @status.id => false }
|
|
||||||
|
|
||||||
RemovalWorker.perform_async(reblog.id)
|
|
||||||
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def favourite
|
|
||||||
@status = FavouriteService.new.call(current_user.account, Status.find(params[:id])).status.reload
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def unfavourite
|
|
||||||
@status = Status.find(params[:id])
|
|
||||||
@favourites_map = { @status.id => false }
|
|
||||||
|
|
||||||
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
|
|
||||||
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def mute
|
|
||||||
current_account.mute_conversation!(@conversation)
|
|
||||||
|
|
||||||
@mutes_map = { @conversation.id => true }
|
|
||||||
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
def unmute
|
|
||||||
current_account.unmute_conversation!(@conversation)
|
|
||||||
|
|
||||||
@mutes_map = { @conversation.id => false }
|
|
||||||
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_status
|
def set_status
|
||||||
@status = Status.find(params[:id])
|
@status = Status.find(params[:id])
|
||||||
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
|
authorize @status, :show?
|
||||||
end
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404 instead of a 403 error code
|
||||||
def set_conversation
|
raise ActiveRecord::RecordNotFound
|
||||||
@conversation = @status.conversation
|
|
||||||
raise Mastodon::ValidationError if @conversation.nil?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_params
|
def status_params
|
||||||
|
|||||||
15
app/controllers/api/v1/streaming_controller.rb
Normal file
15
app/controllers/api/v1/streaming_controller.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::StreamingController < Api::BaseController
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
if Rails.configuration.x.streaming_api_base_url != request.host
|
||||||
|
uri = URI.parse(request.url)
|
||||||
|
uri.host = URI.parse(Rails.configuration.x.streaming_api_base_url).host
|
||||||
|
redirect_to uri.to_s, status: 301
|
||||||
|
else
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Api::V1::Timelines
|
|
||||||
class BaseController < ApiController
|
|
||||||
respond_to :json
|
|
||||||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def cache_collection(raw)
|
|
||||||
super(raw, Status)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:local, :limit).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def insert_pagination_headers
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
raise 'Override in child controllers'
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
raise 'Override in child controllers'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::V1::Timelines
|
class Api::V1::Timelines::HomeController < Api::BaseController
|
||||||
class HomeController < BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }, only: [:show]
|
before_action -> { doorkeeper_authorize! :read }, only: [:show]
|
||||||
before_action :require_user!, only: [:show]
|
before_action :require_user!, only: [:show]
|
||||||
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_statuses
|
def load_statuses
|
||||||
cached_home_statuses.tap do |statuses|
|
cached_home_statuses
|
||||||
set_maps(statuses)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_home_statuses
|
def cached_home_statuses
|
||||||
cache_collection home_statuses
|
cache_collection home_statuses, Status
|
||||||
end
|
end
|
||||||
|
|
||||||
def home_statuses
|
def home_statuses
|
||||||
@@ -33,12 +34,27 @@ module Api::V1::Timelines
|
|||||||
Feed.new(:home, current_account)
|
Feed.new(:home, current_account)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:local, :limit).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
def next_path
|
def next_path
|
||||||
api_v1_timelines_home_url pagination_params(max_id: @statuses.last.id)
|
api_v1_timelines_home_url pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_home_url pagination_params(since_id: @statuses.first.id)
|
api_v1_timelines_home_url pagination_params(since_id: pagination_since_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@statuses.first.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::V1::Timelines
|
class Api::V1::Timelines::PublicController < Api::BaseController
|
||||||
class PublicController < BaseController
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_statuses
|
def load_statuses
|
||||||
cached_public_statuses.tap do |statuses|
|
cached_public_statuses
|
||||||
set_maps(statuses)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_public_statuses
|
def cached_public_statuses
|
||||||
cache_collection public_statuses
|
cache_collection public_statuses, Status
|
||||||
end
|
end
|
||||||
|
|
||||||
def public_statuses
|
def public_statuses
|
||||||
@@ -30,12 +32,27 @@ module Api::V1::Timelines
|
|||||||
Status.as_public_timeline(current_account, params[:local])
|
Status.as_public_timeline(current_account, params[:local])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:local, :limit).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
def next_path
|
def next_path
|
||||||
api_v1_timelines_public_url pagination_params(max_id: @statuses.last.id)
|
api_v1_timelines_public_url pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_public_url pagination_params(since_id: @statuses.first.id)
|
api_v1_timelines_public_url pagination_params(since_id: pagination_since_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@statuses.first.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::V1::Timelines
|
class Api::V1::Timelines::TagController < Api::BaseController
|
||||||
class TagController < BaseController
|
|
||||||
before_action :load_tag
|
before_action :load_tag
|
||||||
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -15,13 +18,11 @@ module Api::V1::Timelines
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_statuses
|
def load_statuses
|
||||||
cached_tagged_statuses.tap do |statuses|
|
cached_tagged_statuses
|
||||||
set_maps(statuses)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_tagged_statuses
|
def cached_tagged_statuses
|
||||||
cache_collection tagged_statuses
|
cache_collection tagged_statuses, Status
|
||||||
end
|
end
|
||||||
|
|
||||||
def tagged_statuses
|
def tagged_statuses
|
||||||
@@ -40,12 +41,27 @@ module Api::V1::Timelines
|
|||||||
Status.as_tag_timeline(@tag, current_account, params[:local])
|
Status.as_tag_timeline(@tag, current_account, params[:local])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.permit(:local, :limit).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
def next_path
|
def next_path
|
||||||
api_v1_timelines_tag_url params[:id], pagination_params(max_id: @statuses.last.id)
|
api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_tag_url params[:id], pagination_params(since_id: @statuses.first.id)
|
api_v1_timelines_tag_url params[:id], pagination_params(since_id: pagination_since_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@statuses.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@statuses.first.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
52
app/controllers/api/web/push_subscriptions_controller.rb
Normal file
52
app/controllers/api/web/push_subscriptions_controller.rb
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::Web::PushSubscriptionsController < Api::BaseController
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
def create
|
||||||
|
params.require(:subscription).require(:endpoint)
|
||||||
|
params.require(:subscription).require(:keys).require([:auth, :p256dh])
|
||||||
|
|
||||||
|
active_session = current_session
|
||||||
|
|
||||||
|
unless active_session.web_push_subscription.nil?
|
||||||
|
active_session.web_push_subscription.destroy!
|
||||||
|
active_session.update!(web_push_subscription: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mobile devices do not support regular notifications, so we enable push notifications by default
|
||||||
|
alerts_enabled = active_session.detection.device.mobile? || active_session.detection.device.tablet?
|
||||||
|
|
||||||
|
data = {
|
||||||
|
alerts: {
|
||||||
|
follow: alerts_enabled,
|
||||||
|
favourite: alerts_enabled,
|
||||||
|
reblog: alerts_enabled,
|
||||||
|
mention: alerts_enabled,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
web_subscription = ::Web::PushSubscription.create!(
|
||||||
|
endpoint: params[:subscription][:endpoint],
|
||||||
|
key_p256dh: params[:subscription][:keys][:p256dh],
|
||||||
|
key_auth: params[:subscription][:keys][:auth],
|
||||||
|
data: data
|
||||||
|
)
|
||||||
|
|
||||||
|
active_session.update!(web_push_subscription: web_subscription)
|
||||||
|
|
||||||
|
render json: web_subscription.as_payload
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
params.require([:id, :data])
|
||||||
|
|
||||||
|
web_subscription = ::Web::PushSubscription.find(params[:id])
|
||||||
|
|
||||||
|
web_subscription.update!(data: params[:data])
|
||||||
|
|
||||||
|
render json: web_subscription.as_payload
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::Web::SettingsController < ApiController
|
class Api::Web::SettingsController < Api::BaseController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base
|
|||||||
include UserTrackingConcern
|
include UserTrackingConcern
|
||||||
|
|
||||||
helper_method :current_account
|
helper_method :current_account
|
||||||
|
helper_method :current_session
|
||||||
helper_method :single_user_mode?
|
helper_method :single_user_mode?
|
||||||
|
|
||||||
rescue_from ActionController::RoutingError, with: :not_found
|
rescue_from ActionController::RoutingError, with: :not_found
|
||||||
@@ -68,6 +69,10 @@ class ApplicationController < ActionController::Base
|
|||||||
@current_account ||= current_user.try(:account)
|
@current_account ||= current_user.try(:account)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_session
|
||||||
|
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
|
||||||
|
end
|
||||||
|
|
||||||
def cache_collection(raw, klass)
|
def cache_collection(raw, klass)
|
||||||
return raw unless klass.respond_to?(:with_includes)
|
return raw unless klass.respond_to?(:with_includes)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
|
|
||||||
before_action :check_enabled_registrations, only: [:new, :create]
|
before_action :check_enabled_registrations, only: [:new, :create]
|
||||||
before_action :configure_sign_up_params, only: [:create]
|
before_action :configure_sign_up_params, only: [:create]
|
||||||
|
before_action :set_sessions, only: [:edit, :update]
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
not_found
|
not_found
|
||||||
@@ -41,4 +42,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
def determine_layout
|
def determine_layout
|
||||||
%w(edit update).include?(action_name) ? 'admin' : 'auth'
|
%w(edit update).include?(action_name) ? 'admin' : 'auth'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_sessions
|
||||||
|
@sessions = current_user.session_activations
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||||||
if session[:otp_user_id]
|
if session[:otp_user_id]
|
||||||
User.find(session[:otp_user_id])
|
User.find(session[:otp_user_id])
|
||||||
elsif user_params[:email]
|
elsif user_params[:email]
|
||||||
User.find_by(email: user_params[:email])
|
User.find_for_authentication(email: user_params[:email])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class AuthorizeFollowsController < ApplicationController
|
|||||||
if @account.nil?
|
if @account.nil?
|
||||||
render :error
|
render :error
|
||||||
else
|
else
|
||||||
redirect_to web_url("accounts/#{@account.id}")
|
render :success
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
|
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
|
||||||
render :error
|
render :error
|
||||||
@@ -40,7 +40,7 @@ class AuthorizeFollowsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def account_from_remote_follow
|
def account_from_remote_follow
|
||||||
FollowRemoteAccountService.new.call(acct_without_prefix)
|
ResolveRemoteAccountService.new.call(acct_without_prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
def acct_param_is_url?
|
def acct_param_is_url?
|
||||||
|
|||||||
22
app/controllers/concerns/authorization.rb
Normal file
22
app/controllers/concerns/authorization.rb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Authorization
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
include Pundit
|
||||||
|
|
||||||
|
def pundit_user
|
||||||
|
current_account
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize(*)
|
||||||
|
super
|
||||||
|
rescue Pundit::NotAuthorizedError
|
||||||
|
raise Mastodon::NotPermittedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_with(user, record, query)
|
||||||
|
Pundit.authorize(user, record, query)
|
||||||
|
rescue Pundit::NotAuthorizedError
|
||||||
|
raise Mastodon::NotPermittedError
|
||||||
|
end
|
||||||
|
end
|
||||||
30
app/controllers/concerns/export_controller_concern.rb
Normal file
30
app/controllers/concerns/export_controller_concern.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module ExportControllerConcern
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
before_action :authenticate_user!
|
||||||
|
before_action :load_export
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_export
|
||||||
|
@export = Export.new(current_account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_export_file
|
||||||
|
respond_to do |format|
|
||||||
|
format.csv { send_data export_data, filename: export_filename }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def export_data
|
||||||
|
raise 'Override in controller'
|
||||||
|
end
|
||||||
|
|
||||||
|
def export_filename
|
||||||
|
"#{controller_name}.csv"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -17,12 +17,24 @@ module Localized
|
|||||||
end
|
end
|
||||||
|
|
||||||
def default_locale
|
def default_locale
|
||||||
ENV.fetch('DEFAULT_LOCALE') do
|
request_locale || env_locale || I18n.default_locale
|
||||||
user_supplied_locale || I18n.default_locale
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_supplied_locale
|
def env_locale
|
||||||
http_accept_language.language_region_compatible_from(I18n.available_locales)
|
ENV['DEFAULT_LOCALE']
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_locale
|
||||||
|
preferred_locale || compatible_locale
|
||||||
|
end
|
||||||
|
|
||||||
|
def preferred_locale
|
||||||
|
http_accept_language.preferred_language_from([env_locale]) ||
|
||||||
|
http_accept_language.preferred_language_from(I18n.available_locales)
|
||||||
|
end
|
||||||
|
|
||||||
|
def compatible_locale
|
||||||
|
http_accept_language.compatible_language_from([env_locale]) ||
|
||||||
|
http_accept_language.compatible_language_from(I18n.available_locales)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,19 +4,13 @@ module ObfuscateFilename
|
|||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def obfuscate_filename(*args)
|
|
||||||
before_action { obfuscate_filename(*args) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def obfuscate_filename(path)
|
def obfuscate_filename(path)
|
||||||
|
before_action do
|
||||||
file = params.dig(*path)
|
file = params.dig(*path)
|
||||||
return if file.nil?
|
next if file.nil?
|
||||||
|
|
||||||
file.original_filename = secure_token + File.extname(file.original_filename)
|
file.original_filename = SecureRandom.hex(8) + File.extname(file.original_filename)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def secure_token(length = 16)
|
|
||||||
SecureRandom.hex(length / 2)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
57
app/controllers/concerns/rate_limit_headers.rb
Normal file
57
app/controllers/concerns/rate_limit_headers.rb
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RateLimitHeaders
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
before_action :set_rate_limit_headers, if: :rate_limited_request?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_rate_limit_headers
|
||||||
|
apply_header_limit
|
||||||
|
apply_header_remaining
|
||||||
|
apply_header_reset
|
||||||
|
end
|
||||||
|
|
||||||
|
def rate_limited_request?
|
||||||
|
!request.env['rack.attack.throttle_data'].nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def apply_header_limit
|
||||||
|
response.headers['X-RateLimit-Limit'] = rate_limit_limit
|
||||||
|
end
|
||||||
|
|
||||||
|
def rate_limit_limit
|
||||||
|
api_throttle_data[:limit].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def apply_header_remaining
|
||||||
|
response.headers['X-RateLimit-Remaining'] = rate_limit_remaining
|
||||||
|
end
|
||||||
|
|
||||||
|
def rate_limit_remaining
|
||||||
|
(api_throttle_data[:limit] - api_throttle_data[:count]).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def apply_header_reset
|
||||||
|
response.headers['X-RateLimit-Reset'] = rate_limit_reset
|
||||||
|
end
|
||||||
|
|
||||||
|
def rate_limit_reset
|
||||||
|
(request_time + reset_period_offset).iso8601(6)
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_throttle_data
|
||||||
|
request.env['rack.attack.throttle_data']['api']
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_time
|
||||||
|
@_request_time ||= Time.now.utc
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_period_offset
|
||||||
|
api_throttle_data[:period] - request_time.to_i % api_throttle_data[:period]
|
||||||
|
end
|
||||||
|
end
|
||||||
87
app/controllers/concerns/signature_verification.rb
Normal file
87
app/controllers/concerns/signature_verification.rb
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Implemented according to HTTP signatures (Draft 6)
|
||||||
|
# <https://tools.ietf.org/html/draft-cavage-http-signatures-06>
|
||||||
|
module SignatureVerification
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def signed_request?
|
||||||
|
request.headers['Signature'].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def signed_request_account
|
||||||
|
return @signed_request_account if defined?(@signed_request_account)
|
||||||
|
|
||||||
|
unless signed_request?
|
||||||
|
@signed_request_account = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
raw_signature = request.headers['Signature']
|
||||||
|
signature_params = {}
|
||||||
|
|
||||||
|
raw_signature.split(',').each do |part|
|
||||||
|
parsed_parts = part.match(/([a-z]+)="([^"]+)"/i)
|
||||||
|
next if parsed_parts.nil? || parsed_parts.size != 3
|
||||||
|
signature_params[parsed_parts[1]] = parsed_parts[2]
|
||||||
|
end
|
||||||
|
|
||||||
|
if incompatible_signature?(signature_params)
|
||||||
|
@signed_request_account = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
account = ResolveRemoteAccountService.new.call(signature_params['keyId'].gsub(/\Aacct:/, ''))
|
||||||
|
|
||||||
|
if account.nil?
|
||||||
|
@signed_request_account = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
signature = Base64.decode64(signature_params['signature'])
|
||||||
|
compare_signed_string = build_signed_string(signature_params['headers'])
|
||||||
|
|
||||||
|
if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string)
|
||||||
|
@signed_request_account = account
|
||||||
|
@signed_request_account
|
||||||
|
else
|
||||||
|
@signed_request_account = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_signed_string(signed_headers)
|
||||||
|
signed_headers = 'date' if signed_headers.blank?
|
||||||
|
|
||||||
|
signed_headers.split(' ').map do |signed_header|
|
||||||
|
if signed_header == Request::REQUEST_TARGET
|
||||||
|
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
|
||||||
|
else
|
||||||
|
"#{signed_header}: #{request.headers[to_header_name(signed_header)]}"
|
||||||
|
end
|
||||||
|
end.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches_time_window?
|
||||||
|
begin
|
||||||
|
time_sent = DateTime.httpdate(request.headers['Date'])
|
||||||
|
rescue ArgumentError
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
(Time.now.utc - time_sent).abs <= 30
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_header_name(name)
|
||||||
|
name.split(/-/).map(&:capitalize).join('-')
|
||||||
|
end
|
||||||
|
|
||||||
|
def incompatible_signature?(signature_params)
|
||||||
|
signature_params['keyId'].blank? ||
|
||||||
|
signature_params['signature'].blank? ||
|
||||||
|
signature_params['algorithm'].blank? ||
|
||||||
|
signature_params['algorithm'] != 'rsa-sha256' ||
|
||||||
|
!signature_params['keyId'].start_with?('acct:')
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -17,7 +17,7 @@ module UserTrackingConcern
|
|||||||
current_user.update_tracked_fields!(request)
|
current_user.update_tracked_fields!(request)
|
||||||
|
|
||||||
# Regenerate feed if needed
|
# Regenerate feed if needed
|
||||||
RegenerationWorker.perform_async(current_user.account_id) if user_needs_feed_update?
|
regenerate_feed! if user_needs_feed_update?
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_needs_sign_in_update?
|
def user_needs_sign_in_update?
|
||||||
@@ -27,4 +27,9 @@ module UserTrackingConcern
|
|||||||
def user_needs_feed_update?
|
def user_needs_feed_update?
|
||||||
current_user.last_sign_in_at < REGENERATE_FEED_DAYS.days.ago
|
current_user.last_sign_in_at < REGENERATE_FEED_DAYS.days.ago
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def regenerate_feed!
|
||||||
|
Redis.current.setnx("account:#{current_user.account_id}:regeneration", true) == 1 && Redis.current.expire("account:#{current_user.account_id}:regeneration", 3_600 * 24)
|
||||||
|
RegenerationWorker.perform_async(current_user.account_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,5 +5,24 @@ class FollowerAccountsController < ApplicationController
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
@follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
|
@follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
|
||||||
|
format.json do
|
||||||
|
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def collection_presenter
|
||||||
|
ActivityPub::CollectionPresenter.new(
|
||||||
|
id: account_followers_url(@account),
|
||||||
|
type: :ordered,
|
||||||
|
size: @account.followers_count,
|
||||||
|
items: @follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) }
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,5 +5,24 @@ class FollowingAccountsController < ApplicationController
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
@follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
|
@follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
|
||||||
|
format.json do
|
||||||
|
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def collection_presenter
|
||||||
|
ActivityPub::CollectionPresenter.new(
|
||||||
|
id: account_following_index_url(@account),
|
||||||
|
type: :ordered,
|
||||||
|
size: @account.following_count,
|
||||||
|
items: @follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) }
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
class HomeController < ApplicationController
|
class HomeController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
before_action :set_initial_state_json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@body_classes = 'app-body'
|
@body_classes = 'app-body'
|
||||||
@token = find_or_create_access_token.token
|
|
||||||
@web_settings = Web::Setting.find_by(user: current_user)&.data || {}
|
|
||||||
@admin = Account.find_local(Setting.site_contact_username)
|
|
||||||
@streaming_api_base_url = Rails.configuration.x.streaming_api_base_url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -17,13 +14,18 @@ class HomeController < ApplicationController
|
|||||||
redirect_to(single_user_mode? ? account_path(Account.first) : about_path) unless user_signed_in?
|
redirect_to(single_user_mode? ? account_path(Account.first) : about_path) unless user_signed_in?
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_or_create_access_token
|
def set_initial_state_json
|
||||||
Doorkeeper::AccessToken.find_or_create_for(
|
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
||||||
Doorkeeper::Application.where(superapp: true).first,
|
@initial_state_json = serializable_resource.to_json
|
||||||
current_user.id,
|
end
|
||||||
Doorkeeper::OAuth::Scopes.from_string('read write follow'),
|
|
||||||
Doorkeeper.configuration.access_token_expires_in,
|
def initial_state_params
|
||||||
Doorkeeper.configuration.refresh_token_enabled?
|
{
|
||||||
)
|
settings: Web::Setting.find_by(user: current_user)&.data || {},
|
||||||
|
push_subscription: current_account.user.web_push_subscription(current_session),
|
||||||
|
current_account: current_account,
|
||||||
|
token: current_session.token,
|
||||||
|
admin: Account.find_local(Setting.site_contact_username),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
11
app/controllers/manifests_controller.rb
Normal file
11
app/controllers/manifests_controller.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ManifestsController < ApplicationController
|
||||||
|
before_action :set_instance_presenter
|
||||||
|
|
||||||
|
def show; end
|
||||||
|
|
||||||
|
def set_instance_presenter
|
||||||
|
@instance_presenter = InstancePresenter.new
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MediaController < ApplicationController
|
class MediaController < ApplicationController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action :verify_permitted_status
|
before_action :verify_permitted_status
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@@ -14,6 +16,9 @@ class MediaController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def verify_permitted_status
|
def verify_permitted_status
|
||||||
raise ActiveRecord::RecordNotFound unless media_attachment.status.permitted?(current_account)
|
authorize media_attachment.status, :show?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404 instead of a 403 error code
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
32
app/controllers/settings/deletes_controller.rb
Normal file
32
app/controllers/settings/deletes_controller.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Settings::DeletesController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :check_enabled_deletion
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
def show
|
||||||
|
@confirmation = Form::DeleteConfirmation.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if current_user.valid_password?(delete_params[:password])
|
||||||
|
Admin::SuspensionWorker.perform_async(current_user.account_id, true)
|
||||||
|
sign_out
|
||||||
|
redirect_to new_user_session_path, notice: I18n.t('deletes.success_msg')
|
||||||
|
else
|
||||||
|
redirect_to settings_delete_path, alert: I18n.t('deletes.bad_password_msg')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_enabled_deletion
|
||||||
|
redirect_to root_path unless Setting.open_deletion
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_params
|
||||||
|
params.require(:form_delete_confirmation).permit(:password)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Settings
|
|
||||||
module Exports
|
|
||||||
class BaseController < ApplicationController
|
|
||||||
before_action :authenticate_user!
|
|
||||||
|
|
||||||
def index
|
|
||||||
@export = Export.new(current_account)
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.csv { send_data export_data, filename: export_filename }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def export_filename
|
|
||||||
"#{controller_name}.csv"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BlockedAccountsController < BaseController
|
class BlockedAccountsController < ApplicationController
|
||||||
|
include ExportControllerConcern
|
||||||
|
|
||||||
|
def index
|
||||||
|
send_export_file
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def export_data
|
def export_data
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class FollowingAccountsController < BaseController
|
class FollowingAccountsController < ApplicationController
|
||||||
|
include ExportControllerConcern
|
||||||
|
|
||||||
|
def index
|
||||||
|
send_export_file
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def export_data
|
def export_data
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class MutedAccountsController < BaseController
|
class MutedAccountsController < ApplicationController
|
||||||
|
include ExportControllerConcern
|
||||||
|
|
||||||
|
def index
|
||||||
|
send_export_file
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def export_data
|
def export_data
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'sidekiq-bulk'
|
||||||
|
|
||||||
class Settings::FollowerDomainsController < ApplicationController
|
class Settings::FollowerDomainsController < ApplicationController
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
|
|
||||||
@@ -13,8 +15,8 @@ class Settings::FollowerDomainsController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
domains = bulk_params[:select] || []
|
domains = bulk_params[:select] || []
|
||||||
|
|
||||||
domains.each do |domain|
|
SoftBlockDomainFollowersWorker.push_bulk(domains) do |domain|
|
||||||
SoftBlockDomainFollowersWorker.perform_async(current_account.id, domain)
|
[current_account.id, domain]
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to settings_follower_domains_path, notice: I18n.t('followers.success', count: domains.size)
|
redirect_to settings_follower_domains_path, notice: I18n.t('followers.success', count: domains.size)
|
||||||
|
|||||||
@@ -34,8 +34,13 @@ class Settings::PreferencesController < ApplicationController
|
|||||||
def user_settings_params
|
def user_settings_params
|
||||||
params.require(:user).permit(
|
params.require(:user).permit(
|
||||||
:setting_default_privacy,
|
:setting_default_privacy,
|
||||||
|
:setting_default_sensitive,
|
||||||
|
:setting_unfollow_modal,
|
||||||
:setting_boost_modal,
|
:setting_boost_modal,
|
||||||
|
:setting_delete_modal,
|
||||||
:setting_auto_play_gif,
|
:setting_auto_play_gif,
|
||||||
|
:setting_system_font_ui,
|
||||||
|
:setting_noindex,
|
||||||
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
||||||
interactions: %i(must_be_follower must_be_following)
|
interactions: %i(must_be_follower must_be_following)
|
||||||
)
|
)
|
||||||
|
|||||||
17
app/controllers/settings/sessions_controller.rb
Normal file
17
app/controllers/settings/sessions_controller.rb
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Settings::SessionsController < ApplicationController
|
||||||
|
before_action :set_session, only: :destroy
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@session.destroy!
|
||||||
|
flash[:notice] = I18n.t('sessions.revoke_success')
|
||||||
|
redirect_to edit_user_registration_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_session
|
||||||
|
@session = current_user.session_activations.find(params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -7,7 +7,9 @@ module Settings
|
|||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :verify_otp_required, only: [:create]
|
before_action :verify_otp_required, only: [:create]
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
@confirmation = Form::TwoFactorConfirmation.new
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
current_user.otp_secret = User.generate_otp_secret(32)
|
current_user.otp_secret = User.generate_otp_secret(32)
|
||||||
@@ -16,13 +18,23 @@ module Settings
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
if current_user.validate_and_consume_otp!(confirmation_params[:code])
|
||||||
current_user.otp_required_for_login = false
|
current_user.otp_required_for_login = false
|
||||||
current_user.save!
|
current_user.save!
|
||||||
redirect_to settings_two_factor_authentication_path
|
redirect_to settings_two_factor_authentication_path
|
||||||
|
else
|
||||||
|
flash.now[:alert] = I18n.t('two_factor_authentication.wrong_code')
|
||||||
|
@confirmation = Form::TwoFactorConfirmation.new
|
||||||
|
render :show
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def confirmation_params
|
||||||
|
params.require(:form_two_factor_confirmation).permit(:code)
|
||||||
|
end
|
||||||
|
|
||||||
def verify_otp_required
|
def verify_otp_required
|
||||||
redirect_to settings_two_factor_authentication_path if current_user.otp_required_for_login?
|
redirect_to settings_two_factor_authentication_path if current_user.otp_required_for_login?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StatusesController < ApplicationController
|
class StatusesController < ApplicationController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
layout 'public'
|
layout 'public'
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
@@ -9,12 +11,24 @@ class StatusesController < ApplicationController
|
|||||||
before_action :check_account_suspension
|
before_action :check_account_suspension
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
|
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
|
||||||
@descendants = cache_collection(@status.descendants(current_account), Status)
|
@descendants = cache_collection(@status.descendants(current_account), Status)
|
||||||
|
|
||||||
render 'stream_entries/show'
|
render 'stream_entries/show'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
format.json do
|
||||||
|
render json: @status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity
|
||||||
|
render json: @status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_account
|
def set_account
|
||||||
@@ -30,7 +44,10 @@ class StatusesController < ApplicationController
|
|||||||
@stream_entry = @status.stream_entry
|
@stream_entry = @status.stream_entry
|
||||||
@type = @stream_entry.activity_type.downcase
|
@type = @stream_entry.activity_type.downcase
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
|
authorize @status, :show?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StreamEntriesController < ApplicationController
|
class StreamEntriesController < ApplicationController
|
||||||
|
include Authorization
|
||||||
|
include SignatureVerification
|
||||||
|
|
||||||
layout 'public'
|
layout 'public'
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
@@ -16,7 +19,7 @@ class StreamEntriesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
render xml: AtomSerializer.render(AtomSerializer.new.entry(@stream_entry, true))
|
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.entry(@stream_entry, true))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -42,7 +45,11 @@ class StreamEntriesController < ApplicationController
|
|||||||
@stream_entry = @account.stream_entries.where(activity_type: 'Status').find(params[:id])
|
@stream_entry = @account.stream_entries.where(activity_type: 'Status').find(params[:id])
|
||||||
@type = @stream_entry.activity_type.downcase
|
@type = @stream_entry.activity_type.downcase
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil? || (@stream_entry.hidden? && !@stream_entry.activity.permitted?(current_account))
|
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
|
||||||
|
authorize @stream_entry.activity, :show? if @stream_entry.hidden?
|
||||||
|
rescue Mastodon::NotPermittedError
|
||||||
|
# Reraise in order to get a 404
|
||||||
|
raise ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
|
|||||||
@@ -5,7 +5,26 @@ class TagsController < ApplicationController
|
|||||||
|
|
||||||
def show
|
def show
|
||||||
@tag = Tag.find_by!(name: params[:id].downcase)
|
@tag = Tag.find_by!(name: params[:id].downcase)
|
||||||
@statuses = @tag.nil? ? [] : Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id])
|
@statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id])
|
||||||
@statuses = cache_collection(@statuses, Status)
|
@statuses = cache_collection(@statuses, Status)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
|
||||||
|
format.json do
|
||||||
|
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def collection_presenter
|
||||||
|
ActivityPub::CollectionPresenter.new(
|
||||||
|
id: tag_url(@tag),
|
||||||
|
type: :ordered,
|
||||||
|
size: @tag.statuses.count,
|
||||||
|
items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class HostMetaController < ApplicationController
|
class HostMetaController < ApplicationController
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class WebfingerController < ApplicationController
|
class WebfingerController < ApplicationController
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@account = Account.find_local!(username_from_resource)
|
@account = Account.find_local!(username_from_resource)
|
||||||
@canonical_account_uri = @account.to_webfinger_s
|
@canonical_account_uri = @account.to_webfinger_s
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Activitystreams2BuilderHelper
|
|
||||||
# Gets a usable name for an account, using display name or username.
|
|
||||||
def account_name(account)
|
|
||||||
account.display_name.presence || account.username
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -6,15 +6,21 @@ module Admin::FilterHelper
|
|||||||
|
|
||||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS
|
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS
|
||||||
|
|
||||||
def filter_link_to(text, more_params)
|
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
|
||||||
new_url = filtered_url_for(more_params)
|
new_url = filtered_url_for(link_to_params)
|
||||||
link_to text, new_url, class: filter_link_class(new_url)
|
new_class = filtered_url_for(link_class_params)
|
||||||
|
link_to text, new_url, class: filter_link_class(new_class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def table_link_to(icon, text, path, options = {})
|
def table_link_to(icon, text, path, options = {})
|
||||||
link_to safe_join([fa_icon(icon), text]), path, options.merge(class: 'table-action-link')
|
link_to safe_join([fa_icon(icon), text]), path, options.merge(class: 'table-action-link')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def selected?(more_params)
|
||||||
|
new_url = filtered_url_for(more_params)
|
||||||
|
filter_link_class(new_url) == 'selected' ? true : false
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def filter_params(more_params)
|
def filter_params(more_params)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user