mirror of
https://github.com/cachethq/cachet.git
synced 2026-03-05 03:27:01 +00:00
Compare commits
643 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2311d67624 | ||
|
|
715d65f464 | ||
|
|
1ac4b7a64a | ||
|
|
941809037a | ||
|
|
0b8ce37e84 | ||
|
|
0851427f2d | ||
|
|
860457bfae | ||
|
|
9112e2a58f | ||
|
|
b1600bdbee | ||
|
|
2ef8b8411f | ||
|
|
a55bcb8c48 | ||
|
|
5c8369344d | ||
|
|
8589089a04 | ||
|
|
324f8703ce | ||
|
|
9df14837b9 | ||
|
|
e3a3f97957 | ||
|
|
fbfa62d087 | ||
|
|
1c7fb1a434 | ||
|
|
02f069cdc1 | ||
|
|
1779ac40c9 | ||
|
|
e8d3c013a1 | ||
|
|
85efb7d114 | ||
|
|
11d77328dc | ||
|
|
c05e9d9867 | ||
|
|
f9f2e5c18a | ||
|
|
2ac9d3b23e | ||
|
|
848fb3b607 | ||
|
|
7d21a7682c | ||
|
|
e3c38c7461 | ||
|
|
8dd762184e | ||
|
|
578d4befef | ||
|
|
549c4e1594 | ||
|
|
60536d5334 | ||
|
|
ef3c32c5e9 | ||
|
|
11cf7ef2c8 | ||
|
|
ca367ff151 | ||
|
|
06ecb4b9fb | ||
|
|
122138402b | ||
|
|
14ec134ac1 | ||
|
|
ea0a8dfcff | ||
|
|
6cd10581e4 | ||
|
|
90baf18724 | ||
|
|
5bdbc87bf2 | ||
|
|
60c7235d94 | ||
|
|
2c8cd19137 | ||
|
|
c1d53a7b42 | ||
|
|
22b0e105ee | ||
|
|
c7b55401d4 | ||
|
|
167b90265f | ||
|
|
bb71d0175f | ||
|
|
f964c03072 | ||
|
|
46c43a8b82 | ||
|
|
ee7a0ec5f2 | ||
|
|
427c8d24a5 | ||
|
|
60e6d99b95 | ||
|
|
18db70b9cd | ||
|
|
3a73a9be5c | ||
|
|
fb933720fc | ||
|
|
a4ce37f29a | ||
|
|
4f3664b3e0 | ||
|
|
c46c255722 | ||
|
|
971a422258 | ||
|
|
b6de8bf258 | ||
|
|
573a301957 | ||
|
|
d8323f126c | ||
|
|
e6db90a798 | ||
|
|
9d9bec812d | ||
|
|
c9b3760a4d | ||
|
|
fb127fb861 | ||
|
|
2425682381 | ||
|
|
da1c999ca6 | ||
|
|
79aa78cff5 | ||
|
|
4438142348 | ||
|
|
e917e338cd | ||
|
|
da22fa208a | ||
|
|
2cb1d9e07d | ||
|
|
68c458227f | ||
|
|
043690764d | ||
|
|
845d9e1e14 | ||
|
|
68572db6d2 | ||
|
|
5d7b05d857 | ||
|
|
9eb65eba3b | ||
|
|
17492b0dcf | ||
|
|
0f8773a547 | ||
|
|
45f376e564 | ||
|
|
3a44e4a809 | ||
|
|
fea555f2b0 | ||
|
|
9094f37156 | ||
|
|
0e502ed53b | ||
|
|
7f0c2a772d | ||
|
|
e06688aee5 | ||
|
|
bfe2b6ca48 | ||
|
|
7e663d7a76 | ||
|
|
65fe410a93 | ||
|
|
c747f11f3c | ||
|
|
9065b7dccc | ||
|
|
7727dbf33b | ||
|
|
2868f9e052 | ||
|
|
aab2b1fe6e | ||
|
|
1e4a8c8143 | ||
|
|
e002d596b1 | ||
|
|
1e3e1df616 | ||
|
|
6e3d1af85a | ||
|
|
e91cf591ea | ||
|
|
14bbe69509 | ||
|
|
c328575417 | ||
|
|
ecb3a4e1d9 | ||
|
|
71f5de8726 | ||
|
|
38257c6ae6 | ||
|
|
6802609ce6 | ||
|
|
476adef1b0 | ||
|
|
3a83110f50 | ||
|
|
8c4832343d | ||
|
|
a0d354c3e9 | ||
|
|
02cb04d36f | ||
|
|
07861dd245 | ||
|
|
14ac707d76 | ||
|
|
0fba574f5b | ||
|
|
71c30fb0bd | ||
|
|
bf77fbdd33 | ||
|
|
6336bd8905 | ||
|
|
dbbf4a093e | ||
|
|
5190578da9 | ||
|
|
c5f3655d49 | ||
|
|
721df30642 | ||
|
|
b79c8902fc | ||
|
|
bcc72d224f | ||
|
|
679005fe3f | ||
|
|
4990868d9a | ||
|
|
a7a4fe03e4 | ||
|
|
c2678ea89c | ||
|
|
f1bbf0200c | ||
|
|
1a5155dbc5 | ||
|
|
7e14d6d25f | ||
|
|
b003a7aa1c | ||
|
|
2c5549120b | ||
|
|
6a29b306e2 | ||
|
|
f01849f758 | ||
|
|
f592aa08c9 | ||
|
|
691e6fffe7 | ||
|
|
dbda00cef8 | ||
|
|
408141dd8b | ||
|
|
9b43b42e27 | ||
|
|
83955fcff5 | ||
|
|
bf05197c4f | ||
|
|
a72543daa2 | ||
|
|
cbf888d7b7 | ||
|
|
0a321bffd8 | ||
|
|
f74f44048d | ||
|
|
78567f865a | ||
|
|
de9240d295 | ||
|
|
a3235f78d0 | ||
|
|
3da8f3065c | ||
|
|
39091b51b5 | ||
|
|
e250d5e3fe | ||
|
|
8ed0f17761 | ||
|
|
92caf08d1d | ||
|
|
1e6db61066 | ||
|
|
13e5ee548d | ||
|
|
3d328663d5 | ||
|
|
fafcc8880b | ||
|
|
7a283dceb7 | ||
|
|
c1a0fc10ae | ||
|
|
13180cf77d | ||
|
|
903da245ef | ||
|
|
939766bf7d | ||
|
|
977cac091c | ||
|
|
04161678b6 | ||
|
|
793564e0c0 | ||
|
|
ea89254bf6 | ||
|
|
54011d7635 | ||
|
|
62a71554c6 | ||
|
|
e92dd0151a | ||
|
|
0a2f7659aa | ||
|
|
c0f19093e4 | ||
|
|
e858a288a6 | ||
|
|
d20f2cbbc8 | ||
|
|
902d7bd01b | ||
|
|
19d780325e | ||
|
|
b6a6acec4d | ||
|
|
e28a08f6bb | ||
|
|
0d8a3b4efc | ||
|
|
7db305edcc | ||
|
|
74ceb9885b | ||
|
|
d6617b6971 | ||
|
|
c28ba2dfb8 | ||
|
|
e794aedb3a | ||
|
|
2fa2ff9070 | ||
|
|
0f187b323b | ||
|
|
00a480b98b | ||
|
|
69f213a4dc | ||
|
|
cef5c9b1e2 | ||
|
|
0ca1668518 | ||
|
|
814a6cf30b | ||
|
|
b0d1eaafc2 | ||
|
|
e68467a308 | ||
|
|
0c940adc56 | ||
|
|
96dfd5d057 | ||
|
|
91dfa822bc | ||
|
|
3c5a5b49f1 | ||
|
|
c12d901147 | ||
|
|
60dac4664b | ||
|
|
b7dc6ab503 | ||
|
|
d207a2eeeb | ||
|
|
986fb4c588 | ||
|
|
5b1c7a69dd | ||
|
|
f7b53c06f6 | ||
|
|
f9d831bf8a | ||
|
|
dc85aa79c8 | ||
|
|
261b38b308 | ||
|
|
05a103c47d | ||
|
|
f51fc34f6d | ||
|
|
1b8e474223 | ||
|
|
83c671c977 | ||
|
|
e13a47aecb | ||
|
|
2579b8a48e | ||
|
|
9f528584f0 | ||
|
|
a27fe6f8ad | ||
|
|
7578b640bd | ||
|
|
e1681a7021 | ||
|
|
a99aa6be1f | ||
|
|
60f6bec8bc | ||
|
|
26857597f0 | ||
|
|
60409c14fe | ||
|
|
da2eab97aa | ||
|
|
8ab422143d | ||
|
|
14494cc74b | ||
|
|
77834fb493 | ||
|
|
62ac2780cf | ||
|
|
2b43b83455 | ||
|
|
ddf64cc653 | ||
|
|
c52f0ada07 | ||
|
|
a7effcce7a | ||
|
|
1df2d71285 | ||
|
|
9a1e6d4549 | ||
|
|
fad3ed9a51 | ||
|
|
8c4653c18c | ||
|
|
0acc419bab | ||
|
|
70003c6b9c | ||
|
|
5a9e18a592 | ||
|
|
19f21f9096 | ||
|
|
2f2c4c2557 | ||
|
|
027b0b6363 | ||
|
|
5d7964ea53 | ||
|
|
f52f5a1c80 | ||
|
|
44109dd9fb | ||
|
|
b91e128c72 | ||
|
|
f13e0cce2c | ||
|
|
bbb7616f93 | ||
|
|
4284fdbb27 | ||
|
|
c4628d4f5a | ||
|
|
a4cd730665 | ||
|
|
7cd7e595f2 | ||
|
|
ea56ca4cec | ||
|
|
915f84fc07 | ||
|
|
fd2401a302 | ||
|
|
259ec3d3bb | ||
|
|
abd801b69e | ||
|
|
44481c4648 | ||
|
|
99b453bbd9 | ||
|
|
9d879b162e | ||
|
|
49411d8568 | ||
|
|
9c35554a5d | ||
|
|
26ff4dc85a | ||
|
|
2eb4bd1e69 | ||
|
|
5a8f0b3145 | ||
|
|
90b2fe51f8 | ||
|
|
28110f5c8e | ||
|
|
8573b78210 | ||
|
|
4f25318271 | ||
|
|
2669d4330e | ||
|
|
f867d22b96 | ||
|
|
3bc499a093 | ||
|
|
538e22deff | ||
|
|
b591cf188c | ||
|
|
e71c573043 | ||
|
|
3f53d76d07 | ||
|
|
16cb1bd545 | ||
|
|
939ec3be23 | ||
|
|
8ab3209afb | ||
|
|
fa3b80e3af | ||
|
|
d5c4561fd1 | ||
|
|
56802476a6 | ||
|
|
5c6bcae02d | ||
|
|
0076c2d561 | ||
|
|
ca1b5f0658 | ||
|
|
1650093861 | ||
|
|
0862c707d9 | ||
|
|
6d851bf9f3 | ||
|
|
c0980dc7a1 | ||
|
|
c471105fdd | ||
|
|
112a104a6b | ||
|
|
5fe3520137 | ||
|
|
a36ec06b2d | ||
|
|
3c5c8b0096 | ||
|
|
c1fadbf0d7 | ||
|
|
37b89700a6 | ||
|
|
43e75ceca1 | ||
|
|
4f78d7c513 | ||
|
|
397679bc57 | ||
|
|
7bd3a57883 | ||
|
|
2d9dcd9747 | ||
|
|
5ceb700b4c | ||
|
|
0cc0cdc9e3 | ||
|
|
f9744b04bb | ||
|
|
615f9e0d75 | ||
|
|
0aacc038c2 | ||
|
|
8f7b538fac | ||
|
|
bf53768530 | ||
|
|
33a282ca4e | ||
|
|
2e3fa35aca | ||
|
|
b8efd4829e | ||
|
|
78b7e4b8f0 | ||
|
|
50096f6a6f | ||
|
|
c56be4c6e0 | ||
|
|
22332e7969 | ||
|
|
0833f41189 | ||
|
|
3cde840e2b | ||
|
|
7888f5953b | ||
|
|
884c43f160 | ||
|
|
866d73e8f8 | ||
|
|
832db53ef2 | ||
|
|
f1080680bf | ||
|
|
df2ae7726d | ||
|
|
e308ba3aea | ||
|
|
9257135641 | ||
|
|
732ec5c827 | ||
|
|
eb191a52d7 | ||
|
|
9a200684c1 | ||
|
|
036928e53e | ||
|
|
9877023bb4 | ||
|
|
de9745c7cf | ||
|
|
8cdfd90df5 | ||
|
|
afa8c98fbd | ||
|
|
472e2316ae | ||
|
|
92173b65bc | ||
|
|
ff2c255d9e | ||
|
|
9315de8a4c | ||
|
|
7b61ad0445 | ||
|
|
980d34abbc | ||
|
|
620e7fed56 | ||
|
|
d9e515c62d | ||
|
|
48c40952f2 | ||
|
|
55dcf3a277 | ||
|
|
254c578ca2 | ||
|
|
106c1a034a | ||
|
|
d788691006 | ||
|
|
fc31ce13bc | ||
|
|
6b98832f3b | ||
|
|
cac63fe1fc | ||
|
|
5a705f9b62 | ||
|
|
987f045c55 | ||
|
|
d85d035ab1 | ||
|
|
32e97a7fde | ||
|
|
13468239a3 | ||
|
|
ba79d2c8a3 | ||
|
|
e70e228e38 | ||
|
|
3a781c5e66 | ||
|
|
8ec29e9921 | ||
|
|
1e27882b90 | ||
|
|
fad393be1d | ||
|
|
dd8fc60209 | ||
|
|
c06019a554 | ||
|
|
f15f492bf3 | ||
|
|
743ed28fd8 | ||
|
|
90110944ff | ||
|
|
f94a5ec57b | ||
|
|
4245b95406 | ||
|
|
9de5847004 | ||
|
|
6637e49c6c | ||
|
|
b6b5146f16 | ||
|
|
149f043be3 | ||
|
|
f06e9cc88f | ||
|
|
4d8b340397 | ||
|
|
ee66f4c451 | ||
|
|
f550a7369e | ||
|
|
2baf17b9d5 | ||
|
|
fff91417c7 | ||
|
|
2af917ace4 | ||
|
|
049b9ac308 | ||
|
|
0c065ae690 | ||
|
|
d3d744780d | ||
|
|
a1fb287a1b | ||
|
|
4347a5cc0c | ||
|
|
f970ae7100 | ||
|
|
224618b0a4 | ||
|
|
d9414fc25c | ||
|
|
e81b29053a | ||
|
|
672f475a0d | ||
|
|
142473c693 | ||
|
|
cb83f5c0c6 | ||
|
|
3197b5d18d | ||
|
|
4c28335ffe | ||
|
|
e7852e06f8 | ||
|
|
62c2c1c7ea | ||
|
|
b85752b101 | ||
|
|
9355854289 | ||
|
|
99e6f5a234 | ||
|
|
49305a2553 | ||
|
|
97c99d0afc | ||
|
|
3f9ebb8abf | ||
|
|
5540a50fae | ||
|
|
e93fda4d53 | ||
|
|
65b1038b84 | ||
|
|
77e4532319 | ||
|
|
4c67e04786 | ||
|
|
128fdbed19 | ||
|
|
7b3f6fee26 | ||
|
|
c2b69ff547 | ||
|
|
12e940e59c | ||
|
|
eb9d22975d | ||
|
|
c460cd9efe | ||
|
|
a314d8b838 | ||
|
|
8299afaa8a | ||
|
|
40a65fe7e2 | ||
|
|
d8811c974b | ||
|
|
ea94f6dd9e | ||
|
|
fb8990dff2 | ||
|
|
32029c0bf1 | ||
|
|
6b70ca7eac | ||
|
|
7aba6e31ea | ||
|
|
c0db4d883a | ||
|
|
bc01c0bb63 | ||
|
|
d29b872fee | ||
|
|
502ae9d2a0 | ||
|
|
e6f6946497 | ||
|
|
430f580b47 | ||
|
|
f7d9f8237c | ||
|
|
1efe164d7b | ||
|
|
6c6caa7f6c | ||
|
|
c85eba8f04 | ||
|
|
e399fe4637 | ||
|
|
a844a711e1 | ||
|
|
80580eadeb | ||
|
|
2b3b6fb8d8 | ||
|
|
9bc598d234 | ||
|
|
bc11ae6ed6 | ||
|
|
ebc842f19e | ||
|
|
084f685387 | ||
|
|
f235780dda | ||
|
|
09c33a698d | ||
|
|
fbf55eeb48 | ||
|
|
946b442ae0 | ||
|
|
51a4799a29 | ||
|
|
6dbd15d272 | ||
|
|
5a9cb34332 | ||
|
|
5709995b13 | ||
|
|
aa5e24e96d | ||
|
|
26fbbf9f35 | ||
|
|
634c318f3f | ||
|
|
45abeea90f | ||
|
|
3988753b99 | ||
|
|
b06167f5e9 | ||
|
|
a1470a01cf | ||
|
|
c554b40c7d | ||
|
|
0e40fe4d3f | ||
|
|
1402242766 | ||
|
|
bf5941f66e | ||
|
|
6044f7d87c | ||
|
|
82cdd171c5 | ||
|
|
768f4979be | ||
|
|
dc1f1c4737 | ||
|
|
0b8ec411ae | ||
|
|
91e4dafca9 | ||
|
|
65aaa6402a | ||
|
|
1af50d991e | ||
|
|
01b6bb1c2b | ||
|
|
83be116075 | ||
|
|
92604f2ecd | ||
|
|
d01ef397b3 | ||
|
|
0fb43b2ada | ||
|
|
e577451833 | ||
|
|
6803f8e4a8 | ||
|
|
fd18b0ae07 | ||
|
|
b743d56901 | ||
|
|
2a94965bb6 | ||
|
|
03bcf20001 | ||
|
|
e4ef64d014 | ||
|
|
d24e83e0ae | ||
|
|
2ae5fb9f22 | ||
|
|
aeea02efa2 | ||
|
|
b15ce2c2c7 | ||
|
|
7a3a7588b1 | ||
|
|
1e6cb06387 | ||
|
|
8e2ab97dfa | ||
|
|
0be55c75c0 | ||
|
|
78b7dc92d6 | ||
|
|
d70ca8d4e5 | ||
|
|
af69c99896 | ||
|
|
707248e436 | ||
|
|
088b54a5ce | ||
|
|
10bcbc6169 | ||
|
|
33f6bf167c | ||
|
|
b6aa4b1d8b | ||
|
|
f7bf3607ce | ||
|
|
3e9d62f3f7 | ||
|
|
cc755f5184 | ||
|
|
8840bca990 | ||
|
|
bf8b722e7b | ||
|
|
79889edd29 | ||
|
|
053ed46b97 | ||
|
|
a1ab59a15a | ||
|
|
a119ed14b2 | ||
|
|
8e06f6241b | ||
|
|
9337c1a75b | ||
|
|
879a8a5c69 | ||
|
|
bc376748c8 | ||
|
|
8984aecd85 | ||
|
|
1aedce0219 | ||
|
|
d9b5c31a06 | ||
|
|
f2e869f610 | ||
|
|
c097585ca0 | ||
|
|
c04ac4a5e3 | ||
|
|
166e6f8d59 | ||
|
|
77d0c20015 | ||
|
|
babef3f7fb | ||
|
|
4d28b28bdf | ||
|
|
0b58160f6d | ||
|
|
f714176f39 | ||
|
|
0928251673 | ||
|
|
30248b00aa | ||
|
|
05dfb3038b | ||
|
|
d2048e44b3 | ||
|
|
f277d8b2bc | ||
|
|
31336478fe | ||
|
|
159e4fc0c9 | ||
|
|
c370ed47ef | ||
|
|
241947d069 | ||
|
|
afa66814fa | ||
|
|
3fa0912818 | ||
|
|
fe12b83c5a | ||
|
|
accc828836 | ||
|
|
7b00dbdf9b | ||
|
|
05968b21e0 | ||
|
|
dcf7d62ca5 | ||
|
|
6de4a2fb59 | ||
|
|
f993cfcbc3 | ||
|
|
87baa067a6 | ||
|
|
46441ca0e3 | ||
|
|
9045c52774 | ||
|
|
4a481f5736 | ||
|
|
863a2f4ed3 | ||
|
|
a475a857c2 | ||
|
|
0a92d8be31 | ||
|
|
85967a9991 | ||
|
|
9b4e626447 | ||
|
|
fe1425a6c0 | ||
|
|
0569142f84 | ||
|
|
43eaf2aa2d | ||
|
|
853cd9bfbf | ||
|
|
06b9bc2757 | ||
|
|
2c0e806ad6 | ||
|
|
a5526c7ca7 | ||
|
|
4eb1bee983 | ||
|
|
6973943e3a | ||
|
|
bb5fd311fe | ||
|
|
5280fc8df4 | ||
|
|
2712e61ea5 | ||
|
|
65debb5014 | ||
|
|
8a9456ab42 | ||
|
|
444b236f9f | ||
|
|
8f9d2614e9 | ||
|
|
b0c808f449 | ||
|
|
cb049f6458 | ||
|
|
b26bef7251 | ||
|
|
61afb54121 | ||
|
|
c4c55a73cb | ||
|
|
dda8917db0 | ||
|
|
26642eb573 | ||
|
|
cbf59b9b78 | ||
|
|
01ea120747 | ||
|
|
968abd0dc0 | ||
|
|
8b200ef35e | ||
|
|
497cc24545 | ||
|
|
1543643f4c | ||
|
|
6917870c23 | ||
|
|
04438e31ed | ||
|
|
4c4a32da3d | ||
|
|
09dd120805 | ||
|
|
60af02969f | ||
|
|
e8750e9726 | ||
|
|
70a07e6d19 | ||
|
|
d451fc4c7d | ||
|
|
51ae02992e | ||
|
|
2d7be16229 | ||
|
|
ed88aa841a | ||
|
|
8714f4643d | ||
|
|
861041ff31 | ||
|
|
c3c62a6b4e | ||
|
|
7cf61b9699 | ||
|
|
80e3d9167d | ||
|
|
dc139ef09f | ||
|
|
f9917e525c | ||
|
|
af084ceec8 | ||
|
|
ba7f9881d6 | ||
|
|
17c31f4f2f | ||
|
|
31003e1d7f | ||
|
|
fa12463ac2 | ||
|
|
9c221b7b2a | ||
|
|
35dc0f6f77 | ||
|
|
7c9fff983e | ||
|
|
191e17b1a6 | ||
|
|
d2043f41c4 | ||
|
|
f462cc99c7 | ||
|
|
4f09ce1f1b | ||
|
|
d3554ec4f4 | ||
|
|
04f957cf39 | ||
|
|
0e8899e90e | ||
|
|
f73afb87d8 | ||
|
|
92c1d69b16 | ||
|
|
cee25ba530 | ||
|
|
39bf9f789c | ||
|
|
f7aa87c503 | ||
|
|
3a9bc47f09 | ||
|
|
31f5d76bcf | ||
|
|
1117f421b1 | ||
|
|
3b4fcd793f | ||
|
|
e61cae2ddd | ||
|
|
caeaf4c1a9 | ||
|
|
6d6e8bcaf9 | ||
|
|
0f44fab68c | ||
|
|
3f0b2d1375 | ||
|
|
64f5c23546 | ||
|
|
f6c4f3df27 | ||
|
|
cdd91ce673 | ||
|
|
5251369317 | ||
|
|
64d1d73d70 | ||
|
|
082f57569f | ||
|
|
37e20bf2bf | ||
|
|
eb22ac6d8a | ||
|
|
85bab1d238 | ||
|
|
21355e3dd7 | ||
|
|
ce92de2f7e | ||
|
|
da9c32d38a | ||
|
|
41186b7271 | ||
|
|
44ac45fc6b | ||
|
|
09e83ab689 | ||
|
|
c5a93d99a7 | ||
|
|
d4fa4e59a0 | ||
|
|
c1c3eb65d9 | ||
|
|
bdbd1cbd1e | ||
|
|
1ca9b85389 | ||
|
|
b4ac66d727 |
2
.bowerrc
2
.bowerrc
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"directory": "app/assets/bower_components",
|
||||
"directory": "vendor/bower_components",
|
||||
"interactive": false
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.git
|
||||
26
.env.example
Normal file
26
.env.example
Normal file
@@ -0,0 +1,26 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://localhost
|
||||
APP_KEY=SomeRandomString
|
||||
|
||||
DB_DRIVER=mysql
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=cachet
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=database
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ADDRESS=null
|
||||
MAIL_NAME=null
|
||||
|
||||
REDIS_HOST=null
|
||||
REDIS_DATABASE=null
|
||||
REDIS_PORT=null
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'APP_DEBUG' => getenv('APP_DEBUG') ?: false,
|
||||
'DB_DRIVER' => 'mysql',
|
||||
'DB_HOST' => 'localhost',
|
||||
'DB_DATABASE' => 'cachet',
|
||||
'DB_USERNAME' => 'homestead',
|
||||
'DB_PASSWORD' => 'secret',
|
||||
'CACHE_DRIVER' => 'apc',
|
||||
];
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
$dbURL = parse_url(getenv('DATABASE_URL'));
|
||||
$dbName = substr($dbURL["path"], 1);
|
||||
|
||||
return [
|
||||
'APP_DEBUG' => getenv('APP_DEBUG') ?: false,
|
||||
'DB_HOST' => $dbURL['host'],
|
||||
'DB_DATABASE' => $dbName,
|
||||
'DB_USERNAME' => $dbURL['user'],
|
||||
'DB_PASSWORD' => $dbURL['pass'],
|
||||
'DB_DRIVER' => 'pgsql',
|
||||
'CACHE_DRIVER' => 'apc',
|
||||
];
|
||||
10
.gitattributes
vendored
10
.gitattributes
vendored
@@ -1,9 +1,3 @@
|
||||
* text=auto
|
||||
|
||||
/tests export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/phpunit.xml export-ignore
|
||||
/CONTRIBUTING.md export-ignore
|
||||
/INSTALL.md export-ignore
|
||||
/README.md export-ignore
|
||||
*.css linguist-vendored
|
||||
*.less linguist-vendored
|
||||
|
||||
24
.gitignore
vendored
24
.gitignore
vendored
@@ -1,24 +1,4 @@
|
||||
# Laravel
|
||||
bootstrap/compiled.php
|
||||
vendor
|
||||
|
||||
# Configuration
|
||||
.env.*.php
|
||||
.env.php
|
||||
config.codekit
|
||||
!.env.heroku.php
|
||||
!.env.example.php
|
||||
|
||||
# Assets
|
||||
app/assets/bower_components
|
||||
.env
|
||||
node_modules
|
||||
public/dist
|
||||
public/css
|
||||
public/js
|
||||
|
||||
# Packages
|
||||
npm-debug.log
|
||||
.vagrant
|
||||
|
||||
# PHPUnit
|
||||
phpunit.xml
|
||||
vendor
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5.9
|
||||
- 5.5
|
||||
- 5.6
|
||||
- nightly
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
|
||||
sudo: false
|
||||
|
||||
install: travis_retry composer install --no-interaction --ignore-platform-reqs --no-scripts --prefer-source
|
||||
|
||||
before_script: php artisan cachet:one-click-deploy
|
||||
|
||||
script:
|
||||
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "hhvm" ]; then vendor/bin/phpunit; fi;'
|
||||
- bash -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then vendor/bin/phpunit --coverage-clover build/logs/clover.xml; fi;'
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
|
||||
## Creating issues
|
||||
|
||||
Issues should be made by using the [issue tracker](https://github.com/cachethq/Cachet/issues).
|
||||
Feature requests and bug reports should be made by using the [issue tracker](https://github.com/cachethq/Cachet/issues). Support questions should be directed to our support email; [support@alt-three.com](mailto:support@alt-three.com?subject=Cachet Support).
|
||||
|
||||
Things to remember:
|
||||
|
||||
- Be descriptive
|
||||
- Be respectful of others
|
||||
**Always be respectful.** Organization members reserve the right to lock topics if they feel necessary.
|
||||
|
||||
## Languages
|
||||
|
||||
When needing to add labels, placeholders or general text, you **must not** write directly into the source file, rather make use of the `./app/lang/` directory. Always provide the English translation and copy your English string to all other languages - making sure that the indentation and alignment of the arrays are updated.
|
||||
When needing to add labels, placeholders or general text, you **must not** write directly into the source file, rather make use of the `./resources/lang/` directory.
|
||||
|
||||
Always provide the English translation and copy your English string to all other languages - making sure that the indentation and alignment of the arrays are updated.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
@@ -20,9 +19,9 @@ Please follow existing coding standards:
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Foo\Bar\Controller;
|
||||
namespace CachetHQ\Cachet\Controller;
|
||||
|
||||
use Foo\Bar\Bar;
|
||||
use CachetHQ\Cachet\Bar;
|
||||
|
||||
class Foo extends Bar
|
||||
{
|
||||
@@ -50,14 +49,13 @@ class Foo extends Bar
|
||||
}
|
||||
```
|
||||
- Braces on a new line following: `namespace`, `use`, `function` and `class`.
|
||||
- Line lengths have a soft 80 limit and hard 120 length.
|
||||
- PHP constants should be in lowercase; `true`, `false` and `null`.
|
||||
- Defined constants should always be in uppercase.
|
||||
- Never leave trailing spaces at the end of a line.
|
||||
- Files should end with one blank line.
|
||||
- Do not use `# Bash` style comments.
|
||||
- Always add or update Docblocs to functions.
|
||||
- If your pull request consists of more than two commits, you **must** squash them into one.
|
||||
- We use [StyleCI](https://styleci.io) to automatically check code standards in Pull Requests. If your PR fails the CI check, then apply the supplied patch and re-push.
|
||||
|
||||
If you're still unsure, then take a look at existing code.
|
||||
|
||||
@@ -75,8 +73,6 @@ If you're not particularly fond of the command line, you can get one of GitHub's
|
||||
|
||||
If you're feeling adventurous, you can become a Git & GitHub master with the [Git Path on Code School](https://www.codeschool.com/paths/git).
|
||||
|
||||
There is always the Cachet Gitter chat to ask any questions you may have:
|
||||
|
||||
[](https://gitter.im/cachethq/Cachet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
## .editorconfig
|
||||
|
||||
You should also make use of the [.editorconfig](/.editorconfig) file found within the root of the repository. It'll make sure that your editor is setup with the same file settings.
|
||||
|
||||
42
Dockerfile
42
Dockerfile
@@ -1,42 +0,0 @@
|
||||
FROM debian:jessie
|
||||
|
||||
ENV DB_DRIVER=mysql \
|
||||
ENV=production \
|
||||
DB_DATABASE=cachet \
|
||||
DB_HOST= \
|
||||
DB_USERNAME= \
|
||||
DB_PASSWORD= \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
COPY . /var/www/html/
|
||||
WORKDIR /var/www/html/
|
||||
|
||||
# Using nodesource and debian jessie packages instead of compiling from scratch
|
||||
RUN echo "APT::Install-Recommends \"0\";" >> /etc/apt/apt.conf.d/02recommends && \
|
||||
echo "APT::Install-Suggests \"0\";" >> /etc/apt/apt.conf.d/02recommends && \
|
||||
apt-get -qq update && \
|
||||
apt-get -qq install \
|
||||
ca-certificates nginx php5-fpm=5.* php5-curl php5-readline php5-mcrypt php5-mysql php5-apcu php5-cli \
|
||||
git sqlite libsqlite3-dev curl supervisor && \
|
||||
apt-get clean && apt-get autoremove -qq && \
|
||||
rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man /tmp/* && \
|
||||
chown -R www-data /var/www/html
|
||||
|
||||
# Hardcode the Illuminate key in app/config/app.php. If you want security, feel free
|
||||
# to override the key in your own container with a 'php artisan key:generate' :)
|
||||
RUN sed -i "s/'key' => '\w.*/'key' => 'f20d3e5ae02125a94bd60203a4edfbde',/" app/config/app.php && \
|
||||
grep key app/config/app.php
|
||||
|
||||
# copy the various nginx and supervisor conf (to handle both fpm and nginx)
|
||||
RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf ;\
|
||||
echo "daemon off;" >> /etc/nginx/nginx.conf ;\
|
||||
mv /var/www/html/docker/php-fpm-pool.conf /etc/php5/fpm/pool.d/www.conf ;\
|
||||
rm -f /etc/nginx/sites-enabled/* && rm -f /etc/nginx/conf.d/* && mv /var/www/html/docker/nginx-site.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
RUN curl -sS https://getcomposer.org/installer | php && php composer.phar install --no-dev -o
|
||||
|
||||
COPY docker/supervisord.conf /etc/supervisor/supervisord.conf
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015 James Brooks and individual contributors.
|
||||
Copyright (c) 2015 Alt Three Services Limited.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
84
README.md
84
README.md
@@ -1,85 +1,55 @@
|
||||
# Cachet [](https://heroku.com/deploy)
|
||||
# Cachet
|
||||
|
||||
[](https://styleci.io/repos/26730195/)
|
||||
[](https://travis-ci.org/cachethq/Cachet)
|
||||
[](https://scrutinizer-ci.com/g/cachethq/Cachet)
|
||||
[](LICENSE)
|
||||
[](https://gitter.im/cachethq/Cachet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](LICENSE)
|
||||
[](http://translate.cachethq.io/project/cachet)
|
||||
|
||||

|
||||
|
||||
**Currently in development. Things may change or break until a solid release has been announced.**
|
||||
|
||||
## Features
|
||||
|
||||
- List your services components.
|
||||
- Log incidents.
|
||||
- Apply a custom stylesheet to the status page.
|
||||
- Markdown support for incident messages.
|
||||
- RESTful API.
|
||||
- Translated into several languages.
|
||||
- Easy Heroku deployment.
|
||||
- Metrics.
|
||||
- Cross-database support: MySQL, PostgreSQL and SQLite.
|
||||
- List your services components
|
||||
- Log incidents
|
||||
- Apply custom CSS to the status page
|
||||
- Markdown support for incident messages
|
||||
- JSON API
|
||||
- Translated into eleven languages
|
||||
- Metrics
|
||||
- Cross-database support: MySQL, PostgreSQL and SQLite
|
||||
- Subscriber notifications via Email
|
||||
- Two factor authentication, with Google Authenticator
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP 5.4 or newer
|
||||
- mcrypt extension
|
||||
- PHP 5.5.9+ or newer
|
||||
- [Composer](https://getcomposer.org)
|
||||
|
||||
### Development Requirements
|
||||
|
||||
The following extra dependencies are required to develop Cachet.
|
||||
Theses extra dependencies are required to develop Cachet:
|
||||
|
||||
- Node.js
|
||||
+ Bower
|
||||
+ Gulp
|
||||
- Bower
|
||||
- Gulp
|
||||
|
||||
## Installation & Documentation
|
||||
## Installation, Upgrades and Documentation
|
||||
|
||||
You can now find our documentation at [https://docs.cachethq.io](https://docs.cachethq.io) or, directly at [http://cachet.readme.io](http://cachet.readme.io) if the first link fails to load. [Cachet Demo](https://demo.cachethq.io)
|
||||
You can now find our documentation at [https://docs.cachethq.io](https://docs.cachethq.io).
|
||||
|
||||
## What Cachet is not
|
||||
- [Installing Cachet](https://docs.cachethq.io/docs/installing-cachet)
|
||||
- [Getting started with Docker](https://docs.cachethq.io/docs/get-started-with-docker)
|
||||
- [Getting started with Vagrant](https://docs.cachethq.io/docs/get-started-with-vagrant)
|
||||
|
||||
Here is a list of things that Cachet is not or does not do:
|
||||
### Demo Account
|
||||
|
||||
1. It does not monitor your services. It works only as a way to display the status of your services. *However, Cachet is able to receive updates from third-party services via its API.*
|
||||
2. It does not work on a plugin system. There are no monitoring services to extend.
|
||||
3. It's not a Twitter clone.
|
||||
To test out the demo, you may login to the [Dashboard](https://demo.cachethq.io/dashboard) with the following:
|
||||
|
||||
## Quickstart with Docker
|
||||
- **Username:** test@test.com
|
||||
- **Password:** test123
|
||||
|
||||
Run a DB container (you can either pass in environment variables for the DB, or mount a config with `-v /my/database.php:/var/www/html/app/config/database.php`):
|
||||
|
||||
```bash
|
||||
$ export DB_USERNAME=cachet
|
||||
$ export DB_PASSWORD=cachet
|
||||
$ export DB_ROOT_PASSWORD=cachet
|
||||
$ export DB_DATABASE=cachet
|
||||
$ docker run --name mysql -e MYSQL_USER=$DB_USERNAME -e MYSQL_PASSWORD=$DB_PASSWORD -e MYSQL_ROOT_PASSWORD=$DB_ROOT_PASSWORD -e MYSQL_DATABASE=$DB_DATABASE -d mysql
|
||||
```
|
||||
|
||||
Initialize the DB if you haven't yet:
|
||||
|
||||
```bash
|
||||
$ docker run --link mysql:mysql -e DB_HOST=mysql -e DB_DATABASE=$DB_DATABASE -e DB_USERNAME=$DB_USERNAME -e DB_PASSWORD=$DB_PASSWORD cachethq/cachet:latest php artisan migrate --force
|
||||
```
|
||||
|
||||
Run Cachet:
|
||||
|
||||
```bash
|
||||
$ docker run -d --name cachet --link mysql:mysql -p 80:8000 -e DB_HOST=mysql -e DB_DATABASE=$DB_DATABASE -e DB_USERNAME=$DB_USERNAME -e DB_PASSWORD=$DB_PASSWORD cachethq/cachet:latest
|
||||
```
|
||||
|
||||
Now go to `http://<ipdockerisboundto>/setup` and have fun!
|
||||
|
||||
Note: When running in production you should ensure that you enable SSL.
|
||||
This is commonly achieved by running Nginx with your certificates on your Docker host, service or load balancers in-front of the running container, or by adding your custom SSL certificates and configuration to the supplied Nginx configuration.
|
||||
|
||||
## Read more about Cachet
|
||||
|
||||
For more information on why I started developing Cachet, check out my [Cachet articles on my blog](https://james-brooks.uk/tag/cachet/?utm_source=github&utm_medium=readme&utm_campaign=github-cachet).
|
||||
The demo is reset every half hour.
|
||||
|
||||
## Translations
|
||||
|
||||
|
||||
34
app.json
34
app.json
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "Cachet",
|
||||
"description": "An open source status page system.",
|
||||
"keywords": [
|
||||
"cachet",
|
||||
"laravel",
|
||||
"status",
|
||||
"page"
|
||||
],
|
||||
"website": "https://cachethq.io",
|
||||
"logo": "https://raw.githubusercontent.com/cachethq/assets/79336a33c24b28c470a89742671e0e291813d004/images/icon/Cachet-Icon.png",
|
||||
"success_url": "/setup",
|
||||
"repository": "https://github.com/cachethq/Cachet",
|
||||
"addons": [
|
||||
"heroku-postgresql"
|
||||
],
|
||||
"env": {
|
||||
"ENV": {
|
||||
"value": "heroku",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
},
|
||||
"BUILDPACK_URL": {
|
||||
"value": "https://github.com/heroku/heroku-buildpack-php",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
},
|
||||
"CACHE_DRIVER": {
|
||||
"value": "apc",
|
||||
"description": "Warning: Do not modify this value on Heroku deployments."
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"postdeploy": "php artisan migrate --env=heroku; php artisan key:generate;"
|
||||
}
|
||||
}
|
||||
36
app/Composers/AppComposer.php
Normal file
36
app/Composers/AppComposer.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class AppComposer
|
||||
{
|
||||
/**
|
||||
* Index page view composer.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
|
||||
$withData = [
|
||||
'subscribersEnabled' => $isEnabled && $mailAddress && $mailFrom,
|
||||
];
|
||||
|
||||
$view->with($withData);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class DashboardComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param \Illuminate\View\View $view
|
||||
*
|
||||
* @return void
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
@@ -1,19 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class IndexComposer
|
||||
{
|
||||
/**
|
||||
* Index page view composer.
|
||||
*
|
||||
* @param \Illuminate\View\View $view
|
||||
*
|
||||
* @return void
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
@@ -21,6 +28,7 @@ class IndexComposer
|
||||
$withData = [
|
||||
'systemStatus' => 'danger',
|
||||
'systemMessage' => trans('cachet.service.bad'),
|
||||
'favicon' => 'favicon-high-alert',
|
||||
];
|
||||
|
||||
if (Component::notStatus(1)->count() === 0) {
|
||||
@@ -32,8 +40,13 @@ class IndexComposer
|
||||
$withData = [
|
||||
'systemStatus' => 'success',
|
||||
'systemMessage' => trans('cachet.service.good'),
|
||||
'favicon' => 'favicon',
|
||||
];
|
||||
}
|
||||
} else {
|
||||
if (Component::whereIn('status', [2, 3])->count() > 0) {
|
||||
$withData['favicon'] = 'favicon-medium-alert';
|
||||
}
|
||||
}
|
||||
|
||||
$view->with($withData);
|
||||
28
app/Composers/LoggedUserComposer.php
Normal file
28
app/Composers/LoggedUserComposer.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoggedUserComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$view->with('loggedUser', Auth::user());
|
||||
}
|
||||
}
|
||||
37
app/Composers/ThemeComposer.php
Normal file
37
app/Composers/ThemeComposer.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class ThemeComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$view->with('themeBackgroundColor', Setting::get('style_background_color'));
|
||||
$view->with('themeTextColor', Setting::get('style_text_color'));
|
||||
|
||||
$viewData = $view->getData();
|
||||
$themeView = array_only($viewData, preg_grep('/^theme/', array_keys($viewData)));
|
||||
$hasThemeSettings = array_filter($themeView, function ($data) {
|
||||
return $data != null;
|
||||
});
|
||||
|
||||
$view->with('themeSetup', !empty($hasThemeSettings));
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Composers;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class TimezoneLocaleComposer
|
||||
{
|
||||
/**
|
||||
* Timezones and Locales composer.
|
||||
*
|
||||
* @param \Illuminate\View\View $view
|
||||
*
|
||||
* @return void
|
||||
* @param \Illuminate\Contracts\View\View $view
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
@@ -24,7 +31,7 @@ class TimezoneLocaleComposer
|
||||
$locale = basename($lang);
|
||||
|
||||
return [$locale => $enabledLangs[$locale]];
|
||||
}, glob(app_path('lang').'/*'));
|
||||
}, glob(base_path('resources/lang').'/*'));
|
||||
|
||||
$langs = call_user_func_array('array_merge', $langs);
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Config;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
@@ -24,8 +33,6 @@ class Repository
|
||||
* Create a new settings service instance.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Setting $model
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Setting $model)
|
||||
{
|
||||
@@ -35,27 +42,32 @@ class Repository
|
||||
/**
|
||||
* Returns a setting from the database.
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $checkEnv
|
||||
* @param string $name
|
||||
* @param string|null $default
|
||||
* @param bool $checkEnv
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get($name, $checkEnv = true)
|
||||
public function get($name, $default = null, $checkEnv = true)
|
||||
{
|
||||
// if we've not loaded the settings, load them now
|
||||
if (!$this->settings) {
|
||||
$this->settings = $this->model->all()->lists('value', 'name');
|
||||
}
|
||||
|
||||
// if the setting exists, return it
|
||||
if (isset($this->settings[$name])) {
|
||||
// if the setting exists and is not blank, return it
|
||||
if (!empty($this->settings[$name])) {
|
||||
return $this->settings[$name];
|
||||
}
|
||||
|
||||
// fallback to getenv if allowed to
|
||||
if ($checkEnv) {
|
||||
return $this->settings[$name] = getenv(strtoupper($name));
|
||||
if ($this->settings[$name] = env(strtoupper($name))) {
|
||||
return $this->settings[$name];
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +75,6 @@ class Repository
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
@@ -1,5 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Console\Commands;
|
||||
|
||||
use DirectoryIterator;
|
||||
@@ -19,7 +28,7 @@ class FixPermissionsCommand extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fixes file and directory permissions. Ensures SQLite database is writeable.';
|
||||
protected $description = 'Fixes file and directory permissions. Ensures SQLite database is writable.';
|
||||
|
||||
/**
|
||||
* Path to the storage directory.
|
||||
@@ -56,8 +65,6 @@ class FixPermissionsCommand extends Command
|
||||
* @param string $databaseDirectory
|
||||
* @param string $databasePath
|
||||
* @param string $databaseDefault
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($storageDirectory, $databaseDirectory, $databasePath, $databaseDefault)
|
||||
{
|
||||
@@ -71,8 +78,6 @@ class FixPermissionsCommand extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
@@ -89,8 +94,6 @@ class FixPermissionsCommand extends Command
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $mode
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function recursiveChmod($path, $mode = '0755')
|
||||
{
|
||||
37
app/Console/Kernel.php
Normal file
37
app/Console/Kernel.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
'CachetHQ\Cachet\Console\Commands\FixPermissionsCommand',
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('queue:work --sleep=3 --tries=3')->everyMinute();
|
||||
}
|
||||
}
|
||||
32
app/Events/CustomerHasSubscribedEvent.php
Normal file
32
app/Events/CustomerHasSubscribedEvent.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
|
||||
class CustomerHasSubscribedEvent
|
||||
{
|
||||
/**
|
||||
* The customer who has subscribed.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
public $subscriber;
|
||||
|
||||
/**
|
||||
* Create a new customer has subscribed event instance.
|
||||
*/
|
||||
public function __construct(Subscriber $subscriber)
|
||||
{
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
}
|
||||
32
app/Events/IncidentHasReportedEvent.php
Normal file
32
app/Events/IncidentHasReportedEvent.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
|
||||
class IncidentHasReportedEvent
|
||||
{
|
||||
/**
|
||||
* The incident that has been reported.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public $incident;
|
||||
|
||||
/**
|
||||
* Create a new incident has reported event instance.
|
||||
*/
|
||||
public function __construct(Incident $incident)
|
||||
{
|
||||
$this->incident = $incident;
|
||||
}
|
||||
}
|
||||
32
app/Events/MaintenanceHasScheduledEvent.php
Normal file
32
app/Events/MaintenanceHasScheduledEvent.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Events;
|
||||
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
|
||||
class MaintenanceHasScheduledEvent
|
||||
{
|
||||
/**
|
||||
* The incident that has been reported.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public $incident;
|
||||
|
||||
/**
|
||||
* Create a new maintenance has scheduled event instance.
|
||||
*/
|
||||
public function __construct(Incident $incident)
|
||||
{
|
||||
$this->incident = $incident;
|
||||
}
|
||||
}
|
||||
87
app/Exceptions/Displayers/RedirectDisplayer.php
Normal file
87
app/Exceptions/Displayers/RedirectDisplayer.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Exceptions\Displayers;
|
||||
|
||||
use Exception;
|
||||
use GrahamCampbell\Exceptions\Displayers\DisplayerInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
||||
class RedirectDisplayer implements DisplayerInterface
|
||||
{
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Create a new redirect displayer instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*/
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error response associated with the given exception.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param string $id
|
||||
* @param int $code
|
||||
* @param string[] $headers
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function display(Exception $exception, $id, $code, array $headers)
|
||||
{
|
||||
return redirect()->guest('auth/login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the supported content type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'text/html';
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we display the exception?
|
||||
*
|
||||
* @param \Exception $original
|
||||
* @param \Exception $transformed
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDisplay(Exception $original, Exception $transformed)
|
||||
{
|
||||
$redirect = $transformed instanceof HttpExceptionInterface && $transformed->getStatusCode() === 401;
|
||||
|
||||
return $redirect && !$this->request->is('api*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we provide verbose information about the exception?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVerbose()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
57
app/Exceptions/Filters/ApiFilter.php
Normal file
57
app/Exceptions/Filters/ApiFilter.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Exceptions\Filters;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiFilter
|
||||
{
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Create a new api filter instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*/
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter and return the displayers.
|
||||
*
|
||||
* @param \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[] $displayers
|
||||
* @param \Exception $original
|
||||
* @param \Exception $transformed
|
||||
*
|
||||
* @return \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[]
|
||||
*/
|
||||
public function filter(array $displayers, Exception $original, Exception $transformed)
|
||||
{
|
||||
if ($this->request->is('api*')) {
|
||||
foreach ($displayers as $index => $displayer) {
|
||||
if (!str_contains($displayer->contentType(), 'application/')) {
|
||||
unset($displayers[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($displayers);
|
||||
}
|
||||
}
|
||||
27
app/Exceptions/Handler.php
Normal file
27
app/Exceptions/Handler.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Exceptions;
|
||||
|
||||
use GrahamCampbell\Exceptions\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of the exception types that should not be reported.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $dontReport = [
|
||||
NotFoundHttpException::class,
|
||||
];
|
||||
}
|
||||
41
app/Exceptions/Transformers/ModelNotFoundTransformer.php
Normal file
41
app/Exceptions/Transformers/ModelNotFoundTransformer.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Exceptions\Transformers;
|
||||
|
||||
use Exception;
|
||||
use GrahamCampbell\Exceptions\Transformers\TransformerInterface;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* This is the model not found transformer class.
|
||||
*
|
||||
* @author Graham Campbell <graham@alt-three.com>
|
||||
*/
|
||||
class ModelNotFoundTransformer implements TransformerInterface
|
||||
{
|
||||
/**
|
||||
* Transform the provided exception.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
*
|
||||
* @return \Exception
|
||||
*/
|
||||
public function transform(Exception $exception)
|
||||
{
|
||||
if ($exception instanceof ModelNotFoundException) {
|
||||
$exception = new NotFoundHttpException('Resource not found');
|
||||
}
|
||||
|
||||
return $exception;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
89
app/Handlers/Events/SendIncidentEmailNotificationHandler.php
Normal file
89
app/Handlers/Events/SendIncidentEmailNotificationHandler.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\IncidentHasReportedEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
use McCool\LaravelAutoPresenter\PresenterDecorator;
|
||||
|
||||
class SendIncidentEmailNotificationHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* The subscriber instance.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
protected $subscriber;
|
||||
|
||||
/**
|
||||
* The presenter instance.
|
||||
*
|
||||
* @var \McCool\LaravelAutoPresenter\PresenterDecorator
|
||||
*/
|
||||
protected $presenter;
|
||||
|
||||
/**
|
||||
* Create a new send incident email notification handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
* @param \McCool\LaravelAutoPresenter\PresenterDecorator $presenter
|
||||
*/
|
||||
public function __construct(MailQueue $mailer, Subscriber $subscriber, PresenterDecorator $presenter)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->presenter = $presenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\IncidentHasReportedEvent $event
|
||||
*/
|
||||
public function handle(IncidentHasReportedEvent $event)
|
||||
{
|
||||
$data = $this->presenter->decorate($event->incident);
|
||||
|
||||
// Only send emails for public incidents.
|
||||
if ($event->incident->visible === 1) {
|
||||
foreach ($this->subscriber->all() as $subscriber) {
|
||||
$mail = [
|
||||
'email' => $subscriber->email,
|
||||
'subject' => 'New incident reported.',
|
||||
'status' => $data->humanStatus,
|
||||
'htmlContent' => $data->formattedMessage,
|
||||
'textContent' => $data->message,
|
||||
'token' => $subscriber->token,
|
||||
'unsubscribeLink' => route('unsubscribe', ['code' => $subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$this->mailer->queue([
|
||||
'html' => 'emails.incidents.new-html',
|
||||
'text' => 'emails.incidents.new-text',
|
||||
], $mail, function (Message $message) use ($mail) {
|
||||
$message->to($mail['email'])->subject($mail['subject']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
use McCool\LaravelAutoPresenter\PresenterDecorator;
|
||||
|
||||
class SendMaintenanceEmailNotificationHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\MailQueue
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* The subscriber instance.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
protected $subscriber;
|
||||
|
||||
/**
|
||||
* The presenter instance.
|
||||
*
|
||||
* @var \McCool\LaravelAutoPresenter\PresenterDecorator
|
||||
*/
|
||||
protected $presenter;
|
||||
|
||||
/**
|
||||
* Create a new send maintenance email notification handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
* @param \McCool\LaravelAutoPresenter\PresenterDecorator $presenter
|
||||
*/
|
||||
public function __construct(MailQueue $mailer, Subscriber $subscriber, PresenterDecorator $presenter)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->presenter = $presenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent $event
|
||||
*/
|
||||
public function handle(MaintenanceHasScheduledEvent $event)
|
||||
{
|
||||
$data = $this->presenter->decorate($event->incident);
|
||||
|
||||
foreach ($this->subscriber->all() as $subscriber) {
|
||||
$mail = [
|
||||
'email' => $subscriber->email,
|
||||
'subject' => 'Scheduled maintenance.',
|
||||
'status' => $data->humanStatus,
|
||||
'htmlContent' => $data->formattedMessage,
|
||||
'textContent' => $data->message,
|
||||
'token' => $subscriber->token,
|
||||
'unsubscribeLink' => route('unsubscribe', ['code' => $subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$this->mailer->queue([
|
||||
'html' => 'emails.incidents.maintenance-html',
|
||||
'text' => 'emails.incidents.maintenance-text',
|
||||
], $mail, function (Message $message) use ($mail) {
|
||||
$message->to($mail['email'])->subject($mail['subject']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Handlers\Events;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
|
||||
class SendSubscriberVerificationEmailHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\MailQueue
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* Create a new send subscriber verification email handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
*/
|
||||
public function __construct(MailQueue $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\CustomerHasSubscribedEvent $event
|
||||
*/
|
||||
public function handle(CustomerHasSubscribedEvent $event)
|
||||
{
|
||||
$mail = [
|
||||
'email' => $event->subscriber->email,
|
||||
'subject' => 'Confirm your subscription.',
|
||||
'link' => route('subscribe-verify', ['code' => $event->subscriber->verify_code]),
|
||||
'appUrl' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$this->mailer->queue([
|
||||
'html' => 'emails.subscribers.verify-html',
|
||||
'text' => 'emails.subscribers.verify-text',
|
||||
], $mail, function (Message $message) use ($mail) {
|
||||
$message->to($mail['email'])->subject($mail['subject']);
|
||||
});
|
||||
}
|
||||
}
|
||||
21
app/Http/Controllers/AbstractController.php
Normal file
21
app/Http/Controllers/AbstractController.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
abstract class AbstractController extends BaseController
|
||||
{
|
||||
use DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
@@ -1,15 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\IncidentTemplate;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class DashAPIController extends Controller
|
||||
class ApiController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Updates a component with the entered info.
|
||||
@@ -36,17 +46,34 @@ class DashAPIController extends Controller
|
||||
*/
|
||||
public function postUpdateComponentOrder()
|
||||
{
|
||||
$componentData = Binput::all();
|
||||
unset($componentData['component'][0]); // Remove random 0 index.
|
||||
$componentData = Binput::get('ids');
|
||||
|
||||
foreach ($componentData['component'] as $componentId => $order) {
|
||||
$component = Component::find($componentId);
|
||||
$component->update(['order' => $order]);
|
||||
foreach ($componentData as $order => $componentId) {
|
||||
// Ordering should be 1-based, data comes in 0-based
|
||||
Component::find($componentId)->update(['order' => $order + 1]);
|
||||
}
|
||||
|
||||
return $componentData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the order of component groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function postUpdateComponentGroupOrder()
|
||||
{
|
||||
$groupData = Binput::get('ids');
|
||||
|
||||
foreach ($groupData as $order => $groupId) {
|
||||
ComponentGroup::find($groupId)->update([
|
||||
'order' => $order + 1,
|
||||
]);
|
||||
}
|
||||
|
||||
return $groupData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a template by slug.
|
||||
*
|
||||
@@ -1,17 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Tag;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DashComponentController extends Controller
|
||||
class ComponentController extends AbstractController
|
||||
{
|
||||
protected $subMenu = [];
|
||||
|
||||
@@ -32,9 +40,10 @@ class DashComponentController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
View::share('subMenu', $this->subMenu);
|
||||
|
||||
View::share('subTitle', trans_choice('dashboard.components.components', 2));
|
||||
View::share([
|
||||
'sub_menu' => $this->subMenu,
|
||||
'sub_title' => trans_choice('dashboard.components.components', 2),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,9 +58,9 @@ class DashComponentController extends Controller
|
||||
$this->subMenu['components']['active'] = true;
|
||||
|
||||
return View::make('dashboard.components.index')->with([
|
||||
'pageTitle' => trans_choice('dashboard.components.components', 2).' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans_choice('dashboard.components.components', 2).' - '.trans('dashboard.dashboard'),
|
||||
'components' => $components,
|
||||
'subMenu' => $this->subMenu,
|
||||
'sub_menu' => $this->subMenu,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -65,9 +74,9 @@ class DashComponentController extends Controller
|
||||
$this->subMenu['groups']['active'] = true;
|
||||
|
||||
return View::make('dashboard.components.groups.index')->with([
|
||||
'pageTitle' => trans_choice('dashboard.components.groups.groups', 2).' - '.trans('dashboard.dashboard'),
|
||||
'groups' => ComponentGroup::all(),
|
||||
'subMenu' => $this->subMenu,
|
||||
'page_title' => trans_choice('dashboard.components.groups.groups', 2).' - '.trans('dashboard.dashboard'),
|
||||
'groups' => ComponentGroup::orderBy('order')->get(),
|
||||
'sub_menu' => $this->subMenu,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -90,9 +99,9 @@ class DashComponentController extends Controller
|
||||
);
|
||||
|
||||
return View::make('dashboard.components.edit')->with([
|
||||
'pageTitle' => $pageTitle,
|
||||
'component' => $component,
|
||||
'groups' => $groups,
|
||||
'page_title' => $pageTitle,
|
||||
'component' => $component,
|
||||
'groups' => $groups,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -106,31 +115,20 @@ class DashComponentController extends Controller
|
||||
public function updateComponentAction(Component $component)
|
||||
{
|
||||
$_component = Binput::get('component');
|
||||
$_component['user_id'] = Auth::user()->id;
|
||||
$tags = array_pull($_component, 'tags');
|
||||
|
||||
$component->update($_component);
|
||||
|
||||
if (! $component->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edit Component',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$component->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.components.edit.failure')
|
||||
))
|
||||
->with('errors', $component->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edit Component',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
// The component was added successfully, so now let's deal with the tags.
|
||||
$tags = preg_split('/ ?, ?/', $tags);
|
||||
|
||||
@@ -144,7 +142,7 @@ class DashComponentController extends Controller
|
||||
$component->tags()->sync($componentTags);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.components.edit.success')
|
||||
);
|
||||
@@ -162,8 +160,8 @@ class DashComponentController extends Controller
|
||||
$groups = ComponentGroup::all();
|
||||
|
||||
return View::make('dashboard.components.add')->with([
|
||||
'pageTitle' => trans('dashboard.components.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'groups' => $groups,
|
||||
'page_title' => trans('dashboard.components.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'groups' => $groups,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -175,32 +173,21 @@ class DashComponentController extends Controller
|
||||
public function createComponentAction()
|
||||
{
|
||||
$_component = Binput::get('component');
|
||||
$_component['user_id'] = Auth::user()->id;
|
||||
// We deal with tags separately.
|
||||
$tags = array_pull($_component, 'tags');
|
||||
|
||||
$component = Component::create($_component);
|
||||
|
||||
if (! $component->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Component',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$component->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.components.add.failure')
|
||||
))
|
||||
->with('errors', $component->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Component',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
// The component was added successfully, so now let's deal with the tags.
|
||||
$tags = preg_split('/ ?, ?/', $tags);
|
||||
|
||||
@@ -214,7 +201,7 @@ class DashComponentController extends Controller
|
||||
$component->tags()->sync($componentTags);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.components.add.success')
|
||||
);
|
||||
@@ -231,10 +218,6 @@ class DashComponentController extends Controller
|
||||
*/
|
||||
public function deleteComponentAction(Component $component)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Deleted Component',
|
||||
]);
|
||||
|
||||
$component->delete();
|
||||
|
||||
return Redirect::back();
|
||||
@@ -249,9 +232,11 @@ class DashComponentController extends Controller
|
||||
*/
|
||||
public function deleteComponentGroupAction(ComponentGroup $group)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Deleted Component Group',
|
||||
]);
|
||||
$group->components->map(function ($component) {
|
||||
$component->update([
|
||||
'group_id' => 0,
|
||||
]);
|
||||
});
|
||||
|
||||
$group->delete();
|
||||
|
||||
@@ -266,7 +251,7 @@ class DashComponentController extends Controller
|
||||
public function showAddComponentGroup()
|
||||
{
|
||||
return View::make('dashboard.components.groups.add')->with([
|
||||
'pageTitle' => trans('dashboard.components.groups.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.components.groups.add.title').' - '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -280,8 +265,8 @@ class DashComponentController extends Controller
|
||||
public function showEditComponentGroup(ComponentGroup $group)
|
||||
{
|
||||
return View::make('dashboard.components.groups.edit')->with([
|
||||
'pageTitle' => trans('dashboard.components.groups.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'group' => $group,
|
||||
'page_title' => trans('dashboard.components.groups.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'group' => $group,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -294,28 +279,18 @@ class DashComponentController extends Controller
|
||||
{
|
||||
$group = ComponentGroup::create(Binput::get('group'));
|
||||
|
||||
if (! $group->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Component Group',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$group->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.components.groups.add.failure')
|
||||
))
|
||||
->with('errors', $group->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Component Group',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.components.groups.add.success')
|
||||
);
|
||||
@@ -335,28 +310,18 @@ class DashComponentController extends Controller
|
||||
$groupData = Binput::get('group');
|
||||
$group->update($groupData);
|
||||
|
||||
if (! $group->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edit Component Group',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$group->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.components.groups.edit.failure')
|
||||
))
|
||||
->with('errors', $group->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edit Component Group',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.components.groups.edit.success')
|
||||
);
|
||||
@@ -1,12 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DashboardController extends Controller
|
||||
class DashboardController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the dashboard view.
|
||||
@@ -15,7 +24,7 @@ class DashboardController extends Controller
|
||||
*/
|
||||
public function showDashboard()
|
||||
{
|
||||
$components = Component::all();
|
||||
$components = Component::orderBy('order')->get();
|
||||
|
||||
return View::make('dashboard.index')->with([
|
||||
'components' => $components,
|
||||
@@ -30,7 +39,7 @@ class DashboardController extends Controller
|
||||
public function showNotifications()
|
||||
{
|
||||
return View::make('dashboard.notifications.index')->with([
|
||||
'pageTitle' => trans('dashboard.notifications.notifications').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.notifications.notifications').' '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Events\IncidentHasReportedEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use CachetHQ\Cachet\Models\IncidentTemplate;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class DashIncidentController extends Controller
|
||||
class IncidentController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Stores the sub-sidebar tree list.
|
||||
@@ -34,7 +47,7 @@ class DashIncidentController extends Controller
|
||||
'icon' => 'ion-android-checkmark-circle',
|
||||
'active' => true,
|
||||
],
|
||||
'schedule' => [
|
||||
'schedule' => [
|
||||
'title' => trans('dashboard.schedule.schedule'),
|
||||
'url' => route('dashboard.schedule'),
|
||||
'icon' => 'ion-android-calendar',
|
||||
@@ -42,8 +55,8 @@ class DashIncidentController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
View::share('subMenu', $this->subMenu);
|
||||
View::share('subTitle', trans('dashboard.incidents.title'));
|
||||
View::share('sub_menu', $this->subMenu);
|
||||
View::share('sub_title', trans('dashboard.incidents.title'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,8 +69,8 @@ class DashIncidentController extends Controller
|
||||
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get();
|
||||
|
||||
return View::make('dashboard.incidents.index')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.incidents').' - '.trans('dashboard.dashboard'),
|
||||
'incidents' => $incidents,
|
||||
'page_title' => trans('dashboard.incidents.incidents').' - '.trans('dashboard.dashboard'),
|
||||
'incidents' => $incidents,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -68,10 +81,14 @@ class DashIncidentController extends Controller
|
||||
*/
|
||||
public function showAddIncident()
|
||||
{
|
||||
$componentsInGroups = ComponentGroup::with('components')->get();
|
||||
$componentsOutGroups = Component::where('group_id', 0)->get();
|
||||
|
||||
return View::make('dashboard.incidents.add')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'components' => Component::all(),
|
||||
'incidentTemplates' => IncidentTemplate::all(),
|
||||
'page_title' => trans('dashboard.incidents.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'componentsInGroups' => $componentsInGroups,
|
||||
'componentsOutGroups' => $componentsOutGroups,
|
||||
'incidentTemplates' => IncidentTemplate::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -83,7 +100,7 @@ class DashIncidentController extends Controller
|
||||
public function showTemplates()
|
||||
{
|
||||
return View::make('dashboard.incidents.templates.index')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.templates.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.incidents.templates.title').' - '.trans('dashboard.dashboard'),
|
||||
'incidentTemplates' => IncidentTemplate::all(),
|
||||
]);
|
||||
}
|
||||
@@ -96,20 +113,22 @@ class DashIncidentController extends Controller
|
||||
public function createIncidentAction()
|
||||
{
|
||||
$incidentData = Binput::get('incident');
|
||||
$incidentData['user_id'] = Auth::user()->id;
|
||||
$componentStatus = array_pull($incidentData, 'component_status');
|
||||
|
||||
if (array_has($incidentData, 'created_at') && $incidentData['created_at']) {
|
||||
$incidentDate = Date::createFromFormat('d/m/Y H:i', $incidentData['created_at'], Setting::get('app_timezone'))->setTimezone(Config::get('app.timezone'));
|
||||
$incidentData['created_at'] = $incidentDate;
|
||||
$incidentData['updated_at'] = $incidentDate;
|
||||
} else {
|
||||
unset($incidentData['created_at']);
|
||||
}
|
||||
|
||||
$incident = Incident::create($incidentData);
|
||||
|
||||
if (! $incident->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Incident',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$incident->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.incidents.add.failure')
|
||||
))
|
||||
@@ -123,17 +142,21 @@ class DashIncidentController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Incident',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.incidents.add.success')
|
||||
);
|
||||
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
$subscribersEnabled = $isEnabled && $mailAddress && $mailFrom;
|
||||
|
||||
if (array_get($incidentData, 'notify') && $subscribersEnabled) {
|
||||
event(new IncidentHasReportedEvent($incident));
|
||||
}
|
||||
|
||||
return Redirect::back()->with('success', $successMsg);
|
||||
}
|
||||
|
||||
@@ -145,7 +168,7 @@ class DashIncidentController extends Controller
|
||||
public function showAddIncidentTemplate()
|
||||
{
|
||||
return View::make('dashboard.incidents.templates.add')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.templates.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.incidents.templates.add.title').' - '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -159,8 +182,8 @@ class DashIncidentController extends Controller
|
||||
public function showEditTemplateAction(IncidentTemplate $template)
|
||||
{
|
||||
return View::make('dashboard.incidents.templates.edit')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.templates.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'template' => $template,
|
||||
'page_title' => trans('dashboard.incidents.templates.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'template' => $template,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -173,10 +196,6 @@ class DashIncidentController extends Controller
|
||||
*/
|
||||
public function deleteTemplateAction(IncidentTemplate $template)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Deleted Incident Template',
|
||||
]);
|
||||
|
||||
$template->delete();
|
||||
|
||||
return Redirect::back();
|
||||
@@ -192,28 +211,18 @@ class DashIncidentController extends Controller
|
||||
$_template = Binput::get('template');
|
||||
$template = IncidentTemplate::create($_template);
|
||||
|
||||
if (! $template->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Incident Template',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$template->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.incidents.templates.add.failure')
|
||||
))
|
||||
->with('errors', $template->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Incident Template',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.incidents.templates.add.success')
|
||||
);
|
||||
@@ -230,10 +239,6 @@ class DashIncidentController extends Controller
|
||||
*/
|
||||
public function deleteIncidentAction(Incident $incident)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Deleted Incident',
|
||||
]);
|
||||
|
||||
$incident->delete();
|
||||
|
||||
return Redirect::back();
|
||||
@@ -248,10 +253,14 @@ class DashIncidentController extends Controller
|
||||
*/
|
||||
public function showEditIncidentAction(Incident $incident)
|
||||
{
|
||||
$componentsInGroups = ComponentGroup::with('components')->get();
|
||||
$componentsOutGroups = Component::where('group_id', 0)->get();
|
||||
|
||||
return View::make('dashboard.incidents.edit')->with([
|
||||
'pageTitle' => trans('dashboard.incidents.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'incident' => $incident,
|
||||
'components' => Component::all(),
|
||||
'page_title' => trans('dashboard.incidents.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'incident' => $incident,
|
||||
'componentsInGroups' => $componentsInGroups,
|
||||
'componentsOutGroups' => $componentsOutGroups,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -265,31 +274,36 @@ class DashIncidentController extends Controller
|
||||
public function editIncidentAction(Incident $incident)
|
||||
{
|
||||
$incidentData = Binput::get('incident');
|
||||
$incidentData['user_id'] = Auth::user()->id;
|
||||
|
||||
if (array_has($incidentData, 'created_at') && $incidentData['created_at']) {
|
||||
$incidentDate = Date::createFromFormat('d/m/Y H:i', $incidentData['created_at'], Setting::get('app_timezone'))->setTimezone(Config::get('app.timezone'));
|
||||
$incidentData['created_at'] = $incidentDate;
|
||||
$incidentData['updated_at'] = $incidentDate;
|
||||
} else {
|
||||
unset($incidentData['created_at']);
|
||||
}
|
||||
|
||||
$incident->update($incidentData);
|
||||
|
||||
if (! $incident->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Incident',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$incident->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.incidents.templates.edit.failure')
|
||||
))
|
||||
->with('errors', $incident->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Incident',
|
||||
'success' => true,
|
||||
]);
|
||||
$componentStatus = array_pull($incidentData, 'component_status');
|
||||
if ($incident->component) {
|
||||
$incident->component->update([
|
||||
'status' => $componentStatus,
|
||||
]);
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.incidents.edit.success')
|
||||
);
|
||||
@@ -306,10 +320,6 @@ class DashIncidentController extends Controller
|
||||
*/
|
||||
public function editTemplateAction(IncidentTemplate $template)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Incident Template',
|
||||
]);
|
||||
|
||||
$template->update(Binput::get('template'));
|
||||
|
||||
return Redirect::back()->with('updatedTemplate', $template);
|
||||
@@ -1,15 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use CachetHQ\Cachet\Models\MetricPoint;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DashMetricController extends Controller
|
||||
class MetricController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the metrics view.
|
||||
@@ -21,8 +30,8 @@ class DashMetricController extends Controller
|
||||
$metrics = Metric::orderBy('created_at', 'desc')->get();
|
||||
|
||||
return View::make('dashboard.metrics.index')->with([
|
||||
'pageTitle' => trans('dashboard.metrics.metrics').' - '.trans('dashboard.dashboard'),
|
||||
'metrics' => $metrics,
|
||||
'page_title' => trans('dashboard.metrics.metrics').' - '.trans('dashboard.dashboard'),
|
||||
'metrics' => $metrics,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -34,8 +43,8 @@ class DashMetricController extends Controller
|
||||
public function showAddMetric()
|
||||
{
|
||||
return View::make('dashboard.metrics.add')->with([
|
||||
'pageTitle' => trans('dashboard.metrics.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'metricMetricPoints' => MetricPoint::all(),
|
||||
'page_title' => trans('dashboard.metrics.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'metricMetricPoints' => MetricPoint::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -47,7 +56,7 @@ class DashMetricController extends Controller
|
||||
public function showMetricPoints()
|
||||
{
|
||||
return View::make('dashboard.metrics.points.index')->with([
|
||||
'pageTitle' => trans('dashboard.metrics.points.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.metrics.points.title').' - '.trans('dashboard.dashboard'),
|
||||
'metricMetricPoints' => MetricPoint::all(),
|
||||
]);
|
||||
}
|
||||
@@ -62,28 +71,18 @@ class DashMetricController extends Controller
|
||||
$metricData = Binput::get('metric');
|
||||
$metric = Metric::create($metricData);
|
||||
|
||||
if (! $metric->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Metric',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$metric->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.metrics.add.failure')
|
||||
))
|
||||
->with('errors', $metric->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Metric',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.metrics.add.success')
|
||||
);
|
||||
@@ -99,7 +98,7 @@ class DashMetricController extends Controller
|
||||
public function showAddMetricPoint()
|
||||
{
|
||||
return View::make('dashboard.metrics.points.add')->with([
|
||||
'pageTitle' => trans('dashboard.metrics.points.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.metrics.points.add.title').' - '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -110,21 +109,21 @@ class DashMetricController extends Controller
|
||||
*/
|
||||
public function createMetricPointAction()
|
||||
{
|
||||
$_point = Binput::get('point');
|
||||
$_point = Binput::get('point', null, false);
|
||||
$point = MetricPoint::create($_point);
|
||||
|
||||
if (! $point->isValid()) {
|
||||
if (!$point->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.metrics.points.add.failure')
|
||||
))
|
||||
->with('errors', $point->getErrors());
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.metrics.points.add.success')
|
||||
);
|
||||
@@ -156,7 +155,7 @@ class DashMetricController extends Controller
|
||||
public function showEditMetricAction(Metric $metric)
|
||||
{
|
||||
return View::make('dashboard.metrics.edit')->with([
|
||||
'pageTitle' => trans('dashboard.metrics.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.metrics.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'metric' => $metric,
|
||||
]);
|
||||
}
|
||||
@@ -170,30 +169,20 @@ class DashMetricController extends Controller
|
||||
*/
|
||||
public function editMetricAction(Metric $metric)
|
||||
{
|
||||
$_metric = Binput::get('metric');
|
||||
$metric->update($_metric);
|
||||
|
||||
if (! $metric->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Metric',
|
||||
'success' => false,
|
||||
]);
|
||||
$metricData = Binput::get('metric', null, false);
|
||||
$metric->update($metricData);
|
||||
|
||||
if (!$metric->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong>',
|
||||
trans('dashboard.notifications.awesome')
|
||||
trans('dashboard.notifications.whoops')
|
||||
))
|
||||
->with('errors', $metric->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Metric',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.metrics.edit.success')
|
||||
);
|
||||
@@ -1,20 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use CachetHQ\Cachet\Models\IncidentTemplate;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class DashScheduleController extends Controller
|
||||
class ScheduleController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Stores the sub-sidebar tree list.
|
||||
@@ -38,7 +47,7 @@ class DashScheduleController extends Controller
|
||||
'icon' => 'ion-android-checkmark-circle',
|
||||
'active' => false,
|
||||
],
|
||||
'schedule' => [
|
||||
'schedule' => [
|
||||
'title' => trans('dashboard.schedule.schedule'),
|
||||
'url' => route('dashboard.schedule'),
|
||||
'icon' => 'ion-android-calendar',
|
||||
@@ -46,8 +55,8 @@ class DashScheduleController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
View::share('subMenu', $this->subMenu);
|
||||
View::share('subTitle', trans('dashboard.incidents.title'));
|
||||
View::share('sub_menu', $this->subMenu);
|
||||
View::share('sub_title', trans('dashboard.incidents.title'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +93,6 @@ class DashScheduleController extends Controller
|
||||
public function addScheduleAction()
|
||||
{
|
||||
$scheduleData = Binput::get('incident');
|
||||
$scheduleData['user_id'] = Auth::user()->id;
|
||||
// Parse the schedule date.
|
||||
$scheduledAt = Date::createFromFormat('d/m/Y H:i', $scheduleData['scheduled_at'], Setting::get('app_timezone'))
|
||||
->setTimezone(Config::get('app.timezone'));
|
||||
@@ -104,32 +112,31 @@ class DashScheduleController extends Controller
|
||||
|
||||
$incident = Incident::create($scheduleData);
|
||||
|
||||
if (! $incident->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Scheduled Maintenance',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$incident->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('success', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.schedule.add.failure')
|
||||
))
|
||||
->with('errors', $incident->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Created Scheduled Maintenance',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.schedule.add.success')
|
||||
);
|
||||
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
$subscribersEnabled = $isEnabled && $mailAddress && $mailFrom;
|
||||
|
||||
if (array_get($scheduleData, 'notify') && $subscribersEnabled) {
|
||||
event(new MaintenanceHasScheduledEvent($incident));
|
||||
}
|
||||
|
||||
return Redirect::back()->with('success', $successMsg);
|
||||
}
|
||||
|
||||
@@ -160,7 +167,6 @@ class DashScheduleController extends Controller
|
||||
public function editScheduleAction(Incident $schedule)
|
||||
{
|
||||
$scheduleData = Binput::get('incident');
|
||||
$scheduleData['user_id'] = Auth::user()->id;
|
||||
// Parse the schedule date.
|
||||
$scheduledAt = Date::createFromFormat('d/m/Y H:i', $scheduleData['scheduled_at'], Setting::get('app_timezone'))
|
||||
->setTimezone(Config::get('app.timezone'));
|
||||
@@ -180,28 +186,18 @@ class DashScheduleController extends Controller
|
||||
|
||||
$schedule->update($scheduleData);
|
||||
|
||||
if (! $schedule->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Schedule',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$schedule->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.schedule.edit.failure')
|
||||
))
|
||||
->with('errors', $schedule->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Edited Schedule',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.schedule.edit.success')
|
||||
);
|
||||
@@ -218,14 +214,10 @@ class DashScheduleController extends Controller
|
||||
*/
|
||||
public function deleteScheduleAction(Incident $schedule)
|
||||
{
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Deleted Schedule',
|
||||
]);
|
||||
|
||||
$schedule->delete();
|
||||
|
||||
return Redirect::back()->with('warning', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.schedule.delete.failure')
|
||||
));
|
||||
@@ -1,16 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DashSettingsController extends Controller
|
||||
class SettingsController extends AbstractController
|
||||
{
|
||||
protected $subMenu = [];
|
||||
protected $subTitle = 'Settings';
|
||||
@@ -44,9 +54,9 @@ class DashSettingsController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
View::share('subTitle', $this->subTitle);
|
||||
View::share('sub_title', $this->subTitle);
|
||||
|
||||
View::share('subMenu', $this->subMenu);
|
||||
View::share('sub_menu', $this->subMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,8 +69,8 @@ class DashSettingsController extends Controller
|
||||
$this->subMenu['setup']['active'] = true;
|
||||
|
||||
return View::make('dashboard.settings.app-setup')->with([
|
||||
'pageTitle' => 'Application Setup - Dashboard',
|
||||
'subMenu' => $this->subMenu,
|
||||
'page_title' => 'Application Setup - Dashboard',
|
||||
'sub_menu' => $this->subMenu,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -74,8 +84,8 @@ class DashSettingsController extends Controller
|
||||
$this->subMenu['theme']['active'] = true;
|
||||
|
||||
return View::make('dashboard.settings.theme')->with([
|
||||
'pageTitle' => 'Theme - Dashboard',
|
||||
'subMenu' => $this->subMenu,
|
||||
'page_title' => 'Theme - Dashboard',
|
||||
'sub_menu' => $this->subMenu,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -88,9 +98,12 @@ class DashSettingsController extends Controller
|
||||
{
|
||||
$this->subMenu['security']['active'] = true;
|
||||
|
||||
$unsecureUsers = User::whereNull('google_2fa_secret')->orWhere('google_2fa_secret', '')->get();
|
||||
|
||||
return View::make('dashboard.settings.security')->with([
|
||||
'pageTitle' => 'Security - Dashboard',
|
||||
'subMenu' => $this->subMenu,
|
||||
'page_title' => 'Security - Dashboard',
|
||||
'sub_menu' => $this->subMenu,
|
||||
'unsecureUsers' => $unsecureUsers,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -104,8 +117,8 @@ class DashSettingsController extends Controller
|
||||
$this->subMenu['stylesheet']['active'] = true;
|
||||
|
||||
return View::make('dashboard.settings.stylesheet')->with([
|
||||
'pageTitle' => 'Stylesheet - Dashboard',
|
||||
'subMenu' => $this->subMenu,
|
||||
'page_title' => 'Stylesheet - Dashboard',
|
||||
'sub_menu' => $this->subMenu,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -159,6 +172,10 @@ class DashSettingsController extends Controller
|
||||
|
||||
try {
|
||||
foreach (Binput::except(['app_banner', 'remove_banner']) as $settingName => $settingValue) {
|
||||
if ($settingName === 'app_analytics_pi_url') {
|
||||
$settingValue = rtrim($settingValue, '/');
|
||||
}
|
||||
|
||||
Setting::firstOrCreate([
|
||||
'name' => $settingName,
|
||||
])->update([
|
||||
104
app/Http/Controllers/Admin/SubscriberController.php
Normal file
104
app/Http/Controllers/Admin/SubscriberController.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class SubscriberController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the subscribers view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showSubscribers()
|
||||
{
|
||||
$subscribers = Subscriber::all();
|
||||
|
||||
return View::make('dashboard.subscribers.index')
|
||||
->with([
|
||||
'page_title' => trans('dashboard.subscribers.subscribers').' - '.trans('dashboard.dashboard'),
|
||||
'subscribers' => $subscribers,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the add subscriber view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showAddSubscriber()
|
||||
{
|
||||
return View::make('dashboard.subscribers.add')
|
||||
->with([
|
||||
'page_title' => trans('dashboard.subscribers.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'incidentTemplates' => Subscriber::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new subscriber.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function createSubscriberAction()
|
||||
{
|
||||
$email = Binput::get('email');
|
||||
|
||||
$subscriber = Subscriber::create([
|
||||
'email' => $email,
|
||||
]);
|
||||
|
||||
if (!$subscriber->isValid()) {
|
||||
return Redirect::back()
|
||||
->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.subscribers.add.failure')
|
||||
))
|
||||
->with('errors', $subscriber->getErrors());
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.subscribers.add.success')
|
||||
);
|
||||
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
|
||||
return Redirect::back()
|
||||
->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a subscriber.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function deleteSubscriberAction(Subscriber $subscriber)
|
||||
{
|
||||
$subscriber->delete();
|
||||
|
||||
return Redirect::back();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DashTeamController extends Controller
|
||||
class TeamController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the team members view.
|
||||
@@ -20,7 +29,7 @@ class DashTeamController extends Controller
|
||||
$team = User::all();
|
||||
|
||||
return View::make('dashboard.team.index')->with([
|
||||
'pageTitle' => trans('dashboard.team.team').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.team.team').' - '.trans('dashboard.dashboard'),
|
||||
'teamMembers' => $team,
|
||||
]);
|
||||
}
|
||||
@@ -33,8 +42,8 @@ class DashTeamController extends Controller
|
||||
public function showTeamMemberView(User $user)
|
||||
{
|
||||
return View::make('dashboard.team.edit')->with([
|
||||
'pageTitle' => trans('dashboard.team.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'user' => $user,
|
||||
'page_title' => trans('dashboard.team.edit.title').' - '.trans('dashboard.dashboard'),
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -46,7 +55,7 @@ class DashTeamController extends Controller
|
||||
public function showAddTeamMemberView()
|
||||
{
|
||||
return View::make('dashboard.team.add')->with([
|
||||
'pageTitle' => trans('dashboard.team.add.title').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.team.add.title').' - '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -59,28 +68,18 @@ class DashTeamController extends Controller
|
||||
{
|
||||
$user = User::create(Binput::all());
|
||||
|
||||
if (! $user->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Added User',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$user->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::except('password'))
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.team.add.failure')
|
||||
))
|
||||
->with('errors', $user->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Added User',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.team.add.success')
|
||||
);
|
||||
@@ -107,28 +106,18 @@ class DashTeamController extends Controller
|
||||
|
||||
$user->update($items);
|
||||
|
||||
if (! $user->isValid()) {
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Updated User',
|
||||
'success' => false,
|
||||
]);
|
||||
|
||||
if (!$user->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::except('password'))
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.team.edit.failure')
|
||||
))
|
||||
->with('errors', $user->getErrors());
|
||||
}
|
||||
|
||||
segment_track('Dashboard', [
|
||||
'event' => 'Updated User',
|
||||
'success' => true,
|
||||
]);
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.team.edit.success')
|
||||
);
|
||||
@@ -1,16 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Admin;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController;
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use PragmaRX\Google2FA\Vendor\Laravel\Facade as Google2FA;
|
||||
|
||||
class DashUserController extends Controller
|
||||
class UserController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the user view.
|
||||
@@ -20,7 +29,7 @@ class DashUserController extends Controller
|
||||
public function showUser()
|
||||
{
|
||||
return View::make('dashboard.user.index')->with([
|
||||
'pageTitle' => trans('dashboard.team.profile').' - '.trans('dashboard.dashboard'),
|
||||
'page_title' => trans('dashboard.team.profile').' - '.trans('dashboard.dashboard'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -37,20 +46,10 @@ class DashUserController extends Controller
|
||||
$enable2FA = (bool) array_pull($items, 'google2fa');
|
||||
|
||||
// Let's enable/disable auth
|
||||
if ($enable2FA && ! Auth::user()->hasTwoFactor) {
|
||||
if ($enable2FA && !Auth::user()->hasTwoFactor) {
|
||||
$items['google_2fa_secret'] = Google2FA::generateSecretKey();
|
||||
|
||||
segment_track('User Management', [
|
||||
'event' => 'enabled_two_factor',
|
||||
'value' => true,
|
||||
]);
|
||||
} elseif (! $enable2FA) {
|
||||
} elseif (!$enable2FA) {
|
||||
$items['google_2fa_secret'] = '';
|
||||
|
||||
segment_track('User Management', [
|
||||
'event' => 'enabled_two_factor',
|
||||
'value' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
if (trim($passwordChange) === '') {
|
||||
@@ -60,10 +59,10 @@ class DashUserController extends Controller
|
||||
$user = Auth::user();
|
||||
$user->update($items);
|
||||
|
||||
if (! $user->isValid()) {
|
||||
if (!$user->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::except('password'))
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('dashboard.team.edit.failure')
|
||||
))
|
||||
@@ -71,7 +70,7 @@ class DashUserController extends Controller
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
'%s %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('dashboard.team.edit.success')
|
||||
);
|
||||
@@ -86,10 +85,6 @@ class DashUserController extends Controller
|
||||
*/
|
||||
public function regenerateApiKey(User $user)
|
||||
{
|
||||
segment_track('User Management', [
|
||||
'event' => 'regenrated_api_token',
|
||||
]);
|
||||
|
||||
$user->api_key = User::generateApiKey();
|
||||
$user->save();
|
||||
|
||||
204
app/Http/Controllers/Api/AbstractApiController.php
Normal file
204
app/Http/Controllers/Api/AbstractApiController.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Http\Controllers\AbstractController as BaseController;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
|
||||
|
||||
abstract class AbstractApiController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The HTTP response headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* The HTTP response meta data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $meta = [];
|
||||
|
||||
/**
|
||||
* The HTTP response data.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $data = null;
|
||||
|
||||
/**
|
||||
* The HTTP response status code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $statusCode = 200;
|
||||
|
||||
/**
|
||||
* Set the response headers.
|
||||
*
|
||||
* @param array $headers
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response meta data.
|
||||
*
|
||||
* @param array $meta
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setMetaData(array $meta)
|
||||
{
|
||||
$this->meta = $meta;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response meta data.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response status code.
|
||||
*
|
||||
* @param int $statusCode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setStatusCode($statusCode)
|
||||
{
|
||||
$this->statusCode = $statusCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with an item response.
|
||||
*
|
||||
* @param mixed
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function item($item)
|
||||
{
|
||||
return $this->setData(AutoPresenter::decorate($item))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a collection response.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $collection
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function collection(Collection $collection)
|
||||
{
|
||||
return $this->setData(AutoPresenter::decorate($collection))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a pagination response.
|
||||
*
|
||||
* @param \Illuminate\Pagination\Paginator $paginator
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function paginator(Paginator $paginator, Request $request)
|
||||
{
|
||||
foreach ($request->query as $key => $value) {
|
||||
if ($key != 'page') {
|
||||
$paginator->addQuery($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$pagination = [
|
||||
'pagination' => [
|
||||
'total' => $paginator->total(),
|
||||
'count' => count($paginator->items()),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'total_pages' => $paginator->lastPage(),
|
||||
'links' => [
|
||||
'next_page' => $paginator->nextPageUrl(),
|
||||
'previous_page' => $paginator->previousPageUrl(),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$items = $paginator->getCollection();
|
||||
|
||||
if ($sortBy = $request->get('sort')) {
|
||||
$direction = $request->has('order') && $request->get('order') == 'desc';
|
||||
|
||||
$items = $items->sortBy($sortBy, SORT_REGULAR, $direction);
|
||||
}
|
||||
|
||||
return $this->setMetaData($pagination)->setData(AutoPresenter::decorate($items->values()->all()))->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with a no content response.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function noContent()
|
||||
{
|
||||
return $this->setStatusCode(204)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the response.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function respond()
|
||||
{
|
||||
if (!empty($this->meta)) {
|
||||
$response['meta'] = $this->meta;
|
||||
}
|
||||
|
||||
$response['data'] = $this->data;
|
||||
|
||||
if ($this->data instanceof Arrayable) {
|
||||
$response['data'] = $this->data->toArray();
|
||||
}
|
||||
|
||||
return Response::json($response, $this->statusCode, $this->headers);
|
||||
}
|
||||
}
|
||||
132
app/Http/Controllers/Api/ComponentController.php
Normal file
132
app/Http/Controllers/Api/ComponentController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\Tag;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class ComponentController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all components.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getComponents(Request $request)
|
||||
{
|
||||
$components = Component::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($components, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Component $component
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function getComponent(Component $component)
|
||||
{
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new component.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function postComponents(Guard $auth)
|
||||
{
|
||||
$componentData = Binput::except('tags');
|
||||
|
||||
try {
|
||||
$component = Component::create($componentData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (!$component->isValid()) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (Binput::has('tags')) {
|
||||
// The component was added successfully, so now let's deal with the tags.
|
||||
$tags = preg_split('/ ?, ?/', Binput::get('tags'));
|
||||
|
||||
// For every tag, do we need to create it?
|
||||
$componentTags = array_map(function ($taggable) use ($component) {
|
||||
return Tag::firstOrCreate([
|
||||
'name' => $taggable,
|
||||
])->id;
|
||||
}, $tags);
|
||||
|
||||
$component->tags()->sync($componentTags);
|
||||
}
|
||||
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Componet $component
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Component
|
||||
*/
|
||||
public function putComponent(Component $component)
|
||||
{
|
||||
$component->update(Binput::except('tags'));
|
||||
|
||||
if (!$component->isValid('updating')) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if (Binput::has('tags')) {
|
||||
$tags = preg_split('/ ?, ?/', Binput::get('tags'));
|
||||
|
||||
// For every tag, do we need to create it?
|
||||
$componentTags = array_map(function ($taggable) use ($component) {
|
||||
return Tag::firstOrCreate([
|
||||
'name' => $taggable,
|
||||
])->id;
|
||||
}, $tags);
|
||||
|
||||
$component->tags()->sync($componentTags);
|
||||
}
|
||||
|
||||
return $this->item($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing component.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Component $component
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteComponent(Component $component)
|
||||
{
|
||||
$component->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
20
app/Http/Controllers/Api/GeneralController.php
Normal file
20
app/Http/Controllers/Api/GeneralController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
class GeneralController extends AbstractApiController
|
||||
{
|
||||
public function ping()
|
||||
{
|
||||
return $this->item('Pong!');
|
||||
}
|
||||
}
|
||||
123
app/Http/Controllers/Api/IncidentController.php
Normal file
123
app/Http/Controllers/Api/IncidentController.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Events\IncidentHasReportedEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class IncidentController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all incidents.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getIncidents(Request $request, Guard $auth)
|
||||
{
|
||||
$incidentVisiblity = $auth->check() ? 0 : 1;
|
||||
|
||||
$incidents = Incident::where('visible', '>=', $incidentVisiblity)
|
||||
->paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($incidents, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Incident $incident
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function getIncident(Incident $incident)
|
||||
{
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new incident.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function postIncidents(Guard $auth)
|
||||
{
|
||||
$incidentData = Binput::all();
|
||||
|
||||
if (!array_has($incidentData, 'visible')) {
|
||||
$incidentData['visible'] = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
$incident = Incident::create($incidentData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$isEnabled = (bool) Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
$subscribersEnabled = $isEnabled && $mailAddress && $mailFrom;
|
||||
|
||||
if (array_get($incidentData, 'notify') && $subscribersEnabled) {
|
||||
event(new IncidentHasReportedEvent($incident));
|
||||
}
|
||||
|
||||
if ($incident->isValid()) {
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Inicdent $incident
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Incident
|
||||
*/
|
||||
public function putIncident(Incident $incident)
|
||||
{
|
||||
$incident->update(Binput::all());
|
||||
|
||||
if ($incident->isValid('updating')) {
|
||||
return $this->item($incident);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing incident.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Inicdent $incident
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteIncident(Incident $incident)
|
||||
{
|
||||
$incident->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
111
app/Http/Controllers/Api/MetricController.php
Normal file
111
app/Http/Controllers/Api/MetricController.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class MetricController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all metrics.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getMetrics(Request $request)
|
||||
{
|
||||
$metrics = Metric::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($metrics, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function getMetric(Metric $metric)
|
||||
{
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all metric points.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getMetricPoints(Metric $metric)
|
||||
{
|
||||
return $this->collection($metric->points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metric.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function postMetrics()
|
||||
{
|
||||
try {
|
||||
$metric = Metric::create(Binput::all());
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if ($metric->isValid()) {
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Metric
|
||||
*/
|
||||
public function putMetric(Metric $metric)
|
||||
{
|
||||
$metric->update(Binput::all());
|
||||
|
||||
if ($metric->isValid('updating')) {
|
||||
return $this->item($metric);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing metric.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteMetric(Metric $metric)
|
||||
{
|
||||
$metric->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
98
app/Http/Controllers/Api/MetricPointController.php
Normal file
98
app/Http/Controllers/Api/MetricPointController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use CachetHQ\Cachet\Models\MetricPoint;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
|
||||
class MetricPointController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get a single metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetricPoint $metricPoint
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function getMetricPoints(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function postMetricPoints(Metric $metric)
|
||||
{
|
||||
$metricPointData = Binput::all();
|
||||
$metricPointData['metric_id'] = $metric->id;
|
||||
|
||||
if ($timestamp = array_pull($metricPointData, 'timestamp')) {
|
||||
$pointTimestamp = Carbon::createFromFormat('U', $timestamp);
|
||||
$metricPointData['created_at'] = $pointTimestamp->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
try {
|
||||
$metricPoint = MetricPoint::create($metricPointData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetircPoint $metricPoint
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\MetricPoint
|
||||
*/
|
||||
public function putMetricPoint(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
$metricPointData = Binput::all();
|
||||
$metricPointData['metric_id'] = $metric->id;
|
||||
|
||||
if ($timestamp = array_pull($metricPointData, 'timestamp')) {
|
||||
$pointTimestamp = Carbon::createFromFormat('U', $timestamp);
|
||||
$metricPointData['created_at'] = $pointTimestamp->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$metricPoint->update($metricPointData);
|
||||
|
||||
return $this->item($metricPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a metric point.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Metric $metric
|
||||
* @param \CachetHQ\Cachet\Models\MetricPoint $metricPoint
|
||||
*
|
||||
* @return \Dingo\Api\Http\Response
|
||||
*/
|
||||
public function deleteMetricPoint(Metric $metric, MetricPoint $metricPoint)
|
||||
{
|
||||
$metricPoint->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
77
app/Http/Controllers/Api/SubscriberController.php
Normal file
77
app/Http/Controllers/Api/SubscriberController.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class SubscriberController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all subscribers.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getSubscribers(Request $request)
|
||||
{
|
||||
$subscribers = Subscriber::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($subscribers, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subscriber.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
public function postSubscribers()
|
||||
{
|
||||
$subscriberData = Binput::except('verify');
|
||||
|
||||
try {
|
||||
$subscriber = Subscriber::create($subscriberData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if ($subscriber->isValid()) {
|
||||
// If we're auto-verifying the subscriber, don't bother with this event.
|
||||
if (!(Binput::get('verify'))) {
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
}
|
||||
|
||||
return $this->item($subscriber);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a subscriber.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteSubscriber(Subscriber $subscriber)
|
||||
{
|
||||
$subscriber->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
||||
70
app/Http/Controllers/AtomController.php
Normal file
70
app/Http/Controllers/AtomController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Str;
|
||||
use Roumen\Feed\Facades\Feed;
|
||||
|
||||
class AtomController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Generates an Atom feed of all incidents.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\ComponentGroup|null $group
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function feedAction(ComponentGroup $group = null)
|
||||
{
|
||||
$feed = Feed::make();
|
||||
$feed->title = Setting::get('app_name');
|
||||
$feed->description = trans('cachet.feed');
|
||||
$feed->link = Str::canonicalize(Setting::get('app_domain'));
|
||||
|
||||
$feed->setDateFormat('datetime');
|
||||
|
||||
if ($group->exists) {
|
||||
$group->components->map(function ($component) use ($feed) {
|
||||
$component->incidents()->visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Incident::visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
}
|
||||
|
||||
return $feed->render('atom');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the feed.
|
||||
*
|
||||
* @param \Roumen\Feed\Facades\Feed $feed
|
||||
* @param \CachetHQ\Cachet\Models\Incident $incident
|
||||
*/
|
||||
private function feedAddItem(&$feed, $incident)
|
||||
{
|
||||
$feed->add(
|
||||
$incident->name,
|
||||
Setting::get('app_name'),
|
||||
Str::canonicalize(Setting::get('app_domain')).'#'.$incident->id,
|
||||
$incident->created_at->toAtomString(),
|
||||
Markdown::convertToHtml($incident->message)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use GrahamCampbell\Throttle\Facades\Throttle;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
@@ -15,7 +22,7 @@ use PragmaRX\Google2FA\Vendor\Laravel\Facade as Google2FA;
|
||||
/**
|
||||
* Logs users into their account.
|
||||
*/
|
||||
class AuthController extends Controller
|
||||
class AuthController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Shows the login view.
|
||||
@@ -24,7 +31,9 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function showLogin()
|
||||
{
|
||||
return View::make('auth.login');
|
||||
return View::make('auth.login')->with([
|
||||
'page_title' => trans('dashboard.login.login'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,14 +56,12 @@ class AuthController extends Controller
|
||||
return Redirect::route('two-factor');
|
||||
}
|
||||
|
||||
// We probably wan't to add support for "Remember me" here.
|
||||
// We probably want to add support for "Remember me" here.
|
||||
Auth::attempt(Binput::only(['email', 'password']));
|
||||
|
||||
return Redirect::intended('dashboard');
|
||||
}
|
||||
|
||||
Throttle::hit(Request::instance(), 10, 10);
|
||||
|
||||
return Redirect::back()
|
||||
->withInput(Binput::except('password'))
|
||||
->with('error', trans('forms.login.invalid'));
|
||||
118
app/Http/Controllers/HomeController.php
Normal file
118
app/Http/Controllers/HomeController.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Component;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use CachetHQ\Cachet\Models\Metric;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Returns the rendered Blade templates.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showIndex()
|
||||
{
|
||||
$today = Date::now();
|
||||
$startDate = Date::now();
|
||||
|
||||
// Check if we have another starting date
|
||||
if (Binput::has('start_date')) {
|
||||
try {
|
||||
// If date provided is valid
|
||||
$oldDate = Date::createFromFormat('Y-m-d', Binput::get('start_date'));
|
||||
|
||||
// If trying to get a future date fallback to today
|
||||
if ($today->gt($oldDate)) {
|
||||
$startDate = $oldDate;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Fallback to today
|
||||
}
|
||||
}
|
||||
|
||||
$metrics = null;
|
||||
|
||||
if ($displayMetrics = Setting::get('display_graphs')) {
|
||||
$metrics = Metric::where('display_chart', 1)->get();
|
||||
}
|
||||
|
||||
$daysToShow = Setting::get('app_incident_days') ?: 7;
|
||||
$incidentDays = range(0, $daysToShow - 1);
|
||||
$dateTimeZone = Setting::get('app_timezone');
|
||||
|
||||
$incidentVisiblity = Auth::check() ? 0 : 1;
|
||||
|
||||
$allIncidents = Incident::notScheduled()->where('visible', '>=', $incidentVisiblity)->whereBetween('created_at', [
|
||||
$startDate->copy()->subDays($daysToShow)->format('Y-m-d').' 00:00:00',
|
||||
$startDate->format('Y-m-d').' 23:59:59',
|
||||
])->orderBy('scheduled_at', 'desc')->orderBy('created_at', 'desc')->get()->groupBy(function (Incident $incident) use ($dateTimeZone) {
|
||||
// If it's scheduled, get the scheduled at date.
|
||||
if ($incident->is_scheduled) {
|
||||
return (new Date($incident->scheduled_at))
|
||||
->setTimezone($dateTimeZone)->toDateString();
|
||||
}
|
||||
|
||||
return (new Date($incident->created_at))
|
||||
->setTimezone($dateTimeZone)->toDateString();
|
||||
});
|
||||
|
||||
// Add in days that have no incidents
|
||||
foreach ($incidentDays as $i) {
|
||||
$date = (new Date($startDate))->setTimezone($dateTimeZone)->subDays($i);
|
||||
|
||||
if (!isset($allIncidents[$date->toDateString()])) {
|
||||
$allIncidents[$date->toDateString()] = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the array so it takes into account the added days
|
||||
$allIncidents = $allIncidents->sortBy(function ($value, $key) {
|
||||
return strtotime($key);
|
||||
}, SORT_REGULAR, true)->all();
|
||||
|
||||
// Scheduled maintenance code.
|
||||
$scheduledMaintenance = Incident::scheduled()->orderBy('scheduled_at')->get();
|
||||
|
||||
// Component & Component Group lists.
|
||||
$usedComponentGroups = Component::where('group_id', '>', 0)->groupBy('group_id')->lists('group_id');
|
||||
$componentGroups = ComponentGroup::whereIn('id', $usedComponentGroups)->orderBy('order')->get();
|
||||
$ungroupedComponents = Component::where('group_id', 0)->orderBy('order')->orderBy('created_at')->get();
|
||||
|
||||
$canPageBackward = Incident::notScheduled()->where('created_at', '<', $startDate->format('Y-m-d'))->count() != 0;
|
||||
|
||||
return View::make('index', [
|
||||
'componentGroups' => $componentGroups,
|
||||
'ungroupedComponents' => $ungroupedComponents,
|
||||
'displayMetrics' => $displayMetrics,
|
||||
'metrics' => $metrics,
|
||||
'allIncidents' => $allIncidents,
|
||||
'scheduledMaintenance' => $scheduledMaintenance,
|
||||
'aboutApp' => Markdown::convertToHtml(Setting::get('app_about')),
|
||||
'canPageForward' => (bool) $today->gt($startDate),
|
||||
'canPageBackward' => $canPageBackward,
|
||||
'previousDate' => $startDate->copy()->subDays($daysToShow)->toDateString(),
|
||||
'nextDate' => $startDate->copy()->addDays($daysToShow)->toDateString(),
|
||||
'page_title' => Setting::get('app_name'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
70
app/Http/Controllers/RssController.php
Normal file
70
app/Http/Controllers/RssController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\ComponentGroup;
|
||||
use CachetHQ\Cachet\Models\Incident;
|
||||
use Illuminate\Support\Str;
|
||||
use Roumen\Feed\Facades\Feed;
|
||||
|
||||
class RssController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Generates an Atom feed of all incidents.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\ComponentGroup|null $group
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function feedAction(ComponentGroup $group = null)
|
||||
{
|
||||
$feed = Feed::make();
|
||||
$feed->title = Setting::get('app_name');
|
||||
$feed->lang = Setting::get('app_locale');
|
||||
$feed->description = trans('cachet.feed');
|
||||
$feed->link = Str::canonicalize(Setting::get('app_domain'));
|
||||
|
||||
$feed->setDateFormat('datetime');
|
||||
|
||||
if ($group->exists) {
|
||||
$group->components->map(function ($component) use ($feed) {
|
||||
$component->incidents()->visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Incident::visible()->orderBy('created_at', 'desc')->get()->map(function ($incident) use ($feed) {
|
||||
$this->feedAddItem($feed, $incident);
|
||||
});
|
||||
}
|
||||
|
||||
return $feed->render('rss');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the feed.
|
||||
*
|
||||
* @param \Roumen\Feed\Facades\Feed $feed
|
||||
* @param \CachetHQ\Cachet\Models\Incident $incident
|
||||
*/
|
||||
private function feedAddItem(&$feed, $incident)
|
||||
{
|
||||
$feed->add(
|
||||
$incident->name,
|
||||
Setting::get('app_name'),
|
||||
Str::canonicalize(Setting::get('app_domain')).'#'.$incident->id,
|
||||
$incident->created_at->toRssString(),
|
||||
$incident->message
|
||||
);
|
||||
}
|
||||
}
|
||||
216
app/Http/Controllers/SetupController.php
Normal file
216
app/Http/Controllers/SetupController.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class SetupController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Array of cache drivers.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $cacheDrivers = [
|
||||
'apc' => 'APC(u)',
|
||||
'array' => 'Array',
|
||||
'file' => 'File',
|
||||
'database' => 'Database',
|
||||
'memcached' => 'Memcached',
|
||||
'redis' => 'Redis',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new setup controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->beforeFilter('csrf', ['only' => ['postCachet']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setup page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
// If we've copied the .env.example file, then we should try and reset it.
|
||||
if (getenv('APP_KEY') === 'SomeRandomString') {
|
||||
$this->keyGenerate();
|
||||
}
|
||||
|
||||
return View::make('setup')->with([
|
||||
'page_title' => trans('setup.setup'),
|
||||
'cacheDrivers' => $this->cacheDrivers,
|
||||
'appUrl' => Request::root(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles validation on step one of the setup form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep1()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
return Response::json(['status' => 1]);
|
||||
} else {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles validation on step two of the setup form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep2()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'settings.app_name' => 'required',
|
||||
'settings.app_domain' => 'required',
|
||||
'settings.app_timezone' => 'required',
|
||||
'settings.app_locale' => 'required',
|
||||
'settings.show_support' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
return Response::json(['status' => 1]);
|
||||
} else {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the actual app setup, including user, settings and env.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function postStep3()
|
||||
{
|
||||
$postData = Binput::all();
|
||||
|
||||
$v = Validator::make($postData, [
|
||||
'env.cache_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'env.session_driver' => 'required|in:'.implode(',', array_keys($this->cacheDrivers)),
|
||||
'settings.app_name' => 'required',
|
||||
'settings.app_domain' => 'required',
|
||||
'settings.app_timezone' => 'required',
|
||||
'settings.app_locale' => 'required',
|
||||
'settings.show_support' => 'boolean',
|
||||
'user.username' => ['required', 'regex:/\A(?!.*[:;]-\))[ -~]+\z/'],
|
||||
'user.email' => 'email|required',
|
||||
'user.password' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->passes()) {
|
||||
// Pull the user details out.
|
||||
$userDetails = array_pull($postData, 'user');
|
||||
|
||||
$user = User::create([
|
||||
'username' => $userDetails['username'],
|
||||
'email' => $userDetails['email'],
|
||||
'password' => $userDetails['password'],
|
||||
'level' => 1,
|
||||
]);
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
$settings = array_pull($postData, 'settings');
|
||||
|
||||
foreach ($settings as $settingName => $settingValue) {
|
||||
Setting::create([
|
||||
'name' => $settingName,
|
||||
'value' => $settingValue,
|
||||
]);
|
||||
}
|
||||
|
||||
$envData = array_pull($postData, 'env');
|
||||
|
||||
// Write the env to the .env file.
|
||||
foreach ($envData as $envKey => $envValue) {
|
||||
$this->writeEnv($envKey, $envValue);
|
||||
}
|
||||
|
||||
Session::flash('setup.done', true);
|
||||
|
||||
if (Request::ajax()) {
|
||||
return Response::json(['status' => 1]);
|
||||
}
|
||||
|
||||
return Redirect::to('dashboard');
|
||||
} else {
|
||||
if (Request::ajax()) {
|
||||
return Response::json(['errors' => $v->messages()], 400);
|
||||
}
|
||||
|
||||
return Redirect::back()->withInput()->with('errors', $v->messages());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to the .env file with given parameters.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function writeEnv($key, $value)
|
||||
{
|
||||
static $path = null;
|
||||
|
||||
if ($path === null || ($path !== null && file_exists($path))) {
|
||||
$path = base_path('.env');
|
||||
file_put_contents($path, str_replace(
|
||||
getenv(strtoupper($key)), $value, file_get_contents($path)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the app.key value.
|
||||
*/
|
||||
protected function keyGenerate()
|
||||
{
|
||||
$key = str_random(42);
|
||||
|
||||
$path = base_path('.env');
|
||||
|
||||
file_put_contents($path, str_replace(
|
||||
Config::get('app.key'), $key, file_get_contents($path)
|
||||
));
|
||||
|
||||
Config::set('app.key', $key);
|
||||
}
|
||||
}
|
||||
129
app/Http/Controllers/SubscribeController.php
Normal file
129
app/Http/Controllers/SubscribeController.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Carbon\Carbon;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class SubscribeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Show the subscribe by email page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showSubscribe()
|
||||
{
|
||||
return View::make('subscribe', [
|
||||
'page_title' => Setting::get('app_name'),
|
||||
'aboutApp' => Markdown::convertToHtml(Setting::get('app_about')),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the subscribe user.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function postSubscribe()
|
||||
{
|
||||
$subscriber = Subscriber::create(['email' => Binput::get('email')]);
|
||||
|
||||
if (!$subscriber->isValid()) {
|
||||
return Redirect::back()->withInput(Binput::all())
|
||||
->with('title', sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.whoops'),
|
||||
trans('cachet.subscriber.email.failure')
|
||||
))
|
||||
->with('errors', $subscriber->getErrors());
|
||||
}
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.subscribed')
|
||||
);
|
||||
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the verify subscriber email.
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getVerify($code = null)
|
||||
{
|
||||
if (is_null($code)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||
|
||||
if (!$subscriber || $subscriber->verified()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
$subscriber->verified_at = Carbon::now();
|
||||
$subscriber->save();
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.verified')
|
||||
);
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the unsubscribe.
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function getUnsubscribe($code = null)
|
||||
{
|
||||
if (is_null($code)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||
|
||||
if (!$subscriber || !$subscriber->verified()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
$subscriber->delete();
|
||||
|
||||
$successMsg = sprintf(
|
||||
'<strong>%s</strong> %s',
|
||||
trans('dashboard.notifications.awesome'),
|
||||
trans('cachet.subscriber.email.unsuscribed')
|
||||
);
|
||||
|
||||
return Redirect::route('status-page')->with('success', $successMsg);
|
||||
}
|
||||
}
|
||||
50
app/Http/Kernel.php
Normal file
50
app/Http/Kernel.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http;
|
||||
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
'Fideloper\Proxy\TrustProxies',
|
||||
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
|
||||
'Illuminate\Cookie\Middleware\EncryptCookies',
|
||||
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
|
||||
'Illuminate\Session\Middleware\StartSession',
|
||||
'Illuminate\View\Middleware\ShareErrorsFromSession',
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth' => 'CachetHQ\Cachet\Http\Middleware\Authenticate',
|
||||
'auth.api' => 'CachetHQ\Cachet\Http\Middleware\ApiAuthenticate',
|
||||
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
|
||||
'guest' => 'CachetHQ\Cachet\Http\Middleware\RedirectIfAuthenticated',
|
||||
'csrf' => 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
|
||||
'admin' => 'CachetHQ\Cachet\Http\Middleware\Admin',
|
||||
'throttling' => 'GrahamCampbell\Throttle\Http\Middleware\ThrottleMiddleware',
|
||||
'app.isSetup' => 'CachetHQ\Cachet\Http\Middleware\AppIsSetup',
|
||||
'app.hasSetting' => 'CachetHQ\Cachet\Http\Middleware\HasSetting',
|
||||
'app.subscribers' => 'CachetHQ\Cachet\Http\Middleware\SubscribersConfigured',
|
||||
'accept' => 'CachetHQ\Cachet\Http\Middleware\Acceptable',
|
||||
];
|
||||
}
|
||||
36
app/Http/Middleware/Acceptable.php
Normal file
36
app/Http/Middleware/Acceptable.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
|
||||
class Acceptable
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $type
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $type)
|
||||
{
|
||||
if (!$request->accepts($type)) {
|
||||
throw new NotAcceptableHttpException();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
53
app/Http/Middleware/Admin.php
Normal file
53
app/Http/Middleware/Admin.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class Admin
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new admin middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* We're verifying that the current user is logged in to Cachet and is an admin level.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$this->auth->check() || ($this->auth->check() && !$this->auth->user()->isAdmin)) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
67
app/Http/Middleware/ApiAuthenticate.php
Normal file
67
app/Http/Middleware/ApiAuthenticate.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use CachetHQ\Cachet\Models\User;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class ApiAuthenticate
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new api authenticate middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($this->auth->guest()) {
|
||||
if ($apiToken = $request->header('X-Cachet-Token')) {
|
||||
try {
|
||||
$this->auth->onceUsingId(User::findByApiToken($apiToken)->id);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
} elseif ($request->getUser()) {
|
||||
if ($this->auth->onceBasic() !== null) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Before;
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class IsSetupFilter
|
||||
class AppIsSetup
|
||||
{
|
||||
/**
|
||||
* Run the is setup filter.
|
||||
@@ -17,19 +25,21 @@ class IsSetupFilter
|
||||
* sending the user to the dashboard so they can use Cachet.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return \Illuminate\Http\Response|null
|
||||
* @return mixed
|
||||
*/
|
||||
public function filter(Route $route, Request $request)
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
try {
|
||||
$setting = Setting::where('name', 'app_name')->first();
|
||||
if ($setting && $setting->value) {
|
||||
return Redirect::to('/dashboard');
|
||||
return Redirect::route('dashboard');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
53
app/Http/Middleware/Authenticate.php
Normal file
53
app/Http/Middleware/Authenticate.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class Authenticate
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new authenticate middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($this->auth->guest()) {
|
||||
throw new HttpException(401);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
62
app/Http/Middleware/HasSetting.php
Normal file
62
app/Http/Middleware/HasSetting.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use CachetHQ\Cachet\Models\Setting;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class HasSetting
|
||||
{
|
||||
/**
|
||||
* Run the has setting middleware.
|
||||
*
|
||||
* We're verifying that the given setting exists in our database. If it
|
||||
* doesn't, then we're sending the user to the setup page so that they can
|
||||
* complete the installation of Cachet on their server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$settingName = $this->getSettingName($request);
|
||||
|
||||
try {
|
||||
$setting = Setting::where('name', $settingName)->first();
|
||||
if (!$setting || !$setting->value) {
|
||||
return Redirect::to('setup');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return Redirect::to('setup');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting from the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSettingName($request)
|
||||
{
|
||||
$actions = $request->route()->getAction();
|
||||
|
||||
return $actions['setting'];
|
||||
}
|
||||
}
|
||||
53
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
53
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* The authentication guard instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new redirect if authenticated middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
return new RedirectResponse(route('dashboard'));
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
35
app/Http/Middleware/SubscribersConfigured.php
Normal file
35
app/Http/Middleware/SubscribersConfigured.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class SubscribersConfigured
|
||||
{
|
||||
/**
|
||||
* We're verifying that subscribers is both enabled and configured.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!subscribers_enabled()) {
|
||||
return Redirect::route('status-page');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
224
app/Http/Routes/AdminRoutes.php
Normal file
224
app/Http/Routes/AdminRoutes.php
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class AdminRoutes
|
||||
{
|
||||
/**
|
||||
* Define the dashboard routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group([
|
||||
'middleware' => 'auth',
|
||||
'prefix' => 'dashboard',
|
||||
'namespace' => 'Admin',
|
||||
], function ($router) {
|
||||
// Dashboard
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard',
|
||||
'uses' => 'DashboardController@showDashboard',
|
||||
]);
|
||||
|
||||
// Components
|
||||
$router->group(['prefix' => 'components'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.components',
|
||||
'uses' => 'ComponentController@showComponents',
|
||||
]);
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.components.add',
|
||||
'uses' => 'ComponentController@showAddComponent',
|
||||
]);
|
||||
$router->post('add', 'ComponentController@createComponentAction');
|
||||
$router->get('groups', [
|
||||
'as' => 'dashboard.components.groups',
|
||||
'uses' => 'ComponentController@showComponentGroups',
|
||||
]);
|
||||
$router->get('groups/add', [
|
||||
'as' => 'dashboard.components.groups.add',
|
||||
'uses' => 'ComponentController@showAddComponentGroup',
|
||||
]);
|
||||
$router->get('groups/edit/{component_group}', [
|
||||
'as' => 'dashboard.components.groups.edit',
|
||||
'uses' => 'ComponentController@showEditComponentGroup',
|
||||
]);
|
||||
$router->post('groups/edit/{component_group}', 'ComponentController@updateComponentGroupAction');
|
||||
|
||||
$router->delete('groups/{component_group}/delete', 'ComponentController@deleteComponentGroupAction');
|
||||
$router->post('groups/add', 'ComponentController@postAddComponentGroup');
|
||||
$router->delete('{component}/delete', 'ComponentController@deleteComponentAction');
|
||||
$router->get('{component}/edit', 'ComponentController@showEditComponent');
|
||||
$router->post('{component}/edit', 'ComponentController@updateComponentAction');
|
||||
});
|
||||
|
||||
// Incidents
|
||||
$router->group(['prefix' => 'incidents'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.incidents',
|
||||
'uses' => 'IncidentController@showIncidents',
|
||||
]);
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.incidents.add',
|
||||
'uses' => 'IncidentController@showAddIncident',
|
||||
]);
|
||||
$router->post('add', 'IncidentController@createIncidentAction');
|
||||
$router->delete('{incident}/delete', 'IncidentController@deleteIncidentAction');
|
||||
$router->get('{incident}/edit', 'IncidentController@showEditIncidentAction');
|
||||
$router->post('{incident}/edit', 'IncidentController@editIncidentAction');
|
||||
});
|
||||
|
||||
// Scheduled Maintenance
|
||||
$router->group(['prefix' => 'schedule'], function ($router) {
|
||||
$router->get('/', ['as' => 'dashboard.schedule', 'uses' => 'ScheduleController@showIndex']);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.schedule.add',
|
||||
'uses' => 'ScheduleController@showAddSchedule',
|
||||
]);
|
||||
$router->post('add', 'ScheduleController@addScheduleAction');
|
||||
|
||||
$router->get('{incident}/edit', [
|
||||
'as' => 'dashboard.schedule.edit',
|
||||
'uses' => 'ScheduleController@showEditSchedule',
|
||||
]);
|
||||
$router->post('{incident}/edit', 'ScheduleController@editScheduleAction');
|
||||
|
||||
$router->delete('{incident}/delete', [
|
||||
'as' => 'dashboard.schedule.delete',
|
||||
'uses' => 'ScheduleController@deleteScheduleAction',
|
||||
]);
|
||||
});
|
||||
|
||||
// Incident Templates
|
||||
$router->group(['prefix' => 'templates'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.templates',
|
||||
'uses' => 'IncidentController@showTemplates',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.templates.add',
|
||||
'uses' => 'IncidentController@showAddIncidentTemplate',
|
||||
]);
|
||||
$router->post('add', 'IncidentController@createIncidentTemplateAction');
|
||||
|
||||
$router->get('{incident_template}/edit', 'IncidentController@showEditTemplateAction');
|
||||
$router->post('{incident_template}/edit', 'IncidentController@editTemplateAction');
|
||||
$router->delete('{incident_template}/delete', 'IncidentController@deleteTemplateAction');
|
||||
});
|
||||
|
||||
// Subscribers
|
||||
$router->group(['prefix' => 'subscribers'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.subscribers',
|
||||
'uses' => 'SubscriberController@showSubscribers',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.subscribers.add',
|
||||
'uses' => 'SubscriberController@showAddSubscriber',
|
||||
]);
|
||||
$router->post('add', 'SubscriberController@createSubscriberAction');
|
||||
|
||||
$router->delete('{subscriber}/delete', 'SubscriberController@deleteSubscriberAction');
|
||||
});
|
||||
|
||||
// Metrics
|
||||
$router->group(['prefix' => 'metrics'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.metrics',
|
||||
'uses' => 'MetricController@showMetrics',
|
||||
]);
|
||||
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.metrics.add',
|
||||
'uses' => 'MetricController@showAddMetric',
|
||||
]);
|
||||
$router->post('add', 'MetricController@createMetricAction');
|
||||
$router->delete('{metric}/delete', 'MetricController@deleteMetricAction');
|
||||
$router->get('{metric}/edit', 'MetricController@showEditMetricAction');
|
||||
$router->post('{metric}/edit', 'MetricController@editMetricAction');
|
||||
});
|
||||
|
||||
// Notifications
|
||||
$router->group(['prefix' => 'notifications'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.notifications',
|
||||
'uses' => 'DashboardController@showNotifications',
|
||||
]);
|
||||
});
|
||||
|
||||
// Team Members
|
||||
$router->group(['prefix' => 'team'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.team',
|
||||
'uses' => 'TeamController@showTeamView',
|
||||
]);
|
||||
|
||||
$router->group(['middleware' => 'admin'], function ($router) {
|
||||
$router->get('add', [
|
||||
'as' => 'dashboard.team.add',
|
||||
'uses' => 'TeamController@showAddTeamMemberView',
|
||||
]);
|
||||
$router->get('{user}', 'TeamController@showTeamMemberView');
|
||||
$router->post('add', 'TeamController@postAddUser');
|
||||
$router->post('{user}', 'TeamController@postUpdateUser');
|
||||
});
|
||||
});
|
||||
|
||||
// Settings
|
||||
$router->group(['prefix' => 'settings'], function ($router) {
|
||||
$router->get('setup', [
|
||||
'as' => 'dashboard.settings.setup',
|
||||
'uses' => 'SettingsController@showSetupView',
|
||||
]);
|
||||
$router->get('security', [
|
||||
'as' => 'dashboard.settings.security',
|
||||
'uses' => 'SettingsController@showSecurityView',
|
||||
]);
|
||||
$router->get('theme', [
|
||||
'as' => 'dashboard.settings.theme',
|
||||
'uses' => 'SettingsController@showThemeView',
|
||||
]);
|
||||
$router->get('stylesheet', [
|
||||
'as' => 'dashboard.settings.stylesheet',
|
||||
'uses' => 'SettingsController@showStylesheetView',
|
||||
]);
|
||||
$router->post('/', 'SettingsController@postSettings');
|
||||
});
|
||||
|
||||
// User Settings
|
||||
$router->group(['prefix' => 'user'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'dashboard.user',
|
||||
'uses' => 'UserController@showUser',
|
||||
]);
|
||||
$router->post('/', 'UserController@postUser');
|
||||
$router->get('{user}/api/regen', 'UserController@regenerateApiKey');
|
||||
});
|
||||
|
||||
// Internal API.
|
||||
// This should only be used for making requests within the dashboard.
|
||||
$router->group(['prefix' => 'api'], function ($router) {
|
||||
$router->get('incidents/templates', 'ApiController@getIncidentTemplate');
|
||||
$router->post('components/groups/order', 'ApiController@postUpdateComponentGroupOrder');
|
||||
$router->post('components/order', 'ApiController@postUpdateComponentOrder');
|
||||
$router->post('components/{component}', 'ApiController@postUpdateComponent');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
69
app/Http/Routes/ApiRoutes.php
Normal file
69
app/Http/Routes/ApiRoutes.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class ApiRoutes
|
||||
{
|
||||
/**
|
||||
* Define the api routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group([
|
||||
'namespace' => 'Api',
|
||||
'prefix' => 'api/v1',
|
||||
'middleware' => 'accept:application/json',
|
||||
], function ($router) {
|
||||
// General
|
||||
$router->get('ping', 'GeneralController@ping');
|
||||
|
||||
// Components
|
||||
$router->get('components', 'ComponentController@getComponents');
|
||||
$router->get('components/{component}', 'ComponentController@getComponent');
|
||||
|
||||
// Incidents
|
||||
$router->get('incidents', 'IncidentController@getIncidents');
|
||||
$router->get('incidents/{incident}', 'IncidentController@getIncident');
|
||||
|
||||
// Metrics
|
||||
$router->get('metrics', 'MetricController@getMetrics');
|
||||
$router->get('metrics/{metric}', 'MetricController@getMetric');
|
||||
$router->get('metrics/{metric}/points', 'MetricController@getMetricPoints');
|
||||
|
||||
// Api protected
|
||||
$router->group(['middleware' => 'auth.api'], function ($router) {
|
||||
$router->get('subscribers', 'SubscriberController@getSubscribers');
|
||||
|
||||
$router->post('components', 'ComponentController@postComponents');
|
||||
$router->post('incidents', 'IncidentController@postIncidents');
|
||||
$router->post('metrics', 'MetricController@postMetrics');
|
||||
$router->post('metrics/{metric}/points', 'MetricPointController@postMetricPoints');
|
||||
$router->post('subscribers', 'SubscriberController@postSubscribers');
|
||||
|
||||
$router->put('components/{component}', 'ComponentController@putComponent');
|
||||
$router->put('incidents/{incident}', 'IncidentController@putIncident');
|
||||
$router->put('metrics/{metric}', 'MetricController@putMetric');
|
||||
$router->put('metrics/{metric}/points/{metric_point}', 'MetricPointController@putMetricPoint');
|
||||
|
||||
$router->delete('components/{component}', 'ComponentController@deleteComponent');
|
||||
$router->delete('incidents/{incident}', 'IncidentController@deleteIncident');
|
||||
$router->delete('metrics/{metric}', 'MetricController@deleteMetric');
|
||||
$router->delete('metrics/{metric}/points/{metric_point}', 'MetricPointController@deleteMetricPoint');
|
||||
$router->delete('subscribers/{subscriber}', 'SubscriberController@deleteSubscriber');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
57
app/Http/Routes/AuthRoutes.php
Normal file
57
app/Http/Routes/AuthRoutes.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class AuthRoutes
|
||||
{
|
||||
/**
|
||||
* Define the auth routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['prefix' => 'auth'], function ($router) {
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
// Login routes
|
||||
$router->get('login', [
|
||||
'middleware' => 'guest',
|
||||
'as' => 'login',
|
||||
'uses' => 'AuthController@showLogin',
|
||||
]);
|
||||
|
||||
$router->post('login', [
|
||||
'middleware' => ['guest', 'csrf', 'throttling:10,10'],
|
||||
'as' => 'login',
|
||||
'uses' => 'AuthController@postLogin',
|
||||
]);
|
||||
|
||||
// Two factor authorization
|
||||
$router->get('2fa', [
|
||||
'as' => 'two-factor',
|
||||
'uses' => 'AuthController@showTwoFactorAuth',
|
||||
]);
|
||||
|
||||
$router->post('2fa', 'AuthController@postTwoFactor');
|
||||
});
|
||||
|
||||
$router->group(['middleware' => 'auth'], function ($router) {
|
||||
$router->get('logout', [
|
||||
'as' => 'logout',
|
||||
'uses' => 'AuthController@logoutAction',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
29
app/Http/Routes/SetupRoutes.php
Normal file
29
app/Http/Routes/SetupRoutes.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class SetupRoutes
|
||||
{
|
||||
/**
|
||||
* Define the setup routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['middleware' => 'app.isSetup'], function ($router) {
|
||||
$router->controller('setup', 'SetupController');
|
||||
});
|
||||
}
|
||||
}
|
||||
36
app/Http/Routes/StatusPageRoutes.php
Normal file
36
app/Http/Routes/StatusPageRoutes.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class StatusPageRoutes
|
||||
{
|
||||
/**
|
||||
* Define the status page routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
// Prevent access until the app is setup.
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
$router->get('/', [
|
||||
'as' => 'status-page',
|
||||
'uses' => 'HomeController@showIndex',
|
||||
]);
|
||||
|
||||
$router->get('/atom/{component_group?}', 'AtomController@feedAction');
|
||||
$router->get('/rss/{component_group?}', 'RssController@feedAction');
|
||||
});
|
||||
}
|
||||
}
|
||||
49
app/Http/Routes/SubscribeRoutes.php
Normal file
49
app/Http/Routes/SubscribeRoutes.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Routes;
|
||||
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
|
||||
class SubscribeRoutes
|
||||
{
|
||||
/**
|
||||
* Define the subscribe routes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||
*/
|
||||
public function map(Registrar $router)
|
||||
{
|
||||
$router->group(['middleware' => 'app.hasSetting', 'setting' => 'app_name'], function ($router) {
|
||||
$router->group(['middleware' => 'app.subscribers'], function ($router) {
|
||||
$router->get('subscribe', [
|
||||
'as' => 'subscribe-page',
|
||||
'uses' => 'SubscribeController@showSubscribe',
|
||||
]);
|
||||
|
||||
$router->post('subscribe', [
|
||||
'as' => 'subscribe',
|
||||
'uses' => 'SubscribeController@postSubscribe',
|
||||
]);
|
||||
|
||||
$router->get('subscribe/verify/{code}', [
|
||||
'as' => 'subscribe-verify',
|
||||
'uses' => 'SubscribeController@getVerify',
|
||||
]);
|
||||
|
||||
$router->get('unsubscribe/{code}', [
|
||||
'as' => 'unsubscribe',
|
||||
'uses' => 'SubscribeController@getUnsubscribe',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
69
app/Http/helpers.php
Normal file
69
app/Http/helpers.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
if (!function_exists('set_active')) {
|
||||
|
||||
/**
|
||||
* Set active class if request is in path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $classes
|
||||
* @param string $active
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function set_active($path, array $classes = [], $active = 'active')
|
||||
{
|
||||
if (Request::is($path)) {
|
||||
$classes[] = $active;
|
||||
}
|
||||
|
||||
$class = e(implode(' ', $classes));
|
||||
|
||||
return empty($classes) ? '' : "class=\"{$class}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('formatted_date')) {
|
||||
/**
|
||||
* Formats a date with the user timezone and the selected format.
|
||||
*
|
||||
* @param string $date
|
||||
*
|
||||
* @return \Jenssegers\Date\Date
|
||||
*/
|
||||
function formatted_date($date)
|
||||
{
|
||||
$dateFormat = Setting::get('date_format', 'jS F Y');
|
||||
|
||||
return (new Date($date))->format($dateFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('subscribers_enabled')) {
|
||||
/**
|
||||
* Is the subscriber functionality enabled and configured.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function subscribers_enabled()
|
||||
{
|
||||
$isEnabled = Setting::get('enable_subscribers', false);
|
||||
$mailAddress = env('MAIL_ADDRESS', false);
|
||||
$mailFrom = env('MAIL_NAME', false);
|
||||
|
||||
return $isEnabled && $mailAddress && $mailFrom;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Transformers\ComponentTransformer;
|
||||
use Dingo\Api\Transformer\TransformableInterface;
|
||||
use CachetHQ\Cachet\Presenters\ComponentPresenter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingTrait;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $name
|
||||
* @property string $description
|
||||
* @property int $status
|
||||
* @property string $link
|
||||
* @property int $order
|
||||
* @property int $group_id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
*/
|
||||
class Component extends Model implements TransformableInterface
|
||||
class Component extends Model implements HasPresenter
|
||||
{
|
||||
use SoftDeletingTrait, ValidatingTrait;
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rulesets = [
|
||||
[
|
||||
'creating' => [
|
||||
'user_id' => 'integer|required',
|
||||
'name' => 'required',
|
||||
'status' => 'integer|required',
|
||||
'link' => 'url',
|
||||
],
|
||||
],
|
||||
[
|
||||
'updating' => [
|
||||
'status' => 'integer',
|
||||
'link' => 'url',
|
||||
],
|
||||
],
|
||||
protected $rules = [
|
||||
'name' => 'required|string',
|
||||
'status' => 'integer|required',
|
||||
'link' => 'url',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -57,7 +42,6 @@ class Component extends Model implements TransformableInterface
|
||||
'name',
|
||||
'description',
|
||||
'status',
|
||||
'user_id',
|
||||
'tags',
|
||||
'link',
|
||||
'order',
|
||||
@@ -76,6 +60,13 @@ class Component extends Model implements TransformableInterface
|
||||
'link' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
/**
|
||||
* Components can belong to a group.
|
||||
*
|
||||
@@ -83,7 +74,7 @@ class Component extends Model implements TransformableInterface
|
||||
*/
|
||||
public function group()
|
||||
{
|
||||
return $this->belongsTo('CachetHQ\Cachet\Models\ComponentGroup', 'group_id', 'id');
|
||||
return $this->belongsTo(ComponentGroup::class, 'group_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +84,7 @@ class Component extends Model implements TransformableInterface
|
||||
*/
|
||||
public function incidents()
|
||||
{
|
||||
return $this->hasMany('CachetHQ\Cachet\Models\Incident', 'component_id', 'id');
|
||||
return $this->hasMany(Incident::class, 'component_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +94,7 @@ class Component extends Model implements TransformableInterface
|
||||
*/
|
||||
public function tags()
|
||||
{
|
||||
return $this->belongsToMany('CachetHQ\Cachet\Models\Tag');
|
||||
return $this->belongsToMany(Tag::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,12 +148,12 @@ class Component extends Model implements TransformableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transformer instance.
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Transformers\ComponentTransformer
|
||||
* @return string
|
||||
*/
|
||||
public function getTransformer()
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return new ComponentTransformer();
|
||||
return ComponentPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingTrait;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
*/
|
||||
class ComponentGroup extends Model
|
||||
{
|
||||
use SoftDeletingTrait, ValidatingTrait;
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
@@ -31,7 +32,7 @@ class ComponentGroup extends Model
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['name'];
|
||||
protected $fillable = ['name', 'order'];
|
||||
|
||||
/**
|
||||
* A group can have many components.
|
||||
@@ -40,6 +41,6 @@ class ComponentGroup extends Model
|
||||
*/
|
||||
public function components()
|
||||
{
|
||||
return $this->hasMany('CachetHQ\Cachet\Models\Component', 'id', 'group_id');
|
||||
return $this->hasMany(Component::class, 'group_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Transformers\IncidentTransformer;
|
||||
use CachetHQ\Cachet\Presenters\IncidentPresenter;
|
||||
use Carbon\Carbon;
|
||||
use Dingo\Api\Transformer\TransformableInterface;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingTrait;
|
||||
use McCool\LaravelAutoPresenter\PresenterInterface;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $component_id
|
||||
* @property int $user_id
|
||||
* @property string $name
|
||||
* @property int $status
|
||||
* @property string $message
|
||||
* @property string $humanStatus
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
*/
|
||||
class Incident extends Model implements TransformableInterface, PresenterInterface
|
||||
class Incident extends Model implements HasPresenter
|
||||
{
|
||||
use SoftDeletingTrait, ValidatingTrait;
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
@@ -32,10 +28,10 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'user_id' => 'required|integer',
|
||||
'component_id' => 'integer',
|
||||
'name' => 'required',
|
||||
'status' => 'required|integer',
|
||||
'visible' => 'required|boolean',
|
||||
'message' => 'required',
|
||||
];
|
||||
|
||||
@@ -44,14 +40,23 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['user_id', 'component_id', 'name', 'status', 'message', 'scheduled_at'];
|
||||
protected $fillable = [
|
||||
'component_id',
|
||||
'name',
|
||||
'status',
|
||||
'visible',
|
||||
'message',
|
||||
'scheduled_at',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* The accessors to append to the model's serialized form.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $appends = ['humanStatus'];
|
||||
protected $appends = ['human_status'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
@@ -60,6 +65,27 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
*/
|
||||
protected $dates = ['scheduled_at', 'deleted_at'];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'visible' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Finds all visible incidents.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeVisible($query)
|
||||
{
|
||||
return $query->where('visible', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all scheduled incidents (maintenance).
|
||||
*
|
||||
@@ -86,16 +112,6 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenter()
|
||||
{
|
||||
return 'CachetHQ\Cachet\Presenters\IncidentPresenter';
|
||||
}
|
||||
|
||||
/**
|
||||
* An incident belongs to a component.
|
||||
*
|
||||
@@ -103,7 +119,7 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
*/
|
||||
public function component()
|
||||
{
|
||||
return $this->belongsTo('CachetHQ\Cachet\Models\Component', 'component_id', 'id');
|
||||
return $this->belongsTo(Component::class, 'component_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,16 +141,16 @@ class Incident extends Model implements TransformableInterface, PresenterInterfa
|
||||
*/
|
||||
public function getIsScheduledAttribute()
|
||||
{
|
||||
return $this->getOriginal('scheduled_at');
|
||||
return $this->getOriginal('scheduled_at') !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transformer instance.
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Transformers\IncidentTransformer
|
||||
* @return string
|
||||
*/
|
||||
public function getTransformer()
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return new IncidentTransformer();
|
||||
return IncidentPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $template
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*/
|
||||
class IncidentTemplate extends Model
|
||||
{
|
||||
use ValidatingTrait;
|
||||
@@ -37,8 +38,6 @@ class IncidentTemplate extends Model
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
150
app/Models/Metric.php
Normal file
150
app/Models/Metric.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting as SettingFacade;
|
||||
use CachetHQ\Cachet\Presenters\MetricPresenter;
|
||||
use DateInterval;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Jenssegers\Date\Date;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Metric extends Model implements HasPresenter
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
const CALC_SUM = 0;
|
||||
const CALC_AVG = 1;
|
||||
|
||||
/**
|
||||
* The model's attributes.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $attributes = [
|
||||
'name' => '',
|
||||
'display_chart' => 1,
|
||||
'default_value' => 0,
|
||||
'calc_type' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'name' => 'required',
|
||||
'suffix' => 'required',
|
||||
'display_chart' => 'boolean',
|
||||
'default_value' => 'numeric',
|
||||
];
|
||||
|
||||
/**
|
||||
* The fillable properties.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['name', 'suffix', 'description', 'display_chart', 'default_value', 'calc_type'];
|
||||
|
||||
/**
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $with = ['points'];
|
||||
|
||||
/**
|
||||
* Metrics contain many metric points.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function points()
|
||||
{
|
||||
return $this->hasMany(MetricPoint::class, 'metric_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of all values a metric has by the hour.
|
||||
*
|
||||
* @param int $hour
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getValuesByHour($hour)
|
||||
{
|
||||
$dateTimeZone = SettingFacade::get('app_timezone');
|
||||
$dateTime = (new Date())->setTimezone($dateTimeZone)->sub(new DateInterval('PT'.$hour.'H'));
|
||||
|
||||
$hourInterval = $dateTime->format('YmdH');
|
||||
|
||||
if (Config::get('database.default') === 'mysql') {
|
||||
if (!isset($this->calc_type) || $this->calc_type == self::CALC_SUM) {
|
||||
$value = (int) $this->points()
|
||||
->whereRaw('DATE_FORMAT(created_at, "%Y%m%d%H") = '.$hourInterval)
|
||||
->groupBy(DB::raw('HOUR(created_at)'))->sum('value');
|
||||
} elseif ($this->calc_type == self::CALC_AVG) {
|
||||
$value = (int) $this->points()
|
||||
->whereRaw('DATE_FORMAT(created_at, "%Y%m%d%H") = '.$hourInterval)
|
||||
->groupBy(DB::raw('HOUR(created_at)'))->avg('value');
|
||||
}
|
||||
} else {
|
||||
// Default metrics calculations.
|
||||
if (!isset($this->calc_type) || $this->calc_type == self::CALC_SUM) {
|
||||
$queryType = 'sum(metric_points.value)';
|
||||
} elseif ($this->calc_type == self::CALC_AVG) {
|
||||
$queryType = 'avg(metric_points.value)';
|
||||
} else {
|
||||
$queryType = 'sum(metric_points.value)';
|
||||
}
|
||||
|
||||
$query = DB::select("select {$queryType} as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE metric_points.metric_id = {$this->id} AND to_char(metric_points.created_at, 'YYYYMMDDHH24') = :timestamp GROUP BY to_char(metric_points.created_at, 'H')", [
|
||||
'timestamp' => $hourInterval,
|
||||
]);
|
||||
|
||||
if (isset($query[0])) {
|
||||
$value = $query[0]->aggregate;
|
||||
} else {
|
||||
$value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($value === 0 && $this->default_value != $value) {
|
||||
return $this->default_value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a chart should be shown.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShouldDisplayAttribute()
|
||||
{
|
||||
return $this->display_chart === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return MetricPresenter::class;
|
||||
}
|
||||
}
|
||||
58
app/Models/MetricPoint.php
Normal file
58
app/Models/MetricPoint.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\MetricPointPresenter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class MetricPoint extends Model implements HasPresenter
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['metric_id', 'value', 'created_at'];
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'value' => 'numeric|required',
|
||||
];
|
||||
|
||||
/**
|
||||
* A metric point belongs to a metric unit.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function metric()
|
||||
{
|
||||
return $this->belongsTo(Metric::class, 'id', 'metric_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return MetricPointPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,18 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $value
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*/
|
||||
class Setting extends Model
|
||||
{
|
||||
/**
|
||||
99
app/Models/Subscriber.php
Normal file
99
app/Models/Subscriber.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\SubscriberPresenter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Subscriber extends Model implements HasPresenter
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'email' => 'required|email|unique:subscribers',
|
||||
];
|
||||
|
||||
/**
|
||||
* The fillable properties.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['email'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['verified_at'];
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'email' => 'string',
|
||||
'verify_code' => 'string',
|
||||
];
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($user) {
|
||||
if (!$user->verify_code) {
|
||||
$user->verify_code = self::generateVerifyCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the subscriber is verified.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verified()
|
||||
{
|
||||
return !is_null($this->verified_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an new verify code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateVerifyCode()
|
||||
{
|
||||
return str_random(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return SubscriberPresenter::class;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*/
|
||||
class Tag extends Model
|
||||
{
|
||||
use ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The fillable properties.
|
||||
*
|
||||
@@ -26,8 +25,6 @@ class Tag extends Model
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
@@ -45,6 +42,6 @@ class Tag extends Model
|
||||
*/
|
||||
public function components()
|
||||
{
|
||||
return $this->belongsToMany('CachetHQ\Cachet\Models\Component');
|
||||
return $this->belongsToMany(Component::class);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Auth\Reminders\RemindableInterface;
|
||||
use Illuminate\Auth\Reminders\RemindableTrait;
|
||||
use Illuminate\Auth\UserInterface;
|
||||
use Illuminate\Auth\UserTrait;
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $username
|
||||
* @property string $password
|
||||
* @property string $remember_token
|
||||
* @property string $google_2fa_secret
|
||||
* @property string $email
|
||||
* @property string $api_key
|
||||
* @property int $active
|
||||
* @property int $level
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*/
|
||||
class User extends Model implements UserInterface, RemindableInterface
|
||||
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
|
||||
{
|
||||
use RemindableTrait, UserTrait, ValidatingTrait;
|
||||
use Authenticatable, CanResetPassword, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
@@ -34,7 +30,7 @@ class User extends Model implements UserInterface, RemindableInterface
|
||||
* @var string[]
|
||||
*/
|
||||
protected $rules = [
|
||||
'username' => 'required|alpha_num|unique:users',
|
||||
'username' => ['required', 'regex:/\A(?!.*[:;]-\))[ -~]+\z/', 'unique:users'],
|
||||
'email' => 'required|email|unique:users',
|
||||
'password' => 'required',
|
||||
];
|
||||
@@ -57,15 +53,13 @@ class User extends Model implements UserInterface, RemindableInterface
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($user) {
|
||||
if (! $user->api_key) {
|
||||
if (!$user->api_key) {
|
||||
$user->api_key = self::generateApiKey();
|
||||
}
|
||||
});
|
||||
38
app/Presenters/AbstractPresenter.php
Normal file
38
app/Presenters/AbstractPresenter.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use McCool\LaravelAutoPresenter\BasePresenter as BaseLaravelAutoPresenter;
|
||||
|
||||
abstract class AbstractPresenter extends BaseLaravelAutoPresenter implements Arrayable
|
||||
{
|
||||
/**
|
||||
* The setting repository.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Config\Repository
|
||||
*/
|
||||
protected $setting;
|
||||
|
||||
/**
|
||||
* Create a incident presenter instance.
|
||||
*
|
||||
* @param object $resource
|
||||
*/
|
||||
public function __construct($resource)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
|
||||
$this->setting = app('setting');
|
||||
}
|
||||
}
|
||||
33
app/Presenters/ComponentPresenter.php
Normal file
33
app/Presenters/ComponentPresenter.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class ComponentPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
'status_name' => $this->wrappedObject->humanStatus,
|
||||
]);
|
||||
}
|
||||
}
|
||||
196
app/Presenters/IncidentPresenter.php
Normal file
196
app/Presenters/IncidentPresenter.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
class IncidentPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Renders the message from Markdown into HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formattedMessage()
|
||||
{
|
||||
return Markdown::convertToHtml($this->wrappedObject->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Present diff for humans date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_diff()
|
||||
{
|
||||
return (new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->diffForHumans();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_formatted()
|
||||
{
|
||||
return ucfirst((new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the created_at time ready to be used by bootstrap-datetimepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_datetimepicker()
|
||||
{
|
||||
return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at_iso()
|
||||
{
|
||||
return $this->wrappedObject->created_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present diff for humans date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_diff()
|
||||
{
|
||||
return (new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->diffForHumans();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formated date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_formatted()
|
||||
{
|
||||
return ucfirst((new Date($this->wrappedObject->scheduled_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))
|
||||
->format($this->setting->get('incident_date_format', 'l jS F Y H:i:s')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_iso()
|
||||
{
|
||||
return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->toISO8601String();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the scheduled_at time ready to be used by bootstrap-datetimepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scheduled_at_datetimepicker()
|
||||
{
|
||||
return $this->wrappedObject->scheduled_at->setTimezone($this->setting->get('app_timezone'))->format('d/m/Y H:i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted timestamp for use within the timeline.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function timestamp_formatted()
|
||||
{
|
||||
if ($this->wrappedObject->is_scheduled) {
|
||||
return $this->scheduled_at_formatted;
|
||||
} else {
|
||||
return $this->created_at_formatted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the iso timestamp for use within the timeline.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function timestamp_iso()
|
||||
{
|
||||
if ($this->wrappedObject->is_scheduled) {
|
||||
return $this->scheduled_at_iso;
|
||||
} else {
|
||||
return $this->created_at_iso;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the status with an icon.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function icon()
|
||||
{
|
||||
switch ($this->wrappedObject->status) {
|
||||
case 0: // Scheduled
|
||||
return 'icon ion-android-calendar';
|
||||
case 1: // Investigating
|
||||
return 'icon ion-flag';
|
||||
case 2: // Identified
|
||||
return 'icon ion-alert';
|
||||
case 3: // Watching
|
||||
return 'icon ion-eye';
|
||||
case 4: // Fixed
|
||||
return 'icon ion-checkmark';
|
||||
default: // Something actually broke, this shouldn't happen.
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'scheduled_at' => $this->created_at(),
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
32
app/Presenters/MetricPointPresenter.php
Normal file
32
app/Presenters/MetricPointPresenter.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class MetricPointPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
32
app/Presenters/MetricPresenter.php
Normal file
32
app/Presenters/MetricPresenter.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class MetricPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
33
app/Presenters/SubscriberPresenter.php
Normal file
33
app/Presenters/SubscriberPresenter.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class SubscriberPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
'verified_at' => $this->verified_at(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
61
app/Presenters/Traits/TimestampsTrait.php
Normal file
61
app/Presenters/Traits/TimestampsTrait.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters\Traits;
|
||||
|
||||
use Jenssegers\Date\Date;
|
||||
|
||||
trait TimestampsTrait
|
||||
{
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function created_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->created_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function updated_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->updated_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function deleted_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->deleted_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function verified_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->verified_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
}
|
||||
43
app/Providers/AppServiceProvider.php
Normal file
43
app/Providers/AppServiceProvider.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use Illuminate\Bus\Dispatcher;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*
|
||||
* @param \Illuminate\Bus\Dispatcher $dispatcher
|
||||
*/
|
||||
public function boot(Dispatcher $dispatcher)
|
||||
{
|
||||
$dispatcher->mapUsing(function ($command) {
|
||||
return Dispatcher::simpleMapping($command, 'CachetHQ\Cachet\Commands', 'CachetHQ\Cachet\Handlers\Commands');
|
||||
});
|
||||
|
||||
Str::macro('canonicalize', function ($url) {
|
||||
return preg_replace('/([^\/])$/', '$1/', $url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->bind('Illuminate\Contracts\Auth\Registrar', 'CachetHQ\Cachet\Services\Registrar');
|
||||
}
|
||||
}
|
||||
47
app/Providers/ComposerServiceProvider.php
Normal file
47
app/Providers/ComposerServiceProvider.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use CachetHQ\Cachet\Composers\AppComposer;
|
||||
use CachetHQ\Cachet\Composers\DashboardComposer;
|
||||
use CachetHQ\Cachet\Composers\IndexComposer;
|
||||
use CachetHQ\Cachet\Composers\LoggedUserComposer;
|
||||
use CachetHQ\Cachet\Composers\ThemeComposer;
|
||||
use CachetHQ\Cachet\Composers\TimezoneLocaleComposer;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ComposerServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\Factory $factory
|
||||
*/
|
||||
public function boot(Factory $factory)
|
||||
{
|
||||
$factory->composer('*', AppComposer::class);
|
||||
$factory->composer('*', LoggedUserComposer::class);
|
||||
$factory->composer(['index', 'subscribe'], IndexComposer::class);
|
||||
$factory->composer(['index', 'subscribe'], ThemeComposer::class);
|
||||
$factory->composer('dashboard.*', DashboardComposer::class);
|
||||
$factory->composer(['setup', 'dashboard.settings.app-setup'], TimezoneLocaleComposer::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
70
app/Providers/ConfigServiceProvider.php
Normal file
70
app/Providers/ConfigServiceProvider.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use CachetHQ\Cachet\Config\Repository;
|
||||
use CachetHQ\Cachet\Facades\Setting;
|
||||
use CachetHQ\Cachet\Models\Setting as SettingModel;
|
||||
use Exception;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ConfigServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$appDomain = $appLocale = null;
|
||||
|
||||
try {
|
||||
// Get app custom configuration.
|
||||
$appDomain = Setting::get('app_domain');
|
||||
$appLocale = Setting::get('app_locale');
|
||||
|
||||
// Setup Cors.
|
||||
$allowedOrigins = $this->app->config->get('cors.defaults.allowedOrigins');
|
||||
$allowedOrigins[] = Setting::get('app_domain');
|
||||
|
||||
// Add our allowed domains too.
|
||||
if ($allowedDomains = Setting::get('allowed_domains')) {
|
||||
$domains = explode(',', $allowedDomains);
|
||||
foreach ($domains as $domain) {
|
||||
$allowedOrigins[] = $domain;
|
||||
}
|
||||
} else {
|
||||
$allowedOrigins[] = env('APP_URL');
|
||||
}
|
||||
|
||||
$this->app->config->set('cors.paths.api/v1/*.allowedOrigins', $allowedOrigins);
|
||||
} catch (Exception $e) {
|
||||
// Don't throw any errors, we may not be setup yet.
|
||||
}
|
||||
|
||||
// Override default app values.
|
||||
$this->app->config->set('app.url', $appDomain ?: $this->app->config->get('app.url'));
|
||||
$this->app->config->set('app.locale', $appLocale ?: $this->app->config->get('app.locale'));
|
||||
|
||||
// Set custom lang.
|
||||
$this->app->translator->setLocale($appLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->bindShared('setting', function () {
|
||||
return new Repository(new SettingModel());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use CachetHQ\Cachet\Console\Commands\FixPermissionsCommand;
|
||||
use CachetHQ\Cachet\Console\Commands\OneClickDeployCommand;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ConsoleServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->commands('CachetHQ\Cachet\Console\Commands\FixPermissionsCommand');
|
||||
$this->commands('CachetHQ\Cachet\Console\Commands\OneClickDeployCommand');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('CachetHQ\Cachet\Console\Commands\FixPermissionsCommand', function ($app) {
|
||||
$storageDirectory = $app['path.storage'];
|
||||
$databaseDirectory = $app['path'].'/database';
|
||||
$storageDirectory = storage_path();
|
||||
$databaseDirectory = base_path('database');
|
||||
$databasePath = $app->config->get('database.connections.sqlite.database');
|
||||
$databaseDefault = $app->config->get('database.default');
|
||||
|
||||
return new FixPermissionsCommand($storageDirectory, $databaseDirectory, $databasePath, $databaseDefault);
|
||||
});
|
||||
|
||||
$this->app->singleton('CachetHQ\Cachet\Console\Commands\OneClickDeployCommand', function ($app) {
|
||||
return new OneClickDeployCommand($app->environment('heroku'));
|
||||
});
|
||||
}
|
||||
}
|
||||
34
app/Providers/EventServiceProvider.php
Normal file
34
app/Providers/EventServiceProvider.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event handler mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $listen = [
|
||||
'CachetHQ\Cachet\Events\CustomerHasSubscribedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendSubscriberVerificationEmailHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\IncidentHasReportedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendIncidentEmailNotificationHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\MaintenanceHasScheduledEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\SendMaintenanceEmailNotificationHandler',
|
||||
],
|
||||
];
|
||||
}
|
||||
69
app/Providers/RouteServiceProvider.php
Normal file
69
app/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Routing\Router;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* This namespace is applied to the controller routes in your routes file.
|
||||
*
|
||||
* In addition, it is set as the URL generator's root namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'CachetHQ\Cachet\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Define the route model bindings, pattern filters, etc.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
*/
|
||||
public function boot(Router $router)
|
||||
{
|
||||
parent::boot($router);
|
||||
|
||||
$this->registerBindings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register model bindings.
|
||||
*/
|
||||
protected function registerBindings()
|
||||
{
|
||||
$this->app->router->model('component', 'CachetHQ\Cachet\Models\Component');
|
||||
$this->app->router->model('component_group', 'CachetHQ\Cachet\Models\ComponentGroup');
|
||||
$this->app->router->model('incident', 'CachetHQ\Cachet\Models\Incident');
|
||||
$this->app->router->model('incident_template', 'CachetHQ\Cachet\Models\IncidentTemplate');
|
||||
$this->app->router->model('metric', 'CachetHQ\Cachet\Models\Metric');
|
||||
$this->app->router->model('metric_point', 'CachetHQ\Cachet\Models\MetricPoint');
|
||||
$this->app->router->model('setting', 'CachetHQ\Cachet\Models\Setting');
|
||||
$this->app->router->model('subscriber', 'CachetHQ\Cachet\Models\Subscriber');
|
||||
$this->app->router->model('user', 'CachetHQ\Cachet\Models\User');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
*/
|
||||
public function map(Router $router)
|
||||
{
|
||||
$router->group(['namespace' => $this->namespace], function (Router $router) {
|
||||
foreach (glob(app_path('Http//Routes').'/*.php') as $file) {
|
||||
$this->app->make('CachetHQ\\Cachet\\Http\\Routes\\'.basename($file, '.php'))->map($router);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
51
app/Services/Registrar.php
Normal file
51
app/Services/Registrar.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Services;
|
||||
|
||||
use CachetHQ\Cachet\User;
|
||||
use Illuminate\Contracts\Auth\Registrar as RegistrarContract;
|
||||
use Validator;
|
||||
|
||||
class Registrar implements RegistrarContract
|
||||
{
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
public function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'name' => 'required|max:255',
|
||||
'email' => 'required|email|max:255|unique:users',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Bootstrap variable overrides and custom variables
|
||||
@import "variables";
|
||||
|
||||
// Core variables and mixins
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/variables";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/mixins";
|
||||
|
||||
// Reset and dependencies
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/normalize";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/print";
|
||||
|
||||
// Core CSS
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/scaffolding";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/type";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/code";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/grid";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tables";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/forms";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/buttons";
|
||||
|
||||
// Components
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/component-animations";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/dropdowns";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/button-groups";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/input-groups";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navs";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navbar";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pagination";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pager";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/labels";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/badges";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/jumbotron";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/thumbnails";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/alerts";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/progress-bars";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/media";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/list-group";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/panels";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/wells";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/close";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/modals";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tooltip";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/carousel";
|
||||
|
||||
// Utility classes
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/utilities";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities";
|
||||
@@ -1,18 +0,0 @@
|
||||
.login {
|
||||
padding-top: 90px;
|
||||
}
|
||||
|
||||
.login .logo {
|
||||
display: block;
|
||||
margin: 0 auto 30px;
|
||||
}
|
||||
|
||||
.login legend {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin: 0 0 30px 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user